1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
12 #include <sys/ioctl.h>
14 #include <linux/if_tun.h>
15 #include <arpa/inet.h>
16 #include <sys/types.h>
19 #include <sys/socket.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>
28 #include <linux/virtio_net.h>
32 #include <um_malloc.h>
33 #include "vector_user.h"
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
)
63 for (i
= 0; i
< ifspec
->numargs
; i
++) {
64 if (strcmp(ifspec
->tokens
[i
], token
) == 0)
65 return ifspec
->values
[i
];
71 struct arglist
*uml_parse_vector_ifspec(char *arg
)
73 struct arglist
*result
;
75 bool parsing_token
= true, next_starts
= true;
79 result
= uml_kmalloc(sizeof(struct arglist
), UM_GFP_KERNEL
);
84 for (pos
= 0; pos
< len
; pos
++) {
87 result
->tokens
[result
->numargs
] = arg
+ pos
;
89 result
->values
[result
->numargs
] = arg
+ pos
;
94 if (*(arg
+ pos
) == '=') {
96 parsing_token
= false;
100 (*(arg
+ pos
)) = '\0';
102 if (*(arg
+ pos
) == ',') {
103 parsing_token
= true;
105 (*(arg
+ pos
)) = '\0';
110 printk(UM_KERN_ERR
"vector_setup - Couldn't parse '%s'\n", arg
);
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
)
128 int err
= -ENOMEM
, offload
;
130 fd
= open(PATH_NET_TUN
, O_RDWR
);
132 printk(UM_KERN_ERR
"uml_tap: failed to open tun device\n");
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
);
141 printk(UM_KERN_ERR
"uml_tap: failed to select tap interface\n");
145 offload
= TUN_F_CSUM
| TUN_F_TSO4
| TUN_F_TSO6
;
146 ioctl(fd
, TUNSETOFFLOAD
, offload
);
154 static int create_raw_fd(char *iface
, int flags
, int proto
)
158 struct sockaddr_ll sock
;
161 fd
= socket(AF_PACKET
, SOCK_RAW
, flags
);
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) {
173 sock
.sll_family
= AF_PACKET
;
174 sock
.sll_protocol
= htons(proto
);
175 sock
.sll_ifindex
= ifr
.ifr_ifindex
;
178 (struct sockaddr
*) &sock
, sizeof(struct sockaddr_ll
)) < 0) {
184 printk(UM_KERN_ERR
"user_init_raw: init failed, error %d", err
);
190 static struct vector_fds
*user_init_tap_fds(struct arglist
*ifspec
)
194 struct vector_fds
*result
= NULL
;
196 iface
= uml_vector_fetch_arg(ifspec
, TOKEN_IFNAME
);
198 printk(UM_KERN_ERR
"uml_tap: failed to parse interface spec\n");
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");
209 result
->remote_addr
= NULL
;
210 result
->remote_addr_size
= 0;
214 fd
= create_tap_fd(iface
);
216 printk(UM_KERN_ERR
"uml_tap: failed to create tun interface\n");
223 printk(UM_KERN_ERR
"user_init_tap: init failed, error %d", fd
);
229 static struct vector_fds
*user_init_hybrid_fds(struct arglist
*ifspec
)
232 struct vector_fds
*result
= NULL
;
234 iface
= uml_vector_fetch_arg(ifspec
, TOKEN_IFNAME
);
236 printk(UM_KERN_ERR
"uml_tap: failed to parse interface spec\n");
240 result
= uml_kmalloc(sizeof(struct vector_fds
), UM_GFP_KERNEL
);
241 if (result
== NULL
) {
242 printk(UM_KERN_ERR
"uml_tap: failed to allocate file descriptors\n");
247 result
->remote_addr
= NULL
;
248 result
->remote_addr_size
= 0;
252 result
->tx_fd
= create_tap_fd(iface
);
253 if (result
->tx_fd
< 0) {
254 printk(UM_KERN_ERR
"uml_tap: failed to create tun interface: %i\n", result
->tx_fd
);
260 result
->rx_fd
= create_raw_fd(iface
, ETH_P_ALL
, ETH_P_ALL
);
261 if (result
->rx_fd
== -1) {
263 "uml_tap: failed to create paired raw socket: %i\n", result
->rx_fd
);
268 printk(UM_KERN_ERR
"user_init_hybrid: init failed");
274 static struct vector_fds
*user_init_unix_fds(struct arglist
*ifspec
, int id
)
279 struct vector_fds
*result
= NULL
;
280 struct sockaddr_un
*local_addr
= NULL
, *remote_addr
= NULL
;
282 src
= uml_vector_fetch_arg(ifspec
, "src");
283 dst
= uml_vector_fetch_arg(ifspec
, "dst");
284 result
= uml_kmalloc(sizeof(struct vector_fds
), UM_GFP_KERNEL
);
285 if (result
== NULL
) {
286 printk(UM_KERN_ERR
"unix open:cannot allocate remote addr");
289 remote_addr
= uml_kmalloc(sizeof(struct sockaddr_un
), UM_GFP_KERNEL
);
290 if (remote_addr
== NULL
) {
291 printk(UM_KERN_ERR
"unix open:cannot allocate remote addr");
297 socktype
= SOCK_SEQPACKET
;
298 if ((src
!= NULL
) && (strlen(src
) <= MAX_UN_LEN
)) {
299 local_addr
= uml_kmalloc(sizeof(struct sockaddr_un
), UM_GFP_KERNEL
);
300 if (local_addr
== NULL
) {
301 printk(UM_KERN_ERR
"bess open:cannot allocate local addr");
304 local_addr
->sun_family
= AF_UNIX
;
305 memcpy(local_addr
->sun_path
, src
, strlen(src
) + 1);
307 if ((dst
== NULL
) || (strlen(dst
) > MAX_UN_LEN
))
309 remote_addr
->sun_family
= AF_UNIX
;
310 memcpy(remote_addr
->sun_path
, dst
, strlen(dst
) + 1);
313 printk(KERN_ERR
"Unsupported unix socket type\n");
317 fd
= socket(AF_UNIX
, socktype
, 0);
320 "unix open: could not open socket, error = %d",
325 if (local_addr
!= NULL
) {
326 if (bind(fd
, (struct sockaddr
*) local_addr
, sizeof(struct sockaddr_un
))) {
327 printk(UM_KERN_ERR UNIX_BIND_FAIL
, errno
);
333 if (connect(fd
, remote_addr
, sizeof(struct sockaddr_un
)) < 0) {
334 printk(UM_KERN_ERR
"bess open:cannot connect to %s %i", remote_addr
->sun_path
, -errno
);
341 result
->remote_addr_size
= sizeof(struct sockaddr_un
);
342 result
->remote_addr
= remote_addr
;
347 if (remote_addr
!= NULL
)
354 static struct vector_fds
*user_init_raw_fds(struct arglist
*ifspec
)
356 int rxfd
= -1, txfd
= -1;
359 struct vector_fds
*result
= NULL
;
361 iface
= uml_vector_fetch_arg(ifspec
, TOKEN_IFNAME
);
365 rxfd
= create_raw_fd(iface
, ETH_P_ALL
, ETH_P_ALL
);
370 txfd
= create_raw_fd(iface
, 0, ETH_P_IP
); /* Turn off RX on this fd */
375 result
= uml_kmalloc(sizeof(struct vector_fds
), UM_GFP_KERNEL
);
376 if (result
!= NULL
) {
377 result
->rx_fd
= rxfd
;
378 result
->tx_fd
= txfd
;
379 result
->remote_addr
= NULL
;
380 result
->remote_addr_size
= 0;
384 printk(UM_KERN_ERR
"user_init_raw: init failed, error %d", err
);
391 bool uml_raw_enable_qdisc_bypass(int fd
)
396 SOL_PACKET
, PACKET_QDISC_BYPASS
,
397 &optval
, sizeof(optval
)) != 0) {
403 bool uml_raw_enable_vnet_headers(int fd
)
408 SOL_PACKET
, PACKET_VNET_HDR
,
409 &optval
, sizeof(optval
)) != 0) {
410 printk(UM_KERN_INFO VNET_HDR_FAIL
, fd
);
415 bool uml_tap_enable_vnet_headers(int fd
)
417 unsigned int features
;
418 int len
= sizeof(struct virtio_net_hdr
);
420 if (ioctl(fd
, TUNGETFEATURES
, &features
) == -1) {
421 printk(UM_KERN_INFO TUN_GET_F_FAIL
, strerror(errno
));
424 if ((features
& IFF_VNET_HDR
) == 0) {
425 printk(UM_KERN_INFO
"tapraw: No VNET HEADER support");
428 ioctl(fd
, TUNSETVNETHDRSZ
, &len
);
432 static struct vector_fds
*user_init_socket_fds(struct arglist
*ifspec
, int id
)
436 struct addrinfo srchints
;
437 struct addrinfo dsthints
;
440 char *src
, *dst
, *srcport
, *dstport
;
441 struct addrinfo
*gairesult
= NULL
;
442 struct vector_fds
*result
= NULL
;
445 value
= uml_vector_fetch_arg(ifspec
, "v6");
449 if (strtol((const char *) value
, NULL
, 10) > 0)
453 value
= uml_vector_fetch_arg(ifspec
, "udp");
455 if (strtol((const char *) value
, NULL
, 10) > 0)
458 src
= uml_vector_fetch_arg(ifspec
, "src");
459 dst
= uml_vector_fetch_arg(ifspec
, "dst");
460 srcport
= uml_vector_fetch_arg(ifspec
, "srcport");
461 dstport
= uml_vector_fetch_arg(ifspec
, "dstport");
463 memset(&dsthints
, 0, sizeof(dsthints
));
466 dsthints
.ai_family
= AF_INET6
;
468 dsthints
.ai_family
= AF_INET
;
472 dsthints
.ai_socktype
= SOCK_RAW
;
473 dsthints
.ai_protocol
= IPPROTO_GRE
;
477 dsthints
.ai_socktype
= SOCK_DGRAM
;
478 dsthints
.ai_protocol
= 0;
480 dsthints
.ai_socktype
= SOCK_RAW
;
481 dsthints
.ai_protocol
= IPPROTO_L2TP
;
485 printk(KERN_ERR
"Unsupported socket type\n");
488 memcpy(&srchints
, &dsthints
, sizeof(struct addrinfo
));
490 gairet
= getaddrinfo(src
, srcport
, &dsthints
, &gairesult
);
491 if ((gairet
!= 0) || (gairesult
== NULL
)) {
493 "socket_open : could not resolve src, error = %s",
498 fd
= socket(gairesult
->ai_family
,
499 gairesult
->ai_socktype
, gairesult
->ai_protocol
);
502 "socket_open : could not open socket, error = %d",
508 (struct sockaddr
*) gairesult
->ai_addr
,
509 gairesult
->ai_addrlen
)) {
510 printk(UM_KERN_ERR L2TPV3_BIND_FAIL
, errno
);
514 if (gairesult
!= NULL
)
515 freeaddrinfo(gairesult
);
519 gairet
= getaddrinfo(dst
, dstport
, &dsthints
, &gairesult
);
520 if ((gairet
!= 0) || (gairesult
== NULL
)) {
522 "socket_open : could not resolve dst, error = %s",
528 result
= uml_kmalloc(sizeof(struct vector_fds
), UM_GFP_KERNEL
);
529 if (result
!= NULL
) {
532 result
->remote_addr
= uml_kmalloc(
533 gairesult
->ai_addrlen
, UM_GFP_KERNEL
);
534 if (result
->remote_addr
== NULL
)
536 result
->remote_addr_size
= gairesult
->ai_addrlen
;
540 gairesult
->ai_addrlen
543 freeaddrinfo(gairesult
);
546 if (gairesult
!= NULL
)
547 freeaddrinfo(gairesult
);
548 printk(UM_KERN_ERR
"user_init_socket: init failed, error %d", err
);
551 if (result
!= NULL
) {
552 kfree(result
->remote_addr
);
558 struct vector_fds
*uml_vector_user_open(
560 struct arglist
*parsed
565 if (parsed
== NULL
) {
566 printk(UM_KERN_ERR
"no parsed config for unit %d\n", unit
);
569 transport
= uml_vector_fetch_arg(parsed
, "transport");
570 if (transport
== NULL
) {
571 printk(UM_KERN_ERR
"missing transport for unit %d\n", unit
);
574 if (strncmp(transport
, TRANS_RAW
, TRANS_RAW_LEN
) == 0)
575 return user_init_raw_fds(parsed
);
576 if (strncmp(transport
, TRANS_HYBRID
, TRANS_HYBRID_LEN
) == 0)
577 return user_init_hybrid_fds(parsed
);
578 if (strncmp(transport
, TRANS_TAP
, TRANS_TAP_LEN
) == 0)
579 return user_init_tap_fds(parsed
);
580 if (strncmp(transport
, TRANS_GRE
, TRANS_GRE_LEN
) == 0)
581 return user_init_socket_fds(parsed
, ID_GRE
);
582 if (strncmp(transport
, TRANS_L2TPV3
, TRANS_L2TPV3_LEN
) == 0)
583 return user_init_socket_fds(parsed
, ID_L2TPV3
);
584 if (strncmp(transport
, TRANS_BESS
, TRANS_BESS_LEN
) == 0)
585 return user_init_unix_fds(parsed
, ID_BESS
);
590 int uml_vector_sendmsg(int fd
, void *hdr
, int flags
)
594 CATCH_EINTR(n
= sendmsg(fd
, (struct msghdr
*) hdr
, flags
));
595 if ((n
< 0) && (errno
== EAGAIN
))
603 int uml_vector_recvmsg(int fd
, void *hdr
, int flags
)
606 struct msghdr
*msg
= (struct msghdr
*) hdr
;
608 CATCH_EINTR(n
= readv(fd
, msg
->msg_iov
, msg
->msg_iovlen
));
609 if ((n
< 0) && (errno
== EAGAIN
))
617 int uml_vector_writev(int fd
, void *hdr
, int iovcount
)
621 CATCH_EINTR(n
= writev(fd
, (struct iovec
*) hdr
, iovcount
));
622 if ((n
< 0) && ((errno
== EAGAIN
) || (errno
== ENOBUFS
)))
630 int uml_vector_sendmmsg(
638 CATCH_EINTR(n
= sendmmsg(fd
, (struct mmsghdr
*) msgvec
, vlen
, flags
));
639 if ((n
< 0) && ((errno
== EAGAIN
) || (errno
== ENOBUFS
)))
647 int uml_vector_recvmmsg(
656 n
= recvmmsg(fd
, (struct mmsghdr
*) msgvec
, vlen
, flags
, 0));
657 if ((n
< 0) && (errno
== EAGAIN
))
664 int uml_vector_attach_bpf(int fd
, void *bpf
)
666 struct sock_fprog
*prog
= bpf
;
668 int err
= setsockopt(fd
, SOL_SOCKET
, SO_ATTACH_FILTER
, bpf
, sizeof(struct sock_fprog
));
671 printk(KERN_ERR BPF_ATTACH_FAIL
, prog
->len
, prog
->filter
, fd
, -errno
);
675 int uml_vector_detach_bpf(int fd
, void *bpf
)
677 struct sock_fprog
*prog
= bpf
;
679 int err
= setsockopt(fd
, SOL_SOCKET
, SO_DETACH_FILTER
, bpf
, sizeof(struct sock_fprog
));
681 printk(KERN_ERR BPF_DETACH_FAIL
, prog
->len
, prog
->filter
, fd
, -errno
);
684 void *uml_vector_default_bpf(void *mac
)
686 struct sock_filter
*bpf
;
687 uint32_t *mac1
= (uint32_t *)(mac
+ 2);
688 uint16_t *mac2
= (uint16_t *) mac
;
689 struct sock_fprog
*bpf_prog
;
691 bpf_prog
= uml_kmalloc(sizeof(struct sock_fprog
), UM_GFP_KERNEL
);
693 bpf_prog
->len
= DEFAULT_BPF_LEN
;
694 bpf_prog
->filter
= NULL
;
699 sizeof(struct sock_filter
) * DEFAULT_BPF_LEN
, UM_GFP_KERNEL
);
701 bpf_prog
->filter
= bpf
;
703 bpf
[0] = (struct sock_filter
){ 0x20, 0, 0, 0x00000008 };
704 /* jeq #0xMAC[2-6] jt 2 jf 5*/
705 bpf
[1] = (struct sock_filter
){ 0x15, 0, 3, ntohl(*mac1
)};
707 bpf
[2] = (struct sock_filter
){ 0x28, 0, 0, 0x00000006 };
708 /* jeq #0xMAC[0-1] jt 4 jf 5 */
709 bpf
[3] = (struct sock_filter
){ 0x15, 0, 1, ntohs(*mac2
)};
711 bpf
[4] = (struct sock_filter
){ 0x6, 0, 0, 0x00000000 };
713 bpf
[5] = (struct sock_filter
){ 0x6, 0, 0, 0x00040000 };
721 /* Note - this function requires a valid mac being passed as an arg */
723 void *uml_vector_user_bpf(char *filename
)
725 struct sock_filter
*bpf
;
726 struct sock_fprog
*bpf_prog
;
730 if (filename
== NULL
)
733 if (stat(filename
, &statbuf
) < 0) {
734 printk(KERN_ERR
"Error %d reading bpf file", -errno
);
737 bpf_prog
= uml_kmalloc(sizeof(struct sock_fprog
), UM_GFP_KERNEL
);
738 if (bpf_prog
!= NULL
) {
739 bpf_prog
->len
= statbuf
.st_size
/ sizeof(struct sock_filter
);
740 bpf_prog
->filter
= NULL
;
742 ffd
= os_open_file(filename
, of_read(OPENFLAGS()), 0);
744 printk(KERN_ERR
"Error %d opening bpf file", -errno
);
747 bpf
= uml_kmalloc(statbuf
.st_size
, UM_GFP_KERNEL
);
749 printk(KERN_ERR
"Failed to allocate bpf buffer");
752 bpf_prog
->filter
= bpf
;
753 res
= os_read_file(ffd
, bpf
, statbuf
.st_size
);
754 if (res
< statbuf
.st_size
) {
755 printk(KERN_ERR
"Failed to read bpf program %s, error %d", filename
, res
);