~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/um/drivers/vector_user.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php