aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c1
-rw-r--r--net/bridge/br_device.c91
-rw-r--r--net/bridge/br_if.c55
-rw-r--r--net/bridge/br_input.c11
-rw-r--r--net/bridge/br_netfilter.c4
-rw-r--r--net/bridge/br_notify.c14
-rw-r--r--net/bridge/br_private.h7
-rw-r--r--net/bridge/br_stp_if.c5
-rw-r--r--net/bridge/br_sysfs_if.c4
-rw-r--r--net/bridge/netfilter/Kconfig6
-rw-r--r--net/bridge/netfilter/ebt_log.c73
-rw-r--r--net/bridge/netfilter/ebt_ulog.c53
12 files changed, 267 insertions, 57 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index f8f184942aaf..188cc1ac49eb 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -67,3 +67,4 @@ EXPORT_SYMBOL(br_should_route_hook);
67module_init(br_init) 67module_init(br_init)
68module_exit(br_deinit) 68module_exit(br_deinit)
69MODULE_LICENSE("GPL"); 69MODULE_LICENSE("GPL");
70MODULE_VERSION(BR_VERSION);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f564ee99782d..0b33a7b3a00c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -15,7 +15,9 @@
15 15
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/module.h> 18#include <linux/etherdevice.h>
19#include <linux/ethtool.h>
20
19#include <asm/uaccess.h> 21#include <asm/uaccess.h>
20#include "br_private.h" 22#include "br_private.h"
21 23
@@ -82,6 +84,87 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
82 return 0; 84 return 0;
83} 85}
84 86
87/* Allow setting mac address of pseudo-bridge to be same as
88 * any of the bound interfaces
89 */
90static int br_set_mac_address(struct net_device *dev, void *p)
91{
92 struct net_bridge *br = netdev_priv(dev);
93 struct sockaddr *addr = p;
94 struct net_bridge_port *port;
95 int err = -EADDRNOTAVAIL;
96
97 spin_lock_bh(&br->lock);
98 list_for_each_entry(port, &br->port_list, list) {
99 if (!compare_ether_addr(port->dev->dev_addr, addr->sa_data)) {
100 br_stp_change_bridge_id(br, addr->sa_data);
101 err = 0;
102 break;
103 }
104 }
105 spin_unlock_bh(&br->lock);
106
107 return err;
108}
109
110static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
111{
112 strcpy(info->driver, "bridge");
113 strcpy(info->version, BR_VERSION);
114 strcpy(info->fw_version, "N/A");
115 strcpy(info->bus_info, "N/A");
116}
117
118static int br_set_sg(struct net_device *dev, u32 data)
119{
120 struct net_bridge *br = netdev_priv(dev);
121
122 if (data)
123 br->feature_mask |= NETIF_F_SG;
124 else
125 br->feature_mask &= ~NETIF_F_SG;
126
127 br_features_recompute(br);
128 return 0;
129}
130
131static int br_set_tso(struct net_device *dev, u32 data)
132{
133 struct net_bridge *br = netdev_priv(dev);
134
135 if (data)
136 br->feature_mask |= NETIF_F_TSO;
137 else
138 br->feature_mask &= ~NETIF_F_TSO;
139
140 br_features_recompute(br);
141 return 0;
142}
143
144static int br_set_tx_csum(struct net_device *dev, u32 data)
145{
146 struct net_bridge *br = netdev_priv(dev);
147
148 if (data)
149 br->feature_mask |= NETIF_F_IP_CSUM;
150 else
151 br->feature_mask &= ~NETIF_F_IP_CSUM;
152
153 br_features_recompute(br);
154 return 0;
155}
156
157static struct ethtool_ops br_ethtool_ops = {
158 .get_drvinfo = br_getinfo,
159 .get_link = ethtool_op_get_link,
160 .get_sg = ethtool_op_get_sg,
161 .set_sg = br_set_sg,
162 .get_tx_csum = ethtool_op_get_tx_csum,
163 .set_tx_csum = br_set_tx_csum,
164 .get_tso = ethtool_op_get_tso,
165 .set_tso = br_set_tso,
166};
167
85void br_dev_setup(struct net_device *dev) 168void br_dev_setup(struct net_device *dev)
86{ 169{
87 memset(dev->dev_addr, 0, ETH_ALEN); 170 memset(dev->dev_addr, 0, ETH_ALEN);
@@ -96,8 +179,12 @@ void br_dev_setup(struct net_device *dev)
96 dev->change_mtu = br_change_mtu; 179 dev->change_mtu = br_change_mtu;
97 dev->destructor = free_netdev; 180 dev->destructor = free_netdev;
98 SET_MODULE_OWNER(dev); 181 SET_MODULE_OWNER(dev);
182 SET_ETHTOOL_OPS(dev, &br_ethtool_ops);
99 dev->stop = br_dev_stop; 183 dev->stop = br_dev_stop;
100 dev->tx_queue_len = 0; 184 dev->tx_queue_len = 0;
101 dev->set_mac_address = NULL; 185 dev->set_mac_address = br_set_mac_address;
102 dev->priv_flags = IFF_EBRIDGE; 186 dev->priv_flags = IFF_EBRIDGE;
187
188 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
189 | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
103} 190}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 975abe254b7a..11321197338e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -32,9 +32,8 @@
32 * ethtool, use ethtool_ops. Also, since driver might sleep need to 32 * ethtool, use ethtool_ops. Also, since driver might sleep need to
33 * not be holding any locks. 33 * not be holding any locks.
34 */ 34 */
35static int br_initial_port_cost(struct net_device *dev) 35static int port_cost(struct net_device *dev)
36{ 36{
37
38 struct ethtool_cmd ecmd = { ETHTOOL_GSET }; 37 struct ethtool_cmd ecmd = { ETHTOOL_GSET };
39 struct ifreq ifr; 38 struct ifreq ifr;
40 mm_segment_t old_fs; 39 mm_segment_t old_fs;
@@ -58,10 +57,6 @@ static int br_initial_port_cost(struct net_device *dev)
58 return 2; 57 return 2;
59 case SPEED_10: 58 case SPEED_10:
60 return 100; 59 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 } 60 }
66 } 61 }
67 62
@@ -75,6 +70,35 @@ static int br_initial_port_cost(struct net_device *dev)
75 return 100; /* assume old 10Mbps */ 70 return 100; /* assume old 10Mbps */
76} 71}
77 72
73
74/*
75 * Check for port carrier transistions.
76 * Called from work queue to allow for calling functions that
77 * might sleep (such as speed check), and to debounce.
78 */
79static void port_carrier_check(void *arg)
80{
81 struct net_bridge_port *p = arg;
82
83 rtnl_lock();
84 if (netif_carrier_ok(p->dev)) {
85 u32 cost = port_cost(p->dev);
86
87 spin_lock_bh(&p->br->lock);
88 if (p->state == BR_STATE_DISABLED) {
89 p->path_cost = cost;
90 br_stp_enable_port(p);
91 }
92 spin_unlock_bh(&p->br->lock);
93 } else {
94 spin_lock_bh(&p->br->lock);
95 if (p->state != BR_STATE_DISABLED)
96 br_stp_disable_port(p);
97 spin_unlock_bh(&p->br->lock);
98 }
99 rtnl_unlock();
100}
101
78static void destroy_nbp(struct net_bridge_port *p) 102static void destroy_nbp(struct net_bridge_port *p)
79{ 103{
80 struct net_device *dev = p->dev; 104 struct net_device *dev = p->dev;
@@ -102,6 +126,9 @@ static void del_nbp(struct net_bridge_port *p)
102 dev->br_port = NULL; 126 dev->br_port = NULL;
103 dev_set_promiscuity(dev, -1); 127 dev_set_promiscuity(dev, -1);
104 128
129 cancel_delayed_work(&p->carrier_check);
130 flush_scheduled_work();
131
105 spin_lock_bh(&br->lock); 132 spin_lock_bh(&br->lock);
106 br_stp_disable_port(p); 133 br_stp_disable_port(p);
107 spin_unlock_bh(&br->lock); 134 spin_unlock_bh(&br->lock);
@@ -155,6 +182,7 @@ static struct net_device *new_bridge_dev(const char *name)
155 br->bridge_id.prio[1] = 0x00; 182 br->bridge_id.prio[1] = 0x00;
156 memset(br->bridge_id.addr, 0, ETH_ALEN); 183 memset(br->bridge_id.addr, 0, ETH_ALEN);
157 184
185 br->feature_mask = dev->features;
158 br->stp_enabled = 0; 186 br->stp_enabled = 0;
159 br->designated_root = br->bridge_id; 187 br->designated_root = br->bridge_id;
160 br->root_path_cost = 0; 188 br->root_path_cost = 0;
@@ -195,10 +223,9 @@ static int find_portno(struct net_bridge *br)
195 return (index >= BR_MAX_PORTS) ? -EXFULL : index; 223 return (index >= BR_MAX_PORTS) ? -EXFULL : index;
196} 224}
197 225
198/* called with RTNL */ 226/* called with RTNL but without bridge lock */
199static struct net_bridge_port *new_nbp(struct net_bridge *br, 227static struct net_bridge_port *new_nbp(struct net_bridge *br,
200 struct net_device *dev, 228 struct net_device *dev)
201 unsigned long cost)
202{ 229{
203 int index; 230 int index;
204 struct net_bridge_port *p; 231 struct net_bridge_port *p;
@@ -215,12 +242,13 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br,
215 p->br = br; 242 p->br = br;
216 dev_hold(dev); 243 dev_hold(dev);
217 p->dev = dev; 244 p->dev = dev;
218 p->path_cost = cost; 245 p->path_cost = port_cost(dev);
219 p->priority = 0x8000 >> BR_PORT_BITS; 246 p->priority = 0x8000 >> BR_PORT_BITS;
220 dev->br_port = p; 247 dev->br_port = p;
221 p->port_no = index; 248 p->port_no = index;
222 br_init_port(p); 249 br_init_port(p);
223 p->state = BR_STATE_DISABLED; 250 p->state = BR_STATE_DISABLED;
251 INIT_WORK(&p->carrier_check, port_carrier_check, p);
224 kobject_init(&p->kobj); 252 kobject_init(&p->kobj);
225 253
226 return p; 254 return p;
@@ -322,9 +350,8 @@ void br_features_recompute(struct net_bridge *br)
322 struct net_bridge_port *p; 350 struct net_bridge_port *p;
323 unsigned long features, checksum; 351 unsigned long features, checksum;
324 352
325 features = NETIF_F_SG | NETIF_F_FRAGLIST 353 features = br->feature_mask &~ NETIF_F_IP_CSUM;
326 | NETIF_F_HIGHDMA | NETIF_F_TSO; 354 checksum = br->feature_mask & NETIF_F_IP_CSUM;
327 checksum = NETIF_F_IP_CSUM; /* least commmon subset */
328 355
329 list_for_each_entry(p, &br->port_list, list) { 356 list_for_each_entry(p, &br->port_list, list) {
330 if (!(p->dev->features 357 if (!(p->dev->features
@@ -351,7 +378,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
351 if (dev->br_port != NULL) 378 if (dev->br_port != NULL)
352 return -EBUSY; 379 return -EBUSY;
353 380
354 if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev)))) 381 if (IS_ERR(p = new_nbp(br, dev)))
355 return PTR_ERR(p); 382 return PTR_ERR(p);
356 383
357 if ((err = br_fdb_insert(br, p, dev->dev_addr))) 384 if ((err = br_fdb_insert(br, p, dev->dev_addr)))
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index b88220a64cd8..c387852f753a 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -53,6 +53,11 @@ int br_handle_frame_finish(struct sk_buff *skb)
53 /* insert into forwarding database after filtering to avoid spoofing */ 53 /* insert into forwarding database after filtering to avoid spoofing */
54 br_fdb_update(p->br, p, eth_hdr(skb)->h_source); 54 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
55 55
56 if (p->state == BR_STATE_LEARNING) {
57 kfree_skb(skb);
58 goto out;
59 }
60
56 if (br->dev->flags & IFF_PROMISC) { 61 if (br->dev->flags & IFF_PROMISC) {
57 struct sk_buff *skb2; 62 struct sk_buff *skb2;
58 63
@@ -107,9 +112,6 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
107 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 112 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
108 goto err; 113 goto err;
109 114
110 if (p->state == BR_STATE_LEARNING)
111 br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
112
113 if (p->br->stp_enabled && 115 if (p->br->stp_enabled &&
114 !memcmp(dest, bridge_ula, 5) && 116 !memcmp(dest, bridge_ula, 5) &&
115 !(dest[5] & 0xF0)) { 117 !(dest[5] & 0xF0)) {
@@ -118,9 +120,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
118 NULL, br_stp_handle_bpdu); 120 NULL, br_stp_handle_bpdu);
119 return 1; 121 return 1;
120 } 122 }
123 goto err;
121 } 124 }
122 125
123 else if (p->state == BR_STATE_FORWARDING) { 126 if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
124 if (br_should_route_hook) { 127 if (br_should_route_hook) {
125 if (br_should_route_hook(pskb)) 128 if (br_should_route_hook(pskb))
126 return 0; 129 return 0;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 23422bd53a5e..223f8270daee 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -26,6 +26,7 @@
26#include <linux/ip.h> 26#include <linux/ip.h>
27#include <linux/netdevice.h> 27#include <linux/netdevice.h>
28#include <linux/skbuff.h> 28#include <linux/skbuff.h>
29#include <linux/if_arp.h>
29#include <linux/if_ether.h> 30#include <linux/if_ether.h>
30#include <linux/if_vlan.h> 31#include <linux/if_vlan.h>
31#include <linux/netfilter_bridge.h> 32#include <linux/netfilter_bridge.h>
@@ -33,8 +34,11 @@
33#include <linux/netfilter_ipv6.h> 34#include <linux/netfilter_ipv6.h>
34#include <linux/netfilter_arp.h> 35#include <linux/netfilter_arp.h>
35#include <linux/in_route.h> 36#include <linux/in_route.h>
37
36#include <net/ip.h> 38#include <net/ip.h>
37#include <net/ipv6.h> 39#include <net/ipv6.h>
40#include <net/route.h>
41
38#include <asm/uaccess.h> 42#include <asm/uaccess.h>
39#include <asm/checksum.h> 43#include <asm/checksum.h>
40#include "br_private.h" 44#include "br_private.h"
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index 917311c6828b..a43a9c1d50d7 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -52,17 +52,9 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
52 br_stp_recalculate_bridge_id(br); 52 br_stp_recalculate_bridge_id(br);
53 break; 53 break;
54 54
55 case NETDEV_CHANGE: /* device is up but carrier changed */ 55 case NETDEV_CHANGE:
56 if (!(br->dev->flags & IFF_UP)) 56 if (br->dev->flags & IFF_UP)
57 break; 57 schedule_delayed_work(&p->carrier_check, BR_PORT_DEBOUNCE);
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; 58 break;
67 59
68 case NETDEV_FEAT_CHANGE: 60 case NETDEV_FEAT_CHANGE:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bdf95a74d8cd..c5bd631ffcd5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -27,6 +27,10 @@
27#define BR_PORT_BITS 10 27#define BR_PORT_BITS 10
28#define BR_MAX_PORTS (1<<BR_PORT_BITS) 28#define BR_MAX_PORTS (1<<BR_PORT_BITS)
29 29
30#define BR_PORT_DEBOUNCE (HZ/10)
31
32#define BR_VERSION "2.1"
33
30typedef struct bridge_id bridge_id; 34typedef struct bridge_id bridge_id;
31typedef struct mac_addr mac_addr; 35typedef struct mac_addr mac_addr;
32typedef __u16 port_id; 36typedef __u16 port_id;
@@ -78,6 +82,7 @@ struct net_bridge_port
78 struct timer_list hold_timer; 82 struct timer_list hold_timer;
79 struct timer_list message_age_timer; 83 struct timer_list message_age_timer;
80 struct kobject kobj; 84 struct kobject kobj;
85 struct work_struct carrier_check;
81 struct rcu_head rcu; 86 struct rcu_head rcu;
82}; 87};
83 88
@@ -90,6 +95,7 @@ struct net_bridge
90 spinlock_t hash_lock; 95 spinlock_t hash_lock;
91 struct hlist_head hash[BR_HASH_SIZE]; 96 struct hlist_head hash[BR_HASH_SIZE];
92 struct list_head age_list; 97 struct list_head age_list;
98 unsigned long feature_mask;
93 99
94 /* STP */ 100 /* STP */
95 bridge_id designated_root; 101 bridge_id designated_root;
@@ -201,6 +207,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br);
201extern void br_stp_enable_port(struct net_bridge_port *p); 207extern void br_stp_enable_port(struct net_bridge_port *p);
202extern void br_stp_disable_port(struct net_bridge_port *p); 208extern void br_stp_disable_port(struct net_bridge_port *p);
203extern void br_stp_recalculate_bridge_id(struct net_bridge *br); 209extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
210extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a);
204extern void br_stp_set_bridge_priority(struct net_bridge *br, 211extern void br_stp_set_bridge_priority(struct net_bridge *br,
205 u16 newprio); 212 u16 newprio);
206extern void br_stp_set_port_priority(struct net_bridge_port *p, 213extern void br_stp_set_port_priority(struct net_bridge_port *p,
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index ac09b6a23523..cc047f7fb6ef 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -120,8 +120,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
120} 120}
121 121
122/* called under bridge lock */ 122/* called under bridge lock */
123static void br_stp_change_bridge_id(struct net_bridge *br, 123void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr)
124 const unsigned char *addr)
125{ 124{
126 unsigned char oldaddr[6]; 125 unsigned char oldaddr[6];
127 struct net_bridge_port *p; 126 struct net_bridge_port *p;
@@ -158,7 +157,7 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br)
158 157
159 list_for_each_entry(p, &br->port_list, list) { 158 list_for_each_entry(p, &br->port_list, list) {
160 if (addr == br_mac_zero || 159 if (addr == br_mac_zero ||
161 compare_ether_addr(p->dev->dev_addr, addr) < 0) 160 memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)
162 addr = p->dev->dev_addr; 161 addr = p->dev->dev_addr;
163 162
164 } 163 }
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index f6a19d53eaeb..2ebdc23bbe26 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -248,7 +248,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
248 if (err) 248 if (err)
249 goto out2; 249 goto out2;
250 250
251 kobject_hotplug(&p->kobj, KOBJ_ADD); 251 kobject_uevent(&p->kobj, KOBJ_ADD);
252 return 0; 252 return 0;
253 out2: 253 out2:
254 kobject_del(&p->kobj); 254 kobject_del(&p->kobj);
@@ -260,7 +260,7 @@ void br_sysfs_removeif(struct net_bridge_port *p)
260{ 260{
261 pr_debug("br_sysfs_removeif\n"); 261 pr_debug("br_sysfs_removeif\n");
262 sysfs_remove_link(&p->br->ifobj, p->dev->name); 262 sysfs_remove_link(&p->br->ifobj, p->dev->name);
263 kobject_hotplug(&p->kobj, KOBJ_REMOVE); 263 kobject_uevent(&p->kobj, KOBJ_REMOVE);
264 kobject_del(&p->kobj); 264 kobject_del(&p->kobj);
265} 265}
266 266
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig
index c70b3be23026..b84fc6075fe1 100644
--- a/net/bridge/netfilter/Kconfig
+++ b/net/bridge/netfilter/Kconfig
@@ -196,9 +196,13 @@ config BRIDGE_EBT_LOG
196 To compile it as a module, choose M here. If unsure, say N. 196 To compile it as a module, choose M here. If unsure, say N.
197 197
198config BRIDGE_EBT_ULOG 198config BRIDGE_EBT_ULOG
199 tristate "ebt: ulog support" 199 tristate "ebt: ulog support (OBSOLETE)"
200 depends on BRIDGE_NF_EBTABLES 200 depends on BRIDGE_NF_EBTABLES
201 help 201 help
202 This option enables the old bridge-specific "ebt_ulog" implementation
203 which has been obsoleted by the new "nfnetlink_log" code (see
204 CONFIG_NETFILTER_NETLINK_LOG).
205
202 This option adds the ulog watcher, that you can use in any rule 206 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 207 in any ebtables table. The packet is passed to a userspace
204 logging daemon using netlink multicast sockets. This differs 208 logging daemon using netlink multicast sockets. This differs
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index 662975be3d1d..9f6e0193ae10 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -3,13 +3,16 @@
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Harald Welte <laforge@netfilter.org>
6 * 7 *
7 * April, 2002 8 * April, 2002
8 * 9 *
9 */ 10 */
10 11
12#include <linux/in.h>
11#include <linux/netfilter_bridge/ebtables.h> 13#include <linux/netfilter_bridge/ebtables.h>
12#include <linux/netfilter_bridge/ebt_log.h> 14#include <linux/netfilter_bridge/ebt_log.h>
15#include <linux/netfilter.h>
13#include <linux/module.h> 16#include <linux/module.h>
14#include <linux/ip.h> 17#include <linux/ip.h>
15#include <linux/if_arp.h> 18#include <linux/if_arp.h>
@@ -55,27 +58,30 @@ static void print_MAC(unsigned char *p)
55} 58}
56 59
57#define myNIPQUAD(a) a[0], a[1], a[2], a[3] 60#define myNIPQUAD(a) a[0], a[1], a[2], a[3]
58static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, 61static void
59 const struct net_device *in, const struct net_device *out, 62ebt_log_packet(unsigned int pf, unsigned int hooknum,
60 const void *data, unsigned int datalen) 63 const struct sk_buff *skb, const struct net_device *in,
64 const struct net_device *out, const struct nf_loginfo *loginfo,
65 const char *prefix)
61{ 66{
62 struct ebt_log_info *info = (struct ebt_log_info *)data; 67 unsigned int bitmask;
63 char level_string[4] = "< >";
64 68
65 level_string[1] = '0' + info->loglevel;
66 spin_lock_bh(&ebt_log_lock); 69 spin_lock_bh(&ebt_log_lock);
67 printk(level_string); 70 printk("<%c>%s IN=%s OUT=%s MAC source = ", '0' + loginfo->u.log.level,
68 printk("%s IN=%s OUT=%s ", info->prefix, in ? in->name : "", 71 prefix, in ? in->name : "", out ? out->name : "");
69 out ? out->name : "");
70 72
71 printk("MAC source = ");
72 print_MAC(eth_hdr(skb)->h_source); 73 print_MAC(eth_hdr(skb)->h_source);
73 printk("MAC dest = "); 74 printk("MAC dest = ");
74 print_MAC(eth_hdr(skb)->h_dest); 75 print_MAC(eth_hdr(skb)->h_dest);
75 76
76 printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto)); 77 printk("proto = 0x%04x", ntohs(eth_hdr(skb)->h_proto));
77 78
78 if ((info->bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto == 79 if (loginfo->type == NF_LOG_TYPE_LOG)
80 bitmask = loginfo->u.log.logflags;
81 else
82 bitmask = NF_LOG_MASK;
83
84 if ((bitmask & EBT_LOG_IP) && eth_hdr(skb)->h_proto ==
79 htons(ETH_P_IP)){ 85 htons(ETH_P_IP)){
80 struct iphdr _iph, *ih; 86 struct iphdr _iph, *ih;
81 87
@@ -84,10 +90,9 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
84 printk(" INCOMPLETE IP header"); 90 printk(" INCOMPLETE IP header");
85 goto out; 91 goto out;
86 } 92 }
87 printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u,", 93 printk(" IP SRC=%u.%u.%u.%u IP DST=%u.%u.%u.%u, IP "
88 NIPQUAD(ih->saddr), NIPQUAD(ih->daddr)); 94 "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr),
89 printk(" IP tos=0x%02X, IP proto=%d", ih->tos, 95 NIPQUAD(ih->daddr), ih->tos, ih->protocol);
90 ih->protocol);
91 if (ih->protocol == IPPROTO_TCP || 96 if (ih->protocol == IPPROTO_TCP ||
92 ih->protocol == IPPROTO_UDP) { 97 ih->protocol == IPPROTO_UDP) {
93 struct tcpudphdr _ports, *pptr; 98 struct tcpudphdr _ports, *pptr;
@@ -104,7 +109,7 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
104 goto out; 109 goto out;
105 } 110 }
106 111
107 if ((info->bitmask & EBT_LOG_ARP) && 112 if ((bitmask & EBT_LOG_ARP) &&
108 ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) || 113 ((eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) ||
109 (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) { 114 (eth_hdr(skb)->h_proto == htons(ETH_P_RARP)))) {
110 struct arphdr _arph, *ah; 115 struct arphdr _arph, *ah;
@@ -144,6 +149,21 @@ static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
144out: 149out:
145 printk("\n"); 150 printk("\n");
146 spin_unlock_bh(&ebt_log_lock); 151 spin_unlock_bh(&ebt_log_lock);
152
153}
154
155static void ebt_log(const struct sk_buff *skb, unsigned int hooknr,
156 const struct net_device *in, const struct net_device *out,
157 const void *data, unsigned int datalen)
158{
159 struct ebt_log_info *info = (struct ebt_log_info *)data;
160 struct nf_loginfo li;
161
162 li.type = NF_LOG_TYPE_LOG;
163 li.u.log.level = info->loglevel;
164 li.u.log.logflags = info->bitmask;
165
166 nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, info->prefix);
147} 167}
148 168
149static struct ebt_watcher log = 169static struct ebt_watcher log =
@@ -154,13 +174,32 @@ static struct ebt_watcher log =
154 .me = THIS_MODULE, 174 .me = THIS_MODULE,
155}; 175};
156 176
177static struct nf_logger ebt_log_logger = {
178 .name = "ebt_log",
179 .logfn = &ebt_log_packet,
180 .me = THIS_MODULE,
181};
182
157static int __init init(void) 183static int __init init(void)
158{ 184{
159 return ebt_register_watcher(&log); 185 int ret;
186
187 ret = ebt_register_watcher(&log);
188 if (ret < 0)
189 return ret;
190 if (nf_log_register(PF_BRIDGE, &ebt_log_logger) < 0) {
191 printk(KERN_WARNING "ebt_log: not logging via system console "
192 "since somebody else already registered for PF_INET\n");
193 /* we cannot make module load fail here, since otherwise
194 * ebtables userspace would abort */
195 }
196
197 return 0;
160} 198}
161 199
162static void __exit fini(void) 200static void __exit fini(void)
163{ 201{
202 nf_log_unregister_logger(&ebt_log_logger);
164 ebt_unregister_watcher(&log); 203 ebt_unregister_watcher(&log);
165} 204}
166 205
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index aae26ae2e61f..ce617b3dbbb8 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Authors: 4 * Authors:
5 * Bart De Schuymer <bdschuym@pandora.be> 5 * Bart De Schuymer <bdschuym@pandora.be>
6 * Harald Welte <laforge@netfilter.org>
6 * 7 *
7 * November, 2004 8 * November, 2004
8 * 9 *
@@ -115,14 +116,13 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size)
115 return skb; 116 return skb;
116} 117}
117 118
118static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, 119static void ebt_ulog_packet(unsigned int hooknr, const struct sk_buff *skb,
119 const struct net_device *in, const struct net_device *out, 120 const struct net_device *in, const struct net_device *out,
120 const void *data, unsigned int datalen) 121 const struct ebt_ulog_info *uloginfo, const char *prefix)
121{ 122{
122 ebt_ulog_packet_msg_t *pm; 123 ebt_ulog_packet_msg_t *pm;
123 size_t size, copy_len; 124 size_t size, copy_len;
124 struct nlmsghdr *nlh; 125 struct nlmsghdr *nlh;
125 struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
126 unsigned int group = uloginfo->nlgroup; 126 unsigned int group = uloginfo->nlgroup;
127 ebt_ulog_buff_t *ub = &ulog_buffers[group]; 127 ebt_ulog_buff_t *ub = &ulog_buffers[group];
128 spinlock_t *lock = &ub->lock; 128 spinlock_t *lock = &ub->lock;
@@ -216,6 +216,39 @@ alloc_failure:
216 goto unlock; 216 goto unlock;
217} 217}
218 218
219/* this function is registered with the netfilter core */
220static void ebt_log_packet(unsigned int pf, unsigned int hooknum,
221 const struct sk_buff *skb, const struct net_device *in,
222 const struct net_device *out, const struct nf_loginfo *li,
223 const char *prefix)
224{
225 struct ebt_ulog_info loginfo;
226
227 if (!li || li->type != NF_LOG_TYPE_ULOG) {
228 loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP;
229 loginfo.cprange = 0;
230 loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD;
231 loginfo.prefix[0] = '\0';
232 } else {
233 loginfo.nlgroup = li->u.ulog.group;
234 loginfo.cprange = li->u.ulog.copy_len;
235 loginfo.qthreshold = li->u.ulog.qthreshold;
236 strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix));
237 }
238
239 ebt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
240}
241
242static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr,
243 const struct net_device *in, const struct net_device *out,
244 const void *data, unsigned int datalen)
245{
246 struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data;
247
248 ebt_ulog_packet(hooknr, skb, in, out, uloginfo, NULL);
249}
250
251
219static int ebt_ulog_check(const char *tablename, unsigned int hookmask, 252static int ebt_ulog_check(const char *tablename, unsigned int hookmask,
220 const struct ebt_entry *e, void *data, unsigned int datalen) 253 const struct ebt_entry *e, void *data, unsigned int datalen)
221{ 254{
@@ -240,6 +273,12 @@ static struct ebt_watcher ulog = {
240 .me = THIS_MODULE, 273 .me = THIS_MODULE,
241}; 274};
242 275
276static struct nf_logger ebt_ulog_logger = {
277 .name = EBT_ULOG_WATCHER,
278 .logfn = &ebt_log_packet,
279 .me = THIS_MODULE,
280};
281
243static int __init init(void) 282static int __init init(void)
244{ 283{
245 int i, ret = 0; 284 int i, ret = 0;
@@ -265,6 +304,13 @@ static int __init init(void)
265 else if ((ret = ebt_register_watcher(&ulog))) 304 else if ((ret = ebt_register_watcher(&ulog)))
266 sock_release(ebtulognl->sk_socket); 305 sock_release(ebtulognl->sk_socket);
267 306
307 if (nf_log_register(PF_BRIDGE, &ebt_ulog_logger) < 0) {
308 printk(KERN_WARNING "ebt_ulog: not logging via ulog "
309 "since somebody else already registered for PF_BRIDGE\n");
310 /* we cannot make module load fail here, since otherwise
311 * ebtables userspace would abort */
312 }
313
268 return ret; 314 return ret;
269} 315}
270 316
@@ -273,6 +319,7 @@ static void __exit fini(void)
273 ebt_ulog_buff_t *ub; 319 ebt_ulog_buff_t *ub;
274 int i; 320 int i;
275 321
322 nf_log_unregister_logger(&ebt_ulog_logger);
276 ebt_unregister_watcher(&ulog); 323 ebt_unregister_watcher(&ulog);
277 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { 324 for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) {
278 ub = &ulog_buffers[i]; 325 ub = &ulog_buffers[i];