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