aboutgitcodebugslistschat
path: root/tap.c
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2021-09-27 00:26:15 +0200
committerStefano Brivio <sbrivio@redhat.com>2021-09-27 01:28:02 +0200
commit8cc50c346b983c2a01536f7a48b9525792e1c4d7 (patch)
tree926c8b4bf86697f60ab8de29b39f6112f2f3ac21 /tap.c
parenta491c8ee3cd0124571ee4ae3fa29084ce42925f3 (diff)
downloadpasst-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.c76
1 files 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 <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;