aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/Makefile15
-rw-r--r--net/bridge/br.c69
-rw-r--r--net/bridge/br_device.c104
-rw-r--r--net/bridge/br_fdb.c368
-rw-r--r--net/bridge/br_forward.c159
-rw-r--r--net/bridge/br_if.c388
-rw-r--r--net/bridge/br_input.c144
-rw-r--r--net/bridge/br_ioctl.c410
-rw-r--r--net/bridge/br_netfilter.c1087
-rw-r--r--net/bridge/br_notify.c87
-rw-r--r--net/bridge/br_private.h244
-rw-r--r--net/bridge/br_private_stp.h58
-rw-r--r--net/bridge/br_stp.c459
-rw-r--r--net/bridge/br_stp_bpdu.c205
-rw-r--r--net/bridge/br_stp_if.c225
-rw-r--r--net/bridge/br_stp_timer.c188
-rw-r--r--net/bridge/br_sysfs_br.c364
-rw-r--r--net/bridge/br_sysfs_if.c269
-rw-r--r--net/bridge/netfilter/Kconfig211
-rw-r--r--net/bridge/netfilter/Makefile32
-rw-r--r--net/bridge/netfilter/ebt_802_3.c73
-rw-r--r--net/bridge/netfilter/ebt_among.c228
-rw-r--r--net/bridge/netfilter/ebt_arp.c140
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c97
-rw-r--r--net/bridge/netfilter/ebt_dnat.c76
-rw-r--r--net/bridge/netfilter/ebt_ip.c122
-rw-r--r--net/bridge/netfilter/ebt_limit.c113
-rw-r--r--net/bridge/netfilter/ebt_log.c171
-rw-r--r--net/bridge/netfilter/ebt_mark.c68
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c62
-rw-r--r--net/bridge/netfilter/ebt_pkttype.c59
-rw-r--r--net/bridge/netfilter/ebt_redirect.c81
-rw-r--r--net/bridge/netfilter/ebt_snat.c76
-rw-r--r--net/bridge/netfilter/ebt_stp.c194
-rw-r--r--net/bridge/netfilter/ebt_ulog.c295
-rw-r--r--net/bridge/netfilter/ebt_vlan.c195
-rw-r--r--net/bridge/netfilter/ebtable_broute.c86
-rw-r--r--net/bridge/netfilter/ebtable_filter.c123
-rw-r--r--net/bridge/netfilter/ebtable_nat.c130
-rw-r--r--net/bridge/netfilter/ebtables.c1507
40 files changed, 8982 insertions, 0 deletions
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
new file mode 100644
index 000000000000..59556e40e143
--- /dev/null
+++ b/net/bridge/Makefile
@@ -0,0 +1,15 @@
1#
2# Makefile for the IEEE 802.1d ethernet bridging layer.
3#
4
5obj-$(CONFIG_BRIDGE) += bridge.o
6
7bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
8 br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
9 br_stp_if.o br_stp_timer.o
10
11bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
12
13bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
14
15obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/
diff --git a/net/bridge/br.c b/net/bridge/br.c
new file mode 100644
index 000000000000..f8f184942aaf
--- /dev/null
+++ b/net/bridge/br.c
@@ -0,0 +1,69 @@
1/*
2 * Generic parts
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br.c,v 1.47 2001/12/24 00:56:41 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/config.h>
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/netdevice.h>
20#include <linux/etherdevice.h>
21#include <linux/init.h>
22
23#include "br_private.h"
24
25int (*br_should_route_hook) (struct sk_buff **pskb) = NULL;
26
27static int __init br_init(void)
28{
29 br_fdb_init();
30
31#ifdef CONFIG_BRIDGE_NETFILTER
32 if (br_netfilter_init())
33 return 1;
34#endif
35 brioctl_set(br_ioctl_deviceless_stub);
36 br_handle_frame_hook = br_handle_frame;
37
38 br_fdb_get_hook = br_fdb_get;
39 br_fdb_put_hook = br_fdb_put;
40
41 register_netdevice_notifier(&br_device_notifier);
42
43 return 0;
44}
45
46static void __exit br_deinit(void)
47{
48#ifdef CONFIG_BRIDGE_NETFILTER
49 br_netfilter_fini();
50#endif
51 unregister_netdevice_notifier(&br_device_notifier);
52 brioctl_set(NULL);
53
54 br_cleanup_bridges();
55
56 synchronize_net();
57
58 br_fdb_get_hook = NULL;
59 br_fdb_put_hook = NULL;
60
61 br_handle_frame_hook = NULL;
62 br_fdb_fini();
63}
64
65EXPORT_SYMBOL(br_should_route_hook);
66
67module_init(br_init)
68module_exit(br_deinit)
69MODULE_LICENSE("GPL");
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
new file mode 100644
index 000000000000..d9b72fde433c
--- /dev/null
+++ b/net/bridge/br_device.c
@@ -0,0 +1,104 @@
1/*
2 * Device handling code
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_device.c,v 1.6 2001/12/24 00:59:55 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/netdevice.h>
18#include <linux/module.h>
19#include <asm/uaccess.h>
20#include "br_private.h"
21
22static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
23{
24 struct net_bridge *br;
25
26 br = dev->priv;
27
28 return &br->statistics;
29}
30
31int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
32{
33 struct net_bridge *br = netdev_priv(dev);
34 const unsigned char *dest = skb->data;
35 struct net_bridge_fdb_entry *dst;
36
37 br->statistics.tx_packets++;
38 br->statistics.tx_bytes += skb->len;
39
40 skb->mac.raw = skb->data;
41 skb_pull(skb, ETH_HLEN);
42
43 rcu_read_lock();
44 if (dest[0] & 1)
45 br_flood_deliver(br, skb, 0);
46 else if ((dst = __br_fdb_get(br, dest)) != NULL)
47 br_deliver(dst->dst, skb);
48 else
49 br_flood_deliver(br, skb, 0);
50
51 rcu_read_unlock();
52 return 0;
53}
54
55static int br_dev_open(struct net_device *dev)
56{
57 netif_start_queue(dev);
58
59 br_stp_enable_bridge(dev->priv);
60
61 return 0;
62}
63
64static void br_dev_set_multicast_list(struct net_device *dev)
65{
66}
67
68static int br_dev_stop(struct net_device *dev)
69{
70 br_stp_disable_bridge(dev->priv);
71
72 netif_stop_queue(dev);
73
74 return 0;
75}
76
77static int br_change_mtu(struct net_device *dev, int new_mtu)
78{
79 if ((new_mtu < 68) || new_mtu > br_min_mtu(dev->priv))
80 return -EINVAL;
81
82 dev->mtu = new_mtu;
83 return 0;
84}
85
86void br_dev_setup(struct net_device *dev)
87{
88 memset(dev->dev_addr, 0, ETH_ALEN);
89
90 ether_setup(dev);
91
92 dev->do_ioctl = br_dev_ioctl;
93 dev->get_stats = br_dev_get_stats;
94 dev->hard_start_xmit = br_dev_xmit;
95 dev->open = br_dev_open;
96 dev->set_multicast_list = br_dev_set_multicast_list;
97 dev->change_mtu = br_change_mtu;
98 dev->destructor = free_netdev;
99 SET_MODULE_OWNER(dev);
100 dev->stop = br_dev_stop;
101 dev->tx_queue_len = 0;
102 dev->set_mac_address = NULL;
103 dev->priv_flags = IFF_EBRIDGE;
104}
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
new file mode 100644
index 000000000000..e6c2200b7ca3
--- /dev/null
+++ b/net/bridge/br_fdb.c
@@ -0,0 +1,368 @@
1/*
2 * Forwarding database
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_fdb.c,v 1.6 2002/01/17 00:57:07 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/spinlock.h>
19#include <linux/times.h>
20#include <linux/netdevice.h>
21#include <linux/etherdevice.h>
22#include <linux/jhash.h>
23#include <asm/atomic.h>
24#include "br_private.h"
25
26static kmem_cache_t *br_fdb_cache;
27static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
28 const unsigned char *addr);
29
30void __init br_fdb_init(void)
31{
32 br_fdb_cache = kmem_cache_create("bridge_fdb_cache",
33 sizeof(struct net_bridge_fdb_entry),
34 0,
35 SLAB_HWCACHE_ALIGN, NULL, NULL);
36}
37
38void __exit br_fdb_fini(void)
39{
40 kmem_cache_destroy(br_fdb_cache);
41}
42
43
44/* if topology_changing then use forward_delay (default 15 sec)
45 * otherwise keep longer (default 5 minutes)
46 */
47static __inline__ unsigned long hold_time(const struct net_bridge *br)
48{
49 return br->topology_change ? br->forward_delay : br->ageing_time;
50}
51
52static __inline__ int has_expired(const struct net_bridge *br,
53 const struct net_bridge_fdb_entry *fdb)
54{
55 return !fdb->is_static
56 && time_before_eq(fdb->ageing_timer + hold_time(br), jiffies);
57}
58
59static __inline__ int br_mac_hash(const unsigned char *mac)
60{
61 return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1);
62}
63
64static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
65{
66 hlist_del_rcu(&f->hlist);
67 br_fdb_put(f);
68}
69
70void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
71{
72 struct net_bridge *br = p->br;
73 int i;
74
75 spin_lock_bh(&br->hash_lock);
76
77 /* Search all chains since old address/hash is unknown */
78 for (i = 0; i < BR_HASH_SIZE; i++) {
79 struct hlist_node *h;
80 hlist_for_each(h, &br->hash[i]) {
81 struct net_bridge_fdb_entry *f;
82
83 f = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
84 if (f->dst == p && f->is_local) {
85 /* maybe another port has same hw addr? */
86 struct net_bridge_port *op;
87 list_for_each_entry(op, &br->port_list, list) {
88 if (op != p &&
89 !memcmp(op->dev->dev_addr,
90 f->addr.addr, ETH_ALEN)) {
91 f->dst = op;
92 goto insert;
93 }
94 }
95
96 /* delete old one */
97 fdb_delete(f);
98 goto insert;
99 }
100 }
101 }
102 insert:
103 /* insert new address, may fail if invalid address or dup. */
104 fdb_insert(br, p, newaddr);
105
106 spin_unlock_bh(&br->hash_lock);
107}
108
109void br_fdb_cleanup(unsigned long _data)
110{
111 struct net_bridge *br = (struct net_bridge *)_data;
112 unsigned long delay = hold_time(br);
113 int i;
114
115 spin_lock_bh(&br->hash_lock);
116 for (i = 0; i < BR_HASH_SIZE; i++) {
117 struct net_bridge_fdb_entry *f;
118 struct hlist_node *h, *n;
119
120 hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
121 if (!f->is_static &&
122 time_before_eq(f->ageing_timer + delay, jiffies))
123 fdb_delete(f);
124 }
125 }
126 spin_unlock_bh(&br->hash_lock);
127
128 mod_timer(&br->gc_timer, jiffies + HZ/10);
129}
130
131void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
132{
133 int i;
134
135 spin_lock_bh(&br->hash_lock);
136 for (i = 0; i < BR_HASH_SIZE; i++) {
137 struct hlist_node *h, *g;
138
139 hlist_for_each_safe(h, g, &br->hash[i]) {
140 struct net_bridge_fdb_entry *f
141 = hlist_entry(h, struct net_bridge_fdb_entry, hlist);
142 if (f->dst != p)
143 continue;
144
145 /*
146 * if multiple ports all have the same device address
147 * then when one port is deleted, assign
148 * the local entry to other port
149 */
150 if (f->is_local) {
151 struct net_bridge_port *op;
152 list_for_each_entry(op, &br->port_list, list) {
153 if (op != p &&
154 !memcmp(op->dev->dev_addr,
155 f->addr.addr, ETH_ALEN)) {
156 f->dst = op;
157 goto skip_delete;
158 }
159 }
160 }
161
162 fdb_delete(f);
163 skip_delete: ;
164 }
165 }
166 spin_unlock_bh(&br->hash_lock);
167}
168
169/* No locking or refcounting, assumes caller has no preempt (rcu_read_lock) */
170struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
171 const unsigned char *addr)
172{
173 struct hlist_node *h;
174 struct net_bridge_fdb_entry *fdb;
175
176 hlist_for_each_entry_rcu(fdb, h, &br->hash[br_mac_hash(addr)], hlist) {
177 if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
178 if (unlikely(has_expired(br, fdb)))
179 break;
180 return fdb;
181 }
182 }
183
184 return NULL;
185}
186
187/* Interface used by ATM hook that keeps a ref count */
188struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
189 unsigned char *addr)
190{
191 struct net_bridge_fdb_entry *fdb;
192
193 rcu_read_lock();
194 fdb = __br_fdb_get(br, addr);
195 if (fdb)
196 atomic_inc(&fdb->use_count);
197 rcu_read_unlock();
198 return fdb;
199}
200
201static void fdb_rcu_free(struct rcu_head *head)
202{
203 struct net_bridge_fdb_entry *ent
204 = container_of(head, struct net_bridge_fdb_entry, rcu);
205 kmem_cache_free(br_fdb_cache, ent);
206}
207
208/* Set entry up for deletion with RCU */
209void br_fdb_put(struct net_bridge_fdb_entry *ent)
210{
211 if (atomic_dec_and_test(&ent->use_count))
212 call_rcu(&ent->rcu, fdb_rcu_free);
213}
214
215/*
216 * Fill buffer with forwarding table records in
217 * the API format.
218 */
219int br_fdb_fillbuf(struct net_bridge *br, void *buf,
220 unsigned long maxnum, unsigned long skip)
221{
222 struct __fdb_entry *fe = buf;
223 int i, num = 0;
224 struct hlist_node *h;
225 struct net_bridge_fdb_entry *f;
226
227 memset(buf, 0, maxnum*sizeof(struct __fdb_entry));
228
229 rcu_read_lock();
230 for (i = 0; i < BR_HASH_SIZE; i++) {
231 hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
232 if (num >= maxnum)
233 goto out;
234
235 if (has_expired(br, f))
236 continue;
237
238 if (skip) {
239 --skip;
240 continue;
241 }
242
243 /* convert from internal format to API */
244 memcpy(fe->mac_addr, f->addr.addr, ETH_ALEN);
245 fe->port_no = f->dst->port_no;
246 fe->is_local = f->is_local;
247 if (!f->is_static)
248 fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->ageing_timer);
249 ++fe;
250 ++num;
251 }
252 }
253
254 out:
255 rcu_read_unlock();
256
257 return num;
258}
259
260static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
261 const unsigned char *addr)
262{
263 struct hlist_node *h;
264 struct net_bridge_fdb_entry *fdb;
265
266 hlist_for_each_entry_rcu(fdb, h, head, hlist) {
267 if (!memcmp(fdb->addr.addr, addr, ETH_ALEN))
268 return fdb;
269 }
270 return NULL;
271}
272
273static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
274 struct net_bridge_port *source,
275 const unsigned char *addr,
276 int is_local)
277{
278 struct net_bridge_fdb_entry *fdb;
279
280 fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
281 if (fdb) {
282 memcpy(fdb->addr.addr, addr, ETH_ALEN);
283 atomic_set(&fdb->use_count, 1);
284 hlist_add_head_rcu(&fdb->hlist, head);
285
286 fdb->dst = source;
287 fdb->is_local = is_local;
288 fdb->is_static = is_local;
289 fdb->ageing_timer = jiffies;
290 }
291 return fdb;
292}
293
294static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
295 const unsigned char *addr)
296{
297 struct hlist_head *head = &br->hash[br_mac_hash(addr)];
298 struct net_bridge_fdb_entry *fdb;
299
300 if (!is_valid_ether_addr(addr))
301 return -EINVAL;
302
303 fdb = fdb_find(head, addr);
304 if (fdb) {
305 /* it is okay to have multiple ports with same
306 * address, just use the first one.
307 */
308 if (fdb->is_local)
309 return 0;
310
311 printk(KERN_WARNING "%s adding interface with same address "
312 "as a received packet\n",
313 source->dev->name);
314 fdb_delete(fdb);
315 }
316
317 if (!fdb_create(head, source, addr, 1))
318 return -ENOMEM;
319
320 return 0;
321}
322
323int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
324 const unsigned char *addr)
325{
326 int ret;
327
328 spin_lock_bh(&br->hash_lock);
329 ret = fdb_insert(br, source, addr);
330 spin_unlock_bh(&br->hash_lock);
331 return ret;
332}
333
334void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
335 const unsigned char *addr)
336{
337 struct hlist_head *head = &br->hash[br_mac_hash(addr)];
338 struct net_bridge_fdb_entry *fdb;
339
340 /* some users want to always flood. */
341 if (hold_time(br) == 0)
342 return;
343
344 rcu_read_lock();
345 fdb = fdb_find(head, addr);
346 if (likely(fdb)) {
347 /* attempt to update an entry for a local interface */
348 if (unlikely(fdb->is_local)) {
349 if (net_ratelimit())
350 printk(KERN_WARNING "%s: received packet with "
351 " own address as source address\n",
352 source->dev->name);
353 } else {
354 /* fastpath: update of existing entry */
355 fdb->dst = source;
356 fdb->ageing_timer = jiffies;
357 }
358 } else {
359 spin_lock_bh(&br->hash_lock);
360 if (!fdb_find(head, addr))
361 fdb_create(head, source, addr, 0);
362 /* else we lose race and someone else inserts
363 * it first, don't bother updating
364 */
365 spin_unlock_bh(&br->hash_lock);
366 }
367 rcu_read_unlock();
368}
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
new file mode 100644
index 000000000000..ef9f2095f96e
--- /dev/null
+++ b/net/bridge/br_forward.c
@@ -0,0 +1,159 @@
1/*
2 * Forwarding decision
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_forward.c,v 1.4 2001/08/14 22:05:57 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/netdevice.h>
18#include <linux/skbuff.h>
19#include <linux/netfilter_bridge.h>
20#include "br_private.h"
21
22static inline int should_deliver(const struct net_bridge_port *p,
23 const struct sk_buff *skb)
24{
25 if (skb->dev == p->dev ||
26 p->state != BR_STATE_FORWARDING)
27 return 0;
28
29 return 1;
30}
31
32int br_dev_queue_push_xmit(struct sk_buff *skb)
33{
34 if (skb->len > skb->dev->mtu)
35 kfree_skb(skb);
36 else {
37#ifdef CONFIG_BRIDGE_NETFILTER
38 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
39 nf_bridge_maybe_copy_header(skb);
40#endif
41 skb_push(skb, ETH_HLEN);
42
43 dev_queue_xmit(skb);
44 }
45
46 return 0;
47}
48
49int br_forward_finish(struct sk_buff *skb)
50{
51 NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
52 br_dev_queue_push_xmit);
53
54 return 0;
55}
56
57static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
58{
59 skb->dev = to->dev;
60#ifdef CONFIG_NETFILTER_DEBUG
61 skb->nf_debug = 0;
62#endif
63 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
64 br_forward_finish);
65}
66
67static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
68{
69 struct net_device *indev;
70
71 indev = skb->dev;
72 skb->dev = to->dev;
73 skb->ip_summed = CHECKSUM_NONE;
74
75 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
76 br_forward_finish);
77}
78
79/* called with rcu_read_lock */
80void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
81{
82 if (should_deliver(to, skb)) {
83 __br_deliver(to, skb);
84 return;
85 }
86
87 kfree_skb(skb);
88}
89
90/* called with rcu_read_lock */
91void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
92{
93 if (should_deliver(to, skb)) {
94 __br_forward(to, skb);
95 return;
96 }
97
98 kfree_skb(skb);
99}
100
101/* called under bridge lock */
102static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
103 void (*__packet_hook)(const struct net_bridge_port *p,
104 struct sk_buff *skb))
105{
106 struct net_bridge_port *p;
107 struct net_bridge_port *prev;
108
109 if (clone) {
110 struct sk_buff *skb2;
111
112 if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
113 br->statistics.tx_dropped++;
114 return;
115 }
116
117 skb = skb2;
118 }
119
120 prev = NULL;
121
122 list_for_each_entry_rcu(p, &br->port_list, list) {
123 if (should_deliver(p, skb)) {
124 if (prev != NULL) {
125 struct sk_buff *skb2;
126
127 if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
128 br->statistics.tx_dropped++;
129 kfree_skb(skb);
130 return;
131 }
132
133 __packet_hook(prev, skb2);
134 }
135
136 prev = p;
137 }
138 }
139
140 if (prev != NULL) {
141 __packet_hook(prev, skb);
142 return;
143 }
144
145 kfree_skb(skb);
146}
147
148
149/* called with rcu_read_lock */
150void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb, int clone)
151{
152 br_flood(br, skb, clone, __br_deliver);
153}
154
155/* called under bridge lock */
156void br_flood_forward(struct net_bridge *br, struct sk_buff *skb, int clone)
157{
158 br_flood(br, skb, clone, __br_forward);
159}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
new file mode 100644
index 000000000000..69872bf3b87e
--- /dev/null
+++ b/net/bridge/br_if.c
@@ -0,0 +1,388 @@
1/*
2 * Userspace interface
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_if.c,v 1.7 2001/12/24 00:59:55 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/netdevice.h>
18#include <linux/ethtool.h>
19#include <linux/if_arp.h>
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/rtnetlink.h>
23#include <net/sock.h>
24
25#include "br_private.h"
26
27/*
28 * Determine initial path cost based on speed.
29 * using recommendations from 802.1d standard
30 *
31 * Need to simulate user ioctl because not all device's that support
32 * ethtool, use ethtool_ops. Also, since driver might sleep need to
33 * not be holding any locks.
34 */
35static int br_initial_port_cost(struct net_device *dev)
36{
37
38 struct ethtool_cmd ecmd = { ETHTOOL_GSET };
39 struct ifreq ifr;
40 mm_segment_t old_fs;
41 int err;
42
43 strncpy(ifr.ifr_name, dev->name, IFNAMSIZ);
44 ifr.ifr_data = (void __user *) &ecmd;
45
46 old_fs = get_fs();
47 set_fs(KERNEL_DS);
48 err = dev_ethtool(&ifr);
49 set_fs(old_fs);
50
51 if (!err) {
52 switch(ecmd.speed) {
53 case SPEED_100:
54 return 19;
55 case SPEED_1000:
56 return 4;
57 case SPEED_10000:
58 return 2;
59 case SPEED_10:
60 return 100;
61 default:
62 pr_info("bridge: can't decode speed from %s: %d\n",
63 dev->name, ecmd.speed);
64 return 100;
65 }
66 }
67
68 /* Old silly heuristics based on name */
69 if (!strncmp(dev->name, "lec", 3))
70 return 7;
71
72 if (!strncmp(dev->name, "plip", 4))
73 return 2500;
74
75 return 100; /* assume old 10Mbps */
76}
77
78static void destroy_nbp(struct net_bridge_port *p)
79{
80 struct net_device *dev = p->dev;
81
82 dev->br_port = NULL;
83 p->br = NULL;
84 p->dev = NULL;
85 dev_put(dev);
86
87 br_sysfs_freeif(p);
88}
89
90static void destroy_nbp_rcu(struct rcu_head *head)
91{
92 struct net_bridge_port *p =
93 container_of(head, struct net_bridge_port, rcu);
94 destroy_nbp(p);
95}
96
97/* called with RTNL */
98static void del_nbp(struct net_bridge_port *p)
99{
100 struct net_bridge *br = p->br;
101 struct net_device *dev = p->dev;
102
103 dev_set_promiscuity(dev, -1);
104
105 spin_lock_bh(&br->lock);
106 br_stp_disable_port(p);
107 spin_unlock_bh(&br->lock);
108
109 br_fdb_delete_by_port(br, p);
110
111 list_del_rcu(&p->list);
112
113 del_timer_sync(&p->message_age_timer);
114 del_timer_sync(&p->forward_delay_timer);
115 del_timer_sync(&p->hold_timer);
116
117 call_rcu(&p->rcu, destroy_nbp_rcu);
118}
119
120/* called with RTNL */
121static void del_br(struct net_bridge *br)
122{
123 struct net_bridge_port *p, *n;
124
125 list_for_each_entry_safe(p, n, &br->port_list, list) {
126 br_sysfs_removeif(p);
127 del_nbp(p);
128 }
129
130 del_timer_sync(&br->gc_timer);
131
132 br_sysfs_delbr(br->dev);
133 unregister_netdevice(br->dev);
134}
135
136static struct net_device *new_bridge_dev(const char *name)
137{
138 struct net_bridge *br;
139 struct net_device *dev;
140
141 dev = alloc_netdev(sizeof(struct net_bridge), name,
142 br_dev_setup);
143
144 if (!dev)
145 return NULL;
146
147 br = netdev_priv(dev);
148 br->dev = dev;
149
150 spin_lock_init(&br->lock);
151 INIT_LIST_HEAD(&br->port_list);
152 spin_lock_init(&br->hash_lock);
153
154 br->bridge_id.prio[0] = 0x80;
155 br->bridge_id.prio[1] = 0x00;
156 memset(br->bridge_id.addr, 0, ETH_ALEN);
157
158 br->stp_enabled = 0;
159 br->designated_root = br->bridge_id;
160 br->root_path_cost = 0;
161 br->root_port = 0;
162 br->bridge_max_age = br->max_age = 20 * HZ;
163 br->bridge_hello_time = br->hello_time = 2 * HZ;
164 br->bridge_forward_delay = br->forward_delay = 15 * HZ;
165 br->topology_change = 0;
166 br->topology_change_detected = 0;
167 br->ageing_time = 300 * HZ;
168 INIT_LIST_HEAD(&br->age_list);
169
170 br_stp_timer_init(br);
171
172 return dev;
173}
174
175/* find an available port number */
176static int find_portno(struct net_bridge *br)
177{
178 int index;
179 struct net_bridge_port *p;
180 unsigned long *inuse;
181
182 inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long),
183 GFP_KERNEL);
184 if (!inuse)
185 return -ENOMEM;
186
187 memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long));
188 set_bit(0, inuse); /* zero is reserved */
189 list_for_each_entry(p, &br->port_list, list) {
190 set_bit(p->port_no, inuse);
191 }
192 index = find_first_zero_bit(inuse, BR_MAX_PORTS);
193 kfree(inuse);
194
195 return (index >= BR_MAX_PORTS) ? -EXFULL : index;
196}
197
198/* called with RTNL */
199static struct net_bridge_port *new_nbp(struct net_bridge *br,
200 struct net_device *dev,
201 unsigned long cost)
202{
203 int index;
204 struct net_bridge_port *p;
205
206 index = find_portno(br);
207 if (index < 0)
208 return ERR_PTR(index);
209
210 p = kmalloc(sizeof(*p), GFP_KERNEL);
211 if (p == NULL)
212 return ERR_PTR(-ENOMEM);
213
214 memset(p, 0, sizeof(*p));
215 p->br = br;
216 dev_hold(dev);
217 p->dev = dev;
218 p->path_cost = cost;
219 p->priority = 0x8000 >> BR_PORT_BITS;
220 dev->br_port = p;
221 p->port_no = index;
222 br_init_port(p);
223 p->state = BR_STATE_DISABLED;
224 kobject_init(&p->kobj);
225
226 return p;
227}
228
229int br_add_bridge(const char *name)
230{
231 struct net_device *dev;
232 int ret;
233
234 dev = new_bridge_dev(name);
235 if (!dev)
236 return -ENOMEM;
237
238 rtnl_lock();
239 if (strchr(dev->name, '%')) {
240 ret = dev_alloc_name(dev, dev->name);
241 if (ret < 0)
242 goto err1;
243 }
244
245 ret = register_netdevice(dev);
246 if (ret)
247 goto err2;
248
249 /* network device kobject is not setup until
250 * after rtnl_unlock does it's hotplug magic.
251 * so hold reference to avoid race.
252 */
253 dev_hold(dev);
254 rtnl_unlock();
255
256 ret = br_sysfs_addbr(dev);
257 dev_put(dev);
258
259 if (ret)
260 unregister_netdev(dev);
261 out:
262 return ret;
263
264 err2:
265 free_netdev(dev);
266 err1:
267 rtnl_unlock();
268 goto out;
269}
270
271int br_del_bridge(const char *name)
272{
273 struct net_device *dev;
274 int ret = 0;
275
276 rtnl_lock();
277 dev = __dev_get_by_name(name);
278 if (dev == NULL)
279 ret = -ENXIO; /* Could not find device */
280
281 else if (!(dev->priv_flags & IFF_EBRIDGE)) {
282 /* Attempt to delete non bridge device! */
283 ret = -EPERM;
284 }
285
286 else if (dev->flags & IFF_UP) {
287 /* Not shutdown yet. */
288 ret = -EBUSY;
289 }
290
291 else
292 del_br(netdev_priv(dev));
293
294 rtnl_unlock();
295 return ret;
296}
297
298/* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */
299int br_min_mtu(const struct net_bridge *br)
300{
301 const struct net_bridge_port *p;
302 int mtu = 0;
303
304 ASSERT_RTNL();
305
306 if (list_empty(&br->port_list))
307 mtu = 1500;
308 else {
309 list_for_each_entry(p, &br->port_list, list) {
310 if (!mtu || p->dev->mtu < mtu)
311 mtu = p->dev->mtu;
312 }
313 }
314 return mtu;
315}
316
317/* called with RTNL */
318int br_add_if(struct net_bridge *br, struct net_device *dev)
319{
320 struct net_bridge_port *p;
321 int err = 0;
322
323 if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
324 return -EINVAL;
325
326 if (dev->hard_start_xmit == br_dev_xmit)
327 return -ELOOP;
328
329 if (dev->br_port != NULL)
330 return -EBUSY;
331
332 if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
333 return PTR_ERR(p);
334
335 if ((err = br_fdb_insert(br, p, dev->dev_addr)))
336 destroy_nbp(p);
337
338 else if ((err = br_sysfs_addif(p)))
339 del_nbp(p);
340 else {
341 dev_set_promiscuity(dev, 1);
342
343 list_add_rcu(&p->list, &br->port_list);
344
345 spin_lock_bh(&br->lock);
346 br_stp_recalculate_bridge_id(br);
347 if ((br->dev->flags & IFF_UP)
348 && (dev->flags & IFF_UP) && netif_carrier_ok(dev))
349 br_stp_enable_port(p);
350 spin_unlock_bh(&br->lock);
351
352 dev_set_mtu(br->dev, br_min_mtu(br));
353 }
354
355 return err;
356}
357
358/* called with RTNL */
359int br_del_if(struct net_bridge *br, struct net_device *dev)
360{
361 struct net_bridge_port *p = dev->br_port;
362
363 if (!p || p->br != br)
364 return -EINVAL;
365
366 br_sysfs_removeif(p);
367 del_nbp(p);
368
369 spin_lock_bh(&br->lock);
370 br_stp_recalculate_bridge_id(br);
371 spin_unlock_bh(&br->lock);
372
373 return 0;
374}
375
376void __exit br_cleanup_bridges(void)
377{
378 struct net_device *dev, *nxt;
379
380 rtnl_lock();
381 for (dev = dev_base; dev; dev = nxt) {
382 nxt = dev->next;
383 if (dev->priv_flags & IFF_EBRIDGE)
384 del_br(dev->priv);
385 }
386 rtnl_unlock();
387
388}
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
new file mode 100644
index 000000000000..2b1cce46cab4
--- /dev/null
+++ b/net/bridge/br_input.c
@@ -0,0 +1,144 @@
1/*
2 * Handle incoming frames
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_input.c,v 1.10 2001/12/24 04:50:20 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
19#include <linux/netfilter_bridge.h>
20#include "br_private.h"
21
22const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
23
24static int br_pass_frame_up_finish(struct sk_buff *skb)
25{
26#ifdef CONFIG_NETFILTER_DEBUG
27 skb->nf_debug = 0;
28#endif
29 netif_rx(skb);
30
31 return 0;
32}
33
34static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
35{
36 struct net_device *indev;
37
38 br->statistics.rx_packets++;
39 br->statistics.rx_bytes += skb->len;
40
41 indev = skb->dev;
42 skb->dev = br->dev;
43
44 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
45 br_pass_frame_up_finish);
46}
47
48/* note: already called with rcu_read_lock (preempt_disabled) */
49int br_handle_frame_finish(struct sk_buff *skb)
50{
51 const unsigned char *dest = eth_hdr(skb)->h_dest;
52 struct net_bridge_port *p = skb->dev->br_port;
53 struct net_bridge *br = p->br;
54 struct net_bridge_fdb_entry *dst;
55 int passedup = 0;
56
57 if (br->dev->flags & IFF_PROMISC) {
58 struct sk_buff *skb2;
59
60 skb2 = skb_clone(skb, GFP_ATOMIC);
61 if (skb2 != NULL) {
62 passedup = 1;
63 br_pass_frame_up(br, skb2);
64 }
65 }
66
67 if (dest[0] & 1) {
68 br_flood_forward(br, skb, !passedup);
69 if (!passedup)
70 br_pass_frame_up(br, skb);
71 goto out;
72 }
73
74 dst = __br_fdb_get(br, dest);
75 if (dst != NULL && dst->is_local) {
76 if (!passedup)
77 br_pass_frame_up(br, skb);
78 else
79 kfree_skb(skb);
80 goto out;
81 }
82
83 if (dst != NULL) {
84 br_forward(dst->dst, skb);
85 goto out;
86 }
87
88 br_flood_forward(br, skb, 0);
89
90out:
91 return 0;
92}
93
94/*
95 * Called via br_handle_frame_hook.
96 * Return 0 if *pskb should be processed furthur
97 * 1 if *pskb is handled
98 * note: already called with rcu_read_lock (preempt_disabled)
99 */
100int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
101{
102 struct sk_buff *skb = *pskb;
103 const unsigned char *dest = eth_hdr(skb)->h_dest;
104
105 if (p->state == BR_STATE_DISABLED)
106 goto err;
107
108 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
109 goto err;
110
111 if (p->state == BR_STATE_LEARNING ||
112 p->state == BR_STATE_FORWARDING)
113 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
114
115 if (p->br->stp_enabled &&
116 !memcmp(dest, bridge_ula, 5) &&
117 !(dest[5] & 0xF0)) {
118 if (!dest[5]) {
119 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
120 NULL, br_stp_handle_bpdu);
121 return 1;
122 }
123 }
124
125 else if (p->state == BR_STATE_FORWARDING) {
126 if (br_should_route_hook) {
127 if (br_should_route_hook(pskb))
128 return 0;
129 skb = *pskb;
130 dest = eth_hdr(skb)->h_dest;
131 }
132
133 if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
134 skb->pkt_type = PACKET_HOST;
135
136 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
137 br_handle_frame_finish);
138 return 1;
139 }
140
141err:
142 kfree_skb(skb);
143 return 1;
144}
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
new file mode 100644
index 000000000000..b8ce14b22181
--- /dev/null
+++ b/net/bridge/br_ioctl.c
@@ -0,0 +1,410 @@
1/*
2 * Ioctl handler
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_ioctl.c,v 1.4 2000/11/08 05:16:40 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/if_bridge.h>
18#include <linux/netdevice.h>
19#include <linux/times.h>
20#include <asm/uaccess.h>
21#include "br_private.h"
22
23/* called with RTNL */
24static int get_bridge_ifindices(int *indices, int num)
25{
26 struct net_device *dev;
27 int i = 0;
28
29 for (dev = dev_base; dev && i < num; dev = dev->next) {
30 if (dev->priv_flags & IFF_EBRIDGE)
31 indices[i++] = dev->ifindex;
32 }
33
34 return i;
35}
36
37/* called with RTNL */
38static void get_port_ifindices(struct net_bridge *br, int *ifindices, int num)
39{
40 struct net_bridge_port *p;
41
42 list_for_each_entry(p, &br->port_list, list) {
43 if (p->port_no < num)
44 ifindices[p->port_no] = p->dev->ifindex;
45 }
46}
47
48/*
49 * Format up to a page worth of forwarding table entries
50 * userbuf -- where to copy result
51 * maxnum -- maximum number of entries desired
52 * (limited to a page for sanity)
53 * offset -- number of records to skip
54 */
55static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
56 unsigned long maxnum, unsigned long offset)
57{
58 int num;
59 void *buf;
60 size_t size = maxnum * sizeof(struct __fdb_entry);
61
62 if (size > PAGE_SIZE) {
63 size = PAGE_SIZE;
64 maxnum = PAGE_SIZE/sizeof(struct __fdb_entry);
65 }
66
67 buf = kmalloc(size, GFP_USER);
68 if (!buf)
69 return -ENOMEM;
70
71 num = br_fdb_fillbuf(br, buf, maxnum, offset);
72 if (num > 0) {
73 if (copy_to_user(userbuf, buf, num*sizeof(struct __fdb_entry)))
74 num = -EFAULT;
75 }
76 kfree(buf);
77
78 return num;
79}
80
81static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
82{
83 struct net_device *dev;
84 int ret;
85
86 if (!capable(CAP_NET_ADMIN))
87 return -EPERM;
88
89 dev = dev_get_by_index(ifindex);
90 if (dev == NULL)
91 return -EINVAL;
92
93 if (isadd)
94 ret = br_add_if(br, dev);
95 else
96 ret = br_del_if(br, dev);
97
98 dev_put(dev);
99 return ret;
100}
101
102/*
103 * Legacy ioctl's through SIOCDEVPRIVATE
104 * This interface is deprecated because it was too difficult to
105 * to do the translation for 32/64bit ioctl compatability.
106 */
107static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
108{
109 struct net_bridge *br = netdev_priv(dev);
110 unsigned long args[4];
111
112 if (copy_from_user(args, rq->ifr_data, sizeof(args)))
113 return -EFAULT;
114
115 switch (args[0]) {
116 case BRCTL_ADD_IF:
117 case BRCTL_DEL_IF:
118 return add_del_if(br, args[1], args[0] == BRCTL_ADD_IF);
119
120 case BRCTL_GET_BRIDGE_INFO:
121 {
122 struct __bridge_info b;
123
124 memset(&b, 0, sizeof(struct __bridge_info));
125 rcu_read_lock();
126 memcpy(&b.designated_root, &br->designated_root, 8);
127 memcpy(&b.bridge_id, &br->bridge_id, 8);
128 b.root_path_cost = br->root_path_cost;
129 b.max_age = jiffies_to_clock_t(br->max_age);
130 b.hello_time = jiffies_to_clock_t(br->hello_time);
131 b.forward_delay = br->forward_delay;
132 b.bridge_max_age = br->bridge_max_age;
133 b.bridge_hello_time = br->bridge_hello_time;
134 b.bridge_forward_delay = jiffies_to_clock_t(br->bridge_forward_delay);
135 b.topology_change = br->topology_change;
136 b.topology_change_detected = br->topology_change_detected;
137 b.root_port = br->root_port;
138 b.stp_enabled = br->stp_enabled;
139 b.ageing_time = jiffies_to_clock_t(br->ageing_time);
140 b.hello_timer_value = br_timer_value(&br->hello_timer);
141 b.tcn_timer_value = br_timer_value(&br->tcn_timer);
142 b.topology_change_timer_value = br_timer_value(&br->topology_change_timer);
143 b.gc_timer_value = br_timer_value(&br->gc_timer);
144 rcu_read_unlock();
145
146 if (copy_to_user((void __user *)args[1], &b, sizeof(b)))
147 return -EFAULT;
148
149 return 0;
150 }
151
152 case BRCTL_GET_PORT_LIST:
153 {
154 int num, *indices;
155
156 num = args[2];
157 if (num < 0)
158 return -EINVAL;
159 if (num == 0)
160 num = 256;
161 if (num > BR_MAX_PORTS)
162 num = BR_MAX_PORTS;
163
164 indices = kmalloc(num*sizeof(int), GFP_KERNEL);
165 if (indices == NULL)
166 return -ENOMEM;
167
168 memset(indices, 0, num*sizeof(int));
169
170 get_port_ifindices(br, indices, num);
171 if (copy_to_user((void __user *)args[1], indices, num*sizeof(int)))
172 num = -EFAULT;
173 kfree(indices);
174 return num;
175 }
176
177 case BRCTL_SET_BRIDGE_FORWARD_DELAY:
178 if (!capable(CAP_NET_ADMIN))
179 return -EPERM;
180
181 spin_lock_bh(&br->lock);
182 br->bridge_forward_delay = clock_t_to_jiffies(args[1]);
183 if (br_is_root_bridge(br))
184 br->forward_delay = br->bridge_forward_delay;
185 spin_unlock_bh(&br->lock);
186 return 0;
187
188 case BRCTL_SET_BRIDGE_HELLO_TIME:
189 if (!capable(CAP_NET_ADMIN))
190 return -EPERM;
191
192 spin_lock_bh(&br->lock);
193 br->bridge_hello_time = clock_t_to_jiffies(args[1]);
194 if (br_is_root_bridge(br))
195 br->hello_time = br->bridge_hello_time;
196 spin_unlock_bh(&br->lock);
197 return 0;
198
199 case BRCTL_SET_BRIDGE_MAX_AGE:
200 if (!capable(CAP_NET_ADMIN))
201 return -EPERM;
202
203 spin_lock_bh(&br->lock);
204 br->bridge_max_age = clock_t_to_jiffies(args[1]);
205 if (br_is_root_bridge(br))
206 br->max_age = br->bridge_max_age;
207 spin_unlock_bh(&br->lock);
208 return 0;
209
210 case BRCTL_SET_AGEING_TIME:
211 if (!capable(CAP_NET_ADMIN))
212 return -EPERM;
213
214 br->ageing_time = clock_t_to_jiffies(args[1]);
215 return 0;
216
217 case BRCTL_GET_PORT_INFO:
218 {
219 struct __port_info p;
220 struct net_bridge_port *pt;
221
222 rcu_read_lock();
223 if ((pt = br_get_port(br, args[2])) == NULL) {
224 rcu_read_unlock();
225 return -EINVAL;
226 }
227
228 memset(&p, 0, sizeof(struct __port_info));
229 memcpy(&p.designated_root, &pt->designated_root, 8);
230 memcpy(&p.designated_bridge, &pt->designated_bridge, 8);
231 p.port_id = pt->port_id;
232 p.designated_port = pt->designated_port;
233 p.path_cost = pt->path_cost;
234 p.designated_cost = pt->designated_cost;
235 p.state = pt->state;
236 p.top_change_ack = pt->topology_change_ack;
237 p.config_pending = pt->config_pending;
238 p.message_age_timer_value = br_timer_value(&pt->message_age_timer);
239 p.forward_delay_timer_value = br_timer_value(&pt->forward_delay_timer);
240 p.hold_timer_value = br_timer_value(&pt->hold_timer);
241
242 rcu_read_unlock();
243
244 if (copy_to_user((void __user *)args[1], &p, sizeof(p)))
245 return -EFAULT;
246
247 return 0;
248 }
249
250 case BRCTL_SET_BRIDGE_STP_STATE:
251 if (!capable(CAP_NET_ADMIN))
252 return -EPERM;
253
254 br->stp_enabled = args[1]?1:0;
255 return 0;
256
257 case BRCTL_SET_BRIDGE_PRIORITY:
258 if (!capable(CAP_NET_ADMIN))
259 return -EPERM;
260
261 spin_lock_bh(&br->lock);
262 br_stp_set_bridge_priority(br, args[1]);
263 spin_unlock_bh(&br->lock);
264 return 0;
265
266 case BRCTL_SET_PORT_PRIORITY:
267 {
268 struct net_bridge_port *p;
269 int ret = 0;
270
271 if (!capable(CAP_NET_ADMIN))
272 return -EPERM;
273
274 if (args[2] >= (1<<(16-BR_PORT_BITS)))
275 return -ERANGE;
276
277 spin_lock_bh(&br->lock);
278 if ((p = br_get_port(br, args[1])) == NULL)
279 ret = -EINVAL;
280 else
281 br_stp_set_port_priority(p, args[2]);
282 spin_unlock_bh(&br->lock);
283 return ret;
284 }
285
286 case BRCTL_SET_PATH_COST:
287 {
288 struct net_bridge_port *p;
289 int ret = 0;
290
291 if (!capable(CAP_NET_ADMIN))
292 return -EPERM;
293
294 spin_lock_bh(&br->lock);
295 if ((p = br_get_port(br, args[1])) == NULL)
296 ret = -EINVAL;
297 else
298 br_stp_set_path_cost(p, args[2]);
299 spin_unlock_bh(&br->lock);
300 return ret;
301 }
302
303 case BRCTL_GET_FDB_ENTRIES:
304 return get_fdb_entries(br, (void __user *)args[1],
305 args[2], args[3]);
306 }
307
308 return -EOPNOTSUPP;
309}
310
311static int old_deviceless(void __user *uarg)
312{
313 unsigned long args[3];
314
315 if (copy_from_user(args, uarg, sizeof(args)))
316 return -EFAULT;
317
318 switch (args[0]) {
319 case BRCTL_GET_VERSION:
320 return BRCTL_VERSION;
321
322 case BRCTL_GET_BRIDGES:
323 {
324 int *indices;
325 int ret = 0;
326
327 if (args[2] >= 2048)
328 return -ENOMEM;
329 indices = kmalloc(args[2]*sizeof(int), GFP_KERNEL);
330 if (indices == NULL)
331 return -ENOMEM;
332
333 memset(indices, 0, args[2]*sizeof(int));
334 args[2] = get_bridge_ifindices(indices, args[2]);
335
336 ret = copy_to_user((void __user *)args[1], indices, args[2]*sizeof(int))
337 ? -EFAULT : args[2];
338
339 kfree(indices);
340 return ret;
341 }
342
343 case BRCTL_ADD_BRIDGE:
344 case BRCTL_DEL_BRIDGE:
345 {
346 char buf[IFNAMSIZ];
347
348 if (!capable(CAP_NET_ADMIN))
349 return -EPERM;
350
351 if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
352 return -EFAULT;
353
354 buf[IFNAMSIZ-1] = 0;
355
356 if (args[0] == BRCTL_ADD_BRIDGE)
357 return br_add_bridge(buf);
358
359 return br_del_bridge(buf);
360 }
361 }
362
363 return -EOPNOTSUPP;
364}
365
366int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
367{
368 switch (cmd) {
369 case SIOCGIFBR:
370 case SIOCSIFBR:
371 return old_deviceless(uarg);
372
373 case SIOCBRADDBR:
374 case SIOCBRDELBR:
375 {
376 char buf[IFNAMSIZ];
377
378 if (!capable(CAP_NET_ADMIN))
379 return -EPERM;
380
381 if (copy_from_user(buf, uarg, IFNAMSIZ))
382 return -EFAULT;
383
384 buf[IFNAMSIZ-1] = 0;
385 if (cmd == SIOCBRADDBR)
386 return br_add_bridge(buf);
387
388 return br_del_bridge(buf);
389 }
390 }
391 return -EOPNOTSUPP;
392}
393
394int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
395{
396 struct net_bridge *br = netdev_priv(dev);
397
398 switch(cmd) {
399 case SIOCDEVPRIVATE:
400 return old_dev_ioctl(dev, rq, cmd);
401
402 case SIOCBRADDIF:
403 case SIOCBRDELIF:
404 return add_del_if(br, rq->ifr_ifindex, cmd == SIOCBRADDIF);
405
406 }
407
408 pr_debug("Bridge does not support ioctl 0x%x\n", cmd);
409 return -EOPNOTSUPP;
410}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
new file mode 100644
index 000000000000..be03d3ad2648
--- /dev/null
+++ b/net/bridge/br_netfilter.c
@@ -0,0 +1,1087 @@
1/*
2 * Handle firewalling
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 * Bart De Schuymer (maintainer) <bdschuym@pandora.be>
8 *
9 * Changes:
10 * Apr 29 2003: physdev module support (bdschuym)
11 * Jun 19 2003: let arptables see bridged ARP traffic (bdschuym)
12 * Oct 06 2003: filter encapsulated IP/ARP VLAN traffic on untagged bridge
13 * (bdschuym)
14 * Sep 01 2004: add IPv6 filtering (bdschuym)
15 *
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
20 *
21 * Lennert dedicates this file to Kerstin Wurdinger.
22 */
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/ip.h>
27#include <linux/netdevice.h>
28#include <linux/skbuff.h>
29#include <linux/if_ether.h>
30#include <linux/if_vlan.h>
31#include <linux/netfilter_bridge.h>
32#include <linux/netfilter_ipv4.h>
33#include <linux/netfilter_ipv6.h>
34#include <linux/netfilter_arp.h>
35#include <linux/in_route.h>
36#include <net/ip.h>
37#include <net/ipv6.h>
38#include <asm/uaccess.h>
39#include <asm/checksum.h>
40#include "br_private.h"
41#ifdef CONFIG_SYSCTL
42#include <linux/sysctl.h>
43#endif
44
45#define skb_origaddr(skb) (((struct bridge_skb_cb *) \
46 (skb->nf_bridge->data))->daddr.ipv4)
47#define store_orig_dstaddr(skb) (skb_origaddr(skb) = (skb)->nh.iph->daddr)
48#define dnat_took_place(skb) (skb_origaddr(skb) != (skb)->nh.iph->daddr)
49
50#define has_bridge_parent(device) ((device)->br_port != NULL)
51#define bridge_parent(device) ((device)->br_port->br->dev)
52
53#ifdef CONFIG_SYSCTL
54static struct ctl_table_header *brnf_sysctl_header;
55static int brnf_call_iptables = 1;
56static int brnf_call_ip6tables = 1;
57static int brnf_call_arptables = 1;
58static int brnf_filter_vlan_tagged = 1;
59#else
60#define brnf_filter_vlan_tagged 1
61#endif
62
63#define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
64 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) && \
65 brnf_filter_vlan_tagged)
66#define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) && \
67 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) && \
68 brnf_filter_vlan_tagged)
69#define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \
70 hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \
71 brnf_filter_vlan_tagged)
72
73/* We need these fake structures to make netfilter happy --
74 * lots of places assume that skb->dst != NULL, which isn't
75 * all that unreasonable.
76 *
77 * Currently, we fill in the PMTU entry because netfilter
78 * refragmentation needs it, and the rt_flags entry because
79 * ipt_REJECT needs it. Future netfilter modules might
80 * require us to fill additional fields. */
81static struct net_device __fake_net_device = {
82 .hard_header_len = ETH_HLEN
83};
84
85static struct rtable __fake_rtable = {
86 .u = {
87 .dst = {
88 .__refcnt = ATOMIC_INIT(1),
89 .dev = &__fake_net_device,
90 .path = &__fake_rtable.u.dst,
91 .metrics = {[RTAX_MTU - 1] = 1500},
92 }
93 },
94 .rt_flags = 0,
95};
96
97
98/* PF_BRIDGE/PRE_ROUTING *********************************************/
99/* Undo the changes made for ip6tables PREROUTING and continue the
100 * bridge PRE_ROUTING hook. */
101static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
102{
103 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
104
105#ifdef CONFIG_NETFILTER_DEBUG
106 skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
107#endif
108
109 if (nf_bridge->mask & BRNF_PKT_TYPE) {
110 skb->pkt_type = PACKET_OTHERHOST;
111 nf_bridge->mask ^= BRNF_PKT_TYPE;
112 }
113 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
114
115 skb->dst = (struct dst_entry *)&__fake_rtable;
116 dst_hold(skb->dst);
117
118 skb->dev = nf_bridge->physindev;
119 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
120 skb_push(skb, VLAN_HLEN);
121 skb->nh.raw -= VLAN_HLEN;
122 }
123 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
124 br_handle_frame_finish, 1);
125
126 return 0;
127}
128
129static void __br_dnat_complain(void)
130{
131 static unsigned long last_complaint;
132
133 if (jiffies - last_complaint >= 5 * HZ) {
134 printk(KERN_WARNING "Performing cross-bridge DNAT requires IP "
135 "forwarding to be enabled\n");
136 last_complaint = jiffies;
137 }
138}
139
140/* This requires some explaining. If DNAT has taken place,
141 * we will need to fix up the destination Ethernet address,
142 * and this is a tricky process.
143 *
144 * There are two cases to consider:
145 * 1. The packet was DNAT'ed to a device in the same bridge
146 * port group as it was received on. We can still bridge
147 * the packet.
148 * 2. The packet was DNAT'ed to a different device, either
149 * a non-bridged device or another bridge port group.
150 * The packet will need to be routed.
151 *
152 * The correct way of distinguishing between these two cases is to
153 * call ip_route_input() and to look at skb->dst->dev, which is
154 * changed to the destination device if ip_route_input() succeeds.
155 *
156 * Let us first consider the case that ip_route_input() succeeds:
157 *
158 * If skb->dst->dev equals the logical bridge device the packet
159 * came in on, we can consider this bridging. We then call
160 * skb->dst->output() which will make the packet enter br_nf_local_out()
161 * not much later. In that function it is assured that the iptables
162 * FORWARD chain is traversed for the packet.
163 *
164 * Otherwise, the packet is considered to be routed and we just
165 * change the destination MAC address so that the packet will
166 * later be passed up to the IP stack to be routed.
167 *
168 * Let us now consider the case that ip_route_input() fails:
169 *
170 * After a "echo '0' > /proc/sys/net/ipv4/ip_forward" ip_route_input()
171 * will fail, while __ip_route_output_key() will return success. The source
172 * address for __ip_route_output_key() is set to zero, so __ip_route_output_key
173 * thinks we're handling a locally generated packet and won't care
174 * if IP forwarding is allowed. We send a warning message to the users's
175 * log telling her to put IP forwarding on.
176 *
177 * ip_route_input() will also fail if there is no route available.
178 * In that case we just drop the packet.
179 *
180 * --Lennert, 20020411
181 * --Bart, 20020416 (updated)
182 * --Bart, 20021007 (updated) */
183static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
184{
185#ifdef CONFIG_NETFILTER_DEBUG
186 skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD);
187#endif
188
189 if (skb->pkt_type == PACKET_OTHERHOST) {
190 skb->pkt_type = PACKET_HOST;
191 skb->nf_bridge->mask |= BRNF_PKT_TYPE;
192 }
193 skb->nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
194
195 skb->dev = bridge_parent(skb->dev);
196 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
197 skb_pull(skb, VLAN_HLEN);
198 skb->nh.raw += VLAN_HLEN;
199 }
200 skb->dst->output(skb);
201 return 0;
202}
203
204static int br_nf_pre_routing_finish(struct sk_buff *skb)
205{
206 struct net_device *dev = skb->dev;
207 struct iphdr *iph = skb->nh.iph;
208 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
209
210#ifdef CONFIG_NETFILTER_DEBUG
211 skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
212#endif
213
214 if (nf_bridge->mask & BRNF_PKT_TYPE) {
215 skb->pkt_type = PACKET_OTHERHOST;
216 nf_bridge->mask ^= BRNF_PKT_TYPE;
217 }
218 nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
219
220 if (dnat_took_place(skb)) {
221 if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
222 dev)) {
223 struct rtable *rt;
224 struct flowi fl = { .nl_u =
225 { .ip4_u = { .daddr = iph->daddr, .saddr = 0 ,
226 .tos = RT_TOS(iph->tos)} }, .proto = 0};
227
228 if (!ip_route_output_key(&rt, &fl)) {
229 /* Bridged-and-DNAT'ed traffic doesn't
230 * require ip_forwarding. */
231 if (((struct dst_entry *)rt)->dev == dev) {
232 skb->dst = (struct dst_entry *)rt;
233 goto bridged_dnat;
234 }
235 __br_dnat_complain();
236 dst_release((struct dst_entry *)rt);
237 }
238 kfree_skb(skb);
239 return 0;
240 } else {
241 if (skb->dst->dev == dev) {
242bridged_dnat:
243 /* Tell br_nf_local_out this is a
244 * bridged frame */
245 nf_bridge->mask |= BRNF_BRIDGED_DNAT;
246 skb->dev = nf_bridge->physindev;
247 if (skb->protocol ==
248 __constant_htons(ETH_P_8021Q)) {
249 skb_push(skb, VLAN_HLEN);
250 skb->nh.raw -= VLAN_HLEN;
251 }
252 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING,
253 skb, skb->dev, NULL,
254 br_nf_pre_routing_finish_bridge,
255 1);
256 return 0;
257 }
258 memcpy(eth_hdr(skb)->h_dest, dev->dev_addr,
259 ETH_ALEN);
260 skb->pkt_type = PACKET_HOST;
261 }
262 } else {
263 skb->dst = (struct dst_entry *)&__fake_rtable;
264 dst_hold(skb->dst);
265 }
266
267 skb->dev = nf_bridge->physindev;
268 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
269 skb_push(skb, VLAN_HLEN);
270 skb->nh.raw -= VLAN_HLEN;
271 }
272 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
273 br_handle_frame_finish, 1);
274
275 return 0;
276}
277
278/* Some common code for IPv4/IPv6 */
279static void setup_pre_routing(struct sk_buff *skb)
280{
281 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
282
283 if (skb->pkt_type == PACKET_OTHERHOST) {
284 skb->pkt_type = PACKET_HOST;
285 nf_bridge->mask |= BRNF_PKT_TYPE;
286 }
287
288 nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;
289 nf_bridge->physindev = skb->dev;
290 skb->dev = bridge_parent(skb->dev);
291}
292
293/* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */
294static int check_hbh_len(struct sk_buff *skb)
295{
296 unsigned char *raw = (u8*)(skb->nh.ipv6h+1);
297 u32 pkt_len;
298 int off = raw - skb->nh.raw;
299 int len = (raw[1]+1)<<3;
300
301 if ((raw + len) - skb->data > skb_headlen(skb))
302 goto bad;
303
304 off += 2;
305 len -= 2;
306
307 while (len > 0) {
308 int optlen = raw[off+1]+2;
309
310 switch (skb->nh.raw[off]) {
311 case IPV6_TLV_PAD0:
312 optlen = 1;
313 break;
314
315 case IPV6_TLV_PADN:
316 break;
317
318 case IPV6_TLV_JUMBO:
319 if (skb->nh.raw[off+1] != 4 || (off&3) != 2)
320 goto bad;
321
322 pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2));
323
324 if (pkt_len > skb->len - sizeof(struct ipv6hdr))
325 goto bad;
326 if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
327 if (__pskb_trim(skb,
328 pkt_len + sizeof(struct ipv6hdr)))
329 goto bad;
330 if (skb->ip_summed == CHECKSUM_HW)
331 skb->ip_summed = CHECKSUM_NONE;
332 }
333 break;
334 default:
335 if (optlen > len)
336 goto bad;
337 break;
338 }
339 off += optlen;
340 len -= optlen;
341 }
342 if (len == 0)
343 return 0;
344bad:
345 return -1;
346
347}
348
349/* Replicate the checks that IPv6 does on packet reception and pass the packet
350 * to ip6tables, which doesn't support NAT, so things are fairly simple. */
351static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
352 struct sk_buff *skb, const struct net_device *in,
353 const struct net_device *out, int (*okfn)(struct sk_buff *))
354{
355 struct ipv6hdr *hdr;
356 u32 pkt_len;
357 struct nf_bridge_info *nf_bridge;
358
359 if (skb->len < sizeof(struct ipv6hdr))
360 goto inhdr_error;
361
362 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
363 goto inhdr_error;
364
365 hdr = skb->nh.ipv6h;
366
367 if (hdr->version != 6)
368 goto inhdr_error;
369
370 pkt_len = ntohs(hdr->payload_len);
371
372 if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
373 if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
374 goto inhdr_error;
375 if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
376 if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
377 goto inhdr_error;
378 if (skb->ip_summed == CHECKSUM_HW)
379 skb->ip_summed = CHECKSUM_NONE;
380 }
381 }
382 if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
383 goto inhdr_error;
384
385#ifdef CONFIG_NETFILTER_DEBUG
386 skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
387#endif
388 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
389 return NF_DROP;
390 setup_pre_routing(skb);
391
392 NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
393 br_nf_pre_routing_finish_ipv6);
394
395 return NF_STOLEN;
396
397inhdr_error:
398 return NF_DROP;
399}
400
401/* Direct IPv6 traffic to br_nf_pre_routing_ipv6.
402 * Replicate the checks that IPv4 does on packet reception.
403 * Set skb->dev to the bridge device (i.e. parent of the
404 * receiving device) to make netfilter happy, the REDIRECT
405 * target in particular. Save the original destination IP
406 * address to be able to detect DNAT afterwards. */
407static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
408 const struct net_device *in, const struct net_device *out,
409 int (*okfn)(struct sk_buff *))
410{
411 struct iphdr *iph;
412 __u32 len;
413 struct sk_buff *skb = *pskb;
414 struct nf_bridge_info *nf_bridge;
415 struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb);
416
417 if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) {
418#ifdef CONFIG_SYSCTL
419 if (!brnf_call_ip6tables)
420 return NF_ACCEPT;
421#endif
422 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
423 goto out;
424
425 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
426 skb_pull(skb, VLAN_HLEN);
427 (skb)->nh.raw += VLAN_HLEN;
428 }
429 return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
430 }
431#ifdef CONFIG_SYSCTL
432 if (!brnf_call_iptables)
433 return NF_ACCEPT;
434#endif
435
436 if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP)
437 return NF_ACCEPT;
438
439 if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
440 goto out;
441
442 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
443 skb_pull(skb, VLAN_HLEN);
444 (skb)->nh.raw += VLAN_HLEN;
445 }
446
447 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
448 goto inhdr_error;
449
450 iph = skb->nh.iph;
451 if (iph->ihl < 5 || iph->version != 4)
452 goto inhdr_error;
453
454 if (!pskb_may_pull(skb, 4*iph->ihl))
455 goto inhdr_error;
456
457 iph = skb->nh.iph;
458 if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0)
459 goto inhdr_error;
460
461 len = ntohs(iph->tot_len);
462 if (skb->len < len || len < 4*iph->ihl)
463 goto inhdr_error;
464
465 if (skb->len > len) {
466 __pskb_trim(skb, len);
467 if (skb->ip_summed == CHECKSUM_HW)
468 skb->ip_summed = CHECKSUM_NONE;
469 }
470
471#ifdef CONFIG_NETFILTER_DEBUG
472 skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
473#endif
474 if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
475 return NF_DROP;
476 setup_pre_routing(skb);
477 store_orig_dstaddr(skb);
478
479 NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
480 br_nf_pre_routing_finish);
481
482 return NF_STOLEN;
483
484inhdr_error:
485// IP_INC_STATS_BH(IpInHdrErrors);
486out:
487 return NF_DROP;
488}
489
490
491/* PF_BRIDGE/LOCAL_IN ************************************************/
492/* The packet is locally destined, which requires a real
493 * dst_entry, so detach the fake one. On the way up, the
494 * packet would pass through PRE_ROUTING again (which already
495 * took place when the packet entered the bridge), but we
496 * register an IPv4 PRE_ROUTING 'sabotage' hook that will
497 * prevent this from happening. */
498static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb,
499 const struct net_device *in, const struct net_device *out,
500 int (*okfn)(struct sk_buff *))
501{
502 struct sk_buff *skb = *pskb;
503
504 if (skb->dst == (struct dst_entry *)&__fake_rtable) {
505 dst_release(skb->dst);
506 skb->dst = NULL;
507 }
508
509 return NF_ACCEPT;
510}
511
512
513/* PF_BRIDGE/FORWARD *************************************************/
514static int br_nf_forward_finish(struct sk_buff *skb)
515{
516 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
517 struct net_device *in;
518 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
519
520#ifdef CONFIG_NETFILTER_DEBUG
521 skb->nf_debug ^= (1 << NF_BR_FORWARD);
522#endif
523
524 if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
525 in = nf_bridge->physindev;
526 if (nf_bridge->mask & BRNF_PKT_TYPE) {
527 skb->pkt_type = PACKET_OTHERHOST;
528 nf_bridge->mask ^= BRNF_PKT_TYPE;
529 }
530 } else {
531 in = *((struct net_device **)(skb->cb));
532 }
533 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
534 skb_push(skb, VLAN_HLEN);
535 skb->nh.raw -= VLAN_HLEN;
536 }
537 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in,
538 skb->dev, br_forward_finish, 1);
539 return 0;
540}
541
542/* This is the 'purely bridged' case. For IP, we pass the packet to
543 * netfilter with indev and outdev set to the bridge device,
544 * but we are still able to filter on the 'real' indev/outdev
545 * because of the physdev module. For ARP, indev and outdev are the
546 * bridge ports. */
547static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
548 const struct net_device *in, const struct net_device *out,
549 int (*okfn)(struct sk_buff *))
550{
551 struct sk_buff *skb = *pskb;
552 struct nf_bridge_info *nf_bridge;
553 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
554 int pf;
555
556 if (!skb->nf_bridge)
557 return NF_ACCEPT;
558
559 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
560 pf = PF_INET;
561 else
562 pf = PF_INET6;
563
564 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
565 skb_pull(*pskb, VLAN_HLEN);
566 (*pskb)->nh.raw += VLAN_HLEN;
567 }
568
569#ifdef CONFIG_NETFILTER_DEBUG
570 skb->nf_debug ^= (1 << NF_BR_FORWARD);
571#endif
572 nf_bridge = skb->nf_bridge;
573 if (skb->pkt_type == PACKET_OTHERHOST) {
574 skb->pkt_type = PACKET_HOST;
575 nf_bridge->mask |= BRNF_PKT_TYPE;
576 }
577
578 /* The physdev module checks on this */
579 nf_bridge->mask |= BRNF_BRIDGED;
580 nf_bridge->physoutdev = skb->dev;
581
582 NF_HOOK(pf, NF_IP_FORWARD, skb, bridge_parent(in),
583 bridge_parent(out), br_nf_forward_finish);
584
585 return NF_STOLEN;
586}
587
588static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
589 const struct net_device *in, const struct net_device *out,
590 int (*okfn)(struct sk_buff *))
591{
592 struct sk_buff *skb = *pskb;
593 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
594 struct net_device **d = (struct net_device **)(skb->cb);
595
596#ifdef CONFIG_SYSCTL
597 if (!brnf_call_arptables)
598 return NF_ACCEPT;
599#endif
600
601 if (skb->protocol != __constant_htons(ETH_P_ARP)) {
602 if (!IS_VLAN_ARP)
603 return NF_ACCEPT;
604 skb_pull(*pskb, VLAN_HLEN);
605 (*pskb)->nh.raw += VLAN_HLEN;
606 }
607
608#ifdef CONFIG_NETFILTER_DEBUG
609 skb->nf_debug ^= (1 << NF_BR_FORWARD);
610#endif
611
612 if (skb->nh.arph->ar_pln != 4) {
613 if (IS_VLAN_ARP) {
614 skb_push(*pskb, VLAN_HLEN);
615 (*pskb)->nh.raw -= VLAN_HLEN;
616 }
617 return NF_ACCEPT;
618 }
619 *d = (struct net_device *)in;
620 NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
621 (struct net_device *)out, br_nf_forward_finish);
622
623 return NF_STOLEN;
624}
625
626
627/* PF_BRIDGE/LOCAL_OUT ***********************************************/
628static int br_nf_local_out_finish(struct sk_buff *skb)
629{
630#ifdef CONFIG_NETFILTER_DEBUG
631 skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT);
632#endif
633 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
634 skb_push(skb, VLAN_HLEN);
635 skb->nh.raw -= VLAN_HLEN;
636 }
637
638 NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
639 br_forward_finish, NF_BR_PRI_FIRST + 1);
640
641 return 0;
642}
643
644/* This function sees both locally originated IP packets and forwarded
645 * IP packets (in both cases the destination device is a bridge
646 * device). It also sees bridged-and-DNAT'ed packets.
647 * To be able to filter on the physical bridge devices (with the physdev
648 * module), we steal packets destined to a bridge device away from the
649 * PF_INET/FORWARD and PF_INET/OUTPUT hook functions, and give them back later,
650 * when we have determined the real output device. This is done in here.
651 *
652 * If (nf_bridge->mask & BRNF_BRIDGED_DNAT) then the packet is bridged
653 * and we fake the PF_BRIDGE/FORWARD hook. The function br_nf_forward()
654 * will then fake the PF_INET/FORWARD hook. br_nf_local_out() has priority
655 * NF_BR_PRI_FIRST, so no relevant PF_BRIDGE/INPUT functions have been nor
656 * will be executed.
657 * Otherwise, if nf_bridge->physindev is NULL, the bridge-nf code never touched
658 * this packet before, and so the packet was locally originated. We fake
659 * the PF_INET/LOCAL_OUT hook.
660 * Finally, if nf_bridge->physindev isn't NULL, then the packet was IP routed,
661 * so we fake the PF_INET/FORWARD hook. ip_sabotage_out() makes sure
662 * even routed packets that didn't arrive on a bridge interface have their
663 * nf_bridge->physindev set. */
664static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
665 const struct net_device *in, const struct net_device *out,
666 int (*okfn)(struct sk_buff *))
667{
668 struct net_device *realindev, *realoutdev;
669 struct sk_buff *skb = *pskb;
670 struct nf_bridge_info *nf_bridge;
671 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
672 int pf;
673
674 if (!skb->nf_bridge)
675 return NF_ACCEPT;
676
677 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
678 pf = PF_INET;
679 else
680 pf = PF_INET6;
681
682#ifdef CONFIG_NETFILTER_DEBUG
683 /* Sometimes we get packets with NULL ->dst here (for example,
684 * running a dhcp client daemon triggers this). This should now
685 * be fixed, but let's keep the check around. */
686 if (skb->dst == NULL) {
687 printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
688 return NF_ACCEPT;
689 }
690#endif
691
692 nf_bridge = skb->nf_bridge;
693 nf_bridge->physoutdev = skb->dev;
694 realindev = nf_bridge->physindev;
695
696 /* Bridged, take PF_BRIDGE/FORWARD.
697 * (see big note in front of br_nf_pre_routing_finish) */
698 if (nf_bridge->mask & BRNF_BRIDGED_DNAT) {
699 if (nf_bridge->mask & BRNF_PKT_TYPE) {
700 skb->pkt_type = PACKET_OTHERHOST;
701 nf_bridge->mask ^= BRNF_PKT_TYPE;
702 }
703 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
704 skb_push(skb, VLAN_HLEN);
705 skb->nh.raw -= VLAN_HLEN;
706 }
707
708 NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, realindev,
709 skb->dev, br_forward_finish);
710 goto out;
711 }
712 realoutdev = bridge_parent(skb->dev);
713
714#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
715 /* iptables should match -o br0.x */
716 if (nf_bridge->netoutdev)
717 realoutdev = nf_bridge->netoutdev;
718#endif
719 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
720 skb_pull(skb, VLAN_HLEN);
721 (*pskb)->nh.raw += VLAN_HLEN;
722 }
723 /* IP forwarded traffic has a physindev, locally
724 * generated traffic hasn't. */
725 if (realindev != NULL) {
726 if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) &&
727 has_bridge_parent(realindev))
728 realindev = bridge_parent(realindev);
729
730 NF_HOOK_THRESH(pf, NF_IP_FORWARD, skb, realindev,
731 realoutdev, br_nf_local_out_finish,
732 NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
733 } else {
734#ifdef CONFIG_NETFILTER_DEBUG
735 skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
736#endif
737
738 NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
739 realoutdev, br_nf_local_out_finish,
740 NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
741 }
742
743out:
744 return NF_STOLEN;
745}
746
747
748/* PF_BRIDGE/POST_ROUTING ********************************************/
749static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
750 const struct net_device *in, const struct net_device *out,
751 int (*okfn)(struct sk_buff *))
752{
753 struct sk_buff *skb = *pskb;
754 struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge;
755 struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
756 struct net_device *realoutdev = bridge_parent(skb->dev);
757 int pf;
758
759#ifdef CONFIG_NETFILTER_DEBUG
760 /* Be very paranoid. This probably won't happen anymore, but let's
761 * keep the check just to be sure... */
762 if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) {
763 printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: "
764 "bad mac.raw pointer.");
765 goto print_error;
766 }
767#endif
768
769 if (!nf_bridge)
770 return NF_ACCEPT;
771
772 if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP)
773 pf = PF_INET;
774 else
775 pf = PF_INET6;
776
777#ifdef CONFIG_NETFILTER_DEBUG
778 if (skb->dst == NULL) {
779 printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
780 goto print_error;
781 }
782
783 skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
784#endif
785
786 /* We assume any code from br_dev_queue_push_xmit onwards doesn't care
787 * about the value of skb->pkt_type. */
788 if (skb->pkt_type == PACKET_OTHERHOST) {
789 skb->pkt_type = PACKET_HOST;
790 nf_bridge->mask |= BRNF_PKT_TYPE;
791 }
792
793 if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
794 skb_pull(skb, VLAN_HLEN);
795 skb->nh.raw += VLAN_HLEN;
796 }
797
798 nf_bridge_save_header(skb);
799
800#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
801 if (nf_bridge->netoutdev)
802 realoutdev = nf_bridge->netoutdev;
803#endif
804 NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev,
805 br_dev_queue_push_xmit);
806
807 return NF_STOLEN;
808
809#ifdef CONFIG_NETFILTER_DEBUG
810print_error:
811 if (skb->dev != NULL) {
812 printk("[%s]", skb->dev->name);
813 if (has_bridge_parent(skb->dev))
814 printk("[%s]", bridge_parent(skb->dev)->name);
815 }
816 printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw,
817 skb->data);
818 return NF_ACCEPT;
819#endif
820}
821
822
823/* IP/SABOTAGE *****************************************************/
824/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
825 * for the second time. */
826static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb,
827 const struct net_device *in, const struct net_device *out,
828 int (*okfn)(struct sk_buff *))
829{
830 if ((*pskb)->nf_bridge &&
831 !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
832 return NF_STOP;
833 }
834
835 return NF_ACCEPT;
836}
837
838/* Postpone execution of PF_INET(6)/FORWARD, PF_INET(6)/LOCAL_OUT
839 * and PF_INET(6)/POST_ROUTING until we have done the forwarding
840 * decision in the bridge code and have determined nf_bridge->physoutdev. */
841static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb,
842 const struct net_device *in, const struct net_device *out,
843 int (*okfn)(struct sk_buff *))
844{
845 struct sk_buff *skb = *pskb;
846
847 if ((out->hard_start_xmit == br_dev_xmit &&
848 okfn != br_nf_forward_finish &&
849 okfn != br_nf_local_out_finish &&
850 okfn != br_dev_queue_push_xmit)
851#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
852 || ((out->priv_flags & IFF_802_1Q_VLAN) &&
853 VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit)
854#endif
855 ) {
856 struct nf_bridge_info *nf_bridge;
857
858 if (!skb->nf_bridge) {
859#ifdef CONFIG_SYSCTL
860 /* This code is executed while in the IP(v6) stack,
861 the version should be 4 or 6. We can't use
862 skb->protocol because that isn't set on
863 PF_INET(6)/LOCAL_OUT. */
864 struct iphdr *ip = skb->nh.iph;
865
866 if (ip->version == 4 && !brnf_call_iptables)
867 return NF_ACCEPT;
868 else if (ip->version == 6 && !brnf_call_ip6tables)
869 return NF_ACCEPT;
870#endif
871 if (hook == NF_IP_POST_ROUTING)
872 return NF_ACCEPT;
873 if (!nf_bridge_alloc(skb))
874 return NF_DROP;
875 }
876
877 nf_bridge = skb->nf_bridge;
878
879 /* This frame will arrive on PF_BRIDGE/LOCAL_OUT and we
880 * will need the indev then. For a brouter, the real indev
881 * can be a bridge port, so we make sure br_nf_local_out()
882 * doesn't use the bridge parent of the indev by using
883 * the BRNF_DONT_TAKE_PARENT mask. */
884 if (hook == NF_IP_FORWARD && nf_bridge->physindev == NULL) {
885 nf_bridge->mask &= BRNF_DONT_TAKE_PARENT;
886 nf_bridge->physindev = (struct net_device *)in;
887 }
888#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
889 /* the iptables outdev is br0.x, not br0 */
890 if (out->priv_flags & IFF_802_1Q_VLAN)
891 nf_bridge->netoutdev = (struct net_device *)out;
892#endif
893 return NF_STOP;
894 }
895
896 return NF_ACCEPT;
897}
898
899/* For br_nf_local_out we need (prio = NF_BR_PRI_FIRST), to insure that innocent
900 * PF_BRIDGE/NF_BR_LOCAL_OUT functions don't get bridged traffic as input.
901 * For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
902 * ip_refrag() can return NF_STOLEN. */
903static struct nf_hook_ops br_nf_ops[] = {
904 { .hook = br_nf_pre_routing,
905 .owner = THIS_MODULE,
906 .pf = PF_BRIDGE,
907 .hooknum = NF_BR_PRE_ROUTING,
908 .priority = NF_BR_PRI_BRNF, },
909 { .hook = br_nf_local_in,
910 .owner = THIS_MODULE,
911 .pf = PF_BRIDGE,
912 .hooknum = NF_BR_LOCAL_IN,
913 .priority = NF_BR_PRI_BRNF, },
914 { .hook = br_nf_forward_ip,
915 .owner = THIS_MODULE,
916 .pf = PF_BRIDGE,
917 .hooknum = NF_BR_FORWARD,
918 .priority = NF_BR_PRI_BRNF - 1, },
919 { .hook = br_nf_forward_arp,
920 .owner = THIS_MODULE,
921 .pf = PF_BRIDGE,
922 .hooknum = NF_BR_FORWARD,
923 .priority = NF_BR_PRI_BRNF, },
924 { .hook = br_nf_local_out,
925 .owner = THIS_MODULE,
926 .pf = PF_BRIDGE,
927 .hooknum = NF_BR_LOCAL_OUT,
928 .priority = NF_BR_PRI_FIRST, },
929 { .hook = br_nf_post_routing,
930 .owner = THIS_MODULE,
931 .pf = PF_BRIDGE,
932 .hooknum = NF_BR_POST_ROUTING,
933 .priority = NF_BR_PRI_LAST, },
934 { .hook = ip_sabotage_in,
935 .owner = THIS_MODULE,
936 .pf = PF_INET,
937 .hooknum = NF_IP_PRE_ROUTING,
938 .priority = NF_IP_PRI_FIRST, },
939 { .hook = ip_sabotage_in,
940 .owner = THIS_MODULE,
941 .pf = PF_INET6,
942 .hooknum = NF_IP6_PRE_ROUTING,
943 .priority = NF_IP6_PRI_FIRST, },
944 { .hook = ip_sabotage_out,
945 .owner = THIS_MODULE,
946 .pf = PF_INET,
947 .hooknum = NF_IP_FORWARD,
948 .priority = NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD, },
949 { .hook = ip_sabotage_out,
950 .owner = THIS_MODULE,
951 .pf = PF_INET6,
952 .hooknum = NF_IP6_FORWARD,
953 .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD, },
954 { .hook = ip_sabotage_out,
955 .owner = THIS_MODULE,
956 .pf = PF_INET,
957 .hooknum = NF_IP_LOCAL_OUT,
958 .priority = NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
959 { .hook = ip_sabotage_out,
960 .owner = THIS_MODULE,
961 .pf = PF_INET6,
962 .hooknum = NF_IP6_LOCAL_OUT,
963 .priority = NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT, },
964 { .hook = ip_sabotage_out,
965 .owner = THIS_MODULE,
966 .pf = PF_INET,
967 .hooknum = NF_IP_POST_ROUTING,
968 .priority = NF_IP_PRI_FIRST, },
969 { .hook = ip_sabotage_out,
970 .owner = THIS_MODULE,
971 .pf = PF_INET6,
972 .hooknum = NF_IP6_POST_ROUTING,
973 .priority = NF_IP6_PRI_FIRST, },
974};
975
976#ifdef CONFIG_SYSCTL
977static
978int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp,
979 void __user *buffer, size_t *lenp, loff_t *ppos)
980{
981 int ret;
982
983 ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
984
985 if (write && *(int *)(ctl->data))
986 *(int *)(ctl->data) = 1;
987 return ret;
988}
989
990static ctl_table brnf_table[] = {
991 {
992 .ctl_name = NET_BRIDGE_NF_CALL_ARPTABLES,
993 .procname = "bridge-nf-call-arptables",
994 .data = &brnf_call_arptables,
995 .maxlen = sizeof(int),
996 .mode = 0644,
997 .proc_handler = &brnf_sysctl_call_tables,
998 },
999 {
1000 .ctl_name = NET_BRIDGE_NF_CALL_IPTABLES,
1001 .procname = "bridge-nf-call-iptables",
1002 .data = &brnf_call_iptables,
1003 .maxlen = sizeof(int),
1004 .mode = 0644,
1005 .proc_handler = &brnf_sysctl_call_tables,
1006 },
1007 {
1008 .ctl_name = NET_BRIDGE_NF_CALL_IP6TABLES,
1009 .procname = "bridge-nf-call-ip6tables",
1010 .data = &brnf_call_ip6tables,
1011 .maxlen = sizeof(int),
1012 .mode = 0644,
1013 .proc_handler = &brnf_sysctl_call_tables,
1014 },
1015 {
1016 .ctl_name = NET_BRIDGE_NF_FILTER_VLAN_TAGGED,
1017 .procname = "bridge-nf-filter-vlan-tagged",
1018 .data = &brnf_filter_vlan_tagged,
1019 .maxlen = sizeof(int),
1020 .mode = 0644,
1021 .proc_handler = &brnf_sysctl_call_tables,
1022 },
1023 { .ctl_name = 0 }
1024};
1025
1026static ctl_table brnf_bridge_table[] = {
1027 {
1028 .ctl_name = NET_BRIDGE,
1029 .procname = "bridge",
1030 .mode = 0555,
1031 .child = brnf_table,
1032 },
1033 { .ctl_name = 0 }
1034};
1035
1036static ctl_table brnf_net_table[] = {
1037 {
1038 .ctl_name = CTL_NET,
1039 .procname = "net",
1040 .mode = 0555,
1041 .child = brnf_bridge_table,
1042 },
1043 { .ctl_name = 0 }
1044};
1045#endif
1046
1047int br_netfilter_init(void)
1048{
1049 int i;
1050
1051 for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) {
1052 int ret;
1053
1054 if ((ret = nf_register_hook(&br_nf_ops[i])) >= 0)
1055 continue;
1056
1057 while (i--)
1058 nf_unregister_hook(&br_nf_ops[i]);
1059
1060 return ret;
1061 }
1062
1063#ifdef CONFIG_SYSCTL
1064 brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0);
1065 if (brnf_sysctl_header == NULL) {
1066 printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n");
1067 for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++)
1068 nf_unregister_hook(&br_nf_ops[i]);
1069 return -EFAULT;
1070 }
1071#endif
1072
1073 printk(KERN_NOTICE "Bridge firewalling registered\n");
1074
1075 return 0;
1076}
1077
1078void br_netfilter_fini(void)
1079{
1080 int i;
1081
1082 for (i = ARRAY_SIZE(br_nf_ops) - 1; i >= 0; i--)
1083 nf_unregister_hook(&br_nf_ops[i]);
1084#ifdef CONFIG_SYSCTL
1085 unregister_sysctl_table(brnf_sysctl_header);
1086#endif
1087}
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
new file mode 100644
index 000000000000..f8fb49e34764
--- /dev/null
+++ b/net/bridge/br_notify.c
@@ -0,0 +1,87 @@
1/*
2 * Device event handling
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_notify.c,v 1.2 2000/02/21 15:51:34 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17
18#include "br_private.h"
19
20static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr);
21
22struct notifier_block br_device_notifier = {
23 .notifier_call = br_device_event
24};
25
26/*
27 * Handle changes in state of network devices enslaved to a bridge.
28 *
29 * Note: don't care about up/down if bridge itself is down, because
30 * port state is checked when bridge is brought up.
31 */
32static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
33{
34 struct net_device *dev = ptr;
35 struct net_bridge_port *p = dev->br_port;
36 struct net_bridge *br;
37
38 /* not a port of a bridge */
39 if (p == NULL)
40 return NOTIFY_DONE;
41
42 br = p->br;
43
44 spin_lock_bh(&br->lock);
45 switch (event) {
46 case NETDEV_CHANGEMTU:
47 dev_set_mtu(br->dev, br_min_mtu(br));
48 break;
49
50 case NETDEV_CHANGEADDR:
51 br_fdb_changeaddr(p, dev->dev_addr);
52 br_stp_recalculate_bridge_id(br);
53 break;
54
55 case NETDEV_CHANGE: /* device is up but carrier changed */
56 if (!(br->dev->flags & IFF_UP))
57 break;
58
59 if (netif_carrier_ok(dev)) {
60 if (p->state == BR_STATE_DISABLED)
61 br_stp_enable_port(p);
62 } else {
63 if (p->state != BR_STATE_DISABLED)
64 br_stp_disable_port(p);
65 }
66 break;
67
68 case NETDEV_DOWN:
69 if (br->dev->flags & IFF_UP)
70 br_stp_disable_port(p);
71 break;
72
73 case NETDEV_UP:
74 if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP))
75 br_stp_enable_port(p);
76 break;
77
78 case NETDEV_UNREGISTER:
79 spin_unlock_bh(&br->lock);
80 br_del_if(br, dev);
81 goto done;
82 }
83 spin_unlock_bh(&br->lock);
84
85 done:
86 return NOTIFY_DONE;
87}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
new file mode 100644
index 000000000000..54d63f1372a0
--- /dev/null
+++ b/net/bridge/br_private.h
@@ -0,0 +1,244 @@
1/*
2 * Linux ethernet bridge
3 *
4 * Authors:
5 * Lennert Buytenhek <buytenh@gnu.org>
6 *
7 * $Id: br_private.h,v 1.7 2001/12/24 00:59:55 davem Exp $
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#ifndef _BR_PRIVATE_H
16#define _BR_PRIVATE_H
17
18#include <linux/netdevice.h>
19#include <linux/miscdevice.h>
20#include <linux/if_bridge.h>
21
22#define BR_HASH_BITS 8
23#define BR_HASH_SIZE (1 << BR_HASH_BITS)
24
25#define BR_HOLD_TIME (1*HZ)
26
27#define BR_PORT_BITS 10
28#define BR_MAX_PORTS (1<<BR_PORT_BITS)
29
30typedef struct bridge_id bridge_id;
31typedef struct mac_addr mac_addr;
32typedef __u16 port_id;
33
34struct bridge_id
35{
36 unsigned char prio[2];
37 unsigned char addr[6];
38};
39
40struct mac_addr
41{
42 unsigned char addr[6];
43};
44
45struct net_bridge_fdb_entry
46{
47 struct hlist_node hlist;
48 struct net_bridge_port *dst;
49
50 struct rcu_head rcu;
51 atomic_t use_count;
52 unsigned long ageing_timer;
53 mac_addr addr;
54 unsigned char is_local;
55 unsigned char is_static;
56};
57
58struct net_bridge_port
59{
60 struct net_bridge *br;
61 struct net_device *dev;
62 struct list_head list;
63
64 /* STP */
65 u8 priority;
66 u8 state;
67 u16 port_no;
68 unsigned char topology_change_ack;
69 unsigned char config_pending;
70 port_id port_id;
71 port_id designated_port;
72 bridge_id designated_root;
73 bridge_id designated_bridge;
74 u32 path_cost;
75 u32 designated_cost;
76
77 struct timer_list forward_delay_timer;
78 struct timer_list hold_timer;
79 struct timer_list message_age_timer;
80 struct kobject kobj;
81 struct rcu_head rcu;
82};
83
84struct net_bridge
85{
86 spinlock_t lock;
87 struct list_head port_list;
88 struct net_device *dev;
89 struct net_device_stats statistics;
90 spinlock_t hash_lock;
91 struct hlist_head hash[BR_HASH_SIZE];
92 struct list_head age_list;
93
94 /* STP */
95 bridge_id designated_root;
96 bridge_id bridge_id;
97 u32 root_path_cost;
98 unsigned long max_age;
99 unsigned long hello_time;
100 unsigned long forward_delay;
101 unsigned long bridge_max_age;
102 unsigned long ageing_time;
103 unsigned long bridge_hello_time;
104 unsigned long bridge_forward_delay;
105
106 u16 root_port;
107 unsigned char stp_enabled;
108 unsigned char topology_change;
109 unsigned char topology_change_detected;
110
111 struct timer_list hello_timer;
112 struct timer_list tcn_timer;
113 struct timer_list topology_change_timer;
114 struct timer_list gc_timer;
115 struct kobject ifobj;
116};
117
118extern struct notifier_block br_device_notifier;
119extern const unsigned char bridge_ula[6];
120
121/* called under bridge lock */
122static inline int br_is_root_bridge(const struct net_bridge *br)
123{
124 return !memcmp(&br->bridge_id, &br->designated_root, 8);
125}
126
127
128/* br_device.c */
129extern void br_dev_setup(struct net_device *dev);
130extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev);
131
132/* br_fdb.c */
133extern void br_fdb_init(void);
134extern void br_fdb_fini(void);
135extern void br_fdb_changeaddr(struct net_bridge_port *p,
136 const unsigned char *newaddr);
137extern void br_fdb_cleanup(unsigned long arg);
138extern void br_fdb_delete_by_port(struct net_bridge *br,
139 struct net_bridge_port *p);
140extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br,
141 const unsigned char *addr);
142extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
143 unsigned char *addr);
144extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
145extern int br_fdb_fillbuf(struct net_bridge *br, void *buf,
146 unsigned long count, unsigned long off);
147extern int br_fdb_insert(struct net_bridge *br,
148 struct net_bridge_port *source,
149 const unsigned char *addr);
150extern void br_fdb_update(struct net_bridge *br,
151 struct net_bridge_port *source,
152 const unsigned char *addr);
153
154/* br_forward.c */
155extern void br_deliver(const struct net_bridge_port *to,
156 struct sk_buff *skb);
157extern int br_dev_queue_push_xmit(struct sk_buff *skb);
158extern void br_forward(const struct net_bridge_port *to,
159 struct sk_buff *skb);
160extern int br_forward_finish(struct sk_buff *skb);
161extern void br_flood_deliver(struct net_bridge *br,
162 struct sk_buff *skb,
163 int clone);
164extern void br_flood_forward(struct net_bridge *br,
165 struct sk_buff *skb,
166 int clone);
167
168/* br_if.c */
169extern int br_add_bridge(const char *name);
170extern int br_del_bridge(const char *name);
171extern void br_cleanup_bridges(void);
172extern int br_add_if(struct net_bridge *br,
173 struct net_device *dev);
174extern int br_del_if(struct net_bridge *br,
175 struct net_device *dev);
176extern int br_min_mtu(const struct net_bridge *br);
177
178/* br_input.c */
179extern int br_handle_frame_finish(struct sk_buff *skb);
180extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb);
181
182/* br_ioctl.c */
183extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
184extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
185
186/* br_netfilter.c */
187extern int br_netfilter_init(void);
188extern void br_netfilter_fini(void);
189
190/* br_stp.c */
191extern void br_log_state(const struct net_bridge_port *p);
192extern struct net_bridge_port *br_get_port(struct net_bridge *br,
193 u16 port_no);
194extern void br_init_port(struct net_bridge_port *p);
195extern void br_become_designated_port(struct net_bridge_port *p);
196
197/* br_stp_if.c */
198extern void br_stp_enable_bridge(struct net_bridge *br);
199extern void br_stp_disable_bridge(struct net_bridge *br);
200extern void br_stp_enable_port(struct net_bridge_port *p);
201extern void br_stp_disable_port(struct net_bridge_port *p);
202extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
203extern void br_stp_set_bridge_priority(struct net_bridge *br,
204 u16 newprio);
205extern void br_stp_set_port_priority(struct net_bridge_port *p,
206 u8 newprio);
207extern void br_stp_set_path_cost(struct net_bridge_port *p,
208 u32 path_cost);
209extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id);
210
211/* br_stp_bpdu.c */
212extern int br_stp_handle_bpdu(struct sk_buff *skb);
213
214/* br_stp_timer.c */
215extern void br_stp_timer_init(struct net_bridge *br);
216extern void br_stp_port_timer_init(struct net_bridge_port *p);
217extern unsigned long br_timer_value(const struct timer_list *timer);
218
219/* br.c */
220extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
221 unsigned char *addr);
222extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
223
224
225#ifdef CONFIG_SYSFS
226/* br_sysfs_if.c */
227extern int br_sysfs_addif(struct net_bridge_port *p);
228extern void br_sysfs_removeif(struct net_bridge_port *p);
229extern void br_sysfs_freeif(struct net_bridge_port *p);
230
231/* br_sysfs_br.c */
232extern int br_sysfs_addbr(struct net_device *dev);
233extern void br_sysfs_delbr(struct net_device *dev);
234
235#else
236
237#define br_sysfs_addif(p) (0)
238#define br_sysfs_removeif(p) do { } while(0)
239#define br_sysfs_freeif(p) kfree(p)
240#define br_sysfs_addbr(dev) (0)
241#define br_sysfs_delbr(dev) do { } while(0)
242#endif /* CONFIG_SYSFS */
243
244#endif
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h
new file mode 100644
index 000000000000..e29f01ac1adf
--- /dev/null
+++ b/net/bridge/br_private_stp.h
@@ -0,0 +1,58 @@
1/*
2 * Linux ethernet bridge
3 *
4 * Authors:
5 * Lennert Buytenhek <buytenh@gnu.org>
6 *
7 * $Id: br_private_stp.h,v 1.3 2001/02/05 06:03:47 davem Exp $
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#ifndef _BR_PRIVATE_STP_H
16#define _BR_PRIVATE_STP_H
17
18#define BPDU_TYPE_CONFIG 0
19#define BPDU_TYPE_TCN 0x80
20
21struct br_config_bpdu
22{
23 unsigned topology_change:1;
24 unsigned topology_change_ack:1;
25 bridge_id root;
26 int root_path_cost;
27 bridge_id bridge_id;
28 port_id port_id;
29 int message_age;
30 int max_age;
31 int hello_time;
32 int forward_delay;
33};
34
35/* called under bridge lock */
36static inline int br_is_designated_port(const struct net_bridge_port *p)
37{
38 return !memcmp(&p->designated_bridge, &p->br->bridge_id, 8) &&
39 (p->designated_port == p->port_id);
40}
41
42
43/* br_stp.c */
44extern void br_become_root_bridge(struct net_bridge *br);
45extern void br_config_bpdu_generation(struct net_bridge *);
46extern void br_configuration_update(struct net_bridge *);
47extern void br_port_state_selection(struct net_bridge *);
48extern void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
49extern void br_received_tcn_bpdu(struct net_bridge_port *p);
50extern void br_transmit_config(struct net_bridge_port *p);
51extern void br_transmit_tcn(struct net_bridge *br);
52extern void br_topology_change_detection(struct net_bridge *br);
53
54/* br_stp_bpdu.c */
55extern void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
56extern void br_send_tcn_bpdu(struct net_bridge_port *);
57
58#endif
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
new file mode 100644
index 000000000000..04ca0639a95a
--- /dev/null
+++ b/net/bridge/br_stp.c
@@ -0,0 +1,459 @@
1/*
2 * Spanning tree protocol; generic parts
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_stp.c,v 1.4 2000/06/19 10:13:35 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15#include <linux/kernel.h>
16#include <linux/smp_lock.h>
17
18#include "br_private.h"
19#include "br_private_stp.h"
20
21/* since time values in bpdu are in jiffies and then scaled (1/256)
22 * before sending, make sure that is at least one.
23 */
24#define MESSAGE_AGE_INCR ((HZ < 256) ? 1 : (HZ/256))
25
26static const char *br_port_state_names[] = {
27 [BR_STATE_DISABLED] = "disabled",
28 [BR_STATE_LISTENING] = "listening",
29 [BR_STATE_LEARNING] = "learning",
30 [BR_STATE_FORWARDING] = "forwarding",
31 [BR_STATE_BLOCKING] = "blocking",
32};
33
34void br_log_state(const struct net_bridge_port *p)
35{
36 pr_info("%s: port %d(%s) entering %s state\n",
37 p->br->dev->name, p->port_no, p->dev->name,
38 br_port_state_names[p->state]);
39
40}
41
42/* called under bridge lock */
43struct net_bridge_port *br_get_port(struct net_bridge *br, u16 port_no)
44{
45 struct net_bridge_port *p;
46
47 list_for_each_entry_rcu(p, &br->port_list, list) {
48 if (p->port_no == port_no)
49 return p;
50 }
51
52 return NULL;
53}
54
55/* called under bridge lock */
56static int br_should_become_root_port(const struct net_bridge_port *p,
57 u16 root_port)
58{
59 struct net_bridge *br;
60 struct net_bridge_port *rp;
61 int t;
62
63 br = p->br;
64 if (p->state == BR_STATE_DISABLED ||
65 br_is_designated_port(p))
66 return 0;
67
68 if (memcmp(&br->bridge_id, &p->designated_root, 8) <= 0)
69 return 0;
70
71 if (!root_port)
72 return 1;
73
74 rp = br_get_port(br, root_port);
75
76 t = memcmp(&p->designated_root, &rp->designated_root, 8);
77 if (t < 0)
78 return 1;
79 else if (t > 0)
80 return 0;
81
82 if (p->designated_cost + p->path_cost <
83 rp->designated_cost + rp->path_cost)
84 return 1;
85 else if (p->designated_cost + p->path_cost >
86 rp->designated_cost + rp->path_cost)
87 return 0;
88
89 t = memcmp(&p->designated_bridge, &rp->designated_bridge, 8);
90 if (t < 0)
91 return 1;
92 else if (t > 0)
93 return 0;
94
95 if (p->designated_port < rp->designated_port)
96 return 1;
97 else if (p->designated_port > rp->designated_port)
98 return 0;
99
100 if (p->port_id < rp->port_id)
101 return 1;
102
103 return 0;
104}
105
106/* called under bridge lock */
107static void br_root_selection(struct net_bridge *br)
108{
109 struct net_bridge_port *p;
110 u16 root_port = 0;
111
112 list_for_each_entry(p, &br->port_list, list) {
113 if (br_should_become_root_port(p, root_port))
114 root_port = p->port_no;
115
116 }
117
118 br->root_port = root_port;
119
120 if (!root_port) {
121 br->designated_root = br->bridge_id;
122 br->root_path_cost = 0;
123 } else {
124 p = br_get_port(br, root_port);
125 br->designated_root = p->designated_root;
126 br->root_path_cost = p->designated_cost + p->path_cost;
127 }
128}
129
130/* called under bridge lock */
131void br_become_root_bridge(struct net_bridge *br)
132{
133 br->max_age = br->bridge_max_age;
134 br->hello_time = br->bridge_hello_time;
135 br->forward_delay = br->bridge_forward_delay;
136 br_topology_change_detection(br);
137 del_timer(&br->tcn_timer);
138
139 if (br->dev->flags & IFF_UP) {
140 br_config_bpdu_generation(br);
141 mod_timer(&br->hello_timer, jiffies + br->hello_time);
142 }
143}
144
145/* called under bridge lock */
146void br_transmit_config(struct net_bridge_port *p)
147{
148 struct br_config_bpdu bpdu;
149 struct net_bridge *br;
150
151
152 if (timer_pending(&p->hold_timer)) {
153 p->config_pending = 1;
154 return;
155 }
156
157 br = p->br;
158
159 bpdu.topology_change = br->topology_change;
160 bpdu.topology_change_ack = p->topology_change_ack;
161 bpdu.root = br->designated_root;
162 bpdu.root_path_cost = br->root_path_cost;
163 bpdu.bridge_id = br->bridge_id;
164 bpdu.port_id = p->port_id;
165 if (br_is_root_bridge(br))
166 bpdu.message_age = 0;
167 else {
168 struct net_bridge_port *root
169 = br_get_port(br, br->root_port);
170 bpdu.message_age = br->max_age
171 - (root->message_age_timer.expires - jiffies)
172 + MESSAGE_AGE_INCR;
173 }
174 bpdu.max_age = br->max_age;
175 bpdu.hello_time = br->hello_time;
176 bpdu.forward_delay = br->forward_delay;
177
178 if (bpdu.message_age < br->max_age) {
179 br_send_config_bpdu(p, &bpdu);
180 p->topology_change_ack = 0;
181 p->config_pending = 0;
182 mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);
183 }
184}
185
186/* called under bridge lock */
187static inline void br_record_config_information(struct net_bridge_port *p,
188 const struct br_config_bpdu *bpdu)
189{
190 p->designated_root = bpdu->root;
191 p->designated_cost = bpdu->root_path_cost;
192 p->designated_bridge = bpdu->bridge_id;
193 p->designated_port = bpdu->port_id;
194
195 mod_timer(&p->message_age_timer, jiffies
196 + (p->br->max_age - bpdu->message_age));
197}
198
199/* called under bridge lock */
200static inline void br_record_config_timeout_values(struct net_bridge *br,
201 const struct br_config_bpdu *bpdu)
202{
203 br->max_age = bpdu->max_age;
204 br->hello_time = bpdu->hello_time;
205 br->forward_delay = bpdu->forward_delay;
206 br->topology_change = bpdu->topology_change;
207}
208
209/* called under bridge lock */
210void br_transmit_tcn(struct net_bridge *br)
211{
212 br_send_tcn_bpdu(br_get_port(br, br->root_port));
213}
214
215/* called under bridge lock */
216static int br_should_become_designated_port(const struct net_bridge_port *p)
217{
218 struct net_bridge *br;
219 int t;
220
221 br = p->br;
222 if (br_is_designated_port(p))
223 return 1;
224
225 if (memcmp(&p->designated_root, &br->designated_root, 8))
226 return 1;
227
228 if (br->root_path_cost < p->designated_cost)
229 return 1;
230 else if (br->root_path_cost > p->designated_cost)
231 return 0;
232
233 t = memcmp(&br->bridge_id, &p->designated_bridge, 8);
234 if (t < 0)
235 return 1;
236 else if (t > 0)
237 return 0;
238
239 if (p->port_id < p->designated_port)
240 return 1;
241
242 return 0;
243}
244
245/* called under bridge lock */
246static void br_designated_port_selection(struct net_bridge *br)
247{
248 struct net_bridge_port *p;
249
250 list_for_each_entry(p, &br->port_list, list) {
251 if (p->state != BR_STATE_DISABLED &&
252 br_should_become_designated_port(p))
253 br_become_designated_port(p);
254
255 }
256}
257
258/* called under bridge lock */
259static int br_supersedes_port_info(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
260{
261 int t;
262
263 t = memcmp(&bpdu->root, &p->designated_root, 8);
264 if (t < 0)
265 return 1;
266 else if (t > 0)
267 return 0;
268
269 if (bpdu->root_path_cost < p->designated_cost)
270 return 1;
271 else if (bpdu->root_path_cost > p->designated_cost)
272 return 0;
273
274 t = memcmp(&bpdu->bridge_id, &p->designated_bridge, 8);
275 if (t < 0)
276 return 1;
277 else if (t > 0)
278 return 0;
279
280 if (memcmp(&bpdu->bridge_id, &p->br->bridge_id, 8))
281 return 1;
282
283 if (bpdu->port_id <= p->designated_port)
284 return 1;
285
286 return 0;
287}
288
289/* called under bridge lock */
290static inline void br_topology_change_acknowledged(struct net_bridge *br)
291{
292 br->topology_change_detected = 0;
293 del_timer(&br->tcn_timer);
294}
295
296/* called under bridge lock */
297void br_topology_change_detection(struct net_bridge *br)
298{
299 int isroot = br_is_root_bridge(br);
300
301 pr_info("%s: topology change detected, %s\n", br->dev->name,
302 isroot ? "propagating" : "sending tcn bpdu");
303
304 if (isroot) {
305 br->topology_change = 1;
306 mod_timer(&br->topology_change_timer, jiffies
307 + br->bridge_forward_delay + br->bridge_max_age);
308 } else if (!br->topology_change_detected) {
309 br_transmit_tcn(br);
310 mod_timer(&br->tcn_timer, jiffies + br->bridge_hello_time);
311 }
312
313 br->topology_change_detected = 1;
314}
315
316/* called under bridge lock */
317void br_config_bpdu_generation(struct net_bridge *br)
318{
319 struct net_bridge_port *p;
320
321 list_for_each_entry(p, &br->port_list, list) {
322 if (p->state != BR_STATE_DISABLED &&
323 br_is_designated_port(p))
324 br_transmit_config(p);
325 }
326}
327
328/* called under bridge lock */
329static inline void br_reply(struct net_bridge_port *p)
330{
331 br_transmit_config(p);
332}
333
334/* called under bridge lock */
335void br_configuration_update(struct net_bridge *br)
336{
337 br_root_selection(br);
338 br_designated_port_selection(br);
339}
340
341/* called under bridge lock */
342void br_become_designated_port(struct net_bridge_port *p)
343{
344 struct net_bridge *br;
345
346 br = p->br;
347 p->designated_root = br->designated_root;
348 p->designated_cost = br->root_path_cost;
349 p->designated_bridge = br->bridge_id;
350 p->designated_port = p->port_id;
351}
352
353
354/* called under bridge lock */
355static void br_make_blocking(struct net_bridge_port *p)
356{
357 if (p->state != BR_STATE_DISABLED &&
358 p->state != BR_STATE_BLOCKING) {
359 if (p->state == BR_STATE_FORWARDING ||
360 p->state == BR_STATE_LEARNING)
361 br_topology_change_detection(p->br);
362
363 p->state = BR_STATE_BLOCKING;
364 br_log_state(p);
365 del_timer(&p->forward_delay_timer);
366 }
367}
368
369/* called under bridge lock */
370static void br_make_forwarding(struct net_bridge_port *p)
371{
372 if (p->state == BR_STATE_BLOCKING) {
373 if (p->br->stp_enabled) {
374 p->state = BR_STATE_LISTENING;
375 } else {
376 p->state = BR_STATE_LEARNING;
377 }
378 br_log_state(p);
379 mod_timer(&p->forward_delay_timer, jiffies + p->br->forward_delay); }
380}
381
382/* called under bridge lock */
383void br_port_state_selection(struct net_bridge *br)
384{
385 struct net_bridge_port *p;
386
387 list_for_each_entry(p, &br->port_list, list) {
388 if (p->state != BR_STATE_DISABLED) {
389 if (p->port_no == br->root_port) {
390 p->config_pending = 0;
391 p->topology_change_ack = 0;
392 br_make_forwarding(p);
393 } else if (br_is_designated_port(p)) {
394 del_timer(&p->message_age_timer);
395 br_make_forwarding(p);
396 } else {
397 p->config_pending = 0;
398 p->topology_change_ack = 0;
399 br_make_blocking(p);
400 }
401 }
402
403 }
404}
405
406/* called under bridge lock */
407static inline void br_topology_change_acknowledge(struct net_bridge_port *p)
408{
409 p->topology_change_ack = 1;
410 br_transmit_config(p);
411}
412
413/* called under bridge lock */
414void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
415{
416 struct net_bridge *br;
417 int was_root;
418
419 br = p->br;
420 was_root = br_is_root_bridge(br);
421
422 if (br_supersedes_port_info(p, bpdu)) {
423 br_record_config_information(p, bpdu);
424 br_configuration_update(br);
425 br_port_state_selection(br);
426
427 if (!br_is_root_bridge(br) && was_root) {
428 del_timer(&br->hello_timer);
429 if (br->topology_change_detected) {
430 del_timer(&br->topology_change_timer);
431 br_transmit_tcn(br);
432
433 mod_timer(&br->tcn_timer,
434 jiffies + br->bridge_hello_time);
435 }
436 }
437
438 if (p->port_no == br->root_port) {
439 br_record_config_timeout_values(br, bpdu);
440 br_config_bpdu_generation(br);
441 if (bpdu->topology_change_ack)
442 br_topology_change_acknowledged(br);
443 }
444 } else if (br_is_designated_port(p)) {
445 br_reply(p);
446 }
447}
448
449/* called under bridge lock */
450void br_received_tcn_bpdu(struct net_bridge_port *p)
451{
452 if (br_is_designated_port(p)) {
453 pr_info("%s: received tcn bpdu on port %i(%s)\n",
454 p->br->dev->name, p->port_no, p->dev->name);
455
456 br_topology_change_detection(p->br);
457 br_topology_change_acknowledge(p);
458 }
459}
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
new file mode 100644
index 000000000000..b91a875aca01
--- /dev/null
+++ b/net/bridge/br_stp_bpdu.c
@@ -0,0 +1,205 @@
1/*
2 * Spanning tree protocol; BPDU handling
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_stp_bpdu.c,v 1.3 2001/11/10 02:35:25 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/netfilter_bridge.h>
18
19#include "br_private.h"
20#include "br_private_stp.h"
21
22#define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ)
23#define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8)
24
25static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length)
26{
27 struct net_device *dev;
28 struct sk_buff *skb;
29 int size;
30
31 if (!p->br->stp_enabled)
32 return;
33
34 size = length + 2*ETH_ALEN + 2;
35 if (size < 60)
36 size = 60;
37
38 dev = p->dev;
39
40 if ((skb = dev_alloc_skb(size)) == NULL) {
41 printk(KERN_INFO "br: memory squeeze!\n");
42 return;
43 }
44
45 skb->dev = dev;
46 skb->protocol = htons(ETH_P_802_2);
47 skb->mac.raw = skb_put(skb, size);
48 memcpy(skb->mac.raw, bridge_ula, ETH_ALEN);
49 memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN);
50 skb->mac.raw[2*ETH_ALEN] = 0;
51 skb->mac.raw[2*ETH_ALEN+1] = length;
52 skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2;
53 memcpy(skb->nh.raw, data, length);
54 memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2);
55
56 NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
57 dev_queue_xmit);
58}
59
60static __inline__ void br_set_ticks(unsigned char *dest, int jiff)
61{
62 __u16 ticks;
63
64 ticks = JIFFIES_TO_TICKS(jiff);
65 dest[0] = (ticks >> 8) & 0xFF;
66 dest[1] = ticks & 0xFF;
67}
68
69static __inline__ int br_get_ticks(unsigned char *dest)
70{
71 return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]);
72}
73
74/* called under bridge lock */
75void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)
76{
77 unsigned char buf[38];
78
79 buf[0] = 0x42;
80 buf[1] = 0x42;
81 buf[2] = 0x03;
82 buf[3] = 0;
83 buf[4] = 0;
84 buf[5] = 0;
85 buf[6] = BPDU_TYPE_CONFIG;
86 buf[7] = (bpdu->topology_change ? 0x01 : 0) |
87 (bpdu->topology_change_ack ? 0x80 : 0);
88 buf[8] = bpdu->root.prio[0];
89 buf[9] = bpdu->root.prio[1];
90 buf[10] = bpdu->root.addr[0];
91 buf[11] = bpdu->root.addr[1];
92 buf[12] = bpdu->root.addr[2];
93 buf[13] = bpdu->root.addr[3];
94 buf[14] = bpdu->root.addr[4];
95 buf[15] = bpdu->root.addr[5];
96 buf[16] = (bpdu->root_path_cost >> 24) & 0xFF;
97 buf[17] = (bpdu->root_path_cost >> 16) & 0xFF;
98 buf[18] = (bpdu->root_path_cost >> 8) & 0xFF;
99 buf[19] = bpdu->root_path_cost & 0xFF;
100 buf[20] = bpdu->bridge_id.prio[0];
101 buf[21] = bpdu->bridge_id.prio[1];
102 buf[22] = bpdu->bridge_id.addr[0];
103 buf[23] = bpdu->bridge_id.addr[1];
104 buf[24] = bpdu->bridge_id.addr[2];
105 buf[25] = bpdu->bridge_id.addr[3];
106 buf[26] = bpdu->bridge_id.addr[4];
107 buf[27] = bpdu->bridge_id.addr[5];
108 buf[28] = (bpdu->port_id >> 8) & 0xFF;
109 buf[29] = bpdu->port_id & 0xFF;
110
111 br_set_ticks(buf+30, bpdu->message_age);
112 br_set_ticks(buf+32, bpdu->max_age);
113 br_set_ticks(buf+34, bpdu->hello_time);
114 br_set_ticks(buf+36, bpdu->forward_delay);
115
116 br_send_bpdu(p, buf, 38);
117}
118
119/* called under bridge lock */
120void br_send_tcn_bpdu(struct net_bridge_port *p)
121{
122 unsigned char buf[7];
123
124 buf[0] = 0x42;
125 buf[1] = 0x42;
126 buf[2] = 0x03;
127 buf[3] = 0;
128 buf[4] = 0;
129 buf[5] = 0;
130 buf[6] = BPDU_TYPE_TCN;
131 br_send_bpdu(p, buf, 7);
132}
133
134static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
135
136/* NO locks */
137int br_stp_handle_bpdu(struct sk_buff *skb)
138{
139 struct net_bridge_port *p = skb->dev->br_port;
140 struct net_bridge *br = p->br;
141 unsigned char *buf;
142
143 /* need at least the 802 and STP headers */
144 if (!pskb_may_pull(skb, sizeof(header)+1) ||
145 memcmp(skb->data, header, sizeof(header)))
146 goto err;
147
148 buf = skb_pull(skb, sizeof(header));
149
150 spin_lock_bh(&br->lock);
151 if (p->state == BR_STATE_DISABLED
152 || !(br->dev->flags & IFF_UP)
153 || !br->stp_enabled)
154 goto out;
155
156 if (buf[0] == BPDU_TYPE_CONFIG) {
157 struct br_config_bpdu bpdu;
158
159 if (!pskb_may_pull(skb, 32))
160 goto out;
161
162 buf = skb->data;
163 bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0;
164 bpdu.topology_change_ack = (buf[1] & 0x80) ? 1 : 0;
165
166 bpdu.root.prio[0] = buf[2];
167 bpdu.root.prio[1] = buf[3];
168 bpdu.root.addr[0] = buf[4];
169 bpdu.root.addr[1] = buf[5];
170 bpdu.root.addr[2] = buf[6];
171 bpdu.root.addr[3] = buf[7];
172 bpdu.root.addr[4] = buf[8];
173 bpdu.root.addr[5] = buf[9];
174 bpdu.root_path_cost =
175 (buf[10] << 24) |
176 (buf[11] << 16) |
177 (buf[12] << 8) |
178 buf[13];
179 bpdu.bridge_id.prio[0] = buf[14];
180 bpdu.bridge_id.prio[1] = buf[15];
181 bpdu.bridge_id.addr[0] = buf[16];
182 bpdu.bridge_id.addr[1] = buf[17];
183 bpdu.bridge_id.addr[2] = buf[18];
184 bpdu.bridge_id.addr[3] = buf[19];
185 bpdu.bridge_id.addr[4] = buf[20];
186 bpdu.bridge_id.addr[5] = buf[21];
187 bpdu.port_id = (buf[22] << 8) | buf[23];
188
189 bpdu.message_age = br_get_ticks(buf+24);
190 bpdu.max_age = br_get_ticks(buf+26);
191 bpdu.hello_time = br_get_ticks(buf+28);
192 bpdu.forward_delay = br_get_ticks(buf+30);
193
194 br_received_config_bpdu(p, &bpdu);
195 }
196
197 else if (buf[0] == BPDU_TYPE_TCN) {
198 br_received_tcn_bpdu(p);
199 }
200 out:
201 spin_unlock_bh(&br->lock);
202 err:
203 kfree_skb(skb);
204 return 0;
205}
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
new file mode 100644
index 000000000000..0da11ff05fa3
--- /dev/null
+++ b/net/bridge/br_stp_if.c
@@ -0,0 +1,225 @@
1/*
2 * Spanning tree protocol; interface code
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_stp_if.c,v 1.4 2001/04/14 21:14:39 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/smp_lock.h>
18
19#include "br_private.h"
20#include "br_private_stp.h"
21
22
23/* Port id is composed of priority and port number.
24 * NB: least significant bits of priority are dropped to
25 * make room for more ports.
26 */
27static inline port_id br_make_port_id(__u8 priority, __u16 port_no)
28{
29 return ((u16)priority << BR_PORT_BITS)
30 | (port_no & ((1<<BR_PORT_BITS)-1));
31}
32
33/* called under bridge lock */
34void br_init_port(struct net_bridge_port *p)
35{
36 p->port_id = br_make_port_id(p->priority, p->port_no);
37 br_become_designated_port(p);
38 p->state = BR_STATE_BLOCKING;
39 p->topology_change_ack = 0;
40 p->config_pending = 0;
41
42 br_stp_port_timer_init(p);
43}
44
45/* called under bridge lock */
46void br_stp_enable_bridge(struct net_bridge *br)
47{
48 struct net_bridge_port *p;
49
50 spin_lock_bh(&br->lock);
51 mod_timer(&br->hello_timer, jiffies + br->hello_time);
52 mod_timer(&br->gc_timer, jiffies + HZ/10);
53
54 br_config_bpdu_generation(br);
55
56 list_for_each_entry(p, &br->port_list, list) {
57 if ((p->dev->flags & IFF_UP) && netif_carrier_ok(p->dev))
58 br_stp_enable_port(p);
59
60 }
61 spin_unlock_bh(&br->lock);
62}
63
64/* NO locks held */
65void br_stp_disable_bridge(struct net_bridge *br)
66{
67 struct net_bridge_port *p;
68
69 spin_lock(&br->lock);
70 list_for_each_entry(p, &br->port_list, list) {
71 if (p->state != BR_STATE_DISABLED)
72 br_stp_disable_port(p);
73
74 }
75
76 br->topology_change = 0;
77 br->topology_change_detected = 0;
78 spin_unlock(&br->lock);
79
80 del_timer_sync(&br->hello_timer);
81 del_timer_sync(&br->topology_change_timer);
82 del_timer_sync(&br->tcn_timer);
83 del_timer_sync(&br->gc_timer);
84}
85
86/* called under bridge lock */
87void br_stp_enable_port(struct net_bridge_port *p)
88{
89 br_init_port(p);
90 br_port_state_selection(p->br);
91}
92
93/* called under bridge lock */
94void br_stp_disable_port(struct net_bridge_port *p)
95{
96 struct net_bridge *br;
97 int wasroot;
98
99 br = p->br;
100 printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
101 br->dev->name, p->port_no, p->dev->name, "disabled");
102
103 wasroot = br_is_root_bridge(br);
104 br_become_designated_port(p);
105 p->state = BR_STATE_DISABLED;
106 p->topology_change_ack = 0;
107 p->config_pending = 0;
108
109 del_timer(&p->message_age_timer);
110 del_timer(&p->forward_delay_timer);
111 del_timer(&p->hold_timer);
112
113 br_configuration_update(br);
114
115 br_port_state_selection(br);
116
117 if (br_is_root_bridge(br) && !wasroot)
118 br_become_root_bridge(br);
119}
120
121/* called under bridge lock */
122static void br_stp_change_bridge_id(struct net_bridge *br,
123 const unsigned char *addr)
124{
125 unsigned char oldaddr[6];
126 struct net_bridge_port *p;
127 int wasroot;
128
129 wasroot = br_is_root_bridge(br);
130
131 memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
132 memcpy(br->bridge_id.addr, addr, ETH_ALEN);
133 memcpy(br->dev->dev_addr, addr, ETH_ALEN);
134
135 list_for_each_entry(p, &br->port_list, list) {
136 if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
137 memcpy(p->designated_bridge.addr, addr, ETH_ALEN);
138
139 if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN))
140 memcpy(p->designated_root.addr, addr, ETH_ALEN);
141
142 }
143
144 br_configuration_update(br);
145 br_port_state_selection(br);
146 if (br_is_root_bridge(br) && !wasroot)
147 br_become_root_bridge(br);
148}
149
150static const unsigned char br_mac_zero[6];
151
152/* called under bridge lock */
153void br_stp_recalculate_bridge_id(struct net_bridge *br)
154{
155 const unsigned char *addr = br_mac_zero;
156 struct net_bridge_port *p;
157
158 list_for_each_entry(p, &br->port_list, list) {
159 if (addr == br_mac_zero ||
160 memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
161 addr = p->dev->dev_addr;
162
163 }
164
165 if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))
166 br_stp_change_bridge_id(br, addr);
167}
168
169/* called under bridge lock */
170void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio)
171{
172 struct net_bridge_port *p;
173 int wasroot;
174
175 wasroot = br_is_root_bridge(br);
176
177 list_for_each_entry(p, &br->port_list, list) {
178 if (p->state != BR_STATE_DISABLED &&
179 br_is_designated_port(p)) {
180 p->designated_bridge.prio[0] = (newprio >> 8) & 0xFF;
181 p->designated_bridge.prio[1] = newprio & 0xFF;
182 }
183
184 }
185
186 br->bridge_id.prio[0] = (newprio >> 8) & 0xFF;
187 br->bridge_id.prio[1] = newprio & 0xFF;
188 br_configuration_update(br);
189 br_port_state_selection(br);
190 if (br_is_root_bridge(br) && !wasroot)
191 br_become_root_bridge(br);
192}
193
194/* called under bridge lock */
195void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio)
196{
197 port_id new_port_id = br_make_port_id(newprio, p->port_no);
198
199 if (br_is_designated_port(p))
200 p->designated_port = new_port_id;
201
202 p->port_id = new_port_id;
203 p->priority = newprio;
204 if (!memcmp(&p->br->bridge_id, &p->designated_bridge, 8) &&
205 p->port_id < p->designated_port) {
206 br_become_designated_port(p);
207 br_port_state_selection(p->br);
208 }
209}
210
211/* called under bridge lock */
212void br_stp_set_path_cost(struct net_bridge_port *p, u32 path_cost)
213{
214 p->path_cost = path_cost;
215 br_configuration_update(p->br);
216 br_port_state_selection(p->br);
217}
218
219ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id)
220{
221 return sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n",
222 id->prio[0], id->prio[1],
223 id->addr[0], id->addr[1], id->addr[2],
224 id->addr[3], id->addr[4], id->addr[5]);
225}
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
new file mode 100644
index 000000000000..9bef55f56425
--- /dev/null
+++ b/net/bridge/br_stp_timer.c
@@ -0,0 +1,188 @@
1/*
2 * Spanning tree protocol; timer-related code
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 *
8 * $Id: br_stp_timer.c,v 1.3 2000/05/05 02:17:17 davem Exp $
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#include <linux/kernel.h>
17#include <linux/times.h>
18#include <linux/smp_lock.h>
19
20#include "br_private.h"
21#include "br_private_stp.h"
22
23/* called under bridge lock */
24static int br_is_designated_for_some_port(const struct net_bridge *br)
25{
26 struct net_bridge_port *p;
27
28 list_for_each_entry(p, &br->port_list, list) {
29 if (p->state != BR_STATE_DISABLED &&
30 !memcmp(&p->designated_bridge, &br->bridge_id, 8))
31 return 1;
32 }
33
34 return 0;
35}
36
37static void br_hello_timer_expired(unsigned long arg)
38{
39 struct net_bridge *br = (struct net_bridge *)arg;
40
41 pr_debug("%s: hello timer expired\n", br->dev->name);
42 spin_lock_bh(&br->lock);
43 if (br->dev->flags & IFF_UP) {
44 br_config_bpdu_generation(br);
45
46 mod_timer(&br->hello_timer, jiffies + br->hello_time);
47 }
48 spin_unlock_bh(&br->lock);
49}
50
51static void br_message_age_timer_expired(unsigned long arg)
52{
53 struct net_bridge_port *p = (struct net_bridge_port *) arg;
54 struct net_bridge *br = p->br;
55 const bridge_id *id = &p->designated_bridge;
56 int was_root;
57
58 if (p->state == BR_STATE_DISABLED)
59 return;
60
61
62 pr_info("%s: neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)\n",
63 br->dev->name,
64 id->prio[0], id->prio[1],
65 id->addr[0], id->addr[1], id->addr[2],
66 id->addr[3], id->addr[4], id->addr[5],
67 p->port_no, p->dev->name);
68
69 /*
70 * According to the spec, the message age timer cannot be
71 * running when we are the root bridge. So.. this was_root
72 * check is redundant. I'm leaving it in for now, though.
73 */
74 spin_lock_bh(&br->lock);
75 if (p->state == BR_STATE_DISABLED)
76 goto unlock;
77 was_root = br_is_root_bridge(br);
78
79 br_become_designated_port(p);
80 br_configuration_update(br);
81 br_port_state_selection(br);
82 if (br_is_root_bridge(br) && !was_root)
83 br_become_root_bridge(br);
84 unlock:
85 spin_unlock_bh(&br->lock);
86}
87
88static void br_forward_delay_timer_expired(unsigned long arg)
89{
90 struct net_bridge_port *p = (struct net_bridge_port *) arg;
91 struct net_bridge *br = p->br;
92
93 pr_debug("%s: %d(%s) forward delay timer\n",
94 br->dev->name, p->port_no, p->dev->name);
95 spin_lock_bh(&br->lock);
96 if (p->state == BR_STATE_LISTENING) {
97 p->state = BR_STATE_LEARNING;
98 mod_timer(&p->forward_delay_timer,
99 jiffies + br->forward_delay);
100 } else if (p->state == BR_STATE_LEARNING) {
101 p->state = BR_STATE_FORWARDING;
102 if (br_is_designated_for_some_port(br))
103 br_topology_change_detection(br);
104 }
105 br_log_state(p);
106 spin_unlock_bh(&br->lock);
107}
108
109static void br_tcn_timer_expired(unsigned long arg)
110{
111 struct net_bridge *br = (struct net_bridge *) arg;
112
113 pr_debug("%s: tcn timer expired\n", br->dev->name);
114 spin_lock_bh(&br->lock);
115 if (br->dev->flags & IFF_UP) {
116 br_transmit_tcn(br);
117
118 mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time);
119 }
120 spin_unlock_bh(&br->lock);
121}
122
123static void br_topology_change_timer_expired(unsigned long arg)
124{
125 struct net_bridge *br = (struct net_bridge *) arg;
126
127 pr_debug("%s: topo change timer expired\n", br->dev->name);
128 spin_lock_bh(&br->lock);
129 br->topology_change_detected = 0;
130 br->topology_change = 0;
131 spin_unlock_bh(&br->lock);
132}
133
134static void br_hold_timer_expired(unsigned long arg)
135{
136 struct net_bridge_port *p = (struct net_bridge_port *) arg;
137
138 pr_debug("%s: %d(%s) hold timer expired\n",
139 p->br->dev->name, p->port_no, p->dev->name);
140
141 spin_lock_bh(&p->br->lock);
142 if (p->config_pending)
143 br_transmit_config(p);
144 spin_unlock_bh(&p->br->lock);
145}
146
147static inline void br_timer_init(struct timer_list *timer,
148 void (*_function)(unsigned long),
149 unsigned long _data)
150{
151 init_timer(timer);
152 timer->function = _function;
153 timer->data = _data;
154}
155
156void br_stp_timer_init(struct net_bridge *br)
157{
158 br_timer_init(&br->hello_timer, br_hello_timer_expired,
159 (unsigned long) br);
160
161 br_timer_init(&br->tcn_timer, br_tcn_timer_expired,
162 (unsigned long) br);
163
164 br_timer_init(&br->topology_change_timer,
165 br_topology_change_timer_expired,
166 (unsigned long) br);
167
168 br_timer_init(&br->gc_timer, br_fdb_cleanup, (unsigned long) br);
169}
170
171void br_stp_port_timer_init(struct net_bridge_port *p)
172{
173 br_timer_init(&p->message_age_timer, br_message_age_timer_expired,
174 (unsigned long) p);
175
176 br_timer_init(&p->forward_delay_timer, br_forward_delay_timer_expired,
177 (unsigned long) p);
178
179 br_timer_init(&p->hold_timer, br_hold_timer_expired,
180 (unsigned long) p);
181}
182
183/* Report ticks left (in USER_HZ) used for API */
184unsigned long br_timer_value(const struct timer_list *timer)
185{
186 return timer_pending(timer)
187 ? jiffies_to_clock_t(timer->expires - jiffies) : 0;
188}
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
new file mode 100644
index 000000000000..98cf53c81fad
--- /dev/null
+++ b/net/bridge/br_sysfs_br.c
@@ -0,0 +1,364 @@
1/*
2 * Sysfs attributes of bridge ports
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Stephen Hemminger <shemminger@osdl.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/netdevice.h>
16#include <linux/if_bridge.h>
17#include <linux/rtnetlink.h>
18#include <linux/spinlock.h>
19#include <linux/times.h>
20
21#include "br_private.h"
22
23#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
24#define to_net_dev(class) container_of(class, struct net_device, class_dev)
25#define to_bridge(cd) ((struct net_bridge *)(to_net_dev(cd)->priv))
26
27/*
28 * Common code for storing bridge parameters.
29 */
30static ssize_t store_bridge_parm(struct class_device *cd,
31 const char *buf, size_t len,
32 void (*set)(struct net_bridge *, unsigned long))
33{
34 struct net_bridge *br = to_bridge(cd);
35 char *endp;
36 unsigned long val;
37
38 if (!capable(CAP_NET_ADMIN))
39 return -EPERM;
40
41 val = simple_strtoul(buf, &endp, 0);
42 if (endp == buf)
43 return -EINVAL;
44
45 spin_lock_bh(&br->lock);
46 (*set)(br, val);
47 spin_unlock_bh(&br->lock);
48 return len;
49}
50
51
52static ssize_t show_forward_delay(struct class_device *cd, char *buf)
53{
54 struct net_bridge *br = to_bridge(cd);
55 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
56}
57
58static void set_forward_delay(struct net_bridge *br, unsigned long val)
59{
60 unsigned long delay = clock_t_to_jiffies(val);
61 br->forward_delay = delay;
62 if (br_is_root_bridge(br))
63 br->bridge_forward_delay = delay;
64}
65
66static ssize_t store_forward_delay(struct class_device *cd, const char *buf,
67 size_t len)
68{
69 return store_bridge_parm(cd, buf, len, set_forward_delay);
70}
71static CLASS_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
72 show_forward_delay, store_forward_delay);
73
74static ssize_t show_hello_time(struct class_device *cd, char *buf)
75{
76 return sprintf(buf, "%lu\n",
77 jiffies_to_clock_t(to_bridge(cd)->hello_time));
78}
79
80static void set_hello_time(struct net_bridge *br, unsigned long val)
81{
82 unsigned long t = clock_t_to_jiffies(val);
83 br->hello_time = t;
84 if (br_is_root_bridge(br))
85 br->bridge_hello_time = t;
86}
87
88static ssize_t store_hello_time(struct class_device *cd, const char *buf,
89 size_t len)
90{
91 return store_bridge_parm(cd, buf, len, set_hello_time);
92}
93
94static CLASS_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
95 store_hello_time);
96
97static ssize_t show_max_age(struct class_device *cd, char *buf)
98{
99 return sprintf(buf, "%lu\n",
100 jiffies_to_clock_t(to_bridge(cd)->max_age));
101}
102
103static void set_max_age(struct net_bridge *br, unsigned long val)
104{
105 unsigned long t = clock_t_to_jiffies(val);
106 br->max_age = t;
107 if (br_is_root_bridge(br))
108 br->bridge_max_age = t;
109}
110
111static ssize_t store_max_age(struct class_device *cd, const char *buf,
112 size_t len)
113{
114 return store_bridge_parm(cd, buf, len, set_max_age);
115}
116
117static CLASS_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age,
118 store_max_age);
119
120static ssize_t show_ageing_time(struct class_device *cd, char *buf)
121{
122 struct net_bridge *br = to_bridge(cd);
123 return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
124}
125
126static void set_ageing_time(struct net_bridge *br, unsigned long val)
127{
128 br->ageing_time = clock_t_to_jiffies(val);
129}
130
131static ssize_t store_ageing_time(struct class_device *cd, const char *buf,
132 size_t len)
133{
134 return store_bridge_parm(cd, buf, len, set_ageing_time);
135}
136
137static CLASS_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
138 store_ageing_time);
139static ssize_t show_stp_state(struct class_device *cd, char *buf)
140{
141 struct net_bridge *br = to_bridge(cd);
142 return sprintf(buf, "%d\n", br->stp_enabled);
143}
144
145static void set_stp_state(struct net_bridge *br, unsigned long val)
146{
147 br->stp_enabled = val;
148}
149
150static ssize_t store_stp_state(struct class_device *cd,
151 const char *buf, size_t len)
152{
153 return store_bridge_parm(cd, buf, len, set_stp_state);
154}
155
156static CLASS_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
157 store_stp_state);
158
159static ssize_t show_priority(struct class_device *cd, char *buf)
160{
161 struct net_bridge *br = to_bridge(cd);
162 return sprintf(buf, "%d\n",
163 (br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
164}
165
166static void set_priority(struct net_bridge *br, unsigned long val)
167{
168 br_stp_set_bridge_priority(br, (u16) val);
169}
170
171static ssize_t store_priority(struct class_device *cd,
172 const char *buf, size_t len)
173{
174 return store_bridge_parm(cd, buf, len, set_priority);
175}
176static CLASS_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority,
177 store_priority);
178
179static ssize_t show_root_id(struct class_device *cd, char *buf)
180{
181 return br_show_bridge_id(buf, &to_bridge(cd)->designated_root);
182}
183static CLASS_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
184
185static ssize_t show_bridge_id(struct class_device *cd, char *buf)
186{
187 return br_show_bridge_id(buf, &to_bridge(cd)->bridge_id);
188}
189static CLASS_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
190
191static ssize_t show_root_port(struct class_device *cd, char *buf)
192{
193 return sprintf(buf, "%d\n", to_bridge(cd)->root_port);
194}
195static CLASS_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
196
197static ssize_t show_root_path_cost(struct class_device *cd, char *buf)
198{
199 return sprintf(buf, "%d\n", to_bridge(cd)->root_path_cost);
200}
201static CLASS_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
202
203static ssize_t show_topology_change(struct class_device *cd, char *buf)
204{
205 return sprintf(buf, "%d\n", to_bridge(cd)->topology_change);
206}
207static CLASS_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
208
209static ssize_t show_topology_change_detected(struct class_device *cd, char *buf)
210{
211 struct net_bridge *br = to_bridge(cd);
212 return sprintf(buf, "%d\n", br->topology_change_detected);
213}
214static CLASS_DEVICE_ATTR(topology_change_detected, S_IRUGO, show_topology_change_detected, NULL);
215
216static ssize_t show_hello_timer(struct class_device *cd, char *buf)
217{
218 struct net_bridge *br = to_bridge(cd);
219 return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
220}
221static CLASS_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
222
223static ssize_t show_tcn_timer(struct class_device *cd, char *buf)
224{
225 struct net_bridge *br = to_bridge(cd);
226 return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
227}
228static CLASS_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
229
230static ssize_t show_topology_change_timer(struct class_device *cd, char *buf)
231{
232 struct net_bridge *br = to_bridge(cd);
233 return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
234}
235static CLASS_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer, NULL);
236
237static ssize_t show_gc_timer(struct class_device *cd, char *buf)
238{
239 struct net_bridge *br = to_bridge(cd);
240 return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
241}
242static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
243
244static struct attribute *bridge_attrs[] = {
245 &class_device_attr_forward_delay.attr,
246 &class_device_attr_hello_time.attr,
247 &class_device_attr_max_age.attr,
248 &class_device_attr_ageing_time.attr,
249 &class_device_attr_stp_state.attr,
250 &class_device_attr_priority.attr,
251 &class_device_attr_bridge_id.attr,
252 &class_device_attr_root_id.attr,
253 &class_device_attr_root_path_cost.attr,
254 &class_device_attr_root_port.attr,
255 &class_device_attr_topology_change.attr,
256 &class_device_attr_topology_change_detected.attr,
257 &class_device_attr_hello_timer.attr,
258 &class_device_attr_tcn_timer.attr,
259 &class_device_attr_topology_change_timer.attr,
260 &class_device_attr_gc_timer.attr,
261 NULL
262};
263
264static struct attribute_group bridge_group = {
265 .name = SYSFS_BRIDGE_ATTR,
266 .attrs = bridge_attrs,
267};
268
269/*
270 * Export the forwarding information table as a binary file
271 * The records are struct __fdb_entry.
272 *
273 * Returns the number of bytes read.
274 */
275static ssize_t brforward_read(struct kobject *kobj, char *buf,
276 loff_t off, size_t count)
277{
278 struct class_device *cdev = to_class_dev(kobj);
279 struct net_bridge *br = to_bridge(cdev);
280 int n;
281
282 /* must read whole records */
283 if (off % sizeof(struct __fdb_entry) != 0)
284 return -EINVAL;
285
286 n = br_fdb_fillbuf(br, buf,
287 count / sizeof(struct __fdb_entry),
288 off / sizeof(struct __fdb_entry));
289
290 if (n > 0)
291 n *= sizeof(struct __fdb_entry);
292
293 return n;
294}
295
296static struct bin_attribute bridge_forward = {
297 .attr = { .name = SYSFS_BRIDGE_FDB,
298 .mode = S_IRUGO,
299 .owner = THIS_MODULE, },
300 .read = brforward_read,
301};
302
303/*
304 * Add entries in sysfs onto the existing network class device
305 * for the bridge.
306 * Adds a attribute group "bridge" containing tuning parameters.
307 * Binary attribute containing the forward table
308 * Sub directory to hold links to interfaces.
309 *
310 * Note: the ifobj exists only to be a subdirectory
311 * to hold links. The ifobj exists in same data structure
312 * as it's parent the bridge so reference counting works.
313 */
314int br_sysfs_addbr(struct net_device *dev)
315{
316 struct kobject *brobj = &dev->class_dev.kobj;
317 struct net_bridge *br = netdev_priv(dev);
318 int err;
319
320 err = sysfs_create_group(brobj, &bridge_group);
321 if (err) {
322 pr_info("%s: can't create group %s/%s\n",
323 __FUNCTION__, dev->name, bridge_group.name);
324 goto out1;
325 }
326
327 err = sysfs_create_bin_file(brobj, &bridge_forward);
328 if (err) {
329 pr_info("%s: can't create attribue file %s/%s\n",
330 __FUNCTION__, dev->name, bridge_forward.attr.name);
331 goto out2;
332 }
333
334
335 kobject_set_name(&br->ifobj, SYSFS_BRIDGE_PORT_SUBDIR);
336 br->ifobj.ktype = NULL;
337 br->ifobj.kset = NULL;
338 br->ifobj.parent = brobj;
339
340 err = kobject_register(&br->ifobj);
341 if (err) {
342 pr_info("%s: can't add kobject (directory) %s/%s\n",
343 __FUNCTION__, dev->name, br->ifobj.name);
344 goto out3;
345 }
346 return 0;
347 out3:
348 sysfs_remove_bin_file(&dev->class_dev.kobj, &bridge_forward);
349 out2:
350 sysfs_remove_group(&dev->class_dev.kobj, &bridge_group);
351 out1:
352 return err;
353
354}
355
356void br_sysfs_delbr(struct net_device *dev)
357{
358 struct kobject *kobj = &dev->class_dev.kobj;
359 struct net_bridge *br = netdev_priv(dev);
360
361 kobject_unregister(&br->ifobj);
362 sysfs_remove_bin_file(kobj, &bridge_forward);
363 sysfs_remove_group(kobj, &bridge_group);
364}
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
new file mode 100644
index 000000000000..567249bf9331
--- /dev/null
+++ b/net/bridge/br_sysfs_if.c
@@ -0,0 +1,269 @@
1/*
2 * Sysfs attributes of bridge ports
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Stephen Hemminger <shemminger@osdl.org>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/netdevice.h>
16#include <linux/if_bridge.h>
17#include <linux/rtnetlink.h>
18#include <linux/spinlock.h>
19
20#include "br_private.h"
21
22struct brport_attribute {
23 struct attribute attr;
24 ssize_t (*show)(struct net_bridge_port *, char *);
25 ssize_t (*store)(struct net_bridge_port *, unsigned long);
26};
27
28#define BRPORT_ATTR(_name,_mode,_show,_store) \
29struct brport_attribute brport_attr_##_name = { \
30 .attr = {.name = __stringify(_name), \
31 .mode = _mode, \
32 .owner = THIS_MODULE, }, \
33 .show = _show, \
34 .store = _store, \
35};
36
37static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
38{
39 return sprintf(buf, "%d\n", p->path_cost);
40}
41static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v)
42{
43 br_stp_set_path_cost(p, v);
44 return 0;
45}
46static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
47 show_path_cost, store_path_cost);
48
49static ssize_t show_priority(struct net_bridge_port *p, char *buf)
50{
51 return sprintf(buf, "%d\n", p->priority);
52}
53static ssize_t store_priority(struct net_bridge_port *p, unsigned long v)
54{
55 if (v >= (1<<(16-BR_PORT_BITS)))
56 return -ERANGE;
57 br_stp_set_port_priority(p, v);
58 return 0;
59}
60static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
61 show_priority, store_priority);
62
63static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
64{
65 return br_show_bridge_id(buf, &p->designated_root);
66}
67static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
68
69static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf)
70{
71 return br_show_bridge_id(buf, &p->designated_bridge);
72}
73static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
74
75static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
76{
77 return sprintf(buf, "%d\n", p->designated_port);
78}
79static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
80
81static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
82{
83 return sprintf(buf, "%d\n", p->designated_cost);
84}
85static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
86
87static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
88{
89 return sprintf(buf, "0x%x\n", p->port_id);
90}
91static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
92
93static ssize_t show_port_no(struct net_bridge_port *p, char *buf)
94{
95 return sprintf(buf, "0x%x\n", p->port_no);
96}
97
98static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
99
100static ssize_t show_change_ack(struct net_bridge_port *p, char *buf)
101{
102 return sprintf(buf, "%d\n", p->topology_change_ack);
103}
104static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
105
106static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
107{
108 return sprintf(buf, "%d\n", p->config_pending);
109}
110static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
111
112static ssize_t show_port_state(struct net_bridge_port *p, char *buf)
113{
114 return sprintf(buf, "%d\n", p->state);
115}
116static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
117
118static ssize_t show_message_age_timer(struct net_bridge_port *p,
119 char *buf)
120{
121 return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer));
122}
123static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
124
125static ssize_t show_forward_delay_timer(struct net_bridge_port *p,
126 char *buf)
127{
128 return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer));
129}
130static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
131
132static ssize_t show_hold_timer(struct net_bridge_port *p,
133 char *buf)
134{
135 return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer));
136}
137static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
138
139static struct brport_attribute *brport_attrs[] = {
140 &brport_attr_path_cost,
141 &brport_attr_priority,
142 &brport_attr_port_id,
143 &brport_attr_port_no,
144 &brport_attr_designated_root,
145 &brport_attr_designated_bridge,
146 &brport_attr_designated_port,
147 &brport_attr_designated_cost,
148 &brport_attr_state,
149 &brport_attr_change_ack,
150 &brport_attr_config_pending,
151 &brport_attr_message_age_timer,
152 &brport_attr_forward_delay_timer,
153 &brport_attr_hold_timer,
154 NULL
155};
156
157#define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)
158#define to_brport(obj) container_of(obj, struct net_bridge_port, kobj)
159
160static ssize_t brport_show(struct kobject * kobj,
161 struct attribute * attr, char * buf)
162{
163 struct brport_attribute * brport_attr = to_brport_attr(attr);
164 struct net_bridge_port * p = to_brport(kobj);
165
166 return brport_attr->show(p, buf);
167}
168
169static ssize_t brport_store(struct kobject * kobj,
170 struct attribute * attr,
171 const char * buf, size_t count)
172{
173 struct brport_attribute * brport_attr = to_brport_attr(attr);
174 struct net_bridge_port * p = to_brport(kobj);
175 ssize_t ret = -EINVAL;
176 char *endp;
177 unsigned long val;
178
179 if (!capable(CAP_NET_ADMIN))
180 return -EPERM;
181
182 val = simple_strtoul(buf, &endp, 0);
183 if (endp != buf) {
184 rtnl_lock();
185 if (p->dev && p->br && brport_attr->store) {
186 spin_lock_bh(&p->br->lock);
187 ret = brport_attr->store(p, val);
188 spin_unlock_bh(&p->br->lock);
189 if (ret == 0)
190 ret = count;
191 }
192 rtnl_unlock();
193 }
194 return ret;
195}
196
197/* called from kobject_put when port ref count goes to zero. */
198static void brport_release(struct kobject *kobj)
199{
200 kfree(container_of(kobj, struct net_bridge_port, kobj));
201}
202
203static struct sysfs_ops brport_sysfs_ops = {
204 .show = brport_show,
205 .store = brport_store,
206};
207
208static struct kobj_type brport_ktype = {
209 .sysfs_ops = &brport_sysfs_ops,
210 .release = brport_release,
211};
212
213
214/*
215 * Add sysfs entries to ethernet device added to a bridge.
216 * Creates a brport subdirectory with bridge attributes.
217 * Puts symlink in bridge's brport subdirectory
218 */
219int br_sysfs_addif(struct net_bridge_port *p)
220{
221 struct net_bridge *br = p->br;
222 struct brport_attribute **a;
223 int err;
224
225 ASSERT_RTNL();
226
227 kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
228 p->kobj.ktype = &brport_ktype;
229 p->kobj.parent = &(p->dev->class_dev.kobj);
230 p->kobj.kset = NULL;
231
232 err = kobject_add(&p->kobj);
233 if(err)
234 goto out1;
235
236 err = sysfs_create_link(&p->kobj, &br->dev->class_dev.kobj,
237 SYSFS_BRIDGE_PORT_LINK);
238 if (err)
239 goto out2;
240
241 for (a = brport_attrs; *a; ++a) {
242 err = sysfs_create_file(&p->kobj, &((*a)->attr));
243 if (err)
244 goto out2;
245 }
246
247 err = sysfs_create_link(&br->ifobj, &p->kobj, p->dev->name);
248 if (err)
249 goto out2;
250
251 return 0;
252 out2:
253 kobject_del(&p->kobj);
254 out1:
255 return err;
256}
257
258void br_sysfs_removeif(struct net_bridge_port *p)
259{
260 pr_debug("br_sysfs_removeif\n");
261 sysfs_remove_link(&p->br->ifobj, p->dev->name);
262 kobject_del(&p->kobj);
263}
264
265void br_sysfs_freeif(struct net_bridge_port *p)
266{
267 pr_debug("br_sysfs_freeif\n");
268 kobject_put(&p->kobj);
269}
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
new file mode 100644
index 000000000000..68ccef507b49
--- /dev/null
+++ b/net/bridge/netfilter/Kconfig
@@ -0,0 +1,211 @@
1#
2# Bridge netfilter configuration
3#
4
5menu "Bridge: Netfilter Configuration"
6 depends on BRIDGE && NETFILTER
7
8config BRIDGE_NF_EBTABLES
9 tristate "Ethernet Bridge tables (ebtables) support"
10 help
11 ebtables is a general, extensible frame/packet identification
12 framework. Say 'Y' or 'M' here if you want to do Ethernet
13 filtering/NAT/brouting on the Ethernet bridge.
14#
15# tables
16#
17config BRIDGE_EBT_BROUTE
18 tristate "ebt: broute table support"
19 depends on BRIDGE_NF_EBTABLES
20 help
21 The ebtables broute table is used to define rules that decide between
22 bridging and routing frames, giving Linux the functionality of a
23 brouter. See the man page for ebtables(8) and examples on the ebtables
24 website.
25
26 To compile it as a module, choose M here. If unsure, say N.
27
28config BRIDGE_EBT_T_FILTER
29 tristate "ebt: filter table support"
30 depends on BRIDGE_NF_EBTABLES
31 help
32 The ebtables filter table is used to define frame filtering rules at
33 local input, forwarding and local output. See the man page for
34 ebtables(8).
35
36 To compile it as a module, choose M here. If unsure, say N.
37
38config BRIDGE_EBT_T_NAT
39 tristate "ebt: nat table support"
40 depends on BRIDGE_NF_EBTABLES
41 help
42 The ebtables nat table is used to define rules that alter the MAC
43 source address (MAC SNAT) or the MAC destination address (MAC DNAT).
44 See the man page for ebtables(8).
45
46 To compile it as a module, choose M here. If unsure, say N.
47#
48# matches
49#
50config BRIDGE_EBT_802_3
51 tristate "ebt: 802.3 filter support"
52 depends on BRIDGE_NF_EBTABLES
53 help
54 This option adds matching support for 802.3 Ethernet frames.
55
56 To compile it as a module, choose M here. If unsure, say N.
57
58config BRIDGE_EBT_AMONG
59 tristate "ebt: among filter support"
60 depends on BRIDGE_NF_EBTABLES
61 help
62 This option adds the among match, which allows matching the MAC source
63 and/or destination address on a list of addresses. Optionally,
64 MAC/IP address pairs can be matched, f.e. for anti-spoofing rules.
65
66 To compile it as a module, choose M here. If unsure, say N.
67
68config BRIDGE_EBT_ARP
69 tristate "ebt: ARP filter support"
70 depends on BRIDGE_NF_EBTABLES
71 help
72 This option adds the ARP match, which allows ARP and RARP header field
73 filtering.
74
75 To compile it as a module, choose M here. If unsure, say N.
76
77config BRIDGE_EBT_IP
78 tristate "ebt: IP filter support"
79 depends on BRIDGE_NF_EBTABLES
80 help
81 This option adds the IP match, which allows basic IP header field
82 filtering.
83
84 To compile it as a module, choose M here. If unsure, say N.
85
86config BRIDGE_EBT_LIMIT
87 tristate "ebt: limit match support"
88 depends on BRIDGE_NF_EBTABLES
89 help
90 This option adds the limit match, which allows you to control
91 the rate at which a rule can be matched. This match is the
92 equivalent of the iptables limit match.
93
94 If you want to compile it as a module, say M here and read
95 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
96
97config BRIDGE_EBT_MARK
98 tristate "ebt: mark filter support"
99 depends on BRIDGE_NF_EBTABLES
100 help
101 This option adds the mark match, which allows matching frames based on
102 the 'nfmark' value in the frame. This can be set by the mark target.
103 This value is the same as the one used in the iptables mark match and
104 target.
105
106 To compile it as a module, choose M here. If unsure, say N.
107
108config BRIDGE_EBT_PKTTYPE
109 tristate "ebt: packet type filter support"
110 depends on BRIDGE_NF_EBTABLES
111 help
112 This option adds the packet type match, which allows matching on the
113 type of packet based on its Ethernet "class" (as determined by
114 the generic networking code): broadcast, multicast,
115 for this host alone or for another host.
116
117 To compile it as a module, choose M here. If unsure, say N.
118
119config BRIDGE_EBT_STP
120 tristate "ebt: STP filter support"
121 depends on BRIDGE_NF_EBTABLES
122 help
123 This option adds the Spanning Tree Protocol match, which
124 allows STP header field filtering.
125
126 To compile it as a module, choose M here. If unsure, say N.
127
128config BRIDGE_EBT_VLAN
129 tristate "ebt: 802.1Q VLAN filter support"
130 depends on BRIDGE_NF_EBTABLES
131 help
132 This option adds the 802.1Q vlan match, which allows the filtering of
133 802.1Q vlan fields.
134
135 To compile it as a module, choose M here. If unsure, say N.
136#
137# targets
138#
139config BRIDGE_EBT_ARPREPLY
140 tristate "ebt: arp reply target support"
141 depends on BRIDGE_NF_EBTABLES
142 help
143 This option adds the arp reply target, which allows
144 automatically sending arp replies to arp requests.
145
146 To compile it as a module, choose M here. If unsure, say N.
147
148config BRIDGE_EBT_DNAT
149 tristate "ebt: dnat target support"
150 depends on BRIDGE_NF_EBTABLES
151 help
152 This option adds the MAC DNAT target, which allows altering the MAC
153 destination address of frames.
154
155 To compile it as a module, choose M here. If unsure, say N.
156
157config BRIDGE_EBT_MARK_T
158 tristate "ebt: mark target support"
159 depends on BRIDGE_NF_EBTABLES
160 help
161 This option adds the mark target, which allows marking frames by
162 setting the 'nfmark' value in the frame.
163 This value is the same as the one used in the iptables mark match and
164 target.
165
166 To compile it as a module, choose M here. If unsure, say N.
167
168config BRIDGE_EBT_REDIRECT
169 tristate "ebt: redirect target support"
170 depends on BRIDGE_NF_EBTABLES
171 help
172 This option adds the MAC redirect target, which allows altering the MAC
173 destination address of a frame to that of the device it arrived on.
174
175 To compile it as a module, choose M here. If unsure, say N.
176
177config BRIDGE_EBT_SNAT
178 tristate "ebt: snat target support"
179 depends on BRIDGE_NF_EBTABLES
180 help
181 This option adds the MAC SNAT target, which allows altering the MAC
182 source address of frames.
183
184 To compile it as a module, choose M here. If unsure, say N.
185#
186# watchers
187#
188config BRIDGE_EBT_LOG
189 tristate "ebt: log support"
190 depends on BRIDGE_NF_EBTABLES
191 help
192 This option adds the log watcher, that you can use in any rule
193 in any ebtables table. It records info about the frame header
194 to the syslog.
195
196 To compile it as a module, choose M here. If unsure, say N.
197
198config BRIDGE_EBT_ULOG
199 tristate "ebt: ulog support"
200 depends on BRIDGE_NF_EBTABLES
201 help
202 This option adds the ulog watcher, that you can use in any rule
203 in any ebtables table. The packet is passed to a userspace
204 logging daemon using netlink multicast sockets. This differs
205 from the log watcher in the sense that the complete packet is
206 sent to userspace instead of a descriptive text and that
207 netlink multicast sockets are used instead of the syslog.
208
209 To compile it as a module, choose M here. If unsure, say N.
210
211endmenu
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
new file mode 100644
index 000000000000..8bf6d9f6e9d3
--- /dev/null
+++ b/net/bridge/netfilter/Makefile
@@ -0,0 +1,32 @@
1#
2# Makefile for the netfilter modules for Link Layer filtering on a bridge.
3#
4
5obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o
6
7# tables
8obj-$(CONFIG_BRIDGE_EBT_BROUTE) += ebtable_broute.o
9obj-$(CONFIG_BRIDGE_EBT_T_FILTER) += ebtable_filter.o
10obj-$(CONFIG_BRIDGE_EBT_T_NAT) += ebtable_nat.o
11
12#matches
13obj-$(CONFIG_BRIDGE_EBT_802_3) += ebt_802_3.o
14obj-$(CONFIG_BRIDGE_EBT_AMONG) += ebt_among.o
15obj-$(CONFIG_BRIDGE_EBT_ARP) += ebt_arp.o
16obj-$(CONFIG_BRIDGE_EBT_IP) += ebt_ip.o
17obj-$(CONFIG_BRIDGE_EBT_LIMIT) += ebt_limit.o
18obj-$(CONFIG_BRIDGE_EBT_MARK) += ebt_mark_m.o
19obj-$(CONFIG_BRIDGE_EBT_PKTTYPE) += ebt_pkttype.o
20obj-$(CONFIG_BRIDGE_EBT_STP) += ebt_stp.o
21obj-$(CONFIG_BRIDGE_EBT_VLAN) += ebt_vlan.o
22
23# targets
24obj-$(CONFIG_BRIDGE_EBT_ARPREPLY) += ebt_arpreply.o
25obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark.o
26obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o
27obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o
28obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o
29
30# watchers
31obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
32obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_ulog.o
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
new file mode 100644
index 000000000000..468ebdf4bc1c
--- /dev/null
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -0,0 +1,73 @@
1/*
2 * 802_3
3 *
4 * Author:
5 * Chris Vitale csv@bluetail.com
6 *
7 * May 2003
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_802_3.h>
13#include <linux/module.h>
14
15static int ebt_filter_802_3(const struct sk_buff *skb, const struct net_device *in,
16 const struct net_device *out, const void *data, unsigned int datalen)
17{
18 struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
19 struct ebt_802_3_hdr *hdr = ebt_802_3_hdr(skb);
20 uint16_t type = hdr->llc.ui.ctrl & IS_UI ? hdr->llc.ui.type : hdr->llc.ni.type;
21
22 if (info->bitmask & EBT_802_3_SAP) {
23 if (FWINV(info->sap != hdr->llc.ui.ssap, EBT_802_3_SAP))
24 return EBT_NOMATCH;
25 if (FWINV(info->sap != hdr->llc.ui.dsap, EBT_802_3_SAP))
26 return EBT_NOMATCH;
27 }
28
29 if (info->bitmask & EBT_802_3_TYPE) {
30 if (!(hdr->llc.ui.dsap == CHECK_TYPE && hdr->llc.ui.ssap == CHECK_TYPE))
31 return EBT_NOMATCH;
32 if (FWINV(info->type != type, EBT_802_3_TYPE))
33 return EBT_NOMATCH;
34 }
35
36 return EBT_MATCH;
37}
38
39static struct ebt_match filter_802_3;
40static int ebt_802_3_check(const char *tablename, unsigned int hookmask,
41 const struct ebt_entry *e, void *data, unsigned int datalen)
42{
43 struct ebt_802_3_info *info = (struct ebt_802_3_info *)data;
44
45 if (datalen < sizeof(struct ebt_802_3_info))
46 return -EINVAL;
47 if (info->bitmask & ~EBT_802_3_MASK || info->invflags & ~EBT_802_3_MASK)
48 return -EINVAL;
49
50 return 0;
51}
52
53static struct ebt_match filter_802_3 =
54{
55 .name = EBT_802_3_MATCH,
56 .match = ebt_filter_802_3,
57 .check = ebt_802_3_check,
58 .me = THIS_MODULE,
59};
60
61static int __init init(void)
62{
63 return ebt_register_match(&filter_802_3);
64}
65
66static void __exit fini(void)
67{
68 ebt_unregister_match(&filter_802_3);
69}
70
71module_init(init);
72module_exit(fini);
73MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c
new file mode 100644
index 000000000000..5a1f5e3bff15
--- /dev/null
+++ b/net/bridge/netfilter/ebt_among.c
@@ -0,0 +1,228 @@
1/*
2 * ebt_among
3 *
4 * Authors:
5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
6 *
7 * August, 2003
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_among.h>
13#include <linux/ip.h>
14#include <linux/if_arp.h>
15#include <linux/module.h>
16
17static int ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh,
18 const char *mac, uint32_t ip)
19{
20 /* You may be puzzled as to how this code works.
21 * Some tricks were used, refer to
22 * include/linux/netfilter_bridge/ebt_among.h
23 * as there you can find a solution of this mystery.
24 */
25 const struct ebt_mac_wormhash_tuple *p;
26 int start, limit, i;
27 uint32_t cmp[2] = { 0, 0 };
28 int key = (const unsigned char) mac[5];
29
30 memcpy(((char *) cmp) + 2, mac, 6);
31 start = wh->table[key];
32 limit = wh->table[key + 1];
33 if (ip) {
34 for (i = start; i < limit; i++) {
35 p = &wh->pool[i];
36 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
37 if (p->ip == 0 || p->ip == ip) {
38 return 1;
39 }
40 }
41 }
42 } else {
43 for (i = start; i < limit; i++) {
44 p = &wh->pool[i];
45 if (cmp[1] == p->cmp[1] && cmp[0] == p->cmp[0]) {
46 if (p->ip == 0) {
47 return 1;
48 }
49 }
50 }
51 }
52 return 0;
53}
54
55static int ebt_mac_wormhash_check_integrity(const struct ebt_mac_wormhash
56 *wh)
57{
58 int i;
59
60 for (i = 0; i < 256; i++) {
61 if (wh->table[i] > wh->table[i + 1])
62 return -0x100 - i;
63 if (wh->table[i] < 0)
64 return -0x200 - i;
65 if (wh->table[i] > wh->poolsize)
66 return -0x300 - i;
67 }
68 if (wh->table[256] > wh->poolsize)
69 return -0xc00;
70 return 0;
71}
72
73static int get_ip_dst(const struct sk_buff *skb, uint32_t *addr)
74{
75 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
76 struct iphdr _iph, *ih;
77
78 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
79 if (ih == NULL)
80 return -1;
81 *addr = ih->daddr;
82 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
83 struct arphdr _arph, *ah;
84 uint32_t buf, *bp;
85
86 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
87 if (ah == NULL ||
88 ah->ar_pln != sizeof(uint32_t) ||
89 ah->ar_hln != ETH_ALEN)
90 return -1;
91 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
92 2 * ETH_ALEN + sizeof(uint32_t),
93 sizeof(uint32_t), &buf);
94 if (bp == NULL)
95 return -1;
96 *addr = *bp;
97 }
98 return 0;
99}
100
101static int get_ip_src(const struct sk_buff *skb, uint32_t *addr)
102{
103 if (eth_hdr(skb)->h_proto == htons(ETH_P_IP)) {
104 struct iphdr _iph, *ih;
105
106 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
107 if (ih == NULL)
108 return -1;
109 *addr = ih->saddr;
110 } else if (eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) {
111 struct arphdr _arph, *ah;
112 uint32_t buf, *bp;
113
114 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
115 if (ah == NULL ||
116 ah->ar_pln != sizeof(uint32_t) ||
117 ah->ar_hln != ETH_ALEN)
118 return -1;
119 bp = skb_header_pointer(skb, sizeof(struct arphdr) +
120 ETH_ALEN, sizeof(uint32_t), &buf);
121 if (bp == NULL)
122 return -1;
123 *addr = *bp;
124 }
125 return 0;
126}
127
128static int ebt_filter_among(const struct sk_buff *skb,
129 const struct net_device *in,
130 const struct net_device *out, const void *data,
131 unsigned int datalen)
132{
133 struct ebt_among_info *info = (struct ebt_among_info *) data;
134 const char *dmac, *smac;
135 const struct ebt_mac_wormhash *wh_dst, *wh_src;
136 uint32_t dip = 0, sip = 0;
137
138 wh_dst = ebt_among_wh_dst(info);
139 wh_src = ebt_among_wh_src(info);
140
141 if (wh_src) {
142 smac = eth_hdr(skb)->h_source;
143 if (get_ip_src(skb, &sip))
144 return EBT_NOMATCH;
145 if (!(info->bitmask & EBT_AMONG_SRC_NEG)) {
146 /* we match only if it contains */
147 if (!ebt_mac_wormhash_contains(wh_src, smac, sip))
148 return EBT_NOMATCH;
149 } else {
150 /* we match only if it DOES NOT contain */
151 if (ebt_mac_wormhash_contains(wh_src, smac, sip))
152 return EBT_NOMATCH;
153 }
154 }
155
156 if (wh_dst) {
157 dmac = eth_hdr(skb)->h_dest;
158 if (get_ip_dst(skb, &dip))
159 return EBT_NOMATCH;
160 if (!(info->bitmask & EBT_AMONG_DST_NEG)) {
161 /* we match only if it contains */
162 if (!ebt_mac_wormhash_contains(wh_dst, dmac, dip))
163 return EBT_NOMATCH;
164 } else {
165 /* we match only if it DOES NOT contain */
166 if (ebt_mac_wormhash_contains(wh_dst, dmac, dip))
167 return EBT_NOMATCH;
168 }
169 }
170
171 return EBT_MATCH;
172}
173
174static int ebt_among_check(const char *tablename, unsigned int hookmask,
175 const struct ebt_entry *e, void *data,
176 unsigned int datalen)
177{
178 struct ebt_among_info *info = (struct ebt_among_info *) data;
179 int expected_length = sizeof(struct ebt_among_info);
180 const struct ebt_mac_wormhash *wh_dst, *wh_src;
181 int err;
182
183 wh_dst = ebt_among_wh_dst(info);
184 wh_src = ebt_among_wh_src(info);
185 expected_length += ebt_mac_wormhash_size(wh_dst);
186 expected_length += ebt_mac_wormhash_size(wh_src);
187
188 if (datalen != EBT_ALIGN(expected_length)) {
189 printk(KERN_WARNING
190 "ebtables: among: wrong size: %d"
191 "against expected %d, rounded to %Zd\n",
192 datalen, expected_length,
193 EBT_ALIGN(expected_length));
194 return -EINVAL;
195 }
196 if (wh_dst && (err = ebt_mac_wormhash_check_integrity(wh_dst))) {
197 printk(KERN_WARNING
198 "ebtables: among: dst integrity fail: %x\n", -err);
199 return -EINVAL;
200 }
201 if (wh_src && (err = ebt_mac_wormhash_check_integrity(wh_src))) {
202 printk(KERN_WARNING
203 "ebtables: among: src integrity fail: %x\n", -err);
204 return -EINVAL;
205 }
206 return 0;
207}
208
209static struct ebt_match filter_among = {
210 .name = EBT_AMONG_MATCH,
211 .match = ebt_filter_among,
212 .check = ebt_among_check,
213 .me = THIS_MODULE,
214};
215
216static int __init init(void)
217{
218 return ebt_register_match(&filter_among);
219}
220
221static void __exit fini(void)
222{
223 ebt_unregister_match(&filter_among);
224}
225
226module_init(init);
227module_exit(fini);
228MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
new file mode 100644
index 000000000000..b94c48cb6e4b
--- /dev/null
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -0,0 +1,140 @@
1/*
2 * ebt_arp
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Tim Gardner <timg@tpi.com>
7 *
8 * April, 2002
9 *
10 */
11
12#include <linux/netfilter_bridge/ebtables.h>
13#include <linux/netfilter_bridge/ebt_arp.h>
14#include <linux/if_arp.h>
15#include <linux/if_ether.h>
16#include <linux/module.h>
17
18static int ebt_filter_arp(const struct sk_buff *skb, const struct net_device *in,
19 const struct net_device *out, const void *data, unsigned int datalen)
20{
21 struct ebt_arp_info *info = (struct ebt_arp_info *)data;
22 struct arphdr _arph, *ah;
23
24 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
25 if (ah == NULL)
26 return EBT_NOMATCH;
27 if (info->bitmask & EBT_ARP_OPCODE && FWINV(info->opcode !=
28 ah->ar_op, EBT_ARP_OPCODE))
29 return EBT_NOMATCH;
30 if (info->bitmask & EBT_ARP_HTYPE && FWINV(info->htype !=
31 ah->ar_hrd, EBT_ARP_HTYPE))
32 return EBT_NOMATCH;
33 if (info->bitmask & EBT_ARP_PTYPE && FWINV(info->ptype !=
34 ah->ar_pro, EBT_ARP_PTYPE))
35 return EBT_NOMATCH;
36
37 if (info->bitmask & (EBT_ARP_SRC_IP | EBT_ARP_DST_IP)) {
38 uint32_t _addr, *ap;
39
40 /* IPv4 addresses are always 4 bytes */
41 if (ah->ar_pln != sizeof(uint32_t))
42 return EBT_NOMATCH;
43 if (info->bitmask & EBT_ARP_SRC_IP) {
44 ap = skb_header_pointer(skb, sizeof(struct arphdr) +
45 ah->ar_hln, sizeof(_addr),
46 &_addr);
47 if (ap == NULL)
48 return EBT_NOMATCH;
49 if (FWINV(info->saddr != (*ap & info->smsk),
50 EBT_ARP_SRC_IP))
51 return EBT_NOMATCH;
52 }
53
54 if (info->bitmask & EBT_ARP_DST_IP) {
55 ap = skb_header_pointer(skb, sizeof(struct arphdr) +
56 2*ah->ar_hln+sizeof(uint32_t),
57 sizeof(_addr), &_addr);
58 if (ap == NULL)
59 return EBT_NOMATCH;
60 if (FWINV(info->daddr != (*ap & info->dmsk),
61 EBT_ARP_DST_IP))
62 return EBT_NOMATCH;
63 }
64 }
65
66 if (info->bitmask & (EBT_ARP_SRC_MAC | EBT_ARP_DST_MAC)) {
67 unsigned char _mac[ETH_ALEN], *mp;
68 uint8_t verdict, i;
69
70 /* MAC addresses are 6 bytes */
71 if (ah->ar_hln != ETH_ALEN)
72 return EBT_NOMATCH;
73 if (info->bitmask & EBT_ARP_SRC_MAC) {
74 mp = skb_header_pointer(skb, sizeof(struct arphdr),
75 sizeof(_mac), &_mac);
76 if (mp == NULL)
77 return EBT_NOMATCH;
78 verdict = 0;
79 for (i = 0; i < 6; i++)
80 verdict |= (mp[i] ^ info->smaddr[i]) &
81 info->smmsk[i];
82 if (FWINV(verdict != 0, EBT_ARP_SRC_MAC))
83 return EBT_NOMATCH;
84 }
85
86 if (info->bitmask & EBT_ARP_DST_MAC) {
87 mp = skb_header_pointer(skb, sizeof(struct arphdr) +
88 ah->ar_hln + ah->ar_pln,
89 sizeof(_mac), &_mac);
90 if (mp == NULL)
91 return EBT_NOMATCH;
92 verdict = 0;
93 for (i = 0; i < 6; i++)
94 verdict |= (mp[i] ^ info->dmaddr[i]) &
95 info->dmmsk[i];
96 if (FWINV(verdict != 0, EBT_ARP_DST_MAC))
97 return EBT_NOMATCH;
98 }
99 }
100
101 return EBT_MATCH;
102}
103
104static int ebt_arp_check(const char *tablename, unsigned int hookmask,
105 const struct ebt_entry *e, void *data, unsigned int datalen)
106{
107 struct ebt_arp_info *info = (struct ebt_arp_info *)data;
108
109 if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
110 return -EINVAL;
111 if ((e->ethproto != htons(ETH_P_ARP) &&
112 e->ethproto != htons(ETH_P_RARP)) ||
113 e->invflags & EBT_IPROTO)
114 return -EINVAL;
115 if (info->bitmask & ~EBT_ARP_MASK || info->invflags & ~EBT_ARP_MASK)
116 return -EINVAL;
117 return 0;
118}
119
120static struct ebt_match filter_arp =
121{
122 .name = EBT_ARP_MATCH,
123 .match = ebt_filter_arp,
124 .check = ebt_arp_check,
125 .me = THIS_MODULE,
126};
127
128static int __init init(void)
129{
130 return ebt_register_match(&filter_arp);
131}
132
133static void __exit fini(void)
134{
135 ebt_unregister_match(&filter_arp);
136}
137
138module_init(init);
139module_exit(fini);
140MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
new file mode 100644
index 000000000000..b934de90f7c5
--- /dev/null
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -0,0 +1,97 @@
1/*
2 * ebt_arpreply
3 *
4 * Authors:
5 * Grzegorz Borowiak <grzes@gnu.univ.gda.pl>
6 * Bart De Schuymer <bdschuym@pandora.be>
7 *
8 * August, 2003
9 *
10 */
11
12#include <linux/netfilter_bridge/ebtables.h>
13#include <linux/netfilter_bridge/ebt_arpreply.h>
14#include <linux/if_arp.h>
15#include <net/arp.h>
16#include <linux/module.h>
17
18static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
19 const struct net_device *in, const struct net_device *out,
20 const void *data, unsigned int datalen)
21{
22 struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
23 u32 _sip, *siptr, _dip, *diptr;
24 struct arphdr _ah, *ap;
25 unsigned char _sha[ETH_ALEN], *shp;
26 struct sk_buff *skb = *pskb;
27
28 ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah);
29 if (ap == NULL)
30 return EBT_DROP;
31
32 if (ap->ar_op != htons(ARPOP_REQUEST) ||
33 ap->ar_hln != ETH_ALEN ||
34 ap->ar_pro != htons(ETH_P_IP) ||
35 ap->ar_pln != 4)
36 return EBT_CONTINUE;
37
38 shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha);
39 if (shp == NULL)
40 return EBT_DROP;
41
42 siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN,
43 sizeof(_sip), &_sip);
44 if (siptr == NULL)
45 return EBT_DROP;
46
47 diptr = skb_header_pointer(skb,
48 sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip),
49 sizeof(_dip), &_dip);
50 if (diptr == NULL)
51 return EBT_DROP;
52
53 arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in,
54 *diptr, shp, info->mac, shp);
55
56 return info->target;
57}
58
59static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
60 const struct ebt_entry *e, void *data, unsigned int datalen)
61{
62 struct ebt_arpreply_info *info = (struct ebt_arpreply_info *)data;
63
64 if (datalen != EBT_ALIGN(sizeof(struct ebt_arpreply_info)))
65 return -EINVAL;
66 if (BASE_CHAIN && info->target == EBT_RETURN)
67 return -EINVAL;
68 if (e->ethproto != htons(ETH_P_ARP) ||
69 e->invflags & EBT_IPROTO)
70 return -EINVAL;
71 CLEAR_BASE_CHAIN_BIT;
72 if (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING))
73 return -EINVAL;
74 return 0;
75}
76
77static struct ebt_target reply_target =
78{
79 .name = EBT_ARPREPLY_TARGET,
80 .target = ebt_target_reply,
81 .check = ebt_target_reply_check,
82 .me = THIS_MODULE,
83};
84
85static int __init init(void)
86{
87 return ebt_register_target(&reply_target);
88}
89
90static void __exit fini(void)
91{
92 ebt_unregister_target(&reply_target);
93}
94
95module_init(init);
96module_exit(fini);
97MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
new file mode 100644
index 000000000000..f5463086c7bd
--- /dev/null
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -0,0 +1,76 @@
1/*
2 * ebt_dnat
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * June, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_nat.h>
13#include <linux/module.h>
14#include <net/sock.h>
15
16static int ebt_target_dnat(struct sk_buff **pskb, unsigned int hooknr,
17 const struct net_device *in, const struct net_device *out,
18 const void *data, unsigned int datalen)
19{
20 struct ebt_nat_info *info = (struct ebt_nat_info *)data;
21
22 if (skb_shared(*pskb) || skb_cloned(*pskb)) {
23 struct sk_buff *nskb;
24
25 nskb = skb_copy(*pskb, GFP_ATOMIC);
26 if (!nskb)
27 return NF_DROP;
28 if ((*pskb)->sk)
29 skb_set_owner_w(nskb, (*pskb)->sk);
30 kfree_skb(*pskb);
31 *pskb = nskb;
32 }
33 memcpy(eth_hdr(*pskb)->h_dest, info->mac, ETH_ALEN);
34 return info->target;
35}
36
37static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask,
38 const struct ebt_entry *e, void *data, unsigned int datalen)
39{
40 struct ebt_nat_info *info = (struct ebt_nat_info *)data;
41
42 if (BASE_CHAIN && info->target == EBT_RETURN)
43 return -EINVAL;
44 CLEAR_BASE_CHAIN_BIT;
45 if ( (strcmp(tablename, "nat") ||
46 (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) &&
47 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
48 return -EINVAL;
49 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
50 return -EINVAL;
51 if (INVALID_TARGET)
52 return -EINVAL;
53 return 0;
54}
55
56static struct ebt_target dnat =
57{
58 .name = EBT_DNAT_TARGET,
59 .target = ebt_target_dnat,
60 .check = ebt_target_dnat_check,
61 .me = THIS_MODULE,
62};
63
64static int __init init(void)
65{
66 return ebt_register_target(&dnat);
67}
68
69static void __exit fini(void)
70{
71 ebt_unregister_target(&dnat);
72}
73
74module_init(init);
75module_exit(fini);
76MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
new file mode 100644
index 000000000000..7323805b9726
--- /dev/null
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -0,0 +1,122 @@
1/*
2 * ebt_ip
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 * Changes:
10 * added ip-sport and ip-dport
11 * Innominate Security Technologies AG <mhopf@innominate.com>
12 * September, 2002
13 */
14
15#include <linux/netfilter_bridge/ebtables.h>
16#include <linux/netfilter_bridge/ebt_ip.h>
17#include <linux/ip.h>
18#include <linux/in.h>
19#include <linux/module.h>
20
21struct tcpudphdr {
22 uint16_t src;
23 uint16_t dst;
24};
25
26static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
27 const struct net_device *out, const void *data,
28 unsigned int datalen)
29{
30 struct ebt_ip_info *info = (struct ebt_ip_info *)data;
31 struct iphdr _iph, *ih;
32 struct tcpudphdr _ports, *pptr;
33
34 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
35 if (ih == NULL)
36 return EBT_NOMATCH;
37 if (info->bitmask & EBT_IP_TOS &&
38 FWINV(info->tos != ih->tos, EBT_IP_TOS))
39 return EBT_NOMATCH;
40 if (info->bitmask & EBT_IP_SOURCE &&
41 FWINV((ih->saddr & info->smsk) !=
42 info->saddr, EBT_IP_SOURCE))
43 return EBT_NOMATCH;
44 if ((info->bitmask & EBT_IP_DEST) &&
45 FWINV((ih->daddr & info->dmsk) !=
46 info->daddr, EBT_IP_DEST))
47 return EBT_NOMATCH;
48 if (info->bitmask & EBT_IP_PROTO) {
49 if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO))
50 return EBT_NOMATCH;
51 if (!(info->bitmask & EBT_IP_DPORT) &&
52 !(info->bitmask & EBT_IP_SPORT))
53 return EBT_MATCH;
54 pptr = skb_header_pointer(skb, ih->ihl*4,
55 sizeof(_ports), &_ports);
56 if (pptr == NULL)
57 return EBT_NOMATCH;
58 if (info->bitmask & EBT_IP_DPORT) {
59 u32 dst = ntohs(pptr->dst);
60 if (FWINV(dst < info->dport[0] ||
61 dst > info->dport[1],
62 EBT_IP_DPORT))
63 return EBT_NOMATCH;
64 }
65 if (info->bitmask & EBT_IP_SPORT) {
66 u32 src = ntohs(pptr->src);
67 if (FWINV(src < info->sport[0] ||
68 src > info->sport[1],
69 EBT_IP_SPORT))
70 return EBT_NOMATCH;
71 }
72 }
73 return EBT_MATCH;
74}
75
76static int ebt_ip_check(const char *tablename, unsigned int hookmask,
77 const struct ebt_entry *e, void *data, unsigned int datalen)
78{
79 struct ebt_ip_info *info = (struct ebt_ip_info *)data;
80
81 if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
82 return -EINVAL;
83 if (e->ethproto != htons(ETH_P_IP) ||
84 e->invflags & EBT_IPROTO)
85 return -EINVAL;
86 if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK)
87 return -EINVAL;
88 if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) {
89 if (info->invflags & EBT_IP_PROTO)
90 return -EINVAL;
91 if (info->protocol != IPPROTO_TCP &&
92 info->protocol != IPPROTO_UDP)
93 return -EINVAL;
94 }
95 if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1])
96 return -EINVAL;
97 if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1])
98 return -EINVAL;
99 return 0;
100}
101
102static struct ebt_match filter_ip =
103{
104 .name = EBT_IP_MATCH,
105 .match = ebt_filter_ip,
106 .check = ebt_ip_check,
107 .me = THIS_MODULE,
108};
109
110static int __init init(void)
111{
112 return ebt_register_match(&filter_ip);
113}
114
115static void __exit fini(void)
116{
117 ebt_unregister_match(&filter_ip);
118}
119
120module_init(init);
121module_exit(fini);
122MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
new file mode 100644
index 000000000000..637c8844cd5f
--- /dev/null
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -0,0 +1,113 @@
1/*
2 * ebt_limit
3 *
4 * Authors:
5 * Tom Marshall <tommy@home.tig-grr.com>
6 *
7 * Mostly copied from netfilter's ipt_limit.c, see that file for
8 * more explanation
9 *
10 * September, 2003
11 *
12 */
13
14#include <linux/netfilter_bridge/ebtables.h>
15#include <linux/netfilter_bridge/ebt_limit.h>
16#include <linux/module.h>
17
18#include <linux/netdevice.h>
19#include <linux/spinlock.h>
20
21static DEFINE_SPINLOCK(limit_lock);
22
23#define MAX_CPJ (0xFFFFFFFF / (HZ*60*60*24))
24
25#define _POW2_BELOW2(x) ((x)|((x)>>1))
26#define _POW2_BELOW4(x) (_POW2_BELOW2(x)|_POW2_BELOW2((x)>>2))
27#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
28#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
29#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
30#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
31
32#define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ)
33
34static int ebt_limit_match(const struct sk_buff *skb,
35 const struct net_device *in, const struct net_device *out,
36 const void *data, unsigned int datalen)
37{
38 struct ebt_limit_info *info = (struct ebt_limit_info *)data;
39 unsigned long now = jiffies;
40
41 spin_lock_bh(&limit_lock);
42 info->credit += (now - xchg(&info->prev, now)) * CREDITS_PER_JIFFY;
43 if (info->credit > info->credit_cap)
44 info->credit = info->credit_cap;
45
46 if (info->credit >= info->cost) {
47 /* We're not limited. */
48 info->credit -= info->cost;
49 spin_unlock_bh(&limit_lock);
50 return EBT_MATCH;
51 }
52
53 spin_unlock_bh(&limit_lock);
54 return EBT_NOMATCH;
55}
56
57/* Precision saver. */
58static u_int32_t
59user2credits(u_int32_t user)
60{
61 /* If multiplying would overflow... */
62 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
63 /* Divide first. */
64 return (user / EBT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
65
66 return (user * HZ * CREDITS_PER_JIFFY) / EBT_LIMIT_SCALE;
67}
68
69static int ebt_limit_check(const char *tablename, unsigned int hookmask,
70 const struct ebt_entry *e, void *data, unsigned int datalen)
71{
72 struct ebt_limit_info *info = (struct ebt_limit_info *)data;
73
74 if (datalen != EBT_ALIGN(sizeof(struct ebt_limit_info)))
75 return -EINVAL;
76
77 /* Check for overflow. */
78 if (info->burst == 0 ||
79 user2credits(info->avg * info->burst) < user2credits(info->avg)) {
80 printk("Overflow in ebt_limit, try lower: %u/%u\n",
81 info->avg, info->burst);
82 return -EINVAL;
83 }
84
85 /* User avg in seconds * EBT_LIMIT_SCALE: convert to jiffies * 128. */
86 info->prev = jiffies;
87 info->credit = user2credits(info->avg * info->burst);
88 info->credit_cap = user2credits(info->avg * info->burst);
89 info->cost = user2credits(info->avg);
90 return 0;
91}
92
93static struct ebt_match ebt_limit_reg =
94{
95 .name = EBT_LIMIT_MATCH,
96 .match = ebt_limit_match,
97 .check = ebt_limit_check,
98 .me = THIS_MODULE,
99};
100
101static int __init init(void)
102{
103 return ebt_register_match(&ebt_limit_reg);
104}
105
106static void __exit fini(void)
107{
108 ebt_unregister_match(&ebt_limit_reg);
109}
110
111module_init(init);
112module_exit(fini);
113MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
new file mode 100644
index 000000000000..e4ae34b88925
--- /dev/null
+++ b/net/bridge/netfilter/ebt_log.c
@@ -0,0 +1,171 @@
1/*
2 * ebt_log
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_log.h>
13#include <linux/module.h>
14#include <linux/ip.h>
15#include <linux/if_arp.h>
16#include <linux/spinlock.h>
17
18static DEFINE_SPINLOCK(ebt_log_lock);
19
20static int ebt_log_check(const char *tablename, unsigned int hookmask,
21 const struct ebt_entry *e, void *data, unsigned int datalen)
22{
23 struct ebt_log_info *info = (struct ebt_log_info *)data;
24
25 if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info)))
26 return -EINVAL;
27 if (info->bitmask & ~EBT_LOG_MASK)
28 return -EINVAL;
29 if (info->loglevel >= 8)
30 return -EINVAL;
31 info->prefix[EBT_LOG_PREFIX_SIZE - 1] = '\0';
32 return 0;
33}
34
35struct tcpudphdr
36{
37 uint16_t src;
38 uint16_t dst;
39};
40
41struct arppayload
42{
43 unsigned char mac_src[ETH_ALEN];
44 unsigned char ip_src[4];
45 unsigned char mac_dst[ETH_ALEN];
46 unsigned char ip_dst[4];
47};
48
49static void print_MAC(unsigned char *p)
50{
51 int i;
52
53 for (i = 0; i < ETH_ALEN; i++, p++)
54 printk("%02x%c", *p, i == ETH_ALEN - 1 ? ' ':':');
55}
56
57#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
58static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
59 const struct net_device *in, const struct net_device *out,
60 const void *data, unsigned int datalen)
61{
62 struct ebt_log_info *info = (struct ebt_log_info *)data;
63 char level_string[4] = "< >";
64 union {struct iphdr iph; struct tcpudphdr ports;
65 struct arphdr arph; struct arppayload arpp;} u;
66
67 level_string[1] = '0' + info->loglevel;
68 spin_lock_bh(&ebt_log_lock);
69 printk(level_string);
70 printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "",
71 out ? out->name : "");
72
73 printk("MAC source = ");
74 print_MAC(eth_hdr(skb)->h_source);
75 printk("MAC dest = ");
76 print_MAC(eth_hdr(skb)->h_dest);
77
78 printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
79
80 if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
81 htons(ETH_P_IP)){
82 struct iphdr _iph, *ih;
83
84 ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
85 if (ih == NULL) {
86 printk(" INCOMPLETE IP header");
87 goto out;
88 }
89 printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,",
90 NIPQUAD(ih->saddr), NIPQUAD(ih->daddr));
91 printk(" IP tos=0x%02X, IP proto=%d", u.iph.tos,
92 ih->protocol);
93 if (ih->protocol == IPPROTO_TCP ||
94 ih->protocol == IPPROTO_UDP) {
95 struct tcpudphdr _ports, *pptr;
96
97 pptr = skb_header_pointer(skb, ih->ihl*4,
98 sizeof(_ports), &_ports);
99 if (pptr == NULL) {
100 printk(" INCOMPLETE TCP/UDP header");
101 goto out;
102 }
103 printk(" SPT=%u DPT=%u", ntohs(pptr->src),
104 ntohs(pptr->dst));
105 }
106 goto out;
107 }
108
109 if ((info->bitmask & EBT_LOG_ARP) &&
110 ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
111 (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
112 struct arphdr _arph, *ah;
113
114 ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
115 if (ah == NULL) {
116 printk(" INCOMPLETE ARP header");
117 goto out;
118 }
119 printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
120 ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
121 ntohs(ah->ar_op));
122
123 /* If it's for Ethernet and the lengths are OK,
124 * then log the ARP payload */
125 if (ah->ar_hrd == htons(1) &&
126 ah->ar_hln == ETH_ALEN &&
127 ah->ar_pln == sizeof(uint32_t)) {
128 struct arppayload _arpp, *ap;
129
130 ap = skb_header_pointer(skb, sizeof(u.arph),
131 sizeof(_arpp), &_arpp);
132 if (ap == NULL) {
133 printk(" INCOMPLETE ARP payload");
134 goto out;
135 }
136 printk(" ARP MAC SRC=");
137 print_MAC(ap->mac_src);
138 printk(" ARP IP SRC=%u.%u.%u.%u",
139 myNIPQUAD(ap->ip_src));
140 printk(" ARP MAC DST=");
141 print_MAC(ap->mac_dst);
142 printk(" ARP IP DST=%u.%u.%u.%u",
143 myNIPQUAD(ap->ip_dst));
144 }
145 }
146out:
147 printk("\n");
148 spin_unlock_bh(&ebt_log_lock);
149}
150
151static struct ebt_watcher log =
152{
153 .name = EBT_LOG_WATCHER,
154 .watcher = ebt_log,
155 .check = ebt_log_check,
156 .me = THIS_MODULE,
157};
158
159static int __init init(void)
160{
161 return ebt_register_watcher(&log);
162}
163
164static void __exit fini(void)
165{
166 ebt_unregister_watcher(&log);
167}
168
169module_init(init);
170module_exit(fini);
171MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
new file mode 100644
index 000000000000..02c632b4d325
--- /dev/null
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -0,0 +1,68 @@
1/*
2 * ebt_mark
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * July, 2002
8 *
9 */
10
11/* The mark target can be used in any chain,
12 * I believe adding a mangle table just for marking is total overkill.
13 * Marking a frame doesn't really change anything in the frame anyway.
14 */
15
16#include <linux/netfilter_bridge/ebtables.h>
17#include <linux/netfilter_bridge/ebt_mark_t.h>
18#include <linux/module.h>
19
20static int ebt_target_mark(struct sk_buff **pskb, unsigned int hooknr,
21 const struct net_device *in, const struct net_device *out,
22 const void *data, unsigned int datalen)
23{
24 struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data;
25
26 if ((*pskb)->nfmark != info->mark) {
27 (*pskb)->nfmark = info->mark;
28 (*pskb)->nfcache |= NFC_ALTERED;
29 }
30 return info->target;
31}
32
33static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
34 const struct ebt_entry *e, void *data, unsigned int datalen)
35{
36 struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data;
37
38 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
39 return -EINVAL;
40 if (BASE_CHAIN && info->target == EBT_RETURN)
41 return -EINVAL;
42 CLEAR_BASE_CHAIN_BIT;
43 if (INVALID_TARGET)
44 return -EINVAL;
45 return 0;
46}
47
48static struct ebt_target mark_target =
49{
50 .name = EBT_MARK_TARGET,
51 .target = ebt_target_mark,
52 .check = ebt_target_mark_check,
53 .me = THIS_MODULE,
54};
55
56static int __init init(void)
57{
58 return ebt_register_target(&mark_target);
59}
60
61static void __exit fini(void)
62{
63 ebt_unregister_target(&mark_target);
64}
65
66module_init(init);
67module_exit(fini);
68MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
new file mode 100644
index 000000000000..625102de1495
--- /dev/null
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -0,0 +1,62 @@
1/*
2 * ebt_mark_m
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * July, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_mark_m.h>
13#include <linux/module.h>
14
15static int ebt_filter_mark(const struct sk_buff *skb,
16 const struct net_device *in, const struct net_device *out, const void *data,
17 unsigned int datalen)
18{
19 struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
20
21 if (info->bitmask & EBT_MARK_OR)
22 return !(!!(skb->nfmark & info->mask) ^ info->invert);
23 return !(((skb->nfmark & info->mask) == info->mark) ^ info->invert);
24}
25
26static int ebt_mark_check(const char *tablename, unsigned int hookmask,
27 const struct ebt_entry *e, void *data, unsigned int datalen)
28{
29 struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
30
31 if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_m_info)))
32 return -EINVAL;
33 if (info->bitmask & ~EBT_MARK_MASK)
34 return -EINVAL;
35 if ((info->bitmask & EBT_MARK_OR) && (info->bitmask & EBT_MARK_AND))
36 return -EINVAL;
37 if (!info->bitmask)
38 return -EINVAL;
39 return 0;
40}
41
42static struct ebt_match filter_mark =
43{
44 .name = EBT_MARK_MATCH,
45 .match = ebt_filter_mark,
46 .check = ebt_mark_check,
47 .me = THIS_MODULE,
48};
49
50static int __init init(void)
51{
52 return ebt_register_match(&filter_mark);
53}
54
55static void __exit fini(void)
56{
57 ebt_unregister_match(&filter_mark);
58}
59
60module_init(init);
61module_exit(fini);
62MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
new file mode 100644
index 000000000000..ecd3b42b19b0
--- /dev/null
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -0,0 +1,59 @@
1/*
2 * ebt_pkttype
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2003
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_pkttype.h>
13#include <linux/module.h>
14
15static int ebt_filter_pkttype(const struct sk_buff *skb,
16 const struct net_device *in,
17 const struct net_device *out,
18 const void *data,
19 unsigned int datalen)
20{
21 struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data;
22
23 return (skb->pkt_type != info->pkt_type) ^ info->invert;
24}
25
26static int ebt_pkttype_check(const char *tablename, unsigned int hookmask,
27 const struct ebt_entry *e, void *data, unsigned int datalen)
28{
29 struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data;
30
31 if (datalen != EBT_ALIGN(sizeof(struct ebt_pkttype_info)))
32 return -EINVAL;
33 if (info->invert != 0 && info->invert != 1)
34 return -EINVAL;
35 /* Allow any pkt_type value */
36 return 0;
37}
38
39static struct ebt_match filter_pkttype =
40{
41 .name = EBT_PKTTYPE_MATCH,
42 .match = ebt_filter_pkttype,
43 .check = ebt_pkttype_check,
44 .me = THIS_MODULE,
45};
46
47static int __init init(void)
48{
49 return ebt_register_match(&filter_pkttype);
50}
51
52static void __exit fini(void)
53{
54 ebt_unregister_match(&filter_pkttype);
55}
56
57module_init(init);
58module_exit(fini);
59MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
new file mode 100644
index 000000000000..1538b4386662
--- /dev/null
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -0,0 +1,81 @@
1/*
2 * ebt_redirect
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_redirect.h>
13#include <linux/module.h>
14#include <net/sock.h>
15#include "../br_private.h"
16
17static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
18 const struct net_device *in, const struct net_device *out,
19 const void *data, unsigned int datalen)
20{
21 struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
22
23 if (skb_shared(*pskb) || skb_cloned(*pskb)) {
24 struct sk_buff *nskb;
25
26 nskb = skb_copy(*pskb, GFP_ATOMIC);
27 if (!nskb)
28 return NF_DROP;
29 if ((*pskb)->sk)
30 skb_set_owner_w(nskb, (*pskb)->sk);
31 kfree_skb(*pskb);
32 *pskb = nskb;
33 }
34 if (hooknr != NF_BR_BROUTING)
35 memcpy(eth_hdr(*pskb)->h_dest,
36 in->br_port->br->dev->dev_addr, ETH_ALEN);
37 else
38 memcpy(eth_hdr(*pskb)->h_dest, in->dev_addr, ETH_ALEN);
39 (*pskb)->pkt_type = PACKET_HOST;
40 return info->target;
41}
42
43static int ebt_target_redirect_check(const char *tablename, unsigned int hookmask,
44 const struct ebt_entry *e, void *data, unsigned int datalen)
45{
46 struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
47
48 if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info)))
49 return -EINVAL;
50 if (BASE_CHAIN && info->target == EBT_RETURN)
51 return -EINVAL;
52 CLEAR_BASE_CHAIN_BIT;
53 if ( (strcmp(tablename, "nat") || hookmask & ~(1 << NF_BR_PRE_ROUTING)) &&
54 (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
55 return -EINVAL;
56 if (INVALID_TARGET)
57 return -EINVAL;
58 return 0;
59}
60
61static struct ebt_target redirect_target =
62{
63 .name = EBT_REDIRECT_TARGET,
64 .target = ebt_target_redirect,
65 .check = ebt_target_redirect_check,
66 .me = THIS_MODULE,
67};
68
69static int __init init(void)
70{
71 return ebt_register_target(&redirect_target);
72}
73
74static void __exit fini(void)
75{
76 ebt_unregister_target(&redirect_target);
77}
78
79module_init(init);
80module_exit(fini);
81MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
new file mode 100644
index 000000000000..1529bdcb9a48
--- /dev/null
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -0,0 +1,76 @@
1/*
2 * ebt_snat
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * June, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_nat.h>
13#include <linux/module.h>
14#include <net/sock.h>
15
16static int ebt_target_snat(struct sk_buff **pskb, unsigned int hooknr,
17 const struct net_device *in, const struct net_device *out,
18 const void *data, unsigned int datalen)
19{
20 struct ebt_nat_info *info = (struct ebt_nat_info *) data;
21
22 if (skb_shared(*pskb) || skb_cloned(*pskb)) {
23 struct sk_buff *nskb;
24
25 nskb = skb_copy(*pskb, GFP_ATOMIC);
26 if (!nskb)
27 return NF_DROP;
28 if ((*pskb)->sk)
29 skb_set_owner_w(nskb, (*pskb)->sk);
30 kfree_skb(*pskb);
31 *pskb = nskb;
32 }
33 memcpy(eth_hdr(*pskb)->h_source, info->mac, ETH_ALEN);
34 return info->target;
35}
36
37static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
38 const struct ebt_entry *e, void *data, unsigned int datalen)
39{
40 struct ebt_nat_info *info = (struct ebt_nat_info *) data;
41
42 if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
43 return -EINVAL;
44 if (BASE_CHAIN && info->target == EBT_RETURN)
45 return -EINVAL;
46 CLEAR_BASE_CHAIN_BIT;
47 if (strcmp(tablename, "nat"))
48 return -EINVAL;
49 if (hookmask & ~(1 << NF_BR_POST_ROUTING))
50 return -EINVAL;
51 if (INVALID_TARGET)
52 return -EINVAL;
53 return 0;
54}
55
56static struct ebt_target snat =
57{
58 .name = EBT_SNAT_TARGET,
59 .target = ebt_target_snat,
60 .check = ebt_target_snat_check,
61 .me = THIS_MODULE,
62};
63
64static int __init init(void)
65{
66 return ebt_register_target(&snat);
67}
68
69static void __exit fini(void)
70{
71 ebt_unregister_target(&snat);
72}
73
74module_init(init);
75module_exit(fini);
76MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
new file mode 100644
index 000000000000..f8a8cdec16ee
--- /dev/null
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -0,0 +1,194 @@
1/*
2 * ebt_stp
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Stephen Hemminger <shemminger@osdl.org>
7 *
8 * July, 2003
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_stp.h>
13#include <linux/module.h>
14
15#define BPDU_TYPE_CONFIG 0
16#define BPDU_TYPE_TCN 0x80
17
18struct stp_header {
19 uint8_t dsap;
20 uint8_t ssap;
21 uint8_t ctrl;
22 uint8_t pid;
23 uint8_t vers;
24 uint8_t type;
25};
26
27struct stp_config_pdu {
28 uint8_t flags;
29 uint8_t root[8];
30 uint8_t root_cost[4];
31 uint8_t sender[8];
32 uint8_t port[2];
33 uint8_t msg_age[2];
34 uint8_t max_age[2];
35 uint8_t hello_time[2];
36 uint8_t forward_delay[2];
37};
38
39#define NR16(p) (p[0] << 8 | p[1])
40#define NR32(p) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3])
41
42static int ebt_filter_config(struct ebt_stp_info *info,
43 struct stp_config_pdu *stpc)
44{
45 struct ebt_stp_config_info *c;
46 uint16_t v16;
47 uint32_t v32;
48 int verdict, i;
49
50 c = &info->config;
51 if ((info->bitmask & EBT_STP_FLAGS) &&
52 FWINV(c->flags != stpc->flags, EBT_STP_FLAGS))
53 return EBT_NOMATCH;
54 if (info->bitmask & EBT_STP_ROOTPRIO) {
55 v16 = NR16(stpc->root);
56 if (FWINV(v16 < c->root_priol ||
57 v16 > c->root_priou, EBT_STP_ROOTPRIO))
58 return EBT_NOMATCH;
59 }
60 if (info->bitmask & EBT_STP_ROOTADDR) {
61 verdict = 0;
62 for (i = 0; i < 6; i++)
63 verdict |= (stpc->root[2+i] ^ c->root_addr[i]) &
64 c->root_addrmsk[i];
65 if (FWINV(verdict != 0, EBT_STP_ROOTADDR))
66 return EBT_NOMATCH;
67 }
68 if (info->bitmask & EBT_STP_ROOTCOST) {
69 v32 = NR32(stpc->root_cost);
70 if (FWINV(v32 < c->root_costl ||
71 v32 > c->root_costu, EBT_STP_ROOTCOST))
72 return EBT_NOMATCH;
73 }
74 if (info->bitmask & EBT_STP_SENDERPRIO) {
75 v16 = NR16(stpc->sender);
76 if (FWINV(v16 < c->sender_priol ||
77 v16 > c->sender_priou, EBT_STP_SENDERPRIO))
78 return EBT_NOMATCH;
79 }
80 if (info->bitmask & EBT_STP_SENDERADDR) {
81 verdict = 0;
82 for (i = 0; i < 6; i++)
83 verdict |= (stpc->sender[2+i] ^ c->sender_addr[i]) &
84 c->sender_addrmsk[i];
85 if (FWINV(verdict != 0, EBT_STP_SENDERADDR))
86 return EBT_NOMATCH;
87 }
88 if (info->bitmask & EBT_STP_PORT) {
89 v16 = NR16(stpc->port);
90 if (FWINV(v16 < c->portl ||
91 v16 > c->portu, EBT_STP_PORT))
92 return EBT_NOMATCH;
93 }
94 if (info->bitmask & EBT_STP_MSGAGE) {
95 v16 = NR16(stpc->msg_age);
96 if (FWINV(v16 < c->msg_agel ||
97 v16 > c->msg_ageu, EBT_STP_MSGAGE))
98 return EBT_NOMATCH;
99 }
100 if (info->bitmask & EBT_STP_MAXAGE) {
101 v16 = NR16(stpc->max_age);
102 if (FWINV(v16 < c->max_agel ||
103 v16 > c->max_ageu, EBT_STP_MAXAGE))
104 return EBT_NOMATCH;
105 }
106 if (info->bitmask & EBT_STP_HELLOTIME) {
107 v16 = NR16(stpc->hello_time);
108 if (FWINV(v16 < c->hello_timel ||
109 v16 > c->hello_timeu, EBT_STP_HELLOTIME))
110 return EBT_NOMATCH;
111 }
112 if (info->bitmask & EBT_STP_FWDD) {
113 v16 = NR16(stpc->forward_delay);
114 if (FWINV(v16 < c->forward_delayl ||
115 v16 > c->forward_delayu, EBT_STP_FWDD))
116 return EBT_NOMATCH;
117 }
118 return EBT_MATCH;
119}
120
121static int ebt_filter_stp(const struct sk_buff *skb, const struct net_device *in,
122 const struct net_device *out, const void *data, unsigned int datalen)
123{
124 struct ebt_stp_info *info = (struct ebt_stp_info *)data;
125 struct stp_header _stph, *sp;
126 uint8_t header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00};
127
128 sp = skb_header_pointer(skb, 0, sizeof(_stph), &_stph);
129 if (sp == NULL)
130 return EBT_NOMATCH;
131
132 /* The stp code only considers these */
133 if (memcmp(sp, header, sizeof(header)))
134 return EBT_NOMATCH;
135
136 if (info->bitmask & EBT_STP_TYPE
137 && FWINV(info->type != sp->type, EBT_STP_TYPE))
138 return EBT_NOMATCH;
139
140 if (sp->type == BPDU_TYPE_CONFIG &&
141 info->bitmask & EBT_STP_CONFIG_MASK) {
142 struct stp_config_pdu _stpc, *st;
143
144 st = skb_header_pointer(skb, sizeof(_stph),
145 sizeof(_stpc), &_stpc);
146 if (st == NULL)
147 return EBT_NOMATCH;
148 return ebt_filter_config(info, st);
149 }
150 return EBT_MATCH;
151}
152
153static int ebt_stp_check(const char *tablename, unsigned int hookmask,
154 const struct ebt_entry *e, void *data, unsigned int datalen)
155{
156 struct ebt_stp_info *info = (struct ebt_stp_info *)data;
157 int len = EBT_ALIGN(sizeof(struct ebt_stp_info));
158 uint8_t bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
159 uint8_t msk[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
160
161 if (info->bitmask & ~EBT_STP_MASK || info->invflags & ~EBT_STP_MASK ||
162 !(info->bitmask & EBT_STP_MASK))
163 return -EINVAL;
164 if (datalen != len)
165 return -EINVAL;
166 /* Make sure the match only receives stp frames */
167 if (memcmp(e->destmac, bridge_ula, ETH_ALEN) ||
168 memcmp(e->destmsk, msk, ETH_ALEN) || !(e->bitmask & EBT_DESTMAC))
169 return -EINVAL;
170
171 return 0;
172}
173
174static struct ebt_match filter_stp =
175{
176 .name = EBT_STP_MATCH,
177 .match = ebt_filter_stp,
178 .check = ebt_stp_check,
179 .me = THIS_MODULE,
180};
181
182static int __init init(void)
183{
184 return ebt_register_match(&filter_stp);
185}
186
187static void __exit fini(void)
188{
189 ebt_unregister_match(&filter_stp);
190}
191
192module_init(init);
193module_exit(fini);
194MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
new file mode 100644
index 000000000000..01af4fcef26d
--- /dev/null
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -0,0 +1,295 @@
1/*
2 * netfilter module for userspace bridged Ethernet frames logging daemons
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * November, 2004
8 *
9 * Based on ipt_ULOG.c, which is
10 * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
11 *
12 * This module accepts two parameters:
13 *
14 * nlbufsiz:
15 * The parameter specifies how big the buffer for each netlink multicast
16 * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
17 * get accumulated in the kernel until they are sent to userspace. It is
18 * NOT possible to allocate more than 128kB, and it is strongly discouraged,
19 * because atomically allocating 128kB inside the network rx softirq is not
20 * reliable. Please also keep in mind that this buffer size is allocated for
21 * each nlgroup you are using, so the total kernel memory usage increases
22 * by that factor.
23 *
24 * flushtimeout:
25 * Specify, after how many hundredths of a second the queue should be
26 * flushed even if it is not full yet.
27 *
28 */
29
30#include <linux/module.h>
31#include <linux/config.h>
32#include <linux/spinlock.h>
33#include <linux/socket.h>
34#include <linux/skbuff.h>
35#include <linux/kernel.h>
36#include <linux/timer.h>
37#include <linux/netlink.h>
38#include <linux/netdevice.h>
39#include <linux/module.h>
40#include <linux/netfilter_bridge/ebtables.h>
41#include <linux/netfilter_bridge/ebt_ulog.h>
42#include <net/sock.h>
43#include "../br_private.h"
44
45#define PRINTR(format, args...) do { if (net_ratelimit()) \
46 printk(format , ## args); } while (0)
47
48static unsigned int nlbufsiz = 4096;
49module_param(nlbufsiz, uint, 0600);
50MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) "
51 "(defaults to 4096)");
52
53static unsigned int flushtimeout = 10;
54module_param(flushtimeout, uint, 0600);
55MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) "
56 "(defaults to 10)");
57
58typedef struct {
59 unsigned int qlen; /* number of nlmsgs' in the skb */
60 struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */
61 struct sk_buff *skb; /* the pre-allocated skb */
62 struct timer_list timer; /* the timer function */
63 spinlock_t lock; /* the per-queue lock */
64} ebt_ulog_buff_t;
65
66static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS];
67static struct sock *ebtulognl;
68
69/* send one ulog_buff_t to userspace */
70static void ulog_send(unsigned int nlgroup)
71{
72 ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup];
73
74 if (timer_pending(&ub->timer))
75 del_timer(&ub->timer);
76
77 /* last nlmsg needs NLMSG_DONE */
78 if (ub->qlen > 1)
79 ub->lastnlh->nlmsg_type = NLMSG_DONE;
80
81 NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup;
82 netlink_broadcast(ebtulognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC);
83
84 ub->qlen = 0;
85 ub->skb = NULL;
86}
87
88/* timer function to flush queue in flushtimeout time */
89static void ulog_timer(unsigned long data)
90{
91 spin_lock_bh(&ulog_buffers[data].lock);
92 if (ulog_buffers[data].skb)
93 ulog_send(data);
94 spin_unlock_bh(&ulog_buffers[data].lock);
95}
96
97static struct sk_buff *ulog_alloc_skb(unsigned int size)
98{
99 struct sk_buff *skb;
100
101 skb = alloc_skb(nlbufsiz, GFP_ATOMIC);
102 if (!skb) {
103 PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer "
104 "of size %ub!\n", nlbufsiz);
105 if (size < nlbufsiz) {
106 /* try to allocate only as much as we need for
107 * current packet */
108 skb = alloc_skb(size, GFP_ATOMIC);
109 if (!skb)
110 PRINTR(KERN_ERR "ebt_ulog: can't even allocate "
111 "buffer of size %ub\n", size);
112 }
113 }
114
115 return skb;
116}
117
118static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
119 const struct net_device *in, const struct net_device *out,
120 const void *data, unsigned int datalen)
121{
122 ebt_ulog_packet_msg_t *pm;
123 size_t size, copy_len;
124 struct nlmsghdr *nlh;
125 struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
126 unsigned int group = uloginfo->nlgroup;
127 ebt_ulog_buff_t *ub = &ulog_buffers[group];
128 spinlock_t *lock = &ub->lock;
129
130 if ((uloginfo->cprange == 0) ||
131 (uloginfo->cprange > skb->len + ETH_HLEN))
132 copy_len = skb->len + ETH_HLEN;
133 else
134 copy_len = uloginfo->cprange;
135
136 size = NLMSG_SPACE(sizeof(*pm) + copy_len);
137 if (size > nlbufsiz) {
138 PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n",
139 size, nlbufsiz);
140 return;
141 }
142
143 spin_lock_bh(lock);
144
145 if (!ub->skb) {
146 if (!(ub->skb = ulog_alloc_skb(size)))
147 goto alloc_failure;
148 } else if (size > skb_tailroom(ub->skb)) {
149 ulog_send(group);
150
151 if (!(ub->skb = ulog_alloc_skb(size)))
152 goto alloc_failure;
153 }
154
155 nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0,
156 size - NLMSG_ALIGN(sizeof(*nlh)));
157 ub->qlen++;
158
159 pm = NLMSG_DATA(nlh);
160
161 /* Fill in the ulog data */
162 pm->version = EBT_ULOG_VERSION;
163 do_gettimeofday(&pm->stamp);
164 if (ub->qlen == 1)
165 ub->skb->stamp = pm->stamp;
166 pm->data_len = copy_len;
167 pm->mark = skb->nfmark;
168 pm->hook = hooknr;
169 if (uloginfo->prefix != NULL)
170 strcpy(pm->prefix, uloginfo->prefix);
171 else
172 *(pm->prefix) = '\0';
173
174 if (in) {
175 strcpy(pm->physindev, in->name);
176 /* If in isn't a bridge, then physindev==indev */
177 if (in->br_port)
178 strcpy(pm->indev, in->br_port->br->dev->name);
179 else
180 strcpy(pm->indev, in->name);
181 } else
182 pm->indev[0] = pm->physindev[0] = '\0';
183
184 if (out) {
185 /* If out exists, then out is a bridge port */
186 strcpy(pm->physoutdev, out->name);
187 strcpy(pm->outdev, out->br_port->br->dev->name);
188 } else
189 pm->outdev[0] = pm->physoutdev[0] = '\0';
190
191 if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
192 BUG();
193
194 if (ub->qlen > 1)
195 ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
196
197 ub->lastnlh = nlh;
198
199 if (ub->qlen >= uloginfo->qthreshold)
200 ulog_send(group);
201 else if (!timer_pending(&ub->timer)) {
202 ub->timer.expires = jiffies + flushtimeout * HZ / 100;
203 add_timer(&ub->timer);
204 }
205
206unlock:
207 spin_unlock_bh(lock);
208
209 return;
210
211nlmsg_failure:
212 printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should "
213 "not happen, please report to author.\n");
214 goto unlock;
215alloc_failure:
216 goto unlock;
217}
218
219static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
220 const struct ebt_entry *e, void *data, unsigned int datalen)
221{
222 struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
223
224 if (datalen != EBT_ALIGN(sizeof(struct ebt_ulog_info)) ||
225 uloginfo->nlgroup > 31)
226 return -EINVAL;
227
228 uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
229
230 if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
231 uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
232
233 return 0;
234}
235
236static struct ebt_watcher ulog = {
237 .name = EBT_ULOG_WATCHER,
238 .watcher = ebt_ulog,
239 .check = ebt_ulog_check,
240 .me = THIS_MODULE,
241};
242
243static int __init init(void)
244{
245 int i, ret = 0;
246
247 if (nlbufsiz >= 128*1024) {
248 printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB,"
249 " please try a smaller nlbufsiz parameter.\n");
250 return -EINVAL;
251 }
252
253 /* initialize ulog_buffers */
254 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
255 init_timer(&ulog_buffers[i].timer);
256 ulog_buffers[i].timer.function = ulog_timer;
257 ulog_buffers[i].timer.data = i;
258 spin_lock_init(&ulog_buffers[i].lock);
259 }
260
261 ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL);
262 if (!ebtulognl)
263 ret = -ENOMEM;
264 else if ((ret = ebt_register_watcher(&ulog)))
265 sock_release(ebtulognl->sk_socket);
266
267 return ret;
268}
269
270static void __exit fini(void)
271{
272 ebt_ulog_buff_t *ub;
273 int i;
274
275 ebt_unregister_watcher(&ulog);
276 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
277 ub = &ulog_buffers[i];
278 if (timer_pending(&ub->timer))
279 del_timer(&ub->timer);
280 spin_lock_bh(&ub->lock);
281 if (ub->skb) {
282 kfree_skb(ub->skb);
283 ub->skb = NULL;
284 }
285 spin_unlock_bh(&ub->lock);
286 }
287 sock_release(ebtulognl->sk_socket);
288}
289
290module_init(init);
291module_exit(fini);
292MODULE_LICENSE("GPL");
293MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
294MODULE_DESCRIPTION("ebtables userspace logging module for bridged Ethernet"
295 " frames");
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
new file mode 100644
index 000000000000..db60d734908b
--- /dev/null
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -0,0 +1,195 @@
1/*
2 * Description: EBTables 802.1Q match extension kernelspace module.
3 * Authors: Nick Fedchik <nick@fedchik.org.ua>
4 * Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/if_ether.h>
22#include <linux/if_vlan.h>
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/netfilter_bridge/ebtables.h>
26#include <linux/netfilter_bridge/ebt_vlan.h>
27
28static int debug;
29#define MODULE_VERS "0.6"
30
31module_param(debug, int, 0);
32MODULE_PARM_DESC(debug, "debug=1 is turn on debug messages");
33MODULE_AUTHOR("Nick Fedchik <nick@fedchik.org.ua>");
34MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
35 MODULE_VERS);
36MODULE_LICENSE("GPL");
37
38
39#define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args)
40#define INV_FLAG(_inv_flag_) (info->invflags & _inv_flag_) ? "!" : ""
41#define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
42#define SET_BITMASK(_BIT_MASK_) info->bitmask |= _BIT_MASK_
43#define EXIT_ON_MISMATCH(_MATCH_,_MASK_) {if (!((info->_MATCH_ == _MATCH_)^!!(info->invflags & _MASK_))) return EBT_NOMATCH;}
44
45static int
46ebt_filter_vlan(const struct sk_buff *skb,
47 const struct net_device *in,
48 const struct net_device *out,
49 const void *data, unsigned int datalen)
50{
51 struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
52 struct vlan_hdr _frame, *fp;
53
54 unsigned short TCI; /* Whole TCI, given from parsed frame */
55 unsigned short id; /* VLAN ID, given from frame TCI */
56 unsigned char prio; /* user_priority, given from frame TCI */
57 /* VLAN encapsulated Type/Length field, given from orig frame */
58 unsigned short encap;
59
60 fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame);
61 if (fp == NULL)
62 return EBT_NOMATCH;
63
64 /* Tag Control Information (TCI) consists of the following elements:
65 * - User_priority. The user_priority field is three bits in length,
66 * interpreted as a binary number.
67 * - Canonical Format Indicator (CFI). The Canonical Format Indicator
68 * (CFI) is a single bit flag value. Currently ignored.
69 * - VLAN Identifier (VID). The VID is encoded as
70 * an unsigned binary number. */
71 TCI = ntohs(fp->h_vlan_TCI);
72 id = TCI & VLAN_VID_MASK;
73 prio = (TCI >> 13) & 0x7;
74 encap = fp->h_vlan_encapsulated_proto;
75
76 /* Checking VLAN Identifier (VID) */
77 if (GET_BITMASK(EBT_VLAN_ID))
78 EXIT_ON_MISMATCH(id, EBT_VLAN_ID);
79
80 /* Checking user_priority */
81 if (GET_BITMASK(EBT_VLAN_PRIO))
82 EXIT_ON_MISMATCH(prio, EBT_VLAN_PRIO);
83
84 /* Checking Encapsulated Proto (Length/Type) field */
85 if (GET_BITMASK(EBT_VLAN_ENCAP))
86 EXIT_ON_MISMATCH(encap, EBT_VLAN_ENCAP);
87
88 return EBT_MATCH;
89}
90
91static int
92ebt_check_vlan(const char *tablename,
93 unsigned int hooknr,
94 const struct ebt_entry *e, void *data, unsigned int datalen)
95{
96 struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
97
98 /* Parameters buffer overflow check */
99 if (datalen != EBT_ALIGN(sizeof(struct ebt_vlan_info))) {
100 DEBUG_MSG
101 ("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
102 datalen, sizeof(struct ebt_vlan_info));
103 return -EINVAL;
104 }
105
106 /* Is it 802.1Q frame checked? */
107 if (e->ethproto != htons(ETH_P_8021Q)) {
108 DEBUG_MSG
109 ("passed entry proto %2.4X is not 802.1Q (8100)\n",
110 (unsigned short) ntohs(e->ethproto));
111 return -EINVAL;
112 }
113
114 /* Check for bitmask range
115 * True if even one bit is out of mask */
116 if (info->bitmask & ~EBT_VLAN_MASK) {
117 DEBUG_MSG("bitmask %2X is out of mask (%2X)\n",
118 info->bitmask, EBT_VLAN_MASK);
119 return -EINVAL;
120 }
121
122 /* Check for inversion flags range */
123 if (info->invflags & ~EBT_VLAN_MASK) {
124 DEBUG_MSG("inversion flags %2X is out of mask (%2X)\n",
125 info->invflags, EBT_VLAN_MASK);
126 return -EINVAL;
127 }
128
129 /* Reserved VLAN ID (VID) values
130 * -----------------------------
131 * 0 - The null VLAN ID.
132 * 1 - The default Port VID (PVID)
133 * 0x0FFF - Reserved for implementation use.
134 * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */
135 if (GET_BITMASK(EBT_VLAN_ID)) {
136 if (!!info->id) { /* if id!=0 => check vid range */
137 if (info->id > VLAN_GROUP_ARRAY_LEN) {
138 DEBUG_MSG
139 ("id %d is out of range (1-4096)\n",
140 info->id);
141 return -EINVAL;
142 }
143 /* Note: This is valid VLAN-tagged frame point.
144 * Any value of user_priority are acceptable,
145 * but should be ignored according to 802.1Q Std.
146 * So we just drop the prio flag. */
147 info->bitmask &= ~EBT_VLAN_PRIO;
148 }
149 /* Else, id=0 (null VLAN ID) => user_priority range (any?) */
150 }
151
152 if (GET_BITMASK(EBT_VLAN_PRIO)) {
153 if ((unsigned char) info->prio > 7) {
154 DEBUG_MSG("prio %d is out of range (0-7)\n",
155 info->prio);
156 return -EINVAL;
157 }
158 }
159 /* Check for encapsulated proto range - it is possible to be
160 * any value for u_short range.
161 * if_ether.h: ETH_ZLEN 60 - Min. octets in frame sans FCS */
162 if (GET_BITMASK(EBT_VLAN_ENCAP)) {
163 if ((unsigned short) ntohs(info->encap) < ETH_ZLEN) {
164 DEBUG_MSG
165 ("encap frame length %d is less than minimal\n",
166 ntohs(info->encap));
167 return -EINVAL;
168 }
169 }
170
171 return 0;
172}
173
174static struct ebt_match filter_vlan = {
175 .name = EBT_VLAN_MATCH,
176 .match = ebt_filter_vlan,
177 .check = ebt_check_vlan,
178 .me = THIS_MODULE,
179};
180
181static int __init init(void)
182{
183 DEBUG_MSG("ebtables 802.1Q extension module v"
184 MODULE_VERS "\n");
185 DEBUG_MSG("module debug=%d\n", !!debug);
186 return ebt_register_match(&filter_vlan);
187}
188
189static void __exit fini(void)
190{
191 ebt_unregister_match(&filter_vlan);
192}
193
194module_init(init);
195module_exit(fini);
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
new file mode 100644
index 000000000000..1767c94cd3de
--- /dev/null
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -0,0 +1,86 @@
1/*
2 * ebtable_broute
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 * This table lets you choose between routing and bridging for frames
10 * entering on a bridge enslaved nic. This table is traversed before any
11 * other ebtables table. See net/bridge/br_input.c.
12 */
13
14#include <linux/netfilter_bridge/ebtables.h>
15#include <linux/module.h>
16#include <linux/if_bridge.h>
17
18/* EBT_ACCEPT means the frame will be bridged
19 * EBT_DROP means the frame will be routed
20 */
21static struct ebt_entries initial_chain = {
22 .name = "BROUTING",
23 .policy = EBT_ACCEPT,
24};
25
26static struct ebt_replace initial_table =
27{
28 .name = "broute",
29 .valid_hooks = 1 << NF_BR_BROUTING,
30 .entries_size = sizeof(struct ebt_entries),
31 .hook_entry = {
32 [NF_BR_BROUTING] = &initial_chain,
33 },
34 .entries = (char *)&initial_chain,
35};
36
37static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
38{
39 if (valid_hooks & ~(1 << NF_BR_BROUTING))
40 return -EINVAL;
41 return 0;
42}
43
44static struct ebt_table broute_table =
45{
46 .name = "broute",
47 .table = &initial_table,
48 .valid_hooks = 1 << NF_BR_BROUTING,
49 .lock = RW_LOCK_UNLOCKED,
50 .check = check,
51 .me = THIS_MODULE,
52};
53
54static int ebt_broute(struct sk_buff **pskb)
55{
56 int ret;
57
58 ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
59 &broute_table);
60 if (ret == NF_DROP)
61 return 1; /* route it */
62 return 0; /* bridge it */
63}
64
65static int __init init(void)
66{
67 int ret;
68
69 ret = ebt_register_table(&broute_table);
70 if (ret < 0)
71 return ret;
72 /* see br_input.c */
73 br_should_route_hook = ebt_broute;
74 return ret;
75}
76
77static void __exit fini(void)
78{
79 br_should_route_hook = NULL;
80 synchronize_net();
81 ebt_unregister_table(&broute_table);
82}
83
84module_init(init);
85module_exit(fini);
86MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
new file mode 100644
index 000000000000..c18666e0392b
--- /dev/null
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -0,0 +1,123 @@
1/*
2 * ebtable_filter
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/module.h>
13
14#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
15 (1 << NF_BR_LOCAL_OUT))
16
17static struct ebt_entries initial_chains[] =
18{
19 {
20 .name = "INPUT",
21 .policy = EBT_ACCEPT,
22 },
23 {
24 .name = "FORWARD",
25 .policy = EBT_ACCEPT,
26 },
27 {
28 .name = "OUTPUT",
29 .policy = EBT_ACCEPT,
30 },
31};
32
33static struct ebt_replace initial_table =
34{
35 .name = "filter",
36 .valid_hooks = FILTER_VALID_HOOKS,
37 .entries_size = 3 * sizeof(struct ebt_entries),
38 .hook_entry = {
39 [NF_BR_LOCAL_IN] = &initial_chains[0],
40 [NF_BR_FORWARD] = &initial_chains[1],
41 [NF_BR_LOCAL_OUT] = &initial_chains[2],
42 },
43 .entries = (char *)initial_chains,
44};
45
46static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
47{
48 if (valid_hooks & ~FILTER_VALID_HOOKS)
49 return -EINVAL;
50 return 0;
51}
52
53static struct ebt_table frame_filter =
54{
55 .name = "filter",
56 .table = &initial_table,
57 .valid_hooks = FILTER_VALID_HOOKS,
58 .lock = RW_LOCK_UNLOCKED,
59 .check = check,
60 .me = THIS_MODULE,
61};
62
63static unsigned int
64ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
65 const struct net_device *out, int (*okfn)(struct sk_buff *))
66{
67 return ebt_do_table(hook, pskb, in, out, &frame_filter);
68}
69
70static struct nf_hook_ops ebt_ops_filter[] = {
71 {
72 .hook = ebt_hook,
73 .owner = THIS_MODULE,
74 .pf = PF_BRIDGE,
75 .hooknum = NF_BR_LOCAL_IN,
76 .priority = NF_BR_PRI_FILTER_BRIDGED,
77 },
78 {
79 .hook = ebt_hook,
80 .owner = THIS_MODULE,
81 .pf = PF_BRIDGE,
82 .hooknum = NF_BR_FORWARD,
83 .priority = NF_BR_PRI_FILTER_BRIDGED,
84 },
85 {
86 .hook = ebt_hook,
87 .owner = THIS_MODULE,
88 .pf = PF_BRIDGE,
89 .hooknum = NF_BR_LOCAL_OUT,
90 .priority = NF_BR_PRI_FILTER_OTHER,
91 },
92};
93
94static int __init init(void)
95{
96 int i, j, ret;
97
98 ret = ebt_register_table(&frame_filter);
99 if (ret < 0)
100 return ret;
101 for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
102 if ((ret = nf_register_hook(&ebt_ops_filter[i])) < 0)
103 goto cleanup;
104 return ret;
105cleanup:
106 for (j = 0; j < i; j++)
107 nf_unregister_hook(&ebt_ops_filter[j]);
108 ebt_unregister_table(&frame_filter);
109 return ret;
110}
111
112static void __exit fini(void)
113{
114 int i;
115
116 for (i = 0; i < ARRAY_SIZE(ebt_ops_filter); i++)
117 nf_unregister_hook(&ebt_ops_filter[i]);
118 ebt_unregister_table(&frame_filter);
119}
120
121module_init(init);
122module_exit(fini);
123MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
new file mode 100644
index 000000000000..828cac2cc4a3
--- /dev/null
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -0,0 +1,130 @@
1/*
2 * ebtable_nat
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * April, 2002
8 *
9 */
10
11#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/module.h>
13
14#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \
15 (1 << NF_BR_POST_ROUTING))
16
17static struct ebt_entries initial_chains[] =
18{
19 {
20 .name = "PREROUTING",
21 .policy = EBT_ACCEPT,
22 },
23 {
24 .name = "OUTPUT",
25 .policy = EBT_ACCEPT,
26 },
27 {
28 .name = "POSTROUTING",
29 .policy = EBT_ACCEPT,
30 }
31};
32
33static struct ebt_replace initial_table =
34{
35 .name = "nat",
36 .valid_hooks = NAT_VALID_HOOKS,
37 .entries_size = 3 * sizeof(struct ebt_entries),
38 .hook_entry = {
39 [NF_BR_PRE_ROUTING] = &initial_chains[0],
40 [NF_BR_LOCAL_OUT] = &initial_chains[1],
41 [NF_BR_POST_ROUTING] = &initial_chains[2],
42 },
43 .entries = (char *)initial_chains,
44};
45
46static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
47{
48 if (valid_hooks & ~NAT_VALID_HOOKS)
49 return -EINVAL;
50 return 0;
51}
52
53static struct ebt_table frame_nat =
54{
55 .name = "nat",
56 .table = &initial_table,
57 .valid_hooks = NAT_VALID_HOOKS,
58 .lock = RW_LOCK_UNLOCKED,
59 .check = check,
60 .me = THIS_MODULE,
61};
62
63static unsigned int
64ebt_nat_dst(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
65 , const struct net_device *out, int (*okfn)(struct sk_buff *))
66{
67 return ebt_do_table(hook, pskb, in, out, &frame_nat);
68}
69
70static unsigned int
71ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *in
72 , const struct net_device *out, int (*okfn)(struct sk_buff *))
73{
74 return ebt_do_table(hook, pskb, in, out, &frame_nat);
75}
76
77static struct nf_hook_ops ebt_ops_nat[] = {
78 {
79 .hook = ebt_nat_dst,
80 .owner = THIS_MODULE,
81 .pf = PF_BRIDGE,
82 .hooknum = NF_BR_LOCAL_OUT,
83 .priority = NF_BR_PRI_NAT_DST_OTHER,
84 },
85 {
86 .hook = ebt_nat_src,
87 .owner = THIS_MODULE,
88 .pf = PF_BRIDGE,
89 .hooknum = NF_BR_POST_ROUTING,
90 .priority = NF_BR_PRI_NAT_SRC,
91 },
92 {
93 .hook = ebt_nat_dst,
94 .owner = THIS_MODULE,
95 .pf = PF_BRIDGE,
96 .hooknum = NF_BR_PRE_ROUTING,
97 .priority = NF_BR_PRI_NAT_DST_BRIDGED,
98 },
99};
100
101static int __init init(void)
102{
103 int i, ret, j;
104
105 ret = ebt_register_table(&frame_nat);
106 if (ret < 0)
107 return ret;
108 for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
109 if ((ret = nf_register_hook(&ebt_ops_nat[i])) < 0)
110 goto cleanup;
111 return ret;
112cleanup:
113 for (j = 0; j < i; j++)
114 nf_unregister_hook(&ebt_ops_nat[j]);
115 ebt_unregister_table(&frame_nat);
116 return ret;
117}
118
119static void __exit fini(void)
120{
121 int i;
122
123 for (i = 0; i < ARRAY_SIZE(ebt_ops_nat); i++)
124 nf_unregister_hook(&ebt_ops_nat[i]);
125 ebt_unregister_table(&frame_nat);
126}
127
128module_init(init);
129module_exit(fini);
130MODULE_LICENSE("GPL");
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
new file mode 100644
index 000000000000..18ebc664769b
--- /dev/null
+++ b/net/bridge/netfilter/ebtables.c
@@ -0,0 +1,1507 @@
1/*
2 * ebtables
3 *
4 * Author:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 *
7 * ebtables.c,v 2.0, July, 2002
8 *
9 * This code is stongly inspired on the iptables code which is
10 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18/* used for print_string */
19#include <linux/sched.h>
20#include <linux/tty.h>
21
22#include <linux/kmod.h>
23#include <linux/module.h>
24#include <linux/vmalloc.h>
25#include <linux/netfilter_bridge/ebtables.h>
26#include <linux/spinlock.h>
27#include <asm/uaccess.h>
28#include <linux/smp.h>
29#include <net/sock.h>
30/* needed for logical [in,out]-dev filtering */
31#include "../br_private.h"
32
33/* list_named_find */
34#define ASSERT_READ_LOCK(x)
35#define ASSERT_WRITE_LOCK(x)
36#include <linux/netfilter_ipv4/listhelp.h>
37
38#if 0
39/* use this for remote debugging
40 * Copyright (C) 1998 by Ori Pomerantz
41 * Print the string to the appropriate tty, the one
42 * the current task uses
43 */
44static void print_string(char *str)
45{
46 struct tty_struct *my_tty;
47
48 /* The tty for the current task */
49 my_tty = current->signal->tty;
50 if (my_tty != NULL) {
51 my_tty->driver->write(my_tty, 0, str, strlen(str));
52 my_tty->driver->write(my_tty, 0, "\015\012", 2);
53 }
54}
55
56#define BUGPRINT(args) print_string(args);
57#else
58#define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\
59 "report to author: "format, ## args)
60/* #define BUGPRINT(format, args...) */
61#endif
62#define MEMPRINT(format, args...) printk("kernel msg: ebtables "\
63 ": out of memory: "format, ## args)
64/* #define MEMPRINT(format, args...) */
65
66
67
68/*
69 * Each cpu has its own set of counters, so there is no need for write_lock in
70 * the softirq
71 * For reading or updating the counters, the user context needs to
72 * get a write_lock
73 */
74
75/* The size of each set of counters is altered to get cache alignment */
76#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
77#define COUNTER_OFFSET(n) (SMP_ALIGN(n * sizeof(struct ebt_counter)))
78#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
79 COUNTER_OFFSET(n) * cpu))
80
81
82
83static DECLARE_MUTEX(ebt_mutex);
84static LIST_HEAD(ebt_tables);
85static LIST_HEAD(ebt_targets);
86static LIST_HEAD(ebt_matches);
87static LIST_HEAD(ebt_watchers);
88
89static struct ebt_target ebt_standard_target =
90{ {NULL, NULL}, EBT_STANDARD_TARGET, NULL, NULL, NULL, NULL};
91
92static inline int ebt_do_watcher (struct ebt_entry_watcher *w,
93 const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in,
94 const struct net_device *out)
95{
96 w->u.watcher->watcher(skb, hooknr, in, out, w->data,
97 w->watcher_size);
98 /* watchers don't give a verdict */
99 return 0;
100}
101
102static inline int ebt_do_match (struct ebt_entry_match *m,
103 const struct sk_buff *skb, const struct net_device *in,
104 const struct net_device *out)
105{
106 return m->u.match->match(skb, in, out, m->data,
107 m->match_size);
108}
109
110static inline int ebt_dev_check(char *entry, const struct net_device *device)
111{
112 int i = 0;
113 char *devname = device->name;
114
115 if (*entry == '\0')
116 return 0;
117 if (!device)
118 return 1;
119 /* 1 is the wildcard token */
120 while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
121 i++;
122 return (devname[i] != entry[i] && entry[i] != 1);
123}
124
125#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
126/* process standard matches */
127static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
128 const struct net_device *in, const struct net_device *out)
129{
130 int verdict, i;
131
132 if (e->bitmask & EBT_802_3) {
133 if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO))
134 return 1;
135 } else if (!(e->bitmask & EBT_NOPROTO) &&
136 FWINV2(e->ethproto != h->h_proto, EBT_IPROTO))
137 return 1;
138
139 if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN))
140 return 1;
141 if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
142 return 1;
143 if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
144 e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
145 return 1;
146 if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
147 e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
148 return 1;
149
150 if (e->bitmask & EBT_SOURCEMAC) {
151 verdict = 0;
152 for (i = 0; i < 6; i++)
153 verdict |= (h->h_source[i] ^ e->sourcemac[i]) &
154 e->sourcemsk[i];
155 if (FWINV2(verdict != 0, EBT_ISOURCE) )
156 return 1;
157 }
158 if (e->bitmask & EBT_DESTMAC) {
159 verdict = 0;
160 for (i = 0; i < 6; i++)
161 verdict |= (h->h_dest[i] ^ e->destmac[i]) &
162 e->destmsk[i];
163 if (FWINV2(verdict != 0, EBT_IDEST) )
164 return 1;
165 }
166 return 0;
167}
168
169/* Do some firewalling */
170unsigned int ebt_do_table (unsigned int hook, struct sk_buff **pskb,
171 const struct net_device *in, const struct net_device *out,
172 struct ebt_table *table)
173{
174 int i, nentries;
175 struct ebt_entry *point;
176 struct ebt_counter *counter_base, *cb_base;
177 struct ebt_entry_target *t;
178 int verdict, sp = 0;
179 struct ebt_chainstack *cs;
180 struct ebt_entries *chaininfo;
181 char *base;
182 struct ebt_table_info *private;
183
184 read_lock_bh(&table->lock);
185 private = table->private;
186 cb_base = COUNTER_BASE(private->counters, private->nentries,
187 smp_processor_id());
188 if (private->chainstack)
189 cs = private->chainstack[smp_processor_id()];
190 else
191 cs = NULL;
192 chaininfo = private->hook_entry[hook];
193 nentries = private->hook_entry[hook]->nentries;
194 point = (struct ebt_entry *)(private->hook_entry[hook]->data);
195 counter_base = cb_base + private->hook_entry[hook]->counter_offset;
196 /* base for chain jumps */
197 base = private->entries;
198 i = 0;
199 while (i < nentries) {
200 if (ebt_basic_match(point, eth_hdr(*pskb), in, out))
201 goto letscontinue;
202
203 if (EBT_MATCH_ITERATE(point, ebt_do_match, *pskb, in, out) != 0)
204 goto letscontinue;
205
206 /* increase counter */
207 (*(counter_base + i)).pcnt++;
208 (*(counter_base + i)).bcnt+=(**pskb).len;
209
210 /* these should only watch: not modify, nor tell us
211 what to do with the packet */
212 EBT_WATCHER_ITERATE(point, ebt_do_watcher, *pskb, hook, in,
213 out);
214
215 t = (struct ebt_entry_target *)
216 (((char *)point) + point->target_offset);
217 /* standard target */
218 if (!t->u.target->target)
219 verdict = ((struct ebt_standard_target *)t)->verdict;
220 else
221 verdict = t->u.target->target(pskb, hook,
222 in, out, t->data, t->target_size);
223 if (verdict == EBT_ACCEPT) {
224 read_unlock_bh(&table->lock);
225 return NF_ACCEPT;
226 }
227 if (verdict == EBT_DROP) {
228 read_unlock_bh(&table->lock);
229 return NF_DROP;
230 }
231 if (verdict == EBT_RETURN) {
232letsreturn:
233#ifdef CONFIG_NETFILTER_DEBUG
234 if (sp == 0) {
235 BUGPRINT("RETURN on base chain");
236 /* act like this is EBT_CONTINUE */
237 goto letscontinue;
238 }
239#endif
240 sp--;
241 /* put all the local variables right */
242 i = cs[sp].n;
243 chaininfo = cs[sp].chaininfo;
244 nentries = chaininfo->nentries;
245 point = cs[sp].e;
246 counter_base = cb_base +
247 chaininfo->counter_offset;
248 continue;
249 }
250 if (verdict == EBT_CONTINUE)
251 goto letscontinue;
252#ifdef CONFIG_NETFILTER_DEBUG
253 if (verdict < 0) {
254 BUGPRINT("bogus standard verdict\n");
255 read_unlock_bh(&table->lock);
256 return NF_DROP;
257 }
258#endif
259 /* jump to a udc */
260 cs[sp].n = i + 1;
261 cs[sp].chaininfo = chaininfo;
262 cs[sp].e = (struct ebt_entry *)
263 (((char *)point) + point->next_offset);
264 i = 0;
265 chaininfo = (struct ebt_entries *) (base + verdict);
266#ifdef CONFIG_NETFILTER_DEBUG
267 if (chaininfo->distinguisher) {
268 BUGPRINT("jump to non-chain\n");
269 read_unlock_bh(&table->lock);
270 return NF_DROP;
271 }
272#endif
273 nentries = chaininfo->nentries;
274 point = (struct ebt_entry *)chaininfo->data;
275 counter_base = cb_base + chaininfo->counter_offset;
276 sp++;
277 continue;
278letscontinue:
279 point = (struct ebt_entry *)
280 (((char *)point) + point->next_offset);
281 i++;
282 }
283
284 /* I actually like this :) */
285 if (chaininfo->policy == EBT_RETURN)
286 goto letsreturn;
287 if (chaininfo->policy == EBT_ACCEPT) {
288 read_unlock_bh(&table->lock);
289 return NF_ACCEPT;
290 }
291 read_unlock_bh(&table->lock);
292 return NF_DROP;
293}
294
295/* If it succeeds, returns element and locks mutex */
296static inline void *
297find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
298 struct semaphore *mutex)
299{
300 void *ret;
301
302 *error = down_interruptible(mutex);
303 if (*error != 0)
304 return NULL;
305
306 ret = list_named_find(head, name);
307 if (!ret) {
308 *error = -ENOENT;
309 up(mutex);
310 }
311 return ret;
312}
313
314#ifndef CONFIG_KMOD
315#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
316#else
317static void *
318find_inlist_lock(struct list_head *head, const char *name, const char *prefix,
319 int *error, struct semaphore *mutex)
320{
321 void *ret;
322
323 ret = find_inlist_lock_noload(head, name, error, mutex);
324 if (!ret) {
325 request_module("%s%s", prefix, name);
326 ret = find_inlist_lock_noload(head, name, error, mutex);
327 }
328 return ret;
329}
330#endif
331
332static inline struct ebt_table *
333find_table_lock(const char *name, int *error, struct semaphore *mutex)
334{
335 return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex);
336}
337
338static inline struct ebt_match *
339find_match_lock(const char *name, int *error, struct semaphore *mutex)
340{
341 return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex);
342}
343
344static inline struct ebt_watcher *
345find_watcher_lock(const char *name, int *error, struct semaphore *mutex)
346{
347 return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex);
348}
349
350static inline struct ebt_target *
351find_target_lock(const char *name, int *error, struct semaphore *mutex)
352{
353 return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex);
354}
355
356static inline int
357ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
358 const char *name, unsigned int hookmask, unsigned int *cnt)
359{
360 struct ebt_match *match;
361 int ret;
362
363 if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
364 ((char *)e) + e->watchers_offset)
365 return -EINVAL;
366 match = find_match_lock(m->u.name, &ret, &ebt_mutex);
367 if (!match)
368 return ret;
369 m->u.match = match;
370 if (!try_module_get(match->me)) {
371 up(&ebt_mutex);
372 return -ENOENT;
373 }
374 up(&ebt_mutex);
375 if (match->check &&
376 match->check(name, hookmask, e, m->data, m->match_size) != 0) {
377 BUGPRINT("match->check failed\n");
378 module_put(match->me);
379 return -EINVAL;
380 }
381 (*cnt)++;
382 return 0;
383}
384
385static inline int
386ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
387 const char *name, unsigned int hookmask, unsigned int *cnt)
388{
389 struct ebt_watcher *watcher;
390 int ret;
391
392 if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
393 ((char *)e) + e->target_offset)
394 return -EINVAL;
395 watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
396 if (!watcher)
397 return ret;
398 w->u.watcher = watcher;
399 if (!try_module_get(watcher->me)) {
400 up(&ebt_mutex);
401 return -ENOENT;
402 }
403 up(&ebt_mutex);
404 if (watcher->check &&
405 watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) {
406 BUGPRINT("watcher->check failed\n");
407 module_put(watcher->me);
408 return -EINVAL;
409 }
410 (*cnt)++;
411 return 0;
412}
413
414/*
415 * this one is very careful, as it is the first function
416 * to parse the userspace data
417 */
418static inline int
419ebt_check_entry_size_and_hooks(struct ebt_entry *e,
420 struct ebt_table_info *newinfo, char *base, char *limit,
421 struct ebt_entries **hook_entries, unsigned int *n, unsigned int *cnt,
422 unsigned int *totalcnt, unsigned int *udc_cnt, unsigned int valid_hooks)
423{
424 int i;
425
426 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
427 if ((valid_hooks & (1 << i)) == 0)
428 continue;
429 if ( (char *)hook_entries[i] - base ==
430 (char *)e - newinfo->entries)
431 break;
432 }
433 /* beginning of a new chain
434 if i == NF_BR_NUMHOOKS it must be a user defined chain */
435 if (i != NF_BR_NUMHOOKS || !(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
436 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) != 0) {
437 /* we make userspace set this right,
438 so there is no misunderstanding */
439 BUGPRINT("EBT_ENTRY_OR_ENTRIES shouldn't be set "
440 "in distinguisher\n");
441 return -EINVAL;
442 }
443 /* this checks if the previous chain has as many entries
444 as it said it has */
445 if (*n != *cnt) {
446 BUGPRINT("nentries does not equal the nr of entries "
447 "in the chain\n");
448 return -EINVAL;
449 }
450 /* before we look at the struct, be sure it is not too big */
451 if ((char *)hook_entries[i] + sizeof(struct ebt_entries)
452 > limit) {
453 BUGPRINT("entries_size too small\n");
454 return -EINVAL;
455 }
456 if (((struct ebt_entries *)e)->policy != EBT_DROP &&
457 ((struct ebt_entries *)e)->policy != EBT_ACCEPT) {
458 /* only RETURN from udc */
459 if (i != NF_BR_NUMHOOKS ||
460 ((struct ebt_entries *)e)->policy != EBT_RETURN) {
461 BUGPRINT("bad policy\n");
462 return -EINVAL;
463 }
464 }
465 if (i == NF_BR_NUMHOOKS) /* it's a user defined chain */
466 (*udc_cnt)++;
467 else
468 newinfo->hook_entry[i] = (struct ebt_entries *)e;
469 if (((struct ebt_entries *)e)->counter_offset != *totalcnt) {
470 BUGPRINT("counter_offset != totalcnt");
471 return -EINVAL;
472 }
473 *n = ((struct ebt_entries *)e)->nentries;
474 *cnt = 0;
475 return 0;
476 }
477 /* a plain old entry, heh */
478 if (sizeof(struct ebt_entry) > e->watchers_offset ||
479 e->watchers_offset > e->target_offset ||
480 e->target_offset >= e->next_offset) {
481 BUGPRINT("entry offsets not in right order\n");
482 return -EINVAL;
483 }
484 /* this is not checked anywhere else */
485 if (e->next_offset - e->target_offset < sizeof(struct ebt_entry_target)) {
486 BUGPRINT("target size too small\n");
487 return -EINVAL;
488 }
489
490 (*cnt)++;
491 (*totalcnt)++;
492 return 0;
493}
494
495struct ebt_cl_stack
496{
497 struct ebt_chainstack cs;
498 int from;
499 unsigned int hookmask;
500};
501
502/*
503 * we need these positions to check that the jumps to a different part of the
504 * entries is a jump to the beginning of a new chain.
505 */
506static inline int
507ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
508 struct ebt_entries **hook_entries, unsigned int *n, unsigned int valid_hooks,
509 struct ebt_cl_stack *udc)
510{
511 int i;
512
513 /* we're only interested in chain starts */
514 if (e->bitmask & EBT_ENTRY_OR_ENTRIES)
515 return 0;
516 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
517 if ((valid_hooks & (1 << i)) == 0)
518 continue;
519 if (newinfo->hook_entry[i] == (struct ebt_entries *)e)
520 break;
521 }
522 /* only care about udc */
523 if (i != NF_BR_NUMHOOKS)
524 return 0;
525
526 udc[*n].cs.chaininfo = (struct ebt_entries *)e;
527 /* these initialisations are depended on later in check_chainloops() */
528 udc[*n].cs.n = 0;
529 udc[*n].hookmask = 0;
530
531 (*n)++;
532 return 0;
533}
534
535static inline int
536ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
537{
538 if (i && (*i)-- == 0)
539 return 1;
540 if (m->u.match->destroy)
541 m->u.match->destroy(m->data, m->match_size);
542 module_put(m->u.match->me);
543
544 return 0;
545}
546
547static inline int
548ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
549{
550 if (i && (*i)-- == 0)
551 return 1;
552 if (w->u.watcher->destroy)
553 w->u.watcher->destroy(w->data, w->watcher_size);
554 module_put(w->u.watcher->me);
555
556 return 0;
557}
558
559static inline int
560ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
561{
562 struct ebt_entry_target *t;
563
564 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
565 return 0;
566 /* we're done */
567 if (cnt && (*cnt)-- == 0)
568 return 1;
569 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL);
570 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL);
571 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
572 if (t->u.target->destroy)
573 t->u.target->destroy(t->data, t->target_size);
574 module_put(t->u.target->me);
575
576 return 0;
577}
578
579static inline int
580ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
581 const char *name, unsigned int *cnt, unsigned int valid_hooks,
582 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
583{
584 struct ebt_entry_target *t;
585 struct ebt_target *target;
586 unsigned int i, j, hook = 0, hookmask = 0;
587 int ret;
588
589 /* don't mess with the struct ebt_entries */
590 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
591 return 0;
592
593 if (e->bitmask & ~EBT_F_MASK) {
594 BUGPRINT("Unknown flag for bitmask\n");
595 return -EINVAL;
596 }
597 if (e->invflags & ~EBT_INV_MASK) {
598 BUGPRINT("Unknown flag for inv bitmask\n");
599 return -EINVAL;
600 }
601 if ( (e->bitmask & EBT_NOPROTO) && (e->bitmask & EBT_802_3) ) {
602 BUGPRINT("NOPROTO & 802_3 not allowed\n");
603 return -EINVAL;
604 }
605 /* what hook do we belong to? */
606 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
607 if ((valid_hooks & (1 << i)) == 0)
608 continue;
609 if ((char *)newinfo->hook_entry[i] < (char *)e)
610 hook = i;
611 else
612 break;
613 }
614 /* (1 << NF_BR_NUMHOOKS) tells the check functions the rule is on
615 a base chain */
616 if (i < NF_BR_NUMHOOKS)
617 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
618 else {
619 for (i = 0; i < udc_cnt; i++)
620 if ((char *)(cl_s[i].cs.chaininfo) > (char *)e)
621 break;
622 if (i == 0)
623 hookmask = (1 << hook) | (1 << NF_BR_NUMHOOKS);
624 else
625 hookmask = cl_s[i - 1].hookmask;
626 }
627 i = 0;
628 ret = EBT_MATCH_ITERATE(e, ebt_check_match, e, name, hookmask, &i);
629 if (ret != 0)
630 goto cleanup_matches;
631 j = 0;
632 ret = EBT_WATCHER_ITERATE(e, ebt_check_watcher, e, name, hookmask, &j);
633 if (ret != 0)
634 goto cleanup_watchers;
635 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
636 target = find_target_lock(t->u.name, &ret, &ebt_mutex);
637 if (!target)
638 goto cleanup_watchers;
639 if (!try_module_get(target->me)) {
640 up(&ebt_mutex);
641 ret = -ENOENT;
642 goto cleanup_watchers;
643 }
644 up(&ebt_mutex);
645
646 t->u.target = target;
647 if (t->u.target == &ebt_standard_target) {
648 if (e->target_offset + sizeof(struct ebt_standard_target) >
649 e->next_offset) {
650 BUGPRINT("Standard target size too big\n");
651 ret = -EFAULT;
652 goto cleanup_watchers;
653 }
654 if (((struct ebt_standard_target *)t)->verdict <
655 -NUM_STANDARD_TARGETS) {
656 BUGPRINT("Invalid standard target\n");
657 ret = -EFAULT;
658 goto cleanup_watchers;
659 }
660 } else if ((e->target_offset + t->target_size +
661 sizeof(struct ebt_entry_target) > e->next_offset) ||
662 (t->u.target->check &&
663 t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
664 module_put(t->u.target->me);
665 ret = -EFAULT;
666 goto cleanup_watchers;
667 }
668 (*cnt)++;
669 return 0;
670cleanup_watchers:
671 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j);
672cleanup_matches:
673 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i);
674 return ret;
675}
676
677/*
678 * checks for loops and sets the hook mask for udc
679 * the hook mask for udc tells us from which base chains the udc can be
680 * accessed. This mask is a parameter to the check() functions of the extensions
681 */
682static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
683 unsigned int udc_cnt, unsigned int hooknr, char *base)
684{
685 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
686 struct ebt_entry *e = (struct ebt_entry *)chain->data;
687 struct ebt_entry_target *t;
688
689 while (pos < nentries || chain_nr != -1) {
690 /* end of udc, go back one 'recursion' step */
691 if (pos == nentries) {
692 /* put back values of the time when this chain was called */
693 e = cl_s[chain_nr].cs.e;
694 if (cl_s[chain_nr].from != -1)
695 nentries =
696 cl_s[cl_s[chain_nr].from].cs.chaininfo->nentries;
697 else
698 nentries = chain->nentries;
699 pos = cl_s[chain_nr].cs.n;
700 /* make sure we won't see a loop that isn't one */
701 cl_s[chain_nr].cs.n = 0;
702 chain_nr = cl_s[chain_nr].from;
703 if (pos == nentries)
704 continue;
705 }
706 t = (struct ebt_entry_target *)
707 (((char *)e) + e->target_offset);
708 if (strcmp(t->u.name, EBT_STANDARD_TARGET))
709 goto letscontinue;
710 if (e->target_offset + sizeof(struct ebt_standard_target) >
711 e->next_offset) {
712 BUGPRINT("Standard target size too big\n");
713 return -1;
714 }
715 verdict = ((struct ebt_standard_target *)t)->verdict;
716 if (verdict >= 0) { /* jump to another chain */
717 struct ebt_entries *hlp2 =
718 (struct ebt_entries *)(base + verdict);
719 for (i = 0; i < udc_cnt; i++)
720 if (hlp2 == cl_s[i].cs.chaininfo)
721 break;
722 /* bad destination or loop */
723 if (i == udc_cnt) {
724 BUGPRINT("bad destination\n");
725 return -1;
726 }
727 if (cl_s[i].cs.n) {
728 BUGPRINT("loop\n");
729 return -1;
730 }
731 /* this can't be 0, so the above test is correct */
732 cl_s[i].cs.n = pos + 1;
733 pos = 0;
734 cl_s[i].cs.e = ((void *)e + e->next_offset);
735 e = (struct ebt_entry *)(hlp2->data);
736 nentries = hlp2->nentries;
737 cl_s[i].from = chain_nr;
738 chain_nr = i;
739 /* this udc is accessible from the base chain for hooknr */
740 cl_s[i].hookmask |= (1 << hooknr);
741 continue;
742 }
743letscontinue:
744 e = (void *)e + e->next_offset;
745 pos++;
746 }
747 return 0;
748}
749
750/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
751static int translate_table(struct ebt_replace *repl,
752 struct ebt_table_info *newinfo)
753{
754 unsigned int i, j, k, udc_cnt;
755 int ret;
756 struct ebt_cl_stack *cl_s = NULL; /* used in the checking for chain loops */
757
758 i = 0;
759 while (i < NF_BR_NUMHOOKS && !(repl->valid_hooks & (1 << i)))
760 i++;
761 if (i == NF_BR_NUMHOOKS) {
762 BUGPRINT("No valid hooks specified\n");
763 return -EINVAL;
764 }
765 if (repl->hook_entry[i] != (struct ebt_entries *)repl->entries) {
766 BUGPRINT("Chains don't start at beginning\n");
767 return -EINVAL;
768 }
769 /* make sure chains are ordered after each other in same order
770 as their corresponding hooks */
771 for (j = i + 1; j < NF_BR_NUMHOOKS; j++) {
772 if (!(repl->valid_hooks & (1 << j)))
773 continue;
774 if ( repl->hook_entry[j] <= repl->hook_entry[i] ) {
775 BUGPRINT("Hook order must be followed\n");
776 return -EINVAL;
777 }
778 i = j;
779 }
780
781 for (i = 0; i < NF_BR_NUMHOOKS; i++)
782 newinfo->hook_entry[i] = NULL;
783
784 newinfo->entries_size = repl->entries_size;
785 newinfo->nentries = repl->nentries;
786
787 /* do some early checkings and initialize some things */
788 i = 0; /* holds the expected nr. of entries for the chain */
789 j = 0; /* holds the up to now counted entries for the chain */
790 k = 0; /* holds the total nr. of entries, should equal
791 newinfo->nentries afterwards */
792 udc_cnt = 0; /* will hold the nr. of user defined chains (udc) */
793 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
794 ebt_check_entry_size_and_hooks, newinfo, repl->entries,
795 repl->entries + repl->entries_size, repl->hook_entry, &i, &j, &k,
796 &udc_cnt, repl->valid_hooks);
797
798 if (ret != 0)
799 return ret;
800
801 if (i != j) {
802 BUGPRINT("nentries does not equal the nr of entries in the "
803 "(last) chain\n");
804 return -EINVAL;
805 }
806 if (k != newinfo->nentries) {
807 BUGPRINT("Total nentries is wrong\n");
808 return -EINVAL;
809 }
810
811 /* check if all valid hooks have a chain */
812 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
813 if (newinfo->hook_entry[i] == NULL &&
814 (repl->valid_hooks & (1 << i))) {
815 BUGPRINT("Valid hook without chain\n");
816 return -EINVAL;
817 }
818 }
819
820 /* get the location of the udc, put them in an array
821 while we're at it, allocate the chainstack */
822 if (udc_cnt) {
823 /* this will get free'd in do_replace()/ebt_register_table()
824 if an error occurs */
825 newinfo->chainstack = (struct ebt_chainstack **)
826 vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack));
827 if (!newinfo->chainstack)
828 return -ENOMEM;
829 for (i = 0; i < num_possible_cpus(); i++) {
830 newinfo->chainstack[i] =
831 vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
832 if (!newinfo->chainstack[i]) {
833 while (i)
834 vfree(newinfo->chainstack[--i]);
835 vfree(newinfo->chainstack);
836 newinfo->chainstack = NULL;
837 return -ENOMEM;
838 }
839 }
840
841 cl_s = (struct ebt_cl_stack *)
842 vmalloc(udc_cnt * sizeof(struct ebt_cl_stack));
843 if (!cl_s)
844 return -ENOMEM;
845 i = 0; /* the i'th udc */
846 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
847 ebt_get_udc_positions, newinfo, repl->hook_entry, &i,
848 repl->valid_hooks, cl_s);
849 /* sanity check */
850 if (i != udc_cnt) {
851 BUGPRINT("i != udc_cnt\n");
852 vfree(cl_s);
853 return -EFAULT;
854 }
855 }
856
857 /* Check for loops */
858 for (i = 0; i < NF_BR_NUMHOOKS; i++)
859 if (repl->valid_hooks & (1 << i))
860 if (check_chainloops(newinfo->hook_entry[i],
861 cl_s, udc_cnt, i, newinfo->entries)) {
862 if (cl_s)
863 vfree(cl_s);
864 return -EINVAL;
865 }
866
867 /* we now know the following (along with E=mc²):
868 - the nr of entries in each chain is right
869 - the size of the allocated space is right
870 - all valid hooks have a corresponding chain
871 - there are no loops
872 - wrong data can still be on the level of a single entry
873 - could be there are jumps to places that are not the
874 beginning of a chain. This can only occur in chains that
875 are not accessible from any base chains, so we don't care. */
876
877 /* used to know what we need to clean up if something goes wrong */
878 i = 0;
879 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
880 ebt_check_entry, newinfo, repl->name, &i, repl->valid_hooks,
881 cl_s, udc_cnt);
882 if (ret != 0) {
883 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
884 ebt_cleanup_entry, &i);
885 }
886 if (cl_s)
887 vfree(cl_s);
888 return ret;
889}
890
891/* called under write_lock */
892static void get_counters(struct ebt_counter *oldcounters,
893 struct ebt_counter *counters, unsigned int nentries)
894{
895 int i, cpu;
896 struct ebt_counter *counter_base;
897
898 /* counters of cpu 0 */
899 memcpy(counters, oldcounters,
900 sizeof(struct ebt_counter) * nentries);
901 /* add other counters to those of cpu 0 */
902 for (cpu = 1; cpu < num_possible_cpus(); cpu++) {
903 counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
904 for (i = 0; i < nentries; i++) {
905 counters[i].pcnt += counter_base[i].pcnt;
906 counters[i].bcnt += counter_base[i].bcnt;
907 }
908 }
909}
910
911/* replace the table */
912static int do_replace(void __user *user, unsigned int len)
913{
914 int ret, i, countersize;
915 struct ebt_table_info *newinfo;
916 struct ebt_replace tmp;
917 struct ebt_table *t;
918 struct ebt_counter *counterstmp = NULL;
919 /* used to be able to unlock earlier */
920 struct ebt_table_info *table;
921
922 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
923 return -EFAULT;
924
925 if (len != sizeof(tmp) + tmp.entries_size) {
926 BUGPRINT("Wrong len argument\n");
927 return -EINVAL;
928 }
929
930 if (tmp.entries_size == 0) {
931 BUGPRINT("Entries_size never zero\n");
932 return -EINVAL;
933 }
934 countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus();
935 newinfo = (struct ebt_table_info *)
936 vmalloc(sizeof(struct ebt_table_info) + countersize);
937 if (!newinfo)
938 return -ENOMEM;
939
940 if (countersize)
941 memset(newinfo->counters, 0, countersize);
942
943 newinfo->entries = (char *)vmalloc(tmp.entries_size);
944 if (!newinfo->entries) {
945 ret = -ENOMEM;
946 goto free_newinfo;
947 }
948 if (copy_from_user(
949 newinfo->entries, tmp.entries, tmp.entries_size) != 0) {
950 BUGPRINT("Couldn't copy entries from userspace\n");
951 ret = -EFAULT;
952 goto free_entries;
953 }
954
955 /* the user wants counters back
956 the check on the size is done later, when we have the lock */
957 if (tmp.num_counters) {
958 counterstmp = (struct ebt_counter *)
959 vmalloc(tmp.num_counters * sizeof(struct ebt_counter));
960 if (!counterstmp) {
961 ret = -ENOMEM;
962 goto free_entries;
963 }
964 }
965 else
966 counterstmp = NULL;
967
968 /* this can get initialized by translate_table() */
969 newinfo->chainstack = NULL;
970 ret = translate_table(&tmp, newinfo);
971
972 if (ret != 0)
973 goto free_counterstmp;
974
975 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
976 if (!t) {
977 ret = -ENOENT;
978 goto free_iterate;
979 }
980
981 /* the table doesn't like it */
982 if (t->check && (ret = t->check(newinfo, tmp.valid_hooks)))
983 goto free_unlock;
984
985 if (tmp.num_counters && tmp.num_counters != t->private->nentries) {
986 BUGPRINT("Wrong nr. of counters requested\n");
987 ret = -EINVAL;
988 goto free_unlock;
989 }
990
991 /* we have the mutex lock, so no danger in reading this pointer */
992 table = t->private;
993 /* make sure the table can only be rmmod'ed if it contains no rules */
994 if (!table->nentries && newinfo->nentries && !try_module_get(t->me)) {
995 ret = -ENOENT;
996 goto free_unlock;
997 } else if (table->nentries && !newinfo->nentries)
998 module_put(t->me);
999 /* we need an atomic snapshot of the counters */
1000 write_lock_bh(&t->lock);
1001 if (tmp.num_counters)
1002 get_counters(t->private->counters, counterstmp,
1003 t->private->nentries);
1004
1005 t->private = newinfo;
1006 write_unlock_bh(&t->lock);
1007 up(&ebt_mutex);
1008 /* so, a user can change the chains while having messed up her counter
1009 allocation. Only reason why this is done is because this way the lock
1010 is held only once, while this doesn't bring the kernel into a
1011 dangerous state. */
1012 if (tmp.num_counters &&
1013 copy_to_user(tmp.counters, counterstmp,
1014 tmp.num_counters * sizeof(struct ebt_counter))) {
1015 BUGPRINT("Couldn't copy counters to userspace\n");
1016 ret = -EFAULT;
1017 }
1018 else
1019 ret = 0;
1020
1021 /* decrease module count and free resources */
1022 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1023 ebt_cleanup_entry, NULL);
1024
1025 vfree(table->entries);
1026 if (table->chainstack) {
1027 for (i = 0; i < num_possible_cpus(); i++)
1028 vfree(table->chainstack[i]);
1029 vfree(table->chainstack);
1030 }
1031 vfree(table);
1032
1033 if (counterstmp)
1034 vfree(counterstmp);
1035 return ret;
1036
1037free_unlock:
1038 up(&ebt_mutex);
1039free_iterate:
1040 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1041 ebt_cleanup_entry, NULL);
1042free_counterstmp:
1043 if (counterstmp)
1044 vfree(counterstmp);
1045 /* can be initialized in translate_table() */
1046 if (newinfo->chainstack) {
1047 for (i = 0; i < num_possible_cpus(); i++)
1048 vfree(newinfo->chainstack[i]);
1049 vfree(newinfo->chainstack);
1050 }
1051free_entries:
1052 if (newinfo->entries)
1053 vfree(newinfo->entries);
1054free_newinfo:
1055 if (newinfo)
1056 vfree(newinfo);
1057 return ret;
1058}
1059
1060int ebt_register_target(struct ebt_target *target)
1061{
1062 int ret;
1063
1064 ret = down_interruptible(&ebt_mutex);
1065 if (ret != 0)
1066 return ret;
1067 if (!list_named_insert(&ebt_targets, target)) {
1068 up(&ebt_mutex);
1069 return -EEXIST;
1070 }
1071 up(&ebt_mutex);
1072
1073 return 0;
1074}
1075
1076void ebt_unregister_target(struct ebt_target *target)
1077{
1078 down(&ebt_mutex);
1079 LIST_DELETE(&ebt_targets, target);
1080 up(&ebt_mutex);
1081}
1082
1083int ebt_register_match(struct ebt_match *match)
1084{
1085 int ret;
1086
1087 ret = down_interruptible(&ebt_mutex);
1088 if (ret != 0)
1089 return ret;
1090 if (!list_named_insert(&ebt_matches, match)) {
1091 up(&ebt_mutex);
1092 return -EEXIST;
1093 }
1094 up(&ebt_mutex);
1095
1096 return 0;
1097}
1098
1099void ebt_unregister_match(struct ebt_match *match)
1100{
1101 down(&ebt_mutex);
1102 LIST_DELETE(&ebt_matches, match);
1103 up(&ebt_mutex);
1104}
1105
1106int ebt_register_watcher(struct ebt_watcher *watcher)
1107{
1108 int ret;
1109
1110 ret = down_interruptible(&ebt_mutex);
1111 if (ret != 0)
1112 return ret;
1113 if (!list_named_insert(&ebt_watchers, watcher)) {
1114 up(&ebt_mutex);
1115 return -EEXIST;
1116 }
1117 up(&ebt_mutex);
1118
1119 return 0;
1120}
1121
1122void ebt_unregister_watcher(struct ebt_watcher *watcher)
1123{
1124 down(&ebt_mutex);
1125 LIST_DELETE(&ebt_watchers, watcher);
1126 up(&ebt_mutex);
1127}
1128
1129int ebt_register_table(struct ebt_table *table)
1130{
1131 struct ebt_table_info *newinfo;
1132 int ret, i, countersize;
1133
1134 if (!table || !table->table ||!table->table->entries ||
1135 table->table->entries_size == 0 ||
1136 table->table->counters || table->private) {
1137 BUGPRINT("Bad table data for ebt_register_table!!!\n");
1138 return -EINVAL;
1139 }
1140
1141 countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus();
1142 newinfo = (struct ebt_table_info *)
1143 vmalloc(sizeof(struct ebt_table_info) + countersize);
1144 ret = -ENOMEM;
1145 if (!newinfo)
1146 return -ENOMEM;
1147
1148 newinfo->entries = (char *)vmalloc(table->table->entries_size);
1149 if (!(newinfo->entries))
1150 goto free_newinfo;
1151
1152 memcpy(newinfo->entries, table->table->entries,
1153 table->table->entries_size);
1154
1155 if (countersize)
1156 memset(newinfo->counters, 0, countersize);
1157
1158 /* fill in newinfo and parse the entries */
1159 newinfo->chainstack = NULL;
1160 ret = translate_table(table->table, newinfo);
1161 if (ret != 0) {
1162 BUGPRINT("Translate_table failed\n");
1163 goto free_chainstack;
1164 }
1165
1166 if (table->check && table->check(newinfo, table->valid_hooks)) {
1167 BUGPRINT("The table doesn't like its own initial data, lol\n");
1168 return -EINVAL;
1169 }
1170
1171 table->private = newinfo;
1172 rwlock_init(&table->lock);
1173 ret = down_interruptible(&ebt_mutex);
1174 if (ret != 0)
1175 goto free_chainstack;
1176
1177 if (list_named_find(&ebt_tables, table->name)) {
1178 ret = -EEXIST;
1179 BUGPRINT("Table name already exists\n");
1180 goto free_unlock;
1181 }
1182
1183 /* Hold a reference count if the chains aren't empty */
1184 if (newinfo->nentries && !try_module_get(table->me)) {
1185 ret = -ENOENT;
1186 goto free_unlock;
1187 }
1188 list_prepend(&ebt_tables, table);
1189 up(&ebt_mutex);
1190 return 0;
1191free_unlock:
1192 up(&ebt_mutex);
1193free_chainstack:
1194 if (newinfo->chainstack) {
1195 for (i = 0; i < num_possible_cpus(); i++)
1196 vfree(newinfo->chainstack[i]);
1197 vfree(newinfo->chainstack);
1198 }
1199 vfree(newinfo->entries);
1200free_newinfo:
1201 vfree(newinfo);
1202 return ret;
1203}
1204
1205void ebt_unregister_table(struct ebt_table *table)
1206{
1207 int i;
1208
1209 if (!table) {
1210 BUGPRINT("Request to unregister NULL table!!!\n");
1211 return;
1212 }
1213 down(&ebt_mutex);
1214 LIST_DELETE(&ebt_tables, table);
1215 up(&ebt_mutex);
1216 if (table->private->entries)
1217 vfree(table->private->entries);
1218 if (table->private->chainstack) {
1219 for (i = 0; i < num_possible_cpus(); i++)
1220 vfree(table->private->chainstack[i]);
1221 vfree(table->private->chainstack);
1222 }
1223 vfree(table->private);
1224}
1225
1226/* userspace just supplied us with counters */
1227static int update_counters(void __user *user, unsigned int len)
1228{
1229 int i, ret;
1230 struct ebt_counter *tmp;
1231 struct ebt_replace hlp;
1232 struct ebt_table *t;
1233
1234 if (copy_from_user(&hlp, user, sizeof(hlp)))
1235 return -EFAULT;
1236
1237 if (len != sizeof(hlp) + hlp.num_counters * sizeof(struct ebt_counter))
1238 return -EINVAL;
1239 if (hlp.num_counters == 0)
1240 return -EINVAL;
1241
1242 if ( !(tmp = (struct ebt_counter *)
1243 vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){
1244 MEMPRINT("Update_counters && nomemory\n");
1245 return -ENOMEM;
1246 }
1247
1248 t = find_table_lock(hlp.name, &ret, &ebt_mutex);
1249 if (!t)
1250 goto free_tmp;
1251
1252 if (hlp.num_counters != t->private->nentries) {
1253 BUGPRINT("Wrong nr of counters\n");
1254 ret = -EINVAL;
1255 goto unlock_mutex;
1256 }
1257
1258 if ( copy_from_user(tmp, hlp.counters,
1259 hlp.num_counters * sizeof(struct ebt_counter)) ) {
1260 BUGPRINT("Updata_counters && !cfu\n");
1261 ret = -EFAULT;
1262 goto unlock_mutex;
1263 }
1264
1265 /* we want an atomic add of the counters */
1266 write_lock_bh(&t->lock);
1267
1268 /* we add to the counters of the first cpu */
1269 for (i = 0; i < hlp.num_counters; i++) {
1270 t->private->counters[i].pcnt += tmp[i].pcnt;
1271 t->private->counters[i].bcnt += tmp[i].bcnt;
1272 }
1273
1274 write_unlock_bh(&t->lock);
1275 ret = 0;
1276unlock_mutex:
1277 up(&ebt_mutex);
1278free_tmp:
1279 vfree(tmp);
1280 return ret;
1281}
1282
1283static inline int ebt_make_matchname(struct ebt_entry_match *m,
1284 char *base, char *ubase)
1285{
1286 char *hlp = ubase - base + (char *)m;
1287 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
1288 return -EFAULT;
1289 return 0;
1290}
1291
1292static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1293 char *base, char *ubase)
1294{
1295 char *hlp = ubase - base + (char *)w;
1296 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
1297 return -EFAULT;
1298 return 0;
1299}
1300
1301static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase)
1302{
1303 int ret;
1304 char *hlp;
1305 struct ebt_entry_target *t;
1306
1307 if ((e->bitmask & EBT_ENTRY_OR_ENTRIES) == 0)
1308 return 0;
1309
1310 hlp = ubase - base + (char *)e + e->target_offset;
1311 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
1312
1313 ret = EBT_MATCH_ITERATE(e, ebt_make_matchname, base, ubase);
1314 if (ret != 0)
1315 return ret;
1316 ret = EBT_WATCHER_ITERATE(e, ebt_make_watchername, base, ubase);
1317 if (ret != 0)
1318 return ret;
1319 if (copy_to_user(hlp, t->u.target->name, EBT_FUNCTION_MAXNAMELEN))
1320 return -EFAULT;
1321 return 0;
1322}
1323
1324/* called with ebt_mutex down */
1325static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1326 int *len, int cmd)
1327{
1328 struct ebt_replace tmp;
1329 struct ebt_counter *counterstmp, *oldcounters;
1330 unsigned int entries_size, nentries;
1331 char *entries;
1332
1333 if (cmd == EBT_SO_GET_ENTRIES) {
1334 entries_size = t->private->entries_size;
1335 nentries = t->private->nentries;
1336 entries = t->private->entries;
1337 oldcounters = t->private->counters;
1338 } else {
1339 entries_size = t->table->entries_size;
1340 nentries = t->table->nentries;
1341 entries = t->table->entries;
1342 oldcounters = t->table->counters;
1343 }
1344
1345 if (copy_from_user(&tmp, user, sizeof(tmp))) {
1346 BUGPRINT("Cfu didn't work\n");
1347 return -EFAULT;
1348 }
1349
1350 if (*len != sizeof(struct ebt_replace) + entries_size +
1351 (tmp.num_counters? nentries * sizeof(struct ebt_counter): 0)) {
1352 BUGPRINT("Wrong size\n");
1353 return -EINVAL;
1354 }
1355
1356 if (tmp.nentries != nentries) {
1357 BUGPRINT("Nentries wrong\n");
1358 return -EINVAL;
1359 }
1360
1361 if (tmp.entries_size != entries_size) {
1362 BUGPRINT("Wrong size\n");
1363 return -EINVAL;
1364 }
1365
1366 /* userspace might not need the counters */
1367 if (tmp.num_counters) {
1368 if (tmp.num_counters != nentries) {
1369 BUGPRINT("Num_counters wrong\n");
1370 return -EINVAL;
1371 }
1372 counterstmp = (struct ebt_counter *)
1373 vmalloc(nentries * sizeof(struct ebt_counter));
1374 if (!counterstmp) {
1375 MEMPRINT("Couldn't copy counters, out of memory\n");
1376 return -ENOMEM;
1377 }
1378 write_lock_bh(&t->lock);
1379 get_counters(oldcounters, counterstmp, nentries);
1380 write_unlock_bh(&t->lock);
1381
1382 if (copy_to_user(tmp.counters, counterstmp,
1383 nentries * sizeof(struct ebt_counter))) {
1384 BUGPRINT("Couldn't copy counters to userspace\n");
1385 vfree(counterstmp);
1386 return -EFAULT;
1387 }
1388 vfree(counterstmp);
1389 }
1390
1391 if (copy_to_user(tmp.entries, entries, entries_size)) {
1392 BUGPRINT("Couldn't copy entries to userspace\n");
1393 return -EFAULT;
1394 }
1395 /* set the match/watcher/target names right */
1396 return EBT_ENTRY_ITERATE(entries, entries_size,
1397 ebt_make_names, entries, tmp.entries);
1398}
1399
1400static int do_ebt_set_ctl(struct sock *sk,
1401 int cmd, void __user *user, unsigned int len)
1402{
1403 int ret;
1404
1405 switch(cmd) {
1406 case EBT_SO_SET_ENTRIES:
1407 ret = do_replace(user, len);
1408 break;
1409 case EBT_SO_SET_COUNTERS:
1410 ret = update_counters(user, len);
1411 break;
1412 default:
1413 ret = -EINVAL;
1414 }
1415 return ret;
1416}
1417
1418static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
1419{
1420 int ret;
1421 struct ebt_replace tmp;
1422 struct ebt_table *t;
1423
1424 if (copy_from_user(&tmp, user, sizeof(tmp)))
1425 return -EFAULT;
1426
1427 t = find_table_lock(tmp.name, &ret, &ebt_mutex);
1428 if (!t)
1429 return ret;
1430
1431 switch(cmd) {
1432 case EBT_SO_GET_INFO:
1433 case EBT_SO_GET_INIT_INFO:
1434 if (*len != sizeof(struct ebt_replace)){
1435 ret = -EINVAL;
1436 up(&ebt_mutex);
1437 break;
1438 }
1439 if (cmd == EBT_SO_GET_INFO) {
1440 tmp.nentries = t->private->nentries;
1441 tmp.entries_size = t->private->entries_size;
1442 tmp.valid_hooks = t->valid_hooks;
1443 } else {
1444 tmp.nentries = t->table->nentries;
1445 tmp.entries_size = t->table->entries_size;
1446 tmp.valid_hooks = t->table->valid_hooks;
1447 }
1448 up(&ebt_mutex);
1449 if (copy_to_user(user, &tmp, *len) != 0){
1450 BUGPRINT("c2u Didn't work\n");
1451 ret = -EFAULT;
1452 break;
1453 }
1454 ret = 0;
1455 break;
1456
1457 case EBT_SO_GET_ENTRIES:
1458 case EBT_SO_GET_INIT_ENTRIES:
1459 ret = copy_everything_to_user(t, user, len, cmd);
1460 up(&ebt_mutex);
1461 break;
1462
1463 default:
1464 up(&ebt_mutex);
1465 ret = -EINVAL;
1466 }
1467
1468 return ret;
1469}
1470
1471static struct nf_sockopt_ops ebt_sockopts =
1472{ { NULL, NULL }, PF_INET, EBT_BASE_CTL, EBT_SO_SET_MAX + 1, do_ebt_set_ctl,
1473 EBT_BASE_CTL, EBT_SO_GET_MAX + 1, do_ebt_get_ctl, 0, NULL
1474};
1475
1476static int __init init(void)
1477{
1478 int ret;
1479
1480 down(&ebt_mutex);
1481 list_named_insert(&ebt_targets, &ebt_standard_target);
1482 up(&ebt_mutex);
1483 if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0)
1484 return ret;
1485
1486 printk(KERN_NOTICE "Ebtables v2.0 registered\n");
1487 return 0;
1488}
1489
1490static void __exit fini(void)
1491{
1492 nf_unregister_sockopt(&ebt_sockopts);
1493 printk(KERN_NOTICE "Ebtables v2.0 unregistered\n");
1494}
1495
1496EXPORT_SYMBOL(ebt_register_table);
1497EXPORT_SYMBOL(ebt_unregister_table);
1498EXPORT_SYMBOL(ebt_register_match);
1499EXPORT_SYMBOL(ebt_unregister_match);
1500EXPORT_SYMBOL(ebt_register_watcher);
1501EXPORT_SYMBOL(ebt_unregister_watcher);
1502EXPORT_SYMBOL(ebt_register_target);
1503EXPORT_SYMBOL(ebt_unregister_target);
1504EXPORT_SYMBOL(ebt_do_table);
1505module_init(init);
1506module_exit(fini);
1507MODULE_LICENSE("GPL");