Merge 7a4d07ebff
into 563f9afcc0
This commit is contained in:
commit
6f198e8d6e
@ -9,11 +9,12 @@ uci:section('network', 'interface', 'wan',
|
||||
{
|
||||
ifname = sysconfig.wan_ifname,
|
||||
type = 'bridge',
|
||||
igmp_snooping = 0,
|
||||
peerdns = 0,
|
||||
auto = 1,
|
||||
}
|
||||
)
|
||||
uci:delete('network', 'wan', 'igmp_snooping')
|
||||
uci:delete('network', 'wan', 'multicast_querier')
|
||||
|
||||
if not uci:get('network', 'wan', 'proto') then
|
||||
uci:set('network', 'wan', 'proto', 'dhcp')
|
||||
@ -56,5 +57,31 @@ uci:save('network')
|
||||
uci:commit('network')
|
||||
|
||||
|
||||
uci:section('firewall', 'rule', 'wan_igmp',
|
||||
{
|
||||
name = 'Allow-IGMP',
|
||||
src = 'wan',
|
||||
proto = 'igmp',
|
||||
family = 'ipv4',
|
||||
target = 'ACCEPT',
|
||||
}
|
||||
)
|
||||
|
||||
uci:section('firewall', 'rule', 'wan_mld',
|
||||
{
|
||||
name = 'Allow-MLD',
|
||||
src = 'wan',
|
||||
proto = 'icmp',
|
||||
src_ip = 'fe80::/10',
|
||||
icmp_type = { '130/0', '131/0', '143/0', },
|
||||
family = 'ipv6',
|
||||
target = 'ACCEPT',
|
||||
}
|
||||
)
|
||||
|
||||
uci:save('firewall')
|
||||
uci:commit('firewall')
|
||||
|
||||
|
||||
sysctl.set('net.ipv6.conf.all.accept_ra', 0)
|
||||
sysctl.set('net.ipv6.conf.default.accept_ra', 0)
|
||||
|
@ -1 +1,2 @@
|
||||
chain('MULTICAST_OUT', 'DROP')
|
||||
chain('MULTICAST_IN', 'ACCEPT', 'nat')
|
||||
|
@ -1,2 +1,4 @@
|
||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol 0 -j RETURN' -- hop-by-hop
|
||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP' -- MLD query
|
||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP' -- MLDv1 report
|
||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP' -- MLDv2 report
|
||||
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j RETURN'
|
||||
|
@ -1 +0,0 @@
|
||||
rule 'MULTICAST_OUT -p IPv4 --ip-protocol igmp -j RETURN'
|
@ -0,0 +1 @@
|
||||
rule('MULTICAST_IN -p IPv4 --ip-protocol igmp -j DROP', 'nat')
|
@ -0,0 +1,3 @@
|
||||
rule('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP', 'nat') -- MLD query
|
||||
rule('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP', 'nat') -- MLDv1 report
|
||||
rule('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP', 'nat') -- MLDv2 report
|
@ -1,2 +1,4 @@
|
||||
rule 'FORWARD --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT'
|
||||
rule 'OUTPUT --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT'
|
||||
|
||||
rule('PREROUTING --logical-in br-client -i bat0 -d Multicast -j MULTICAST_IN', 'nat')
|
||||
|
@ -24,12 +24,15 @@ exec_file() {
|
||||
local file="$1"
|
||||
|
||||
/usr/bin/lua -e "
|
||||
function rule(command)
|
||||
function rule(command, table)
|
||||
table = table or 'filter'
|
||||
os.execute($EBTABLES_RULE)
|
||||
end
|
||||
function chain(name, policy)
|
||||
function chain(name, policy, table)
|
||||
table = table or 'filter'
|
||||
os.execute($EBTABLES_CHAIN)
|
||||
end
|
||||
|
||||
" "$file"
|
||||
}
|
||||
|
||||
@ -48,8 +51,8 @@ exec_all() {
|
||||
|
||||
start() {
|
||||
(
|
||||
export EBTABLES_RULE='"ebtables -A " .. command'
|
||||
export EBTABLES_CHAIN='"ebtables -N " .. name .. " -P " .. policy'
|
||||
export EBTABLES_RULE='"ebtables -t " .. table .. " -A " .. command'
|
||||
export EBTABLES_CHAIN='"ebtables -t " .. table .. " -N " .. name .. " -P " .. policy'
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
exec_all ''
|
||||
@ -61,8 +64,8 @@ start() {
|
||||
|
||||
stop() {
|
||||
(
|
||||
export EBTABLES_RULE='"ebtables -D " .. command'
|
||||
export EBTABLES_CHAIN='"ebtables -X " .. name'
|
||||
export EBTABLES_RULE='"ebtables -t " .. table .. " -D " .. command'
|
||||
export EBTABLES_CHAIN='"ebtables -t " .. table .. " -X " .. name'
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
exec_all '-r'
|
||||
|
@ -50,7 +50,7 @@ if type(ifname) == 'string' then
|
||||
end
|
||||
end
|
||||
|
||||
uci:set('network', 'client', 'igmp_snooping', 0)
|
||||
uci:delete('network', 'client', 'igmp_snooping')
|
||||
uci:set('network', 'client', 'macaddr', sysconfig.primary_mac)
|
||||
uci:set('network', 'client', 'peerdns', 1)
|
||||
uci:set('network', 'client', 'sourcefilter', 0)
|
||||
@ -61,6 +61,7 @@ uci:section('network', 'interface', 'bat0',
|
||||
ifname = 'bat0',
|
||||
proto = 'none',
|
||||
macaddr = sysconfig.primary_mac,
|
||||
multicast_router = 2,
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -0,0 +1,549 @@
|
||||
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Date: Sat, 5 Sep 2015 02:22:27 +0200
|
||||
Subject: netifd: bridge related fixes + config options
|
||||
|
||||
This commit backports upstream patches in netifd / OpenWRT trunk,
|
||||
regarding bridges:
|
||||
|
||||
* bridge: Fix multicast_to_unicast feature by hairpin+isolate
|
||||
* bridge: Allow setting multicast_to_unicast option
|
||||
* bridge: Allow setting multicast_router option
|
||||
|
||||
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
|
||||
diff --git a/package/network/config/netifd/patches/0001-bridge-Fix-multicast_to_unicast-feature-by-hairpin-i.patch b/package/network/config/netifd/patches/0001-bridge-Fix-multicast_to_unicast-feature-by-hairpin-i.patch
|
||||
new file mode 100644
|
||||
index 0000000..3e4cbc5
|
||||
--- /dev/null
|
||||
+++ b/package/network/config/netifd/patches/0001-bridge-Fix-multicast_to_unicast-feature-by-hairpin-i.patch
|
||||
@@ -0,0 +1,201 @@
|
||||
+From 484614cf607e2a1220e39111468c525d3ae96497 Mon Sep 17 00:00:00 2001
|
||||
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue>
|
||||
+Date: Sun, 23 Aug 2015 17:19:26 +0200
|
||||
+Subject: [PATCH 1/3] bridge: Fix multicast_to_unicast feature by
|
||||
+ hairpin+isolate
|
||||
+MIME-Version: 1.0
|
||||
+Content-Type: text/plain; charset=UTF-8
|
||||
+Content-Transfer-Encoding: 8bit
|
||||
+
|
||||
+All IGMP and MLD versions suffer from a specific limitation (from a
|
||||
+snooping switch perspective): Report suppression.
|
||||
+
|
||||
+Once a listener hears an IGMPv2/3 or MLDv1 report for the same group
|
||||
+itself participates in then it might (if this listener is an IGMPv3 or
|
||||
+MLDv2 listener) or will (if this is an IGMPv1/2 or MLDv1 listener)
|
||||
+refrain from sending its own report.
|
||||
+
|
||||
+Therefore we might currently miss such surpressing listeners as they
|
||||
+won't receive the multicast packet with the mangled, unicasted
|
||||
+destination.
|
||||
+
|
||||
+Fixing this by first isolating the STAs and giving the bridge more
|
||||
+control over traffic forwarding. E.g. refraining to forward listener
|
||||
+reports to other STAs.
|
||||
+
|
||||
+For broadcast and unicast traffic to an STA on the same AP, the hairpin
|
||||
+feature of the bridge will reflect such traffic back to the AP
|
||||
+interface. However, if the AP interface is actually configured to
|
||||
+isolate STAs, then hairpin is kept disabled.
|
||||
+
|
||||
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
+---
|
||||
+ device.h | 1 +
|
||||
+ scripts/netifd-wireless.sh | 15 +++++++++++++++
|
||||
+ system-linux.c | 26 ++++++++++++++++++++------
|
||||
+ wireless.c | 12 +++++++++++-
|
||||
+ wireless.h | 1 +
|
||||
+ 5 files changed, 48 insertions(+), 7 deletions(-)
|
||||
+
|
||||
+diff --git a/device.h b/device.h
|
||||
+index 3001f10..47ef77b 100644
|
||||
+--- a/device.h
|
||||
++++ b/device.h
|
||||
+@@ -167,6 +167,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 6dc9acd..ff25259 100644
|
||||
+--- a/system-linux.c
|
||||
++++ b/system-linux.c
|
||||
+@@ -310,6 +310,16 @@ static void system_set_neigh6reachabletime(struct device *dev, const char *val)
|
||||
+ system_set_dev_sysctl("/proc/sys/net/ipv6/neigh/%s/base_reachable_time_ms", 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;
|
||||
+@@ -545,12 +555,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)
|
||||
+@@ -563,7 +577,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;
|
||||
+ }
|
||||
+diff --git a/wireless.c b/wireless.c
|
||||
+index fbd6191..337f563 100644
|
||||
+--- a/wireless.c
|
||||
++++ b/wireless.c
|
||||
+@@ -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);
|
||||
+ }
|
||||
+
|
||||
+diff --git a/wireless.h b/wireless.h
|
||||
+index c5dbb88..476c63e 100644
|
||||
+--- a/wireless.h
|
||||
++++ b/wireless.h
|
||||
+@@ -77,6 +77,7 @@ struct wireless_interface {
|
||||
+
|
||||
+ const char *ifname;
|
||||
+ struct blob_attr *network;
|
||||
++ bool isolate;
|
||||
+ };
|
||||
+
|
||||
+ struct wireless_process {
|
||||
+--
|
||||
+1.7.10.4
|
||||
+
|
||||
diff --git a/package/network/config/netifd/patches/0002-bridge-Allow-setting-multicast_to_unicast-option.patch b/package/network/config/netifd/patches/0002-bridge-Allow-setting-multicast_to_unicast-option.patch
|
||||
new file mode 100644
|
||||
index 0000000..d199a97
|
||||
--- /dev/null
|
||||
+++ b/package/network/config/netifd/patches/0002-bridge-Allow-setting-multicast_to_unicast-option.patch
|
||||
@@ -0,0 +1,159 @@
|
||||
+From 2adcda7967a652547202f18fadc2efca0f290625 Mon Sep 17 00:00:00 2001
|
||||
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue>
|
||||
+Date: Sun, 23 Aug 2015 17:19:27 +0200
|
||||
+Subject: [PATCH 2/3] bridge: Allow setting multicast_to_unicast option
|
||||
+MIME-Version: 1.0
|
||||
+Content-Type: text/plain; charset=UTF-8
|
||||
+Content-Transfer-Encoding: 8bit
|
||||
+
|
||||
+With this patch the multicast_to_unicast feature can be disabled for all
|
||||
+wireless interfaces via an according option on the uci bridge interface.
|
||||
+
|
||||
+This patch also exports the setting information to wireless handler
|
||||
+scripts. The hostapd script will need that information to determine
|
||||
+whether to enable or disable ap-isolation, for instance.
|
||||
+
|
||||
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
+---
|
||||
+ device.c | 9 +++++++++
|
||||
+ device.h | 3 +++
|
||||
+ scripts/netifd-wireless.sh | 1 +
|
||||
+ system-linux.c | 13 +++++++++----
|
||||
+ wireless.c | 4 ++++
|
||||
+ 5 files changed, 26 insertions(+), 4 deletions(-)
|
||||
+
|
||||
+diff --git a/device.c b/device.c
|
||||
+index dd2823d..776829d 100644
|
||||
+--- a/device.c
|
||||
++++ b/device.c
|
||||
+@@ -46,6 +46,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
|
||||
+ [DEV_ATTR_NEIGHREACHABLETIME] = { .name = "neighreachabletime", .type = BLOBMSG_TYPE_INT32 },
|
||||
+ [DEV_ATTR_RPS] = { .name = "rps", .type = BLOBMSG_TYPE_BOOL },
|
||||
+ [DEV_ATTR_XPS] = { .name = "xps", .type = BLOBMSG_TYPE_BOOL },
|
||||
++ [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
|
||||
+ };
|
||||
+
|
||||
+ const struct uci_blob_param_list device_attr_list = {
|
||||
+@@ -169,6 +170,7 @@ device_merge_settings(struct device *dev, struct device_settings *n)
|
||||
+ s->neigh4reachabletime : os->neigh4reachabletime;
|
||||
+ n->neigh6reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ?
|
||||
+ s->neigh6reachabletime : os->neigh6reachabletime;
|
||||
++ n->multicast_to_unicast = s->multicast_to_unicast;
|
||||
+ n->flags = s->flags | os->flags;
|
||||
+ }
|
||||
+
|
||||
+@@ -259,6 +261,11 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
|
||||
+ else
|
||||
+ s->xps = default_ps;
|
||||
+
|
||||
++ if ((cur = tb[DEV_ATTR_MULTICAST_TO_UNICAST])) {
|
||||
++ s->multicast_to_unicast = blobmsg_get_bool(cur);
|
||||
++ s->flags |= DEV_OPT_MULTICAST_TO_UNICAST;
|
||||
++ }
|
||||
++
|
||||
+ device_set_disabled(dev, disabled);
|
||||
+ }
|
||||
+
|
||||
+@@ -863,6 +870,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
|
||||
+ blobmsg_add_u32(b, "neigh4reachabletime", st.neigh4reachabletime);
|
||||
+ blobmsg_add_u32(b, "neigh6reachabletime", st.neigh6reachabletime);
|
||||
+ }
|
||||
++ if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST)
|
||||
++ blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast);
|
||||
+ }
|
||||
+
|
||||
+ s = blobmsg_open_table(b, "statistics");
|
||||
+diff --git a/device.h b/device.h
|
||||
+index 47ef77b..55ef1cf 100644
|
||||
+--- a/device.h
|
||||
++++ b/device.h
|
||||
+@@ -40,6 +40,7 @@ enum {
|
||||
+ DEV_ATTR_NEIGHREACHABLETIME,
|
||||
+ DEV_ATTR_RPS,
|
||||
+ DEV_ATTR_XPS,
|
||||
++ DEV_ATTR_MULTICAST_TO_UNICAST,
|
||||
+ __DEV_ATTR_MAX,
|
||||
+ };
|
||||
+
|
||||
+@@ -80,6 +81,7 @@ enum {
|
||||
+ DEV_OPT_NEIGHREACHABLETIME = (1 << 9),
|
||||
+ DEV_OPT_RPS = (1 << 10),
|
||||
+ DEV_OPT_XPS = (1 << 11),
|
||||
++ DEV_OPT_MULTICAST_TO_UNICAST = (1 << 12),
|
||||
+ };
|
||||
+
|
||||
+ /* events broadcasted to all users of a device */
|
||||
+@@ -135,6 +137,7 @@ struct device_settings {
|
||||
+ unsigned int neigh6reachabletime;
|
||||
+ bool rps;
|
||||
+ bool xps;
|
||||
++ bool multicast_to_unicast;
|
||||
+ };
|
||||
+
|
||||
+ /*
|
||||
+diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh
|
||||
+index f981f1b..83a8223 100644
|
||||
+--- a/scripts/netifd-wireless.sh
|
||||
++++ b/scripts/netifd-wireless.sh
|
||||
+@@ -274,6 +274,7 @@ for_each_interface() {
|
||||
+ json_select "$_w_iface"
|
||||
+ if [ -n "$_w_types" ]; then
|
||||
+ json_get_var network_bridge bridge
|
||||
++ json_get_var multicast_to_unicast multicast_to_unicast
|
||||
+ json_select config
|
||||
+ _wireless_set_brsnoop_isolation "$multicast_to_unicast"
|
||||
+ json_get_var _w_type mode
|
||||
+diff --git a/system-linux.c b/system-linux.c
|
||||
+index ff25259..549d9c0 100644
|
||||
+--- a/system-linux.c
|
||||
++++ b/system-linux.c
|
||||
+@@ -556,14 +556,19 @@ static char *system_get_bridge(const char *name, char *buf, int buflen)
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+-system_bridge_set_wireless(struct device *dev)
|
||||
++system_bridge_set_wireless(struct device *bridge, struct device *dev)
|
||||
+ {
|
||||
++ bool mcast_to_ucast = true;
|
||||
+ bool hairpin = true;
|
||||
+
|
||||
+- if (dev->wireless_isolate)
|
||||
++ if (bridge->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST &&
|
||||
++ !bridge->settings.multicast_to_unicast)
|
||||
++ mcast_to_ucast = false;
|
||||
++
|
||||
++ if (!mcast_to_ucast || dev->wireless_isolate)
|
||||
+ hairpin = false;
|
||||
+
|
||||
+- system_bridge_set_multicast_to_unicast(dev, "1");
|
||||
++ system_bridge_set_multicast_to_unicast(dev, mcast_to_ucast ? "1" : "0");
|
||||
+ system_bridge_set_hairpin_mode(dev, hairpin ? "1" : "0");
|
||||
+ }
|
||||
+
|
||||
+@@ -577,7 +582,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(dev);
|
||||
++ system_bridge_set_wireless(bridge, dev);
|
||||
+
|
||||
+ return ret;
|
||||
+ }
|
||||
+diff --git a/wireless.c b/wireless.c
|
||||
+index 337f563..d0d2942 100644
|
||||
+--- a/wireless.c
|
||||
++++ b/wireless.c
|
||||
+@@ -92,6 +92,10 @@ vif_config_add_bridge(struct blob_buf *buf, struct blob_attr *networks, bool pre
|
||||
+ dev->hotplug_ops->prepare(dev);
|
||||
+
|
||||
+ blobmsg_add_string(buf, "bridge", dev->ifname);
|
||||
++
|
||||
++ if (dev->settings.flags & DEV_OPT_MULTICAST_TO_UNICAST)
|
||||
++ blobmsg_add_u8(buf, "multicast_to_unicast",
|
||||
++ dev->settings.multicast_to_unicast);
|
||||
+ }
|
||||
+
|
||||
+ static void
|
||||
+--
|
||||
+1.7.10.4
|
||||
+
|
||||
diff --git a/package/network/config/netifd/patches/0003-bridge-Allow-setting-multicast_router-option.patch b/package/network/config/netifd/patches/0003-bridge-Allow-setting-multicast_router-option.patch
|
||||
new file mode 100644
|
||||
index 0000000..e4b3b9c
|
||||
--- /dev/null
|
||||
+++ b/package/network/config/netifd/patches/0003-bridge-Allow-setting-multicast_router-option.patch
|
||||
@@ -0,0 +1,158 @@
|
||||
+From 4c467dffae6b9f540cc2242a5e872e49807f310d Mon Sep 17 00:00:00 2001
|
||||
+From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue>
|
||||
+Date: Sun, 23 Aug 2015 17:19:28 +0200
|
||||
+Subject: [PATCH 3/3] bridge: Allow setting multicast_router option
|
||||
+MIME-Version: 1.0
|
||||
+Content-Type: text/plain; charset=UTF-8
|
||||
+Content-Transfer-Encoding: 8bit
|
||||
+
|
||||
+The multicast_router option of a bridge allows to control the forwarding
|
||||
+behaviour of multicast packets independant of the listener state:
|
||||
+
|
||||
+* 0: Only forward if specific listener is present
|
||||
+* 1 (default): Forward if specific listener or a multicast router
|
||||
+ was detected (currently only learned via query messages, no MRD
|
||||
+ support yet)
|
||||
+* 2: Always forward any multicast traffic on this port
|
||||
+
|
||||
+Since MRD is not mandated you might end up with silent multicast routers
|
||||
+(e.g. if your link has more than one multicast router; only one can
|
||||
+become the selected, "noisy" querier). Here you might need a manual
|
||||
+configuration option like the "multicast_router" option.
|
||||
+
|
||||
+Other scenarios where this can be useful are for instance:
|
||||
+* Segmentation of IGMP/MLD domains together with ebtables
|
||||
+* Dedicated bridge port for monitoring/debugging purposes
|
||||
+
|
||||
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
+---
|
||||
+ device.c | 12 ++++++++++++
|
||||
+ device.h | 3 +++
|
||||
+ system-linux.c | 18 ++++++++++++++++++
|
||||
+ 3 files changed, 33 insertions(+)
|
||||
+
|
||||
+diff --git a/device.c b/device.c
|
||||
+index 776829d..75edc07 100644
|
||||
+--- a/device.c
|
||||
++++ b/device.c
|
||||
+@@ -47,6 +47,7 @@ static const struct blobmsg_policy dev_attrs[__DEV_ATTR_MAX] = {
|
||||
+ [DEV_ATTR_RPS] = { .name = "rps", .type = BLOBMSG_TYPE_BOOL },
|
||||
+ [DEV_ATTR_XPS] = { .name = "xps", .type = BLOBMSG_TYPE_BOOL },
|
||||
+ [DEV_ATTR_MULTICAST_TO_UNICAST] = { .name = "multicast_to_unicast", .type = BLOBMSG_TYPE_BOOL },
|
||||
++ [DEV_ATTR_MULTICAST_ROUTER] = { .name = "multicast_router", .type = BLOBMSG_TYPE_INT32 },
|
||||
+ };
|
||||
+
|
||||
+ const struct uci_blob_param_list device_attr_list = {
|
||||
+@@ -171,6 +172,7 @@ device_merge_settings(struct device *dev, struct device_settings *n)
|
||||
+ n->neigh6reachabletime = s->flags & DEV_OPT_NEIGHREACHABLETIME ?
|
||||
+ s->neigh6reachabletime : os->neigh6reachabletime;
|
||||
+ n->multicast_to_unicast = s->multicast_to_unicast;
|
||||
++ n->multicast_router = s->multicast_router;
|
||||
+ n->flags = s->flags | os->flags;
|
||||
+ }
|
||||
+
|
||||
+@@ -266,6 +268,14 @@ device_init_settings(struct device *dev, struct blob_attr **tb)
|
||||
+ s->flags |= DEV_OPT_MULTICAST_TO_UNICAST;
|
||||
+ }
|
||||
+
|
||||
++ if ((cur = tb[DEV_ATTR_MULTICAST_ROUTER])) {
|
||||
++ s->multicast_router = blobmsg_get_u32(cur);
|
||||
++ if (s->multicast_router <= 2)
|
||||
++ s->flags |= DEV_OPT_MULTICAST_ROUTER;
|
||||
++ else
|
||||
++ DPRINTF("Invalid value: %d - (Use 0: never, 1: learn, 2: always)\n", blobmsg_get_u32(cur));
|
||||
++ }
|
||||
++
|
||||
+ device_set_disabled(dev, disabled);
|
||||
+ }
|
||||
+
|
||||
+@@ -872,6 +882,8 @@ device_dump_status(struct blob_buf *b, struct device *dev)
|
||||
+ }
|
||||
+ if (st.flags & DEV_OPT_MULTICAST_TO_UNICAST)
|
||||
+ blobmsg_add_u8(b, "multicast_to_unicast", st.multicast_to_unicast);
|
||||
++ if (st.flags & DEV_OPT_MULTICAST_ROUTER)
|
||||
++ blobmsg_add_u32(b, "multicast_router", st.multicast_router);
|
||||
+ }
|
||||
+
|
||||
+ s = blobmsg_open_table(b, "statistics");
|
||||
+diff --git a/device.h b/device.h
|
||||
+index 55ef1cf..a487466 100644
|
||||
+--- a/device.h
|
||||
++++ b/device.h
|
||||
+@@ -41,6 +41,7 @@ enum {
|
||||
+ DEV_ATTR_RPS,
|
||||
+ DEV_ATTR_XPS,
|
||||
+ DEV_ATTR_MULTICAST_TO_UNICAST,
|
||||
++ DEV_ATTR_MULTICAST_ROUTER,
|
||||
+ __DEV_ATTR_MAX,
|
||||
+ };
|
||||
+
|
||||
+@@ -82,6 +83,7 @@ enum {
|
||||
+ DEV_OPT_RPS = (1 << 10),
|
||||
+ DEV_OPT_XPS = (1 << 11),
|
||||
+ DEV_OPT_MULTICAST_TO_UNICAST = (1 << 12),
|
||||
++ DEV_OPT_MULTICAST_ROUTER = (1 << 13),
|
||||
+ };
|
||||
+
|
||||
+ /* events broadcasted to all users of a device */
|
||||
+@@ -138,6 +140,7 @@ struct device_settings {
|
||||
+ bool rps;
|
||||
+ bool xps;
|
||||
+ bool multicast_to_unicast;
|
||||
++ unsigned int multicast_router;
|
||||
+ };
|
||||
+
|
||||
+ /*
|
||||
+diff --git a/system-linux.c b/system-linux.c
|
||||
+index 549d9c0..9061f25 100644
|
||||
+--- a/system-linux.c
|
||||
++++ b/system-linux.c
|
||||
+@@ -320,6 +320,13 @@ 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 void system_bridge_set_multicast_router(struct device *dev, const char *val, bool bridge)
|
||||
++{
|
||||
++ system_set_dev_sysctl(bridge ? "/sys/class/net/%s/bridge/multicast_router" :
|
||||
++ "/sys/class/net/%s/brport/multicast_router",
|
||||
++ dev->ifname, val);
|
||||
++}
|
||||
++
|
||||
+ static int system_get_sysctl(const char *path, char *buf, const size_t buf_sz)
|
||||
+ {
|
||||
+ int fd = -1, ret = -1;
|
||||
+@@ -574,6 +581,7 @@ system_bridge_set_wireless(struct device *bridge, struct device *dev)
|
||||
+
|
||||
+ int system_bridge_addif(struct device *bridge, struct device *dev)
|
||||
+ {
|
||||
++ char buf[64];
|
||||
+ char *oldbr;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+@@ -584,6 +592,11 @@ int system_bridge_addif(struct device *bridge, struct device *dev)
|
||||
+ if (dev->wireless)
|
||||
+ system_bridge_set_wireless(bridge, dev);
|
||||
+
|
||||
++ if (dev->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
|
||||
++ snprintf(buf, sizeof(buf), "%i", dev->settings.multicast_router);
|
||||
++ system_bridge_set_multicast_router(dev, buf, false);
|
||||
++ }
|
||||
++
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+@@ -834,6 +847,11 @@ int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
|
||||
+ system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/hash_max",
|
||||
+ bridge->ifname, buf);
|
||||
+
|
||||
++ if (bridge->settings.flags & DEV_OPT_MULTICAST_ROUTER) {
|
||||
++ snprintf(buf, sizeof(buf), "%i", bridge->settings.multicast_router);
|
||||
++ system_bridge_set_multicast_router(bridge, buf, true);
|
||||
++ }
|
||||
++
|
||||
+ args[0] = BRCTL_SET_BRIDGE_PRIORITY;
|
||||
+ args[1] = cfg->priority;
|
||||
+ system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
|
||||
+--
|
||||
+1.7.10.4
|
||||
+
|
@ -0,0 +1,181 @@
|
||||
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Date: Sat, 5 Sep 2015 02:57:34 +0200
|
||||
Subject: Revert "kernel: disable multicast-to-unicast translation for ipv6 neighbor solicitation (#17625)"
|
||||
|
||||
This reverts commit a080e8e1943156168913d0353a2e99d1151102aa.
|
||||
|
||||
It did not fix the problem but just hid some symptom. The real issue was
|
||||
that IGMP/MLD report suppression was not considered for the
|
||||
multicast-to-unicast feature. A recent netifd which isolates IGMP/MLD
|
||||
reports between STAs by utilizing AP-isolation and bridge-hairpinning
|
||||
should have fixed this.
|
||||
|
||||
It is perfectly fine to apply multicast-to-unicast to IPv6 Neighbor
|
||||
Solicitations, too (once that feature is configured correctly).
|
||||
|
||||
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
|
||||
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46720 3c298f89-4303-0410-b956-a3cf2f4a3e73
|
||||
|
||||
diff --git a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
index 00ad14f..8c436e0 100644
|
||||
--- a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
+++ b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
@@ -87,19 +87,16 @@
|
||||
{
|
||||
struct br_ip br_group;
|
||||
|
||||
-@@ -736,7 +758,10 @@ static int br_ip6_multicast_add_group(st
|
||||
+@@ -736,7 +758,7 @@ static int br_ip6_multicast_add_group(st
|
||||
br_group.proto = htons(ETH_P_IPV6);
|
||||
br_group.vid = vid;
|
||||
|
||||
- return br_multicast_add_group(br, port, &br_group);
|
||||
-+ if (ipv6_addr_is_solict_mult(group))
|
||||
-+ src = NULL;
|
||||
-+
|
||||
+ return br_multicast_add_group(br, port, &br_group, src);
|
||||
}
|
||||
#endif
|
||||
|
||||
-@@ -965,6 +990,7 @@ static int br_ip4_multicast_igmp3_report
|
||||
+@@ -965,6 +987,7 @@ static int br_ip4_multicast_igmp3_report
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
@@ -107,7 +104,7 @@
|
||||
struct igmpv3_report *ih;
|
||||
struct igmpv3_grec *grec;
|
||||
int i;
|
||||
-@@ -1008,7 +1034,7 @@ static int br_ip4_multicast_igmp3_report
|
||||
+@@ -1008,7 +1031,7 @@ static int br_ip4_multicast_igmp3_report
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -116,7 +113,7 @@
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
-@@ -1022,6 +1048,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
+@@ -1022,6 +1045,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
@@ -124,7 +121,7 @@
|
||||
struct icmp6hdr *icmp6h;
|
||||
struct mld2_grec *grec;
|
||||
int i;
|
||||
-@@ -1070,7 +1097,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
+@@ -1070,7 +1094,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
}
|
||||
|
||||
err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
|
||||
@@ -133,7 +130,7 @@
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
-@@ -1406,7 +1433,8 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1406,7 +1430,8 @@ br_multicast_leave_group(struct net_brid
|
||||
struct net_bridge_port *port,
|
||||
struct br_ip *group,
|
||||
struct bridge_mcast_other_query *other_query,
|
||||
@@ -143,7 +140,7 @@
|
||||
{
|
||||
struct net_bridge_mdb_htable *mdb;
|
||||
struct net_bridge_mdb_entry *mp;
|
||||
-@@ -1456,7 +1484,7 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1456,7 +1481,7 @@ br_multicast_leave_group(struct net_brid
|
||||
for (pp = &mp->ports;
|
||||
(p = mlock_dereference(*pp, br)) != NULL;
|
||||
pp = &p->next) {
|
||||
@@ -152,7 +149,7 @@
|
||||
continue;
|
||||
|
||||
rcu_assign_pointer(*pp, p->next);
|
||||
-@@ -1490,7 +1518,7 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1490,7 +1515,7 @@ br_multicast_leave_group(struct net_brid
|
||||
for (p = mlock_dereference(mp->ports, br);
|
||||
p != NULL;
|
||||
p = mlock_dereference(p->next, br)) {
|
||||
@@ -161,7 +158,7 @@
|
||||
continue;
|
||||
|
||||
if (!hlist_unhashed(&p->mglist) &&
|
||||
-@@ -1508,8 +1536,8 @@ out:
|
||||
+@@ -1508,8 +1533,8 @@ out:
|
||||
|
||||
static void br_ip4_multicast_leave_group(struct net_bridge *br,
|
||||
struct net_bridge_port *port,
|
||||
@@ -172,7 +169,7 @@
|
||||
{
|
||||
struct br_ip br_group;
|
||||
struct bridge_mcast_own_query *own_query;
|
||||
-@@ -1524,14 +1552,14 @@ static void br_ip4_multicast_leave_group
|
||||
+@@ -1524,14 +1549,14 @@ static void br_ip4_multicast_leave_group
|
||||
br_group.vid = vid;
|
||||
|
||||
br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
|
||||
@@ -189,7 +186,7 @@
|
||||
{
|
||||
struct br_ip br_group;
|
||||
struct bridge_mcast_own_query *own_query;
|
||||
-@@ -1546,7 +1574,7 @@ static void br_ip6_multicast_leave_group
|
||||
+@@ -1546,7 +1571,7 @@ static void br_ip6_multicast_leave_group
|
||||
br_group.vid = vid;
|
||||
|
||||
br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
|
||||
@@ -198,7 +195,7 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
-@@ -1555,6 +1583,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1555,6 +1580,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
@@ -206,7 +203,7 @@
|
||||
struct sk_buff *skb2 = skb;
|
||||
const struct iphdr *iph;
|
||||
struct igmphdr *ih;
|
||||
-@@ -1628,7 +1657,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1628,7 +1654,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
case IGMP_HOST_MEMBERSHIP_REPORT:
|
||||
case IGMPV2_HOST_MEMBERSHIP_REPORT:
|
||||
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
@@ -215,7 +212,7 @@
|
||||
break;
|
||||
case IGMPV3_HOST_MEMBERSHIP_REPORT:
|
||||
err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
|
||||
-@@ -1637,7 +1666,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1637,7 +1663,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
err = br_ip4_multicast_query(br, port, skb2, vid);
|
||||
break;
|
||||
case IGMP_HOST_LEAVE_MESSAGE:
|
||||
@@ -224,7 +221,7 @@
|
||||
break;
|
||||
}
|
||||
|
||||
-@@ -1655,6 +1684,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1655,6 +1681,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
@@ -232,7 +229,7 @@
|
||||
struct sk_buff *skb2;
|
||||
const struct ipv6hdr *ip6h;
|
||||
u8 icmp6_type;
|
||||
-@@ -1764,7 +1794,8 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1764,7 +1791,8 @@ static int br_multicast_ipv6_rcv(struct
|
||||
}
|
||||
mld = (struct mld_msg *)skb_transport_header(skb2);
|
||||
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
@@ -242,7 +239,7 @@
|
||||
break;
|
||||
}
|
||||
case ICMPV6_MLD2_REPORT:
|
||||
-@@ -1781,7 +1812,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1781,7 +1809,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
goto out;
|
||||
}
|
||||
mld = (struct mld_msg *)skb_transport_header(skb2);
|
@ -0,0 +1,173 @@
|
||||
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Date: Sat, 5 Sep 2015 03:11:34 +0200
|
||||
Subject: kernel: bridge, multicast-to-unicast: assign src after pskb_may_pull()
|
||||
|
||||
A call to pskb_may_pull() might reallocate skb->data. Therefore we
|
||||
should only assign the src-pointer after any potential reallocations.
|
||||
|
||||
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
|
||||
|
||||
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46721 3c298f89-4303-0410-b956-a3cf2f4a3e73
|
||||
|
||||
diff --git a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
index 8c436e0..6707b03 100644
|
||||
--- a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
+++ b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
@@ -100,37 +100,40 @@
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
-+ const unsigned char *src = eth_hdr(skb)->h_source;
|
||||
++ const unsigned char *src;
|
||||
struct igmpv3_report *ih;
|
||||
struct igmpv3_grec *grec;
|
||||
int i;
|
||||
-@@ -1008,7 +1031,7 @@ static int br_ip4_multicast_igmp3_report
|
||||
+@@ -1008,7 +1031,8 @@ static int br_ip4_multicast_igmp3_report
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = br_ip4_multicast_add_group(br, port, group, vid);
|
||||
++ src = eth_hdr(skb)->h_source;
|
||||
+ err = br_ip4_multicast_add_group(br, port, group, vid, src);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
-@@ -1022,6 +1045,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
+@@ -1022,6 +1046,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
-+ const unsigned char *src = eth_hdr(skb)->h_source;
|
||||
++ const unsigned char *src;
|
||||
struct icmp6hdr *icmp6h;
|
||||
struct mld2_grec *grec;
|
||||
int i;
|
||||
-@@ -1070,7 +1094,7 @@ static int br_ip6_multicast_mld2_report(
|
||||
+@@ -1069,8 +1094,9 @@ static int br_ip6_multicast_mld2_report(
|
||||
+ continue;
|
||||
}
|
||||
|
||||
++ src = eth_hdr(skb)->h_source;
|
||||
err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
|
||||
- vid);
|
||||
+ vid, src);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
-@@ -1406,7 +1430,8 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1406,7 +1432,8 @@ br_multicast_leave_group(struct net_brid
|
||||
struct net_bridge_port *port,
|
||||
struct br_ip *group,
|
||||
struct bridge_mcast_other_query *other_query,
|
||||
@@ -140,7 +143,7 @@
|
||||
{
|
||||
struct net_bridge_mdb_htable *mdb;
|
||||
struct net_bridge_mdb_entry *mp;
|
||||
-@@ -1456,7 +1481,7 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1456,7 +1483,7 @@ br_multicast_leave_group(struct net_brid
|
||||
for (pp = &mp->ports;
|
||||
(p = mlock_dereference(*pp, br)) != NULL;
|
||||
pp = &p->next) {
|
||||
@@ -149,7 +152,7 @@
|
||||
continue;
|
||||
|
||||
rcu_assign_pointer(*pp, p->next);
|
||||
-@@ -1490,7 +1515,7 @@ br_multicast_leave_group(struct net_brid
|
||||
+@@ -1490,7 +1517,7 @@ br_multicast_leave_group(struct net_brid
|
||||
for (p = mlock_dereference(mp->ports, br);
|
||||
p != NULL;
|
||||
p = mlock_dereference(p->next, br)) {
|
||||
@@ -158,7 +161,7 @@
|
||||
continue;
|
||||
|
||||
if (!hlist_unhashed(&p->mglist) &&
|
||||
-@@ -1508,8 +1533,8 @@ out:
|
||||
+@@ -1508,8 +1535,8 @@ out:
|
||||
|
||||
static void br_ip4_multicast_leave_group(struct net_bridge *br,
|
||||
struct net_bridge_port *port,
|
||||
@@ -169,7 +172,7 @@
|
||||
{
|
||||
struct br_ip br_group;
|
||||
struct bridge_mcast_own_query *own_query;
|
||||
-@@ -1524,14 +1549,14 @@ static void br_ip4_multicast_leave_group
|
||||
+@@ -1524,14 +1551,14 @@ static void br_ip4_multicast_leave_group
|
||||
br_group.vid = vid;
|
||||
|
||||
br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
|
||||
@@ -186,7 +189,7 @@
|
||||
{
|
||||
struct br_ip br_group;
|
||||
struct bridge_mcast_own_query *own_query;
|
||||
-@@ -1546,7 +1571,7 @@ static void br_ip6_multicast_leave_group
|
||||
+@@ -1546,7 +1573,7 @@ static void br_ip6_multicast_leave_group
|
||||
br_group.vid = vid;
|
||||
|
||||
br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
|
||||
@@ -195,41 +198,43 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
-@@ -1555,6 +1580,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1555,6 +1582,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
-+ const unsigned char *src = eth_hdr(skb)->h_source;
|
||||
++ const unsigned char *src;
|
||||
struct sk_buff *skb2 = skb;
|
||||
const struct iphdr *iph;
|
||||
struct igmphdr *ih;
|
||||
-@@ -1628,7 +1654,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1628,7 +1656,8 @@ static int br_multicast_ipv4_rcv(struct
|
||||
case IGMP_HOST_MEMBERSHIP_REPORT:
|
||||
case IGMPV2_HOST_MEMBERSHIP_REPORT:
|
||||
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
- err = br_ip4_multicast_add_group(br, port, ih->group, vid);
|
||||
++ src = eth_hdr(skb)->h_source;
|
||||
+ err = br_ip4_multicast_add_group(br, port, ih->group, vid, src);
|
||||
break;
|
||||
case IGMPV3_HOST_MEMBERSHIP_REPORT:
|
||||
err = br_ip4_multicast_igmp3_report(br, port, skb2, vid);
|
||||
-@@ -1637,7 +1663,7 @@ static int br_multicast_ipv4_rcv(struct
|
||||
+@@ -1637,7 +1666,8 @@ static int br_multicast_ipv4_rcv(struct
|
||||
err = br_ip4_multicast_query(br, port, skb2, vid);
|
||||
break;
|
||||
case IGMP_HOST_LEAVE_MESSAGE:
|
||||
- br_ip4_multicast_leave_group(br, port, ih->group, vid);
|
||||
++ src = eth_hdr(skb)->h_source;
|
||||
+ br_ip4_multicast_leave_group(br, port, ih->group, vid, src);
|
||||
break;
|
||||
}
|
||||
|
||||
-@@ -1655,6 +1681,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1655,6 +1685,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
struct sk_buff *skb,
|
||||
u16 vid)
|
||||
{
|
||||
-+ const unsigned char *src = eth_hdr(skb)->h_source;
|
||||
++ const unsigned char *src;
|
||||
struct sk_buff *skb2;
|
||||
const struct ipv6hdr *ip6h;
|
||||
u8 icmp6_type;
|
||||
-@@ -1764,7 +1791,8 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1764,7 +1795,8 @@ static int br_multicast_ipv6_rcv(struct
|
||||
}
|
||||
mld = (struct mld_msg *)skb_transport_header(skb2);
|
||||
BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
|
||||
@@ -239,11 +244,12 @@
|
||||
break;
|
||||
}
|
||||
case ICMPV6_MLD2_REPORT:
|
||||
-@@ -1781,7 +1809,7 @@ static int br_multicast_ipv6_rcv(struct
|
||||
+@@ -1781,7 +1813,8 @@ static int br_multicast_ipv6_rcv(struct
|
||||
goto out;
|
||||
}
|
||||
mld = (struct mld_msg *)skb_transport_header(skb2);
|
||||
- br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid);
|
||||
++ src = eth_hdr(skb)->h_source;
|
||||
+ br_ip6_multicast_leave_group(br, port, &mld->mld_mca, vid, src);
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
Date: Sat, 5 Sep 2015 03:18:28 +0200
|
||||
Subject: kernel: bridge, multicast-to-unicast: fix echoes on STA
|
||||
|
||||
Currently, multicast packets from an STA are sent to any according
|
||||
multicast listener directly through the bridge multicast-to-unicast
|
||||
feature. Unfortunately, so far this includes the originating STA, too,
|
||||
resulting in multicast packets being echo'ed back to the originating STA
|
||||
if it itself is a multicast listener for that group.
|
||||
|
||||
This behaviour breaks IPv6 duplicate address detection: An IPv6 Neighbor
|
||||
Solicitation for IPv6 Duplicate Address Detection is being echo'ed back,
|
||||
resulting in the host falsely detecting an address collision, which
|
||||
makes the node unable to claim an IPv6 address and use IPv6 in general.
|
||||
|
||||
Mac80211 unfortunately only prevents the echoes for us for multicast
|
||||
frames. For the multicast frames cast to a unicast destination we'll
|
||||
need to take care of excluding the originator ourselves.
|
||||
|
||||
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
||||
|
||||
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@46765 3c298f89-4303-0410-b956-a3cf2f4a3e73
|
||||
|
||||
diff --git a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
index 6707b03..399f5c6 100644
|
||||
--- a/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
+++ b/target/linux/generic/patches-3.18/645-bridge_multicast_to_unicast.patch
|
||||
@@ -297,7 +297,7 @@
|
||||
rcu_assign_pointer(*pp, p);
|
||||
--- a/net/bridge/br_forward.c
|
||||
+++ b/net/bridge/br_forward.c
|
||||
-@@ -168,6 +168,29 @@ out:
|
||||
+@@ -168,6 +168,34 @@ out:
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -308,10 +308,15 @@
|
||||
+ struct sk_buff *skb))
|
||||
+{
|
||||
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
|
||||
++ const unsigned char *src = eth_hdr(skb)->h_source;
|
||||
+
|
||||
+ if (!should_deliver(p, skb))
|
||||
+ return prev;
|
||||
+
|
||||
++ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */
|
||||
++ if (skb->dev == p->dev && ether_addr_equal(src, addr))
|
||||
++ return prev;
|
||||
++
|
||||
+ skb = skb_copy(skb, GFP_ATOMIC);
|
||||
+ if (!skb) {
|
||||
+ dev->stats.tx_dropped++;
|
||||
@@ -327,7 +332,7 @@
|
||||
/* called under bridge lock */
|
||||
static void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
||||
struct sk_buff *skb0,
|
||||
-@@ -232,6 +255,7 @@ static void br_multicast_flood(struct ne
|
||||
+@@ -232,6 +260,7 @@ static void br_multicast_flood(struct ne
|
||||
struct net_bridge_port *prev = NULL;
|
||||
struct net_bridge_port_group *p;
|
||||
struct hlist_node *rp;
|
||||
@@ -335,7 +340,7 @@
|
||||
|
||||
rp = rcu_dereference(hlist_first_rcu(&br->router_list));
|
||||
p = mdst ? rcu_dereference(mdst->ports) : NULL;
|
||||
-@@ -242,10 +266,19 @@ static void br_multicast_flood(struct ne
|
||||
+@@ -242,10 +271,19 @@ static void br_multicast_flood(struct ne
|
||||
rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) :
|
||||
NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user