diff options
-rw-r--r-- | device.h | 1 | ||||
-rw-r--r-- | scripts/netifd-wireless.sh | 15 | ||||
-rw-r--r-- | system-linux.c | 26 | ||||
-rw-r--r-- | wireless.c | 12 | ||||
-rw-r--r-- | wireless.h | 1 |
5 files changed, 48 insertions, 7 deletions
@@ -176,6 +176,7 @@ struct device { bool iface_config; bool default_config; bool wireless; + bool wireless_isolate; struct interface *config_iface; diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh index c5d8a96..f981f1b 100644 --- a/scripts/netifd-wireless.sh +++ b/scripts/netifd-wireless.sh @@ -248,12 +248,26 @@ wireless_vif_parse_encryption() { esac } +_wireless_set_brsnoop_isolation() { + local multicast_to_unicast="$1" + local isolate + + json_get_var isolate isolate + + [ $isolate -gt 0 -o -z "$network_bridge" ] && return + + [ -z "$multicast_to_unicast" ] && multicast_to_unicast=1 + [ $multicast_to_unicast -gt 0 ] && json_add_boolean isolate 1 +} + for_each_interface() { local _w_types="$1"; shift local _w_ifaces _w_iface local _w_type local _w_found + local multicast_to_unicast + json_get_keys _w_ifaces interfaces json_select interfaces for _w_iface in $_w_ifaces; do @@ -261,6 +275,7 @@ for_each_interface() { if [ -n "$_w_types" ]; then json_get_var network_bridge bridge json_select config + _wireless_set_brsnoop_isolation "$multicast_to_unicast" json_get_var _w_type mode json_select .. _w_types=" $_w_types " diff --git a/system-linux.c b/system-linux.c index 9ba13fd..9c4bea6 100644 --- a/system-linux.c +++ b/system-linux.c @@ -315,6 +315,16 @@ static void system_set_dadtransmits(struct device *dev, const char *val) system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/dad_transmits", 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); +} + +static void system_bridge_set_hairpin_mode(struct device *dev, const char *val) +{ + system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, val); +} + static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz) { int fd = -1, ret = -1; @@ -556,12 +566,16 @@ static char *system_get_bridge(const char *name, char *buf, int buflen) return path + 1; } -static void system_bridge_set_wireless(const char *bridge, const char *dev) +static void +system_bridge_set_wireless(struct device *dev) { - snprintf(dev_buf, sizeof(dev_buf), - "/sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", - bridge, dev); - system_set_sysctl(dev_buf, "1"); + bool hairpin = true; + + if (dev->wireless_isolate) + hairpin = false; + + system_bridge_set_multicast_to_unicast(dev, "1"); + system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0"); } int system_bridge_addif(struct device *bridge, struct device *dev) @@ -574,7 +588,7 @@ int system_bridge_addif(struct device *bridge, struct device *dev) ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); if (dev->wireless) - system_bridge_set_wireless(bridge->ifname, dev->ifname); + system_bridge_set_wireless(dev); return ret; } @@ -35,12 +35,14 @@ static const struct uci_blob_param_list wdev_param = { enum { VIF_ATTR_DISABLED, VIF_ATTR_NETWORK, + VIF_ATTR_ISOLATE, __VIF_ATTR_MAX, }; static const struct blobmsg_policy vif_policy[__VIF_ATTR_MAX] = { [VIF_ATTR_DISABLED] = { .name = "disabled", .type = BLOBMSG_TYPE_BOOL }, [VIF_ATTR_NETWORK] = { .name = "network", .type = BLOBMSG_TYPE_ARRAY }, + [VIF_ATTR_ISOLATE] = { .name = "isolate", .type = BLOBMSG_TYPE_BOOL }, }; static const struct uci_blob_param_list vif_param = { @@ -204,8 +206,10 @@ static void wireless_interface_handle_link(struct wireless_interface *vif, bool if (up) { struct device *dev = device_get(vif->ifname, 2); - if (dev) + if (dev) { + dev->wireless_isolate = vif->isolate; dev->wireless = true; + } } blobmsg_for_each_attr(cur, vif->network, rem) { @@ -700,6 +704,12 @@ void wireless_interface_create(struct wireless_device *wdev, struct blob_attr *d vif->wdev = wdev; vif->config = data; vif->section = section; + vif->isolate = false; + + cur = tb[VIF_ATTR_ISOLATE]; + if (cur && blobmsg_get_bool(cur)) + vif->isolate = blobmsg_get_bool(cur); + vlist_add(&wdev->interfaces, &vif->node, vif->name); } @@ -77,6 +77,7 @@ struct wireless_interface { const char *ifname; struct blob_attr *network; + bool isolate; }; struct wireless_process { |