Main use case is being able to disable IPv6 on (a) WAN interface(s) when only IPv4 connectivity is offered or 6rd is used.
Signed-off-by: Hans Dedecker <[email protected]> --- bridge.c | 7 +++++++ device.c | 9 +++++++++ device.h | 3 +++ system-linux.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/bridge.c b/bridge.c index 6baef29..03aeff9 100644 --- a/bridge.c +++ b/bridge.c @@ -154,6 +154,12 @@ bridge_enable_member(struct bridge_member *bm) if (!bm->present) return 0; + /* Disable IPv6 for bridge members */ + if (!(bm->dev.dev->settings.flags & DEV_OPT_IPV6)) { + bm->dev.dev->settings.ipv6 = 0; + bm->dev.dev->settings.flags |= DEV_OPT_IPV6; + } + ret = device_claim(&bm->dev); if (ret < 0) goto error; @@ -237,6 +243,7 @@ bridge_member_cb(struct device_user *dev, enum device_event ev) if (bst->n_present == 1) device_set_present(&bst->dev, true); + if (bst->dev.active && !bridge_enable_member(bm)) { /* * Adding a bridge member can overwrite the bridge mtu diff --git a/device.c b/device.c index 2fb68d7..f484c28 100644 --- a/device.c +++ b/device.c @@ -37,6 +37,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = { [DEV_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, [DEV_ATTR_TXQUEUELEN] = { .name = "txqueuelen", .type = BLOBMSG_TYPE_INT32 }, [DEV_ATTR_ENABLED] = { .name = "enabled", .type = BLOBMSG_TYPE_BOOL }, + [DEV_ATTR_IPV6] = { .name = "ipv6", .type = BLOBMSG_TYPE_BOOL }, }; const struct uci_blob_param_list device_attr_list = { @@ -139,6 +140,7 @@ device_merge_settings(struct device *dev, struct device_settings *n) memcpy(n->macaddr, (s->flags & DEV_OPT_MACADDR ? s->macaddr : os->macaddr), sizeof(n->macaddr)); + n->ipv6 = s->flags & DEV_OPT_IPV6 ? s->ipv6 : os->ipv6; n->flags = s->flags | os->flags; } @@ -172,6 +174,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb) } } + if ((cur = tb[DEV_ATTR_IPV6])) { + s->ipv6 = blobmsg_get_bool(cur); + s->flags |= DEV_OPT_IPV6; + } + device_set_disabled(dev, disabled); } @@ -705,6 +712,8 @@ device_dump_status(struct blob_buf *b, struct device *dev) blobmsg_add_string(b, "macaddr", format_macaddr(st.macaddr)); if (st.flags & DEV_OPT_TXQUEUELEN) blobmsg_add_u32(b, "txqueuelen", st.txqueuelen); + if (st.flags & DEV_OPT_IPV6) + blobmsg_add_u8(b, "ipv6", st.ipv6); } s = blobmsg_open_table(b, "statistics"); diff --git a/device.h b/device.h index e71027e..6fceaa1 100644 --- a/device.h +++ b/device.h @@ -31,6 +31,7 @@ enum { DEV_ATTR_MACADDR, DEV_ATTR_TXQUEUELEN, DEV_ATTR_ENABLED, + DEV_ATTR_IPV6, __DEV_ATTR_MAX, }; @@ -60,6 +61,7 @@ enum { DEV_OPT_MTU = (1 << 0), DEV_OPT_MACADDR = (1 << 1), DEV_OPT_TXQUEUELEN = (1 << 2), + DEV_OPT_IPV6 = (1 << 3), }; /* events broadcasted to all users of a device */ @@ -105,6 +107,7 @@ struct device_settings { unsigned int mtu; unsigned int txqueuelen; uint8_t macaddr[6]; + bool ipv6; }; /* diff --git a/system-linux.c b/system-linux.c index 7cec649..8f46705 100644 --- a/system-linux.c +++ b/system-linux.c @@ -211,6 +211,40 @@ 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); } +static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz) +{ + int fd = -1, ret = -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto out; + + ssize_t len = read(fd, buf, buf_sz - 1); + if (len < 0) + goto out; + + ret = buf[len] = 0; + +out: + if (fd >= 0) + close(fd); + + return ret; +} + +static int +system_get_dev_sysctl(const char *path, const char *device, char *buf, const size_t buf_sz) +{ + snprintf(dev_buf, sizeof(dev_buf), path, device); + return system_get_sysctl(dev_buf, buf, buf_sz); +} + +static int system_get_disable_ipv6(struct device *dev, char *buf, const size_t buf_sz) +{ + return system_get_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", + dev->ifname, buf, buf_sz); +} + #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 #endif @@ -380,7 +414,6 @@ int system_bridge_addif(struct device *bridge, struct device *dev) { char *oldbr; - system_set_disable_ipv6(dev, "1"); oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf)); if (oldbr && !strcmp(oldbr, bridge->ifname)) return 0; @@ -390,7 +423,6 @@ int system_bridge_addif(struct device *bridge, struct device *dev) 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); } @@ -777,6 +809,7 @@ static void system_if_get_settings(struct device *dev, struct device_settings *s) { struct ifreq ifr; + char buf[10]; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); @@ -795,6 +828,11 @@ system_if_get_settings(struct device *dev, struct device_settings *s) memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr)); s->flags |= DEV_OPT_MACADDR; } + + if (!system_get_disable_ipv6(dev, buf, sizeof(buf))) { + s->ipv6 = !strtoul(buf, NULL, 0); + s->flags |= DEV_OPT_IPV6; + } } void @@ -823,6 +861,8 @@ system_if_apply_settings(struct device *dev, struct device_settings *s, unsigned if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0) s->flags &= ~DEV_OPT_MACADDR; } + if (s->flags & DEV_OPT_IPV6 & apply_mask) + system_set_disable_ipv6(dev, s->ipv6 ? "0" : "1"); } int system_if_up(struct device *dev) -- 1.7.1 _______________________________________________ openwrt-devel mailing list [email protected] https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
