diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /net/bridge | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'net/bridge')
28 files changed, 709 insertions, 1443 deletions
diff --git a/net/bridge/Makefile b/net/bridge/Makefile index e859098f5ee..d0359ea8ee7 100644 --- a/net/bridge/Makefile +++ b/net/bridge/Makefile | |||
@@ -12,6 +12,6 @@ bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o | |||
12 | 12 | ||
13 | bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o | 13 | bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o |
14 | 14 | ||
15 | bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o | 15 | bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o |
16 | 16 | ||
17 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/ | 17 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/ |
diff --git a/net/bridge/br.c b/net/bridge/br.c index ba780cc8e51..f20c4fd915a 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -62,7 +62,7 @@ static int __init br_init(void) | |||
62 | 62 | ||
63 | brioctl_set(br_ioctl_deviceless_stub); | 63 | brioctl_set(br_ioctl_deviceless_stub); |
64 | 64 | ||
65 | #if IS_ENABLED(CONFIG_ATM_LANE) | 65 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
66 | br_fdb_test_addr_hook = br_fdb_test_addr; | 66 | br_fdb_test_addr_hook = br_fdb_test_addr; |
67 | #endif | 67 | #endif |
68 | 68 | ||
@@ -93,7 +93,7 @@ static void __exit br_deinit(void) | |||
93 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 93 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
94 | 94 | ||
95 | br_netfilter_fini(); | 95 | br_netfilter_fini(); |
96 | #if IS_ENABLED(CONFIG_ATM_LANE) | 96 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
97 | br_fdb_test_addr_hook = NULL; | 97 | br_fdb_test_addr_hook = NULL; |
98 | #endif | 98 | #endif |
99 | 99 | ||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 7c78e264019..dac6a214746 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -31,25 +31,25 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
31 | struct net_bridge_mdb_entry *mdst; | 31 | struct net_bridge_mdb_entry *mdst; |
32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | 32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); |
33 | 33 | ||
34 | rcu_read_lock(); | ||
35 | #ifdef CONFIG_BRIDGE_NETFILTER | 34 | #ifdef CONFIG_BRIDGE_NETFILTER |
36 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | 35 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { |
37 | br_nf_pre_routing_finish_bridge_slow(skb); | 36 | br_nf_pre_routing_finish_bridge_slow(skb); |
38 | rcu_read_unlock(); | ||
39 | return NETDEV_TX_OK; | 37 | return NETDEV_TX_OK; |
40 | } | 38 | } |
41 | #endif | 39 | #endif |
42 | 40 | ||
43 | u64_stats_update_begin(&brstats->syncp); | ||
44 | brstats->tx_packets++; | ||
45 | brstats->tx_bytes += skb->len; | ||
46 | u64_stats_update_end(&brstats->syncp); | ||
47 | |||
48 | BR_INPUT_SKB_CB(skb)->brdev = dev; | 41 | BR_INPUT_SKB_CB(skb)->brdev = dev; |
49 | 42 | ||
50 | skb_reset_mac_header(skb); | 43 | skb_reset_mac_header(skb); |
51 | skb_pull(skb, ETH_HLEN); | 44 | skb_pull(skb, ETH_HLEN); |
52 | 45 | ||
46 | u64_stats_update_begin(&brstats->syncp); | ||
47 | brstats->tx_packets++; | ||
48 | /* Exclude ETH_HLEN from byte stats for consistency with Rx chain */ | ||
49 | brstats->tx_bytes += skb->len; | ||
50 | u64_stats_update_end(&brstats->syncp); | ||
51 | |||
52 | rcu_read_lock(); | ||
53 | if (is_broadcast_ether_addr(dest)) | 53 | if (is_broadcast_ether_addr(dest)) |
54 | br_flood_deliver(br, skb); | 54 | br_flood_deliver(br, skb); |
55 | else if (is_multicast_ether_addr(dest)) { | 55 | else if (is_multicast_ether_addr(dest)) { |
@@ -128,9 +128,9 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, | |||
128 | const struct br_cpu_netstats *bstats | 128 | const struct br_cpu_netstats *bstats |
129 | = per_cpu_ptr(br->stats, cpu); | 129 | = per_cpu_ptr(br->stats, cpu); |
130 | do { | 130 | do { |
131 | start = u64_stats_fetch_begin_bh(&bstats->syncp); | 131 | start = u64_stats_fetch_begin(&bstats->syncp); |
132 | memcpy(&tmp, bstats, sizeof(tmp)); | 132 | memcpy(&tmp, bstats, sizeof(tmp)); |
133 | } while (u64_stats_fetch_retry_bh(&bstats->syncp, start)); | 133 | } while (u64_stats_fetch_retry(&bstats->syncp, start)); |
134 | sum.tx_bytes += tmp.tx_bytes; | 134 | sum.tx_bytes += tmp.tx_bytes; |
135 | sum.tx_packets += tmp.tx_packets; | 135 | sum.tx_packets += tmp.tx_packets; |
136 | sum.rx_bytes += tmp.rx_bytes; | 136 | sum.rx_bytes += tmp.rx_bytes; |
@@ -168,15 +168,11 @@ static int br_set_mac_address(struct net_device *dev, void *p) | |||
168 | struct sockaddr *addr = p; | 168 | struct sockaddr *addr = p; |
169 | 169 | ||
170 | if (!is_valid_ether_addr(addr->sa_data)) | 170 | if (!is_valid_ether_addr(addr->sa_data)) |
171 | return -EADDRNOTAVAIL; | 171 | return -EINVAL; |
172 | 172 | ||
173 | spin_lock_bh(&br->lock); | 173 | spin_lock_bh(&br->lock); |
174 | if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) { | 174 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
175 | dev->addr_assign_type &= ~NET_ADDR_RANDOM; | 175 | br_stp_change_bridge_id(br, addr->sa_data); |
176 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | ||
177 | br_fdb_change_mac_address(br, addr->sa_data); | ||
178 | br_stp_change_bridge_id(br, addr->sa_data); | ||
179 | } | ||
180 | br->flags |= BR_SET_MAC_ADDR; | 176 | br->flags |= BR_SET_MAC_ADDR; |
181 | spin_unlock_bh(&br->lock); | 177 | spin_unlock_bh(&br->lock); |
182 | 178 | ||
@@ -191,8 +187,7 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
191 | strcpy(info->bus_info, "N/A"); | 187 | strcpy(info->bus_info, "N/A"); |
192 | } | 188 | } |
193 | 189 | ||
194 | static netdev_features_t br_fix_features(struct net_device *dev, | 190 | static u32 br_fix_features(struct net_device *dev, u32 features) |
195 | netdev_features_t features) | ||
196 | { | 191 | { |
197 | struct net_bridge *br = netdev_priv(dev); | 192 | struct net_bridge *br = netdev_priv(dev); |
198 | 193 | ||
@@ -207,23 +202,24 @@ static void br_poll_controller(struct net_device *br_dev) | |||
207 | static void br_netpoll_cleanup(struct net_device *dev) | 202 | static void br_netpoll_cleanup(struct net_device *dev) |
208 | { | 203 | { |
209 | struct net_bridge *br = netdev_priv(dev); | 204 | struct net_bridge *br = netdev_priv(dev); |
210 | struct net_bridge_port *p; | 205 | struct net_bridge_port *p, *n; |
211 | 206 | ||
212 | list_for_each_entry(p, &br->port_list, list) | 207 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
213 | br_netpoll_disable(p); | 208 | br_netpoll_disable(p); |
209 | } | ||
214 | } | 210 | } |
215 | 211 | ||
216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, | 212 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) |
217 | gfp_t gfp) | ||
218 | { | 213 | { |
219 | struct net_bridge *br = netdev_priv(dev); | 214 | struct net_bridge *br = netdev_priv(dev); |
220 | struct net_bridge_port *p; | 215 | struct net_bridge_port *p, *n; |
221 | int err = 0; | 216 | int err = 0; |
222 | 217 | ||
223 | list_for_each_entry(p, &br->port_list, list) { | 218 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
224 | if (!p->dev) | 219 | if (!p->dev) |
225 | continue; | 220 | continue; |
226 | err = br_netpoll_enable(p, gfp); | 221 | |
222 | err = br_netpoll_enable(p); | ||
227 | if (err) | 223 | if (err) |
228 | goto fail; | 224 | goto fail; |
229 | } | 225 | } |
@@ -236,17 +232,20 @@ fail: | |||
236 | goto out; | 232 | goto out; |
237 | } | 233 | } |
238 | 234 | ||
239 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | 235 | int br_netpoll_enable(struct net_bridge_port *p) |
240 | { | 236 | { |
241 | struct netpoll *np; | 237 | struct netpoll *np; |
242 | int err = 0; | 238 | int err = 0; |
243 | 239 | ||
244 | np = kzalloc(sizeof(*p->np), gfp); | 240 | np = kzalloc(sizeof(*p->np), GFP_KERNEL); |
245 | err = -ENOMEM; | 241 | err = -ENOMEM; |
246 | if (!np) | 242 | if (!np) |
247 | goto out; | 243 | goto out; |
248 | 244 | ||
249 | err = __netpoll_setup(np, p->dev, gfp); | 245 | np->dev = p->dev; |
246 | strlcpy(np->dev_name, p->dev->name, IFNAMSIZ); | ||
247 | |||
248 | err = __netpoll_setup(np); | ||
250 | if (err) { | 249 | if (err) { |
251 | kfree(np); | 250 | kfree(np); |
252 | goto out; | 251 | goto out; |
@@ -267,7 +266,11 @@ void br_netpoll_disable(struct net_bridge_port *p) | |||
267 | 266 | ||
268 | p->np = NULL; | 267 | p->np = NULL; |
269 | 268 | ||
270 | __netpoll_free_rcu(np); | 269 | /* Wait for transmitting packets to finish before freeing. */ |
270 | synchronize_rcu_bh(); | ||
271 | |||
272 | __netpoll_cleanup(np); | ||
273 | kfree(np); | ||
271 | } | 274 | } |
272 | 275 | ||
273 | #endif | 276 | #endif |
@@ -299,7 +302,7 @@ static const struct net_device_ops br_netdev_ops = { | |||
299 | .ndo_start_xmit = br_dev_xmit, | 302 | .ndo_start_xmit = br_dev_xmit, |
300 | .ndo_get_stats64 = br_get_stats64, | 303 | .ndo_get_stats64 = br_get_stats64, |
301 | .ndo_set_mac_address = br_set_mac_address, | 304 | .ndo_set_mac_address = br_set_mac_address, |
302 | .ndo_set_rx_mode = br_dev_set_multicast_list, | 305 | .ndo_set_multicast_list = br_dev_set_multicast_list, |
303 | .ndo_change_mtu = br_change_mtu, | 306 | .ndo_change_mtu = br_change_mtu, |
304 | .ndo_do_ioctl = br_dev_ioctl, | 307 | .ndo_do_ioctl = br_dev_ioctl, |
305 | #ifdef CONFIG_NET_POLL_CONTROLLER | 308 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -310,11 +313,6 @@ static const struct net_device_ops br_netdev_ops = { | |||
310 | .ndo_add_slave = br_add_slave, | 313 | .ndo_add_slave = br_add_slave, |
311 | .ndo_del_slave = br_del_slave, | 314 | .ndo_del_slave = br_del_slave, |
312 | .ndo_fix_features = br_fix_features, | 315 | .ndo_fix_features = br_fix_features, |
313 | .ndo_fdb_add = br_fdb_add, | ||
314 | .ndo_fdb_del = br_fdb_delete, | ||
315 | .ndo_fdb_dump = br_fdb_dump, | ||
316 | .ndo_bridge_getlink = br_getlink, | ||
317 | .ndo_bridge_setlink = br_setlink, | ||
318 | }; | 316 | }; |
319 | 317 | ||
320 | static void br_dev_free(struct net_device *dev) | 318 | static void br_dev_free(struct net_device *dev) |
@@ -333,7 +331,7 @@ void br_dev_setup(struct net_device *dev) | |||
333 | { | 331 | { |
334 | struct net_bridge *br = netdev_priv(dev); | 332 | struct net_bridge *br = netdev_priv(dev); |
335 | 333 | ||
336 | eth_hw_addr_random(dev); | 334 | random_ether_addr(dev->dev_addr); |
337 | ether_setup(dev); | 335 | ether_setup(dev); |
338 | 336 | ||
339 | dev->netdev_ops = &br_netdev_ops; | 337 | dev->netdev_ops = &br_netdev_ops; |
@@ -344,10 +342,10 @@ void br_dev_setup(struct net_device *dev) | |||
344 | dev->priv_flags = IFF_EBRIDGE; | 342 | dev->priv_flags = IFF_EBRIDGE; |
345 | 343 | ||
346 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | 344 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | |
347 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX | | 345 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | |
348 | NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX; | 346 | NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX; |
349 | dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | 347 | dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | |
350 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | | 348 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | |
351 | NETIF_F_HW_VLAN_TX; | 349 | NETIF_F_HW_VLAN_TX; |
352 | 350 | ||
353 | br->dev = dev; | 351 | br->dev = dev; |
@@ -358,11 +356,9 @@ void br_dev_setup(struct net_device *dev) | |||
358 | br->bridge_id.prio[0] = 0x80; | 356 | br->bridge_id.prio[0] = 0x80; |
359 | br->bridge_id.prio[1] = 0x00; | 357 | br->bridge_id.prio[1] = 0x00; |
360 | 358 | ||
361 | memcpy(br->group_addr, eth_reserved_addr_base, ETH_ALEN); | 359 | memcpy(br->group_addr, br_group_address, ETH_ALEN); |
362 | 360 | ||
363 | br->stp_enabled = BR_NO_STP; | 361 | br->stp_enabled = BR_NO_STP; |
364 | br->group_fwd_mask = BR_GROUPFWD_DEFAULT; | ||
365 | |||
366 | br->designated_root = br->bridge_id; | 362 | br->designated_root = br->bridge_id; |
367 | br->bridge_max_age = br->max_age = 20 * HZ; | 363 | br->bridge_max_age = br->max_age = 20 * HZ; |
368 | br->bridge_hello_time = br->hello_time = 2 * HZ; | 364 | br->bridge_hello_time = br->hello_time = 2 * HZ; |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index d9576e6de2b..68def3b7fb4 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -28,8 +28,7 @@ | |||
28 | static struct kmem_cache *br_fdb_cache __read_mostly; | 28 | static struct kmem_cache *br_fdb_cache __read_mostly; |
29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
30 | const unsigned char *addr); | 30 | const unsigned char *addr); |
31 | static void fdb_notify(struct net_bridge *br, | 31 | static void fdb_notify(const struct net_bridge_fdb_entry *, int); |
32 | const struct net_bridge_fdb_entry *, int); | ||
33 | 32 | ||
34 | static u32 fdb_salt __read_mostly; | 33 | static u32 fdb_salt __read_mostly; |
35 | 34 | ||
@@ -81,10 +80,10 @@ static void fdb_rcu_free(struct rcu_head *head) | |||
81 | kmem_cache_free(br_fdb_cache, ent); | 80 | kmem_cache_free(br_fdb_cache, ent); |
82 | } | 81 | } |
83 | 82 | ||
84 | static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) | 83 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) |
85 | { | 84 | { |
85 | fdb_notify(f, RTM_DELNEIGH); | ||
86 | hlist_del_rcu(&f->hlist); | 86 | hlist_del_rcu(&f->hlist); |
87 | fdb_notify(br, f, RTM_DELNEIGH); | ||
88 | call_rcu(&f->rcu, fdb_rcu_free); | 87 | call_rcu(&f->rcu, fdb_rcu_free); |
89 | } | 88 | } |
90 | 89 | ||
@@ -107,15 +106,15 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | |||
107 | struct net_bridge_port *op; | 106 | struct net_bridge_port *op; |
108 | list_for_each_entry(op, &br->port_list, list) { | 107 | list_for_each_entry(op, &br->port_list, list) { |
109 | if (op != p && | 108 | if (op != p && |
110 | ether_addr_equal(op->dev->dev_addr, | 109 | !compare_ether_addr(op->dev->dev_addr, |
111 | f->addr.addr)) { | 110 | f->addr.addr)) { |
112 | f->dst = op; | 111 | f->dst = op; |
113 | goto insert; | 112 | goto insert; |
114 | } | 113 | } |
115 | } | 114 | } |
116 | 115 | ||
117 | /* delete old one */ | 116 | /* delete old one */ |
118 | fdb_delete(br, f); | 117 | fdb_delete(f); |
119 | goto insert; | 118 | goto insert; |
120 | } | 119 | } |
121 | } | 120 | } |
@@ -127,18 +126,6 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | |||
127 | spin_unlock_bh(&br->hash_lock); | 126 | spin_unlock_bh(&br->hash_lock); |
128 | } | 127 | } |
129 | 128 | ||
130 | void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr) | ||
131 | { | ||
132 | struct net_bridge_fdb_entry *f; | ||
133 | |||
134 | /* If old entry was unassociated with any port, then delete it. */ | ||
135 | f = __br_fdb_get(br, br->dev->dev_addr); | ||
136 | if (f && f->is_local && !f->dst) | ||
137 | fdb_delete(br, f); | ||
138 | |||
139 | fdb_insert(br, NULL, newaddr); | ||
140 | } | ||
141 | |||
142 | void br_fdb_cleanup(unsigned long _data) | 129 | void br_fdb_cleanup(unsigned long _data) |
143 | { | 130 | { |
144 | struct net_bridge *br = (struct net_bridge *)_data; | 131 | struct net_bridge *br = (struct net_bridge *)_data; |
@@ -146,7 +133,7 @@ void br_fdb_cleanup(unsigned long _data) | |||
146 | unsigned long next_timer = jiffies + br->ageing_time; | 133 | unsigned long next_timer = jiffies + br->ageing_time; |
147 | int i; | 134 | int i; |
148 | 135 | ||
149 | spin_lock(&br->hash_lock); | 136 | spin_lock_bh(&br->hash_lock); |
150 | for (i = 0; i < BR_HASH_SIZE; i++) { | 137 | for (i = 0; i < BR_HASH_SIZE; i++) { |
151 | struct net_bridge_fdb_entry *f; | 138 | struct net_bridge_fdb_entry *f; |
152 | struct hlist_node *h, *n; | 139 | struct hlist_node *h, *n; |
@@ -157,12 +144,12 @@ void br_fdb_cleanup(unsigned long _data) | |||
157 | continue; | 144 | continue; |
158 | this_timer = f->updated + delay; | 145 | this_timer = f->updated + delay; |
159 | if (time_before_eq(this_timer, jiffies)) | 146 | if (time_before_eq(this_timer, jiffies)) |
160 | fdb_delete(br, f); | 147 | fdb_delete(f); |
161 | else if (time_before(this_timer, next_timer)) | 148 | else if (time_before(this_timer, next_timer)) |
162 | next_timer = this_timer; | 149 | next_timer = this_timer; |
163 | } | 150 | } |
164 | } | 151 | } |
165 | spin_unlock(&br->hash_lock); | 152 | spin_unlock_bh(&br->hash_lock); |
166 | 153 | ||
167 | mod_timer(&br->gc_timer, round_jiffies_up(next_timer)); | 154 | mod_timer(&br->gc_timer, round_jiffies_up(next_timer)); |
168 | } | 155 | } |
@@ -178,7 +165,7 @@ void br_fdb_flush(struct net_bridge *br) | |||
178 | struct hlist_node *h, *n; | 165 | struct hlist_node *h, *n; |
179 | hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { | 166 | hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { |
180 | if (!f->is_static) | 167 | if (!f->is_static) |
181 | fdb_delete(br, f); | 168 | fdb_delete(f); |
182 | } | 169 | } |
183 | } | 170 | } |
184 | spin_unlock_bh(&br->hash_lock); | 171 | spin_unlock_bh(&br->hash_lock); |
@@ -214,15 +201,15 @@ void br_fdb_delete_by_port(struct net_bridge *br, | |||
214 | struct net_bridge_port *op; | 201 | struct net_bridge_port *op; |
215 | list_for_each_entry(op, &br->port_list, list) { | 202 | list_for_each_entry(op, &br->port_list, list) { |
216 | if (op != p && | 203 | if (op != p && |
217 | ether_addr_equal(op->dev->dev_addr, | 204 | !compare_ether_addr(op->dev->dev_addr, |
218 | f->addr.addr)) { | 205 | f->addr.addr)) { |
219 | f->dst = op; | 206 | f->dst = op; |
220 | goto skip_delete; | 207 | goto skip_delete; |
221 | } | 208 | } |
222 | } | 209 | } |
223 | } | 210 | } |
224 | 211 | ||
225 | fdb_delete(br, f); | 212 | fdb_delete(f); |
226 | skip_delete: ; | 213 | skip_delete: ; |
227 | } | 214 | } |
228 | } | 215 | } |
@@ -237,7 +224,7 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | |||
237 | struct net_bridge_fdb_entry *fdb; | 224 | struct net_bridge_fdb_entry *fdb; |
238 | 225 | ||
239 | hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { | 226 | hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) { |
240 | if (ether_addr_equal(fdb->addr.addr, addr)) { | 227 | if (!compare_ether_addr(fdb->addr.addr, addr)) { |
241 | if (unlikely(has_expired(br, fdb))) | 228 | if (unlikely(has_expired(br, fdb))) |
242 | break; | 229 | break; |
243 | return fdb; | 230 | return fdb; |
@@ -247,7 +234,7 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | |||
247 | return NULL; | 234 | return NULL; |
248 | } | 235 | } |
249 | 236 | ||
250 | #if IS_ENABLED(CONFIG_ATM_LANE) | 237 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
251 | /* Interface used by ATM LANE hook to test | 238 | /* Interface used by ATM LANE hook to test |
252 | * if an addr is on some other bridge port */ | 239 | * if an addr is on some other bridge port */ |
253 | int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) | 240 | int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) |
@@ -262,7 +249,7 @@ int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) | |||
262 | ret = 0; | 249 | ret = 0; |
263 | else { | 250 | else { |
264 | fdb = __br_fdb_get(port->br, addr); | 251 | fdb = __br_fdb_get(port->br, addr); |
265 | ret = fdb && fdb->dst && fdb->dst->dev != dev && | 252 | ret = fdb && fdb->dst->dev != dev && |
266 | fdb->dst->state == BR_STATE_FORWARDING; | 253 | fdb->dst->state == BR_STATE_FORWARDING; |
267 | } | 254 | } |
268 | rcu_read_unlock(); | 255 | rcu_read_unlock(); |
@@ -294,10 +281,6 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
294 | if (has_expired(br, f)) | 281 | if (has_expired(br, f)) |
295 | continue; | 282 | continue; |
296 | 283 | ||
297 | /* ignore pseudo entry for local MAC address */ | ||
298 | if (!f->dst) | ||
299 | continue; | ||
300 | |||
301 | if (skip) { | 284 | if (skip) { |
302 | --skip; | 285 | --skip; |
303 | continue; | 286 | continue; |
@@ -312,7 +295,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
312 | 295 | ||
313 | fe->is_local = f->is_local; | 296 | fe->is_local = f->is_local; |
314 | if (!f->is_static) | 297 | if (!f->is_static) |
315 | fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated); | 298 | fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->updated); |
316 | ++fe; | 299 | ++fe; |
317 | ++num; | 300 | ++num; |
318 | } | 301 | } |
@@ -331,7 +314,7 @@ static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | |||
331 | struct net_bridge_fdb_entry *fdb; | 314 | struct net_bridge_fdb_entry *fdb; |
332 | 315 | ||
333 | hlist_for_each_entry(fdb, h, head, hlist) { | 316 | hlist_for_each_entry(fdb, h, head, hlist) { |
334 | if (ether_addr_equal(fdb->addr.addr, addr)) | 317 | if (!compare_ether_addr(fdb->addr.addr, addr)) |
335 | return fdb; | 318 | return fdb; |
336 | } | 319 | } |
337 | return NULL; | 320 | return NULL; |
@@ -344,7 +327,7 @@ static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head, | |||
344 | struct net_bridge_fdb_entry *fdb; | 327 | struct net_bridge_fdb_entry *fdb; |
345 | 328 | ||
346 | hlist_for_each_entry_rcu(fdb, h, head, hlist) { | 329 | hlist_for_each_entry_rcu(fdb, h, head, hlist) { |
347 | if (ether_addr_equal(fdb->addr.addr, addr)) | 330 | if (!compare_ether_addr(fdb->addr.addr, addr)) |
348 | return fdb; | 331 | return fdb; |
349 | } | 332 | } |
350 | return NULL; | 333 | return NULL; |
@@ -364,6 +347,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, | |||
364 | fdb->is_static = 0; | 347 | fdb->is_static = 0; |
365 | fdb->updated = fdb->used = jiffies; | 348 | fdb->updated = fdb->used = jiffies; |
366 | hlist_add_head_rcu(&fdb->hlist, head); | 349 | hlist_add_head_rcu(&fdb->hlist, head); |
350 | fdb_notify(fdb, RTM_NEWNEIGH); | ||
367 | } | 351 | } |
368 | return fdb; | 352 | return fdb; |
369 | } | 353 | } |
@@ -387,7 +371,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
387 | br_warn(br, "adding interface %s with same address " | 371 | br_warn(br, "adding interface %s with same address " |
388 | "as a received packet\n", | 372 | "as a received packet\n", |
389 | source->dev->name); | 373 | source->dev->name); |
390 | fdb_delete(br, fdb); | 374 | fdb_delete(fdb); |
391 | } | 375 | } |
392 | 376 | ||
393 | fdb = fdb_create(head, source, addr); | 377 | fdb = fdb_create(head, source, addr); |
@@ -395,7 +379,6 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
395 | return -ENOMEM; | 379 | return -ENOMEM; |
396 | 380 | ||
397 | fdb->is_local = fdb->is_static = 1; | 381 | fdb->is_local = fdb->is_static = 1; |
398 | fdb_notify(br, fdb, RTM_NEWNEIGH); | ||
399 | return 0; | 382 | return 0; |
400 | } | 383 | } |
401 | 384 | ||
@@ -441,11 +424,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
441 | } | 424 | } |
442 | } else { | 425 | } else { |
443 | spin_lock(&br->hash_lock); | 426 | spin_lock(&br->hash_lock); |
444 | if (likely(!fdb_find(head, addr))) { | 427 | if (likely(!fdb_find(head, addr))) |
445 | fdb = fdb_create(head, source, addr); | 428 | fdb_create(head, source, addr); |
446 | if (fdb) | 429 | |
447 | fdb_notify(br, fdb, RTM_NEWNEIGH); | ||
448 | } | ||
449 | /* else we lose race and someone else inserts | 430 | /* else we lose race and someone else inserts |
450 | * it first, don't bother updating | 431 | * it first, don't bother updating |
451 | */ | 432 | */ |
@@ -465,36 +446,37 @@ static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb) | |||
465 | return NUD_REACHABLE; | 446 | return NUD_REACHABLE; |
466 | } | 447 | } |
467 | 448 | ||
468 | static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, | 449 | static int fdb_fill_info(struct sk_buff *skb, |
469 | const struct net_bridge_fdb_entry *fdb, | 450 | const struct net_bridge_fdb_entry *fdb, |
470 | u32 portid, u32 seq, int type, unsigned int flags) | 451 | u32 pid, u32 seq, int type, unsigned int flags) |
471 | { | 452 | { |
472 | unsigned long now = jiffies; | 453 | unsigned long now = jiffies; |
473 | struct nda_cacheinfo ci; | 454 | struct nda_cacheinfo ci; |
474 | struct nlmsghdr *nlh; | 455 | struct nlmsghdr *nlh; |
475 | struct ndmsg *ndm; | 456 | struct ndmsg *ndm; |
476 | 457 | ||
477 | nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); | 458 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); |
478 | if (nlh == NULL) | 459 | if (nlh == NULL) |
479 | return -EMSGSIZE; | 460 | return -EMSGSIZE; |
480 | 461 | ||
462 | |||
481 | ndm = nlmsg_data(nlh); | 463 | ndm = nlmsg_data(nlh); |
482 | ndm->ndm_family = AF_BRIDGE; | 464 | ndm->ndm_family = AF_BRIDGE; |
483 | ndm->ndm_pad1 = 0; | 465 | ndm->ndm_pad1 = 0; |
484 | ndm->ndm_pad2 = 0; | 466 | ndm->ndm_pad2 = 0; |
485 | ndm->ndm_flags = 0; | 467 | ndm->ndm_flags = 0; |
486 | ndm->ndm_type = 0; | 468 | ndm->ndm_type = 0; |
487 | ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex; | 469 | ndm->ndm_ifindex = fdb->dst->dev->ifindex; |
488 | ndm->ndm_state = fdb_to_nud(fdb); | 470 | ndm->ndm_state = fdb_to_nud(fdb); |
489 | 471 | ||
490 | if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr)) | 472 | NLA_PUT(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr); |
491 | goto nla_put_failure; | 473 | |
492 | ci.ndm_used = jiffies_to_clock_t(now - fdb->used); | 474 | ci.ndm_used = jiffies_to_clock_t(now - fdb->used); |
493 | ci.ndm_confirmed = 0; | 475 | ci.ndm_confirmed = 0; |
494 | ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); | 476 | ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); |
495 | ci.ndm_refcnt = 0; | 477 | ci.ndm_refcnt = 0; |
496 | if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) | 478 | NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); |
497 | goto nla_put_failure; | 479 | |
498 | return nlmsg_end(skb, nlh); | 480 | return nlmsg_end(skb, nlh); |
499 | 481 | ||
500 | nla_put_failure: | 482 | nla_put_failure: |
@@ -509,10 +491,9 @@ static inline size_t fdb_nlmsg_size(void) | |||
509 | + nla_total_size(sizeof(struct nda_cacheinfo)); | 491 | + nla_total_size(sizeof(struct nda_cacheinfo)); |
510 | } | 492 | } |
511 | 493 | ||
512 | static void fdb_notify(struct net_bridge *br, | 494 | static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) |
513 | const struct net_bridge_fdb_entry *fdb, int type) | ||
514 | { | 495 | { |
515 | struct net *net = dev_net(br->dev); | 496 | struct net *net = dev_net(fdb->dst->dev); |
516 | struct sk_buff *skb; | 497 | struct sk_buff *skb; |
517 | int err = -ENOBUFS; | 498 | int err = -ENOBUFS; |
518 | 499 | ||
@@ -520,7 +501,7 @@ static void fdb_notify(struct net_bridge *br, | |||
520 | if (skb == NULL) | 501 | if (skb == NULL) |
521 | goto errout; | 502 | goto errout; |
522 | 503 | ||
523 | err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0); | 504 | err = fdb_fill_info(skb, fdb, 0, 0, type, 0); |
524 | if (err < 0) { | 505 | if (err < 0) { |
525 | /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ | 506 | /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ |
526 | WARN_ON(err == -EMSGSIZE); | 507 | WARN_ON(err == -EMSGSIZE); |
@@ -535,88 +516,105 @@ errout: | |||
535 | } | 516 | } |
536 | 517 | ||
537 | /* Dump information about entries, in response to GETNEIGH */ | 518 | /* Dump information about entries, in response to GETNEIGH */ |
538 | int br_fdb_dump(struct sk_buff *skb, | 519 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) |
539 | struct netlink_callback *cb, | ||
540 | struct net_device *dev, | ||
541 | int idx) | ||
542 | { | 520 | { |
543 | struct net_bridge *br = netdev_priv(dev); | 521 | struct net *net = sock_net(skb->sk); |
544 | int i; | 522 | struct net_device *dev; |
523 | int idx = 0; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | for_each_netdev_rcu(net, dev) { | ||
527 | struct net_bridge *br = netdev_priv(dev); | ||
528 | int i; | ||
545 | 529 | ||
546 | if (!(dev->priv_flags & IFF_EBRIDGE)) | 530 | if (!(dev->priv_flags & IFF_EBRIDGE)) |
547 | goto out; | 531 | continue; |
548 | 532 | ||
549 | for (i = 0; i < BR_HASH_SIZE; i++) { | 533 | for (i = 0; i < BR_HASH_SIZE; i++) { |
550 | struct hlist_node *h; | 534 | struct hlist_node *h; |
551 | struct net_bridge_fdb_entry *f; | 535 | struct net_bridge_fdb_entry *f; |
552 | 536 | ||
553 | hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { | 537 | hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { |
554 | if (idx < cb->args[0]) | 538 | if (idx < cb->args[0]) |
555 | goto skip; | 539 | goto skip; |
556 | 540 | ||
557 | if (fdb_fill_info(skb, br, f, | 541 | if (fdb_fill_info(skb, f, |
558 | NETLINK_CB(cb->skb).portid, | 542 | NETLINK_CB(cb->skb).pid, |
559 | cb->nlh->nlmsg_seq, | 543 | cb->nlh->nlmsg_seq, |
560 | RTM_NEWNEIGH, | 544 | RTM_NEWNEIGH, |
561 | NLM_F_MULTI) < 0) | 545 | NLM_F_MULTI) < 0) |
562 | break; | 546 | break; |
563 | skip: | 547 | skip: |
564 | ++idx; | 548 | ++idx; |
549 | } | ||
565 | } | 550 | } |
566 | } | 551 | } |
552 | rcu_read_unlock(); | ||
553 | |||
554 | cb->args[0] = idx; | ||
567 | 555 | ||
568 | out: | 556 | return skb->len; |
569 | return idx; | ||
570 | } | 557 | } |
571 | 558 | ||
572 | /* Update (create or replace) forwarding database entry */ | 559 | /* Create new static fdb entry */ |
573 | static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, | 560 | static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, |
574 | __u16 state, __u16 flags) | 561 | __u16 state) |
575 | { | 562 | { |
576 | struct net_bridge *br = source->br; | 563 | struct net_bridge *br = source->br; |
577 | struct hlist_head *head = &br->hash[br_mac_hash(addr)]; | 564 | struct hlist_head *head = &br->hash[br_mac_hash(addr)]; |
578 | struct net_bridge_fdb_entry *fdb; | 565 | struct net_bridge_fdb_entry *fdb; |
579 | 566 | ||
580 | fdb = fdb_find(head, addr); | 567 | fdb = fdb_find(head, addr); |
581 | if (fdb == NULL) { | 568 | if (fdb) |
582 | if (!(flags & NLM_F_CREATE)) | 569 | return -EEXIST; |
583 | return -ENOENT; | ||
584 | |||
585 | fdb = fdb_create(head, source, addr); | ||
586 | if (!fdb) | ||
587 | return -ENOMEM; | ||
588 | fdb_notify(br, fdb, RTM_NEWNEIGH); | ||
589 | } else { | ||
590 | if (flags & NLM_F_EXCL) | ||
591 | return -EEXIST; | ||
592 | } | ||
593 | 570 | ||
594 | if (fdb_to_nud(fdb) != state) { | 571 | fdb = fdb_create(head, source, addr); |
595 | if (state & NUD_PERMANENT) | 572 | if (!fdb) |
596 | fdb->is_local = fdb->is_static = 1; | 573 | return -ENOMEM; |
597 | else if (state & NUD_NOARP) { | ||
598 | fdb->is_local = 0; | ||
599 | fdb->is_static = 1; | ||
600 | } else | ||
601 | fdb->is_local = fdb->is_static = 0; | ||
602 | |||
603 | fdb->updated = fdb->used = jiffies; | ||
604 | fdb_notify(br, fdb, RTM_NEWNEIGH); | ||
605 | } | ||
606 | 574 | ||
575 | if (state & NUD_PERMANENT) | ||
576 | fdb->is_local = fdb->is_static = 1; | ||
577 | else if (state & NUD_NOARP) | ||
578 | fdb->is_static = 1; | ||
607 | return 0; | 579 | return 0; |
608 | } | 580 | } |
609 | 581 | ||
610 | /* Add new permanent fdb entry with RTM_NEWNEIGH */ | 582 | /* Add new permanent fdb entry with RTM_NEWNEIGH */ |
611 | int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | 583 | int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
612 | struct net_device *dev, | ||
613 | const unsigned char *addr, u16 nlh_flags) | ||
614 | { | 584 | { |
585 | struct net *net = sock_net(skb->sk); | ||
586 | struct ndmsg *ndm; | ||
587 | struct nlattr *tb[NDA_MAX+1]; | ||
588 | struct net_device *dev; | ||
615 | struct net_bridge_port *p; | 589 | struct net_bridge_port *p; |
616 | int err = 0; | 590 | const __u8 *addr; |
591 | int err; | ||
617 | 592 | ||
618 | if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) { | 593 | ASSERT_RTNL(); |
619 | pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state); | 594 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); |
595 | if (err < 0) | ||
596 | return err; | ||
597 | |||
598 | ndm = nlmsg_data(nlh); | ||
599 | if (ndm->ndm_ifindex == 0) { | ||
600 | pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n"); | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | |||
604 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); | ||
605 | if (dev == NULL) { | ||
606 | pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n"); | ||
607 | return -ENODEV; | ||
608 | } | ||
609 | |||
610 | if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { | ||
611 | pr_info("bridge: RTM_NEWNEIGH with invalid address\n"); | ||
612 | return -EINVAL; | ||
613 | } | ||
614 | |||
615 | addr = nla_data(tb[NDA_LLADDR]); | ||
616 | if (!is_valid_ether_addr(addr)) { | ||
617 | pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); | ||
620 | return -EINVAL; | 618 | return -EINVAL; |
621 | } | 619 | } |
622 | 620 | ||
@@ -627,15 +625,9 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | |||
627 | return -EINVAL; | 625 | return -EINVAL; |
628 | } | 626 | } |
629 | 627 | ||
630 | if (ndm->ndm_flags & NTF_USE) { | 628 | spin_lock_bh(&p->br->hash_lock); |
631 | rcu_read_lock(); | 629 | err = fdb_add_entry(p, addr, ndm->ndm_state); |
632 | br_fdb_update(p->br, p, addr); | 630 | spin_unlock_bh(&p->br->hash_lock); |
633 | rcu_read_unlock(); | ||
634 | } else { | ||
635 | spin_lock_bh(&p->br->hash_lock); | ||
636 | err = fdb_add_entry(p, addr, ndm->ndm_state, nlh_flags); | ||
637 | spin_unlock_bh(&p->br->hash_lock); | ||
638 | } | ||
639 | 631 | ||
640 | return err; | 632 | return err; |
641 | } | 633 | } |
@@ -650,17 +642,45 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) | |||
650 | if (!fdb) | 642 | if (!fdb) |
651 | return -ENOENT; | 643 | return -ENOENT; |
652 | 644 | ||
653 | fdb_delete(p->br, fdb); | 645 | fdb_delete(fdb); |
654 | return 0; | 646 | return 0; |
655 | } | 647 | } |
656 | 648 | ||
657 | /* Remove neighbor entry with RTM_DELNEIGH */ | 649 | /* Remove neighbor entry with RTM_DELNEIGH */ |
658 | int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev, | 650 | int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
659 | const unsigned char *addr) | ||
660 | { | 651 | { |
652 | struct net *net = sock_net(skb->sk); | ||
653 | struct ndmsg *ndm; | ||
661 | struct net_bridge_port *p; | 654 | struct net_bridge_port *p; |
655 | struct nlattr *llattr; | ||
656 | const __u8 *addr; | ||
657 | struct net_device *dev; | ||
662 | int err; | 658 | int err; |
663 | 659 | ||
660 | ASSERT_RTNL(); | ||
661 | if (nlmsg_len(nlh) < sizeof(*ndm)) | ||
662 | return -EINVAL; | ||
663 | |||
664 | ndm = nlmsg_data(nlh); | ||
665 | if (ndm->ndm_ifindex == 0) { | ||
666 | pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n"); | ||
667 | return -EINVAL; | ||
668 | } | ||
669 | |||
670 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); | ||
671 | if (dev == NULL) { | ||
672 | pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n"); | ||
673 | return -ENODEV; | ||
674 | } | ||
675 | |||
676 | llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); | ||
677 | if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { | ||
678 | pr_info("bridge: RTM_DELNEIGH with invalid address\n"); | ||
679 | return -EINVAL; | ||
680 | } | ||
681 | |||
682 | addr = nla_data(llattr); | ||
683 | |||
664 | p = br_port_get_rtnl(dev); | 684 | p = br_port_get_rtnl(dev); |
665 | if (p == NULL) { | 685 | if (p == NULL) { |
666 | pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", | 686 | pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 02015a505d2..ee64287f129 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -34,7 +34,7 @@ static inline int should_deliver(const struct net_bridge_port *p, | |||
34 | p->state == BR_STATE_FORWARDING); | 34 | p->state == BR_STATE_FORWARDING); |
35 | } | 35 | } |
36 | 36 | ||
37 | static inline unsigned int packet_length(const struct sk_buff *skb) | 37 | static inline unsigned packet_length(const struct sk_buff *skb) |
38 | { | 38 | { |
39 | return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); | 39 | return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); |
40 | } | 40 | } |
@@ -47,7 +47,6 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
47 | kfree_skb(skb); | 47 | kfree_skb(skb); |
48 | } else { | 48 | } else { |
49 | skb_push(skb, ETH_HLEN); | 49 | skb_push(skb, ETH_HLEN); |
50 | br_drop_fake_rtable(skb); | ||
51 | dev_queue_xmit(skb); | 50 | dev_queue_xmit(skb); |
52 | } | 51 | } |
53 | 52 | ||
@@ -65,7 +64,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
65 | { | 64 | { |
66 | skb->dev = to->dev; | 65 | skb->dev = to->dev; |
67 | 66 | ||
68 | if (unlikely(netpoll_tx_running(to->br->dev))) { | 67 | if (unlikely(netpoll_tx_running(to->dev))) { |
69 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) | 68 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) |
70 | kfree_skb(skb); | 69 | kfree_skb(skb); |
71 | else { | 70 | else { |
@@ -99,7 +98,7 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) | |||
99 | /* called with rcu_read_lock */ | 98 | /* called with rcu_read_lock */ |
100 | void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | 99 | void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) |
101 | { | 100 | { |
102 | if (to && should_deliver(to, skb)) { | 101 | if (should_deliver(to, skb)) { |
103 | __br_deliver(to, skb); | 102 | __br_deliver(to, skb); |
104 | return; | 103 | return; |
105 | } | 104 | } |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 37fe693471a..1d420f64ff2 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | ||
17 | #include <linux/netpoll.h> | 16 | #include <linux/netpoll.h> |
18 | #include <linux/ethtool.h> | 17 | #include <linux/ethtool.h> |
19 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
@@ -34,18 +33,20 @@ | |||
34 | */ | 33 | */ |
35 | static int port_cost(struct net_device *dev) | 34 | static int port_cost(struct net_device *dev) |
36 | { | 35 | { |
37 | struct ethtool_cmd ecmd; | 36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { |
38 | 37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; | |
39 | if (!__ethtool_get_settings(dev, &ecmd)) { | 38 | |
40 | switch (ethtool_cmd_speed(&ecmd)) { | 39 | if (!dev_ethtool_get_settings(dev, &ecmd)) { |
41 | case SPEED_10000: | 40 | switch (ethtool_cmd_speed(&ecmd)) { |
42 | return 2; | 41 | case SPEED_10000: |
43 | case SPEED_1000: | 42 | return 2; |
44 | return 4; | 43 | case SPEED_1000: |
45 | case SPEED_100: | 44 | return 4; |
46 | return 19; | 45 | case SPEED_100: |
47 | case SPEED_10: | 46 | return 19; |
48 | return 100; | 47 | case SPEED_10: |
48 | return 100; | ||
49 | } | ||
49 | } | 50 | } |
50 | } | 51 | } |
51 | 52 | ||
@@ -240,7 +241,6 @@ int br_add_bridge(struct net *net, const char *name) | |||
240 | return -ENOMEM; | 241 | return -ENOMEM; |
241 | 242 | ||
242 | dev_net_set(dev, net); | 243 | dev_net_set(dev, net); |
243 | dev->rtnl_link_ops = &br_link_ops; | ||
244 | 244 | ||
245 | res = register_netdev(dev); | 245 | res = register_netdev(dev); |
246 | if (res) | 246 | if (res) |
@@ -297,11 +297,10 @@ int br_min_mtu(const struct net_bridge *br) | |||
297 | /* | 297 | /* |
298 | * Recomputes features using slave's features | 298 | * Recomputes features using slave's features |
299 | */ | 299 | */ |
300 | netdev_features_t br_features_recompute(struct net_bridge *br, | 300 | u32 br_features_recompute(struct net_bridge *br, u32 features) |
301 | netdev_features_t features) | ||
302 | { | 301 | { |
303 | struct net_bridge_port *p; | 302 | struct net_bridge_port *p; |
304 | netdev_features_t mask; | 303 | u32 mask; |
305 | 304 | ||
306 | if (list_empty(&br->port_list)) | 305 | if (list_empty(&br->port_list)) |
307 | return features; | 306 | return features; |
@@ -326,8 +325,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
326 | 325 | ||
327 | /* Don't allow bridging non-ethernet like devices */ | 326 | /* Don't allow bridging non-ethernet like devices */ |
328 | if ((dev->flags & IFF_LOOPBACK) || | 327 | if ((dev->flags & IFF_LOOPBACK) || |
329 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || | 328 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) |
330 | !is_valid_ether_addr(dev->dev_addr)) | ||
331 | return -EINVAL; | 329 | return -EINVAL; |
332 | 330 | ||
333 | /* No bridging of bridges */ | 331 | /* No bridging of bridges */ |
@@ -355,22 +353,26 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
355 | err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), | 353 | err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), |
356 | SYSFS_BRIDGE_PORT_ATTR); | 354 | SYSFS_BRIDGE_PORT_ATTR); |
357 | if (err) | 355 | if (err) |
356 | goto err0; | ||
357 | |||
358 | err = br_fdb_insert(br, p, dev->dev_addr); | ||
359 | if (err) | ||
358 | goto err1; | 360 | goto err1; |
359 | 361 | ||
360 | err = br_sysfs_addif(p); | 362 | err = br_sysfs_addif(p); |
361 | if (err) | 363 | if (err) |
362 | goto err2; | 364 | goto err2; |
363 | 365 | ||
364 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) | 366 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) |
365 | goto err3; | 367 | goto err3; |
366 | 368 | ||
367 | err = netdev_set_master(dev, br->dev); | 369 | err = netdev_set_master(dev, br->dev); |
368 | if (err) | 370 | if (err) |
369 | goto err4; | 371 | goto err3; |
370 | 372 | ||
371 | err = netdev_rx_handler_register(dev, br_handle_frame, p); | 373 | err = netdev_rx_handler_register(dev, br_handle_frame, p); |
372 | if (err) | 374 | if (err) |
373 | goto err5; | 375 | goto err4; |
374 | 376 | ||
375 | dev->priv_flags |= IFF_BRIDGE_PORT; | 377 | dev->priv_flags |= IFF_BRIDGE_PORT; |
376 | 378 | ||
@@ -395,23 +397,20 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
395 | 397 | ||
396 | dev_set_mtu(br->dev, br_min_mtu(br)); | 398 | dev_set_mtu(br->dev, br_min_mtu(br)); |
397 | 399 | ||
398 | if (br_fdb_insert(br, p, dev->dev_addr)) | ||
399 | netdev_err(dev, "failed insert local address bridge forwarding table\n"); | ||
400 | |||
401 | kobject_uevent(&p->kobj, KOBJ_ADD); | 400 | kobject_uevent(&p->kobj, KOBJ_ADD); |
402 | 401 | ||
403 | return 0; | 402 | return 0; |
404 | 403 | ||
405 | err5: | ||
406 | netdev_set_master(dev, NULL); | ||
407 | err4: | 404 | err4: |
408 | br_netpoll_disable(p); | 405 | netdev_set_master(dev, NULL); |
409 | err3: | 406 | err3: |
410 | sysfs_remove_link(br->ifobj, p->dev->name); | 407 | sysfs_remove_link(br->ifobj, p->dev->name); |
411 | err2: | 408 | err2: |
409 | br_fdb_delete_by_port(br, p, 1); | ||
410 | err1: | ||
412 | kobject_put(&p->kobj); | 411 | kobject_put(&p->kobj); |
413 | p = NULL; /* kobject_put frees */ | 412 | p = NULL; /* kobject_put frees */ |
414 | err1: | 413 | err0: |
415 | dev_set_promiscuity(dev, -1); | 414 | dev_set_promiscuity(dev, -1); |
416 | put_back: | 415 | put_back: |
417 | dev_put(dev); | 416 | dev_put(dev); |
@@ -429,10 +428,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
429 | if (!p || p->br != br) | 428 | if (!p || p->br != br) |
430 | return -EINVAL; | 429 | return -EINVAL; |
431 | 430 | ||
432 | /* Since more than one interface can be attached to a bridge, | ||
433 | * there still maybe an alternate path for netconsole to use; | ||
434 | * therefore there is no reason for a NETDEV_RELEASE event. | ||
435 | */ | ||
436 | del_nbp(p); | 431 | del_nbp(p); |
437 | 432 | ||
438 | spin_lock_bh(&br->lock); | 433 | spin_lock_bh(&br->lock); |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 4b34207419b..f06ee39c73f 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -16,9 +16,11 @@ | |||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
18 | #include <linux/netfilter_bridge.h> | 18 | #include <linux/netfilter_bridge.h> |
19 | #include <linux/export.h> | ||
20 | #include "br_private.h" | 19 | #include "br_private.h" |
21 | 20 | ||
21 | /* Bridge group multicast address 802.1d (pg 51). */ | ||
22 | const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | ||
23 | |||
22 | /* Hook for brouter */ | 24 | /* Hook for brouter */ |
23 | br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; | 25 | br_should_route_hook_t __rcu *br_should_route_hook __read_mostly; |
24 | EXPORT_SYMBOL(br_should_route_hook); | 26 | EXPORT_SYMBOL(br_should_route_hook); |
@@ -124,6 +126,18 @@ static int br_handle_local_finish(struct sk_buff *skb) | |||
124 | return 0; /* process further */ | 126 | return 0; /* process further */ |
125 | } | 127 | } |
126 | 128 | ||
129 | /* Does address match the link local multicast address. | ||
130 | * 01:80:c2:00:00:0X | ||
131 | */ | ||
132 | static inline int is_link_local(const unsigned char *dest) | ||
133 | { | ||
134 | __be16 *a = (__be16 *)dest; | ||
135 | static const __be16 *b = (const __be16 *)br_group_address; | ||
136 | static const __be16 m = cpu_to_be16(0xfff0); | ||
137 | |||
138 | return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0; | ||
139 | } | ||
140 | |||
127 | /* | 141 | /* |
128 | * Return NULL if skb is handled | 142 | * Return NULL if skb is handled |
129 | * note: already called with rcu_read_lock | 143 | * note: already called with rcu_read_lock |
@@ -147,38 +161,15 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) | |||
147 | 161 | ||
148 | p = br_port_get_rcu(skb->dev); | 162 | p = br_port_get_rcu(skb->dev); |
149 | 163 | ||
150 | if (unlikely(is_link_local_ether_addr(dest))) { | 164 | if (unlikely(is_link_local(dest))) { |
151 | /* | 165 | /* Pause frames shouldn't be passed up by driver anyway */ |
152 | * See IEEE 802.1D Table 7-10 Reserved addresses | 166 | if (skb->protocol == htons(ETH_P_PAUSE)) |
153 | * | ||
154 | * Assignment Value | ||
155 | * Bridge Group Address 01-80-C2-00-00-00 | ||
156 | * (MAC Control) 802.3 01-80-C2-00-00-01 | ||
157 | * (Link Aggregation) 802.3 01-80-C2-00-00-02 | ||
158 | * 802.1X PAE address 01-80-C2-00-00-03 | ||
159 | * | ||
160 | * 802.1AB LLDP 01-80-C2-00-00-0E | ||
161 | * | ||
162 | * Others reserved for future standardization | ||
163 | */ | ||
164 | switch (dest[5]) { | ||
165 | case 0x00: /* Bridge Group Address */ | ||
166 | /* If STP is turned off, | ||
167 | then must forward to keep loop detection */ | ||
168 | if (p->br->stp_enabled == BR_NO_STP) | ||
169 | goto forward; | ||
170 | break; | ||
171 | |||
172 | case 0x01: /* IEEE MAC (Pause) */ | ||
173 | goto drop; | 167 | goto drop; |
174 | 168 | ||
175 | default: | 169 | /* If STP is turned off, then forward */ |
176 | /* Allow selective forwarding for most other protocols */ | 170 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) |
177 | if (p->br->group_fwd_mask & (1u << dest[5])) | 171 | goto forward; |
178 | goto forward; | ||
179 | } | ||
180 | 172 | ||
181 | /* Deliver packet to local host only */ | ||
182 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 173 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
183 | NULL, br_handle_local_finish)) { | 174 | NULL, br_handle_local_finish)) { |
184 | return RX_HANDLER_CONSUMED; /* consumed by filter */ | 175 | return RX_HANDLER_CONSUMED; /* consumed by filter */ |
@@ -201,7 +192,7 @@ forward: | |||
201 | } | 192 | } |
202 | /* fall through */ | 193 | /* fall through */ |
203 | case BR_STATE_LEARNING: | 194 | case BR_STATE_LEARNING: |
204 | if (ether_addr_equal(p->br->dev->dev_addr, dest)) | 195 | if (!compare_ether_addr(p->br->dev->dev_addr, dest)) |
205 | skb->pkt_type = PACKET_HOST; | 196 | skb->pkt_type = PACKET_HOST; |
206 | 197 | ||
207 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, | 198 | NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, |
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index cd8c3a44ab7..7222fe1d546 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -85,14 +85,13 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, | |||
85 | /* called with RTNL */ | 85 | /* called with RTNL */ |
86 | static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | 86 | static int add_del_if(struct net_bridge *br, int ifindex, int isadd) |
87 | { | 87 | { |
88 | struct net *net = dev_net(br->dev); | ||
89 | struct net_device *dev; | 88 | struct net_device *dev; |
90 | int ret; | 89 | int ret; |
91 | 90 | ||
92 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | 91 | if (!capable(CAP_NET_ADMIN)) |
93 | return -EPERM; | 92 | return -EPERM; |
94 | 93 | ||
95 | dev = __dev_get_by_index(net, ifindex); | 94 | dev = __dev_get_by_index(dev_net(br->dev), ifindex); |
96 | if (dev == NULL) | 95 | if (dev == NULL) |
97 | return -EINVAL; | 96 | return -EINVAL; |
98 | 97 | ||
@@ -179,25 +178,25 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
179 | } | 178 | } |
180 | 179 | ||
181 | case BRCTL_SET_BRIDGE_FORWARD_DELAY: | 180 | case BRCTL_SET_BRIDGE_FORWARD_DELAY: |
182 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 181 | if (!capable(CAP_NET_ADMIN)) |
183 | return -EPERM; | 182 | return -EPERM; |
184 | 183 | ||
185 | return br_set_forward_delay(br, args[1]); | 184 | return br_set_forward_delay(br, args[1]); |
186 | 185 | ||
187 | case BRCTL_SET_BRIDGE_HELLO_TIME: | 186 | case BRCTL_SET_BRIDGE_HELLO_TIME: |
188 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 187 | if (!capable(CAP_NET_ADMIN)) |
189 | return -EPERM; | 188 | return -EPERM; |
190 | 189 | ||
191 | return br_set_hello_time(br, args[1]); | 190 | return br_set_hello_time(br, args[1]); |
192 | 191 | ||
193 | case BRCTL_SET_BRIDGE_MAX_AGE: | 192 | case BRCTL_SET_BRIDGE_MAX_AGE: |
194 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 193 | if (!capable(CAP_NET_ADMIN)) |
195 | return -EPERM; | 194 | return -EPERM; |
196 | 195 | ||
197 | return br_set_max_age(br, args[1]); | 196 | return br_set_max_age(br, args[1]); |
198 | 197 | ||
199 | case BRCTL_SET_AGEING_TIME: | 198 | case BRCTL_SET_AGEING_TIME: |
200 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 199 | if (!capable(CAP_NET_ADMIN)) |
201 | return -EPERM; | 200 | return -EPERM; |
202 | 201 | ||
203 | br->ageing_time = clock_t_to_jiffies(args[1]); | 202 | br->ageing_time = clock_t_to_jiffies(args[1]); |
@@ -237,14 +236,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
237 | } | 236 | } |
238 | 237 | ||
239 | case BRCTL_SET_BRIDGE_STP_STATE: | 238 | case BRCTL_SET_BRIDGE_STP_STATE: |
240 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 239 | if (!capable(CAP_NET_ADMIN)) |
241 | return -EPERM; | 240 | return -EPERM; |
242 | 241 | ||
243 | br_stp_set_enabled(br, args[1]); | 242 | br_stp_set_enabled(br, args[1]); |
244 | return 0; | 243 | return 0; |
245 | 244 | ||
246 | case BRCTL_SET_BRIDGE_PRIORITY: | 245 | case BRCTL_SET_BRIDGE_PRIORITY: |
247 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 246 | if (!capable(CAP_NET_ADMIN)) |
248 | return -EPERM; | 247 | return -EPERM; |
249 | 248 | ||
250 | spin_lock_bh(&br->lock); | 249 | spin_lock_bh(&br->lock); |
@@ -257,7 +256,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
257 | struct net_bridge_port *p; | 256 | struct net_bridge_port *p; |
258 | int ret; | 257 | int ret; |
259 | 258 | ||
260 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 259 | if (!capable(CAP_NET_ADMIN)) |
261 | return -EPERM; | 260 | return -EPERM; |
262 | 261 | ||
263 | spin_lock_bh(&br->lock); | 262 | spin_lock_bh(&br->lock); |
@@ -274,7 +273,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
274 | struct net_bridge_port *p; | 273 | struct net_bridge_port *p; |
275 | int ret; | 274 | int ret; |
276 | 275 | ||
277 | if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN)) | 276 | if (!capable(CAP_NET_ADMIN)) |
278 | return -EPERM; | 277 | return -EPERM; |
279 | 278 | ||
280 | spin_lock_bh(&br->lock); | 279 | spin_lock_bh(&br->lock); |
@@ -331,7 +330,7 @@ static int old_deviceless(struct net *net, void __user *uarg) | |||
331 | { | 330 | { |
332 | char buf[IFNAMSIZ]; | 331 | char buf[IFNAMSIZ]; |
333 | 332 | ||
334 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | 333 | if (!capable(CAP_NET_ADMIN)) |
335 | return -EPERM; | 334 | return -EPERM; |
336 | 335 | ||
337 | if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) | 336 | if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ)) |
@@ -361,7 +360,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar | |||
361 | { | 360 | { |
362 | char buf[IFNAMSIZ]; | 361 | char buf[IFNAMSIZ]; |
363 | 362 | ||
364 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | 363 | if (!capable(CAP_NET_ADMIN)) |
365 | return -EPERM; | 364 | return -EPERM; |
366 | 365 | ||
367 | if (copy_from_user(buf, uarg, IFNAMSIZ)) | 366 | if (copy_from_user(buf, uarg, IFNAMSIZ)) |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c deleted file mode 100644 index acc9f4cc18f..00000000000 --- a/net/bridge/br_mdb.c +++ /dev/null | |||
@@ -1,493 +0,0 @@ | |||
1 | #include <linux/err.h> | ||
2 | #include <linux/igmp.h> | ||
3 | #include <linux/kernel.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/rculist.h> | ||
6 | #include <linux/skbuff.h> | ||
7 | #include <linux/if_ether.h> | ||
8 | #include <net/ip.h> | ||
9 | #include <net/netlink.h> | ||
10 | #if IS_ENABLED(CONFIG_IPV6) | ||
11 | #include <net/ipv6.h> | ||
12 | #endif | ||
13 | |||
14 | #include "br_private.h" | ||
15 | |||
16 | static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | ||
17 | struct net_device *dev) | ||
18 | { | ||
19 | struct net_bridge *br = netdev_priv(dev); | ||
20 | struct net_bridge_port *p; | ||
21 | struct hlist_node *n; | ||
22 | struct nlattr *nest; | ||
23 | |||
24 | if (!br->multicast_router || hlist_empty(&br->router_list)) | ||
25 | return 0; | ||
26 | |||
27 | nest = nla_nest_start(skb, MDBA_ROUTER); | ||
28 | if (nest == NULL) | ||
29 | return -EMSGSIZE; | ||
30 | |||
31 | hlist_for_each_entry_rcu(p, n, &br->router_list, rlist) { | ||
32 | if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex)) | ||
33 | goto fail; | ||
34 | } | ||
35 | |||
36 | nla_nest_end(skb, nest); | ||
37 | return 0; | ||
38 | fail: | ||
39 | nla_nest_cancel(skb, nest); | ||
40 | return -EMSGSIZE; | ||
41 | } | ||
42 | |||
43 | static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | ||
44 | struct net_device *dev) | ||
45 | { | ||
46 | struct net_bridge *br = netdev_priv(dev); | ||
47 | struct net_bridge_mdb_htable *mdb; | ||
48 | struct nlattr *nest, *nest2; | ||
49 | int i, err = 0; | ||
50 | int idx = 0, s_idx = cb->args[1]; | ||
51 | |||
52 | if (br->multicast_disabled) | ||
53 | return 0; | ||
54 | |||
55 | mdb = rcu_dereference(br->mdb); | ||
56 | if (!mdb) | ||
57 | return 0; | ||
58 | |||
59 | nest = nla_nest_start(skb, MDBA_MDB); | ||
60 | if (nest == NULL) | ||
61 | return -EMSGSIZE; | ||
62 | |||
63 | for (i = 0; i < mdb->max; i++) { | ||
64 | struct hlist_node *h; | ||
65 | struct net_bridge_mdb_entry *mp; | ||
66 | struct net_bridge_port_group *p, **pp; | ||
67 | struct net_bridge_port *port; | ||
68 | |||
69 | hlist_for_each_entry_rcu(mp, h, &mdb->mhash[i], hlist[mdb->ver]) { | ||
70 | if (idx < s_idx) | ||
71 | goto skip; | ||
72 | |||
73 | nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY); | ||
74 | if (nest2 == NULL) { | ||
75 | err = -EMSGSIZE; | ||
76 | goto out; | ||
77 | } | ||
78 | |||
79 | for (pp = &mp->ports; | ||
80 | (p = rcu_dereference(*pp)) != NULL; | ||
81 | pp = &p->next) { | ||
82 | port = p->port; | ||
83 | if (port) { | ||
84 | struct br_mdb_entry e; | ||
85 | e.ifindex = port->dev->ifindex; | ||
86 | e.state = p->state; | ||
87 | if (p->addr.proto == htons(ETH_P_IP)) | ||
88 | e.addr.u.ip4 = p->addr.u.ip4; | ||
89 | #if IS_ENABLED(CONFIG_IPV6) | ||
90 | if (p->addr.proto == htons(ETH_P_IPV6)) | ||
91 | e.addr.u.ip6 = p->addr.u.ip6; | ||
92 | #endif | ||
93 | e.addr.proto = p->addr.proto; | ||
94 | if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) { | ||
95 | nla_nest_cancel(skb, nest2); | ||
96 | err = -EMSGSIZE; | ||
97 | goto out; | ||
98 | } | ||
99 | } | ||
100 | } | ||
101 | nla_nest_end(skb, nest2); | ||
102 | skip: | ||
103 | idx++; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | out: | ||
108 | cb->args[1] = idx; | ||
109 | nla_nest_end(skb, nest); | ||
110 | return err; | ||
111 | } | ||
112 | |||
113 | static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
114 | { | ||
115 | struct net_device *dev; | ||
116 | struct net *net = sock_net(skb->sk); | ||
117 | struct nlmsghdr *nlh = NULL; | ||
118 | int idx = 0, s_idx; | ||
119 | |||
120 | s_idx = cb->args[0]; | ||
121 | |||
122 | rcu_read_lock(); | ||
123 | |||
124 | /* In theory this could be wrapped to 0... */ | ||
125 | cb->seq = net->dev_base_seq + br_mdb_rehash_seq; | ||
126 | |||
127 | for_each_netdev_rcu(net, dev) { | ||
128 | if (dev->priv_flags & IFF_EBRIDGE) { | ||
129 | struct br_port_msg *bpm; | ||
130 | |||
131 | if (idx < s_idx) | ||
132 | goto skip; | ||
133 | |||
134 | nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, | ||
135 | cb->nlh->nlmsg_seq, RTM_GETMDB, | ||
136 | sizeof(*bpm), NLM_F_MULTI); | ||
137 | if (nlh == NULL) | ||
138 | break; | ||
139 | |||
140 | bpm = nlmsg_data(nlh); | ||
141 | bpm->ifindex = dev->ifindex; | ||
142 | if (br_mdb_fill_info(skb, cb, dev) < 0) | ||
143 | goto out; | ||
144 | if (br_rports_fill_info(skb, cb, dev) < 0) | ||
145 | goto out; | ||
146 | |||
147 | cb->args[1] = 0; | ||
148 | nlmsg_end(skb, nlh); | ||
149 | skip: | ||
150 | idx++; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | out: | ||
155 | if (nlh) | ||
156 | nlmsg_end(skb, nlh); | ||
157 | rcu_read_unlock(); | ||
158 | cb->args[0] = idx; | ||
159 | return skb->len; | ||
160 | } | ||
161 | |||
162 | static int nlmsg_populate_mdb_fill(struct sk_buff *skb, | ||
163 | struct net_device *dev, | ||
164 | struct br_mdb_entry *entry, u32 pid, | ||
165 | u32 seq, int type, unsigned int flags) | ||
166 | { | ||
167 | struct nlmsghdr *nlh; | ||
168 | struct br_port_msg *bpm; | ||
169 | struct nlattr *nest, *nest2; | ||
170 | |||
171 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), NLM_F_MULTI); | ||
172 | if (!nlh) | ||
173 | return -EMSGSIZE; | ||
174 | |||
175 | bpm = nlmsg_data(nlh); | ||
176 | bpm->family = AF_BRIDGE; | ||
177 | bpm->ifindex = dev->ifindex; | ||
178 | nest = nla_nest_start(skb, MDBA_MDB); | ||
179 | if (nest == NULL) | ||
180 | goto cancel; | ||
181 | nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY); | ||
182 | if (nest2 == NULL) | ||
183 | goto end; | ||
184 | |||
185 | if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(*entry), entry)) | ||
186 | goto end; | ||
187 | |||
188 | nla_nest_end(skb, nest2); | ||
189 | nla_nest_end(skb, nest); | ||
190 | return nlmsg_end(skb, nlh); | ||
191 | |||
192 | end: | ||
193 | nla_nest_end(skb, nest); | ||
194 | cancel: | ||
195 | nlmsg_cancel(skb, nlh); | ||
196 | return -EMSGSIZE; | ||
197 | } | ||
198 | |||
199 | static inline size_t rtnl_mdb_nlmsg_size(void) | ||
200 | { | ||
201 | return NLMSG_ALIGN(sizeof(struct br_port_msg)) | ||
202 | + nla_total_size(sizeof(struct br_mdb_entry)); | ||
203 | } | ||
204 | |||
205 | static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | ||
206 | int type) | ||
207 | { | ||
208 | struct net *net = dev_net(dev); | ||
209 | struct sk_buff *skb; | ||
210 | int err = -ENOBUFS; | ||
211 | |||
212 | skb = nlmsg_new(rtnl_mdb_nlmsg_size(), GFP_ATOMIC); | ||
213 | if (!skb) | ||
214 | goto errout; | ||
215 | |||
216 | err = nlmsg_populate_mdb_fill(skb, dev, entry, 0, 0, type, NTF_SELF); | ||
217 | if (err < 0) { | ||
218 | kfree_skb(skb); | ||
219 | goto errout; | ||
220 | } | ||
221 | |||
222 | rtnl_notify(skb, net, 0, RTNLGRP_MDB, NULL, GFP_ATOMIC); | ||
223 | return; | ||
224 | errout: | ||
225 | rtnl_set_sk_err(net, RTNLGRP_MDB, err); | ||
226 | } | ||
227 | |||
228 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | ||
229 | struct br_ip *group, int type) | ||
230 | { | ||
231 | struct br_mdb_entry entry; | ||
232 | |||
233 | entry.ifindex = port->dev->ifindex; | ||
234 | entry.addr.proto = group->proto; | ||
235 | entry.addr.u.ip4 = group->u.ip4; | ||
236 | #if IS_ENABLED(CONFIG_IPV6) | ||
237 | entry.addr.u.ip6 = group->u.ip6; | ||
238 | #endif | ||
239 | __br_mdb_notify(dev, &entry, type); | ||
240 | } | ||
241 | |||
242 | static bool is_valid_mdb_entry(struct br_mdb_entry *entry) | ||
243 | { | ||
244 | if (entry->ifindex == 0) | ||
245 | return false; | ||
246 | |||
247 | if (entry->addr.proto == htons(ETH_P_IP)) { | ||
248 | if (!ipv4_is_multicast(entry->addr.u.ip4)) | ||
249 | return false; | ||
250 | if (ipv4_is_local_multicast(entry->addr.u.ip4)) | ||
251 | return false; | ||
252 | #if IS_ENABLED(CONFIG_IPV6) | ||
253 | } else if (entry->addr.proto == htons(ETH_P_IPV6)) { | ||
254 | if (!ipv6_is_transient_multicast(&entry->addr.u.ip6)) | ||
255 | return false; | ||
256 | #endif | ||
257 | } else | ||
258 | return false; | ||
259 | if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) | ||
260 | return false; | ||
261 | |||
262 | return true; | ||
263 | } | ||
264 | |||
265 | static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, | ||
266 | struct net_device **pdev, struct br_mdb_entry **pentry) | ||
267 | { | ||
268 | struct net *net = sock_net(skb->sk); | ||
269 | struct br_mdb_entry *entry; | ||
270 | struct br_port_msg *bpm; | ||
271 | struct nlattr *tb[MDBA_SET_ENTRY_MAX+1]; | ||
272 | struct net_device *dev; | ||
273 | int err; | ||
274 | |||
275 | if (!capable(CAP_NET_ADMIN)) | ||
276 | return -EPERM; | ||
277 | |||
278 | err = nlmsg_parse(nlh, sizeof(*bpm), tb, MDBA_SET_ENTRY, NULL); | ||
279 | if (err < 0) | ||
280 | return err; | ||
281 | |||
282 | bpm = nlmsg_data(nlh); | ||
283 | if (bpm->ifindex == 0) { | ||
284 | pr_info("PF_BRIDGE: br_mdb_parse() with invalid ifindex\n"); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | dev = __dev_get_by_index(net, bpm->ifindex); | ||
289 | if (dev == NULL) { | ||
290 | pr_info("PF_BRIDGE: br_mdb_parse() with unknown ifindex\n"); | ||
291 | return -ENODEV; | ||
292 | } | ||
293 | |||
294 | if (!(dev->priv_flags & IFF_EBRIDGE)) { | ||
295 | pr_info("PF_BRIDGE: br_mdb_parse() with non-bridge\n"); | ||
296 | return -EOPNOTSUPP; | ||
297 | } | ||
298 | |||
299 | *pdev = dev; | ||
300 | |||
301 | if (!tb[MDBA_SET_ENTRY] || | ||
302 | nla_len(tb[MDBA_SET_ENTRY]) != sizeof(struct br_mdb_entry)) { | ||
303 | pr_info("PF_BRIDGE: br_mdb_parse() with invalid attr\n"); | ||
304 | return -EINVAL; | ||
305 | } | ||
306 | |||
307 | entry = nla_data(tb[MDBA_SET_ENTRY]); | ||
308 | if (!is_valid_mdb_entry(entry)) { | ||
309 | pr_info("PF_BRIDGE: br_mdb_parse() with invalid entry\n"); | ||
310 | return -EINVAL; | ||
311 | } | ||
312 | |||
313 | *pentry = entry; | ||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | ||
318 | struct br_ip *group, unsigned char state) | ||
319 | { | ||
320 | struct net_bridge_mdb_entry *mp; | ||
321 | struct net_bridge_port_group *p; | ||
322 | struct net_bridge_port_group __rcu **pp; | ||
323 | struct net_bridge_mdb_htable *mdb; | ||
324 | int err; | ||
325 | |||
326 | mdb = mlock_dereference(br->mdb, br); | ||
327 | mp = br_mdb_ip_get(mdb, group); | ||
328 | if (!mp) { | ||
329 | mp = br_multicast_new_group(br, port, group); | ||
330 | err = PTR_ERR(mp); | ||
331 | if (IS_ERR(mp)) | ||
332 | return err; | ||
333 | } | ||
334 | |||
335 | for (pp = &mp->ports; | ||
336 | (p = mlock_dereference(*pp, br)) != NULL; | ||
337 | pp = &p->next) { | ||
338 | if (p->port == port) | ||
339 | return -EEXIST; | ||
340 | if ((unsigned long)p->port < (unsigned long)port) | ||
341 | break; | ||
342 | } | ||
343 | |||
344 | p = br_multicast_new_port_group(port, group, *pp, state); | ||
345 | if (unlikely(!p)) | ||
346 | return -ENOMEM; | ||
347 | rcu_assign_pointer(*pp, p); | ||
348 | |||
349 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB); | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int __br_mdb_add(struct net *net, struct net_bridge *br, | ||
354 | struct br_mdb_entry *entry) | ||
355 | { | ||
356 | struct br_ip ip; | ||
357 | struct net_device *dev; | ||
358 | struct net_bridge_port *p; | ||
359 | int ret; | ||
360 | |||
361 | if (!netif_running(br->dev) || br->multicast_disabled) | ||
362 | return -EINVAL; | ||
363 | |||
364 | dev = __dev_get_by_index(net, entry->ifindex); | ||
365 | if (!dev) | ||
366 | return -ENODEV; | ||
367 | |||
368 | p = br_port_get_rtnl(dev); | ||
369 | if (!p || p->br != br || p->state == BR_STATE_DISABLED) | ||
370 | return -EINVAL; | ||
371 | |||
372 | ip.proto = entry->addr.proto; | ||
373 | if (ip.proto == htons(ETH_P_IP)) | ||
374 | ip.u.ip4 = entry->addr.u.ip4; | ||
375 | #if IS_ENABLED(CONFIG_IPV6) | ||
376 | else | ||
377 | ip.u.ip6 = entry->addr.u.ip6; | ||
378 | #endif | ||
379 | |||
380 | spin_lock_bh(&br->multicast_lock); | ||
381 | ret = br_mdb_add_group(br, p, &ip, entry->state); | ||
382 | spin_unlock_bh(&br->multicast_lock); | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
387 | { | ||
388 | struct net *net = sock_net(skb->sk); | ||
389 | struct br_mdb_entry *entry; | ||
390 | struct net_device *dev; | ||
391 | struct net_bridge *br; | ||
392 | int err; | ||
393 | |||
394 | err = br_mdb_parse(skb, nlh, &dev, &entry); | ||
395 | if (err < 0) | ||
396 | return err; | ||
397 | |||
398 | br = netdev_priv(dev); | ||
399 | |||
400 | err = __br_mdb_add(net, br, entry); | ||
401 | if (!err) | ||
402 | __br_mdb_notify(dev, entry, RTM_NEWMDB); | ||
403 | return err; | ||
404 | } | ||
405 | |||
406 | static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | ||
407 | { | ||
408 | struct net_bridge_mdb_htable *mdb; | ||
409 | struct net_bridge_mdb_entry *mp; | ||
410 | struct net_bridge_port_group *p; | ||
411 | struct net_bridge_port_group __rcu **pp; | ||
412 | struct br_ip ip; | ||
413 | int err = -EINVAL; | ||
414 | |||
415 | if (!netif_running(br->dev) || br->multicast_disabled) | ||
416 | return -EINVAL; | ||
417 | |||
418 | if (timer_pending(&br->multicast_querier_timer)) | ||
419 | return -EBUSY; | ||
420 | |||
421 | ip.proto = entry->addr.proto; | ||
422 | if (ip.proto == htons(ETH_P_IP)) | ||
423 | ip.u.ip4 = entry->addr.u.ip4; | ||
424 | #if IS_ENABLED(CONFIG_IPV6) | ||
425 | else | ||
426 | ip.u.ip6 = entry->addr.u.ip6; | ||
427 | #endif | ||
428 | |||
429 | spin_lock_bh(&br->multicast_lock); | ||
430 | mdb = mlock_dereference(br->mdb, br); | ||
431 | |||
432 | mp = br_mdb_ip_get(mdb, &ip); | ||
433 | if (!mp) | ||
434 | goto unlock; | ||
435 | |||
436 | for (pp = &mp->ports; | ||
437 | (p = mlock_dereference(*pp, br)) != NULL; | ||
438 | pp = &p->next) { | ||
439 | if (!p->port || p->port->dev->ifindex != entry->ifindex) | ||
440 | continue; | ||
441 | |||
442 | if (p->port->state == BR_STATE_DISABLED) | ||
443 | goto unlock; | ||
444 | |||
445 | rcu_assign_pointer(*pp, p->next); | ||
446 | hlist_del_init(&p->mglist); | ||
447 | del_timer(&p->timer); | ||
448 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | ||
449 | err = 0; | ||
450 | |||
451 | if (!mp->ports && !mp->mglist && | ||
452 | netif_running(br->dev)) | ||
453 | mod_timer(&mp->timer, jiffies); | ||
454 | break; | ||
455 | } | ||
456 | |||
457 | unlock: | ||
458 | spin_unlock_bh(&br->multicast_lock); | ||
459 | return err; | ||
460 | } | ||
461 | |||
462 | static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
463 | { | ||
464 | struct net_device *dev; | ||
465 | struct br_mdb_entry *entry; | ||
466 | struct net_bridge *br; | ||
467 | int err; | ||
468 | |||
469 | err = br_mdb_parse(skb, nlh, &dev, &entry); | ||
470 | if (err < 0) | ||
471 | return err; | ||
472 | |||
473 | br = netdev_priv(dev); | ||
474 | |||
475 | err = __br_mdb_del(br, entry); | ||
476 | if (!err) | ||
477 | __br_mdb_notify(dev, entry, RTM_DELMDB); | ||
478 | return err; | ||
479 | } | ||
480 | |||
481 | void br_mdb_init(void) | ||
482 | { | ||
483 | rtnl_register(PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, NULL); | ||
484 | rtnl_register(PF_BRIDGE, RTM_NEWMDB, br_mdb_add, NULL, NULL); | ||
485 | rtnl_register(PF_BRIDGE, RTM_DELMDB, br_mdb_del, NULL, NULL); | ||
486 | } | ||
487 | |||
488 | void br_mdb_uninit(void) | ||
489 | { | ||
490 | rtnl_unregister(PF_BRIDGE, RTM_GETMDB); | ||
491 | rtnl_unregister(PF_BRIDGE, RTM_NEWMDB); | ||
492 | rtnl_unregister(PF_BRIDGE, RTM_DELMDB); | ||
493 | } | ||
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 6d6f26531de..e79ff75b0e7 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -24,16 +24,26 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
27 | #if IS_ENABLED(CONFIG_IPV6) | 27 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
28 | #include <net/ipv6.h> | 28 | #include <net/ipv6.h> |
29 | #include <net/mld.h> | 29 | #include <net/mld.h> |
30 | #include <net/addrconf.h> | ||
30 | #include <net/ip6_checksum.h> | 31 | #include <net/ip6_checksum.h> |
31 | #endif | 32 | #endif |
32 | 33 | ||
33 | #include "br_private.h" | 34 | #include "br_private.h" |
34 | 35 | ||
35 | static void br_multicast_start_querier(struct net_bridge *br); | 36 | #define mlock_dereference(X, br) \ |
36 | unsigned int br_mdb_rehash_seq; | 37 | rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) |
38 | |||
39 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
40 | static inline int ipv6_is_transient_multicast(const struct in6_addr *addr) | ||
41 | { | ||
42 | if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr)) | ||
43 | return 1; | ||
44 | return 0; | ||
45 | } | ||
46 | #endif | ||
37 | 47 | ||
38 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | 48 | static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) |
39 | { | 49 | { |
@@ -42,7 +52,7 @@ static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) | |||
42 | switch (a->proto) { | 52 | switch (a->proto) { |
43 | case htons(ETH_P_IP): | 53 | case htons(ETH_P_IP): |
44 | return a->u.ip4 == b->u.ip4; | 54 | return a->u.ip4 == b->u.ip4; |
45 | #if IS_ENABLED(CONFIG_IPV6) | 55 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
46 | case htons(ETH_P_IPV6): | 56 | case htons(ETH_P_IPV6): |
47 | return ipv6_addr_equal(&a->u.ip6, &b->u.ip6); | 57 | return ipv6_addr_equal(&a->u.ip6, &b->u.ip6); |
48 | #endif | 58 | #endif |
@@ -55,7 +65,7 @@ static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip) | |||
55 | return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); | 65 | return jhash_1word(mdb->secret, (__force u32)ip) & (mdb->max - 1); |
56 | } | 66 | } |
57 | 67 | ||
58 | #if IS_ENABLED(CONFIG_IPV6) | 68 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
59 | static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb, | 69 | static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb, |
60 | const struct in6_addr *ip) | 70 | const struct in6_addr *ip) |
61 | { | 71 | { |
@@ -69,7 +79,7 @@ static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb, | |||
69 | switch (ip->proto) { | 79 | switch (ip->proto) { |
70 | case htons(ETH_P_IP): | 80 | case htons(ETH_P_IP): |
71 | return __br_ip4_hash(mdb, ip->u.ip4); | 81 | return __br_ip4_hash(mdb, ip->u.ip4); |
72 | #if IS_ENABLED(CONFIG_IPV6) | 82 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
73 | case htons(ETH_P_IPV6): | 83 | case htons(ETH_P_IPV6): |
74 | return __br_ip6_hash(mdb, &ip->u.ip6); | 84 | return __br_ip6_hash(mdb, &ip->u.ip6); |
75 | #endif | 85 | #endif |
@@ -91,8 +101,8 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get( | |||
91 | return NULL; | 101 | return NULL; |
92 | } | 102 | } |
93 | 103 | ||
94 | struct net_bridge_mdb_entry *br_mdb_ip_get(struct net_bridge_mdb_htable *mdb, | 104 | static struct net_bridge_mdb_entry *br_mdb_ip_get( |
95 | struct br_ip *dst) | 105 | struct net_bridge_mdb_htable *mdb, struct br_ip *dst) |
96 | { | 106 | { |
97 | if (!mdb) | 107 | if (!mdb) |
98 | return NULL; | 108 | return NULL; |
@@ -111,13 +121,13 @@ static struct net_bridge_mdb_entry *br_mdb_ip4_get( | |||
111 | return br_mdb_ip_get(mdb, &br_dst); | 121 | return br_mdb_ip_get(mdb, &br_dst); |
112 | } | 122 | } |
113 | 123 | ||
114 | #if IS_ENABLED(CONFIG_IPV6) | 124 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
115 | static struct net_bridge_mdb_entry *br_mdb_ip6_get( | 125 | static struct net_bridge_mdb_entry *br_mdb_ip6_get( |
116 | struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst) | 126 | struct net_bridge_mdb_htable *mdb, const struct in6_addr *dst) |
117 | { | 127 | { |
118 | struct br_ip br_dst; | 128 | struct br_ip br_dst; |
119 | 129 | ||
120 | br_dst.u.ip6 = *dst; | 130 | ipv6_addr_copy(&br_dst.u.ip6, dst); |
121 | br_dst.proto = htons(ETH_P_IPV6); | 131 | br_dst.proto = htons(ETH_P_IPV6); |
122 | 132 | ||
123 | return br_mdb_ip_get(mdb, &br_dst); | 133 | return br_mdb_ip_get(mdb, &br_dst); |
@@ -142,9 +152,9 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br, | |||
142 | case htons(ETH_P_IP): | 152 | case htons(ETH_P_IP): |
143 | ip.u.ip4 = ip_hdr(skb)->daddr; | 153 | ip.u.ip4 = ip_hdr(skb)->daddr; |
144 | break; | 154 | break; |
145 | #if IS_ENABLED(CONFIG_IPV6) | 155 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
146 | case htons(ETH_P_IPV6): | 156 | case htons(ETH_P_IPV6): |
147 | ip.u.ip6 = ipv6_hdr(skb)->daddr; | 157 | ipv6_addr_copy(&ip.u.ip6, &ipv6_hdr(skb)->daddr); |
148 | break; | 158 | break; |
149 | #endif | 159 | #endif |
150 | default: | 160 | default: |
@@ -195,7 +205,7 @@ static int br_mdb_copy(struct net_bridge_mdb_htable *new, | |||
195 | return maxlen > elasticity ? -EINVAL : 0; | 205 | return maxlen > elasticity ? -EINVAL : 0; |
196 | } | 206 | } |
197 | 207 | ||
198 | void br_multicast_free_pg(struct rcu_head *head) | 208 | static void br_multicast_free_pg(struct rcu_head *head) |
199 | { | 209 | { |
200 | struct net_bridge_port_group *p = | 210 | struct net_bridge_port_group *p = |
201 | container_of(head, struct net_bridge_port_group, rcu); | 211 | container_of(head, struct net_bridge_port_group, rcu); |
@@ -231,6 +241,7 @@ static void br_multicast_group_expired(unsigned long data) | |||
231 | hlist_del_rcu(&mp->hlist[mdb->ver]); | 241 | hlist_del_rcu(&mp->hlist[mdb->ver]); |
232 | mdb->size--; | 242 | mdb->size--; |
233 | 243 | ||
244 | del_timer(&mp->query_timer); | ||
234 | call_rcu_bh(&mp->rcu, br_multicast_free_group); | 245 | call_rcu_bh(&mp->rcu, br_multicast_free_group); |
235 | 246 | ||
236 | out: | 247 | out: |
@@ -260,6 +271,7 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
260 | rcu_assign_pointer(*pp, p->next); | 271 | rcu_assign_pointer(*pp, p->next); |
261 | hlist_del_init(&p->mglist); | 272 | hlist_del_init(&p->mglist); |
262 | del_timer(&p->timer); | 273 | del_timer(&p->timer); |
274 | del_timer(&p->query_timer); | ||
263 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 275 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
264 | 276 | ||
265 | if (!mp->ports && !mp->mglist && | 277 | if (!mp->ports && !mp->mglist && |
@@ -279,7 +291,7 @@ static void br_multicast_port_group_expired(unsigned long data) | |||
279 | 291 | ||
280 | spin_lock(&br->multicast_lock); | 292 | spin_lock(&br->multicast_lock); |
281 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || | 293 | if (!netif_running(br->dev) || timer_pending(&pg->timer) || |
282 | hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT) | 294 | hlist_unhashed(&pg->mglist)) |
283 | goto out; | 295 | goto out; |
284 | 296 | ||
285 | br_multicast_del_pg(br, pg); | 297 | br_multicast_del_pg(br, pg); |
@@ -326,7 +338,6 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max, | |||
326 | return err; | 338 | return err; |
327 | } | 339 | } |
328 | 340 | ||
329 | br_mdb_rehash_seq++; | ||
330 | call_rcu_bh(&mdb->rcu, br_mdb_free); | 341 | call_rcu_bh(&mdb->rcu, br_mdb_free); |
331 | 342 | ||
332 | out: | 343 | out: |
@@ -400,7 +411,7 @@ out: | |||
400 | return skb; | 411 | return skb; |
401 | } | 412 | } |
402 | 413 | ||
403 | #if IS_ENABLED(CONFIG_IPV6) | 414 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
404 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | 415 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, |
405 | const struct in6_addr *group) | 416 | const struct in6_addr *group) |
406 | { | 417 | { |
@@ -435,11 +446,8 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
435 | ip6h->nexthdr = IPPROTO_HOPOPTS; | 446 | ip6h->nexthdr = IPPROTO_HOPOPTS; |
436 | ip6h->hop_limit = 1; | 447 | ip6h->hop_limit = 1; |
437 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); | 448 | ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1)); |
438 | if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, | 449 | ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0, |
439 | &ip6h->saddr)) { | 450 | &ip6h->saddr); |
440 | kfree_skb(skb); | ||
441 | return NULL; | ||
442 | } | ||
443 | ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); | 451 | ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); |
444 | 452 | ||
445 | hopopt = (u8 *)(ip6h + 1); | 453 | hopopt = (u8 *)(ip6h + 1); |
@@ -449,8 +457,8 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
449 | hopopt[3] = 2; /* Length of RA Option */ | 457 | hopopt[3] = 2; /* Length of RA Option */ |
450 | hopopt[4] = 0; /* Type = 0x0000 (MLD) */ | 458 | hopopt[4] = 0; /* Type = 0x0000 (MLD) */ |
451 | hopopt[5] = 0; | 459 | hopopt[5] = 0; |
452 | hopopt[6] = IPV6_TLV_PAD1; /* Pad1 */ | 460 | hopopt[6] = IPV6_TLV_PAD0; /* Pad0 */ |
453 | hopopt[7] = IPV6_TLV_PAD1; /* Pad1 */ | 461 | hopopt[7] = IPV6_TLV_PAD0; /* Pad0 */ |
454 | 462 | ||
455 | skb_put(skb, sizeof(*ip6h) + 8); | 463 | skb_put(skb, sizeof(*ip6h) + 8); |
456 | 464 | ||
@@ -466,7 +474,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
466 | mldq->mld_cksum = 0; | 474 | mldq->mld_cksum = 0; |
467 | mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval)); | 475 | mldq->mld_maxdelay = htons((u16)jiffies_to_msecs(interval)); |
468 | mldq->mld_reserved = 0; | 476 | mldq->mld_reserved = 0; |
469 | mldq->mld_mca = *group; | 477 | ipv6_addr_copy(&mldq->mld_mca, group); |
470 | 478 | ||
471 | /* checksum */ | 479 | /* checksum */ |
472 | mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, | 480 | mldq->mld_cksum = csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, |
@@ -488,7 +496,7 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | |||
488 | switch (addr->proto) { | 496 | switch (addr->proto) { |
489 | case htons(ETH_P_IP): | 497 | case htons(ETH_P_IP): |
490 | return br_ip4_multicast_alloc_query(br, addr->u.ip4); | 498 | return br_ip4_multicast_alloc_query(br, addr->u.ip4); |
491 | #if IS_ENABLED(CONFIG_IPV6) | 499 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
492 | case htons(ETH_P_IPV6): | 500 | case htons(ETH_P_IPV6): |
493 | return br_ip6_multicast_alloc_query(br, &addr->u.ip6); | 501 | return br_ip6_multicast_alloc_query(br, &addr->u.ip6); |
494 | #endif | 502 | #endif |
@@ -496,6 +504,74 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br, | |||
496 | return NULL; | 504 | return NULL; |
497 | } | 505 | } |
498 | 506 | ||
507 | static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp) | ||
508 | { | ||
509 | struct net_bridge *br = mp->br; | ||
510 | struct sk_buff *skb; | ||
511 | |||
512 | skb = br_multicast_alloc_query(br, &mp->addr); | ||
513 | if (!skb) | ||
514 | goto timer; | ||
515 | |||
516 | netif_rx(skb); | ||
517 | |||
518 | timer: | ||
519 | if (++mp->queries_sent < br->multicast_last_member_count) | ||
520 | mod_timer(&mp->query_timer, | ||
521 | jiffies + br->multicast_last_member_interval); | ||
522 | } | ||
523 | |||
524 | static void br_multicast_group_query_expired(unsigned long data) | ||
525 | { | ||
526 | struct net_bridge_mdb_entry *mp = (void *)data; | ||
527 | struct net_bridge *br = mp->br; | ||
528 | |||
529 | spin_lock(&br->multicast_lock); | ||
530 | if (!netif_running(br->dev) || !mp->mglist || | ||
531 | mp->queries_sent >= br->multicast_last_member_count) | ||
532 | goto out; | ||
533 | |||
534 | br_multicast_send_group_query(mp); | ||
535 | |||
536 | out: | ||
537 | spin_unlock(&br->multicast_lock); | ||
538 | } | ||
539 | |||
540 | static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg) | ||
541 | { | ||
542 | struct net_bridge_port *port = pg->port; | ||
543 | struct net_bridge *br = port->br; | ||
544 | struct sk_buff *skb; | ||
545 | |||
546 | skb = br_multicast_alloc_query(br, &pg->addr); | ||
547 | if (!skb) | ||
548 | goto timer; | ||
549 | |||
550 | br_deliver(port, skb); | ||
551 | |||
552 | timer: | ||
553 | if (++pg->queries_sent < br->multicast_last_member_count) | ||
554 | mod_timer(&pg->query_timer, | ||
555 | jiffies + br->multicast_last_member_interval); | ||
556 | } | ||
557 | |||
558 | static void br_multicast_port_group_query_expired(unsigned long data) | ||
559 | { | ||
560 | struct net_bridge_port_group *pg = (void *)data; | ||
561 | struct net_bridge_port *port = pg->port; | ||
562 | struct net_bridge *br = port->br; | ||
563 | |||
564 | spin_lock(&br->multicast_lock); | ||
565 | if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) || | ||
566 | pg->queries_sent >= br->multicast_last_member_count) | ||
567 | goto out; | ||
568 | |||
569 | br_multicast_send_port_group_query(pg); | ||
570 | |||
571 | out: | ||
572 | spin_unlock(&br->multicast_lock); | ||
573 | } | ||
574 | |||
499 | static struct net_bridge_mdb_entry *br_multicast_get_group( | 575 | static struct net_bridge_mdb_entry *br_multicast_get_group( |
500 | struct net_bridge *br, struct net_bridge_port *port, | 576 | struct net_bridge *br, struct net_bridge_port *port, |
501 | struct br_ip *group, int hash) | 577 | struct br_ip *group, int hash) |
@@ -503,8 +579,8 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
503 | struct net_bridge_mdb_htable *mdb; | 579 | struct net_bridge_mdb_htable *mdb; |
504 | struct net_bridge_mdb_entry *mp; | 580 | struct net_bridge_mdb_entry *mp; |
505 | struct hlist_node *p; | 581 | struct hlist_node *p; |
506 | unsigned int count = 0; | 582 | unsigned count = 0; |
507 | unsigned int max; | 583 | unsigned max; |
508 | int elasticity; | 584 | int elasticity; |
509 | int err; | 585 | int err; |
510 | 586 | ||
@@ -529,11 +605,10 @@ static struct net_bridge_mdb_entry *br_multicast_get_group( | |||
529 | 605 | ||
530 | if (mdb->size >= max) { | 606 | if (mdb->size >= max) { |
531 | max *= 2; | 607 | max *= 2; |
532 | if (unlikely(max > br->hash_max)) { | 608 | if (unlikely(max >= br->hash_max)) { |
533 | br_warn(br, "Multicast hash table maximum of %d " | 609 | br_warn(br, "Multicast hash table maximum " |
534 | "reached, disabling snooping: %s\n", | 610 | "reached, disabling snooping: %s, %d\n", |
535 | br->hash_max, | 611 | port ? port->dev->name : br->dev->name, max); |
536 | port ? port->dev->name : br->dev->name); | ||
537 | err = -E2BIG; | 612 | err = -E2BIG; |
538 | disable: | 613 | disable: |
539 | br->multicast_disabled = 1; | 614 | br->multicast_disabled = 1; |
@@ -571,8 +646,9 @@ err: | |||
571 | return mp; | 646 | return mp; |
572 | } | 647 | } |
573 | 648 | ||
574 | struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, | 649 | static struct net_bridge_mdb_entry *br_multicast_new_group( |
575 | struct net_bridge_port *port, struct br_ip *group) | 650 | struct net_bridge *br, struct net_bridge_port *port, |
651 | struct br_ip *group) | ||
576 | { | 652 | { |
577 | struct net_bridge_mdb_htable *mdb; | 653 | struct net_bridge_mdb_htable *mdb; |
578 | struct net_bridge_mdb_entry *mp; | 654 | struct net_bridge_mdb_entry *mp; |
@@ -611,6 +687,8 @@ rehash: | |||
611 | mp->addr = *group; | 687 | mp->addr = *group; |
612 | setup_timer(&mp->timer, br_multicast_group_expired, | 688 | setup_timer(&mp->timer, br_multicast_group_expired, |
613 | (unsigned long)mp); | 689 | (unsigned long)mp); |
690 | setup_timer(&mp->query_timer, br_multicast_group_query_expired, | ||
691 | (unsigned long)mp); | ||
614 | 692 | ||
615 | hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); | 693 | hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); |
616 | mdb->size++; | 694 | mdb->size++; |
@@ -619,28 +697,6 @@ out: | |||
619 | return mp; | 697 | return mp; |
620 | } | 698 | } |
621 | 699 | ||
622 | struct net_bridge_port_group *br_multicast_new_port_group( | ||
623 | struct net_bridge_port *port, | ||
624 | struct br_ip *group, | ||
625 | struct net_bridge_port_group __rcu *next, | ||
626 | unsigned char state) | ||
627 | { | ||
628 | struct net_bridge_port_group *p; | ||
629 | |||
630 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | ||
631 | if (unlikely(!p)) | ||
632 | return NULL; | ||
633 | |||
634 | p->addr = *group; | ||
635 | p->port = port; | ||
636 | p->state = state; | ||
637 | rcu_assign_pointer(p->next, next); | ||
638 | hlist_add_head(&p->mglist, &port->mglist); | ||
639 | setup_timer(&p->timer, br_multicast_port_group_expired, | ||
640 | (unsigned long)p); | ||
641 | return p; | ||
642 | } | ||
643 | |||
644 | static int br_multicast_add_group(struct net_bridge *br, | 700 | static int br_multicast_add_group(struct net_bridge *br, |
645 | struct net_bridge_port *port, | 701 | struct net_bridge_port *port, |
646 | struct br_ip *group) | 702 | struct br_ip *group) |
@@ -676,11 +732,21 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
676 | break; | 732 | break; |
677 | } | 733 | } |
678 | 734 | ||
679 | p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY); | 735 | p = kzalloc(sizeof(*p), GFP_ATOMIC); |
736 | err = -ENOMEM; | ||
680 | if (unlikely(!p)) | 737 | if (unlikely(!p)) |
681 | goto err; | 738 | goto err; |
739 | |||
740 | p->addr = *group; | ||
741 | p->port = port; | ||
742 | p->next = *pp; | ||
743 | hlist_add_head(&p->mglist, &port->mglist); | ||
744 | setup_timer(&p->timer, br_multicast_port_group_expired, | ||
745 | (unsigned long)p); | ||
746 | setup_timer(&p->query_timer, br_multicast_port_group_query_expired, | ||
747 | (unsigned long)p); | ||
748 | |||
682 | rcu_assign_pointer(*pp, p); | 749 | rcu_assign_pointer(*pp, p); |
683 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB); | ||
684 | 750 | ||
685 | found: | 751 | found: |
686 | mod_timer(&p->timer, now + br->multicast_membership_interval); | 752 | mod_timer(&p->timer, now + br->multicast_membership_interval); |
@@ -707,7 +773,7 @@ static int br_ip4_multicast_add_group(struct net_bridge *br, | |||
707 | return br_multicast_add_group(br, port, &br_group); | 773 | return br_multicast_add_group(br, port, &br_group); |
708 | } | 774 | } |
709 | 775 | ||
710 | #if IS_ENABLED(CONFIG_IPV6) | 776 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
711 | static int br_ip6_multicast_add_group(struct net_bridge *br, | 777 | static int br_ip6_multicast_add_group(struct net_bridge *br, |
712 | struct net_bridge_port *port, | 778 | struct net_bridge_port *port, |
713 | const struct in6_addr *group) | 779 | const struct in6_addr *group) |
@@ -717,7 +783,7 @@ static int br_ip6_multicast_add_group(struct net_bridge *br, | |||
717 | if (!ipv6_is_transient_multicast(group)) | 783 | if (!ipv6_is_transient_multicast(group)) |
718 | return 0; | 784 | return 0; |
719 | 785 | ||
720 | br_group.u.ip6 = *group; | 786 | ipv6_addr_copy(&br_group.u.ip6, group); |
721 | br_group.proto = htons(ETH_P_IPV6); | 787 | br_group.proto = htons(ETH_P_IPV6); |
722 | 788 | ||
723 | return br_multicast_add_group(br, port, &br_group); | 789 | return br_multicast_add_group(br, port, &br_group); |
@@ -745,20 +811,6 @@ static void br_multicast_local_router_expired(unsigned long data) | |||
745 | { | 811 | { |
746 | } | 812 | } |
747 | 813 | ||
748 | static void br_multicast_querier_expired(unsigned long data) | ||
749 | { | ||
750 | struct net_bridge *br = (void *)data; | ||
751 | |||
752 | spin_lock(&br->multicast_lock); | ||
753 | if (!netif_running(br->dev) || br->multicast_disabled) | ||
754 | goto out; | ||
755 | |||
756 | br_multicast_start_querier(br); | ||
757 | |||
758 | out: | ||
759 | spin_unlock(&br->multicast_lock); | ||
760 | } | ||
761 | |||
762 | static void __br_multicast_send_query(struct net_bridge *br, | 814 | static void __br_multicast_send_query(struct net_bridge *br, |
763 | struct net_bridge_port *port, | 815 | struct net_bridge_port *port, |
764 | struct br_ip *ip) | 816 | struct br_ip *ip) |
@@ -785,7 +837,6 @@ static void br_multicast_send_query(struct net_bridge *br, | |||
785 | struct br_ip br_group; | 837 | struct br_ip br_group; |
786 | 838 | ||
787 | if (!netif_running(br->dev) || br->multicast_disabled || | 839 | if (!netif_running(br->dev) || br->multicast_disabled || |
788 | !br->multicast_querier || | ||
789 | timer_pending(&br->multicast_querier_timer)) | 840 | timer_pending(&br->multicast_querier_timer)) |
790 | return; | 841 | return; |
791 | 842 | ||
@@ -794,7 +845,7 @@ static void br_multicast_send_query(struct net_bridge *br, | |||
794 | br_group.proto = htons(ETH_P_IP); | 845 | br_group.proto = htons(ETH_P_IP); |
795 | __br_multicast_send_query(br, port, &br_group); | 846 | __br_multicast_send_query(br, port, &br_group); |
796 | 847 | ||
797 | #if IS_ENABLED(CONFIG_IPV6) | 848 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
798 | br_group.proto = htons(ETH_P_IPV6); | 849 | br_group.proto = htons(ETH_P_IPV6); |
799 | __br_multicast_send_query(br, port, &br_group); | 850 | __br_multicast_send_query(br, port, &br_group); |
800 | #endif | 851 | #endif |
@@ -938,7 +989,7 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br, | |||
938 | return err; | 989 | return err; |
939 | } | 990 | } |
940 | 991 | ||
941 | #if IS_ENABLED(CONFIG_IPV6) | 992 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
942 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, | 993 | static int br_ip6_multicast_mld2_report(struct net_bridge *br, |
943 | struct net_bridge_port *port, | 994 | struct net_bridge_port *port, |
944 | struct sk_buff *skb) | 995 | struct sk_buff *skb) |
@@ -1134,13 +1185,13 @@ out: | |||
1134 | return err; | 1185 | return err; |
1135 | } | 1186 | } |
1136 | 1187 | ||
1137 | #if IS_ENABLED(CONFIG_IPV6) | 1188 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1138 | static int br_ip6_multicast_query(struct net_bridge *br, | 1189 | static int br_ip6_multicast_query(struct net_bridge *br, |
1139 | struct net_bridge_port *port, | 1190 | struct net_bridge_port *port, |
1140 | struct sk_buff *skb) | 1191 | struct sk_buff *skb) |
1141 | { | 1192 | { |
1142 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 1193 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
1143 | struct mld_msg *mld; | 1194 | struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); |
1144 | struct net_bridge_mdb_entry *mp; | 1195 | struct net_bridge_mdb_entry *mp; |
1145 | struct mld2_query *mld2q; | 1196 | struct mld2_query *mld2q; |
1146 | struct net_bridge_port_group *p; | 1197 | struct net_bridge_port_group *p; |
@@ -1163,7 +1214,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1163 | goto out; | 1214 | goto out; |
1164 | } | 1215 | } |
1165 | mld = (struct mld_msg *) icmp6_hdr(skb); | 1216 | mld = (struct mld_msg *) icmp6_hdr(skb); |
1166 | max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); | 1217 | max_delay = msecs_to_jiffies(htons(mld->mld_maxdelay)); |
1167 | if (max_delay) | 1218 | if (max_delay) |
1168 | group = &mld->mld_mca; | 1219 | group = &mld->mld_mca; |
1169 | } else if (skb->len >= sizeof(*mld2q)) { | 1220 | } else if (skb->len >= sizeof(*mld2q)) { |
@@ -1174,7 +1225,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1174 | mld2q = (struct mld2_query *)icmp6_hdr(skb); | 1225 | mld2q = (struct mld2_query *)icmp6_hdr(skb); |
1175 | if (!mld2q->mld2q_nsrcs) | 1226 | if (!mld2q->mld2q_nsrcs) |
1176 | group = &mld2q->mld2q_mca; | 1227 | group = &mld2q->mld2q_mca; |
1177 | max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1; | 1228 | max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1; |
1178 | } | 1229 | } |
1179 | 1230 | ||
1180 | if (!group) | 1231 | if (!group) |
@@ -1227,28 +1278,6 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1227 | if (!mp) | 1278 | if (!mp) |
1228 | goto out; | 1279 | goto out; |
1229 | 1280 | ||
1230 | if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) { | ||
1231 | struct net_bridge_port_group __rcu **pp; | ||
1232 | |||
1233 | for (pp = &mp->ports; | ||
1234 | (p = mlock_dereference(*pp, br)) != NULL; | ||
1235 | pp = &p->next) { | ||
1236 | if (p->port != port) | ||
1237 | continue; | ||
1238 | |||
1239 | rcu_assign_pointer(*pp, p->next); | ||
1240 | hlist_del_init(&p->mglist); | ||
1241 | del_timer(&p->timer); | ||
1242 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | ||
1243 | br_mdb_notify(br->dev, port, group, RTM_DELMDB); | ||
1244 | |||
1245 | if (!mp->ports && !mp->mglist && | ||
1246 | netif_running(br->dev)) | ||
1247 | mod_timer(&mp->timer, jiffies); | ||
1248 | } | ||
1249 | goto out; | ||
1250 | } | ||
1251 | |||
1252 | now = jiffies; | 1281 | now = jiffies; |
1253 | time = now + br->multicast_last_member_count * | 1282 | time = now + br->multicast_last_member_count * |
1254 | br->multicast_last_member_interval; | 1283 | br->multicast_last_member_interval; |
@@ -1259,6 +1288,9 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1259 | time_after(mp->timer.expires, time) : | 1288 | time_after(mp->timer.expires, time) : |
1260 | try_to_del_timer_sync(&mp->timer) >= 0)) { | 1289 | try_to_del_timer_sync(&mp->timer) >= 0)) { |
1261 | mod_timer(&mp->timer, time); | 1290 | mod_timer(&mp->timer, time); |
1291 | |||
1292 | mp->queries_sent = 0; | ||
1293 | mod_timer(&mp->query_timer, now); | ||
1262 | } | 1294 | } |
1263 | 1295 | ||
1264 | goto out; | 1296 | goto out; |
@@ -1275,6 +1307,9 @@ static void br_multicast_leave_group(struct net_bridge *br, | |||
1275 | time_after(p->timer.expires, time) : | 1307 | time_after(p->timer.expires, time) : |
1276 | try_to_del_timer_sync(&p->timer) >= 0)) { | 1308 | try_to_del_timer_sync(&p->timer) >= 0)) { |
1277 | mod_timer(&p->timer, time); | 1309 | mod_timer(&p->timer, time); |
1310 | |||
1311 | p->queries_sent = 0; | ||
1312 | mod_timer(&p->query_timer, now); | ||
1278 | } | 1313 | } |
1279 | 1314 | ||
1280 | break; | 1315 | break; |
@@ -1299,7 +1334,7 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br, | |||
1299 | br_multicast_leave_group(br, port, &br_group); | 1334 | br_multicast_leave_group(br, port, &br_group); |
1300 | } | 1335 | } |
1301 | 1336 | ||
1302 | #if IS_ENABLED(CONFIG_IPV6) | 1337 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1303 | static void br_ip6_multicast_leave_group(struct net_bridge *br, | 1338 | static void br_ip6_multicast_leave_group(struct net_bridge *br, |
1304 | struct net_bridge_port *port, | 1339 | struct net_bridge_port *port, |
1305 | const struct in6_addr *group) | 1340 | const struct in6_addr *group) |
@@ -1309,7 +1344,7 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br, | |||
1309 | if (!ipv6_is_transient_multicast(group)) | 1344 | if (!ipv6_is_transient_multicast(group)) |
1310 | return; | 1345 | return; |
1311 | 1346 | ||
1312 | br_group.u.ip6 = *group; | 1347 | ipv6_addr_copy(&br_group.u.ip6, group); |
1313 | br_group.proto = htons(ETH_P_IPV6); | 1348 | br_group.proto = htons(ETH_P_IPV6); |
1314 | 1349 | ||
1315 | br_multicast_leave_group(br, port, &br_group); | 1350 | br_multicast_leave_group(br, port, &br_group); |
@@ -1323,8 +1358,8 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1323 | struct sk_buff *skb2 = skb; | 1358 | struct sk_buff *skb2 = skb; |
1324 | const struct iphdr *iph; | 1359 | const struct iphdr *iph; |
1325 | struct igmphdr *ih; | 1360 | struct igmphdr *ih; |
1326 | unsigned int len; | 1361 | unsigned len; |
1327 | unsigned int offset; | 1362 | unsigned offset; |
1328 | int err; | 1363 | int err; |
1329 | 1364 | ||
1330 | /* We treat OOM as packet loss for now. */ | 1365 | /* We treat OOM as packet loss for now. */ |
@@ -1414,7 +1449,7 @@ err_out: | |||
1414 | return err; | 1449 | return err; |
1415 | } | 1450 | } |
1416 | 1451 | ||
1417 | #if IS_ENABLED(CONFIG_IPV6) | 1452 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1418 | static int br_multicast_ipv6_rcv(struct net_bridge *br, | 1453 | static int br_multicast_ipv6_rcv(struct net_bridge *br, |
1419 | struct net_bridge_port *port, | 1454 | struct net_bridge_port *port, |
1420 | struct sk_buff *skb) | 1455 | struct sk_buff *skb) |
@@ -1423,8 +1458,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1423 | const struct ipv6hdr *ip6h; | 1458 | const struct ipv6hdr *ip6h; |
1424 | u8 icmp6_type; | 1459 | u8 icmp6_type; |
1425 | u8 nexthdr; | 1460 | u8 nexthdr; |
1426 | __be16 frag_off; | 1461 | unsigned len; |
1427 | unsigned int len; | ||
1428 | int offset; | 1462 | int offset; |
1429 | int err; | 1463 | int err; |
1430 | 1464 | ||
@@ -1449,7 +1483,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1449 | return -EINVAL; | 1483 | return -EINVAL; |
1450 | 1484 | ||
1451 | nexthdr = ip6h->nexthdr; | 1485 | nexthdr = ip6h->nexthdr; |
1452 | offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr, &frag_off); | 1486 | offset = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nexthdr); |
1453 | 1487 | ||
1454 | if (offset < 0 || nexthdr != IPPROTO_ICMPV6) | 1488 | if (offset < 0 || nexthdr != IPPROTO_ICMPV6) |
1455 | return 0; | 1489 | return 0; |
@@ -1561,7 +1595,7 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port, | |||
1561 | switch (skb->protocol) { | 1595 | switch (skb->protocol) { |
1562 | case htons(ETH_P_IP): | 1596 | case htons(ETH_P_IP): |
1563 | return br_multicast_ipv4_rcv(br, port, skb); | 1597 | return br_multicast_ipv4_rcv(br, port, skb); |
1564 | #if IS_ENABLED(CONFIG_IPV6) | 1598 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
1565 | case htons(ETH_P_IPV6): | 1599 | case htons(ETH_P_IPV6): |
1566 | return br_multicast_ipv6_rcv(br, port, skb); | 1600 | return br_multicast_ipv6_rcv(br, port, skb); |
1567 | #endif | 1601 | #endif |
@@ -1590,7 +1624,6 @@ void br_multicast_init(struct net_bridge *br) | |||
1590 | br->hash_max = 512; | 1624 | br->hash_max = 512; |
1591 | 1625 | ||
1592 | br->multicast_router = 1; | 1626 | br->multicast_router = 1; |
1593 | br->multicast_querier = 0; | ||
1594 | br->multicast_last_member_count = 2; | 1627 | br->multicast_last_member_count = 2; |
1595 | br->multicast_startup_query_count = 2; | 1628 | br->multicast_startup_query_count = 2; |
1596 | 1629 | ||
@@ -1605,7 +1638,7 @@ void br_multicast_init(struct net_bridge *br) | |||
1605 | setup_timer(&br->multicast_router_timer, | 1638 | setup_timer(&br->multicast_router_timer, |
1606 | br_multicast_local_router_expired, 0); | 1639 | br_multicast_local_router_expired, 0); |
1607 | setup_timer(&br->multicast_querier_timer, | 1640 | setup_timer(&br->multicast_querier_timer, |
1608 | br_multicast_querier_expired, (unsigned long)br); | 1641 | br_multicast_local_router_expired, 0); |
1609 | setup_timer(&br->multicast_query_timer, br_multicast_query_expired, | 1642 | setup_timer(&br->multicast_query_timer, br_multicast_query_expired, |
1610 | (unsigned long)br); | 1643 | (unsigned long)br); |
1611 | } | 1644 | } |
@@ -1644,6 +1677,7 @@ void br_multicast_stop(struct net_bridge *br) | |||
1644 | hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], | 1677 | hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i], |
1645 | hlist[ver]) { | 1678 | hlist[ver]) { |
1646 | del_timer(&mp->timer); | 1679 | del_timer(&mp->timer); |
1680 | del_timer(&mp->query_timer); | ||
1647 | call_rcu_bh(&mp->rcu, br_multicast_free_group); | 1681 | call_rcu_bh(&mp->rcu, br_multicast_free_group); |
1648 | } | 1682 | } |
1649 | } | 1683 | } |
@@ -1732,27 +1766,13 @@ unlock: | |||
1732 | return err; | 1766 | return err; |
1733 | } | 1767 | } |
1734 | 1768 | ||
1735 | static void br_multicast_start_querier(struct net_bridge *br) | ||
1736 | { | ||
1737 | struct net_bridge_port *port; | ||
1738 | |||
1739 | br_multicast_open(br); | ||
1740 | |||
1741 | list_for_each_entry(port, &br->port_list, list) { | ||
1742 | if (port->state == BR_STATE_DISABLED || | ||
1743 | port->state == BR_STATE_BLOCKING) | ||
1744 | continue; | ||
1745 | |||
1746 | __br_multicast_enable_port(port); | ||
1747 | } | ||
1748 | } | ||
1749 | |||
1750 | int br_multicast_toggle(struct net_bridge *br, unsigned long val) | 1769 | int br_multicast_toggle(struct net_bridge *br, unsigned long val) |
1751 | { | 1770 | { |
1771 | struct net_bridge_port *port; | ||
1752 | int err = 0; | 1772 | int err = 0; |
1753 | struct net_bridge_mdb_htable *mdb; | 1773 | struct net_bridge_mdb_htable *mdb; |
1754 | 1774 | ||
1755 | spin_lock_bh(&br->multicast_lock); | 1775 | spin_lock(&br->multicast_lock); |
1756 | if (br->multicast_disabled == !val) | 1776 | if (br->multicast_disabled == !val) |
1757 | goto unlock; | 1777 | goto unlock; |
1758 | 1778 | ||
@@ -1778,30 +1798,19 @@ rollback: | |||
1778 | goto rollback; | 1798 | goto rollback; |
1779 | } | 1799 | } |
1780 | 1800 | ||
1781 | br_multicast_start_querier(br); | 1801 | br_multicast_open(br); |
1782 | 1802 | list_for_each_entry(port, &br->port_list, list) { | |
1783 | unlock: | 1803 | if (port->state == BR_STATE_DISABLED || |
1784 | spin_unlock_bh(&br->multicast_lock); | 1804 | port->state == BR_STATE_BLOCKING) |
1785 | 1805 | continue; | |
1786 | return err; | ||
1787 | } | ||
1788 | |||
1789 | int br_multicast_set_querier(struct net_bridge *br, unsigned long val) | ||
1790 | { | ||
1791 | val = !!val; | ||
1792 | |||
1793 | spin_lock_bh(&br->multicast_lock); | ||
1794 | if (br->multicast_querier == val) | ||
1795 | goto unlock; | ||
1796 | 1806 | ||
1797 | br->multicast_querier = val; | 1807 | __br_multicast_enable_port(port); |
1798 | if (val) | 1808 | } |
1799 | br_multicast_start_querier(br); | ||
1800 | 1809 | ||
1801 | unlock: | 1810 | unlock: |
1802 | spin_unlock_bh(&br->multicast_lock); | 1811 | spin_unlock(&br->multicast_lock); |
1803 | 1812 | ||
1804 | return 0; | 1813 | return err; |
1805 | } | 1814 | } |
1806 | 1815 | ||
1807 | int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) | 1816 | int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index fe43bc7b063..5693e5f9e03 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -54,25 +54,14 @@ static int brnf_call_ip6tables __read_mostly = 1; | |||
54 | static int brnf_call_arptables __read_mostly = 1; | 54 | static int brnf_call_arptables __read_mostly = 1; |
55 | static int brnf_filter_vlan_tagged __read_mostly = 0; | 55 | static int brnf_filter_vlan_tagged __read_mostly = 0; |
56 | static int brnf_filter_pppoe_tagged __read_mostly = 0; | 56 | static int brnf_filter_pppoe_tagged __read_mostly = 0; |
57 | static int brnf_pass_vlan_indev __read_mostly = 0; | ||
58 | #else | 57 | #else |
59 | #define brnf_call_iptables 1 | 58 | #define brnf_call_iptables 1 |
60 | #define brnf_call_ip6tables 1 | 59 | #define brnf_call_ip6tables 1 |
61 | #define brnf_call_arptables 1 | 60 | #define brnf_call_arptables 1 |
62 | #define brnf_filter_vlan_tagged 0 | 61 | #define brnf_filter_vlan_tagged 0 |
63 | #define brnf_filter_pppoe_tagged 0 | 62 | #define brnf_filter_pppoe_tagged 0 |
64 | #define brnf_pass_vlan_indev 0 | ||
65 | #endif | 63 | #endif |
66 | 64 | ||
67 | #define IS_IP(skb) \ | ||
68 | (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_IP)) | ||
69 | |||
70 | #define IS_IPV6(skb) \ | ||
71 | (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_IPV6)) | ||
72 | |||
73 | #define IS_ARP(skb) \ | ||
74 | (!vlan_tx_tag_present(skb) && skb->protocol == htons(ETH_P_ARP)) | ||
75 | |||
76 | static inline __be16 vlan_proto(const struct sk_buff *skb) | 65 | static inline __be16 vlan_proto(const struct sk_buff *skb) |
77 | { | 66 | { |
78 | if (vlan_tx_tag_present(skb)) | 67 | if (vlan_tx_tag_present(skb)) |
@@ -111,13 +100,7 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb) | |||
111 | pppoe_proto(skb) == htons(PPP_IPV6) && \ | 100 | pppoe_proto(skb) == htons(PPP_IPV6) && \ |
112 | brnf_filter_pppoe_tagged) | 101 | brnf_filter_pppoe_tagged) |
113 | 102 | ||
114 | static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk, | 103 | static void fake_update_pmtu(struct dst_entry *dst, u32 mtu) |
115 | struct sk_buff *skb, u32 mtu) | ||
116 | { | ||
117 | } | ||
118 | |||
119 | static void fake_redirect(struct dst_entry *dst, struct sock *sk, | ||
120 | struct sk_buff *skb) | ||
121 | { | 104 | { |
122 | } | 105 | } |
123 | 106 | ||
@@ -126,26 +109,17 @@ static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
126 | return NULL; | 109 | return NULL; |
127 | } | 110 | } |
128 | 111 | ||
129 | static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, | 112 | static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst, const void *daddr) |
130 | struct sk_buff *skb, | ||
131 | const void *daddr) | ||
132 | { | 113 | { |
133 | return NULL; | 114 | return NULL; |
134 | } | 115 | } |
135 | 116 | ||
136 | static unsigned int fake_mtu(const struct dst_entry *dst) | ||
137 | { | ||
138 | return dst->dev->mtu; | ||
139 | } | ||
140 | |||
141 | static struct dst_ops fake_dst_ops = { | 117 | static struct dst_ops fake_dst_ops = { |
142 | .family = AF_INET, | 118 | .family = AF_INET, |
143 | .protocol = cpu_to_be16(ETH_P_IP), | 119 | .protocol = cpu_to_be16(ETH_P_IP), |
144 | .update_pmtu = fake_update_pmtu, | 120 | .update_pmtu = fake_update_pmtu, |
145 | .redirect = fake_redirect, | ||
146 | .cow_metrics = fake_cow_metrics, | 121 | .cow_metrics = fake_cow_metrics, |
147 | .neigh_lookup = fake_neigh_lookup, | 122 | .neigh_lookup = fake_neigh_lookup, |
148 | .mtu = fake_mtu, | ||
149 | }; | 123 | }; |
150 | 124 | ||
151 | /* | 125 | /* |
@@ -167,7 +141,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) | |||
167 | rt->dst.dev = br->dev; | 141 | rt->dst.dev = br->dev; |
168 | rt->dst.path = &rt->dst; | 142 | rt->dst.path = &rt->dst; |
169 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); | 143 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); |
170 | rt->dst.flags = DST_NOXFRM | DST_NOPEER | DST_FAKE_RTABLE; | 144 | rt->dst.flags = DST_NOXFRM | DST_NOPEER; |
171 | rt->dst.ops = &fake_dst_ops; | 145 | rt->dst.ops = &fake_dst_ops; |
172 | } | 146 | } |
173 | 147 | ||
@@ -265,9 +239,6 @@ static int br_parse_ip_options(struct sk_buff *skb) | |||
265 | struct net_device *dev = skb->dev; | 239 | struct net_device *dev = skb->dev; |
266 | u32 len; | 240 | u32 len; |
267 | 241 | ||
268 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
269 | goto inhdr_error; | ||
270 | |||
271 | iph = ip_hdr(skb); | 242 | iph = ip_hdr(skb); |
272 | opt = &(IPCB(skb)->opt); | 243 | opt = &(IPCB(skb)->opt); |
273 | 244 | ||
@@ -385,29 +356,19 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | |||
385 | if (!skb->dev) | 356 | if (!skb->dev) |
386 | goto free_skb; | 357 | goto free_skb; |
387 | dst = skb_dst(skb); | 358 | dst = skb_dst(skb); |
388 | neigh = dst_neigh_lookup_skb(dst, skb); | 359 | neigh = dst_get_neighbour(dst); |
389 | if (neigh) { | 360 | if (neigh->hh.hh_len) { |
390 | int ret; | 361 | neigh_hh_bridge(&neigh->hh, skb); |
391 | 362 | skb->dev = nf_bridge->physindev; | |
392 | if (neigh->hh.hh_len) { | 363 | return br_handle_frame_finish(skb); |
393 | neigh_hh_bridge(&neigh->hh, skb); | 364 | } else { |
394 | skb->dev = nf_bridge->physindev; | 365 | /* the neighbour function below overwrites the complete |
395 | ret = br_handle_frame_finish(skb); | 366 | * MAC header, so we save the Ethernet source address and |
396 | } else { | 367 | * protocol number. */ |
397 | /* the neighbour function below overwrites the complete | 368 | skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN); |
398 | * MAC header, so we save the Ethernet source address and | 369 | /* tell br_dev_xmit to continue with forwarding */ |
399 | * protocol number. | 370 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; |
400 | */ | 371 | return neigh->output(neigh, skb); |
401 | skb_copy_from_linear_data_offset(skb, | ||
402 | -(ETH_HLEN-ETH_ALEN), | ||
403 | skb->nf_bridge->data, | ||
404 | ETH_HLEN-ETH_ALEN); | ||
405 | /* tell br_dev_xmit to continue with forwarding */ | ||
406 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | ||
407 | ret = neigh->output(neigh, skb); | ||
408 | } | ||
409 | neigh_release(neigh); | ||
410 | return ret; | ||
411 | } | 372 | } |
412 | free_skb: | 373 | free_skb: |
413 | kfree_skb(skb); | 374 | kfree_skb(skb); |
@@ -527,19 +488,6 @@ bridged_dnat: | |||
527 | return 0; | 488 | return 0; |
528 | } | 489 | } |
529 | 490 | ||
530 | static struct net_device *brnf_get_logical_dev(struct sk_buff *skb, const struct net_device *dev) | ||
531 | { | ||
532 | struct net_device *vlan, *br; | ||
533 | |||
534 | br = bridge_parent(dev); | ||
535 | if (brnf_pass_vlan_indev == 0 || !vlan_tx_tag_present(skb)) | ||
536 | return br; | ||
537 | |||
538 | vlan = __vlan_find_dev_deep(br, vlan_tx_tag_get(skb) & VLAN_VID_MASK); | ||
539 | |||
540 | return vlan ? vlan : br; | ||
541 | } | ||
542 | |||
543 | /* Some common code for IPv4/IPv6 */ | 491 | /* Some common code for IPv4/IPv6 */ |
544 | static struct net_device *setup_pre_routing(struct sk_buff *skb) | 492 | static struct net_device *setup_pre_routing(struct sk_buff *skb) |
545 | { | 493 | { |
@@ -552,7 +500,7 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb) | |||
552 | 500 | ||
553 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; | 501 | nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING; |
554 | nf_bridge->physindev = skb->dev; | 502 | nf_bridge->physindev = skb->dev; |
555 | skb->dev = brnf_get_logical_dev(skb, skb->dev); | 503 | skb->dev = bridge_parent(skb->dev); |
556 | if (skb->protocol == htons(ETH_P_8021Q)) | 504 | if (skb->protocol == htons(ETH_P_8021Q)) |
557 | nf_bridge->mask |= BRNF_8021Q; | 505 | nf_bridge->mask |= BRNF_8021Q; |
558 | else if (skb->protocol == htons(ETH_P_PPP_SES)) | 506 | else if (skb->protocol == htons(ETH_P_PPP_SES)) |
@@ -580,7 +528,7 @@ static int check_hbh_len(struct sk_buff *skb) | |||
580 | int optlen = nh[off + 1] + 2; | 528 | int optlen = nh[off + 1] + 2; |
581 | 529 | ||
582 | switch (nh[off]) { | 530 | switch (nh[off]) { |
583 | case IPV6_TLV_PAD1: | 531 | case IPV6_TLV_PAD0: |
584 | optlen = 1; | 532 | optlen = 1; |
585 | break; | 533 | break; |
586 | 534 | ||
@@ -685,7 +633,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, | |||
685 | return NF_DROP; | 633 | return NF_DROP; |
686 | br = p->br; | 634 | br = p->br; |
687 | 635 | ||
688 | if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) { | 636 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || |
637 | IS_PPPOE_IPV6(skb)) { | ||
689 | if (!brnf_call_ip6tables && !br->nf_call_ip6tables) | 638 | if (!brnf_call_ip6tables && !br->nf_call_ip6tables) |
690 | return NF_ACCEPT; | 639 | return NF_ACCEPT; |
691 | 640 | ||
@@ -696,7 +645,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff *skb, | |||
696 | if (!brnf_call_iptables && !br->nf_call_iptables) | 645 | if (!brnf_call_iptables && !br->nf_call_iptables) |
697 | return NF_ACCEPT; | 646 | return NF_ACCEPT; |
698 | 647 | ||
699 | if (!IS_IP(skb) && !IS_VLAN_IP(skb) && !IS_PPPOE_IP(skb)) | 648 | if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb) && |
649 | !IS_PPPOE_IP(skb)) | ||
700 | return NF_ACCEPT; | 650 | return NF_ACCEPT; |
701 | 651 | ||
702 | nf_bridge_pull_encap_header_rcsum(skb); | 652 | nf_bridge_pull_encap_header_rcsum(skb); |
@@ -731,7 +681,11 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb, | |||
731 | const struct net_device *out, | 681 | const struct net_device *out, |
732 | int (*okfn)(struct sk_buff *)) | 682 | int (*okfn)(struct sk_buff *)) |
733 | { | 683 | { |
734 | br_drop_fake_rtable(skb); | 684 | struct rtable *rt = skb_rtable(skb); |
685 | |||
686 | if (rt && rt == bridge_parent_rtable(in)) | ||
687 | skb_dst_drop(skb); | ||
688 | |||
735 | return NF_ACCEPT; | 689 | return NF_ACCEPT; |
736 | } | 690 | } |
737 | 691 | ||
@@ -741,7 +695,7 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
741 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 695 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
742 | struct net_device *in; | 696 | struct net_device *in; |
743 | 697 | ||
744 | if (!IS_ARP(skb) && !IS_VLAN_ARP(skb)) { | 698 | if (skb->protocol != htons(ETH_P_ARP) && !IS_VLAN_ARP(skb)) { |
745 | in = nf_bridge->physindev; | 699 | in = nf_bridge->physindev; |
746 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | 700 | if (nf_bridge->mask & BRNF_PKT_TYPE) { |
747 | skb->pkt_type = PACKET_OTHERHOST; | 701 | skb->pkt_type = PACKET_OTHERHOST; |
@@ -758,7 +712,6 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
758 | return 0; | 712 | return 0; |
759 | } | 713 | } |
760 | 714 | ||
761 | |||
762 | /* This is the 'purely bridged' case. For IP, we pass the packet to | 715 | /* This is the 'purely bridged' case. For IP, we pass the packet to |
763 | * netfilter with indev and outdev set to the bridge device, | 716 | * netfilter with indev and outdev set to the bridge device, |
764 | * but we are still able to filter on the 'real' indev/outdev | 717 | * but we are still able to filter on the 'real' indev/outdev |
@@ -785,10 +738,12 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
785 | if (!parent) | 738 | if (!parent) |
786 | return NF_DROP; | 739 | return NF_DROP; |
787 | 740 | ||
788 | if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb)) | 741 | if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) || |
789 | pf = NFPROTO_IPV4; | 742 | IS_PPPOE_IP(skb)) |
790 | else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) | 743 | pf = PF_INET; |
791 | pf = NFPROTO_IPV6; | 744 | else if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || |
745 | IS_PPPOE_IPV6(skb)) | ||
746 | pf = PF_INET6; | ||
792 | else | 747 | else |
793 | return NF_ACCEPT; | 748 | return NF_ACCEPT; |
794 | 749 | ||
@@ -800,18 +755,18 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb, | |||
800 | nf_bridge->mask |= BRNF_PKT_TYPE; | 755 | nf_bridge->mask |= BRNF_PKT_TYPE; |
801 | } | 756 | } |
802 | 757 | ||
803 | if (pf == NFPROTO_IPV4 && br_parse_ip_options(skb)) | 758 | if (pf == PF_INET && br_parse_ip_options(skb)) |
804 | return NF_DROP; | 759 | return NF_DROP; |
805 | 760 | ||
806 | /* The physdev module checks on this */ | 761 | /* The physdev module checks on this */ |
807 | nf_bridge->mask |= BRNF_BRIDGED; | 762 | nf_bridge->mask |= BRNF_BRIDGED; |
808 | nf_bridge->physoutdev = skb->dev; | 763 | nf_bridge->physoutdev = skb->dev; |
809 | if (pf == NFPROTO_IPV4) | 764 | if (pf == PF_INET) |
810 | skb->protocol = htons(ETH_P_IP); | 765 | skb->protocol = htons(ETH_P_IP); |
811 | else | 766 | else |
812 | skb->protocol = htons(ETH_P_IPV6); | 767 | skb->protocol = htons(ETH_P_IPV6); |
813 | 768 | ||
814 | NF_HOOK(pf, NF_INET_FORWARD, skb, brnf_get_logical_dev(skb, in), parent, | 769 | NF_HOOK(pf, NF_INET_FORWARD, skb, bridge_parent(in), parent, |
815 | br_nf_forward_finish); | 770 | br_nf_forward_finish); |
816 | 771 | ||
817 | return NF_STOLEN; | 772 | return NF_STOLEN; |
@@ -834,7 +789,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, | |||
834 | if (!brnf_call_arptables && !br->nf_call_arptables) | 789 | if (!brnf_call_arptables && !br->nf_call_arptables) |
835 | return NF_ACCEPT; | 790 | return NF_ACCEPT; |
836 | 791 | ||
837 | if (!IS_ARP(skb)) { | 792 | if (skb->protocol != htons(ETH_P_ARP)) { |
838 | if (!IS_VLAN_ARP(skb)) | 793 | if (!IS_VLAN_ARP(skb)) |
839 | return NF_ACCEPT; | 794 | return NF_ACCEPT; |
840 | nf_bridge_pull_encap_header(skb); | 795 | nf_bridge_pull_encap_header(skb); |
@@ -852,7 +807,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb, | |||
852 | return NF_STOLEN; | 807 | return NF_STOLEN; |
853 | } | 808 | } |
854 | 809 | ||
855 | #if IS_ENABLED(CONFIG_NF_CONNTRACK_IPV4) | 810 | #if defined(CONFIG_NF_CONNTRACK_IPV4) || defined(CONFIG_NF_CONNTRACK_IPV4_MODULE) |
856 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) | 811 | static int br_nf_dev_queue_xmit(struct sk_buff *skb) |
857 | { | 812 | { |
858 | int ret; | 813 | int ret; |
@@ -892,10 +847,12 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
892 | if (!realoutdev) | 847 | if (!realoutdev) |
893 | return NF_DROP; | 848 | return NF_DROP; |
894 | 849 | ||
895 | if (IS_IP(skb) || IS_VLAN_IP(skb) || IS_PPPOE_IP(skb)) | 850 | if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb) || |
896 | pf = NFPROTO_IPV4; | 851 | IS_PPPOE_IP(skb)) |
897 | else if (IS_IPV6(skb) || IS_VLAN_IPV6(skb) || IS_PPPOE_IPV6(skb)) | 852 | pf = PF_INET; |
898 | pf = NFPROTO_IPV6; | 853 | else if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) || |
854 | IS_PPPOE_IPV6(skb)) | ||
855 | pf = PF_INET6; | ||
899 | else | 856 | else |
900 | return NF_ACCEPT; | 857 | return NF_ACCEPT; |
901 | 858 | ||
@@ -908,7 +865,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
908 | 865 | ||
909 | nf_bridge_pull_encap_header(skb); | 866 | nf_bridge_pull_encap_header(skb); |
910 | nf_bridge_save_header(skb); | 867 | nf_bridge_save_header(skb); |
911 | if (pf == NFPROTO_IPV4) | 868 | if (pf == PF_INET) |
912 | skb->protocol = htons(ETH_P_IP); | 869 | skb->protocol = htons(ETH_P_IP); |
913 | else | 870 | else |
914 | skb->protocol = htons(ETH_P_IPV6); | 871 | skb->protocol = htons(ETH_P_IPV6); |
@@ -941,49 +898,49 @@ static struct nf_hook_ops br_nf_ops[] __read_mostly = { | |||
941 | { | 898 | { |
942 | .hook = br_nf_pre_routing, | 899 | .hook = br_nf_pre_routing, |
943 | .owner = THIS_MODULE, | 900 | .owner = THIS_MODULE, |
944 | .pf = NFPROTO_BRIDGE, | 901 | .pf = PF_BRIDGE, |
945 | .hooknum = NF_BR_PRE_ROUTING, | 902 | .hooknum = NF_BR_PRE_ROUTING, |
946 | .priority = NF_BR_PRI_BRNF, | 903 | .priority = NF_BR_PRI_BRNF, |
947 | }, | 904 | }, |
948 | { | 905 | { |
949 | .hook = br_nf_local_in, | 906 | .hook = br_nf_local_in, |
950 | .owner = THIS_MODULE, | 907 | .owner = THIS_MODULE, |
951 | .pf = NFPROTO_BRIDGE, | 908 | .pf = PF_BRIDGE, |
952 | .hooknum = NF_BR_LOCAL_IN, | 909 | .hooknum = NF_BR_LOCAL_IN, |
953 | .priority = NF_BR_PRI_BRNF, | 910 | .priority = NF_BR_PRI_BRNF, |
954 | }, | 911 | }, |
955 | { | 912 | { |
956 | .hook = br_nf_forward_ip, | 913 | .hook = br_nf_forward_ip, |
957 | .owner = THIS_MODULE, | 914 | .owner = THIS_MODULE, |
958 | .pf = NFPROTO_BRIDGE, | 915 | .pf = PF_BRIDGE, |
959 | .hooknum = NF_BR_FORWARD, | 916 | .hooknum = NF_BR_FORWARD, |
960 | .priority = NF_BR_PRI_BRNF - 1, | 917 | .priority = NF_BR_PRI_BRNF - 1, |
961 | }, | 918 | }, |
962 | { | 919 | { |
963 | .hook = br_nf_forward_arp, | 920 | .hook = br_nf_forward_arp, |
964 | .owner = THIS_MODULE, | 921 | .owner = THIS_MODULE, |
965 | .pf = NFPROTO_BRIDGE, | 922 | .pf = PF_BRIDGE, |
966 | .hooknum = NF_BR_FORWARD, | 923 | .hooknum = NF_BR_FORWARD, |
967 | .priority = NF_BR_PRI_BRNF, | 924 | .priority = NF_BR_PRI_BRNF, |
968 | }, | 925 | }, |
969 | { | 926 | { |
970 | .hook = br_nf_post_routing, | 927 | .hook = br_nf_post_routing, |
971 | .owner = THIS_MODULE, | 928 | .owner = THIS_MODULE, |
972 | .pf = NFPROTO_BRIDGE, | 929 | .pf = PF_BRIDGE, |
973 | .hooknum = NF_BR_POST_ROUTING, | 930 | .hooknum = NF_BR_POST_ROUTING, |
974 | .priority = NF_BR_PRI_LAST, | 931 | .priority = NF_BR_PRI_LAST, |
975 | }, | 932 | }, |
976 | { | 933 | { |
977 | .hook = ip_sabotage_in, | 934 | .hook = ip_sabotage_in, |
978 | .owner = THIS_MODULE, | 935 | .owner = THIS_MODULE, |
979 | .pf = NFPROTO_IPV4, | 936 | .pf = PF_INET, |
980 | .hooknum = NF_INET_PRE_ROUTING, | 937 | .hooknum = NF_INET_PRE_ROUTING, |
981 | .priority = NF_IP_PRI_FIRST, | 938 | .priority = NF_IP_PRI_FIRST, |
982 | }, | 939 | }, |
983 | { | 940 | { |
984 | .hook = ip_sabotage_in, | 941 | .hook = ip_sabotage_in, |
985 | .owner = THIS_MODULE, | 942 | .owner = THIS_MODULE, |
986 | .pf = NFPROTO_IPV6, | 943 | .pf = PF_INET6, |
987 | .hooknum = NF_INET_PRE_ROUTING, | 944 | .hooknum = NF_INET_PRE_ROUTING, |
988 | .priority = NF_IP6_PRI_FIRST, | 945 | .priority = NF_IP6_PRI_FIRST, |
989 | }, | 946 | }, |
@@ -1039,13 +996,12 @@ static ctl_table brnf_table[] = { | |||
1039 | .mode = 0644, | 996 | .mode = 0644, |
1040 | .proc_handler = brnf_sysctl_call_tables, | 997 | .proc_handler = brnf_sysctl_call_tables, |
1041 | }, | 998 | }, |
1042 | { | 999 | { } |
1043 | .procname = "bridge-nf-pass-vlan-input-dev", | 1000 | }; |
1044 | .data = &brnf_pass_vlan_indev, | 1001 | |
1045 | .maxlen = sizeof(int), | 1002 | static struct ctl_path brnf_path[] = { |
1046 | .mode = 0644, | 1003 | { .procname = "net", }, |
1047 | .proc_handler = brnf_sysctl_call_tables, | 1004 | { .procname = "bridge", }, |
1048 | }, | ||
1049 | { } | 1005 | { } |
1050 | }; | 1006 | }; |
1051 | #endif | 1007 | #endif |
@@ -1064,7 +1020,7 @@ int __init br_netfilter_init(void) | |||
1064 | return ret; | 1020 | return ret; |
1065 | } | 1021 | } |
1066 | #ifdef CONFIG_SYSCTL | 1022 | #ifdef CONFIG_SYSCTL |
1067 | brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); | 1023 | brnf_sysctl_header = register_sysctl_paths(brnf_path, brnf_table); |
1068 | if (brnf_sysctl_header == NULL) { | 1024 | if (brnf_sysctl_header == NULL) { |
1069 | printk(KERN_WARNING | 1025 | printk(KERN_WARNING |
1070 | "br_netfilter: can't register to sysctl.\n"); | 1026 | "br_netfilter: can't register to sysctl.\n"); |
@@ -1081,7 +1037,7 @@ void br_netfilter_fini(void) | |||
1081 | { | 1037 | { |
1082 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); | 1038 | nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); |
1083 | #ifdef CONFIG_SYSCTL | 1039 | #ifdef CONFIG_SYSCTL |
1084 | unregister_net_sysctl_table(brnf_sysctl_header); | 1040 | unregister_sysctl_table(brnf_sysctl_header); |
1085 | #endif | 1041 | #endif |
1086 | dst_entries_destroy(&fake_dst_ops); | 1042 | dst_entries_destroy(&fake_dst_ops); |
1087 | } | 1043 | } |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 5dc66abcc9e..e5f9ece3c9a 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -18,46 +18,17 @@ | |||
18 | #include <net/sock.h> | 18 | #include <net/sock.h> |
19 | 19 | ||
20 | #include "br_private.h" | 20 | #include "br_private.h" |
21 | #include "br_private_stp.h" | ||
22 | |||
23 | static inline size_t br_port_info_size(void) | ||
24 | { | ||
25 | return nla_total_size(1) /* IFLA_BRPORT_STATE */ | ||
26 | + nla_total_size(2) /* IFLA_BRPORT_PRIORITY */ | ||
27 | + nla_total_size(4) /* IFLA_BRPORT_COST */ | ||
28 | + nla_total_size(1) /* IFLA_BRPORT_MODE */ | ||
29 | + nla_total_size(1) /* IFLA_BRPORT_GUARD */ | ||
30 | + nla_total_size(1) /* IFLA_BRPORT_PROTECT */ | ||
31 | + 0; | ||
32 | } | ||
33 | 21 | ||
34 | static inline size_t br_nlmsg_size(void) | 22 | static inline size_t br_nlmsg_size(void) |
35 | { | 23 | { |
36 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 24 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
37 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | 25 | + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ |
38 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | 26 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ |
39 | + nla_total_size(4) /* IFLA_MASTER */ | 27 | + nla_total_size(4) /* IFLA_MASTER */ |
40 | + nla_total_size(4) /* IFLA_MTU */ | 28 | + nla_total_size(4) /* IFLA_MTU */ |
41 | + nla_total_size(4) /* IFLA_LINK */ | 29 | + nla_total_size(4) /* IFLA_LINK */ |
42 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 30 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
43 | + nla_total_size(br_port_info_size()); /* IFLA_PROTINFO */ | 31 | + nla_total_size(1); /* IFLA_PROTINFO */ |
44 | } | ||
45 | |||
46 | static int br_port_fill_attrs(struct sk_buff *skb, | ||
47 | const struct net_bridge_port *p) | ||
48 | { | ||
49 | u8 mode = !!(p->flags & BR_HAIRPIN_MODE); | ||
50 | |||
51 | if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) || | ||
52 | nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) || | ||
53 | nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) || | ||
54 | nla_put_u8(skb, IFLA_BRPORT_MODE, mode) || | ||
55 | nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) || | ||
56 | nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) || | ||
57 | nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE))) | ||
58 | return -EMSGSIZE; | ||
59 | |||
60 | return 0; | ||
61 | } | 32 | } |
62 | 33 | ||
63 | /* | 34 | /* |
@@ -88,24 +59,19 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por | |||
88 | hdr->ifi_flags = dev_get_flags(dev); | 59 | hdr->ifi_flags = dev_get_flags(dev); |
89 | hdr->ifi_change = 0; | 60 | hdr->ifi_change = 0; |
90 | 61 | ||
91 | if (nla_put_string(skb, IFLA_IFNAME, dev->name) || | 62 | NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); |
92 | nla_put_u32(skb, IFLA_MASTER, br->dev->ifindex) || | 63 | NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex); |
93 | nla_put_u32(skb, IFLA_MTU, dev->mtu) || | 64 | NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); |
94 | nla_put_u8(skb, IFLA_OPERSTATE, operstate) || | 65 | NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate); |
95 | (dev->addr_len && | 66 | |
96 | nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) || | 67 | if (dev->addr_len) |
97 | (dev->ifindex != dev->iflink && | 68 | NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); |
98 | nla_put_u32(skb, IFLA_LINK, dev->iflink))) | 69 | |
99 | goto nla_put_failure; | 70 | if (dev->ifindex != dev->iflink) |
100 | 71 | NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); | |
101 | if (event == RTM_NEWLINK) { | 72 | |
102 | struct nlattr *nest | 73 | if (event == RTM_NEWLINK) |
103 | = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED); | 74 | NLA_PUT_U8(skb, IFLA_PROTINFO, port->state); |
104 | |||
105 | if (nest == NULL || br_port_fill_attrs(skb, port) < 0) | ||
106 | goto nla_put_failure; | ||
107 | nla_nest_end(skb, nest); | ||
108 | } | ||
109 | 75 | ||
110 | return nlmsg_end(skb, nlh); | 76 | return nlmsg_end(skb, nlh); |
111 | 77 | ||
@@ -124,7 +90,7 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port) | |||
124 | int err = -ENOBUFS; | 90 | int err = -ENOBUFS; |
125 | 91 | ||
126 | br_debug(port->br, "port %u(%s) event %d\n", | 92 | br_debug(port->br, "port %u(%s) event %d\n", |
127 | (unsigned int)port->port_no, port->dev->name, event); | 93 | (unsigned)port->port_no, port->dev->name, event); |
128 | 94 | ||
129 | skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); | 95 | skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); |
130 | if (skb == NULL) | 96 | if (skb == NULL) |
@@ -147,134 +113,84 @@ errout: | |||
147 | /* | 113 | /* |
148 | * Dump information about all ports, in response to GETLINK | 114 | * Dump information about all ports, in response to GETLINK |
149 | */ | 115 | */ |
150 | int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | 116 | static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
151 | struct net_device *dev) | ||
152 | { | ||
153 | int err = 0; | ||
154 | struct net_bridge_port *port = br_port_get_rcu(dev); | ||
155 | |||
156 | /* not a bridge port */ | ||
157 | if (!port) | ||
158 | goto out; | ||
159 | |||
160 | err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI); | ||
161 | out: | ||
162 | return err; | ||
163 | } | ||
164 | |||
165 | static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = { | ||
166 | [IFLA_BRPORT_STATE] = { .type = NLA_U8 }, | ||
167 | [IFLA_BRPORT_COST] = { .type = NLA_U32 }, | ||
168 | [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 }, | ||
169 | [IFLA_BRPORT_MODE] = { .type = NLA_U8 }, | ||
170 | [IFLA_BRPORT_GUARD] = { .type = NLA_U8 }, | ||
171 | [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 }, | ||
172 | }; | ||
173 | |||
174 | /* Change the state of the port and notify spanning tree */ | ||
175 | static int br_set_port_state(struct net_bridge_port *p, u8 state) | ||
176 | { | ||
177 | if (state > BR_STATE_BLOCKING) | ||
178 | return -EINVAL; | ||
179 | |||
180 | /* if kernel STP is running, don't allow changes */ | ||
181 | if (p->br->stp_enabled == BR_KERNEL_STP) | ||
182 | return -EBUSY; | ||
183 | |||
184 | if (!netif_running(p->dev) || | ||
185 | (!netif_carrier_ok(p->dev) && state != BR_STATE_DISABLED)) | ||
186 | return -ENETDOWN; | ||
187 | |||
188 | p->state = state; | ||
189 | br_log_state(p); | ||
190 | br_port_state_selection(p->br); | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | /* Set/clear or port flags based on attribute */ | ||
195 | static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[], | ||
196 | int attrtype, unsigned long mask) | ||
197 | { | 117 | { |
198 | if (tb[attrtype]) { | 118 | struct net *net = sock_net(skb->sk); |
199 | u8 flag = nla_get_u8(tb[attrtype]); | 119 | struct net_device *dev; |
200 | if (flag) | 120 | int idx; |
201 | p->flags |= mask; | 121 | |
202 | else | 122 | idx = 0; |
203 | p->flags &= ~mask; | 123 | rcu_read_lock(); |
124 | for_each_netdev_rcu(net, dev) { | ||
125 | struct net_bridge_port *port = br_port_get_rcu(dev); | ||
126 | |||
127 | /* not a bridge port */ | ||
128 | if (!port || idx < cb->args[0]) | ||
129 | goto skip; | ||
130 | |||
131 | if (br_fill_ifinfo(skb, port, | ||
132 | NETLINK_CB(cb->skb).pid, | ||
133 | cb->nlh->nlmsg_seq, RTM_NEWLINK, | ||
134 | NLM_F_MULTI) < 0) | ||
135 | break; | ||
136 | skip: | ||
137 | ++idx; | ||
204 | } | 138 | } |
205 | } | 139 | rcu_read_unlock(); |
140 | cb->args[0] = idx; | ||
206 | 141 | ||
207 | /* Process bridge protocol info on port */ | 142 | return skb->len; |
208 | static int br_setport(struct net_bridge_port *p, struct nlattr *tb[]) | ||
209 | { | ||
210 | int err; | ||
211 | |||
212 | br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE); | ||
213 | br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD); | ||
214 | br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE); | ||
215 | |||
216 | if (tb[IFLA_BRPORT_COST]) { | ||
217 | err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST])); | ||
218 | if (err) | ||
219 | return err; | ||
220 | } | ||
221 | |||
222 | if (tb[IFLA_BRPORT_PRIORITY]) { | ||
223 | err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY])); | ||
224 | if (err) | ||
225 | return err; | ||
226 | } | ||
227 | |||
228 | if (tb[IFLA_BRPORT_STATE]) { | ||
229 | err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE])); | ||
230 | if (err) | ||
231 | return err; | ||
232 | } | ||
233 | return 0; | ||
234 | } | 143 | } |
235 | 144 | ||
236 | /* Change state and parameters on port. */ | 145 | /* |
237 | int br_setlink(struct net_device *dev, struct nlmsghdr *nlh) | 146 | * Change state of port (ie from forwarding to blocking etc) |
147 | * Used by spanning tree in user space. | ||
148 | */ | ||
149 | static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
238 | { | 150 | { |
151 | struct net *net = sock_net(skb->sk); | ||
239 | struct ifinfomsg *ifm; | 152 | struct ifinfomsg *ifm; |
240 | struct nlattr *protinfo; | 153 | struct nlattr *protinfo; |
154 | struct net_device *dev; | ||
241 | struct net_bridge_port *p; | 155 | struct net_bridge_port *p; |
242 | struct nlattr *tb[IFLA_BRPORT_MAX + 1]; | 156 | u8 new_state; |
243 | int err; | 157 | |
158 | if (nlmsg_len(nlh) < sizeof(*ifm)) | ||
159 | return -EINVAL; | ||
244 | 160 | ||
245 | ifm = nlmsg_data(nlh); | 161 | ifm = nlmsg_data(nlh); |
162 | if (ifm->ifi_family != AF_BRIDGE) | ||
163 | return -EPFNOSUPPORT; | ||
246 | 164 | ||
247 | protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); | 165 | protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); |
248 | if (!protinfo) | 166 | if (!protinfo || nla_len(protinfo) < sizeof(u8)) |
249 | return 0; | 167 | return -EINVAL; |
168 | |||
169 | new_state = nla_get_u8(protinfo); | ||
170 | if (new_state > BR_STATE_BLOCKING) | ||
171 | return -EINVAL; | ||
172 | |||
173 | dev = __dev_get_by_index(net, ifm->ifi_index); | ||
174 | if (!dev) | ||
175 | return -ENODEV; | ||
250 | 176 | ||
251 | p = br_port_get_rtnl(dev); | 177 | p = br_port_get_rtnl(dev); |
252 | if (!p) | 178 | if (!p) |
253 | return -EINVAL; | 179 | return -EINVAL; |
254 | 180 | ||
255 | if (protinfo->nla_type & NLA_F_NESTED) { | 181 | /* if kernel STP is running, don't allow changes */ |
256 | err = nla_parse_nested(tb, IFLA_BRPORT_MAX, | 182 | if (p->br->stp_enabled == BR_KERNEL_STP) |
257 | protinfo, ifla_brport_policy); | 183 | return -EBUSY; |
258 | if (err) | ||
259 | return err; | ||
260 | |||
261 | spin_lock_bh(&p->br->lock); | ||
262 | err = br_setport(p, tb); | ||
263 | spin_unlock_bh(&p->br->lock); | ||
264 | } else { | ||
265 | /* Binary compatability with old RSTP */ | ||
266 | if (nla_len(protinfo) < sizeof(u8)) | ||
267 | return -EINVAL; | ||
268 | 184 | ||
269 | spin_lock_bh(&p->br->lock); | 185 | if (!netif_running(dev) || |
270 | err = br_set_port_state(p, nla_get_u8(protinfo)); | 186 | (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)) |
271 | spin_unlock_bh(&p->br->lock); | 187 | return -ENETDOWN; |
272 | } | ||
273 | 188 | ||
274 | if (err == 0) | 189 | p->state = new_state; |
275 | br_ifinfo_notify(RTM_NEWLINK, p); | 190 | br_log_state(p); |
191 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
276 | 192 | ||
277 | return err; | 193 | return 0; |
278 | } | 194 | } |
279 | 195 | ||
280 | static int br_validate(struct nlattr *tb[], struct nlattr *data[]) | 196 | static int br_validate(struct nlattr *tb[], struct nlattr *data[]) |
@@ -289,7 +205,7 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
289 | return 0; | 205 | return 0; |
290 | } | 206 | } |
291 | 207 | ||
292 | struct rtnl_link_ops br_link_ops __read_mostly = { | 208 | static struct rtnl_link_ops br_link_ops __read_mostly = { |
293 | .kind = "bridge", | 209 | .kind = "bridge", |
294 | .priv_size = sizeof(struct net_bridge), | 210 | .priv_size = sizeof(struct net_bridge), |
295 | .setup = br_dev_setup, | 211 | .setup = br_dev_setup, |
@@ -301,19 +217,43 @@ int __init br_netlink_init(void) | |||
301 | { | 217 | { |
302 | int err; | 218 | int err; |
303 | 219 | ||
304 | br_mdb_init(); | ||
305 | err = rtnl_link_register(&br_link_ops); | 220 | err = rtnl_link_register(&br_link_ops); |
221 | if (err < 0) | ||
222 | goto err1; | ||
223 | |||
224 | err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, | ||
225 | br_dump_ifinfo, NULL); | ||
226 | if (err) | ||
227 | goto err2; | ||
228 | err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, | ||
229 | br_rtm_setlink, NULL, NULL); | ||
230 | if (err) | ||
231 | goto err3; | ||
232 | err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, | ||
233 | br_fdb_add, NULL, NULL); | ||
306 | if (err) | 234 | if (err) |
307 | goto out; | 235 | goto err3; |
236 | err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, | ||
237 | br_fdb_delete, NULL, NULL); | ||
238 | if (err) | ||
239 | goto err3; | ||
240 | err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, | ||
241 | NULL, br_fdb_dump, NULL); | ||
242 | if (err) | ||
243 | goto err3; | ||
308 | 244 | ||
309 | return 0; | 245 | return 0; |
310 | out: | 246 | |
311 | br_mdb_uninit(); | 247 | err3: |
248 | rtnl_unregister_all(PF_BRIDGE); | ||
249 | err2: | ||
250 | rtnl_link_unregister(&br_link_ops); | ||
251 | err1: | ||
312 | return err; | 252 | return err; |
313 | } | 253 | } |
314 | 254 | ||
315 | void __exit br_netlink_fini(void) | 255 | void __exit br_netlink_fini(void) |
316 | { | 256 | { |
317 | br_mdb_uninit(); | ||
318 | rtnl_link_unregister(&br_link_ops); | 257 | rtnl_link_unregister(&br_link_ops); |
258 | rtnl_unregister_all(PF_BRIDGE); | ||
319 | } | 259 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 711094aed41..857a021deea 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -29,11 +29,6 @@ | |||
29 | 29 | ||
30 | #define BR_VERSION "2.3" | 30 | #define BR_VERSION "2.3" |
31 | 31 | ||
32 | /* Control of forwarding link local multicast */ | ||
33 | #define BR_GROUPFWD_DEFAULT 0 | ||
34 | /* Don't allow forwarding control protocols like STP and LLDP */ | ||
35 | #define BR_GROUPFWD_RESTRICTED 0x4007u | ||
36 | |||
37 | /* Path to usermode spanning tree program */ | 32 | /* Path to usermode spanning tree program */ |
38 | #define BR_STP_PROG "/sbin/bridge-stp" | 33 | #define BR_STP_PROG "/sbin/bridge-stp" |
39 | 34 | ||
@@ -56,7 +51,7 @@ struct br_ip | |||
56 | { | 51 | { |
57 | union { | 52 | union { |
58 | __be32 ip4; | 53 | __be32 ip4; |
59 | #if IS_ENABLED(CONFIG_IPV6) | 54 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
60 | struct in6_addr ip6; | 55 | struct in6_addr ip6; |
61 | #endif | 56 | #endif |
62 | } u; | 57 | } u; |
@@ -82,8 +77,9 @@ struct net_bridge_port_group { | |||
82 | struct hlist_node mglist; | 77 | struct hlist_node mglist; |
83 | struct rcu_head rcu; | 78 | struct rcu_head rcu; |
84 | struct timer_list timer; | 79 | struct timer_list timer; |
80 | struct timer_list query_timer; | ||
85 | struct br_ip addr; | 81 | struct br_ip addr; |
86 | unsigned char state; | 82 | u32 queries_sent; |
87 | }; | 83 | }; |
88 | 84 | ||
89 | struct net_bridge_mdb_entry | 85 | struct net_bridge_mdb_entry |
@@ -93,8 +89,10 @@ struct net_bridge_mdb_entry | |||
93 | struct net_bridge_port_group __rcu *ports; | 89 | struct net_bridge_port_group __rcu *ports; |
94 | struct rcu_head rcu; | 90 | struct rcu_head rcu; |
95 | struct timer_list timer; | 91 | struct timer_list timer; |
92 | struct timer_list query_timer; | ||
96 | struct br_ip addr; | 93 | struct br_ip addr; |
97 | bool mglist; | 94 | bool mglist; |
95 | u32 queries_sent; | ||
98 | }; | 96 | }; |
99 | 97 | ||
100 | struct net_bridge_mdb_htable | 98 | struct net_bridge_mdb_htable |
@@ -136,9 +134,6 @@ struct net_bridge_port | |||
136 | 134 | ||
137 | unsigned long flags; | 135 | unsigned long flags; |
138 | #define BR_HAIRPIN_MODE 0x00000001 | 136 | #define BR_HAIRPIN_MODE 0x00000001 |
139 | #define BR_BPDU_GUARD 0x00000002 | ||
140 | #define BR_ROOT_BLOCK 0x00000004 | ||
141 | #define BR_MULTICAST_FAST_LEAVE 0x00000008 | ||
142 | 137 | ||
143 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | 138 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
144 | u32 multicast_startup_queries_sent; | 139 | u32 multicast_startup_queries_sent; |
@@ -162,9 +157,7 @@ struct net_bridge_port | |||
162 | 157 | ||
163 | static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) | 158 | static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev) |
164 | { | 159 | { |
165 | struct net_bridge_port *port = | 160 | struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data); |
166 | rcu_dereference_rtnl(dev->rx_handler_data); | ||
167 | |||
168 | return br_port_exists(dev) ? port : NULL; | 161 | return br_port_exists(dev) ? port : NULL; |
169 | } | 162 | } |
170 | 163 | ||
@@ -200,8 +193,6 @@ struct net_bridge | |||
200 | unsigned long flags; | 193 | unsigned long flags; |
201 | #define BR_SET_MAC_ADDR 0x00000001 | 194 | #define BR_SET_MAC_ADDR 0x00000001 |
202 | 195 | ||
203 | u16 group_fwd_mask; | ||
204 | |||
205 | /* STP */ | 196 | /* STP */ |
206 | bridge_id designated_root; | 197 | bridge_id designated_root; |
207 | bridge_id bridge_id; | 198 | bridge_id bridge_id; |
@@ -230,7 +221,6 @@ struct net_bridge | |||
230 | unsigned char multicast_router; | 221 | unsigned char multicast_router; |
231 | 222 | ||
232 | u8 multicast_disabled:1; | 223 | u8 multicast_disabled:1; |
233 | u8 multicast_querier:1; | ||
234 | 224 | ||
235 | u32 hash_elasticity; | 225 | u32 hash_elasticity; |
236 | u32 hash_max; | 226 | u32 hash_max; |
@@ -294,6 +284,7 @@ struct br_input_skb_cb { | |||
294 | pr_debug("%s: " format, (br)->dev->name, ##args) | 284 | pr_debug("%s: " format, (br)->dev->name, ##args) |
295 | 285 | ||
296 | extern struct notifier_block br_device_notifier; | 286 | extern struct notifier_block br_device_notifier; |
287 | extern const u8 br_group_address[ETH_ALEN]; | ||
297 | 288 | ||
298 | /* called under bridge lock */ | 289 | /* called under bridge lock */ |
299 | static inline int br_is_root_bridge(const struct net_bridge *br) | 290 | static inline int br_is_root_bridge(const struct net_bridge *br) |
@@ -321,7 +312,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
321 | netpoll_send_skb(np, skb); | 312 | netpoll_send_skb(np, skb); |
322 | } | 313 | } |
323 | 314 | ||
324 | extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); | 315 | extern int br_netpoll_enable(struct net_bridge_port *p); |
325 | extern void br_netpoll_disable(struct net_bridge_port *p); | 316 | extern void br_netpoll_disable(struct net_bridge_port *p); |
326 | #else | 317 | #else |
327 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) | 318 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) |
@@ -334,7 +325,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
334 | { | 325 | { |
335 | } | 326 | } |
336 | 327 | ||
337 | static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | 328 | static inline int br_netpoll_enable(struct net_bridge_port *p) |
338 | { | 329 | { |
339 | return 0; | 330 | return 0; |
340 | } | 331 | } |
@@ -350,7 +341,6 @@ extern void br_fdb_fini(void); | |||
350 | extern void br_fdb_flush(struct net_bridge *br); | 341 | extern void br_fdb_flush(struct net_bridge *br); |
351 | extern void br_fdb_changeaddr(struct net_bridge_port *p, | 342 | extern void br_fdb_changeaddr(struct net_bridge_port *p, |
352 | const unsigned char *newaddr); | 343 | const unsigned char *newaddr); |
353 | extern void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr); | ||
354 | extern void br_fdb_cleanup(unsigned long arg); | 344 | extern void br_fdb_cleanup(unsigned long arg); |
355 | extern void br_fdb_delete_by_port(struct net_bridge *br, | 345 | extern void br_fdb_delete_by_port(struct net_bridge *br, |
356 | const struct net_bridge_port *p, int do_all); | 346 | const struct net_bridge_port *p, int do_all); |
@@ -365,18 +355,9 @@ extern int br_fdb_insert(struct net_bridge *br, | |||
365 | extern void br_fdb_update(struct net_bridge *br, | 355 | extern void br_fdb_update(struct net_bridge *br, |
366 | struct net_bridge_port *source, | 356 | struct net_bridge_port *source, |
367 | const unsigned char *addr); | 357 | const unsigned char *addr); |
368 | 358 | extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb); | |
369 | extern int br_fdb_delete(struct ndmsg *ndm, | 359 | extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); |
370 | struct net_device *dev, | 360 | extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); |
371 | const unsigned char *addr); | ||
372 | extern int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], | ||
373 | struct net_device *dev, | ||
374 | const unsigned char *addr, | ||
375 | u16 nlh_flags); | ||
376 | extern int br_fdb_dump(struct sk_buff *skb, | ||
377 | struct netlink_callback *cb, | ||
378 | struct net_device *dev, | ||
379 | int idx); | ||
380 | 361 | ||
381 | /* br_forward.c */ | 362 | /* br_forward.c */ |
382 | extern void br_deliver(const struct net_bridge_port *to, | 363 | extern void br_deliver(const struct net_bridge_port *to, |
@@ -399,8 +380,7 @@ extern int br_add_if(struct net_bridge *br, | |||
399 | extern int br_del_if(struct net_bridge *br, | 380 | extern int br_del_if(struct net_bridge *br, |
400 | struct net_device *dev); | 381 | struct net_device *dev); |
401 | extern int br_min_mtu(const struct net_bridge *br); | 382 | extern int br_min_mtu(const struct net_bridge *br); |
402 | extern netdev_features_t br_features_recompute(struct net_bridge *br, | 383 | extern u32 br_features_recompute(struct net_bridge *br, u32 features); |
403 | netdev_features_t features); | ||
404 | 384 | ||
405 | /* br_input.c */ | 385 | /* br_input.c */ |
406 | extern int br_handle_frame_finish(struct sk_buff *skb); | 386 | extern int br_handle_frame_finish(struct sk_buff *skb); |
@@ -412,7 +392,6 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us | |||
412 | 392 | ||
413 | /* br_multicast.c */ | 393 | /* br_multicast.c */ |
414 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | 394 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
415 | extern unsigned int br_mdb_rehash_seq; | ||
416 | extern int br_multicast_rcv(struct net_bridge *br, | 395 | extern int br_multicast_rcv(struct net_bridge *br, |
417 | struct net_bridge_port *port, | 396 | struct net_bridge_port *port, |
418 | struct sk_buff *skb); | 397 | struct sk_buff *skb); |
@@ -433,36 +412,7 @@ extern int br_multicast_set_router(struct net_bridge *br, unsigned long val); | |||
433 | extern int br_multicast_set_port_router(struct net_bridge_port *p, | 412 | extern int br_multicast_set_port_router(struct net_bridge_port *p, |
434 | unsigned long val); | 413 | unsigned long val); |
435 | extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); | 414 | extern int br_multicast_toggle(struct net_bridge *br, unsigned long val); |
436 | extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val); | ||
437 | extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); | 415 | extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val); |
438 | extern struct net_bridge_mdb_entry *br_mdb_ip_get( | ||
439 | struct net_bridge_mdb_htable *mdb, | ||
440 | struct br_ip *dst); | ||
441 | extern struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br, | ||
442 | struct net_bridge_port *port, struct br_ip *group); | ||
443 | extern void br_multicast_free_pg(struct rcu_head *head); | ||
444 | extern struct net_bridge_port_group *br_multicast_new_port_group( | ||
445 | struct net_bridge_port *port, | ||
446 | struct br_ip *group, | ||
447 | struct net_bridge_port_group *next, | ||
448 | unsigned char state); | ||
449 | extern void br_mdb_init(void); | ||
450 | extern void br_mdb_uninit(void); | ||
451 | extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, | ||
452 | struct br_ip *group, int type); | ||
453 | |||
454 | #define mlock_dereference(X, br) \ | ||
455 | rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) | ||
456 | |||
457 | #if IS_ENABLED(CONFIG_IPV6) | ||
458 | #include <net/addrconf.h> | ||
459 | static inline int ipv6_is_transient_multicast(const struct in6_addr *addr) | ||
460 | { | ||
461 | if (ipv6_addr_is_multicast(addr) && IPV6_ADDR_MC_FLAG_TRANSIENT(addr)) | ||
462 | return 1; | ||
463 | return 0; | ||
464 | } | ||
465 | #endif | ||
466 | 416 | ||
467 | static inline bool br_multicast_is_router(struct net_bridge *br) | 417 | static inline bool br_multicast_is_router(struct net_bridge *br) |
468 | { | 418 | { |
@@ -526,12 +476,6 @@ static inline bool br_multicast_is_router(struct net_bridge *br) | |||
526 | { | 476 | { |
527 | return 0; | 477 | return 0; |
528 | } | 478 | } |
529 | static inline void br_mdb_init(void) | ||
530 | { | ||
531 | } | ||
532 | static inline void br_mdb_uninit(void) | ||
533 | { | ||
534 | } | ||
535 | #endif | 479 | #endif |
536 | 480 | ||
537 | /* br_netfilter.c */ | 481 | /* br_netfilter.c */ |
@@ -584,18 +528,14 @@ extern void br_stp_port_timer_init(struct net_bridge_port *p); | |||
584 | extern unsigned long br_timer_value(const struct timer_list *timer); | 528 | extern unsigned long br_timer_value(const struct timer_list *timer); |
585 | 529 | ||
586 | /* br.c */ | 530 | /* br.c */ |
587 | #if IS_ENABLED(CONFIG_ATM_LANE) | 531 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
588 | extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); | 532 | extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); |
589 | #endif | 533 | #endif |
590 | 534 | ||
591 | /* br_netlink.c */ | 535 | /* br_netlink.c */ |
592 | extern struct rtnl_link_ops br_link_ops; | ||
593 | extern int br_netlink_init(void); | 536 | extern int br_netlink_init(void); |
594 | extern void br_netlink_fini(void); | 537 | extern void br_netlink_fini(void); |
595 | extern void br_ifinfo_notify(int event, struct net_bridge_port *port); | 538 | extern void br_ifinfo_notify(int event, struct net_bridge_port *port); |
596 | extern int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg); | ||
597 | extern int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | ||
598 | struct net_device *dev); | ||
599 | 539 | ||
600 | #ifdef CONFIG_SYSFS | 540 | #ifdef CONFIG_SYSFS |
601 | /* br_sysfs_if.c */ | 541 | /* br_sysfs_if.c */ |
@@ -609,10 +549,10 @@ extern void br_sysfs_delbr(struct net_device *dev); | |||
609 | 549 | ||
610 | #else | 550 | #else |
611 | 551 | ||
612 | static inline int br_sysfs_addif(struct net_bridge_port *p) { return 0; } | 552 | #define br_sysfs_addif(p) (0) |
613 | static inline int br_sysfs_renameif(struct net_bridge_port *p) { return 0; } | 553 | #define br_sysfs_renameif(p) (0) |
614 | static inline int br_sysfs_addbr(struct net_device *dev) { return 0; } | 554 | #define br_sysfs_addbr(dev) (0) |
615 | static inline void br_sysfs_delbr(struct net_device *dev) { return; } | 555 | #define br_sysfs_delbr(dev) do { } while(0) |
616 | #endif /* CONFIG_SYSFS */ | 556 | #endif /* CONFIG_SYSFS */ |
617 | 557 | ||
618 | #endif | 558 | #endif |
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 0c0fe36e7aa..05ed9bc7e42 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h | |||
@@ -29,9 +29,10 @@ | |||
29 | #define BR_MIN_PATH_COST 1 | 29 | #define BR_MIN_PATH_COST 1 |
30 | #define BR_MAX_PATH_COST 65535 | 30 | #define BR_MAX_PATH_COST 65535 |
31 | 31 | ||
32 | struct br_config_bpdu { | 32 | struct br_config_bpdu |
33 | unsigned int topology_change:1; | 33 | { |
34 | unsigned int topology_change_ack:1; | 34 | unsigned topology_change:1; |
35 | unsigned topology_change_ack:1; | ||
35 | bridge_id root; | 36 | bridge_id root; |
36 | int root_path_cost; | 37 | int root_path_cost; |
37 | bridge_id bridge_id; | 38 | bridge_id bridge_id; |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index b01849a7431..ad0a3f7cf6c 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -17,9 +17,9 @@ | |||
17 | #include "br_private_stp.h" | 17 | #include "br_private_stp.h" |
18 | 18 | ||
19 | /* since time values in bpdu are in jiffies and then scaled (1/256) | 19 | /* since time values in bpdu are in jiffies and then scaled (1/256) |
20 | * before sending, make sure that is at least one STP tick. | 20 | * before sending, make sure that is at least one. |
21 | */ | 21 | */ |
22 | #define MESSAGE_AGE_INCR ((HZ / 256) + 1) | 22 | #define MESSAGE_AGE_INCR ((HZ < 256) ? 1 : (HZ/256)) |
23 | 23 | ||
24 | static const char *const br_port_state_names[] = { | 24 | static const char *const br_port_state_names[] = { |
25 | [BR_STATE_DISABLED] = "disabled", | 25 | [BR_STATE_DISABLED] = "disabled", |
@@ -31,8 +31,8 @@ static const char *const br_port_state_names[] = { | |||
31 | 31 | ||
32 | void br_log_state(const struct net_bridge_port *p) | 32 | void br_log_state(const struct net_bridge_port *p) |
33 | { | 33 | { |
34 | br_info(p->br, "port %u(%s) entered %s state\n", | 34 | br_info(p->br, "port %u(%s) entering %s state\n", |
35 | (unsigned int) p->port_no, p->dev->name, | 35 | (unsigned) p->port_no, p->dev->name, |
36 | br_port_state_names[p->state]); | 36 | br_port_state_names[p->state]); |
37 | } | 37 | } |
38 | 38 | ||
@@ -100,21 +100,6 @@ static int br_should_become_root_port(const struct net_bridge_port *p, | |||
100 | return 0; | 100 | return 0; |
101 | } | 101 | } |
102 | 102 | ||
103 | static void br_root_port_block(const struct net_bridge *br, | ||
104 | struct net_bridge_port *p) | ||
105 | { | ||
106 | |||
107 | br_notice(br, "port %u(%s) tried to become root port (blocked)", | ||
108 | (unsigned int) p->port_no, p->dev->name); | ||
109 | |||
110 | p->state = BR_STATE_LISTENING; | ||
111 | br_log_state(p); | ||
112 | br_ifinfo_notify(RTM_NEWLINK, p); | ||
113 | |||
114 | if (br->forward_delay > 0) | ||
115 | mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay); | ||
116 | } | ||
117 | |||
118 | /* called under bridge lock */ | 103 | /* called under bridge lock */ |
119 | static void br_root_selection(struct net_bridge *br) | 104 | static void br_root_selection(struct net_bridge *br) |
120 | { | 105 | { |
@@ -122,12 +107,7 @@ static void br_root_selection(struct net_bridge *br) | |||
122 | u16 root_port = 0; | 107 | u16 root_port = 0; |
123 | 108 | ||
124 | list_for_each_entry(p, &br->port_list, list) { | 109 | list_for_each_entry(p, &br->port_list, list) { |
125 | if (!br_should_become_root_port(p, root_port)) | 110 | if (br_should_become_root_port(p, root_port)) |
126 | continue; | ||
127 | |||
128 | if (p->flags & BR_ROOT_BLOCK) | ||
129 | br_root_port_block(br, p); | ||
130 | else | ||
131 | root_port = p->port_no; | 111 | root_port = p->port_no; |
132 | } | 112 | } |
133 | 113 | ||
@@ -206,7 +186,7 @@ static void br_record_config_information(struct net_bridge_port *p, | |||
206 | p->designated_cost = bpdu->root_path_cost; | 186 | p->designated_cost = bpdu->root_path_cost; |
207 | p->designated_bridge = bpdu->bridge_id; | 187 | p->designated_bridge = bpdu->bridge_id; |
208 | p->designated_port = bpdu->port_id; | 188 | p->designated_port = bpdu->port_id; |
209 | p->designated_age = jiffies - bpdu->message_age; | 189 | p->designated_age = jiffies + bpdu->message_age; |
210 | 190 | ||
211 | mod_timer(&p->message_age_timer, jiffies | 191 | mod_timer(&p->message_age_timer, jiffies |
212 | + (p->br->max_age - bpdu->message_age)); | 192 | + (p->br->max_age - bpdu->message_age)); |
@@ -419,24 +399,25 @@ void br_port_state_selection(struct net_bridge *br) | |||
419 | struct net_bridge_port *p; | 399 | struct net_bridge_port *p; |
420 | unsigned int liveports = 0; | 400 | unsigned int liveports = 0; |
421 | 401 | ||
402 | /* Don't change port states if userspace is handling STP */ | ||
403 | if (br->stp_enabled == BR_USER_STP) | ||
404 | return; | ||
405 | |||
422 | list_for_each_entry(p, &br->port_list, list) { | 406 | list_for_each_entry(p, &br->port_list, list) { |
423 | if (p->state == BR_STATE_DISABLED) | 407 | if (p->state == BR_STATE_DISABLED) |
424 | continue; | 408 | continue; |
425 | 409 | ||
426 | /* Don't change port states if userspace is handling STP */ | 410 | if (p->port_no == br->root_port) { |
427 | if (br->stp_enabled != BR_USER_STP) { | 411 | p->config_pending = 0; |
428 | if (p->port_no == br->root_port) { | 412 | p->topology_change_ack = 0; |
429 | p->config_pending = 0; | 413 | br_make_forwarding(p); |
430 | p->topology_change_ack = 0; | 414 | } else if (br_is_designated_port(p)) { |
431 | br_make_forwarding(p); | 415 | del_timer(&p->message_age_timer); |
432 | } else if (br_is_designated_port(p)) { | 416 | br_make_forwarding(p); |
433 | del_timer(&p->message_age_timer); | 417 | } else { |
434 | br_make_forwarding(p); | 418 | p->config_pending = 0; |
435 | } else { | 419 | p->topology_change_ack = 0; |
436 | p->config_pending = 0; | 420 | br_make_blocking(p); |
437 | p->topology_change_ack = 0; | ||
438 | br_make_blocking(p); | ||
439 | } | ||
440 | } | 421 | } |
441 | 422 | ||
442 | if (p->state == BR_STATE_FORWARDING) | 423 | if (p->state == BR_STATE_FORWARDING) |
@@ -498,7 +479,7 @@ void br_received_tcn_bpdu(struct net_bridge_port *p) | |||
498 | { | 479 | { |
499 | if (br_is_designated_port(p)) { | 480 | if (br_is_designated_port(p)) { |
500 | br_info(p->br, "port %u(%s) received tcn bpdu\n", | 481 | br_info(p->br, "port %u(%s) received tcn bpdu\n", |
501 | (unsigned int) p->port_no, p->dev->name); | 482 | (unsigned) p->port_no, p->dev->name); |
502 | 483 | ||
503 | br_topology_change_detection(p->br); | 484 | br_topology_change_detection(p->br); |
504 | br_topology_change_acknowledge(p); | 485 | br_topology_change_acknowledge(p); |
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 7f884e3fb95..e16aade51ae 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c | |||
@@ -167,16 +167,9 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, | |||
167 | if (p->state == BR_STATE_DISABLED) | 167 | if (p->state == BR_STATE_DISABLED) |
168 | goto out; | 168 | goto out; |
169 | 169 | ||
170 | if (!ether_addr_equal(dest, br->group_addr)) | 170 | if (compare_ether_addr(dest, br->group_addr) != 0) |
171 | goto out; | 171 | goto out; |
172 | 172 | ||
173 | if (p->flags & BR_BPDU_GUARD) { | ||
174 | br_notice(br, "BPDU received on blocked port %u(%s)\n", | ||
175 | (unsigned int) p->port_no, p->dev->name); | ||
176 | br_stp_disable_port(p); | ||
177 | goto out; | ||
178 | } | ||
179 | |||
180 | buf = skb_pull(skb, 3); | 173 | buf = skb_pull(skb, 3); |
181 | 174 | ||
182 | if (buf[0] == BPDU_TYPE_CONFIG) { | 175 | if (buf[0] == BPDU_TYPE_CONFIG) { |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 9d5a414a394..10eda3cd1d7 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -12,7 +12,6 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/kmod.h> | ||
16 | #include <linux/etherdevice.h> | 15 | #include <linux/etherdevice.h> |
17 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
18 | 17 | ||
@@ -98,13 +97,14 @@ void br_stp_disable_port(struct net_bridge_port *p) | |||
98 | struct net_bridge *br = p->br; | 97 | struct net_bridge *br = p->br; |
99 | int wasroot; | 98 | int wasroot; |
100 | 99 | ||
100 | br_log_state(p); | ||
101 | |||
101 | wasroot = br_is_root_bridge(br); | 102 | wasroot = br_is_root_bridge(br); |
102 | br_become_designated_port(p); | 103 | br_become_designated_port(p); |
103 | p->state = BR_STATE_DISABLED; | 104 | p->state = BR_STATE_DISABLED; |
104 | p->topology_change_ack = 0; | 105 | p->topology_change_ack = 0; |
105 | p->config_pending = 0; | 106 | p->config_pending = 0; |
106 | 107 | ||
107 | br_log_state(p); | ||
108 | br_ifinfo_notify(RTM_NEWLINK, p); | 108 | br_ifinfo_notify(RTM_NEWLINK, p); |
109 | 109 | ||
110 | del_timer(&p->message_age_timer); | 110 | del_timer(&p->message_age_timer); |
@@ -178,7 +178,7 @@ void br_stp_set_enabled(struct net_bridge *br, unsigned long val) | |||
178 | /* called under bridge lock */ | 178 | /* called under bridge lock */ |
179 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | 179 | void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) |
180 | { | 180 | { |
181 | /* should be aligned on 2 bytes for ether_addr_equal() */ | 181 | /* should be aligned on 2 bytes for compare_ether_addr() */ |
182 | unsigned short oldaddr_aligned[ETH_ALEN >> 1]; | 182 | unsigned short oldaddr_aligned[ETH_ALEN >> 1]; |
183 | unsigned char *oldaddr = (unsigned char *)oldaddr_aligned; | 183 | unsigned char *oldaddr = (unsigned char *)oldaddr_aligned; |
184 | struct net_bridge_port *p; | 184 | struct net_bridge_port *p; |
@@ -191,11 +191,12 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
191 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); | 191 | memcpy(br->dev->dev_addr, addr, ETH_ALEN); |
192 | 192 | ||
193 | list_for_each_entry(p, &br->port_list, list) { | 193 | list_for_each_entry(p, &br->port_list, list) { |
194 | if (ether_addr_equal(p->designated_bridge.addr, oldaddr)) | 194 | if (!compare_ether_addr(p->designated_bridge.addr, oldaddr)) |
195 | memcpy(p->designated_bridge.addr, addr, ETH_ALEN); | 195 | memcpy(p->designated_bridge.addr, addr, ETH_ALEN); |
196 | 196 | ||
197 | if (ether_addr_equal(p->designated_root.addr, oldaddr)) | 197 | if (!compare_ether_addr(p->designated_root.addr, oldaddr)) |
198 | memcpy(p->designated_root.addr, addr, ETH_ALEN); | 198 | memcpy(p->designated_root.addr, addr, ETH_ALEN); |
199 | |||
199 | } | 200 | } |
200 | 201 | ||
201 | br_configuration_update(br); | 202 | br_configuration_update(br); |
@@ -204,7 +205,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
204 | br_become_root_bridge(br); | 205 | br_become_root_bridge(br); |
205 | } | 206 | } |
206 | 207 | ||
207 | /* should be aligned on 2 bytes for ether_addr_equal() */ | 208 | /* should be aligned on 2 bytes for compare_ether_addr() */ |
208 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 209 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; |
209 | 210 | ||
210 | /* called under bridge lock */ | 211 | /* called under bridge lock */ |
@@ -226,7 +227,7 @@ bool br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
226 | 227 | ||
227 | } | 228 | } |
228 | 229 | ||
229 | if (ether_addr_equal(br->bridge_id.addr, addr)) | 230 | if (compare_ether_addr(br->bridge_id.addr, addr) == 0) |
230 | return false; /* no change */ | 231 | return false; /* no change */ |
231 | 232 | ||
232 | br_stp_change_bridge_id(br, addr); | 233 | br_stp_change_bridge_id(br, addr); |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index c3530a81a33..58de2a0f997 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -56,7 +56,7 @@ static void br_message_age_timer_expired(unsigned long arg) | |||
56 | return; | 56 | return; |
57 | 57 | ||
58 | br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n", | 58 | br_info(br, "port %u(%s) neighbor %.2x%.2x.%pM lost\n", |
59 | (unsigned int) p->port_no, p->dev->name, | 59 | (unsigned) p->port_no, p->dev->name, |
60 | id->prio[0], id->prio[1], &id->addr); | 60 | id->prio[0], id->prio[1], &id->addr); |
61 | 61 | ||
62 | /* | 62 | /* |
@@ -84,7 +84,7 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
84 | struct net_bridge *br = p->br; | 84 | struct net_bridge *br = p->br; |
85 | 85 | ||
86 | br_debug(br, "port %u(%s) forward delay timer\n", | 86 | br_debug(br, "port %u(%s) forward delay timer\n", |
87 | (unsigned int) p->port_no, p->dev->name); | 87 | (unsigned) p->port_no, p->dev->name); |
88 | spin_lock(&br->lock); | 88 | spin_lock(&br->lock); |
89 | if (p->state == BR_STATE_LISTENING) { | 89 | if (p->state == BR_STATE_LISTENING) { |
90 | p->state = BR_STATE_LEARNING; | 90 | p->state = BR_STATE_LEARNING; |
@@ -131,7 +131,7 @@ static void br_hold_timer_expired(unsigned long arg) | |||
131 | struct net_bridge_port *p = (struct net_bridge_port *) arg; | 131 | struct net_bridge_port *p = (struct net_bridge_port *) arg; |
132 | 132 | ||
133 | br_debug(p->br, "port %u(%s) hold timer expired\n", | 133 | br_debug(p->br, "port %u(%s) hold timer expired\n", |
134 | (unsigned int) p->port_no, p->dev->name); | 134 | (unsigned) p->port_no, p->dev->name); |
135 | 135 | ||
136 | spin_lock(&p->br->lock); | 136 | spin_lock(&p->br->lock); |
137 | if (p->config_pending) | 137 | if (p->config_pending) |
@@ -170,5 +170,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p) | |||
170 | unsigned long br_timer_value(const struct timer_list *timer) | 170 | unsigned long br_timer_value(const struct timer_list *timer) |
171 | { | 171 | { |
172 | return timer_pending(timer) | 172 | return timer_pending(timer) |
173 | ? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0; | 173 | ? jiffies_to_clock_t(timer->expires - jiffies) : 0; |
174 | } | 174 | } |
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 5913a3a0047..68b893ea8c3 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/capability.h> | 14 | #include <linux/capability.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/etherdevice.h> | ||
18 | #include <linux/if_bridge.h> | 17 | #include <linux/if_bridge.h> |
19 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
20 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
@@ -37,7 +36,7 @@ static ssize_t store_bridge_parm(struct device *d, | |||
37 | unsigned long val; | 36 | unsigned long val; |
38 | int err; | 37 | int err; |
39 | 38 | ||
40 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) | 39 | if (!capable(CAP_NET_ADMIN)) |
41 | return -EPERM; | 40 | return -EPERM; |
42 | 41 | ||
43 | val = simple_strtoul(buf, &endp, 0); | 42 | val = simple_strtoul(buf, &endp, 0); |
@@ -133,7 +132,7 @@ static ssize_t store_stp_state(struct device *d, | |||
133 | char *endp; | 132 | char *endp; |
134 | unsigned long val; | 133 | unsigned long val; |
135 | 134 | ||
136 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) | 135 | if (!capable(CAP_NET_ADMIN)) |
137 | return -EPERM; | 136 | return -EPERM; |
138 | 137 | ||
139 | val = simple_strtoul(buf, &endp, 0); | 138 | val = simple_strtoul(buf, &endp, 0); |
@@ -150,39 +149,6 @@ static ssize_t store_stp_state(struct device *d, | |||
150 | static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, | 149 | static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, |
151 | store_stp_state); | 150 | store_stp_state); |
152 | 151 | ||
153 | static ssize_t show_group_fwd_mask(struct device *d, | ||
154 | struct device_attribute *attr, char *buf) | ||
155 | { | ||
156 | struct net_bridge *br = to_bridge(d); | ||
157 | return sprintf(buf, "%#x\n", br->group_fwd_mask); | ||
158 | } | ||
159 | |||
160 | |||
161 | static ssize_t store_group_fwd_mask(struct device *d, | ||
162 | struct device_attribute *attr, const char *buf, | ||
163 | size_t len) | ||
164 | { | ||
165 | struct net_bridge *br = to_bridge(d); | ||
166 | char *endp; | ||
167 | unsigned long val; | ||
168 | |||
169 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) | ||
170 | return -EPERM; | ||
171 | |||
172 | val = simple_strtoul(buf, &endp, 0); | ||
173 | if (endp == buf) | ||
174 | return -EINVAL; | ||
175 | |||
176 | if (val & BR_GROUPFWD_RESTRICTED) | ||
177 | return -EINVAL; | ||
178 | |||
179 | br->group_fwd_mask = val; | ||
180 | |||
181 | return len; | ||
182 | } | ||
183 | static DEVICE_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask, | ||
184 | store_group_fwd_mask); | ||
185 | |||
186 | static ssize_t show_priority(struct device *d, struct device_attribute *attr, | 152 | static ssize_t show_priority(struct device *d, struct device_attribute *attr, |
187 | char *buf) | 153 | char *buf) |
188 | { | 154 | { |
@@ -298,18 +264,23 @@ static ssize_t store_group_addr(struct device *d, | |||
298 | const char *buf, size_t len) | 264 | const char *buf, size_t len) |
299 | { | 265 | { |
300 | struct net_bridge *br = to_bridge(d); | 266 | struct net_bridge *br = to_bridge(d); |
301 | u8 new_addr[6]; | 267 | unsigned new_addr[6]; |
302 | int i; | 268 | int i; |
303 | 269 | ||
304 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) | 270 | if (!capable(CAP_NET_ADMIN)) |
305 | return -EPERM; | 271 | return -EPERM; |
306 | 272 | ||
307 | if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", | 273 | if (sscanf(buf, "%x:%x:%x:%x:%x:%x", |
308 | &new_addr[0], &new_addr[1], &new_addr[2], | 274 | &new_addr[0], &new_addr[1], &new_addr[2], |
309 | &new_addr[3], &new_addr[4], &new_addr[5]) != 6) | 275 | &new_addr[3], &new_addr[4], &new_addr[5]) != 6) |
310 | return -EINVAL; | 276 | return -EINVAL; |
311 | 277 | ||
312 | if (!is_link_local_ether_addr(new_addr)) | 278 | /* Must be 01:80:c2:00:00:0X */ |
279 | for (i = 0; i < 5; i++) | ||
280 | if (new_addr[i] != br_group_address[i]) | ||
281 | return -EINVAL; | ||
282 | |||
283 | if (new_addr[5] & ~0xf) | ||
313 | return -EINVAL; | 284 | return -EINVAL; |
314 | 285 | ||
315 | if (new_addr[5] == 1 || /* 802.3x Pause address */ | 286 | if (new_addr[5] == 1 || /* 802.3x Pause address */ |
@@ -333,7 +304,7 @@ static ssize_t store_flush(struct device *d, | |||
333 | { | 304 | { |
334 | struct net_bridge *br = to_bridge(d); | 305 | struct net_bridge *br = to_bridge(d); |
335 | 306 | ||
336 | if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN)) | 307 | if (!capable(CAP_NET_ADMIN)) |
337 | return -EPERM; | 308 | return -EPERM; |
338 | 309 | ||
339 | br_fdb_flush(br); | 310 | br_fdb_flush(br); |
@@ -375,23 +346,6 @@ static ssize_t store_multicast_snooping(struct device *d, | |||
375 | static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, | 346 | static DEVICE_ATTR(multicast_snooping, S_IRUGO | S_IWUSR, |
376 | show_multicast_snooping, store_multicast_snooping); | 347 | show_multicast_snooping, store_multicast_snooping); |
377 | 348 | ||
378 | static ssize_t show_multicast_querier(struct device *d, | ||
379 | struct device_attribute *attr, | ||
380 | char *buf) | ||
381 | { | ||
382 | struct net_bridge *br = to_bridge(d); | ||
383 | return sprintf(buf, "%d\n", br->multicast_querier); | ||
384 | } | ||
385 | |||
386 | static ssize_t store_multicast_querier(struct device *d, | ||
387 | struct device_attribute *attr, | ||
388 | const char *buf, size_t len) | ||
389 | { | ||
390 | return store_bridge_parm(d, buf, len, br_multicast_set_querier); | ||
391 | } | ||
392 | static DEVICE_ATTR(multicast_querier, S_IRUGO | S_IWUSR, | ||
393 | show_multicast_querier, store_multicast_querier); | ||
394 | |||
395 | static ssize_t show_hash_elasticity(struct device *d, | 349 | static ssize_t show_hash_elasticity(struct device *d, |
396 | struct device_attribute *attr, char *buf) | 350 | struct device_attribute *attr, char *buf) |
397 | { | 351 | { |
@@ -698,7 +652,6 @@ static struct attribute *bridge_attrs[] = { | |||
698 | &dev_attr_max_age.attr, | 652 | &dev_attr_max_age.attr, |
699 | &dev_attr_ageing_time.attr, | 653 | &dev_attr_ageing_time.attr, |
700 | &dev_attr_stp_state.attr, | 654 | &dev_attr_stp_state.attr, |
701 | &dev_attr_group_fwd_mask.attr, | ||
702 | &dev_attr_priority.attr, | 655 | &dev_attr_priority.attr, |
703 | &dev_attr_bridge_id.attr, | 656 | &dev_attr_bridge_id.attr, |
704 | &dev_attr_root_id.attr, | 657 | &dev_attr_root_id.attr, |
@@ -715,7 +668,6 @@ static struct attribute *bridge_attrs[] = { | |||
715 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | 668 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
716 | &dev_attr_multicast_router.attr, | 669 | &dev_attr_multicast_router.attr, |
717 | &dev_attr_multicast_snooping.attr, | 670 | &dev_attr_multicast_snooping.attr, |
718 | &dev_attr_multicast_querier.attr, | ||
719 | &dev_attr_hash_elasticity.attr, | 671 | &dev_attr_hash_elasticity.attr, |
720 | &dev_attr_hash_max.attr, | 672 | &dev_attr_hash_max.attr, |
721 | &dev_attr_multicast_last_member_count.attr, | 673 | &dev_attr_multicast_last_member_count.attr, |
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index a1ef1b6e14d..6229b62749e 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -27,35 +27,13 @@ struct brport_attribute { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ | 29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ |
30 | const struct brport_attribute brport_attr_##_name = { \ | 30 | struct brport_attribute brport_attr_##_name = { \ |
31 | .attr = {.name = __stringify(_name), \ | 31 | .attr = {.name = __stringify(_name), \ |
32 | .mode = _mode }, \ | 32 | .mode = _mode }, \ |
33 | .show = _show, \ | 33 | .show = _show, \ |
34 | .store = _store, \ | 34 | .store = _store, \ |
35 | }; | 35 | }; |
36 | 36 | ||
37 | #define BRPORT_ATTR_FLAG(_name, _mask) \ | ||
38 | static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \ | ||
39 | { \ | ||
40 | return sprintf(buf, "%d\n", !!(p->flags & _mask)); \ | ||
41 | } \ | ||
42 | static int store_##_name(struct net_bridge_port *p, unsigned long v) \ | ||
43 | { \ | ||
44 | unsigned long flags = p->flags; \ | ||
45 | if (v) \ | ||
46 | flags |= _mask; \ | ||
47 | else \ | ||
48 | flags &= ~_mask; \ | ||
49 | if (flags != p->flags) { \ | ||
50 | p->flags = flags; \ | ||
51 | br_ifinfo_notify(RTM_NEWLINK, p); \ | ||
52 | } \ | ||
53 | return 0; \ | ||
54 | } \ | ||
55 | static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR, \ | ||
56 | show_##_name, store_##_name) | ||
57 | |||
58 | |||
59 | static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) | 37 | static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) |
60 | { | 38 | { |
61 | return sprintf(buf, "%d\n", p->path_cost); | 39 | return sprintf(buf, "%d\n", p->path_cost); |
@@ -155,9 +133,21 @@ static int store_flush(struct net_bridge_port *p, unsigned long v) | |||
155 | } | 133 | } |
156 | static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); | 134 | static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush); |
157 | 135 | ||
158 | BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE); | 136 | static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf) |
159 | BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD); | 137 | { |
160 | BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK); | 138 | int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0; |
139 | return sprintf(buf, "%d\n", hairpin_mode); | ||
140 | } | ||
141 | static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v) | ||
142 | { | ||
143 | if (v) | ||
144 | p->flags |= BR_HAIRPIN_MODE; | ||
145 | else | ||
146 | p->flags &= ~BR_HAIRPIN_MODE; | ||
147 | return 0; | ||
148 | } | ||
149 | static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR, | ||
150 | show_hairpin_mode, store_hairpin_mode); | ||
161 | 151 | ||
162 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | 152 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
163 | static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) | 153 | static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) |
@@ -172,11 +162,9 @@ static int store_multicast_router(struct net_bridge_port *p, | |||
172 | } | 162 | } |
173 | static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, | 163 | static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router, |
174 | store_multicast_router); | 164 | store_multicast_router); |
175 | |||
176 | BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE); | ||
177 | #endif | 165 | #endif |
178 | 166 | ||
179 | static const struct brport_attribute *brport_attrs[] = { | 167 | static struct brport_attribute *brport_attrs[] = { |
180 | &brport_attr_path_cost, | 168 | &brport_attr_path_cost, |
181 | &brport_attr_priority, | 169 | &brport_attr_priority, |
182 | &brport_attr_port_id, | 170 | &brport_attr_port_id, |
@@ -193,11 +181,8 @@ static const struct brport_attribute *brport_attrs[] = { | |||
193 | &brport_attr_hold_timer, | 181 | &brport_attr_hold_timer, |
194 | &brport_attr_flush, | 182 | &brport_attr_flush, |
195 | &brport_attr_hairpin_mode, | 183 | &brport_attr_hairpin_mode, |
196 | &brport_attr_bpdu_guard, | ||
197 | &brport_attr_root_block, | ||
198 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING | 184 | #ifdef CONFIG_BRIDGE_IGMP_SNOOPING |
199 | &brport_attr_multicast_router, | 185 | &brport_attr_multicast_router, |
200 | &brport_attr_multicast_fast_leave, | ||
201 | #endif | 186 | #endif |
202 | NULL | 187 | NULL |
203 | }; | 188 | }; |
@@ -224,7 +209,7 @@ static ssize_t brport_store(struct kobject * kobj, | |||
224 | char *endp; | 209 | char *endp; |
225 | unsigned long val; | 210 | unsigned long val; |
226 | 211 | ||
227 | if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN)) | 212 | if (!capable(CAP_NET_ADMIN)) |
228 | return -EPERM; | 213 | return -EPERM; |
229 | 214 | ||
230 | val = simple_strtoul(buf, &endp, 0); | 215 | val = simple_strtoul(buf, &endp, 0); |
@@ -256,7 +241,7 @@ const struct sysfs_ops brport_sysfs_ops = { | |||
256 | int br_sysfs_addif(struct net_bridge_port *p) | 241 | int br_sysfs_addif(struct net_bridge_port *p) |
257 | { | 242 | { |
258 | struct net_bridge *br = p->br; | 243 | struct net_bridge *br = p->br; |
259 | const struct brport_attribute **a; | 244 | struct brport_attribute **a; |
260 | int err; | 245 | int err; |
261 | 246 | ||
262 | err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, | 247 | err = sysfs_create_link(&p->kobj, &br->dev->dev.kobj, |
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c index 99c85668f55..2ed0056a39a 100644 --- a/net/bridge/netfilter/ebt_ip6.c +++ b/net/bridge/netfilter/ebt_ip6.c | |||
@@ -55,10 +55,9 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
55 | return false; | 55 | return false; |
56 | if (info->bitmask & EBT_IP6_PROTO) { | 56 | if (info->bitmask & EBT_IP6_PROTO) { |
57 | uint8_t nexthdr = ih6->nexthdr; | 57 | uint8_t nexthdr = ih6->nexthdr; |
58 | __be16 frag_off; | ||
59 | int offset_ph; | 58 | int offset_ph; |
60 | 59 | ||
61 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr, &frag_off); | 60 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); |
62 | if (offset_ph == -1) | 61 | if (offset_ph == -1) |
63 | return false; | 62 | return false; |
64 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) | 63 | if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 92de5e5f9db..6e5a8bb9b94 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, | |||
80 | unsigned int bitmask; | 80 | unsigned int bitmask; |
81 | 81 | ||
82 | spin_lock_bh(&ebt_log_lock); | 82 | spin_lock_bh(&ebt_log_lock); |
83 | printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", | 83 | printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x", |
84 | '0' + loginfo->u.log.level, prefix, | 84 | '0' + loginfo->u.log.level, prefix, |
85 | in ? in->name : "", out ? out->name : "", | 85 | in ? in->name : "", out ? out->name : "", |
86 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | 86 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, |
@@ -107,13 +107,12 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, | |||
107 | goto out; | 107 | goto out; |
108 | } | 108 | } |
109 | 109 | ||
110 | #if IS_ENABLED(CONFIG_BRIDGE_EBT_IP6) | 110 | #if defined(CONFIG_BRIDGE_EBT_IP6) || defined(CONFIG_BRIDGE_EBT_IP6_MODULE) |
111 | if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto == | 111 | if ((bitmask & EBT_LOG_IP6) && eth_hdr(skb)->h_proto == |
112 | htons(ETH_P_IPV6)) { | 112 | htons(ETH_P_IPV6)) { |
113 | const struct ipv6hdr *ih; | 113 | const struct ipv6hdr *ih; |
114 | struct ipv6hdr _iph; | 114 | struct ipv6hdr _iph; |
115 | uint8_t nexthdr; | 115 | uint8_t nexthdr; |
116 | __be16 frag_off; | ||
117 | int offset_ph; | 116 | int offset_ph; |
118 | 117 | ||
119 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); | 118 | ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); |
@@ -124,7 +123,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum, | |||
124 | printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d", | 123 | printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d", |
125 | &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr); | 124 | &ih->saddr, &ih->daddr, ih->priority, ih->nexthdr); |
126 | nexthdr = ih->nexthdr; | 125 | nexthdr = ih->nexthdr; |
127 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr, &frag_off); | 126 | offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr); |
128 | if (offset_ph == -1) | 127 | if (offset_ph == -1) |
129 | goto out; | 128 | goto out; |
130 | print_ports(skb, nexthdr, offset_ph); | 129 | print_ports(skb, nexthdr, offset_ph); |
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c index 071d87214dd..5b33a2e634a 100644 --- a/net/bridge/netfilter/ebt_stp.c +++ b/net/bridge/netfilter/ebt_stp.c | |||
@@ -164,8 +164,8 @@ static int ebt_stp_mt_check(const struct xt_mtchk_param *par) | |||
164 | !(info->bitmask & EBT_STP_MASK)) | 164 | !(info->bitmask & EBT_STP_MASK)) |
165 | return -EINVAL; | 165 | return -EINVAL; |
166 | /* Make sure the match only receives stp frames */ | 166 | /* Make sure the match only receives stp frames */ |
167 | if (!ether_addr_equal(e->destmac, bridge_ula) || | 167 | if (compare_ether_addr(e->destmac, bridge_ula) || |
168 | !ether_addr_equal(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) | 168 | compare_ether_addr(e->destmsk, msk) || !(e->bitmask & EBT_DESTMAC)) |
169 | return -EINVAL; | 169 | return -EINVAL; |
170 | 170 | ||
171 | return 0; | 171 | return 0; |
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index 3476ec46974..bf2a333ca7c 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c | |||
@@ -102,15 +102,16 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) | |||
102 | unsigned int n; | 102 | unsigned int n; |
103 | 103 | ||
104 | n = max(size, nlbufsiz); | 104 | n = max(size, nlbufsiz); |
105 | skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN); | 105 | skb = alloc_skb(n, GFP_ATOMIC); |
106 | if (!skb) { | 106 | if (!skb) { |
107 | pr_debug("cannot alloc whole buffer of size %ub!\n", n); | ||
107 | if (n > size) { | 108 | if (n > size) { |
108 | /* try to allocate only as much as we need for | 109 | /* try to allocate only as much as we need for |
109 | * current packet */ | 110 | * current packet */ |
110 | skb = alloc_skb(size, GFP_ATOMIC); | 111 | skb = alloc_skb(size, GFP_ATOMIC); |
111 | if (!skb) | 112 | if (!skb) |
112 | pr_debug("cannot even allocate buffer of size %ub\n", | 113 | pr_debug("cannot even allocate " |
113 | size); | 114 | "buffer of size %ub\n", size); |
114 | } | 115 | } |
115 | } | 116 | } |
116 | 117 | ||
@@ -145,24 +146,19 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, | |||
145 | 146 | ||
146 | if (!ub->skb) { | 147 | if (!ub->skb) { |
147 | if (!(ub->skb = ulog_alloc_skb(size))) | 148 | if (!(ub->skb = ulog_alloc_skb(size))) |
148 | goto unlock; | 149 | goto alloc_failure; |
149 | } else if (size > skb_tailroom(ub->skb)) { | 150 | } else if (size > skb_tailroom(ub->skb)) { |
150 | ulog_send(group); | 151 | ulog_send(group); |
151 | 152 | ||
152 | if (!(ub->skb = ulog_alloc_skb(size))) | 153 | if (!(ub->skb = ulog_alloc_skb(size))) |
153 | goto unlock; | 154 | goto alloc_failure; |
154 | } | 155 | } |
155 | 156 | ||
156 | nlh = nlmsg_put(ub->skb, 0, ub->qlen, 0, | 157 | nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, |
157 | size - NLMSG_ALIGN(sizeof(*nlh)), 0); | 158 | size - NLMSG_ALIGN(sizeof(*nlh))); |
158 | if (!nlh) { | ||
159 | kfree_skb(ub->skb); | ||
160 | ub->skb = NULL; | ||
161 | goto unlock; | ||
162 | } | ||
163 | ub->qlen++; | 159 | ub->qlen++; |
164 | 160 | ||
165 | pm = nlmsg_data(nlh); | 161 | pm = NLMSG_DATA(nlh); |
166 | 162 | ||
167 | /* Fill in the ulog data */ | 163 | /* Fill in the ulog data */ |
168 | pm->version = EBT_ULOG_VERSION; | 164 | pm->version = EBT_ULOG_VERSION; |
@@ -214,6 +210,14 @@ static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb, | |||
214 | 210 | ||
215 | unlock: | 211 | unlock: |
216 | spin_unlock_bh(lock); | 212 | spin_unlock_bh(lock); |
213 | |||
214 | return; | ||
215 | |||
216 | nlmsg_failure: | ||
217 | pr_debug("error during NLMSG_PUT. This should " | ||
218 | "not happen, please report to author.\n"); | ||
219 | alloc_failure: | ||
220 | goto unlock; | ||
217 | } | 221 | } |
218 | 222 | ||
219 | /* this function is registered with the netfilter core */ | 223 | /* this function is registered with the netfilter core */ |
@@ -282,9 +286,6 @@ static int __init ebt_ulog_init(void) | |||
282 | { | 286 | { |
283 | int ret; | 287 | int ret; |
284 | int i; | 288 | int i; |
285 | struct netlink_kernel_cfg cfg = { | ||
286 | .groups = EBT_ULOG_MAXNLGROUPS, | ||
287 | }; | ||
288 | 289 | ||
289 | if (nlbufsiz >= 128*1024) { | 290 | if (nlbufsiz >= 128*1024) { |
290 | pr_warning("Netlink buffer has to be <= 128kB," | 291 | pr_warning("Netlink buffer has to be <= 128kB," |
@@ -298,7 +299,9 @@ static int __init ebt_ulog_init(void) | |||
298 | spin_lock_init(&ulog_buffers[i].lock); | 299 | spin_lock_init(&ulog_buffers[i].lock); |
299 | } | 300 | } |
300 | 301 | ||
301 | ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, &cfg); | 302 | ebtulognl = netlink_kernel_create(&init_net, NETLINK_NFLOG, |
303 | EBT_ULOG_MAXNLGROUPS, NULL, NULL, | ||
304 | THIS_MODULE); | ||
302 | if (!ebtulognl) | 305 | if (!ebtulognl) |
303 | ret = -ENOMEM; | 306 | ret = -ENOMEM; |
304 | else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) | 307 | else if ((ret = xt_register_target(&ebt_ulog_tg_reg)) != 0) |
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 40d8258bf74..1bcaf36ad61 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c | |||
@@ -87,14 +87,14 @@ static int __init ebtable_broute_init(void) | |||
87 | if (ret < 0) | 87 | if (ret < 0) |
88 | return ret; | 88 | return ret; |
89 | /* see br_input.c */ | 89 | /* see br_input.c */ |
90 | RCU_INIT_POINTER(br_should_route_hook, | 90 | rcu_assign_pointer(br_should_route_hook, |
91 | (br_should_route_hook_t *)ebt_broute); | 91 | (br_should_route_hook_t *)ebt_broute); |
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | static void __exit ebtable_broute_fini(void) | 95 | static void __exit ebtable_broute_fini(void) |
96 | { | 96 | { |
97 | RCU_INIT_POINTER(br_should_route_hook, NULL); | 97 | rcu_assign_pointer(br_should_route_hook, NULL); |
98 | synchronize_net(); | 98 | synchronize_net(); |
99 | unregister_pernet_subsys(&broute_net_ops); | 99 | unregister_pernet_subsys(&broute_net_ops); |
100 | } | 100 | } |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 3c2e9dced9e..42e6bd09457 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -100,7 +100,9 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { | |||
100 | static int __net_init frame_filter_net_init(struct net *net) | 100 | static int __net_init frame_filter_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); | 102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); |
103 | return PTR_RET(net->xt.frame_filter); | 103 | if (IS_ERR(net->xt.frame_filter)) |
104 | return PTR_ERR(net->xt.frame_filter); | ||
105 | return 0; | ||
104 | } | 106 | } |
105 | 107 | ||
106 | static void __net_exit frame_filter_net_exit(struct net *net) | 108 | static void __net_exit frame_filter_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 10871bc7790..6dc2f878ae0 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -100,7 +100,9 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { | |||
100 | static int __net_init frame_nat_net_init(struct net *net) | 100 | static int __net_init frame_nat_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); | 102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); |
103 | return PTR_RET(net->xt.frame_nat); | 103 | if (IS_ERR(net->xt.frame_nat)) |
104 | return PTR_ERR(net->xt.frame_nat); | ||
105 | return 0; | ||
104 | } | 106 | } |
105 | 107 | ||
106 | static void __net_exit frame_nat_net_exit(struct net *net) | 108 | static void __net_exit frame_nat_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 5fe2ff3b01e..5864cc49136 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1335,12 +1335,7 @@ static inline int ebt_make_matchname(const struct ebt_entry_match *m, | |||
1335 | const char *base, char __user *ubase) | 1335 | const char *base, char __user *ubase) |
1336 | { | 1336 | { |
1337 | char __user *hlp = ubase + ((char *)m - base); | 1337 | char __user *hlp = ubase + ((char *)m - base); |
1338 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; | 1338 | if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) |
1339 | |||
1340 | /* ebtables expects 32 bytes long names but xt_match names are 29 bytes | ||
1341 | long. Copy 29 bytes and fill remaining bytes with zeroes. */ | ||
1342 | strncpy(name, m->u.match->name, sizeof(name)); | ||
1343 | if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) | ||
1344 | return -EFAULT; | 1339 | return -EFAULT; |
1345 | return 0; | 1340 | return 0; |
1346 | } | 1341 | } |
@@ -1349,10 +1344,7 @@ static inline int ebt_make_watchername(const struct ebt_entry_watcher *w, | |||
1349 | const char *base, char __user *ubase) | 1344 | const char *base, char __user *ubase) |
1350 | { | 1345 | { |
1351 | char __user *hlp = ubase + ((char *)w - base); | 1346 | char __user *hlp = ubase + ((char *)w - base); |
1352 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; | 1347 | if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) |
1353 | |||
1354 | strncpy(name, w->u.watcher->name, sizeof(name)); | ||
1355 | if (copy_to_user(hlp , name, EBT_FUNCTION_MAXNAMELEN)) | ||
1356 | return -EFAULT; | 1348 | return -EFAULT; |
1357 | return 0; | 1349 | return 0; |
1358 | } | 1350 | } |
@@ -1363,7 +1355,6 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) | |||
1363 | int ret; | 1355 | int ret; |
1364 | char __user *hlp; | 1356 | char __user *hlp; |
1365 | const struct ebt_entry_target *t; | 1357 | const struct ebt_entry_target *t; |
1366 | char name[EBT_FUNCTION_MAXNAMELEN] = {}; | ||
1367 | 1358 | ||
1368 | if (e->bitmask == 0) | 1359 | if (e->bitmask == 0) |
1369 | return 0; | 1360 | return 0; |
@@ -1377,8 +1368,7 @@ ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase) | |||
1377 | ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase); | 1368 | ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase); |
1378 | if (ret != 0) | 1369 | if (ret != 0) |
1379 | return ret; | 1370 | return ret; |
1380 | strncpy(name, t->u.target->name, sizeof(name)); | 1371 | if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN)) |
1381 | if (copy_to_user(hlp, name, EBT_FUNCTION_MAXNAMELEN)) | ||
1382 | return -EFAULT; | 1372 | return -EFAULT; |
1383 | return 0; | 1373 | return 0; |
1384 | } | 1374 | } |
@@ -1903,7 +1893,10 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1903 | 1893 | ||
1904 | switch (compat_mwt) { | 1894 | switch (compat_mwt) { |
1905 | case EBT_COMPAT_MATCH: | 1895 | case EBT_COMPAT_MATCH: |
1906 | match = xt_request_find_match(NFPROTO_BRIDGE, name, 0); | 1896 | match = try_then_request_module(xt_find_match(NFPROTO_BRIDGE, |
1897 | name, 0), "ebt_%s", name); | ||
1898 | if (match == NULL) | ||
1899 | return -ENOENT; | ||
1907 | if (IS_ERR(match)) | 1900 | if (IS_ERR(match)) |
1908 | return PTR_ERR(match); | 1901 | return PTR_ERR(match); |
1909 | 1902 | ||
@@ -1922,7 +1915,10 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1922 | break; | 1915 | break; |
1923 | case EBT_COMPAT_WATCHER: /* fallthrough */ | 1916 | case EBT_COMPAT_WATCHER: /* fallthrough */ |
1924 | case EBT_COMPAT_TARGET: | 1917 | case EBT_COMPAT_TARGET: |
1925 | wt = xt_request_find_target(NFPROTO_BRIDGE, name, 0); | 1918 | wt = try_then_request_module(xt_find_target(NFPROTO_BRIDGE, |
1919 | name, 0), "ebt_%s", name); | ||
1920 | if (wt == NULL) | ||
1921 | return -ENOENT; | ||
1926 | if (IS_ERR(wt)) | 1922 | if (IS_ERR(wt)) |
1927 | return PTR_ERR(wt); | 1923 | return PTR_ERR(wt); |
1928 | off = xt_compat_target_offset(wt); | 1924 | off = xt_compat_target_offset(wt); |