X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fnetifd.git;a=blobdiff_plain;f=system-linux.c;h=e313cbc97934bf37f410e180419fe66bef039f99;hp=867af0f823daf7467b60feafa6e2f22274eb3c20;hb=f8276b9b149f3b0c8f3cdf8d3d0c232bd92e3464;hpb=3216a341221f9b0b2901f6489c77888c1a9e192c diff --git a/system-linux.c b/system-linux.c index 867af0f..e313cbc 100644 --- a/system-linux.c +++ b/system-linux.c @@ -87,6 +87,31 @@ static void handler_rtnl_event(struct uloop_fd *u, unsigned int events) nl_recvmsgs(sock_rtnl_event, nl_cb_rtnl_event); } +static void system_set_sysctl(const char *path, const char *val) +{ + int fd; + + fd = open(path, O_WRONLY); + if (fd < 0) + return; + + write(fd, val, strlen(val)); + close(fd); +} + +static void system_set_dev_sysctl(const char *path, const char *device, const char *val) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), path, val); + system_set_sysctl(buf, val); +} + +static void system_set_disable_ipv6(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val); +} + // Evaluate netlink messages static int cb_rtnl_event(struct nl_msg *msg, void *arg) { @@ -138,11 +163,13 @@ static int system_bridge_if(const char *bridge, struct device *dev, int cmd, voi int system_bridge_addif(struct device *bridge, struct device *dev) { + system_set_disable_ipv6(dev, "1"); return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); } int system_bridge_delif(struct device *bridge, struct device *dev) { + system_set_disable_ipv6(dev, "0"); return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); } @@ -365,6 +392,7 @@ void system_if_clear_state(struct device *dev) system_if_clear_entries(dev, RTM_GETADDR, AF_INET); system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6); system_if_clear_entries(dev, RTM_GETADDR, AF_INET6); + system_set_disable_ipv6(dev, "0"); } static inline unsigned long @@ -388,6 +416,9 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg) args[1] = sec_to_jiffies(cfg->forward_delay); system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args); + system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping", + bridge->ifname, cfg->igmp_snoop ? "1" : "0"); + if (cfg->flags & BRIDGE_OPT_AGEING_TIME) { args[0] = BRCTL_SET_AGEING_TIME; args[1] = sec_to_jiffies(cfg->ageing_time); @@ -439,9 +470,32 @@ int system_vlan_del(struct device *dev) return system_vlan(dev, -1); } -int system_if_up(struct device *dev) +static void +system_if_apply_settings(struct device *dev) { + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); + if (dev->flags & DEV_OPT_MTU) { + ifr.ifr_mtu = dev->mtu; + ioctl(sock_ioctl, SIOCSIFMTU, &ifr); + } + if (dev->flags & DEV_OPT_TXQUEUELEN) { + ifr.ifr_qlen = dev->txqueuelen; + ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr); + } + if (dev->flags & DEV_OPT_MACADDR) { + memcpy(&ifr.ifr_hwaddr, dev->macaddr, sizeof(dev->macaddr)); + ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr); + } + dev->ifindex = system_if_resolve(dev); +} + +int system_if_up(struct device *dev) +{ + system_if_apply_settings(dev); return system_if_flags(dev->ifname, IFF_UP, 0); }