diff options
author | Len Brown <len.brown@intel.com> | 2006-01-07 03:50:18 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-01-07 03:50:18 -0500 |
commit | ed03f430cdc8c802652467e9097606fedc2c7abc (patch) | |
tree | 30941ec1e6f93e99358fefe18175e5dd800a4379 /net/bridge | |
parent | ed349a8a0a780ed27e2a765f16cee54d9b63bfee (diff) | |
parent | 6f957eaf79356a32e838f5f262ee9a60544b1d5b (diff) |
Pull pnpacpi into acpica branch
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br.c | 1 | ||||
-rw-r--r-- | net/bridge/br_device.c | 91 | ||||
-rw-r--r-- | net/bridge/br_if.c | 60 | ||||
-rw-r--r-- | net/bridge/br_input.c | 13 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 36 | ||||
-rw-r--r-- | net/bridge/br_notify.c | 14 | ||||
-rw-r--r-- | net/bridge/br_private.h | 7 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 5 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 4 | ||||
-rw-r--r-- | net/bridge/netfilter/Kconfig | 6 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_log.c | 73 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 53 |
12 files changed, 289 insertions, 74 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); | |||
67 | module_init(br_init) | 67 | module_init(br_init) |
68 | module_exit(br_deinit) | 68 | module_exit(br_deinit) |
69 | MODULE_LICENSE("GPL"); | 69 | MODULE_LICENSE("GPL"); |
70 | MODULE_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 | */ | ||
90 | static 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 | |||
110 | static 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 | |||
118 | static 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 | |||
131 | static 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 | |||
144 | static 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 | |||
157 | static 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 | |||
85 | void br_dev_setup(struct net_device *dev) | 168 | void 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..ba442883e877 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/rtnetlink.h> | 22 | #include <linux/rtnetlink.h> |
23 | #include <linux/if_ether.h> | ||
23 | #include <net/sock.h> | 24 | #include <net/sock.h> |
24 | 25 | ||
25 | #include "br_private.h" | 26 | #include "br_private.h" |
@@ -32,9 +33,8 @@ | |||
32 | * ethtool, use ethtool_ops. Also, since driver might sleep need to | 33 | * ethtool, use ethtool_ops. Also, since driver might sleep need to |
33 | * not be holding any locks. | 34 | * not be holding any locks. |
34 | */ | 35 | */ |
35 | static int br_initial_port_cost(struct net_device *dev) | 36 | static int port_cost(struct net_device *dev) |
36 | { | 37 | { |
37 | |||
38 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; | 38 | struct ethtool_cmd ecmd = { ETHTOOL_GSET }; |
39 | struct ifreq ifr; | 39 | struct ifreq ifr; |
40 | mm_segment_t old_fs; | 40 | mm_segment_t old_fs; |
@@ -58,10 +58,6 @@ static int br_initial_port_cost(struct net_device *dev) | |||
58 | return 2; | 58 | return 2; |
59 | case SPEED_10: | 59 | case SPEED_10: |
60 | return 100; | 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 | } | 61 | } |
66 | } | 62 | } |
67 | 63 | ||
@@ -75,6 +71,35 @@ static int br_initial_port_cost(struct net_device *dev) | |||
75 | return 100; /* assume old 10Mbps */ | 71 | return 100; /* assume old 10Mbps */ |
76 | } | 72 | } |
77 | 73 | ||
74 | |||
75 | /* | ||
76 | * Check for port carrier transistions. | ||
77 | * Called from work queue to allow for calling functions that | ||
78 | * might sleep (such as speed check), and to debounce. | ||
79 | */ | ||
80 | static void port_carrier_check(void *arg) | ||
81 | { | ||
82 | struct net_bridge_port *p = arg; | ||
83 | |||
84 | rtnl_lock(); | ||
85 | if (netif_carrier_ok(p->dev)) { | ||
86 | u32 cost = port_cost(p->dev); | ||
87 | |||
88 | spin_lock_bh(&p->br->lock); | ||
89 | if (p->state == BR_STATE_DISABLED) { | ||
90 | p->path_cost = cost; | ||
91 | br_stp_enable_port(p); | ||
92 | } | ||
93 | spin_unlock_bh(&p->br->lock); | ||
94 | } else { | ||
95 | spin_lock_bh(&p->br->lock); | ||
96 | if (p->state != BR_STATE_DISABLED) | ||
97 | br_stp_disable_port(p); | ||
98 | spin_unlock_bh(&p->br->lock); | ||
99 | } | ||
100 | rtnl_unlock(); | ||
101 | } | ||
102 | |||
78 | static void destroy_nbp(struct net_bridge_port *p) | 103 | static void destroy_nbp(struct net_bridge_port *p) |
79 | { | 104 | { |
80 | struct net_device *dev = p->dev; | 105 | struct net_device *dev = p->dev; |
@@ -102,6 +127,9 @@ static void del_nbp(struct net_bridge_port *p) | |||
102 | dev->br_port = NULL; | 127 | dev->br_port = NULL; |
103 | dev_set_promiscuity(dev, -1); | 128 | dev_set_promiscuity(dev, -1); |
104 | 129 | ||
130 | cancel_delayed_work(&p->carrier_check); | ||
131 | flush_scheduled_work(); | ||
132 | |||
105 | spin_lock_bh(&br->lock); | 133 | spin_lock_bh(&br->lock); |
106 | br_stp_disable_port(p); | 134 | br_stp_disable_port(p); |
107 | spin_unlock_bh(&br->lock); | 135 | spin_unlock_bh(&br->lock); |
@@ -155,6 +183,7 @@ static struct net_device *new_bridge_dev(const char *name) | |||
155 | br->bridge_id.prio[1] = 0x00; | 183 | br->bridge_id.prio[1] = 0x00; |
156 | memset(br->bridge_id.addr, 0, ETH_ALEN); | 184 | memset(br->bridge_id.addr, 0, ETH_ALEN); |
157 | 185 | ||
186 | br->feature_mask = dev->features; | ||
158 | br->stp_enabled = 0; | 187 | br->stp_enabled = 0; |
159 | br->designated_root = br->bridge_id; | 188 | br->designated_root = br->bridge_id; |
160 | br->root_path_cost = 0; | 189 | br->root_path_cost = 0; |
@@ -195,10 +224,9 @@ static int find_portno(struct net_bridge *br) | |||
195 | return (index >= BR_MAX_PORTS) ? -EXFULL : index; | 224 | return (index >= BR_MAX_PORTS) ? -EXFULL : index; |
196 | } | 225 | } |
197 | 226 | ||
198 | /* called with RTNL */ | 227 | /* called with RTNL but without bridge lock */ |
199 | static struct net_bridge_port *new_nbp(struct net_bridge *br, | 228 | static struct net_bridge_port *new_nbp(struct net_bridge *br, |
200 | struct net_device *dev, | 229 | struct net_device *dev) |
201 | unsigned long cost) | ||
202 | { | 230 | { |
203 | int index; | 231 | int index; |
204 | struct net_bridge_port *p; | 232 | struct net_bridge_port *p; |
@@ -215,12 +243,13 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
215 | p->br = br; | 243 | p->br = br; |
216 | dev_hold(dev); | 244 | dev_hold(dev); |
217 | p->dev = dev; | 245 | p->dev = dev; |
218 | p->path_cost = cost; | 246 | p->path_cost = port_cost(dev); |
219 | p->priority = 0x8000 >> BR_PORT_BITS; | 247 | p->priority = 0x8000 >> BR_PORT_BITS; |
220 | dev->br_port = p; | 248 | dev->br_port = p; |
221 | p->port_no = index; | 249 | p->port_no = index; |
222 | br_init_port(p); | 250 | br_init_port(p); |
223 | p->state = BR_STATE_DISABLED; | 251 | p->state = BR_STATE_DISABLED; |
252 | INIT_WORK(&p->carrier_check, port_carrier_check, p); | ||
224 | kobject_init(&p->kobj); | 253 | kobject_init(&p->kobj); |
225 | 254 | ||
226 | return p; | 255 | return p; |
@@ -295,7 +324,7 @@ int br_del_bridge(const char *name) | |||
295 | return ret; | 324 | return ret; |
296 | } | 325 | } |
297 | 326 | ||
298 | /* Mtu of the bridge pseudo-device 1500 or the minimum of the ports */ | 327 | /* MTU of the bridge pseudo-device: ETH_DATA_LEN or the minimum of the ports */ |
299 | int br_min_mtu(const struct net_bridge *br) | 328 | int br_min_mtu(const struct net_bridge *br) |
300 | { | 329 | { |
301 | const struct net_bridge_port *p; | 330 | const struct net_bridge_port *p; |
@@ -304,7 +333,7 @@ int br_min_mtu(const struct net_bridge *br) | |||
304 | ASSERT_RTNL(); | 333 | ASSERT_RTNL(); |
305 | 334 | ||
306 | if (list_empty(&br->port_list)) | 335 | if (list_empty(&br->port_list)) |
307 | mtu = 1500; | 336 | mtu = ETH_DATA_LEN; |
308 | else { | 337 | else { |
309 | list_for_each_entry(p, &br->port_list, list) { | 338 | list_for_each_entry(p, &br->port_list, list) { |
310 | if (!mtu || p->dev->mtu < mtu) | 339 | if (!mtu || p->dev->mtu < mtu) |
@@ -322,9 +351,8 @@ void br_features_recompute(struct net_bridge *br) | |||
322 | struct net_bridge_port *p; | 351 | struct net_bridge_port *p; |
323 | unsigned long features, checksum; | 352 | unsigned long features, checksum; |
324 | 353 | ||
325 | features = NETIF_F_SG | NETIF_F_FRAGLIST | 354 | features = br->feature_mask &~ NETIF_F_IP_CSUM; |
326 | | NETIF_F_HIGHDMA | NETIF_F_TSO; | 355 | checksum = br->feature_mask & NETIF_F_IP_CSUM; |
327 | checksum = NETIF_F_IP_CSUM; /* least commmon subset */ | ||
328 | 356 | ||
329 | list_for_each_entry(p, &br->port_list, list) { | 357 | list_for_each_entry(p, &br->port_list, list) { |
330 | if (!(p->dev->features | 358 | if (!(p->dev->features |
@@ -351,7 +379,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
351 | if (dev->br_port != NULL) | 379 | if (dev->br_port != NULL) |
352 | return -EBUSY; | 380 | return -EBUSY; |
353 | 381 | ||
354 | if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev)))) | 382 | if (IS_ERR(p = new_nbp(br, dev))) |
355 | return PTR_ERR(p); | 383 | return PTR_ERR(p); |
356 | 384 | ||
357 | if ((err = br_fdb_insert(br, p, dev->dev_addr))) | 385 | 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..e3a73cead6b6 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 | ||
@@ -63,7 +68,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
63 | } | 68 | } |
64 | } | 69 | } |
65 | 70 | ||
66 | if (dest[0] & 1) { | 71 | if (is_multicast_ether_addr(dest)) { |
67 | br_flood_forward(br, skb, !passedup); | 72 | br_flood_forward(br, skb, !passedup); |
68 | if (!passedup) | 73 | if (!passedup) |
69 | br_pass_frame_up(br, skb); | 74 | br_pass_frame_up(br, skb); |
@@ -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 d8e36b775125..7cac3fb9f809 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" |
@@ -295,7 +299,7 @@ static int check_hbh_len(struct sk_buff *skb) | |||
295 | len -= 2; | 299 | len -= 2; |
296 | 300 | ||
297 | while (len > 0) { | 301 | while (len > 0) { |
298 | int optlen = raw[off+1]+2; | 302 | int optlen = skb->nh.raw[off+1]+2; |
299 | 303 | ||
300 | switch (skb->nh.raw[off]) { | 304 | switch (skb->nh.raw[off]) { |
301 | case IPV6_TLV_PAD0: | 305 | case IPV6_TLV_PAD0: |
@@ -308,18 +312,15 @@ static int check_hbh_len(struct sk_buff *skb) | |||
308 | case IPV6_TLV_JUMBO: | 312 | case IPV6_TLV_JUMBO: |
309 | if (skb->nh.raw[off+1] != 4 || (off&3) != 2) | 313 | if (skb->nh.raw[off+1] != 4 || (off&3) != 2) |
310 | goto bad; | 314 | goto bad; |
311 | |||
312 | pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); | 315 | pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); |
313 | 316 | if (pkt_len <= IPV6_MAXPLEN || | |
317 | skb->nh.ipv6h->payload_len) | ||
318 | goto bad; | ||
314 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) | 319 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) |
315 | goto bad; | 320 | goto bad; |
316 | if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { | 321 | if (pskb_trim_rcsum(skb, |
317 | if (__pskb_trim(skb, | 322 | pkt_len+sizeof(struct ipv6hdr))) |
318 | pkt_len + sizeof(struct ipv6hdr))) | 323 | goto bad; |
319 | goto bad; | ||
320 | if (skb->ip_summed == CHECKSUM_HW) | ||
321 | skb->ip_summed = CHECKSUM_NONE; | ||
322 | } | ||
323 | break; | 324 | break; |
324 | default: | 325 | default: |
325 | if (optlen > len) | 326 | if (optlen > len) |
@@ -372,6 +373,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
372 | if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) | 373 | if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) |
373 | goto inhdr_error; | 374 | goto inhdr_error; |
374 | 375 | ||
376 | nf_bridge_put(skb->nf_bridge); | ||
375 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 377 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) |
376 | return NF_DROP; | 378 | return NF_DROP; |
377 | setup_pre_routing(skb); | 379 | setup_pre_routing(skb); |
@@ -392,8 +394,9 @@ inhdr_error: | |||
392 | * target in particular. Save the original destination IP | 394 | * target in particular. Save the original destination IP |
393 | * address to be able to detect DNAT afterwards. */ | 395 | * address to be able to detect DNAT afterwards. */ |
394 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | 396 | static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, |
395 | const struct net_device *in, const struct net_device *out, | 397 | const struct net_device *in, |
396 | int (*okfn)(struct sk_buff *)) | 398 | const struct net_device *out, |
399 | int (*okfn)(struct sk_buff *)) | ||
397 | { | 400 | { |
398 | struct iphdr *iph; | 401 | struct iphdr *iph; |
399 | __u32 len; | 402 | __u32 len; |
@@ -410,8 +413,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
410 | goto out; | 413 | goto out; |
411 | 414 | ||
412 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 415 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
416 | u8 *vhdr = skb->data; | ||
413 | skb_pull(skb, VLAN_HLEN); | 417 | skb_pull(skb, VLAN_HLEN); |
414 | (skb)->nh.raw += VLAN_HLEN; | 418 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); |
419 | skb->nh.raw += VLAN_HLEN; | ||
415 | } | 420 | } |
416 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 421 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
417 | } | 422 | } |
@@ -427,8 +432,10 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
427 | goto out; | 432 | goto out; |
428 | 433 | ||
429 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 434 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { |
435 | u8 *vhdr = skb->data; | ||
430 | skb_pull(skb, VLAN_HLEN); | 436 | skb_pull(skb, VLAN_HLEN); |
431 | (skb)->nh.raw += VLAN_HLEN; | 437 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); |
438 | skb->nh.raw += VLAN_HLEN; | ||
432 | } | 439 | } |
433 | 440 | ||
434 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 441 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
@@ -455,6 +462,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
455 | skb->ip_summed = CHECKSUM_NONE; | 462 | skb->ip_summed = CHECKSUM_NONE; |
456 | } | 463 | } |
457 | 464 | ||
465 | nf_bridge_put(skb->nf_bridge); | ||
458 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 466 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) |
459 | return NF_DROP; | 467 | return NF_DROP; |
460 | setup_pre_routing(skb); | 468 | setup_pre_routing(skb); |
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 | |||
30 | typedef struct bridge_id bridge_id; | 34 | typedef struct bridge_id bridge_id; |
31 | typedef struct mac_addr mac_addr; | 35 | typedef struct mac_addr mac_addr; |
32 | typedef __u16 port_id; | 36 | typedef __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); | |||
201 | extern void br_stp_enable_port(struct net_bridge_port *p); | 207 | extern void br_stp_enable_port(struct net_bridge_port *p); |
202 | extern void br_stp_disable_port(struct net_bridge_port *p); | 208 | extern void br_stp_disable_port(struct net_bridge_port *p); |
203 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); | 209 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); |
210 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | ||
204 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 211 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
205 | u16 newprio); | 212 | u16 newprio); |
206 | extern void br_stp_set_port_priority(struct net_bridge_port *p, | 213 | extern 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 */ |
123 | static void br_stp_change_bridge_id(struct net_bridge *br, | 123 | void 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 | ||
198 | config BRIDGE_EBT_ULOG | 198 | config 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] |
58 | static void ebt_log(const struct sk_buff *skb, unsigned int hooknr, | 61 | static void |
59 | const struct net_device *in, const struct net_device *out, | 62 | ebt_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, | |||
144 | out: | 149 | out: |
145 | printk("\n"); | 150 | printk("\n"); |
146 | spin_unlock_bh(&ebt_log_lock); | 151 | spin_unlock_bh(&ebt_log_lock); |
152 | |||
153 | } | ||
154 | |||
155 | static 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 | ||
149 | static struct ebt_watcher log = | 169 | static 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 | ||
177 | static struct nf_logger ebt_log_logger = { | ||
178 | .name = "ebt_log", | ||
179 | .logfn = &ebt_log_packet, | ||
180 | .me = THIS_MODULE, | ||
181 | }; | ||
182 | |||
157 | static int __init init(void) | 183 | static 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 | ||
162 | static void __exit fini(void) | 200 | static 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 | ||
118 | static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, | 119 | static 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 */ | ||
220 | static 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 | |||
242 | static 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 | |||
219 | static int ebt_ulog_check(const char *tablename, unsigned int hookmask, | 252 | static 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 | ||
276 | static struct nf_logger ebt_ulog_logger = { | ||
277 | .name = EBT_ULOG_WATCHER, | ||
278 | .logfn = &ebt_log_packet, | ||
279 | .me = THIS_MODULE, | ||
280 | }; | ||
281 | |||
243 | static int __init init(void) | 282 | static 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]; |