Linux Audio

Check our new training course

Embedded Linux training

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