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
);
228 static struct vector_fds
*user_init_hybrid_fds(struct arglist
*ifspec
)
231 struct vector_fds
*result
= NULL
;
233 iface
= uml_vector_fetch_arg(ifspec
, TOKEN_IFNAME
);
235 printk(UM_KERN_ERR
"uml_tap: failed to parse interface spec\n");
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");
246 result
->remote_addr
= NULL
;
247 result
->remote_addr_size
= 0;
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
);
259 result
->rx_fd
= create_raw_fd(iface
, ETH_P_ALL
, ETH_P_ALL
);
260 if (result
->rx_fd
== -1) {
262 "uml_tap: failed to create paired raw socket: %i\n", result
->rx_fd
);
267 printk(UM_KERN_ERR
"user_init_hybrid: init failed");
272 static struct vector_fds
*user_init_unix_fds(struct arglist
*ifspec
, int id
)
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");
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");
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");
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
))
307 remote_addr
->sun_family
= AF_UNIX
;
308 memcpy(remote_addr
->sun_path
, dst
, strlen(dst
) + 1);
311 printk(KERN_ERR
"Unsupported unix socket type\n");
315 fd
= socket(AF_UNIX
, socktype
, 0);
318 "unix open: could not open socket, error = %d",
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
);
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
);
339 result
->remote_addr_size
= sizeof(struct sockaddr_un
);
340 result
->remote_addr
= remote_addr
;
350 static struct vector_fds
*user_init_raw_fds(struct arglist
*ifspec
)
352 int rxfd
= -1, txfd
= -1;
355 struct vector_fds
*result
= NULL
;
357 iface
= uml_vector_fetch_arg(ifspec
, TOKEN_IFNAME
);
361 rxfd
= create_raw_fd(iface
, ETH_P_ALL
, ETH_P_ALL
);
366 txfd
= create_raw_fd(iface
, 0, ETH_P_IP
); /* Turn off RX on this fd */
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;
380 printk(UM_KERN_ERR
"user_init_raw: init failed, error %d", err
);
386 bool uml_raw_enable_qdisc_bypass(int fd
)
391 SOL_PACKET
, PACKET_QDISC_BYPASS
,
392 &optval
, sizeof(optval
)) != 0) {
398 bool uml_raw_enable_vnet_headers(int fd
)
403 SOL_PACKET
, PACKET_VNET_HDR
,
404 &optval
, sizeof(optval
)) != 0) {
405 printk(UM_KERN_INFO VNET_HDR_FAIL
, fd
);
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
));
419 if ((features
& IFF_VNET_HDR
) == 0) {
420 printk(UM_KERN_INFO
"tapraw: No VNET HEADER support");
423 ioctl(fd
, TUNSETVNETHDRSZ
, &len
);
427 static struct vector_fds
*user_init_socket_fds(struct arglist
*ifspec
, int id
)
431 struct addrinfo srchints
;
432 struct addrinfo dsthints
;
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");
444 if (strtol((const char *) value
, NULL
, 10) > 0)
448 value
= uml_vector_fetch_arg(ifspec
, "udp");
450 if (strtol((const char *) value
, NULL
, 10) > 0)
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
));
461 dsthints
.ai_family
= AF_INET6
;
463 dsthints
.ai_family
= AF_INET
;
467 dsthints
.ai_socktype
= SOCK_RAW
;
468 dsthints
.ai_protocol
= IPPROTO_GRE
;
472 dsthints
.ai_socktype
= SOCK_DGRAM
;
473 dsthints
.ai_protocol
= 0;
475 dsthints
.ai_socktype
= SOCK_RAW
;
476 dsthints
.ai_protocol
= IPPROTO_L2TP
;
480 printk(KERN_ERR
"Unsupported socket type\n");
483 memcpy(&srchints
, &dsthints
, sizeof(struct addrinfo
));
485 gairet
= getaddrinfo(src
, srcport
, &dsthints
, &gairesult
);
486 if ((gairet
!= 0) || (gairesult
== NULL
)) {
488 "socket_open : could not resolve src, error = %s",
493 fd
= socket(gairesult
->ai_family
,
494 gairesult
->ai_socktype
, gairesult
->ai_protocol
);
497 "socket_open : could not open socket, error = %d",
503 (struct sockaddr
*) gairesult
->ai_addr
,
504 gairesult
->ai_addrlen
)) {
505 printk(UM_KERN_ERR L2TPV3_BIND_FAIL
, errno
);
509 if (gairesult
!= NULL
)
510 freeaddrinfo(gairesult
);
514 gairet
= getaddrinfo(dst
, dstport
, &dsthints
, &gairesult
);
515 if ((gairet
!= 0) || (gairesult
== NULL
)) {
517 "socket_open : could not resolve dst, error = %s",
523 result
= uml_kmalloc(sizeof(struct vector_fds
), UM_GFP_KERNEL
);
524 if (result
!= NULL
) {
527 result
->remote_addr
= uml_kmalloc(
528 gairesult
->ai_addrlen
, UM_GFP_KERNEL
);
529 if (result
->remote_addr
== NULL
)
531 result
->remote_addr_size
= gairesult
->ai_addrlen
;
535 gairesult
->ai_addrlen
538 freeaddrinfo(gairesult
);
541 if (gairesult
!= NULL
)
542 freeaddrinfo(gairesult
);
543 printk(UM_KERN_ERR
"user_init_socket: init failed, error %d", err
);
546 if (result
!= NULL
) {
547 kfree(result
->remote_addr
);
553 struct vector_fds
*uml_vector_user_open(
555 struct arglist
*parsed
560 if (parsed
== NULL
) {
561 printk(UM_KERN_ERR
"no parsed config for unit %d\n", unit
);
564 transport
= uml_vector_fetch_arg(parsed
, "transport");
565 if (transport
== NULL
) {
566 printk(UM_KERN_ERR
"missing transport for unit %d\n", unit
);
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
);
585 int uml_vector_sendmsg(int fd
, void *hdr
, int flags
)
589 CATCH_EINTR(n
= sendmsg(fd
, (struct msghdr
*) hdr
, flags
));
590 if ((n
< 0) && (errno
== EAGAIN
))
598 int uml_vector_recvmsg(int fd
, void *hdr
, int flags
)
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
))
612 int uml_vector_writev(int fd
, void *hdr
, int iovcount
)
616 CATCH_EINTR(n
= writev(fd
, (struct iovec
*) hdr
, iovcount
));
617 if ((n
< 0) && ((errno
== EAGAIN
) || (errno
== ENOBUFS
)))
625 int uml_vector_sendmmsg(
633 CATCH_EINTR(n
= sendmmsg(fd
, (struct mmsghdr
*) msgvec
, vlen
, flags
));
634 if ((n
< 0) && ((errno
== EAGAIN
) || (errno
== ENOBUFS
)))
642 int uml_vector_recvmmsg(
651 n
= recvmmsg(fd
, (struct mmsghdr
*) msgvec
, vlen
, flags
, 0));
652 if ((n
< 0) && (errno
== EAGAIN
))
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
));
666 printk(KERN_ERR BPF_ATTACH_FAIL
, prog
->len
, prog
->filter
, fd
, -errno
);
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
));
676 printk(KERN_ERR BPF_DETACH_FAIL
, prog
->len
, prog
->filter
, fd
, -errno
);
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
);
688 bpf_prog
->len
= DEFAULT_BPF_LEN
;
689 bpf_prog
->filter
= NULL
;
694 sizeof(struct sock_filter
) * DEFAULT_BPF_LEN
, UM_GFP_KERNEL
);
696 bpf_prog
->filter
= bpf
;
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
)};
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
)};
706 bpf
[4] = (struct sock_filter
){ 0x6, 0, 0, 0x00000000 };
708 bpf
[5] = (struct sock_filter
){ 0x6, 0, 0, 0x00040000 };
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
;
725 if (filename
== NULL
)
728 if (stat(filename
, &statbuf
) < 0) {
729 printk(KERN_ERR
"Error %d reading bpf file", -errno
);
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);
739 printk(KERN_ERR
"Error %d opening bpf file", -errno
);
742 bpf
= uml_kmalloc(statbuf
.st_size
, UM_GFP_KERNEL
);
744 printk(KERN_ERR
"Failed to allocate bpf buffer");
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
);