1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6 #include <stdio.h> 7 #include <unistd.h> 8 #include <stdarg.h> 9 #include <errno.h> 10 #include <stddef.h> 11 #include <string.h> 12 #include <sys/ioctl.h> 13 #include <net/if.h> 14 #include <linux/if_tun.h> 15 #include <arpa/inet.h> 16 #include <sys/types.h> 17 #include <sys/stat.h> 18 #include <fcntl.h> 19 #include <sys/socket.h> 20 #include <sys/un.h> 21 #include <netinet/ip.h> 22 #include <linux/if_ether.h> 23 #include <linux/if_packet.h> 24 #include <sys/wait.h> 25 #include <sys/uio.h> 26 #include <linux/virtio_net.h> 27 #include <netdb.h> 28 #include <stdlib.h> 29 #include <os.h> 30 #include <limits.h> 31 #include <um_malloc.h> 32 #include "vector_user.h" 33 34 #define ID_GRE 0 35 #define ID_L2TPV3 1 36 #define ID_BESS 2 37 #define ID_MAX 2 38 39 #define TOKEN_IFNAME "ifname" 40 #define TOKEN_SCRIPT "ifup" 41 42 #define TRANS_RAW "raw" 43 #define TRANS_RAW_LEN strlen(TRANS_RAW) 44 45 #define TRANS_FD "fd" 46 #define TRANS_FD_LEN strlen(TRANS_FD) 47 48 #define VNET_HDR_FAIL "could not enable vnet headers on fd %d" 49 #define TUN_GET_F_FAIL "tapraw: TUNGETFEATURES failed: %s" 50 #define L2TPV3_BIND_FAIL "l2tpv3_open : could not bind socket err=%i" 51 #define UNIX_BIND_FAIL "unix_open : could not bind socket err=%i" 52 #define BPF_ATTACH_FAIL "Failed to attach filter size %d prog %px to %d, err %d\n" 53 #define BPF_DETACH_FAIL "Failed to detach filter size %d prog %px to %d, err %d\n" 54 55 #define MAX_UN_LEN 107 56 57 static const char padchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 58 static const char *template = "tapXXXXXX"; 59 60 /* This is very ugly and brute force lookup, but it is done 61 * only once at initialization so not worth doing hashes or 62 * anything more intelligent 63 */ 64 65 char *uml_vector_fetch_arg(struct arglist *ifspec, char *token) 66 { 67 int i; 68 69 for (i = 0; i < ifspec->numargs; i++) { 70 if (strcmp(ifspec->tokens[i], token) == 0) 71 return ifspec->values[i]; 72 } 73 return NULL; 74 75 } 76 77 struct arglist *uml_parse_vector_ifspec(char *arg) 78 { 79 struct arglist *result; 80 int pos, len; 81 bool parsing_token = true, next_starts = true; 82 83 if (arg == NULL) 84 return NULL; 85 result = uml_kmalloc(sizeof(struct arglist), UM_GFP_KERNEL); 86 if (result == NULL) 87 return NULL; 88 result->numargs = 0; 89 len = strlen(arg); 90 for (pos = 0; pos < len; pos++) { 91 if (next_starts) { 92 if (parsing_token) { 93 result->tokens[result->numargs] = arg + pos; 94 } else { 95 result->values[result->numargs] = arg + pos; 96 result->numargs++; 97 } 98 next_starts = false; 99 } 100 if (*(arg + pos) == '=') { 101 if (parsing_token) 102 parsing_token = false; 103 else 104 goto cleanup; 105 next_starts = true; 106 (*(arg + pos)) = '\0'; 107 } 108 if (*(arg + pos) == ',') { 109 parsing_token = true; 110 next_starts = true; 111 (*(arg + pos)) = '\0'; 112 } 113 } 114 return result; 115 cleanup: 116 printk(UM_KERN_ERR "vector_setup - Couldn't parse '%s'\n", arg); 117 kfree(result); 118 return NULL; 119 } 120 121 /* 122 * Socket/FD configuration functions. These return an structure 123 * of rx and tx descriptors to cover cases where these are not 124 * the same (f.e. read via raw socket and write via tap). 125 */ 126 127 #define PATH_NET_TUN "/dev/net/tun" 128 129 130 static int create_tap_fd(char *iface) 131 { 132 struct ifreq ifr; 133 int fd = -1; 134 int err = -ENOMEM, offload; 135 136 fd = open(PATH_NET_TUN, O_RDWR); 137 if (fd < 0) { 138 printk(UM_KERN_ERR "uml_tap: failed to open tun device\n"); 139 goto tap_fd_cleanup; 140 } 141 memset(&ifr, 0, sizeof(ifr)); 142 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR; 143 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1); 144 145 err = ioctl(fd, TUNSETIFF, (void *) &ifr); 146 if (err != 0) { 147 printk(UM_KERN_ERR "uml_tap: failed to select tap interface\n"); 148 goto tap_fd_cleanup; 149 } 150 151 offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6; 152 ioctl(fd, TUNSETOFFLOAD, offload); 153 return fd; 154 tap_fd_cleanup: 155 if (fd >= 0) 156 os_close_file(fd); 157 return err; 158 } 159 160 static int create_raw_fd(char *iface, int flags, int proto) 161 { 162 struct ifreq ifr; 163 int fd = -1; 164 struct sockaddr_ll sock; 165 int err = -ENOMEM; 166 167 fd = socket(AF_PACKET, SOCK_RAW, flags); 168 if (fd == -1) { 169 err = -errno; 170 goto raw_fd_cleanup; 171 } 172 memset(&ifr, 0, sizeof(ifr)); 173 strncpy((char *)&ifr.ifr_name, iface, sizeof(ifr.ifr_name) - 1); 174 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) { 175 err = -errno; 176 goto raw_fd_cleanup; 177 } 178 179 sock.sll_family = AF_PACKET; 180 sock.sll_protocol = htons(proto); 181 sock.sll_ifindex = ifr.ifr_ifindex; 182 183 if (bind(fd, 184 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) { 185 err = -errno; 186 goto raw_fd_cleanup; 187 } 188 return fd; 189 raw_fd_cleanup: 190 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err); 191 if (fd >= 0) 192 os_close_file(fd); 193 return err; 194 } 195 196 197 static struct vector_fds *user_init_tap_fds(struct arglist *ifspec) 198 { 199 int fd = -1, i; 200 char *iface; 201 struct vector_fds *result = NULL; 202 bool dynamic = false; 203 char dynamic_ifname[IFNAMSIZ]; 204 char *argv[] = {NULL, NULL, NULL, NULL}; 205 206 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME); 207 if (iface == NULL) { 208 dynamic = true; 209 iface = dynamic_ifname; 210 srand(getpid()); 211 } 212 213 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 214 if (result == NULL) { 215 printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n"); 216 goto tap_cleanup; 217 } 218 result->rx_fd = -1; 219 result->tx_fd = -1; 220 result->remote_addr = NULL; 221 result->remote_addr_size = 0; 222 223 /* TAP */ 224 do { 225 if (dynamic) { 226 strcpy(iface, template); 227 for (i = 0; i < strlen(iface); i++) { 228 if (iface[i] == 'X') { 229 iface[i] = padchar[rand() % strlen(padchar)]; 230 } 231 } 232 } 233 fd = create_tap_fd(iface); 234 if ((fd < 0) && (!dynamic)) { 235 printk(UM_KERN_ERR "uml_tap: failed to create tun interface\n"); 236 goto tap_cleanup; 237 } 238 result->tx_fd = fd; 239 result->rx_fd = fd; 240 } while (fd < 0); 241 242 argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT); 243 if (argv[0]) { 244 argv[1] = iface; 245 run_helper(NULL, NULL, argv); 246 } 247 248 return result; 249 tap_cleanup: 250 printk(UM_KERN_ERR "user_init_tap: init failed, error %d", fd); 251 kfree(result); 252 return NULL; 253 } 254 255 static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec) 256 { 257 char *iface; 258 struct vector_fds *result = NULL; 259 char *argv[] = {NULL, NULL, NULL, NULL}; 260 261 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME); 262 if (iface == NULL) { 263 printk(UM_KERN_ERR "uml_tap: failed to parse interface spec\n"); 264 goto hybrid_cleanup; 265 } 266 267 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 268 if (result == NULL) { 269 printk(UM_KERN_ERR "uml_tap: failed to allocate file descriptors\n"); 270 goto hybrid_cleanup; 271 } 272 result->rx_fd = -1; 273 result->tx_fd = -1; 274 result->remote_addr = NULL; 275 result->remote_addr_size = 0; 276 277 /* TAP */ 278 279 result->tx_fd = create_tap_fd(iface); 280 if (result->tx_fd < 0) { 281 printk(UM_KERN_ERR "uml_tap: failed to create tun interface: %i\n", result->tx_fd); 282 goto hybrid_cleanup; 283 } 284 285 /* RAW */ 286 287 result->rx_fd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL); 288 if (result->rx_fd == -1) { 289 printk(UM_KERN_ERR 290 "uml_tap: failed to create paired raw socket: %i\n", result->rx_fd); 291 goto hybrid_cleanup; 292 } 293 294 argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT); 295 if (argv[0]) { 296 argv[1] = iface; 297 run_helper(NULL, NULL, argv); 298 } 299 return result; 300 hybrid_cleanup: 301 printk(UM_KERN_ERR "user_init_hybrid: init failed"); 302 kfree(result); 303 return NULL; 304 } 305 306 static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id) 307 { 308 int fd = -1; 309 int socktype; 310 char *src, *dst; 311 struct vector_fds *result = NULL; 312 struct sockaddr_un *local_addr = NULL, *remote_addr = NULL; 313 314 src = uml_vector_fetch_arg(ifspec, "src"); 315 dst = uml_vector_fetch_arg(ifspec, "dst"); 316 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 317 if (result == NULL) { 318 printk(UM_KERN_ERR "unix open:cannot allocate remote addr"); 319 goto unix_cleanup; 320 } 321 remote_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 322 if (remote_addr == NULL) { 323 printk(UM_KERN_ERR "unix open:cannot allocate remote addr"); 324 goto unix_cleanup; 325 } 326 327 switch (id) { 328 case ID_BESS: 329 socktype = SOCK_SEQPACKET; 330 if ((src != NULL) && (strlen(src) <= MAX_UN_LEN)) { 331 local_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 332 if (local_addr == NULL) { 333 printk(UM_KERN_ERR "bess open:cannot allocate local addr"); 334 goto unix_cleanup; 335 } 336 local_addr->sun_family = AF_UNIX; 337 memcpy(local_addr->sun_path, src, strlen(src) + 1); 338 } 339 if ((dst == NULL) || (strlen(dst) > MAX_UN_LEN)) 340 goto unix_cleanup; 341 remote_addr->sun_family = AF_UNIX; 342 memcpy(remote_addr->sun_path, dst, strlen(dst) + 1); 343 break; 344 default: 345 printk(KERN_ERR "Unsupported unix socket type\n"); 346 return NULL; 347 } 348 349 fd = socket(AF_UNIX, socktype, 0); 350 if (fd == -1) { 351 printk(UM_KERN_ERR 352 "unix open: could not open socket, error = %d", 353 -errno 354 ); 355 goto unix_cleanup; 356 } 357 if (local_addr != NULL) { 358 if (bind(fd, (struct sockaddr *) local_addr, sizeof(struct sockaddr_un))) { 359 printk(UM_KERN_ERR UNIX_BIND_FAIL, errno); 360 goto unix_cleanup; 361 } 362 } 363 switch (id) { 364 case ID_BESS: 365 if (connect(fd, (const struct sockaddr *) remote_addr, sizeof(struct sockaddr_un)) < 0) { 366 printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno); 367 goto unix_cleanup; 368 } 369 break; 370 } 371 result->rx_fd = fd; 372 result->tx_fd = fd; 373 result->remote_addr_size = sizeof(struct sockaddr_un); 374 result->remote_addr = remote_addr; 375 return result; 376 unix_cleanup: 377 if (fd >= 0) 378 os_close_file(fd); 379 kfree(remote_addr); 380 kfree(result); 381 return NULL; 382 } 383 384 static int strtofd(const char *nptr) 385 { 386 long fd; 387 char *endptr; 388 389 if (nptr == NULL) 390 return -1; 391 392 errno = 0; 393 fd = strtol(nptr, &endptr, 10); 394 if (nptr == endptr || 395 errno != 0 || 396 *endptr != '\0' || 397 fd < 0 || 398 fd > INT_MAX) { 399 return -1; 400 } 401 return fd; 402 } 403 404 static struct vector_fds *user_init_fd_fds(struct arglist *ifspec) 405 { 406 int fd = -1; 407 char *fdarg = NULL; 408 struct vector_fds *result = NULL; 409 410 fdarg = uml_vector_fetch_arg(ifspec, "fd"); 411 fd = strtofd(fdarg); 412 if (fd == -1) { 413 printk(UM_KERN_ERR "fd open: bad or missing fd argument"); 414 goto fd_cleanup; 415 } 416 417 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 418 if (result == NULL) { 419 printk(UM_KERN_ERR "fd open: allocation failed"); 420 goto fd_cleanup; 421 } 422 423 result->rx_fd = fd; 424 result->tx_fd = fd; 425 result->remote_addr_size = 0; 426 result->remote_addr = NULL; 427 return result; 428 429 fd_cleanup: 430 if (fd >= 0) 431 os_close_file(fd); 432 kfree(result); 433 return NULL; 434 } 435 436 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec) 437 { 438 int rxfd = -1, txfd = -1; 439 int err = -ENOMEM; 440 char *iface; 441 struct vector_fds *result = NULL; 442 char *argv[] = {NULL, NULL, NULL, NULL}; 443 444 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME); 445 if (iface == NULL) 446 goto raw_cleanup; 447 448 rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL); 449 if (rxfd == -1) { 450 err = -errno; 451 goto raw_cleanup; 452 } 453 txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */ 454 if (txfd == -1) { 455 err = -errno; 456 goto raw_cleanup; 457 } 458 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 459 if (result != NULL) { 460 result->rx_fd = rxfd; 461 result->tx_fd = txfd; 462 result->remote_addr = NULL; 463 result->remote_addr_size = 0; 464 } 465 argv[0] = uml_vector_fetch_arg(ifspec, TOKEN_SCRIPT); 466 if (argv[0]) { 467 argv[1] = iface; 468 run_helper(NULL, NULL, argv); 469 } 470 return result; 471 raw_cleanup: 472 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err); 473 kfree(result); 474 return NULL; 475 } 476 477 478 bool uml_raw_enable_qdisc_bypass(int fd) 479 { 480 int optval = 1; 481 482 if (setsockopt(fd, 483 SOL_PACKET, PACKET_QDISC_BYPASS, 484 &optval, sizeof(optval)) != 0) { 485 return false; 486 } 487 return true; 488 } 489 490 bool uml_raw_enable_vnet_headers(int fd) 491 { 492 int optval = 1; 493 494 if (setsockopt(fd, 495 SOL_PACKET, PACKET_VNET_HDR, 496 &optval, sizeof(optval)) != 0) { 497 printk(UM_KERN_INFO VNET_HDR_FAIL, fd); 498 return false; 499 } 500 return true; 501 } 502 bool uml_tap_enable_vnet_headers(int fd) 503 { 504 unsigned int features; 505 int len = sizeof(struct virtio_net_hdr); 506 507 if (ioctl(fd, TUNGETFEATURES, &features) == -1) { 508 printk(UM_KERN_INFO TUN_GET_F_FAIL, strerror(errno)); 509 return false; 510 } 511 if ((features & IFF_VNET_HDR) == 0) { 512 printk(UM_KERN_INFO "tapraw: No VNET HEADER support"); 513 return false; 514 } 515 ioctl(fd, TUNSETVNETHDRSZ, &len); 516 return true; 517 } 518 519 static struct vector_fds *user_init_socket_fds(struct arglist *ifspec, int id) 520 { 521 int err = -ENOMEM; 522 int fd = -1, gairet; 523 struct addrinfo srchints; 524 struct addrinfo dsthints; 525 bool v6, udp; 526 char *value; 527 char *src, *dst, *srcport, *dstport; 528 struct addrinfo *gairesult = NULL; 529 struct vector_fds *result = NULL; 530 531 532 value = uml_vector_fetch_arg(ifspec, "v6"); 533 v6 = false; 534 udp = false; 535 if (value != NULL) { 536 if (strtol((const char *) value, NULL, 10) > 0) 537 v6 = true; 538 } 539 540 value = uml_vector_fetch_arg(ifspec, "udp"); 541 if (value != NULL) { 542 if (strtol((const char *) value, NULL, 10) > 0) 543 udp = true; 544 } 545 src = uml_vector_fetch_arg(ifspec, "src"); 546 dst = uml_vector_fetch_arg(ifspec, "dst"); 547 srcport = uml_vector_fetch_arg(ifspec, "srcport"); 548 dstport = uml_vector_fetch_arg(ifspec, "dstport"); 549 550 memset(&dsthints, 0, sizeof(dsthints)); 551 552 if (v6) 553 dsthints.ai_family = AF_INET6; 554 else 555 dsthints.ai_family = AF_INET; 556 557 switch (id) { 558 case ID_GRE: 559 dsthints.ai_socktype = SOCK_RAW; 560 dsthints.ai_protocol = IPPROTO_GRE; 561 break; 562 case ID_L2TPV3: 563 if (udp) { 564 dsthints.ai_socktype = SOCK_DGRAM; 565 dsthints.ai_protocol = 0; 566 } else { 567 dsthints.ai_socktype = SOCK_RAW; 568 dsthints.ai_protocol = IPPROTO_L2TP; 569 } 570 break; 571 default: 572 printk(KERN_ERR "Unsupported socket type\n"); 573 return NULL; 574 } 575 memcpy(&srchints, &dsthints, sizeof(struct addrinfo)); 576 577 gairet = getaddrinfo(src, srcport, &dsthints, &gairesult); 578 if ((gairet != 0) || (gairesult == NULL)) { 579 printk(UM_KERN_ERR 580 "socket_open : could not resolve src, error = %s", 581 gai_strerror(gairet) 582 ); 583 return NULL; 584 } 585 fd = socket(gairesult->ai_family, 586 gairesult->ai_socktype, gairesult->ai_protocol); 587 if (fd == -1) { 588 printk(UM_KERN_ERR 589 "socket_open : could not open socket, error = %d", 590 -errno 591 ); 592 goto cleanup; 593 } 594 if (bind(fd, 595 (struct sockaddr *) gairesult->ai_addr, 596 gairesult->ai_addrlen)) { 597 printk(UM_KERN_ERR L2TPV3_BIND_FAIL, errno); 598 goto cleanup; 599 } 600 601 if (gairesult != NULL) 602 freeaddrinfo(gairesult); 603 604 gairesult = NULL; 605 606 gairet = getaddrinfo(dst, dstport, &dsthints, &gairesult); 607 if ((gairet != 0) || (gairesult == NULL)) { 608 printk(UM_KERN_ERR 609 "socket_open : could not resolve dst, error = %s", 610 gai_strerror(gairet) 611 ); 612 return NULL; 613 } 614 615 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL); 616 if (result != NULL) { 617 result->rx_fd = fd; 618 result->tx_fd = fd; 619 result->remote_addr = uml_kmalloc( 620 gairesult->ai_addrlen, UM_GFP_KERNEL); 621 if (result->remote_addr == NULL) 622 goto cleanup; 623 result->remote_addr_size = gairesult->ai_addrlen; 624 memcpy( 625 result->remote_addr, 626 gairesult->ai_addr, 627 gairesult->ai_addrlen 628 ); 629 } 630 freeaddrinfo(gairesult); 631 return result; 632 cleanup: 633 if (gairesult != NULL) 634 freeaddrinfo(gairesult); 635 printk(UM_KERN_ERR "user_init_socket: init failed, error %d", err); 636 if (fd >= 0) 637 os_close_file(fd); 638 if (result != NULL) { 639 kfree(result->remote_addr); 640 kfree(result); 641 } 642 return NULL; 643 } 644 645 struct vector_fds *uml_vector_user_open( 646 int unit, 647 struct arglist *parsed 648 ) 649 { 650 char *transport; 651 652 if (parsed == NULL) { 653 printk(UM_KERN_ERR "no parsed config for unit %d\n", unit); 654 return NULL; 655 } 656 transport = uml_vector_fetch_arg(parsed, "transport"); 657 if (transport == NULL) { 658 printk(UM_KERN_ERR "missing transport for unit %d\n", unit); 659 return NULL; 660 } 661 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0) 662 return user_init_raw_fds(parsed); 663 if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0) 664 return user_init_hybrid_fds(parsed); 665 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0) 666 return user_init_tap_fds(parsed); 667 if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0) 668 return user_init_socket_fds(parsed, ID_GRE); 669 if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0) 670 return user_init_socket_fds(parsed, ID_L2TPV3); 671 if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0) 672 return user_init_unix_fds(parsed, ID_BESS); 673 if (strncmp(transport, TRANS_FD, TRANS_FD_LEN) == 0) 674 return user_init_fd_fds(parsed); 675 return NULL; 676 } 677 678 679 int uml_vector_sendmsg(int fd, void *hdr, int flags) 680 { 681 int n; 682 683 CATCH_EINTR(n = sendmsg(fd, (struct msghdr *) hdr, flags)); 684 if ((n < 0) && (errno == EAGAIN)) 685 return 0; 686 if (n >= 0) 687 return n; 688 else 689 return -errno; 690 } 691 692 int uml_vector_recvmsg(int fd, void *hdr, int flags) 693 { 694 int n; 695 struct msghdr *msg = (struct msghdr *) hdr; 696 697 CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen)); 698 if ((n < 0) && (errno == EAGAIN)) 699 return 0; 700 if (n >= 0) 701 return n; 702 else 703 return -errno; 704 } 705 706 int uml_vector_writev(int fd, void *hdr, int iovcount) 707 { 708 int n; 709 710 CATCH_EINTR(n = writev(fd, (struct iovec *) hdr, iovcount)); 711 if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS))) 712 return 0; 713 if (n >= 0) 714 return n; 715 else 716 return -errno; 717 } 718 719 int uml_vector_sendmmsg( 720 int fd, 721 void *msgvec, 722 unsigned int vlen, 723 unsigned int flags) 724 { 725 int n; 726 727 CATCH_EINTR(n = sendmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags)); 728 if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS))) 729 return 0; 730 if (n >= 0) 731 return n; 732 else 733 return -errno; 734 } 735 736 int uml_vector_recvmmsg( 737 int fd, 738 void *msgvec, 739 unsigned int vlen, 740 unsigned int flags) 741 { 742 int n; 743 744 CATCH_EINTR( 745 n = recvmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags, 0)); 746 if ((n < 0) && (errno == EAGAIN)) 747 return 0; 748 if (n >= 0) 749 return n; 750 else 751 return -errno; 752 } 753 int uml_vector_attach_bpf(int fd, void *bpf) 754 { 755 struct sock_fprog *prog = bpf; 756 757 int err = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(struct sock_fprog)); 758 759 if (err < 0) 760 printk(KERN_ERR BPF_ATTACH_FAIL, prog->len, prog->filter, fd, -errno); 761 return err; 762 } 763 764 int uml_vector_detach_bpf(int fd, void *bpf) 765 { 766 struct sock_fprog *prog = bpf; 767 768 int err = setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, bpf, sizeof(struct sock_fprog)); 769 if (err < 0) 770 printk(KERN_ERR BPF_DETACH_FAIL, prog->len, prog->filter, fd, -errno); 771 return err; 772 } 773 void *uml_vector_default_bpf(void *mac) 774 { 775 struct sock_filter *bpf; 776 uint32_t *mac1 = (uint32_t *)(mac + 2); 777 uint16_t *mac2 = (uint16_t *) mac; 778 struct sock_fprog *bpf_prog; 779 780 bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL); 781 if (bpf_prog) { 782 bpf_prog->len = DEFAULT_BPF_LEN; 783 bpf_prog->filter = NULL; 784 } else { 785 return NULL; 786 } 787 bpf = uml_kmalloc( 788 sizeof(struct sock_filter) * DEFAULT_BPF_LEN, UM_GFP_KERNEL); 789 if (bpf) { 790 bpf_prog->filter = bpf; 791 /* ld [8] */ 792 bpf[0] = (struct sock_filter){ 0x20, 0, 0, 0x00000008 }; 793 /* jeq #0xMAC[2-6] jt 2 jf 5*/ 794 bpf[1] = (struct sock_filter){ 0x15, 0, 3, ntohl(*mac1)}; 795 /* ldh [6] */ 796 bpf[2] = (struct sock_filter){ 0x28, 0, 0, 0x00000006 }; 797 /* jeq #0xMAC[0-1] jt 4 jf 5 */ 798 bpf[3] = (struct sock_filter){ 0x15, 0, 1, ntohs(*mac2)}; 799 /* ret #0 */ 800 bpf[4] = (struct sock_filter){ 0x6, 0, 0, 0x00000000 }; 801 /* ret #0x40000 */ 802 bpf[5] = (struct sock_filter){ 0x6, 0, 0, 0x00040000 }; 803 } else { 804 kfree(bpf_prog); 805 bpf_prog = NULL; 806 } 807 return bpf_prog; 808 } 809 810 /* Note - this function requires a valid mac being passed as an arg */ 811 812 void *uml_vector_user_bpf(char *filename) 813 { 814 struct sock_filter *bpf; 815 struct sock_fprog *bpf_prog; 816 struct stat statbuf; 817 int res, ffd = -1; 818 819 if (filename == NULL) 820 return NULL; 821 822 if (stat(filename, &statbuf) < 0) { 823 printk(KERN_ERR "Error %d reading bpf file", -errno); 824 return false; 825 } 826 bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL); 827 if (bpf_prog == NULL) { 828 printk(KERN_ERR "Failed to allocate bpf prog buffer"); 829 return NULL; 830 } 831 bpf_prog->len = statbuf.st_size / sizeof(struct sock_filter); 832 bpf_prog->filter = NULL; 833 ffd = os_open_file(filename, of_read(OPENFLAGS()), 0); 834 if (ffd < 0) { 835 printk(KERN_ERR "Error %d opening bpf file", -errno); 836 goto bpf_failed; 837 } 838 bpf = uml_kmalloc(statbuf.st_size, UM_GFP_KERNEL); 839 if (bpf == NULL) { 840 printk(KERN_ERR "Failed to allocate bpf buffer"); 841 goto bpf_failed; 842 } 843 bpf_prog->filter = bpf; 844 res = os_read_file(ffd, bpf, statbuf.st_size); 845 if (res < statbuf.st_size) { 846 printk(KERN_ERR "Failed to read bpf program %s, error %d", filename, res); 847 kfree(bpf); 848 goto bpf_failed; 849 } 850 os_close_file(ffd); 851 return bpf_prog; 852 bpf_failed: 853 if (ffd > 0) 854 os_close_file(ffd); 855 kfree(bpf_prog); 856 return NULL; 857 } 858