aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bridge/br_device.c9
-rw-r--r--net/bridge/br_if.c3
-rw-r--r--net/bridge/br_netfilter.c63
-rw-r--r--net/bridge/br_private.h6
4 files changed, 51 insertions, 30 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index d9449df7cad5..9b58d70b0e7d 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -68,10 +68,17 @@ static int br_dev_stop(struct net_device *dev)
68 68
69static int br_change_mtu(struct net_device *dev, int new_mtu) 69static int br_change_mtu(struct net_device *dev, int new_mtu)
70{ 70{
71 if (new_mtu < 68 || new_mtu > br_min_mtu(netdev_priv(dev))) 71 struct net_bridge *br = netdev_priv(dev);
72 if (new_mtu < 68 || new_mtu > br_min_mtu(br))
72 return -EINVAL; 73 return -EINVAL;
73 74
74 dev->mtu = new_mtu; 75 dev->mtu = new_mtu;
76
77#ifdef CONFIG_BRIDGE_NETFILTER
78 /* remember the MTU in the rtable for PMTU */
79 br->fake_rtable.u.dst.metrics[RTAX_MTU - 1] = new_mtu;
80#endif
81
75 return 0; 82 return 0;
76} 83}
77 84
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a072ea5ca6f5..63c18aacde8c 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -202,6 +202,9 @@ static struct net_device *new_bridge_dev(const char *name)
202 br->topology_change = 0; 202 br->topology_change = 0;
203 br->topology_change_detected = 0; 203 br->topology_change_detected = 0;
204 br->ageing_time = 300 * HZ; 204 br->ageing_time = 300 * HZ;
205
206 br_netfilter_rtable_init(br);
207
205 INIT_LIST_HEAD(&br->age_list); 208 INIT_LIST_HEAD(&br->age_list);
206 209
207 br_stp_timer_init(br); 210 br_stp_timer_init(br);
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index bb90cd7bace3..6e280a8a31ee 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -101,33 +101,30 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
101 pppoe_proto(skb) == htons(PPP_IPV6) && \ 101 pppoe_proto(skb) == htons(PPP_IPV6) && \
102 brnf_filter_pppoe_tagged) 102 brnf_filter_pppoe_tagged)
103 103
104/* We need these fake structures to make netfilter happy -- 104/*
105 * lots of places assume that skb->dst != NULL, which isn't 105 * Initialize bogus route table used to keep netfilter happy.
106 * all that unreasonable.
107 *
108 * Currently, we fill in the PMTU entry because netfilter 106 * Currently, we fill in the PMTU entry because netfilter
109 * refragmentation needs it, and the rt_flags entry because 107 * refragmentation needs it, and the rt_flags entry because
110 * ipt_REJECT needs it. Future netfilter modules might 108 * ipt_REJECT needs it. Future netfilter modules might
111 * require us to fill additional fields. */ 109 * require us to fill additional fields.
112static struct net_device __fake_net_device = { 110 */
113 .hard_header_len = ETH_HLEN, 111void br_netfilter_rtable_init(struct net_bridge *br)
114#ifdef CONFIG_NET_NS 112{
115 .nd_net = &init_net, 113 struct rtable *rt = &br->fake_rtable;
116#endif
117};
118 114
119static struct rtable __fake_rtable = { 115 atomic_set(&rt->u.dst.__refcnt, 1);
120 .u = { 116 rt->u.dst.dev = &br->dev;
121 .dst = { 117 rt->u.dst.path = &rt->u.dst;
122 .__refcnt = ATOMIC_INIT(1), 118 rt->u.dst.metrics[RTAX_MTU - 1] = 1500;
123 .dev = &__fake_net_device, 119 rt->u.dst.flags = DST_NOXFRM;
124 .path = &__fake_rtable.u.dst, 120}
125 .metrics = {[RTAX_MTU - 1] = 1500}, 121
126 .flags = DST_NOXFRM, 122static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
127 } 123{
128 }, 124 struct net_bridge_port *port = rcu_dereference(dev->br_port);
129 .rt_flags = 0, 125
130}; 126 return port ? &port->br->fake_rtable : NULL;
127}
131 128
132static inline struct net_device *bridge_parent(const struct net_device *dev) 129static inline struct net_device *bridge_parent(const struct net_device *dev)
133{ 130{
@@ -226,8 +223,12 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
226 } 223 }
227 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; 224 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
228 225
229 skb->rtable = &__fake_rtable; 226 skb->rtable = bridge_parent_rtable(nf_bridge->physindev);
230 dst_hold(&__fake_rtable.u.dst); 227 if (!skb->rtable) {
228 kfree_skb(skb);
229 return 0;
230 }
231 dst_hold(&skb->rtable->u.dst);
231 232
232 skb->dev = nf_bridge->physindev; 233 skb->dev = nf_bridge->physindev;
233 nf_bridge_push_encap_header(skb); 234 nf_bridge_push_encap_header(skb);
@@ -391,8 +392,12 @@ bridged_dnat:
391 skb->pkt_type = PACKET_HOST; 392 skb->pkt_type = PACKET_HOST;
392 } 393 }
393 } else { 394 } else {
394 skb->rtable = &__fake_rtable; 395 skb->rtable = bridge_parent_rtable(nf_bridge->physindev);
395 dst_hold(&__fake_rtable.u.dst); 396 if (!skb->rtable) {
397 kfree_skb(skb);
398 return 0;
399 }
400 dst_hold(&skb->rtable->u.dst);
396 } 401 }
397 402
398 skb->dev = nf_bridge->physindev; 403 skb->dev = nf_bridge->physindev;
@@ -611,8 +616,8 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb,
611 const struct net_device *out, 616 const struct net_device *out,
612 int (*okfn)(struct sk_buff *)) 617 int (*okfn)(struct sk_buff *))
613{ 618{
614 if (skb->rtable == &__fake_rtable) { 619 if (skb->rtable && skb->rtable == bridge_parent_rtable(in)) {
615 dst_release(&__fake_rtable.u.dst); 620 dst_release(&skb->rtable->u.dst);
616 skb->rtable = NULL; 621 skb->rtable = NULL;
617 } 622 }
618 623
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 815ed38925b2..c3dc18ddc043 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -15,6 +15,7 @@
15 15
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <linux/if_bridge.h> 17#include <linux/if_bridge.h>
18#include <net/route.h>
18 19
19#define BR_HASH_BITS 8 20#define BR_HASH_BITS 8
20#define BR_HASH_SIZE (1 << BR_HASH_BITS) 21#define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -92,6 +93,9 @@ struct net_bridge
92 struct hlist_head hash[BR_HASH_SIZE]; 93 struct hlist_head hash[BR_HASH_SIZE];
93 struct list_head age_list; 94 struct list_head age_list;
94 unsigned long feature_mask; 95 unsigned long feature_mask;
96#ifdef CONFIG_BRIDGE_NETFILTER
97 struct rtable fake_rtable;
98#endif
95 unsigned long flags; 99 unsigned long flags;
96#define BR_SET_MAC_ADDR 0x00000001 100#define BR_SET_MAC_ADDR 0x00000001
97 101
@@ -197,9 +201,11 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us
197#ifdef CONFIG_BRIDGE_NETFILTER 201#ifdef CONFIG_BRIDGE_NETFILTER
198extern int br_netfilter_init(void); 202extern int br_netfilter_init(void);
199extern void br_netfilter_fini(void); 203extern void br_netfilter_fini(void);
204extern void br_netfilter_rtable_init(struct net_bridge *);
200#else 205#else
201#define br_netfilter_init() (0) 206#define br_netfilter_init() (0)
202#define br_netfilter_fini() do { } while(0) 207#define br_netfilter_fini() do { } while(0)
208#define br_netfilter_rtable_init(x)
203#endif 209#endif
204 210
205/* br_stp.c */ 211/* br_stp.c */