From 8cc50c346b983c2a01536f7a48b9525792e1c4d7 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Mon, 27 Sep 2021 00:26:15 +0200 Subject: 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 --- tap.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/tap.c b/tap.c index 162d02b..991dfc8 100644 --- a/tap.c +++ b/tap.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -868,6 +869,72 @@ fail: return 0; } +/** + * 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 @@ -875,8 +942,7 @@ fail: 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; -- cgit v1.2.3