root/arch/um/drivers/vector_user.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uml_vector_fetch_arg
  2. uml_parse_vector_ifspec
  3. create_tap_fd
  4. create_raw_fd
  5. user_init_tap_fds
  6. user_init_hybrid_fds
  7. user_init_unix_fds
  8. user_init_raw_fds
  9. uml_raw_enable_qdisc_bypass
  10. uml_raw_enable_vnet_headers
  11. uml_tap_enable_vnet_headers
  12. user_init_socket_fds
  13. uml_vector_user_open
  14. uml_vector_sendmsg
  15. uml_vector_recvmsg
  16. uml_vector_writev
  17. uml_vector_sendmmsg
  18. uml_vector_recvmmsg
  19. uml_vector_attach_bpf
  20. uml_vector_default_bpf

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

/* [<][>][^][v][top][bottom][index][help] */