Linux 5.7.6
[linux/fpc-iii.git] / arch / um / drivers / vector_user.c
blobaa28e9eecb7baf098d9158f3fee4c2e21887f96e
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4 */
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"
35 #define ID_GRE 0
36 #define ID_L2TPV3 1
37 #define ID_BESS 2
38 #define ID_MAX 2
40 #define TOKEN_IFNAME "ifname"
42 #define TRANS_RAW "raw"
43 #define TRANS_RAW_LEN strlen(TRANS_RAW)
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"
52 #define MAX_UN_LEN 107
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
59 char *uml_vector_fetch_arg(struct arglist *ifspec, char *token)
61 int i;
63 for (i = 0; i < ifspec->numargs; i++) {
64 if (strcmp(ifspec->tokens[i], token) == 0)
65 return ifspec->values[i];
67 return NULL;
71 struct arglist *uml_parse_vector_ifspec(char *arg)
73 struct arglist *result;
74 int pos, len;
75 bool parsing_token = true, next_starts = true;
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++;
92 next_starts = false;
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';
102 if (*(arg + pos) == ',') {
103 parsing_token = true;
104 next_starts = true;
105 (*(arg + pos)) = '\0';
108 return result;
109 cleanup:
110 printk(UM_KERN_ERR "vector_setup - Couldn't parse '%s'\n", arg);
111 kfree(result);
112 return NULL;
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).
121 #define PATH_NET_TUN "/dev/net/tun"
124 static int create_tap_fd(char *iface)
126 struct ifreq ifr;
127 int fd = -1;
128 int err = -ENOMEM, offload;
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;
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);
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;
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;
154 static int create_raw_fd(char *iface, int flags, int proto)
156 struct ifreq ifr;
157 int fd = -1;
158 struct sockaddr_ll sock;
159 int err = -ENOMEM;
161 fd = socket(AF_PACKET, SOCK_RAW, flags);
162 if (fd == -1) {
163 err = -errno;
164 goto raw_fd_cleanup;
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;
173 sock.sll_family = AF_PACKET;
174 sock.sll_protocol = htons(proto);
175 sock.sll_ifindex = ifr.ifr_ifindex;
177 if (bind(fd,
178 (struct sockaddr *) &sock, sizeof(struct sockaddr_ll)) < 0) {
179 err = -errno;
180 goto raw_fd_cleanup;
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;
190 static struct vector_fds *user_init_tap_fds(struct arglist *ifspec)
192 int fd = -1;
193 char *iface;
194 struct vector_fds *result = NULL;
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;
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;
207 result->rx_fd = -1;
208 result->tx_fd = -1;
209 result->remote_addr = NULL;
210 result->remote_addr_size = 0;
212 /* TAP */
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;
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 kfree(result);
225 return NULL;
228 static struct vector_fds *user_init_hybrid_fds(struct arglist *ifspec)
230 char *iface;
231 struct vector_fds *result = NULL;
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;
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;
244 result->rx_fd = -1;
245 result->tx_fd = -1;
246 result->remote_addr = NULL;
247 result->remote_addr_size = 0;
249 /* TAP */
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;
257 /* RAW */
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;
265 return result;
266 hybrid_cleanup:
267 printk(UM_KERN_ERR "user_init_hybrid: init failed");
268 kfree(result);
269 return NULL;
272 static struct vector_fds *user_init_unix_fds(struct arglist *ifspec, int id)
274 int fd = -1;
275 int socktype;
276 char *src, *dst;
277 struct vector_fds *result = NULL;
278 struct sockaddr_un *local_addr = NULL, *remote_addr = NULL;
280 src = uml_vector_fetch_arg(ifspec, "src");
281 dst = uml_vector_fetch_arg(ifspec, "dst");
282 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
283 if (result == NULL) {
284 printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
285 goto unix_cleanup;
287 remote_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
288 if (remote_addr == NULL) {
289 printk(UM_KERN_ERR "unix open:cannot allocate remote addr");
290 goto unix_cleanup;
293 switch (id) {
294 case ID_BESS:
295 socktype = SOCK_SEQPACKET;
296 if ((src != NULL) && (strlen(src) <= MAX_UN_LEN)) {
297 local_addr = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL);
298 if (local_addr == NULL) {
299 printk(UM_KERN_ERR "bess open:cannot allocate local addr");
300 goto unix_cleanup;
302 local_addr->sun_family = AF_UNIX;
303 memcpy(local_addr->sun_path, src, strlen(src) + 1);
305 if ((dst == NULL) || (strlen(dst) > MAX_UN_LEN))
306 goto unix_cleanup;
307 remote_addr->sun_family = AF_UNIX;
308 memcpy(remote_addr->sun_path, dst, strlen(dst) + 1);
309 break;
310 default:
311 printk(KERN_ERR "Unsupported unix socket type\n");
312 return NULL;
315 fd = socket(AF_UNIX, socktype, 0);
316 if (fd == -1) {
317 printk(UM_KERN_ERR
318 "unix open: could not open socket, error = %d",
319 -errno
321 goto unix_cleanup;
323 if (local_addr != NULL) {
324 if (bind(fd, (struct sockaddr *) local_addr, sizeof(struct sockaddr_un))) {
325 printk(UM_KERN_ERR UNIX_BIND_FAIL, errno);
326 goto unix_cleanup;
329 switch (id) {
330 case ID_BESS:
331 if (connect(fd, remote_addr, sizeof(struct sockaddr_un)) < 0) {
332 printk(UM_KERN_ERR "bess open:cannot connect to %s %i", remote_addr->sun_path, -errno);
333 goto unix_cleanup;
335 break;
337 result->rx_fd = fd;
338 result->tx_fd = fd;
339 result->remote_addr_size = sizeof(struct sockaddr_un);
340 result->remote_addr = remote_addr;
341 return result;
342 unix_cleanup:
343 if (fd >= 0)
344 os_close_file(fd);
345 kfree(remote_addr);
346 kfree(result);
347 return NULL;
350 static struct vector_fds *user_init_raw_fds(struct arglist *ifspec)
352 int rxfd = -1, txfd = -1;
353 int err = -ENOMEM;
354 char *iface;
355 struct vector_fds *result = NULL;
357 iface = uml_vector_fetch_arg(ifspec, TOKEN_IFNAME);
358 if (iface == NULL)
359 goto raw_cleanup;
361 rxfd = create_raw_fd(iface, ETH_P_ALL, ETH_P_ALL);
362 if (rxfd == -1) {
363 err = -errno;
364 goto raw_cleanup;
366 txfd = create_raw_fd(iface, 0, ETH_P_IP); /* Turn off RX on this fd */
367 if (txfd == -1) {
368 err = -errno;
369 goto raw_cleanup;
371 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
372 if (result != NULL) {
373 result->rx_fd = rxfd;
374 result->tx_fd = txfd;
375 result->remote_addr = NULL;
376 result->remote_addr_size = 0;
378 return result;
379 raw_cleanup:
380 printk(UM_KERN_ERR "user_init_raw: init failed, error %d", err);
381 kfree(result);
382 return NULL;
386 bool uml_raw_enable_qdisc_bypass(int fd)
388 int optval = 1;
390 if (setsockopt(fd,
391 SOL_PACKET, PACKET_QDISC_BYPASS,
392 &optval, sizeof(optval)) != 0) {
393 return false;
395 return true;
398 bool uml_raw_enable_vnet_headers(int fd)
400 int optval = 1;
402 if (setsockopt(fd,
403 SOL_PACKET, PACKET_VNET_HDR,
404 &optval, sizeof(optval)) != 0) {
405 printk(UM_KERN_INFO VNET_HDR_FAIL, fd);
406 return false;
408 return true;
410 bool uml_tap_enable_vnet_headers(int fd)
412 unsigned int features;
413 int len = sizeof(struct virtio_net_hdr);
415 if (ioctl(fd, TUNGETFEATURES, &features) == -1) {
416 printk(UM_KERN_INFO TUN_GET_F_FAIL, strerror(errno));
417 return false;
419 if ((features & IFF_VNET_HDR) == 0) {
420 printk(UM_KERN_INFO "tapraw: No VNET HEADER support");
421 return false;
423 ioctl(fd, TUNSETVNETHDRSZ, &len);
424 return true;
427 static struct vector_fds *user_init_socket_fds(struct arglist *ifspec, int id)
429 int err = -ENOMEM;
430 int fd = -1, gairet;
431 struct addrinfo srchints;
432 struct addrinfo dsthints;
433 bool v6, udp;
434 char *value;
435 char *src, *dst, *srcport, *dstport;
436 struct addrinfo *gairesult = NULL;
437 struct vector_fds *result = NULL;
440 value = uml_vector_fetch_arg(ifspec, "v6");
441 v6 = false;
442 udp = false;
443 if (value != NULL) {
444 if (strtol((const char *) value, NULL, 10) > 0)
445 v6 = true;
448 value = uml_vector_fetch_arg(ifspec, "udp");
449 if (value != NULL) {
450 if (strtol((const char *) value, NULL, 10) > 0)
451 udp = true;
453 src = uml_vector_fetch_arg(ifspec, "src");
454 dst = uml_vector_fetch_arg(ifspec, "dst");
455 srcport = uml_vector_fetch_arg(ifspec, "srcport");
456 dstport = uml_vector_fetch_arg(ifspec, "dstport");
458 memset(&dsthints, 0, sizeof(dsthints));
460 if (v6)
461 dsthints.ai_family = AF_INET6;
462 else
463 dsthints.ai_family = AF_INET;
465 switch (id) {
466 case ID_GRE:
467 dsthints.ai_socktype = SOCK_RAW;
468 dsthints.ai_protocol = IPPROTO_GRE;
469 break;
470 case ID_L2TPV3:
471 if (udp) {
472 dsthints.ai_socktype = SOCK_DGRAM;
473 dsthints.ai_protocol = 0;
474 } else {
475 dsthints.ai_socktype = SOCK_RAW;
476 dsthints.ai_protocol = IPPROTO_L2TP;
478 break;
479 default:
480 printk(KERN_ERR "Unsupported socket type\n");
481 return NULL;
483 memcpy(&srchints, &dsthints, sizeof(struct addrinfo));
485 gairet = getaddrinfo(src, srcport, &dsthints, &gairesult);
486 if ((gairet != 0) || (gairesult == NULL)) {
487 printk(UM_KERN_ERR
488 "socket_open : could not resolve src, error = %s",
489 gai_strerror(gairet)
491 return NULL;
493 fd = socket(gairesult->ai_family,
494 gairesult->ai_socktype, gairesult->ai_protocol);
495 if (fd == -1) {
496 printk(UM_KERN_ERR
497 "socket_open : could not open socket, error = %d",
498 -errno
500 goto cleanup;
502 if (bind(fd,
503 (struct sockaddr *) gairesult->ai_addr,
504 gairesult->ai_addrlen)) {
505 printk(UM_KERN_ERR L2TPV3_BIND_FAIL, errno);
506 goto cleanup;
509 if (gairesult != NULL)
510 freeaddrinfo(gairesult);
512 gairesult = NULL;
514 gairet = getaddrinfo(dst, dstport, &dsthints, &gairesult);
515 if ((gairet != 0) || (gairesult == NULL)) {
516 printk(UM_KERN_ERR
517 "socket_open : could not resolve dst, error = %s",
518 gai_strerror(gairet)
520 return NULL;
523 result = uml_kmalloc(sizeof(struct vector_fds), UM_GFP_KERNEL);
524 if (result != NULL) {
525 result->rx_fd = fd;
526 result->tx_fd = fd;
527 result->remote_addr = uml_kmalloc(
528 gairesult->ai_addrlen, UM_GFP_KERNEL);
529 if (result->remote_addr == NULL)
530 goto cleanup;
531 result->remote_addr_size = gairesult->ai_addrlen;
532 memcpy(
533 result->remote_addr,
534 gairesult->ai_addr,
535 gairesult->ai_addrlen
538 freeaddrinfo(gairesult);
539 return result;
540 cleanup:
541 if (gairesult != NULL)
542 freeaddrinfo(gairesult);
543 printk(UM_KERN_ERR "user_init_socket: init failed, error %d", err);
544 if (fd >= 0)
545 os_close_file(fd);
546 if (result != NULL) {
547 kfree(result->remote_addr);
548 kfree(result);
550 return NULL;
553 struct vector_fds *uml_vector_user_open(
554 int unit,
555 struct arglist *parsed
558 char *transport;
560 if (parsed == NULL) {
561 printk(UM_KERN_ERR "no parsed config for unit %d\n", unit);
562 return NULL;
564 transport = uml_vector_fetch_arg(parsed, "transport");
565 if (transport == NULL) {
566 printk(UM_KERN_ERR "missing transport for unit %d\n", unit);
567 return NULL;
569 if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
570 return user_init_raw_fds(parsed);
571 if (strncmp(transport, TRANS_HYBRID, TRANS_HYBRID_LEN) == 0)
572 return user_init_hybrid_fds(parsed);
573 if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
574 return user_init_tap_fds(parsed);
575 if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
576 return user_init_socket_fds(parsed, ID_GRE);
577 if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0)
578 return user_init_socket_fds(parsed, ID_L2TPV3);
579 if (strncmp(transport, TRANS_BESS, TRANS_BESS_LEN) == 0)
580 return user_init_unix_fds(parsed, ID_BESS);
581 return NULL;
585 int uml_vector_sendmsg(int fd, void *hdr, int flags)
587 int n;
589 CATCH_EINTR(n = sendmsg(fd, (struct msghdr *) hdr, flags));
590 if ((n < 0) && (errno == EAGAIN))
591 return 0;
592 if (n >= 0)
593 return n;
594 else
595 return -errno;
598 int uml_vector_recvmsg(int fd, void *hdr, int flags)
600 int n;
601 struct msghdr *msg = (struct msghdr *) hdr;
603 CATCH_EINTR(n = readv(fd, msg->msg_iov, msg->msg_iovlen));
604 if ((n < 0) && (errno == EAGAIN))
605 return 0;
606 if (n >= 0)
607 return n;
608 else
609 return -errno;
612 int uml_vector_writev(int fd, void *hdr, int iovcount)
614 int n;
616 CATCH_EINTR(n = writev(fd, (struct iovec *) hdr, iovcount));
617 if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
618 return 0;
619 if (n >= 0)
620 return n;
621 else
622 return -errno;
625 int uml_vector_sendmmsg(
626 int fd,
627 void *msgvec,
628 unsigned int vlen,
629 unsigned int flags)
631 int n;
633 CATCH_EINTR(n = sendmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags));
634 if ((n < 0) && ((errno == EAGAIN) || (errno == ENOBUFS)))
635 return 0;
636 if (n >= 0)
637 return n;
638 else
639 return -errno;
642 int uml_vector_recvmmsg(
643 int fd,
644 void *msgvec,
645 unsigned int vlen,
646 unsigned int flags)
648 int n;
650 CATCH_EINTR(
651 n = recvmmsg(fd, (struct mmsghdr *) msgvec, vlen, flags, 0));
652 if ((n < 0) && (errno == EAGAIN))
653 return 0;
654 if (n >= 0)
655 return n;
656 else
657 return -errno;
659 int uml_vector_attach_bpf(int fd, void *bpf)
661 struct sock_fprog *prog = bpf;
663 int err = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, bpf, sizeof(struct sock_fprog));
665 if (err < 0)
666 printk(KERN_ERR BPF_ATTACH_FAIL, prog->len, prog->filter, fd, -errno);
667 return err;
670 int uml_vector_detach_bpf(int fd, void *bpf)
672 struct sock_fprog *prog = bpf;
674 int err = setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, bpf, sizeof(struct sock_fprog));
675 if (err < 0)
676 printk(KERN_ERR BPF_DETACH_FAIL, prog->len, prog->filter, fd, -errno);
677 return err;
679 void *uml_vector_default_bpf(void *mac)
681 struct sock_filter *bpf;
682 uint32_t *mac1 = (uint32_t *)(mac + 2);
683 uint16_t *mac2 = (uint16_t *) mac;
684 struct sock_fprog *bpf_prog;
686 bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
687 if (bpf_prog) {
688 bpf_prog->len = DEFAULT_BPF_LEN;
689 bpf_prog->filter = NULL;
690 } else {
691 return NULL;
693 bpf = uml_kmalloc(
694 sizeof(struct sock_filter) * DEFAULT_BPF_LEN, UM_GFP_KERNEL);
695 if (bpf) {
696 bpf_prog->filter = bpf;
697 /* ld [8] */
698 bpf[0] = (struct sock_filter){ 0x20, 0, 0, 0x00000008 };
699 /* jeq #0xMAC[2-6] jt 2 jf 5*/
700 bpf[1] = (struct sock_filter){ 0x15, 0, 3, ntohl(*mac1)};
701 /* ldh [6] */
702 bpf[2] = (struct sock_filter){ 0x28, 0, 0, 0x00000006 };
703 /* jeq #0xMAC[0-1] jt 4 jf 5 */
704 bpf[3] = (struct sock_filter){ 0x15, 0, 1, ntohs(*mac2)};
705 /* ret #0 */
706 bpf[4] = (struct sock_filter){ 0x6, 0, 0, 0x00000000 };
707 /* ret #0x40000 */
708 bpf[5] = (struct sock_filter){ 0x6, 0, 0, 0x00040000 };
709 } else {
710 kfree(bpf_prog);
711 bpf_prog = NULL;
713 return bpf_prog;
716 /* Note - this function requires a valid mac being passed as an arg */
718 void *uml_vector_user_bpf(char *filename)
720 struct sock_filter *bpf;
721 struct sock_fprog *bpf_prog;
722 struct stat statbuf;
723 int res, ffd = -1;
725 if (filename == NULL)
726 return NULL;
728 if (stat(filename, &statbuf) < 0) {
729 printk(KERN_ERR "Error %d reading bpf file", -errno);
730 return false;
732 bpf_prog = uml_kmalloc(sizeof(struct sock_fprog), UM_GFP_KERNEL);
733 if (bpf_prog != NULL) {
734 bpf_prog->len = statbuf.st_size / sizeof(struct sock_filter);
735 bpf_prog->filter = NULL;
737 ffd = os_open_file(filename, of_read(OPENFLAGS()), 0);
738 if (ffd < 0) {
739 printk(KERN_ERR "Error %d opening bpf file", -errno);
740 goto bpf_failed;
742 bpf = uml_kmalloc(statbuf.st_size, UM_GFP_KERNEL);
743 if (bpf == NULL) {
744 printk(KERN_ERR "Failed to allocate bpf buffer");
745 goto bpf_failed;
747 bpf_prog->filter = bpf;
748 res = os_read_file(ffd, bpf, statbuf.st_size);
749 if (res < statbuf.st_size) {
750 printk(KERN_ERR "Failed to read bpf program %s, error %d", filename, res);
751 kfree(bpf);
752 goto bpf_failed;
754 os_close_file(ffd);
755 return bpf_prog;
756 bpf_failed:
757 if (ffd > 0)
758 os_close_file(ffd);
759 kfree(bpf_prog);
760 return NULL;