diff options
author | Stefano Brivio <sbrivio@redhat.com> | 2021-09-27 00:26:15 +0200 |
---|---|---|
committer | Stefano Brivio <sbrivio@redhat.com> | 2021-09-27 01:28:02 +0200 |
commit | 8cc50c346b983c2a01536f7a48b9525792e1c4d7 (patch) | |
tree | 926c8b4bf86697f60ab8de29b39f6112f2f3ac21 /tap.c | |
parent | a491c8ee3cd0124571ee4ae3fa29084ce42925f3 (diff) | |
download | passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar.gz passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar.bz2 passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar.lz passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar.xz passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.tar.zst passt-8cc50c346b983c2a01536f7a48b9525792e1c4d7.zip |
tap: Bring up tap device too, configure previous MAC address if any
In case we need to reinitialise the tap interface, make that
relatively transparent to processes running in the namespace.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Diffstat (limited to 'tap.c')
-rw-r--r-- | tap.c | 76 |
1 files changed, 74 insertions, 2 deletions
@@ -20,6 +20,7 @@ #include <string.h> #include <net/ethernet.h> #include <net/if.h> +#include <net/if_arp.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdint.h> @@ -869,14 +870,79 @@ fail: } /** + * struct tap_sock_if_up_ns_arg - Arguments for tap_sock_if_up_ns() + * @c: Execution context + * @target_pid: Target namespace PID + * @ifname: Interface name of tap device + */ +struct tap_sock_if_up_ns_arg { + struct ctx *c; + int target_pid; + char ifname[IFNAMSIZ]; +}; + +/** + * tap_sock_if_up_ns() - Bring up tap, get or set MAC address (if we have one) + * @ifname: Interface name + * + * Return: 0 -- not fundamental, the interface can be brought up later + */ +static int tap_sock_if_up_ns(void *arg) +{ + struct ifreq ifr = { .ifr_flags = IFF_UP }; + struct tap_sock_if_up_ns_arg *a; + int fd; + + a = (struct tap_sock_if_up_ns_arg *)arg; + + if (ns_enter(a->target_pid)) + return 0; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket for ioctl"); + return 0; + } + + strncpy(ifr.ifr_name, a->ifname, IFNAMSIZ); + if (ioctl(fd, SIOCSIFFLAGS, &ifr)) { + perror("SIOCSIFFLAGS ioctl for tap"); + goto out; + } + + if (memcmp(a->c->mac_guest, + ((uint8_t [ETH_ALEN]){ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }), + ETH_ALEN)) { + ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; + memcpy(ifr.ifr_hwaddr.sa_data, a->c->mac_guest, ETH_ALEN); + + if (ioctl(fd, SIOCSIFHWADDR, &ifr) < 0) { + perror("SIOCSIFHWADDR ioctl for tap"); + goto out; + } + } else { + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + perror("SIOCGIFHWADDR ioctl for tap"); + goto out; + } + + memcpy(a->c->mac_guest, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + proto_update_l2_buf(a->c->mac_guest, NULL, NULL); + } + +out: + close(fd); + + return 0; +} + +/** * tap_sock_init_tun() - Set up tuntap file descriptor * @c: Execution context */ static void tap_sock_init_tun(struct ctx *c) { struct ifreq ifr = { .ifr_flags = IFF_TAP | IFF_NO_PI }; - - strncpy(ifr.ifr_name, c->pasta_ifn, IFNAMSIZ); + struct tap_sock_if_up_ns_arg ifup_arg; NS_CALL(tap_sock_init_tun_ns, &c->pasta_pid); if (tun_ns_fd == -1) { @@ -884,11 +950,17 @@ static void tap_sock_init_tun(struct ctx *c) exit(EXIT_FAILURE); } + strncpy(ifr.ifr_name, c->pasta_ifn, IFNAMSIZ); if (ioctl(tun_ns_fd, TUNSETIFF, &ifr)) { perror("TUNSETIFF ioctl"); exit(EXIT_FAILURE); } + strncpy(ifup_arg.ifname, c->pasta_ifn, IFNAMSIZ); + ifup_arg.target_pid = c->pasta_pid; + ifup_arg.c = c; + NS_CALL(tap_sock_if_up_ns, (void *)&ifup_arg); + pcap_init(c, c->pasta_pid); c->fd_tap = tun_ns_fd; |