#include <limits.h>
#include <arpa/inet.h>
-#include <netinet/ether.h>
#include <netinet/in.h>
+#include <netinet/ether.h>
#include <linux/rtnetlink.h>
#include <linux/neighbour.h>
system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
}
+static void system_set_ip6segmentrouting(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/seg6_enabled", dev->ifname, val);
+}
+
static void system_set_rpfilter(struct device *dev, const char *val)
{
system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter", dev->ifname, val);
system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", dev->ifname, val);
}
+static void system_set_sendredirects(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
+}
+
+static void system_set_drop_v4_unicast_in_l2_multicast(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast", dev->ifname, val);
+}
+
+static void system_set_drop_v6_unicast_in_l2_multicast(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast", dev->ifname, val);
+}
+
+static void system_set_drop_gratuitous_arp(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp", dev->ifname, val);
+}
+
+static void system_set_drop_unsolicited_na(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na", dev->ifname, val);
+}
+
+static void system_set_arp_accept(struct device *dev, const char *val)
+{
+ system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/arp_accept", dev->ifname, val);
+}
+
static void system_bridge_set_multicast_to_unicast(struct device *dev, const char *val)
{
system_set_dev_sysctl("/sys/class/net/%s/brport/multicast_to_unicast", dev->ifname, val);
system_set_dev_sysctl("/sys/class/net/%s/brport/unicast_flood", dev->ifname, val);
}
-static void system_set_sendredirects(struct device *dev, const char *val)
-{
- system_set_dev_sysctl("/proc/sys/net/ipv4/conf/%s/send_redirects", dev->ifname, val);
-}
-
static void system_bridge_set_vlan_filtering(struct device *dev, const char *val)
{
system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/vlan_filtering", dev->ifname, val);
dev->ifname, buf, buf_sz);
}
+static int system_get_ip6segmentrouting(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/seg6_enabled",
+ dev->ifname, buf, buf_sz);
+}
+
static int system_get_rpfilter(struct device *dev, char *buf, const size_t buf_sz)
{
return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/rp_filter",
dev->ifname, buf, buf_sz);
}
+
+static int system_get_drop_v4_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_unicast_in_l2_multicast",
+ dev->ifname, buf, buf_sz);
+}
+
+static int system_get_drop_v6_unicast_in_l2_multicast(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unicast_in_l2_multicast",
+ dev->ifname, buf, buf_sz);
+}
+
+static int system_get_drop_gratuitous_arp(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp",
+ dev->ifname, buf, buf_sz);
+}
+
+static int system_get_drop_unsolicited_na(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na",
+ dev->ifname, buf, buf_sz);
+}
+
+static int system_get_arp_accept(struct device *dev, char *buf, const size_t buf_sz)
+{
+ return system_get_dev_sysctl("/proc/sys/net/ipv4/conf/%s/arp_accept",
+ dev->ifname, buf, buf_sz);
+}
+
/* Evaluate netlink messages */
static int cb_rtnl_event(struct nl_msg *msg, void *arg)
{
if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
link_state = strtoul(buf, NULL, 0);
- if (dev->type == &simple_device_type && !system_if_force_external(dev->ifname))
+ if (dev->type == &simple_device_type)
device_set_present(dev, true);
device_set_link(dev, link_state ? true : false);
if (dev->type != &simple_device_type)
return;
- if (add && system_if_force_external(dev->ifname))
- return;
-
device_set_present(dev, add);
}
{
char buf[64];
char *oldbr;
- int ret = 0;
+ int tries = 0;
+ int ret;
+retry:
+ ret = 0;
oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
- if (!oldbr || strcmp(oldbr, bridge->ifname) != 0)
+ if (!oldbr || strcmp(oldbr, bridge->ifname) != 0) {
ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
+ tries++;
+ D(SYSTEM, "Failed to add device '%s' to bridge '%s' (tries=%d): %s\n",
+ dev->ifname, bridge->ifname, tries, strerror(errno));
+ if (tries <= 3)
+ goto retry;
+ }
if (dev->wireless)
system_bridge_set_wireless(bridge, dev);
s->flags |= DEV_OPT_IPV6;
}
+ if (!system_get_ip6segmentrouting(dev, buf, sizeof(buf))) {
+ s->ip6segmentrouting = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_IP6SEGMENTROUTING;
+ }
+
if (ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr) == 0) {
s->promisc = ifr.ifr_flags & IFF_PROMISC;
s->flags |= DEV_OPT_PROMISC;
s->sendredirects = strtoul(buf, NULL, 0);
s->flags |= DEV_OPT_SENDREDIRECTS;
}
+
+ if (!system_get_drop_v4_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
+ s->drop_v4_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST;
+ }
+
+ if (!system_get_drop_v6_unicast_in_l2_multicast(dev, buf, sizeof(buf))) {
+ s->drop_v6_unicast_in_l2_multicast = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST;
+ }
+
+ if (!system_get_drop_gratuitous_arp(dev, buf, sizeof(buf))) {
+ s->drop_gratuitous_arp = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_DROP_GRATUITOUS_ARP;
+ }
+
+ if (!system_get_drop_unsolicited_na(dev, buf, sizeof(buf))) {
+ s->drop_unsolicited_na = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_DROP_UNSOLICITED_NA;
+ }
+
+ if (!system_get_arp_accept(dev, buf, sizeof(buf))) {
+ s->arp_accept = strtoul(buf, NULL, 0);
+ s->flags |= DEV_OPT_ARP_ACCEPT;
+ }
}
void
struct ifreq ifr;
char buf[12];
+ apply_mask &= s->flags;
+
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1);
- if (s->flags & DEV_OPT_MTU & apply_mask) {
+ if (apply_mask & DEV_OPT_MTU) {
ifr.ifr_mtu = s->mtu;
if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
s->flags &= ~DEV_OPT_MTU;
}
- if (s->flags & DEV_OPT_MTU6 & apply_mask) {
+ if (apply_mask & DEV_OPT_MTU6) {
system_update_ipv6_mtu(dev, s->mtu6);
}
- if (s->flags & DEV_OPT_TXQUEUELEN & apply_mask) {
+ if (apply_mask & DEV_OPT_TXQUEUELEN) {
ifr.ifr_qlen = s->txqueuelen;
if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
s->flags &= ~DEV_OPT_TXQUEUELEN;
}
- if ((s->flags & DEV_OPT_MACADDR & apply_mask) && !dev->external) {
+ if ((apply_mask & (DEV_OPT_MACADDR | DEV_OPT_DEFAULT_MACADDR)) && !dev->external) {
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
s->flags &= ~DEV_OPT_MACADDR;
}
- if (s->flags & DEV_OPT_IPV6 & apply_mask)
+ if (apply_mask & DEV_OPT_IPV6)
system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1");
- if (s->flags & DEV_OPT_PROMISC & apply_mask) {
+ if (s->flags & DEV_OPT_IP6SEGMENTROUTING & apply_mask) {
+ struct device dummy = {
+ .ifname = "all",
+ };
+ bool ip6segmentrouting = device_check_ip6segmentrouting();
+
+ system_set_ip6segmentrouting(dev, s->ip6segmentrouting ? "1" : "0");
+ system_set_ip6segmentrouting(&dummy, ip6segmentrouting ? "1" : "0");
+ }
+ if (apply_mask & DEV_OPT_PROMISC) {
if (system_if_flags(dev->ifname, s->promisc ? IFF_PROMISC : 0,
!s->promisc ? IFF_PROMISC : 0) < 0)
s->flags &= ~DEV_OPT_PROMISC;
}
- if (s->flags & DEV_OPT_RPFILTER & apply_mask) {
+ if (apply_mask & DEV_OPT_RPFILTER) {
snprintf(buf, sizeof(buf), "%u", s->rpfilter);
system_set_rpfilter(dev, buf);
}
- if (s->flags & DEV_OPT_ACCEPTLOCAL & apply_mask)
+ if (apply_mask & DEV_OPT_ACCEPTLOCAL)
system_set_acceptlocal(dev, s->acceptlocal ? "1" : "0");
- if (s->flags & DEV_OPT_IGMPVERSION & apply_mask) {
+ if (apply_mask & DEV_OPT_IGMPVERSION) {
snprintf(buf, sizeof(buf), "%u", s->igmpversion);
system_set_igmpversion(dev, buf);
}
- if (s->flags & DEV_OPT_MLDVERSION & apply_mask) {
+ if (apply_mask & DEV_OPT_MLDVERSION) {
snprintf(buf, sizeof(buf), "%u", s->mldversion);
system_set_mldversion(dev, buf);
}
- if (s->flags & DEV_OPT_NEIGHREACHABLETIME & apply_mask) {
+ if (apply_mask & DEV_OPT_NEIGHREACHABLETIME) {
snprintf(buf, sizeof(buf), "%u", s->neigh4reachabletime);
system_set_neigh4reachabletime(dev, buf);
snprintf(buf, sizeof(buf), "%u", s->neigh6reachabletime);
system_set_neigh6reachabletime(dev, buf);
}
- if (s->flags & DEV_OPT_NEIGHLOCKTIME & apply_mask) {
+ if (apply_mask & DEV_OPT_NEIGHLOCKTIME) {
snprintf(buf, sizeof(buf), "%d", s->neigh4locktime);
system_set_neigh4locktime(dev, buf);
}
- if (s->flags & DEV_OPT_NEIGHGCSTALETIME & apply_mask) {
+ if (apply_mask & DEV_OPT_NEIGHGCSTALETIME) {
snprintf(buf, sizeof(buf), "%u", s->neigh4gcstaletime);
system_set_neigh4gcstaletime(dev, buf);
snprintf(buf, sizeof(buf), "%u", s->neigh6gcstaletime);
system_set_neigh6gcstaletime(dev, buf);
}
- if (s->flags & DEV_OPT_DADTRANSMITS & apply_mask) {
+ if (apply_mask & DEV_OPT_DADTRANSMITS) {
snprintf(buf, sizeof(buf), "%u", s->dadtransmits);
system_set_dadtransmits(dev, buf);
}
- if (s->flags & DEV_OPT_MULTICAST & apply_mask) {
+ if (apply_mask & DEV_OPT_MULTICAST) {
if (system_if_flags(dev->ifname, s->multicast ? IFF_MULTICAST : 0,
!s->multicast ? IFF_MULTICAST : 0) < 0)
s->flags &= ~DEV_OPT_MULTICAST;
}
- if (s->flags & DEV_OPT_SENDREDIRECTS & apply_mask)
+ if (apply_mask & DEV_OPT_SENDREDIRECTS)
system_set_sendredirects(dev, s->sendredirects ? "1" : "0");
+ if (apply_mask & DEV_OPT_DROP_V4_UNICAST_IN_L2_MULTICAST)
+ system_set_drop_v4_unicast_in_l2_multicast(dev, s->drop_v4_unicast_in_l2_multicast ? "1" : "0");
+ if (apply_mask & DEV_OPT_DROP_V6_UNICAST_IN_L2_MULTICAST)
+ system_set_drop_v6_unicast_in_l2_multicast(dev, s->drop_v6_unicast_in_l2_multicast ? "1" : "0");
+ if (apply_mask & DEV_OPT_DROP_GRATUITOUS_ARP)
+ system_set_drop_gratuitous_arp(dev, s->drop_gratuitous_arp ? "1" : "0");
+ if (apply_mask & DEV_OPT_DROP_UNSOLICITED_NA)
+ system_set_drop_unsolicited_na(dev, s->drop_unsolicited_na ? "1" : "0");
+ if (apply_mask & DEV_OPT_ARP_ACCEPT)
+ system_set_arp_accept(dev, s->arp_accept ? "1" : "0");
}
int system_if_up(struct device *dev)
{
- system_if_get_settings(dev, &dev->orig_settings);
- /* Only keep orig settings based on what needs to be set */
- dev->orig_settings.valid_flags = dev->orig_settings.flags;
- dev->orig_settings.flags &= dev->settings.flags;
- system_if_apply_settings(dev, &dev->settings, dev->settings.flags);
return system_if_flags(dev->ifname, IFF_UP, 0);
}
int system_if_down(struct device *dev)
{
- int ret = system_if_flags(dev->ifname, 0, IFF_UP);
- system_if_apply_settings(dev, &dev->orig_settings, dev->orig_settings.flags);
- return ret;
+ return system_if_flags(dev->ifname, 0, IFF_UP);
}
struct if_check_data {
if (nh->nlmsg_type != RTM_NEWLINK)
return NL_SKIP;
- device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
+ if (chk->dev->type == &simple_device_type)
+ device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false);
device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false);
return NL_OK;
{
struct if_check_data *chk = (struct if_check_data *)arg;
- device_set_present(chk->dev, false);
+ if (chk->dev->type == &simple_device_type)
+ device_set_present(chk->dev, false);
device_set_link(chk->dev, false);
chk->pending = err->error;