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