aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_fdb.c26
-rw-r--r--net/bridge/br_if.c2
-rw-r--r--net/bridge/br_multicast.c39
-rw-r--r--net/bridge/br_netlink.c1
-rw-r--r--net/bridge/br_private.h5
-rw-r--r--net/bridge/br_vlan.c24
-rw-r--r--net/bridge/netfilter/Kconfig25
-rw-r--r--net/bridge/netfilter/Makefile5
-rw-r--r--net/bridge/netfilter/ebt_log.c47
-rw-r--r--net/bridge/netfilter/ebt_ulog.c393
-rw-r--r--net/bridge/netfilter/ebtables.c10
-rw-r--r--net/bridge/netfilter/nf_log_bridge.c96
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c67
13 files changed, 261 insertions, 479 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index b524c36c1273..6f6c95cfe8f2 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -93,7 +93,7 @@ static void fdb_rcu_free(struct rcu_head *head)
93static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) 93static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr)
94{ 94{
95 int err; 95 int err;
96 struct net_bridge_port *p, *tmp; 96 struct net_bridge_port *p;
97 97
98 ASSERT_RTNL(); 98 ASSERT_RTNL();
99 99
@@ -107,11 +107,9 @@ static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr)
107 107
108 return; 108 return;
109undo: 109undo:
110 list_for_each_entry(tmp, &br->port_list, list) { 110 list_for_each_entry_continue_reverse(p, &br->port_list, list) {
111 if (tmp == p) 111 if (!br_promisc_port(p))
112 break; 112 dev_uc_del(p->dev, addr);
113 if (!br_promisc_port(tmp))
114 dev_uc_del(tmp->dev, addr);
115 } 113 }
116} 114}
117 115
@@ -631,7 +629,7 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
631 if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) 629 if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
632 goto nla_put_failure; 630 goto nla_put_failure;
633 631
634 if (nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id)) 632 if (fdb->vlan_id && nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id))
635 goto nla_put_failure; 633 goto nla_put_failure;
636 634
637 return nlmsg_end(skb, nlh); 635 return nlmsg_end(skb, nlh);
@@ -678,6 +676,7 @@ errout:
678int br_fdb_dump(struct sk_buff *skb, 676int br_fdb_dump(struct sk_buff *skb,
679 struct netlink_callback *cb, 677 struct netlink_callback *cb,
680 struct net_device *dev, 678 struct net_device *dev,
679 struct net_device *filter_dev,
681 int idx) 680 int idx)
682{ 681{
683 struct net_bridge *br = netdev_priv(dev); 682 struct net_bridge *br = netdev_priv(dev);
@@ -693,6 +692,19 @@ int br_fdb_dump(struct sk_buff *skb,
693 if (idx < cb->args[0]) 692 if (idx < cb->args[0])
694 goto skip; 693 goto skip;
695 694
695 if (filter_dev &&
696 (!f->dst || f->dst->dev != filter_dev)) {
697 if (filter_dev != dev)
698 goto skip;
699 /* !f->dst is a speacial case for bridge
700 * It means the MAC belongs to the bridge
701 * Therefore need a little more filtering
702 * we only want to dump the !f->dst case
703 */
704 if (f->dst)
705 goto skip;
706 }
707
696 if (fdb_fill_info(skb, br, f, 708 if (fdb_fill_info(skb, br, f,
697 NETLINK_CB(cb->skb).portid, 709 NETLINK_CB(cb->skb).portid,
698 cb->nlh->nlmsg_seq, 710 cb->nlh->nlmsg_seq,
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 3eca3fdf8fe1..078d336a1f37 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -344,7 +344,7 @@ int br_add_bridge(struct net *net, const char *name)
344 struct net_device *dev; 344 struct net_device *dev;
345 int res; 345 int res;
346 346
347 dev = alloc_netdev(sizeof(struct net_bridge), name, 347 dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN,
348 br_dev_setup); 348 br_dev_setup);
349 349
350 if (!dev) 350 if (!dev)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index abfa0b65a111..7751c92c8c57 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1174,7 +1174,7 @@ static void br_multicast_add_router(struct net_bridge *br,
1174 } 1174 }
1175 1175
1176 if (slot) 1176 if (slot)
1177 hlist_add_after_rcu(slot, &port->rlist); 1177 hlist_add_behind_rcu(&port->rlist, slot);
1178 else 1178 else
1179 hlist_add_head_rcu(&port->rlist, &br->router_list); 1179 hlist_add_head_rcu(&port->rlist, &br->router_list);
1180} 1180}
@@ -2216,6 +2216,43 @@ unlock:
2216EXPORT_SYMBOL_GPL(br_multicast_list_adjacent); 2216EXPORT_SYMBOL_GPL(br_multicast_list_adjacent);
2217 2217
2218/** 2218/**
2219 * br_multicast_has_querier_anywhere - Checks for a querier on a bridge
2220 * @dev: The bridge port providing the bridge on which to check for a querier
2221 * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6
2222 *
2223 * Checks whether the given interface has a bridge on top and if so returns
2224 * true if a valid querier exists anywhere on the bridged link layer.
2225 * Otherwise returns false.
2226 */
2227bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto)
2228{
2229 struct net_bridge *br;
2230 struct net_bridge_port *port;
2231 struct ethhdr eth;
2232 bool ret = false;
2233
2234 rcu_read_lock();
2235 if (!br_port_exists(dev))
2236 goto unlock;
2237
2238 port = br_port_get_rcu(dev);
2239 if (!port || !port->br)
2240 goto unlock;
2241
2242 br = port->br;
2243
2244 memset(&eth, 0, sizeof(eth));
2245 eth.h_proto = htons(proto);
2246
2247 ret = br_multicast_querier_exists(br, &eth);
2248
2249unlock:
2250 rcu_read_unlock();
2251 return ret;
2252}
2253EXPORT_SYMBOL_GPL(br_multicast_has_querier_anywhere);
2254
2255/**
2219 * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port 2256 * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port
2220 * @dev: The bridge port adjacent to which to check for a querier 2257 * @dev: The bridge port adjacent to which to check for a querier
2221 * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 2258 * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 26edb518b839..cb5fcf62f663 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -208,7 +208,6 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
208 int err = 0; 208 int err = 0;
209 struct net_bridge_port *port = br_port_get_rtnl(dev); 209 struct net_bridge_port *port = br_port_get_rtnl(dev);
210 210
211 /* not a bridge port and */
212 if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) 211 if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN))
213 goto out; 212 goto out;
214 213
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 23caf5b0309e..b6c04cbcfdc5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -309,6 +309,9 @@ struct br_input_skb_cb {
309 int igmp; 309 int igmp;
310 int mrouters_only; 310 int mrouters_only;
311#endif 311#endif
312#ifdef CONFIG_BRIDGE_VLAN_FILTERING
313 bool vlan_filtered;
314#endif
312}; 315};
313 316
314#define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) 317#define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb)
@@ -399,7 +402,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
399int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, 402int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev,
400 const unsigned char *addr, u16 nlh_flags); 403 const unsigned char *addr, u16 nlh_flags);
401int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, 404int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
402 struct net_device *dev, int idx); 405 struct net_device *dev, struct net_device *fdev, int idx);
403int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); 406int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
404void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); 407void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
405 408
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 2b2774fe0703..3ba57fcdcd13 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -27,9 +27,13 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags)
27{ 27{
28 if (flags & BRIDGE_VLAN_INFO_PVID) 28 if (flags & BRIDGE_VLAN_INFO_PVID)
29 __vlan_add_pvid(v, vid); 29 __vlan_add_pvid(v, vid);
30 else
31 __vlan_delete_pvid(v, vid);
30 32
31 if (flags & BRIDGE_VLAN_INFO_UNTAGGED) 33 if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
32 set_bit(vid, v->untagged_bitmap); 34 set_bit(vid, v->untagged_bitmap);
35 else
36 clear_bit(vid, v->untagged_bitmap);
33} 37}
34 38
35static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) 39static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
@@ -55,10 +59,8 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
55 59
56 if (p) { 60 if (p) {
57 /* Add VLAN to the device filter if it is supported. 61 /* Add VLAN to the device filter if it is supported.
58 * Stricly speaking, this is not necessary now, since 62 * This ensures tagged traffic enters the bridge when
59 * devices are made promiscuous by the bridge, but if 63 * promiscuous mode is disabled by br_manage_promisc().
60 * that ever changes this code will allow tagged
61 * traffic to enter the bridge.
62 */ 64 */
63 err = vlan_vid_add(dev, br->vlan_proto, vid); 65 err = vlan_vid_add(dev, br->vlan_proto, vid);
64 if (err) 66 if (err)
@@ -127,7 +129,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
127{ 129{
128 u16 vid; 130 u16 vid;
129 131
130 if (!br->vlan_enabled) 132 /* If this packet was not filtered at input, let it pass */
133 if (!BR_INPUT_SKB_CB(skb)->vlan_filtered)
131 goto out; 134 goto out;
132 135
133 /* Vlan filter table must be configured at this point. The 136 /* Vlan filter table must be configured at this point. The
@@ -166,8 +169,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
166 /* If VLAN filtering is disabled on the bridge, all packets are 169 /* If VLAN filtering is disabled on the bridge, all packets are
167 * permitted. 170 * permitted.
168 */ 171 */
169 if (!br->vlan_enabled) 172 if (!br->vlan_enabled) {
173 BR_INPUT_SKB_CB(skb)->vlan_filtered = false;
170 return true; 174 return true;
175 }
171 176
172 /* If there are no vlan in the permitted list, all packets are 177 /* If there are no vlan in the permitted list, all packets are
173 * rejected. 178 * rejected.
@@ -175,6 +180,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
175 if (!v) 180 if (!v)
176 goto drop; 181 goto drop;
177 182
183 BR_INPUT_SKB_CB(skb)->vlan_filtered = true;
178 proto = br->vlan_proto; 184 proto = br->vlan_proto;
179 185
180 /* If vlan tx offload is disabled on bridge device and frame was 186 /* If vlan tx offload is disabled on bridge device and frame was
@@ -183,7 +189,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v,
183 */ 189 */
184 if (unlikely(!vlan_tx_tag_present(skb) && 190 if (unlikely(!vlan_tx_tag_present(skb) &&
185 skb->protocol == proto)) { 191 skb->protocol == proto)) {
186 skb = vlan_untag(skb); 192 skb = skb_vlan_untag(skb);
187 if (unlikely(!skb)) 193 if (unlikely(!skb))
188 return false; 194 return false;
189 } 195 }
@@ -253,7 +259,8 @@ bool br_allowed_egress(struct net_bridge *br,
253{ 259{
254 u16 vid; 260 u16 vid;
255 261
256 if (!br->vlan_enabled) 262 /* If this packet was not filtered at input, let it pass */
263 if (!BR_INPUT_SKB_CB(skb)->vlan_filtered)
257 return true; 264 return true;
258 265
259 if (!v) 266 if (!v)
@@ -272,6 +279,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
272 struct net_bridge *br = p->br; 279 struct net_bridge *br = p->br;
273 struct net_port_vlans *v; 280 struct net_port_vlans *v;
274 281
282 /* If filtering was disabled at input, let it pass. */
275 if (!br->vlan_enabled) 283 if (!br->vlan_enabled)
276 return true; 284 return true;
277 285
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index 629dc77874a9..9cebf47ac840 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -14,6 +14,15 @@ config NFT_BRIDGE_META
14 help 14 help
15 Add support for bridge dedicated meta key. 15 Add support for bridge dedicated meta key.
16 16
17config NFT_BRIDGE_REJECT
18 tristate "Netfilter nf_tables bridge reject support"
19 depends on NFT_REJECT && NFT_REJECT_IPV4 && NFT_REJECT_IPV6
20 help
21 Add support to reject packets.
22
23config NF_LOG_BRIDGE
24 tristate "Bridge packet logging"
25
17endif # NF_TABLES_BRIDGE 26endif # NF_TABLES_BRIDGE
18 27
19menuconfig BRIDGE_NF_EBTABLES 28menuconfig BRIDGE_NF_EBTABLES
@@ -202,22 +211,6 @@ config BRIDGE_EBT_LOG
202 211
203 To compile it as a module, choose M here. If unsure, say N. 212 To compile it as a module, choose M here. If unsure, say N.
204 213
205config BRIDGE_EBT_ULOG
206 tristate "ebt: ulog support (OBSOLETE)"
207 help
208 This option enables the old bridge-specific "ebt_ulog" implementation
209 which has been obsoleted by the new "nfnetlink_log" code (see
210 CONFIG_NETFILTER_NETLINK_LOG).
211
212 This option adds the ulog watcher, that you can use in any rule
213 in any ebtables table. The packet is passed to a userspace
214 logging daemon using netlink multicast sockets. This differs
215 from the log watcher in the sense that the complete packet is
216 sent to userspace instead of a descriptive text and that
217 netlink multicast sockets are used instead of the syslog.
218
219 To compile it as a module, choose M here. If unsure, say N.
220
221config BRIDGE_EBT_NFLOG 214config BRIDGE_EBT_NFLOG
222 tristate "ebt: nflog support" 215 tristate "ebt: nflog support"
223 help 216 help
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile
index 6f2f3943d66f..be4d0cea78ce 100644
--- a/net/bridge/netfilter/Makefile
+++ b/net/bridge/netfilter/Makefile
@@ -4,6 +4,10 @@
4 4
5obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o 5obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o
6obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o 6obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o
7obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o
8
9# packet logging
10obj-$(CONFIG_NF_LOG_BRIDGE) += nf_log_bridge.o
7 11
8obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o 12obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o
9 13
@@ -33,5 +37,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o
33 37
34# watchers 38# watchers
35obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o 39obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o
36obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o
37obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o 40obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 5322a36867a3..17f2e4bc2a29 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -186,6 +186,10 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
186 li.u.log.level = info->loglevel; 186 li.u.log.level = info->loglevel;
187 li.u.log.logflags = info->bitmask; 187 li.u.log.logflags = info->bitmask;
188 188
189 /* Remember that we have to use ebt_log_packet() not to break backward
190 * compatibility. We cannot use the default bridge packet logger via
191 * nf_log_packet() with NFT_LOG_TYPE_LOG here. --Pablo
192 */
189 if (info->bitmask & EBT_LOG_NFLOG) 193 if (info->bitmask & EBT_LOG_NFLOG)
190 nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, 194 nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb,
191 par->in, par->out, &li, "%s", info->prefix); 195 par->in, par->out, &li, "%s", info->prefix);
@@ -205,54 +209,13 @@ static struct xt_target ebt_log_tg_reg __read_mostly = {
205 .me = THIS_MODULE, 209 .me = THIS_MODULE,
206}; 210};
207 211
208static struct nf_logger ebt_log_logger __read_mostly = {
209 .name = "ebt_log",
210 .logfn = &ebt_log_packet,
211 .me = THIS_MODULE,
212};
213
214static int __net_init ebt_log_net_init(struct net *net)
215{
216 nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger);
217 return 0;
218}
219
220static void __net_exit ebt_log_net_fini(struct net *net)
221{
222 nf_log_unset(net, &ebt_log_logger);
223}
224
225static struct pernet_operations ebt_log_net_ops = {
226 .init = ebt_log_net_init,
227 .exit = ebt_log_net_fini,
228};
229
230static int __init ebt_log_init(void) 212static int __init ebt_log_init(void)
231{ 213{
232 int ret; 214 return xt_register_target(&ebt_log_tg_reg);
233
234 ret = register_pernet_subsys(&ebt_log_net_ops);
235 if (ret < 0)
236 goto err_pernet;
237
238 ret = xt_register_target(&ebt_log_tg_reg);
239 if (ret < 0)
240 goto err_target;
241
242 nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger);
243
244 return ret;
245
246err_target:
247 unregister_pernet_subsys(&ebt_log_net_ops);
248err_pernet:
249 return ret;
250} 215}
251 216
252static void __exit ebt_log_fini(void) 217static void __exit ebt_log_fini(void)
253{ 218{
254 unregister_pernet_subsys(&ebt_log_net_ops);
255 nf_log_unregister(&ebt_log_logger);
256 xt_unregister_target(&ebt_log_tg_reg); 219 xt_unregister_target(&ebt_log_tg_reg);
257} 220}
258 221
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
deleted file mode 100644
index 7c470c371e14..000000000000
--- a/net/bridge/netfilter/ebt_ulog.c
+++ /dev/null
@@ -1,393 +0,0 @@
1/*
2 * netfilter module for userspace bridged Ethernet frames logging daemons
3 *
4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Harald Welte <laforge@netfilter.org>
7 *
8 * November, 2004
9 *
10 * Based on ipt_ULOG.c, which is
11 * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
12 *
13 * This module accepts two parameters:
14 *
15 * nlbufsiz:
16 * The parameter specifies how big the buffer for each netlink multicast
17 * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will
18 * get accumulated in the kernel until they are sent to userspace. It is
19 * NOT possible to allocate more than 128kB, and it is strongly discouraged,
20 * because atomically allocating 128kB inside the network rx softirq is not
21 * reliable. Please also keep in mind that this buffer size is allocated for
22 * each nlgroup you are using, so the total kernel memory usage increases
23 * by that factor.
24 *
25 * flushtimeout:
26 * Specify, after how many hundredths of a second the queue should be
27 * flushed even if it is not full yet.
28 *
29 */
30#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
31#include <linux/module.h>
32#include <linux/slab.h>
33#include <linux/spinlock.h>
34#include <linux/socket.h>
35#include <linux/skbuff.h>
36#include <linux/kernel.h>
37#include <linux/timer.h>
38#include <net/netlink.h>
39#include <linux/netdevice.h>
40#include <linux/netfilter/x_tables.h>
41#include <linux/netfilter_bridge/ebtables.h>
42#include <linux/netfilter_bridge/ebt_ulog.h>
43#include <net/netfilter/nf_log.h>
44#include <net/netns/generic.h>
45#include <net/sock.h>
46#include "../br_private.h"
47
48static unsigned int nlbufsiz = NLMSG_GOODSIZE;
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 int ebt_ulog_net_id __read_mostly;
67struct ebt_ulog_net {
68 unsigned int nlgroup[EBT_ULOG_MAXNLGROUPS];
69 ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS];
70 struct sock *ebtulognl;
71};
72
73static struct ebt_ulog_net *ebt_ulog_pernet(struct net *net)
74{
75 return net_generic(net, ebt_ulog_net_id);
76}
77
78/* send one ulog_buff_t to userspace */
79static void ulog_send(struct ebt_ulog_net *ebt, unsigned int nlgroup)
80{
81 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[nlgroup];
82
83 del_timer(&ub->timer);
84
85 if (!ub->skb)
86 return;
87
88 /* last nlmsg needs NLMSG_DONE */
89 if (ub->qlen > 1)
90 ub->lastnlh->nlmsg_type = NLMSG_DONE;
91
92 NETLINK_CB(ub->skb).dst_group = nlgroup + 1;
93 netlink_broadcast(ebt->ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC);
94
95 ub->qlen = 0;
96 ub->skb = NULL;
97}
98
99/* timer function to flush queue in flushtimeout time */
100static void ulog_timer(unsigned long data)
101{
102 struct ebt_ulog_net *ebt = container_of((void *)data,
103 struct ebt_ulog_net,
104 nlgroup[*(unsigned int *)data]);
105
106 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[*(unsigned int *)data];
107 spin_lock_bh(&ub->lock);
108 if (ub->skb)
109 ulog_send(ebt, *(unsigned int *)data);
110 spin_unlock_bh(&ub->lock);
111}
112
113static struct sk_buff *ulog_alloc_skb(unsigned int size)
114{
115 struct sk_buff *skb;
116 unsigned int n;
117
118 n = max(size, nlbufsiz);
119 skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN);
120 if (!skb) {
121 if (n > size) {
122 /* try to allocate only as much as we need for
123 * current packet */
124 skb = alloc_skb(size, GFP_ATOMIC);
125 if (!skb)
126 pr_debug("cannot even allocate buffer of size %ub\n",
127 size);
128 }
129 }
130
131 return skb;
132}
133
134static void ebt_ulog_packet(struct net *net, unsigned int hooknr,
135 const struct sk_buff *skb,
136 const struct net_device *in,
137 const struct net_device *out,
138 const struct ebt_ulog_info *uloginfo,
139 const char *prefix)
140{
141 ebt_ulog_packet_msg_t *pm;
142 size_t size, copy_len;
143 struct nlmsghdr *nlh;
144 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
145 unsigned int group = uloginfo->nlgroup;
146 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group];
147 spinlock_t *lock = &ub->lock;
148 ktime_t kt;
149
150 if ((uloginfo->cprange == 0) ||
151 (uloginfo->cprange > skb->len + ETH_HLEN))
152 copy_len = skb->len + ETH_HLEN;
153 else
154 copy_len = uloginfo->cprange;
155
156 size = nlmsg_total_size(sizeof(*pm) + copy_len);
157 if (size > nlbufsiz) {
158 pr_debug("Size %Zd needed, but nlbufsiz=%d\n", size, nlbufsiz);
159 return;
160 }
161
162 spin_lock_bh(lock);
163
164 if (!ub->skb) {
165 if (!(ub->skb = ulog_alloc_skb(size)))
166 goto unlock;
167 } else if (size > skb_tailroom(ub->skb)) {
168 ulog_send(ebt, group);
169
170 if (!(ub->skb = ulog_alloc_skb(size)))
171 goto unlock;
172 }
173
174 nlh = nlmsg_put(ub->skb, 0, ub->qlen, 0,
175 size - NLMSG_ALIGN(sizeof(*nlh)), 0);
176 if (!nlh) {
177 kfree_skb(ub->skb);
178 ub->skb = NULL;
179 goto unlock;
180 }
181 ub->qlen++;
182
183 pm = nlmsg_data(nlh);
184 memset(pm, 0, sizeof(*pm));
185
186 /* Fill in the ulog data */
187 pm->version = EBT_ULOG_VERSION;
188 kt = ktime_get_real();
189 pm->stamp = ktime_to_timeval(kt);
190 if (ub->qlen == 1)
191 ub->skb->tstamp = kt;
192 pm->data_len = copy_len;
193 pm->mark = skb->mark;
194 pm->hook = hooknr;
195 if (uloginfo->prefix != NULL)
196 strcpy(pm->prefix, uloginfo->prefix);
197
198 if (in) {
199 strcpy(pm->physindev, in->name);
200 /* If in isn't a bridge, then physindev==indev */
201 if (br_port_exists(in))
202 /* rcu_read_lock()ed by nf_hook_slow */
203 strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name);
204 else
205 strcpy(pm->indev, in->name);
206 }
207
208 if (out) {
209 /* If out exists, then out is a bridge port */
210 strcpy(pm->physoutdev, out->name);
211 /* rcu_read_lock()ed by nf_hook_slow */
212 strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name);
213 }
214
215 if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0)
216 BUG();
217
218 if (ub->qlen > 1)
219 ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
220
221 ub->lastnlh = nlh;
222
223 if (ub->qlen >= uloginfo->qthreshold)
224 ulog_send(ebt, group);
225 else if (!timer_pending(&ub->timer)) {
226 ub->timer.expires = jiffies + flushtimeout * HZ / 100;
227 add_timer(&ub->timer);
228 }
229
230unlock:
231 spin_unlock_bh(lock);
232}
233
234/* this function is registered with the netfilter core */
235static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
236 const struct sk_buff *skb, const struct net_device *in,
237 const struct net_device *out, const struct nf_loginfo *li,
238 const char *prefix)
239{
240 struct ebt_ulog_info loginfo;
241
242 if (!li || li->type != NF_LOG_TYPE_ULOG) {
243 loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
244 loginfo.cprange = 0;
245 loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
246 loginfo.prefix[0] = '\0';
247 } else {
248 loginfo.nlgroup = li->u.ulog.group;
249 loginfo.cprange = li->u.ulog.copy_len;
250 loginfo.qthreshold = li->u.ulog.qthreshold;
251 strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
252 }
253
254 ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix);
255}
256
257static unsigned int
258ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par)
259{
260 struct net *net = dev_net(par->in ? par->in : par->out);
261
262 ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out,
263 par->targinfo, NULL);
264 return EBT_CONTINUE;
265}
266
267static int ebt_ulog_tg_check(const struct xt_tgchk_param *par)
268{
269 struct ebt_ulog_info *uloginfo = par->targinfo;
270
271 if (!par->net->xt.ebt_ulog_warn_deprecated) {
272 pr_info("ebt_ulog is deprecated and it will be removed soon, "
273 "use ebt_nflog instead\n");
274 par->net->xt.ebt_ulog_warn_deprecated = true;
275 }
276
277 if (uloginfo->nlgroup > 31)
278 return -EINVAL;
279
280 uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0';
281
282 if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN)
283 uloginfo->qthreshold = EBT_ULOG_MAX_QLEN;
284
285 return 0;
286}
287
288static struct xt_target ebt_ulog_tg_reg __read_mostly = {
289 .name = "ulog",
290 .revision = 0,
291 .family = NFPROTO_BRIDGE,
292 .target = ebt_ulog_tg,
293 .checkentry = ebt_ulog_tg_check,
294 .targetsize = sizeof(struct ebt_ulog_info),
295 .me = THIS_MODULE,
296};
297
298static struct nf_logger ebt_ulog_logger __read_mostly = {
299 .name = "ebt_ulog",
300 .logfn = &ebt_log_packet,
301 .me = THIS_MODULE,
302};
303
304static int __net_init ebt_ulog_net_init(struct net *net)
305{
306 int i;
307 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
308
309 struct netlink_kernel_cfg cfg = {
310 .groups = EBT_ULOG_MAXNLGROUPS,
311 };
312
313 /* initialize ulog_buffers */
314 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
315 ebt->nlgroup[i] = i;
316 setup_timer(&ebt->ulog_buffers[i].timer, ulog_timer,
317 (unsigned long)&ebt->nlgroup[i]);
318 spin_lock_init(&ebt->ulog_buffers[i].lock);
319 }
320
321 ebt->ebtulognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg);
322 if (!ebt->ebtulognl)
323 return -ENOMEM;
324
325 nf_log_set(net, NFPROTO_BRIDGE, &ebt_ulog_logger);
326 return 0;
327}
328
329static void __net_exit ebt_ulog_net_fini(struct net *net)
330{
331 int i;
332 struct ebt_ulog_net *ebt = ebt_ulog_pernet(net);
333
334 nf_log_unset(net, &ebt_ulog_logger);
335 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
336 ebt_ulog_buff_t *ub = &ebt->ulog_buffers[i];
337 del_timer(&ub->timer);
338
339 if (ub->skb) {
340 kfree_skb(ub->skb);
341 ub->skb = NULL;
342 }
343 }
344 netlink_kernel_release(ebt->ebtulognl);
345}
346
347static struct pernet_operations ebt_ulog_net_ops = {
348 .init = ebt_ulog_net_init,
349 .exit = ebt_ulog_net_fini,
350 .id = &ebt_ulog_net_id,
351 .size = sizeof(struct ebt_ulog_net),
352};
353
354static int __init ebt_ulog_init(void)
355{
356 int ret;
357
358 if (nlbufsiz >= 128*1024) {
359 pr_warn("Netlink buffer has to be <= 128kB,"
360 "please try a smaller nlbufsiz parameter.\n");
361 return -EINVAL;
362 }
363
364 ret = register_pernet_subsys(&ebt_ulog_net_ops);
365 if (ret)
366 goto out_pernet;
367
368 ret = xt_register_target(&ebt_ulog_tg_reg);
369 if (ret)
370 goto out_target;
371
372 nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger);
373
374 return 0;
375
376out_target:
377 unregister_pernet_subsys(&ebt_ulog_net_ops);
378out_pernet:
379 return ret;
380}
381
382static void __exit ebt_ulog_fini(void)
383{
384 nf_log_unregister(&ebt_ulog_logger);
385 xt_unregister_target(&ebt_ulog_tg_reg);
386 unregister_pernet_subsys(&ebt_ulog_net_ops);
387}
388
389module_init(ebt_ulog_init);
390module_exit(ebt_ulog_fini);
391MODULE_LICENSE("GPL");
392MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
393MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG");
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 1059ed3bc255..6d69631b9f4d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -327,10 +327,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
327 char name[EBT_FUNCTION_MAXNAMELEN]; 327 char name[EBT_FUNCTION_MAXNAMELEN];
328 } *e; 328 } *e;
329 329
330 *error = mutex_lock_interruptible(mutex); 330 mutex_lock(mutex);
331 if (*error != 0)
332 return NULL;
333
334 list_for_each_entry(e, head, list) { 331 list_for_each_entry(e, head, list) {
335 if (strcmp(e->name, name) == 0) 332 if (strcmp(e->name, name) == 0)
336 return e; 333 return e;
@@ -1203,10 +1200,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table)
1203 1200
1204 table->private = newinfo; 1201 table->private = newinfo;
1205 rwlock_init(&table->lock); 1202 rwlock_init(&table->lock);
1206 ret = mutex_lock_interruptible(&ebt_mutex); 1203 mutex_lock(&ebt_mutex);
1207 if (ret != 0)
1208 goto free_chainstack;
1209
1210 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { 1204 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
1211 if (strcmp(t->name, table->name) == 0) { 1205 if (strcmp(t->name, table->name) == 0) {
1212 ret = -EEXIST; 1206 ret = -EEXIST;
diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c
new file mode 100644
index 000000000000..5d9953a90929
--- /dev/null
+++ b/net/bridge/netfilter/nf_log_bridge.c
@@ -0,0 +1,96 @@
1/*
2 * (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/spinlock.h>
11#include <linux/skbuff.h>
12#include <linux/if_bridge.h>
13#include <linux/ip.h>
14#include <net/route.h>
15
16#include <linux/netfilter.h>
17#include <net/netfilter/nf_log.h>
18
19static void nf_log_bridge_packet(struct net *net, u_int8_t pf,
20 unsigned int hooknum,
21 const struct sk_buff *skb,
22 const struct net_device *in,
23 const struct net_device *out,
24 const struct nf_loginfo *loginfo,
25 const char *prefix)
26{
27 switch (eth_hdr(skb)->h_proto) {
28 case htons(ETH_P_IP):
29 nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
30 loginfo, "%s", prefix);
31 break;
32 case htons(ETH_P_IPV6):
33 nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out,
34 loginfo, "%s", prefix);
35 break;
36 case htons(ETH_P_ARP):
37 case htons(ETH_P_RARP):
38 nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out,
39 loginfo, "%s", prefix);
40 break;
41 }
42}
43
44static struct nf_logger nf_bridge_logger __read_mostly = {
45 .name = "nf_log_bridge",
46 .type = NF_LOG_TYPE_LOG,
47 .logfn = nf_log_bridge_packet,
48 .me = THIS_MODULE,
49};
50
51static int __net_init nf_log_bridge_net_init(struct net *net)
52{
53 nf_log_set(net, NFPROTO_BRIDGE, &nf_bridge_logger);
54 return 0;
55}
56
57static void __net_exit nf_log_bridge_net_exit(struct net *net)
58{
59 nf_log_unset(net, &nf_bridge_logger);
60}
61
62static struct pernet_operations nf_log_bridge_net_ops = {
63 .init = nf_log_bridge_net_init,
64 .exit = nf_log_bridge_net_exit,
65};
66
67static int __init nf_log_bridge_init(void)
68{
69 int ret;
70
71 /* Request to load the real packet loggers. */
72 nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG);
73 nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG);
74 nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG);
75
76 ret = register_pernet_subsys(&nf_log_bridge_net_ops);
77 if (ret < 0)
78 return ret;
79
80 nf_log_register(NFPROTO_BRIDGE, &nf_bridge_logger);
81 return 0;
82}
83
84static void __exit nf_log_bridge_exit(void)
85{
86 unregister_pernet_subsys(&nf_log_bridge_net_ops);
87 nf_log_unregister(&nf_bridge_logger);
88}
89
90module_init(nf_log_bridge_init);
91module_exit(nf_log_bridge_exit);
92
93MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
94MODULE_DESCRIPTION("Netfilter bridge packet logging");
95MODULE_LICENSE("GPL");
96MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 0);
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
new file mode 100644
index 000000000000..ee3ffe93e14e
--- /dev/null
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -0,0 +1,67 @@
1/*
2 * Copyright (c) 2014 Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/netlink.h>
13#include <linux/netfilter.h>
14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nft_reject.h>
17
18static void nft_reject_bridge_eval(const struct nft_expr *expr,
19 struct nft_data data[NFT_REG_MAX + 1],
20 const struct nft_pktinfo *pkt)
21{
22 switch (eth_hdr(pkt->skb)->h_proto) {
23 case htons(ETH_P_IP):
24 return nft_reject_ipv4_eval(expr, data, pkt);
25 case htons(ETH_P_IPV6):
26 return nft_reject_ipv6_eval(expr, data, pkt);
27 default:
28 /* No explicit way to reject this protocol, drop it. */
29 data[NFT_REG_VERDICT].verdict = NF_DROP;
30 break;
31 }
32}
33
34static struct nft_expr_type nft_reject_bridge_type;
35static const struct nft_expr_ops nft_reject_bridge_ops = {
36 .type = &nft_reject_bridge_type,
37 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
38 .eval = nft_reject_bridge_eval,
39 .init = nft_reject_init,
40 .dump = nft_reject_dump,
41};
42
43static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
44 .family = NFPROTO_BRIDGE,
45 .name = "reject",
46 .ops = &nft_reject_bridge_ops,
47 .policy = nft_reject_policy,
48 .maxattr = NFTA_REJECT_MAX,
49 .owner = THIS_MODULE,
50};
51
52static int __init nft_reject_bridge_module_init(void)
53{
54 return nft_register_expr(&nft_reject_bridge_type);
55}
56
57static void __exit nft_reject_bridge_module_exit(void)
58{
59 nft_unregister_expr(&nft_reject_bridge_type);
60}
61
62module_init(nft_reject_bridge_module_init);
63module_exit(nft_reject_bridge_module_exit);
64
65MODULE_LICENSE("GPL");
66MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
67MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject");