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().
This commit is contained in:
+39
-31
@@ -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};
|
struct ifreq ifr = {0};
|
||||||
strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1);
|
strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1);
|
||||||
|
|
||||||
/* get flags of this interface: see netdevice(7) */
|
/* get flags of this interface: see netdevice(7) */
|
||||||
bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0;
|
int success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0;
|
||||||
if (!success && if_action == INTERFACE_DOWN && errno == ENODEV) {
|
if (!success) {
|
||||||
LOG_W(OIP, "trying to remove non-existant device %s\n", ifn);
|
LOG_W(OIP, "On interface %s: ioctl() failed: %d, %s\n", ifn, errno, strerror(errno));
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
LOG_D(OIP, "Got flags for %s: 0x%x (action: %s)\n", ifn, ifr.ifr_flags, action);
|
*flags = ifr.ifr_flags;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
fail_interface_state:
|
/*
|
||||||
LOG_E(OIP, "Bringing interface %s for %s: ioctl call failed: %d, %s\n", action, ifn, errno, strerror(errno));
|
* \brief Set an interface's flags.
|
||||||
return false;
|
* \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);
|
close(sock_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if successfully set IP addresses: set iterface up, disable ARP, no
|
||||||
|
// multicast, point-to-point
|
||||||
if (success)
|
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)
|
if (success)
|
||||||
LOG_I(OIP, "Interface %s successfully configured, IPv4 %s, IPv6 %s\n", ifname, ipv4, ipv6);
|
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;
|
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) {
|
if (success) {
|
||||||
LOG_I(UTIL, "Interface %s is now down.\n", dev);
|
LOG_I(UTIL, "Interface %s is now down.\n", dev);
|
||||||
} else {
|
} // no else: get_if_flags()/set_if_flags() should have printed error
|
||||||
LOG_E(UTIL, "Could not bring interface %s down.\n", dev);
|
|
||||||
}
|
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user