From e9ac0c70c810e09451c866d0ddd0be13b7492831 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Oct 2025 19:08:10 +0200 Subject: [PATCH] Separate change_interface_state() into get/set_if_flags() For configuring a TAP interface, we need to set different options, which is not easily feasible with the current change_interface_state() API (or would make it more complex). To simplify while allowing to set flags more flexibly, separate into two functions get/set_if_flags(). --- common/utils/tun_if.c | 70 ++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/common/utils/tun_if.c b/common/utils/tun_if.c index f74ab3c7f2..c2b21c02b2 100644 --- a/common/utils/tun_if.c +++ b/common/utils/tun_if.c @@ -158,42 +158,47 @@ static bool setInterfaceParameter(int sock_fd, const char *ifn, int af, const ch } -typedef enum { INTERFACE_DOWN, INTERFACE_UP } if_action_t; /* -* \brief bring interface up (up != 0) or down (up == 0) +* \brief Get an interface's flags. +* \param[in] sock_fd socket to use for getting the flags +* \param[in] ifn the interface name for which to get flags +* \param[out] flags the flags of the interface +* \return true on success, false otherwise */ -static bool change_interface_state(int sock_fd, const char *ifn, if_action_t if_action) +static bool get_if_flags(int sock_fd, const char *ifn, short *flags) { - const char *action = if_action == INTERFACE_DOWN ? "DOWN" : "UP"; - struct ifreq ifr = {0}; strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); /* get flags of this interface: see netdevice(7) */ - bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0; - if (!success && if_action == INTERFACE_DOWN && errno == ENODEV) { - LOG_W(OIP, "trying to remove non-existant device %s\n", ifn); - return true; + int success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0; + if (!success) { + LOG_W(OIP, "On interface %s: ioctl() failed: %d, %s\n", ifn, errno, strerror(errno)); + return false; } - LOG_D(OIP, "Got flags for %s: 0x%x (action: %s)\n", ifn, ifr.ifr_flags, action); - - if (if_action == INTERFACE_UP) { - ifr.ifr_flags |= IFF_UP | IFF_NOARP | IFF_POINTOPOINT; - ifr.ifr_flags &= ~IFF_MULTICAST; - } else { - ifr.ifr_flags &= ~IFF_UP; - } - - success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0; - if (!success) - goto fail_interface_state; - LOG_D(OIP, "Interface %s successfully set %s\n", ifn, action); - + *flags = ifr.ifr_flags; return true; +} -fail_interface_state: - LOG_E(OIP, "Bringing interface %s for %s: ioctl call failed: %d, %s\n", action, ifn, errno, strerror(errno)); - return false; +/* + * \brief Set an interface's flags. +* \param[in] sock_fd socket to use for setting the flags +* \param[in] ifn the interface name for which to set flags +* \param[in] flags the flags to set for the interface +* \return true on success, false otherwise + */ +static bool set_if_flags(int sock_fd, const char *ifn, short flags) +{ + struct ifreq ifr = {0}; + strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); + ifr.ifr_flags = flags; + + int success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0; + if (!success) { + LOG_W(OIP, "On interface %s: ioctl() failed: %d, %s\n", ifn, errno, strerror(errno)); + return false; + } + return true; } @@ -227,8 +232,10 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6) close(sock_fd); } + // if successfully set IP addresses: set iterface up, disable ARP, no + // multicast, point-to-point if (success) - success = change_interface_state(sock_fd, ifname, INTERFACE_UP); + success = set_if_flags(sock_fd, ifname, (IFF_UP | IFF_NOARP | IFF_POINTOPOINT) & ~IFF_MULTICAST); if (success) LOG_I(OIP, "Interface %s successfully configured, IPv4 %s, IPv6 %s\n", ifname, ipv4, ipv6); @@ -283,11 +290,12 @@ void tun_destroy(const char *dev) return; } - bool success = change_interface_state(fd, dev, INTERFACE_DOWN); + // interface not up => down + short flags; + bool success = get_if_flags(fd, dev, &flags); + success = success && set_if_flags(fd, dev, flags & ~IFF_UP); if (success) { LOG_I(UTIL, "Interface %s is now down.\n", dev); - } else { - LOG_E(UTIL, "Could not bring interface %s down.\n", dev); - } + } // no else: get_if_flags()/set_if_flags() should have printed error close(fd); }