diff options
Diffstat (limited to 'net/bridge')
| -rw-r--r-- | net/bridge/Kconfig | 1 | ||||
| -rw-r--r-- | net/bridge/br.c | 12 | ||||
| -rw-r--r-- | net/bridge/br_device.c | 3 | ||||
| -rw-r--r-- | net/bridge/br_fdb.c | 6 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 9 | ||||
| -rw-r--r-- | net/bridge/br_input.c | 43 | ||||
| -rw-r--r-- | net/bridge/br_netfilter.c | 225 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 6 | ||||
| -rw-r--r-- | net/bridge/br_stp_bpdu.c | 196 | ||||
| -rw-r--r-- | net/bridge/br_stp_timer.c | 47 | ||||
| -rw-r--r-- | net/bridge/br_sysfs_br.c | 49 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtables.c | 101 |
12 files changed, 398 insertions, 300 deletions
diff --git a/net/bridge/Kconfig b/net/bridge/Kconfig index db23d59746cf..12265aff7099 100644 --- a/net/bridge/Kconfig +++ b/net/bridge/Kconfig | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | config BRIDGE | 5 | config BRIDGE |
| 6 | tristate "802.1d Ethernet Bridging" | 6 | tristate "802.1d Ethernet Bridging" |
| 7 | select LLC | ||
| 7 | ---help--- | 8 | ---help--- |
| 8 | If you say Y here, then your Linux box will be able to act as an | 9 | If you say Y here, then your Linux box will be able to act as an |
| 9 | Ethernet bridge, which means that the different Ethernet segments it | 10 | Ethernet bridge, which means that the different Ethernet segments it |
diff --git a/net/bridge/br.c b/net/bridge/br.c index 188cc1ac49eb..22d806cf40ca 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
| @@ -19,13 +19,23 @@ | |||
| 19 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
| 20 | #include <linux/etherdevice.h> | 20 | #include <linux/etherdevice.h> |
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/llc.h> | ||
| 23 | #include <net/llc.h> | ||
| 22 | 24 | ||
| 23 | #include "br_private.h" | 25 | #include "br_private.h" |
| 24 | 26 | ||
| 25 | int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; | 27 | int (*br_should_route_hook) (struct sk_buff **pskb) = NULL; |
| 26 | 28 | ||
| 29 | static struct llc_sap *br_stp_sap; | ||
| 30 | |||
| 27 | static int __init br_init(void) | 31 | static int __init br_init(void) |
| 28 | { | 32 | { |
| 33 | br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv); | ||
| 34 | if (!br_stp_sap) { | ||
| 35 | printk(KERN_ERR "bridge: can't register sap for STP\n"); | ||
| 36 | return -EBUSY; | ||
| 37 | } | ||
| 38 | |||
| 29 | br_fdb_init(); | 39 | br_fdb_init(); |
| 30 | 40 | ||
| 31 | #ifdef CONFIG_BRIDGE_NETFILTER | 41 | #ifdef CONFIG_BRIDGE_NETFILTER |
| @@ -45,6 +55,8 @@ static int __init br_init(void) | |||
| 45 | 55 | ||
| 46 | static void __exit br_deinit(void) | 56 | static void __exit br_deinit(void) |
| 47 | { | 57 | { |
| 58 | llc_sap_close(br_stp_sap); | ||
| 59 | |||
| 48 | #ifdef CONFIG_BRIDGE_NETFILTER | 60 | #ifdef CONFIG_BRIDGE_NETFILTER |
| 49 | br_netfilter_fini(); | 61 | br_netfilter_fini(); |
| 50 | #endif | 62 | #endif |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 0b33a7b3a00c..0c88a2ac32c1 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -27,6 +27,7 @@ static struct net_device_stats *br_dev_get_stats(struct net_device *dev) | |||
| 27 | return &br->statistics; | 27 | return &br->statistics; |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | /* net device transmit always called with no BH (preempt_disabled) */ | ||
| 30 | int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | 31 | int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) |
| 31 | { | 32 | { |
| 32 | struct net_bridge *br = netdev_priv(dev); | 33 | struct net_bridge *br = netdev_priv(dev); |
| @@ -39,7 +40,6 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 39 | skb->mac.raw = skb->data; | 40 | skb->mac.raw = skb->data; |
| 40 | skb_pull(skb, ETH_HLEN); | 41 | skb_pull(skb, ETH_HLEN); |
| 41 | 42 | ||
| 42 | rcu_read_lock(); | ||
| 43 | if (dest[0] & 1) | 43 | if (dest[0] & 1) |
| 44 | br_flood_deliver(br, skb, 0); | 44 | br_flood_deliver(br, skb, 0); |
| 45 | else if ((dst = __br_fdb_get(br, dest)) != NULL) | 45 | else if ((dst = __br_fdb_get(br, dest)) != NULL) |
| @@ -47,7 +47,6 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 47 | else | 47 | else |
| 48 | br_flood_deliver(br, skb, 0); | 48 | br_flood_deliver(br, skb, 0); |
| 49 | 49 | ||
| 50 | rcu_read_unlock(); | ||
| 51 | return 0; | 50 | return 0; |
| 52 | } | 51 | } |
| 53 | 52 | ||
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 1f08a59b51ea..3a73b8c94271 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -341,7 +341,6 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 341 | if (hold_time(br) == 0) | 341 | if (hold_time(br) == 0) |
| 342 | return; | 342 | return; |
| 343 | 343 | ||
| 344 | rcu_read_lock(); | ||
| 345 | fdb = fdb_find(head, addr); | 344 | fdb = fdb_find(head, addr); |
| 346 | if (likely(fdb)) { | 345 | if (likely(fdb)) { |
| 347 | /* attempt to update an entry for a local interface */ | 346 | /* attempt to update an entry for a local interface */ |
| @@ -356,13 +355,12 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
| 356 | fdb->ageing_timer = jiffies; | 355 | fdb->ageing_timer = jiffies; |
| 357 | } | 356 | } |
| 358 | } else { | 357 | } else { |
| 359 | spin_lock_bh(&br->hash_lock); | 358 | spin_lock(&br->hash_lock); |
| 360 | if (!fdb_find(head, addr)) | 359 | if (!fdb_find(head, addr)) |
| 361 | fdb_create(head, source, addr, 0); | 360 | fdb_create(head, source, addr, 0); |
| 362 | /* else we lose race and someone else inserts | 361 | /* else we lose race and someone else inserts |
| 363 | * it first, don't bother updating | 362 | * it first, don't bother updating |
| 364 | */ | 363 | */ |
| 365 | spin_unlock_bh(&br->hash_lock); | 364 | spin_unlock(&br->hash_lock); |
| 366 | } | 365 | } |
| 367 | rcu_read_unlock(); | ||
| 368 | } | 366 | } |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index f36b35edd60c..59eef42d4a42 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -210,7 +210,8 @@ static struct net_device *new_bridge_dev(const char *name) | |||
| 210 | 210 | ||
| 211 | br->bridge_id.prio[0] = 0x80; | 211 | br->bridge_id.prio[0] = 0x80; |
| 212 | br->bridge_id.prio[1] = 0x00; | 212 | br->bridge_id.prio[1] = 0x00; |
| 213 | memset(br->bridge_id.addr, 0, ETH_ALEN); | 213 | |
| 214 | memcpy(br->group_addr, br_group_address, ETH_ALEN); | ||
| 214 | 215 | ||
| 215 | br->feature_mask = dev->features; | 216 | br->feature_mask = dev->features; |
| 216 | br->stp_enabled = 0; | 217 | br->stp_enabled = 0; |
| @@ -237,12 +238,11 @@ static int find_portno(struct net_bridge *br) | |||
| 237 | struct net_bridge_port *p; | 238 | struct net_bridge_port *p; |
| 238 | unsigned long *inuse; | 239 | unsigned long *inuse; |
| 239 | 240 | ||
| 240 | inuse = kmalloc(BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long), | 241 | inuse = kcalloc(BITS_TO_LONGS(BR_MAX_PORTS), sizeof(unsigned long), |
| 241 | GFP_KERNEL); | 242 | GFP_KERNEL); |
| 242 | if (!inuse) | 243 | if (!inuse) |
| 243 | return -ENOMEM; | 244 | return -ENOMEM; |
| 244 | 245 | ||
| 245 | memset(inuse, 0, BITS_TO_LONGS(BR_MAX_PORTS)*sizeof(unsigned long)); | ||
| 246 | set_bit(0, inuse); /* zero is reserved */ | 246 | set_bit(0, inuse); /* zero is reserved */ |
| 247 | list_for_each_entry(p, &br->port_list, list) { | 247 | list_for_each_entry(p, &br->port_list, list) { |
| 248 | set_bit(p->port_no, inuse); | 248 | set_bit(p->port_no, inuse); |
| @@ -264,11 +264,10 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
| 264 | if (index < 0) | 264 | if (index < 0) |
| 265 | return ERR_PTR(index); | 265 | return ERR_PTR(index); |
| 266 | 266 | ||
| 267 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 267 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
| 268 | if (p == NULL) | 268 | if (p == NULL) |
| 269 | return ERR_PTR(-ENOMEM); | 269 | return ERR_PTR(-ENOMEM); |
| 270 | 270 | ||
| 271 | memset(p, 0, sizeof(*p)); | ||
| 272 | p->br = br; | 271 | p->br = br; |
| 273 | dev_hold(dev); | 272 | dev_hold(dev); |
| 274 | p->dev = dev; | 273 | p->dev = dev; |
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 4eef83755315..b7766562d72c 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -19,13 +19,8 @@ | |||
| 19 | #include <linux/netfilter_bridge.h> | 19 | #include <linux/netfilter_bridge.h> |
| 20 | #include "br_private.h" | 20 | #include "br_private.h" |
| 21 | 21 | ||
| 22 | const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | 22 | /* Bridge group multicast address 802.1d (pg 51). */ |
| 23 | 23 | const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | |
| 24 | static int br_pass_frame_up_finish(struct sk_buff *skb) | ||
| 25 | { | ||
| 26 | netif_receive_skb(skb); | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | 24 | ||
| 30 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | 25 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) |
| 31 | { | 26 | { |
| @@ -38,7 +33,7 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | |||
| 38 | skb->dev = br->dev; | 33 | skb->dev = br->dev; |
| 39 | 34 | ||
| 40 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, | 35 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, |
| 41 | br_pass_frame_up_finish); | 36 | netif_receive_skb); |
| 42 | } | 37 | } |
| 43 | 38 | ||
| 44 | /* note: already called with rcu_read_lock (preempt_disabled) */ | 39 | /* note: already called with rcu_read_lock (preempt_disabled) */ |
| @@ -100,6 +95,25 @@ drop: | |||
| 100 | goto out; | 95 | goto out; |
| 101 | } | 96 | } |
| 102 | 97 | ||
| 98 | /* note: already called with rcu_read_lock (preempt_disabled) */ | ||
| 99 | static int br_handle_local_finish(struct sk_buff *skb) | ||
| 100 | { | ||
| 101 | struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); | ||
| 102 | |||
| 103 | if (p && p->state != BR_STATE_DISABLED) | ||
| 104 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source); | ||
| 105 | |||
| 106 | return 0; /* process further */ | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Does address match the link local multicast address. | ||
| 110 | * 01:80:c2:00:00:0X | ||
| 111 | */ | ||
| 112 | static inline int is_link_local(const unsigned char *dest) | ||
| 113 | { | ||
| 114 | return memcmp(dest, br_group_address, 5) == 0 && (dest[5] & 0xf0) == 0; | ||
| 115 | } | ||
| 116 | |||
| 103 | /* | 117 | /* |
| 104 | * Called via br_handle_frame_hook. | 118 | * Called via br_handle_frame_hook. |
| 105 | * Return 0 if *pskb should be processed furthur | 119 | * Return 0 if *pskb should be processed furthur |
| @@ -117,15 +131,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) | |||
| 117 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 131 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
| 118 | goto err; | 132 | goto err; |
| 119 | 133 | ||
| 120 | if (p->br->stp_enabled && | 134 | if (unlikely(is_link_local(dest))) { |
| 121 | !memcmp(dest, bridge_ula, 5) && | 135 | skb->pkt_type = PACKET_HOST; |
| 122 | !(dest[5] & 0xF0)) { | 136 | return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
| 123 | if (!dest[5]) { | 137 | NULL, br_handle_local_finish) != 0; |
| 124 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | ||
| 125 | NULL, br_stp_handle_bpdu); | ||
| 126 | return 1; | ||
| 127 | } | ||
| 128 | goto err; | ||
| 129 | } | 138 | } |
| 130 | 139 | ||
| 131 | if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { | 140 | if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e060aad8624d..f29450b788be 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -61,15 +61,25 @@ static int brnf_filter_vlan_tagged = 1; | |||
| 61 | #define brnf_filter_vlan_tagged 1 | 61 | #define brnf_filter_vlan_tagged 1 |
| 62 | #endif | 62 | #endif |
| 63 | 63 | ||
| 64 | #define IS_VLAN_IP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ | 64 | static __be16 inline vlan_proto(const struct sk_buff *skb) |
| 65 | hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP) && \ | 65 | { |
| 66 | brnf_filter_vlan_tagged) | 66 | return vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; |
| 67 | #define IS_VLAN_IPV6 (skb->protocol == __constant_htons(ETH_P_8021Q) && \ | 67 | } |
| 68 | hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_IPV6) && \ | 68 | |
| 69 | brnf_filter_vlan_tagged) | 69 | #define IS_VLAN_IP(skb) \ |
| 70 | #define IS_VLAN_ARP (skb->protocol == __constant_htons(ETH_P_8021Q) && \ | 70 | (skb->protocol == htons(ETH_P_8021Q) && \ |
| 71 | hdr->h_vlan_encapsulated_proto == __constant_htons(ETH_P_ARP) && \ | 71 | vlan_proto(skb) == htons(ETH_P_IP) && \ |
| 72 | brnf_filter_vlan_tagged) | 72 | brnf_filter_vlan_tagged) |
| 73 | |||
| 74 | #define IS_VLAN_IPV6(skb) \ | ||
| 75 | (skb->protocol == htons(ETH_P_8021Q) && \ | ||
| 76 | vlan_proto(skb) == htons(ETH_P_IPV6) &&\ | ||
| 77 | brnf_filter_vlan_tagged) | ||
| 78 | |||
| 79 | #define IS_VLAN_ARP(skb) \ | ||
| 80 | (skb->protocol == htons(ETH_P_8021Q) && \ | ||
| 81 | vlan_proto(skb) == htons(ETH_P_ARP) && \ | ||
| 82 | brnf_filter_vlan_tagged) | ||
| 73 | 83 | ||
| 74 | /* We need these fake structures to make netfilter happy -- | 84 | /* We need these fake structures to make netfilter happy -- |
| 75 | * lots of places assume that skb->dst != NULL, which isn't | 85 | * lots of places assume that skb->dst != NULL, which isn't |
| @@ -103,6 +113,25 @@ static inline struct net_device *bridge_parent(const struct net_device *dev) | |||
| 103 | return port ? port->br->dev : NULL; | 113 | return port ? port->br->dev : NULL; |
| 104 | } | 114 | } |
| 105 | 115 | ||
| 116 | static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) | ||
| 117 | { | ||
| 118 | skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); | ||
| 119 | if (likely(skb->nf_bridge)) | ||
| 120 | atomic_set(&(skb->nf_bridge->use), 1); | ||
| 121 | |||
| 122 | return skb->nf_bridge; | ||
| 123 | } | ||
| 124 | |||
| 125 | static inline void nf_bridge_save_header(struct sk_buff *skb) | ||
| 126 | { | ||
| 127 | int header_size = 16; | ||
| 128 | |||
| 129 | if (skb->protocol == htons(ETH_P_8021Q)) | ||
| 130 | header_size = 18; | ||
| 131 | |||
| 132 | memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); | ||
| 133 | } | ||
| 134 | |||
| 106 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ | 135 | /* PF_BRIDGE/PRE_ROUTING *********************************************/ |
| 107 | /* Undo the changes made for ip6tables PREROUTING and continue the | 136 | /* Undo the changes made for ip6tables PREROUTING and continue the |
| 108 | * bridge PRE_ROUTING hook. */ | 137 | * bridge PRE_ROUTING hook. */ |
| @@ -120,7 +149,7 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
| 120 | dst_hold(skb->dst); | 149 | dst_hold(skb->dst); |
| 121 | 150 | ||
| 122 | skb->dev = nf_bridge->physindev; | 151 | skb->dev = nf_bridge->physindev; |
| 123 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 152 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 124 | skb_push(skb, VLAN_HLEN); | 153 | skb_push(skb, VLAN_HLEN); |
| 125 | skb->nh.raw -= VLAN_HLEN; | 154 | skb->nh.raw -= VLAN_HLEN; |
| 126 | } | 155 | } |
| @@ -136,7 +165,7 @@ static void __br_dnat_complain(void) | |||
| 136 | 165 | ||
| 137 | if (jiffies - last_complaint >= 5 * HZ) { | 166 | if (jiffies - last_complaint >= 5 * HZ) { |
| 138 | printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " | 167 | printk(KERN_WARNING "Performing cross-bridge DNAT requires IP " |
| 139 | "forwarding to be enabled\n"); | 168 | "forwarding to be enabled\n"); |
| 140 | last_complaint = jiffies; | 169 | last_complaint = jiffies; |
| 141 | } | 170 | } |
| 142 | } | 171 | } |
| @@ -196,7 +225,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | |||
| 196 | if (!skb->dev) | 225 | if (!skb->dev) |
| 197 | kfree_skb(skb); | 226 | kfree_skb(skb); |
| 198 | else { | 227 | else { |
| 199 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 228 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 200 | skb_pull(skb, VLAN_HLEN); | 229 | skb_pull(skb, VLAN_HLEN); |
| 201 | skb->nh.raw += VLAN_HLEN; | 230 | skb->nh.raw += VLAN_HLEN; |
| 202 | } | 231 | } |
| @@ -218,12 +247,17 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
| 218 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 247 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
| 219 | 248 | ||
| 220 | if (dnat_took_place(skb)) { | 249 | if (dnat_took_place(skb)) { |
| 221 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, | 250 | if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) { |
| 222 | dev)) { | ||
| 223 | struct rtable *rt; | 251 | struct rtable *rt; |
| 224 | struct flowi fl = { .nl_u = | 252 | struct flowi fl = { |
| 225 | { .ip4_u = { .daddr = iph->daddr, .saddr = 0 , | 253 | .nl_u = { |
| 226 | .tos = RT_TOS(iph->tos)} }, .proto = 0}; | 254 | .ip4_u = { |
| 255 | .daddr = iph->daddr, | ||
| 256 | .saddr = 0, | ||
| 257 | .tos = RT_TOS(iph->tos) }, | ||
| 258 | }, | ||
| 259 | .proto = 0, | ||
| 260 | }; | ||
| 227 | 261 | ||
| 228 | if (!ip_route_output_key(&rt, &fl)) { | 262 | if (!ip_route_output_key(&rt, &fl)) { |
| 229 | /* - Bridged-and-DNAT'ed traffic doesn't | 263 | /* - Bridged-and-DNAT'ed traffic doesn't |
| @@ -247,7 +281,7 @@ bridged_dnat: | |||
| 247 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; | 281 | nf_bridge->mask |= BRNF_BRIDGED_DNAT; |
| 248 | skb->dev = nf_bridge->physindev; | 282 | skb->dev = nf_bridge->physindev; |
| 249 | if (skb->protocol == | 283 | if (skb->protocol == |
| 250 | __constant_htons(ETH_P_8021Q)) { | 284 | htons(ETH_P_8021Q)) { |
| 251 | skb_push(skb, VLAN_HLEN); | 285 | skb_push(skb, VLAN_HLEN); |
| 252 | skb->nh.raw -= VLAN_HLEN; | 286 | skb->nh.raw -= VLAN_HLEN; |
| 253 | } | 287 | } |
| @@ -257,8 +291,7 @@ bridged_dnat: | |||
| 257 | 1); | 291 | 1); |
| 258 | return 0; | 292 | return 0; |
| 259 | } | 293 | } |
| 260 | memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, | 294 | memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, ETH_ALEN); |
| 261 | ETH_ALEN); | ||
| 262 | skb->pkt_type = PACKET_HOST; | 295 | skb->pkt_type = PACKET_HOST; |
| 263 | } | 296 | } |
| 264 | } else { | 297 | } else { |
| @@ -267,7 +300,7 @@ bridged_dnat: | |||
| 267 | } | 300 | } |
| 268 | 301 | ||
| 269 | skb->dev = nf_bridge->physindev; | 302 | skb->dev = nf_bridge->physindev; |
| 270 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 303 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 271 | skb_push(skb, VLAN_HLEN); | 304 | skb_push(skb, VLAN_HLEN); |
| 272 | skb->nh.raw -= VLAN_HLEN; | 305 | skb->nh.raw -= VLAN_HLEN; |
| 273 | } | 306 | } |
| @@ -297,10 +330,10 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb) | |||
| 297 | /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ | 330 | /* We only check the length. A bridge shouldn't do any hop-by-hop stuff anyway */ |
| 298 | static int check_hbh_len(struct sk_buff *skb) | 331 | static int check_hbh_len(struct sk_buff *skb) |
| 299 | { | 332 | { |
| 300 | unsigned char *raw = (u8*)(skb->nh.ipv6h+1); | 333 | unsigned char *raw = (u8 *) (skb->nh.ipv6h + 1); |
| 301 | u32 pkt_len; | 334 | u32 pkt_len; |
| 302 | int off = raw - skb->nh.raw; | 335 | int off = raw - skb->nh.raw; |
| 303 | int len = (raw[1]+1)<<3; | 336 | int len = (raw[1] + 1) << 3; |
| 304 | 337 | ||
| 305 | if ((raw + len) - skb->data > skb_headlen(skb)) | 338 | if ((raw + len) - skb->data > skb_headlen(skb)) |
| 306 | goto bad; | 339 | goto bad; |
| @@ -309,7 +342,7 @@ static int check_hbh_len(struct sk_buff *skb) | |||
| 309 | len -= 2; | 342 | len -= 2; |
| 310 | 343 | ||
| 311 | while (len > 0) { | 344 | while (len > 0) { |
| 312 | int optlen = skb->nh.raw[off+1]+2; | 345 | int optlen = skb->nh.raw[off + 1] + 2; |
| 313 | 346 | ||
| 314 | switch (skb->nh.raw[off]) { | 347 | switch (skb->nh.raw[off]) { |
| 315 | case IPV6_TLV_PAD0: | 348 | case IPV6_TLV_PAD0: |
| @@ -320,16 +353,16 @@ static int check_hbh_len(struct sk_buff *skb) | |||
| 320 | break; | 353 | break; |
| 321 | 354 | ||
| 322 | case IPV6_TLV_JUMBO: | 355 | case IPV6_TLV_JUMBO: |
| 323 | if (skb->nh.raw[off+1] != 4 || (off&3) != 2) | 356 | if (skb->nh.raw[off + 1] != 4 || (off & 3) != 2) |
| 324 | goto bad; | 357 | goto bad; |
| 325 | pkt_len = ntohl(*(u32*)(skb->nh.raw+off+2)); | 358 | pkt_len = ntohl(*(u32 *) (skb->nh.raw + off + 2)); |
| 326 | if (pkt_len <= IPV6_MAXPLEN || | 359 | if (pkt_len <= IPV6_MAXPLEN || |
| 327 | skb->nh.ipv6h->payload_len) | 360 | skb->nh.ipv6h->payload_len) |
| 328 | goto bad; | 361 | goto bad; |
| 329 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) | 362 | if (pkt_len > skb->len - sizeof(struct ipv6hdr)) |
| 330 | goto bad; | 363 | goto bad; |
| 331 | if (pskb_trim_rcsum(skb, | 364 | if (pskb_trim_rcsum(skb, |
| 332 | pkt_len+sizeof(struct ipv6hdr))) | 365 | pkt_len + sizeof(struct ipv6hdr))) |
| 333 | goto bad; | 366 | goto bad; |
| 334 | break; | 367 | break; |
| 335 | default: | 368 | default: |
| @@ -350,12 +383,13 @@ bad: | |||
| 350 | /* Replicate the checks that IPv6 does on packet reception and pass the packet | 383 | /* Replicate the checks that IPv6 does on packet reception and pass the packet |
| 351 | * to ip6tables, which doesn't support NAT, so things are fairly simple. */ | 384 | * to ip6tables, which doesn't support NAT, so things are fairly simple. */ |
| 352 | static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | 385 | static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, |
| 353 | struct sk_buff *skb, const struct net_device *in, | 386 | struct sk_buff *skb, |
| 354 | const struct net_device *out, int (*okfn)(struct sk_buff *)) | 387 | const struct net_device *in, |
| 388 | const struct net_device *out, | ||
| 389 | int (*okfn)(struct sk_buff *)) | ||
| 355 | { | 390 | { |
| 356 | struct ipv6hdr *hdr; | 391 | struct ipv6hdr *hdr; |
| 357 | u32 pkt_len; | 392 | u32 pkt_len; |
| 358 | struct nf_bridge_info *nf_bridge; | ||
| 359 | 393 | ||
| 360 | if (skb->len < sizeof(struct ipv6hdr)) | 394 | if (skb->len < sizeof(struct ipv6hdr)) |
| 361 | goto inhdr_error; | 395 | goto inhdr_error; |
| @@ -381,10 +415,10 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
| 381 | } | 415 | } |
| 382 | } | 416 | } |
| 383 | if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) | 417 | if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) |
| 384 | goto inhdr_error; | 418 | goto inhdr_error; |
| 385 | 419 | ||
| 386 | nf_bridge_put(skb->nf_bridge); | 420 | nf_bridge_put(skb->nf_bridge); |
| 387 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 421 | if (!nf_bridge_alloc(skb)) |
| 388 | return NF_DROP; | 422 | return NF_DROP; |
| 389 | if (!setup_pre_routing(skb)) | 423 | if (!setup_pre_routing(skb)) |
| 390 | return NF_DROP; | 424 | return NF_DROP; |
| @@ -412,10 +446,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 412 | struct iphdr *iph; | 446 | struct iphdr *iph; |
| 413 | __u32 len; | 447 | __u32 len; |
| 414 | struct sk_buff *skb = *pskb; | 448 | struct sk_buff *skb = *pskb; |
| 415 | struct nf_bridge_info *nf_bridge; | ||
| 416 | struct vlan_ethhdr *hdr = vlan_eth_hdr(*pskb); | ||
| 417 | 449 | ||
| 418 | if (skb->protocol == __constant_htons(ETH_P_IPV6) || IS_VLAN_IPV6) { | 450 | if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb)) { |
| 419 | #ifdef CONFIG_SYSCTL | 451 | #ifdef CONFIG_SYSCTL |
| 420 | if (!brnf_call_ip6tables) | 452 | if (!brnf_call_ip6tables) |
| 421 | return NF_ACCEPT; | 453 | return NF_ACCEPT; |
| @@ -423,10 +455,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 423 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) | 455 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) |
| 424 | goto out; | 456 | goto out; |
| 425 | 457 | ||
| 426 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 458 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 427 | u8 *vhdr = skb->data; | 459 | skb_pull_rcsum(skb, VLAN_HLEN); |
| 428 | skb_pull(skb, VLAN_HLEN); | ||
| 429 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
| 430 | skb->nh.raw += VLAN_HLEN; | 460 | skb->nh.raw += VLAN_HLEN; |
| 431 | } | 461 | } |
| 432 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); | 462 | return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn); |
| @@ -436,16 +466,14 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 436 | return NF_ACCEPT; | 466 | return NF_ACCEPT; |
| 437 | #endif | 467 | #endif |
| 438 | 468 | ||
| 439 | if (skb->protocol != __constant_htons(ETH_P_IP) && !IS_VLAN_IP) | 469 | if (skb->protocol != htons(ETH_P_IP) && !IS_VLAN_IP(skb)) |
| 440 | return NF_ACCEPT; | 470 | return NF_ACCEPT; |
| 441 | 471 | ||
| 442 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) | 472 | if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL) |
| 443 | goto out; | 473 | goto out; |
| 444 | 474 | ||
| 445 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 475 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 446 | u8 *vhdr = skb->data; | 476 | skb_pull_rcsum(skb, VLAN_HLEN); |
| 447 | skb_pull(skb, VLAN_HLEN); | ||
| 448 | skb_postpull_rcsum(skb, vhdr, VLAN_HLEN); | ||
| 449 | skb->nh.raw += VLAN_HLEN; | 477 | skb->nh.raw += VLAN_HLEN; |
| 450 | } | 478 | } |
| 451 | 479 | ||
| @@ -456,15 +484,15 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 456 | if (iph->ihl < 5 || iph->version != 4) | 484 | if (iph->ihl < 5 || iph->version != 4) |
| 457 | goto inhdr_error; | 485 | goto inhdr_error; |
| 458 | 486 | ||
| 459 | if (!pskb_may_pull(skb, 4*iph->ihl)) | 487 | if (!pskb_may_pull(skb, 4 * iph->ihl)) |
| 460 | goto inhdr_error; | 488 | goto inhdr_error; |
| 461 | 489 | ||
| 462 | iph = skb->nh.iph; | 490 | iph = skb->nh.iph; |
| 463 | if (ip_fast_csum((__u8 *)iph, iph->ihl) != 0) | 491 | if (ip_fast_csum((__u8 *) iph, iph->ihl) != 0) |
| 464 | goto inhdr_error; | 492 | goto inhdr_error; |
| 465 | 493 | ||
| 466 | len = ntohs(iph->tot_len); | 494 | len = ntohs(iph->tot_len); |
| 467 | if (skb->len < len || len < 4*iph->ihl) | 495 | if (skb->len < len || len < 4 * iph->ihl) |
| 468 | goto inhdr_error; | 496 | goto inhdr_error; |
| 469 | 497 | ||
| 470 | if (skb->len > len) { | 498 | if (skb->len > len) { |
| @@ -473,8 +501,8 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 473 | skb->ip_summed = CHECKSUM_NONE; | 501 | skb->ip_summed = CHECKSUM_NONE; |
| 474 | } | 502 | } |
| 475 | 503 | ||
| 476 | nf_bridge_put(skb->nf_bridge); | 504 | nf_bridge_put(skb->nf_bridge); |
| 477 | if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) | 505 | if (!nf_bridge_alloc(skb)) |
| 478 | return NF_DROP; | 506 | return NF_DROP; |
| 479 | if (!setup_pre_routing(skb)) | 507 | if (!setup_pre_routing(skb)) |
| 480 | return NF_DROP; | 508 | return NF_DROP; |
| @@ -486,7 +514,7 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 486 | return NF_STOLEN; | 514 | return NF_STOLEN; |
| 487 | 515 | ||
| 488 | inhdr_error: | 516 | inhdr_error: |
| 489 | // IP_INC_STATS_BH(IpInHdrErrors); | 517 | // IP_INC_STATS_BH(IpInHdrErrors); |
| 490 | out: | 518 | out: |
| 491 | return NF_DROP; | 519 | return NF_DROP; |
| 492 | } | 520 | } |
| @@ -500,8 +528,9 @@ out: | |||
| 500 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will | 528 | * register an IPv4 PRE_ROUTING 'sabotage' hook that will |
| 501 | * prevent this from happening. */ | 529 | * prevent this from happening. */ |
| 502 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, | 530 | static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, |
| 503 | const struct net_device *in, const struct net_device *out, | 531 | const struct net_device *in, |
| 504 | int (*okfn)(struct sk_buff *)) | 532 | const struct net_device *out, |
| 533 | int (*okfn)(struct sk_buff *)) | ||
| 505 | { | 534 | { |
| 506 | struct sk_buff *skb = *pskb; | 535 | struct sk_buff *skb = *pskb; |
| 507 | 536 | ||
| @@ -513,15 +542,13 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff **pskb, | |||
| 513 | return NF_ACCEPT; | 542 | return NF_ACCEPT; |
| 514 | } | 543 | } |
| 515 | 544 | ||
| 516 | |||
| 517 | /* PF_BRIDGE/FORWARD *************************************************/ | 545 | /* PF_BRIDGE/FORWARD *************************************************/ |
| 518 | static int br_nf_forward_finish(struct sk_buff *skb) | 546 | static int br_nf_forward_finish(struct sk_buff *skb) |
| 519 | { | 547 | { |
| 520 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 548 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
| 521 | struct net_device *in; | 549 | struct net_device *in; |
| 522 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 523 | 550 | ||
| 524 | if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) { | 551 | if (skb->protocol != htons(ETH_P_ARP) && !IS_VLAN_ARP(skb)) { |
| 525 | in = nf_bridge->physindev; | 552 | in = nf_bridge->physindev; |
| 526 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | 553 | if (nf_bridge->mask & BRNF_PKT_TYPE) { |
| 527 | skb->pkt_type = PACKET_OTHERHOST; | 554 | skb->pkt_type = PACKET_OTHERHOST; |
| @@ -530,12 +557,12 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
| 530 | } else { | 557 | } else { |
| 531 | in = *((struct net_device **)(skb->cb)); | 558 | in = *((struct net_device **)(skb->cb)); |
| 532 | } | 559 | } |
| 533 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 560 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 534 | skb_push(skb, VLAN_HLEN); | 561 | skb_push(skb, VLAN_HLEN); |
| 535 | skb->nh.raw -= VLAN_HLEN; | 562 | skb->nh.raw -= VLAN_HLEN; |
| 536 | } | 563 | } |
| 537 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, | 564 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_FORWARD, skb, in, |
| 538 | skb->dev, br_forward_finish, 1); | 565 | skb->dev, br_forward_finish, 1); |
| 539 | return 0; | 566 | return 0; |
| 540 | } | 567 | } |
| 541 | 568 | ||
| @@ -545,12 +572,12 @@ static int br_nf_forward_finish(struct sk_buff *skb) | |||
| 545 | * because of the physdev module. For ARP, indev and outdev are the | 572 | * because of the physdev module. For ARP, indev and outdev are the |
| 546 | * bridge ports. */ | 573 | * bridge ports. */ |
| 547 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | 574 | static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, |
| 548 | const struct net_device *in, const struct net_device *out, | 575 | const struct net_device *in, |
| 549 | int (*okfn)(struct sk_buff *)) | 576 | const struct net_device *out, |
| 577 | int (*okfn)(struct sk_buff *)) | ||
| 550 | { | 578 | { |
| 551 | struct sk_buff *skb = *pskb; | 579 | struct sk_buff *skb = *pskb; |
| 552 | struct nf_bridge_info *nf_bridge; | 580 | struct nf_bridge_info *nf_bridge; |
| 553 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 554 | struct net_device *parent; | 581 | struct net_device *parent; |
| 555 | int pf; | 582 | int pf; |
| 556 | 583 | ||
| @@ -561,12 +588,12 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
| 561 | if (!parent) | 588 | if (!parent) |
| 562 | return NF_DROP; | 589 | return NF_DROP; |
| 563 | 590 | ||
| 564 | if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) | 591 | if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) |
| 565 | pf = PF_INET; | 592 | pf = PF_INET; |
| 566 | else | 593 | else |
| 567 | pf = PF_INET6; | 594 | pf = PF_INET6; |
| 568 | 595 | ||
| 569 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 596 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 570 | skb_pull(*pskb, VLAN_HLEN); | 597 | skb_pull(*pskb, VLAN_HLEN); |
| 571 | (*pskb)->nh.raw += VLAN_HLEN; | 598 | (*pskb)->nh.raw += VLAN_HLEN; |
| 572 | } | 599 | } |
| @@ -588,11 +615,11 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, | |||
| 588 | } | 615 | } |
| 589 | 616 | ||
| 590 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | 617 | static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, |
| 591 | const struct net_device *in, const struct net_device *out, | 618 | const struct net_device *in, |
| 592 | int (*okfn)(struct sk_buff *)) | 619 | const struct net_device *out, |
| 620 | int (*okfn)(struct sk_buff *)) | ||
| 593 | { | 621 | { |
| 594 | struct sk_buff *skb = *pskb; | 622 | struct sk_buff *skb = *pskb; |
| 595 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 596 | struct net_device **d = (struct net_device **)(skb->cb); | 623 | struct net_device **d = (struct net_device **)(skb->cb); |
| 597 | 624 | ||
| 598 | #ifdef CONFIG_SYSCTL | 625 | #ifdef CONFIG_SYSCTL |
| @@ -600,15 +627,15 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
| 600 | return NF_ACCEPT; | 627 | return NF_ACCEPT; |
| 601 | #endif | 628 | #endif |
| 602 | 629 | ||
| 603 | if (skb->protocol != __constant_htons(ETH_P_ARP)) { | 630 | if (skb->protocol != htons(ETH_P_ARP)) { |
| 604 | if (!IS_VLAN_ARP) | 631 | if (!IS_VLAN_ARP(skb)) |
| 605 | return NF_ACCEPT; | 632 | return NF_ACCEPT; |
| 606 | skb_pull(*pskb, VLAN_HLEN); | 633 | skb_pull(*pskb, VLAN_HLEN); |
| 607 | (*pskb)->nh.raw += VLAN_HLEN; | 634 | (*pskb)->nh.raw += VLAN_HLEN; |
| 608 | } | 635 | } |
| 609 | 636 | ||
| 610 | if (skb->nh.arph->ar_pln != 4) { | 637 | if (skb->nh.arph->ar_pln != 4) { |
| 611 | if (IS_VLAN_ARP) { | 638 | if (IS_VLAN_ARP(skb)) { |
| 612 | skb_push(*pskb, VLAN_HLEN); | 639 | skb_push(*pskb, VLAN_HLEN); |
| 613 | (*pskb)->nh.raw -= VLAN_HLEN; | 640 | (*pskb)->nh.raw -= VLAN_HLEN; |
| 614 | } | 641 | } |
| @@ -621,17 +648,16 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, | |||
| 621 | return NF_STOLEN; | 648 | return NF_STOLEN; |
| 622 | } | 649 | } |
| 623 | 650 | ||
| 624 | |||
| 625 | /* PF_BRIDGE/LOCAL_OUT ***********************************************/ | 651 | /* PF_BRIDGE/LOCAL_OUT ***********************************************/ |
| 626 | static int br_nf_local_out_finish(struct sk_buff *skb) | 652 | static int br_nf_local_out_finish(struct sk_buff *skb) |
| 627 | { | 653 | { |
| 628 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 654 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 629 | skb_push(skb, VLAN_HLEN); | 655 | skb_push(skb, VLAN_HLEN); |
| 630 | skb->nh.raw -= VLAN_HLEN; | 656 | skb->nh.raw -= VLAN_HLEN; |
| 631 | } | 657 | } |
| 632 | 658 | ||
| 633 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 659 | NF_HOOK_THRESH(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
| 634 | br_forward_finish, NF_BR_PRI_FIRST + 1); | 660 | br_forward_finish, NF_BR_PRI_FIRST + 1); |
| 635 | 661 | ||
| 636 | return 0; | 662 | return 0; |
| 637 | } | 663 | } |
| @@ -657,19 +683,19 @@ static int br_nf_local_out_finish(struct sk_buff *skb) | |||
| 657 | * even routed packets that didn't arrive on a bridge interface have their | 683 | * even routed packets that didn't arrive on a bridge interface have their |
| 658 | * nf_bridge->physindev set. */ | 684 | * nf_bridge->physindev set. */ |
| 659 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | 685 | static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, |
| 660 | const struct net_device *in, const struct net_device *out, | 686 | const struct net_device *in, |
| 661 | int (*okfn)(struct sk_buff *)) | 687 | const struct net_device *out, |
| 688 | int (*okfn)(struct sk_buff *)) | ||
| 662 | { | 689 | { |
| 663 | struct net_device *realindev, *realoutdev; | 690 | struct net_device *realindev, *realoutdev; |
| 664 | struct sk_buff *skb = *pskb; | 691 | struct sk_buff *skb = *pskb; |
| 665 | struct nf_bridge_info *nf_bridge; | 692 | struct nf_bridge_info *nf_bridge; |
| 666 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 667 | int pf; | 693 | int pf; |
| 668 | 694 | ||
| 669 | if (!skb->nf_bridge) | 695 | if (!skb->nf_bridge) |
| 670 | return NF_ACCEPT; | 696 | return NF_ACCEPT; |
| 671 | 697 | ||
| 672 | if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) | 698 | if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) |
| 673 | pf = PF_INET; | 699 | pf = PF_INET; |
| 674 | else | 700 | else |
| 675 | pf = PF_INET6; | 701 | pf = PF_INET6; |
| @@ -695,7 +721,7 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | |||
| 695 | skb->pkt_type = PACKET_OTHERHOST; | 721 | skb->pkt_type = PACKET_OTHERHOST; |
| 696 | nf_bridge->mask ^= BRNF_PKT_TYPE; | 722 | nf_bridge->mask ^= BRNF_PKT_TYPE; |
| 697 | } | 723 | } |
| 698 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 724 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 699 | skb_push(skb, VLAN_HLEN); | 725 | skb_push(skb, VLAN_HLEN); |
| 700 | skb->nh.raw -= VLAN_HLEN; | 726 | skb->nh.raw -= VLAN_HLEN; |
| 701 | } | 727 | } |
| @@ -713,14 +739,14 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, | |||
| 713 | if (nf_bridge->netoutdev) | 739 | if (nf_bridge->netoutdev) |
| 714 | realoutdev = nf_bridge->netoutdev; | 740 | realoutdev = nf_bridge->netoutdev; |
| 715 | #endif | 741 | #endif |
| 716 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 742 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 717 | skb_pull(skb, VLAN_HLEN); | 743 | skb_pull(skb, VLAN_HLEN); |
| 718 | (*pskb)->nh.raw += VLAN_HLEN; | 744 | (*pskb)->nh.raw += VLAN_HLEN; |
| 719 | } | 745 | } |
| 720 | /* IP forwarded traffic has a physindev, locally | 746 | /* IP forwarded traffic has a physindev, locally |
| 721 | * generated traffic hasn't. */ | 747 | * generated traffic hasn't. */ |
| 722 | if (realindev != NULL) { | 748 | if (realindev != NULL) { |
| 723 | if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT) ) { | 749 | if (!(nf_bridge->mask & BRNF_DONT_TAKE_PARENT)) { |
| 724 | struct net_device *parent = bridge_parent(realindev); | 750 | struct net_device *parent = bridge_parent(realindev); |
| 725 | if (parent) | 751 | if (parent) |
| 726 | realindev = parent; | 752 | realindev = parent; |
| @@ -742,12 +768,12 @@ out: | |||
| 742 | 768 | ||
| 743 | /* PF_BRIDGE/POST_ROUTING ********************************************/ | 769 | /* PF_BRIDGE/POST_ROUTING ********************************************/ |
| 744 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | 770 | static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, |
| 745 | const struct net_device *in, const struct net_device *out, | 771 | const struct net_device *in, |
| 746 | int (*okfn)(struct sk_buff *)) | 772 | const struct net_device *out, |
| 773 | int (*okfn)(struct sk_buff *)) | ||
| 747 | { | 774 | { |
| 748 | struct sk_buff *skb = *pskb; | 775 | struct sk_buff *skb = *pskb; |
| 749 | struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; | 776 | struct nf_bridge_info *nf_bridge = (*pskb)->nf_bridge; |
| 750 | struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); | ||
| 751 | struct net_device *realoutdev = bridge_parent(skb->dev); | 777 | struct net_device *realoutdev = bridge_parent(skb->dev); |
| 752 | int pf; | 778 | int pf; |
| 753 | 779 | ||
| @@ -756,7 +782,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 756 | * keep the check just to be sure... */ | 782 | * keep the check just to be sure... */ |
| 757 | if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { | 783 | if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { |
| 758 | printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " | 784 | printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " |
| 759 | "bad mac.raw pointer."); | 785 | "bad mac.raw pointer."); |
| 760 | goto print_error; | 786 | goto print_error; |
| 761 | } | 787 | } |
| 762 | #endif | 788 | #endif |
| @@ -767,7 +793,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 767 | if (!realoutdev) | 793 | if (!realoutdev) |
| 768 | return NF_DROP; | 794 | return NF_DROP; |
| 769 | 795 | ||
| 770 | if (skb->protocol == __constant_htons(ETH_P_IP) || IS_VLAN_IP) | 796 | if (skb->protocol == htons(ETH_P_IP) || IS_VLAN_IP(skb)) |
| 771 | pf = PF_INET; | 797 | pf = PF_INET; |
| 772 | else | 798 | else |
| 773 | pf = PF_INET6; | 799 | pf = PF_INET6; |
| @@ -786,7 +812,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 786 | nf_bridge->mask |= BRNF_PKT_TYPE; | 812 | nf_bridge->mask |= BRNF_PKT_TYPE; |
| 787 | } | 813 | } |
| 788 | 814 | ||
| 789 | if (skb->protocol == __constant_htons(ETH_P_8021Q)) { | 815 | if (skb->protocol == htons(ETH_P_8021Q)) { |
| 790 | skb_pull(skb, VLAN_HLEN); | 816 | skb_pull(skb, VLAN_HLEN); |
| 791 | skb->nh.raw += VLAN_HLEN; | 817 | skb->nh.raw += VLAN_HLEN; |
| 792 | } | 818 | } |
| @@ -798,7 +824,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, | |||
| 798 | realoutdev = nf_bridge->netoutdev; | 824 | realoutdev = nf_bridge->netoutdev; |
| 799 | #endif | 825 | #endif |
| 800 | NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, | 826 | NF_HOOK(pf, NF_IP_POST_ROUTING, skb, NULL, realoutdev, |
| 801 | br_dev_queue_push_xmit); | 827 | br_dev_queue_push_xmit); |
| 802 | 828 | ||
| 803 | return NF_STOLEN; | 829 | return NF_STOLEN; |
| 804 | 830 | ||
| @@ -810,18 +836,18 @@ print_error: | |||
| 810 | printk("[%s]", realoutdev->name); | 836 | printk("[%s]", realoutdev->name); |
| 811 | } | 837 | } |
| 812 | printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, | 838 | printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, |
| 813 | skb->data); | 839 | skb->data); |
| 814 | return NF_ACCEPT; | 840 | return NF_ACCEPT; |
| 815 | #endif | 841 | #endif |
| 816 | } | 842 | } |
| 817 | 843 | ||
| 818 | |||
| 819 | /* IP/SABOTAGE *****************************************************/ | 844 | /* IP/SABOTAGE *****************************************************/ |
| 820 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING | 845 | /* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING |
| 821 | * for the second time. */ | 846 | * for the second time. */ |
| 822 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, | 847 | static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, |
| 823 | const struct net_device *in, const struct net_device *out, | 848 | const struct net_device *in, |
| 824 | int (*okfn)(struct sk_buff *)) | 849 | const struct net_device *out, |
| 850 | int (*okfn)(struct sk_buff *)) | ||
| 825 | { | 851 | { |
| 826 | if ((*pskb)->nf_bridge && | 852 | if ((*pskb)->nf_bridge && |
| 827 | !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { | 853 | !((*pskb)->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) { |
| @@ -835,18 +861,18 @@ static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff **pskb, | |||
| 835 | * and PF_INET(6)/POST_ROUTING until we have done the forwarding | 861 | * and PF_INET(6)/POST_ROUTING until we have done the forwarding |
| 836 | * decision in the bridge code and have determined nf_bridge->physoutdev. */ | 862 | * decision in the bridge code and have determined nf_bridge->physoutdev. */ |
| 837 | static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, | 863 | static unsigned int ip_sabotage_out(unsigned int hook, struct sk_buff **pskb, |
| 838 | const struct net_device *in, const struct net_device *out, | 864 | const struct net_device *in, |
| 839 | int (*okfn)(struct sk_buff *)) | 865 | const struct net_device *out, |
| 866 | int (*okfn)(struct sk_buff *)) | ||
| 840 | { | 867 | { |
| 841 | struct sk_buff *skb = *pskb; | 868 | struct sk_buff *skb = *pskb; |
| 842 | 869 | ||
| 843 | if ((out->hard_start_xmit == br_dev_xmit && | 870 | if ((out->hard_start_xmit == br_dev_xmit && |
| 844 | okfn != br_nf_forward_finish && | 871 | okfn != br_nf_forward_finish && |
| 845 | okfn != br_nf_local_out_finish && | 872 | okfn != br_nf_local_out_finish && okfn != br_dev_queue_push_xmit) |
| 846 | okfn != br_dev_queue_push_xmit) | ||
| 847 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 873 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
| 848 | || ((out->priv_flags & IFF_802_1Q_VLAN) && | 874 | || ((out->priv_flags & IFF_802_1Q_VLAN) && |
| 849 | VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) | 875 | VLAN_DEV_INFO(out)->real_dev->hard_start_xmit == br_dev_xmit) |
| 850 | #endif | 876 | #endif |
| 851 | ) { | 877 | ) { |
| 852 | struct nf_bridge_info *nf_bridge; | 878 | struct nf_bridge_info *nf_bridge; |
| @@ -971,8 +997,8 @@ static struct nf_hook_ops br_nf_ops[] = { | |||
| 971 | 997 | ||
| 972 | #ifdef CONFIG_SYSCTL | 998 | #ifdef CONFIG_SYSCTL |
| 973 | static | 999 | static |
| 974 | int brnf_sysctl_call_tables(ctl_table *ctl, int write, struct file * filp, | 1000 | int brnf_sysctl_call_tables(ctl_table * ctl, int write, struct file *filp, |
| 975 | void __user *buffer, size_t *lenp, loff_t *ppos) | 1001 | void __user * buffer, size_t * lenp, loff_t * ppos) |
| 976 | { | 1002 | { |
| 977 | int ret; | 1003 | int ret; |
| 978 | 1004 | ||
| @@ -1059,7 +1085,8 @@ int br_netfilter_init(void) | |||
| 1059 | #ifdef CONFIG_SYSCTL | 1085 | #ifdef CONFIG_SYSCTL |
| 1060 | brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); | 1086 | brnf_sysctl_header = register_sysctl_table(brnf_net_table, 0); |
| 1061 | if (brnf_sysctl_header == NULL) { | 1087 | if (brnf_sysctl_header == NULL) { |
| 1062 | printk(KERN_WARNING "br_netfilter: can't register to sysctl.\n"); | 1088 | printk(KERN_WARNING |
| 1089 | "br_netfilter: can't register to sysctl.\n"); | ||
| 1063 | for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) | 1090 | for (i = 0; i < ARRAY_SIZE(br_nf_ops); i++) |
| 1064 | nf_unregister_hook(&br_nf_ops[i]); | 1091 | nf_unregister_hook(&br_nf_ops[i]); |
| 1065 | return -EFAULT; | 1092 | return -EFAULT; |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 8f10e09f251b..86ecea7ed372 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -109,6 +109,7 @@ struct net_bridge | |||
| 109 | unsigned long bridge_hello_time; | 109 | unsigned long bridge_hello_time; |
| 110 | unsigned long bridge_forward_delay; | 110 | unsigned long bridge_forward_delay; |
| 111 | 111 | ||
| 112 | u8 group_addr[ETH_ALEN]; | ||
| 112 | u16 root_port; | 113 | u16 root_port; |
| 113 | unsigned char stp_enabled; | 114 | unsigned char stp_enabled; |
| 114 | unsigned char topology_change; | 115 | unsigned char topology_change; |
| @@ -122,7 +123,7 @@ struct net_bridge | |||
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | extern struct notifier_block br_device_notifier; | 125 | extern struct notifier_block br_device_notifier; |
| 125 | extern const unsigned char bridge_ula[6]; | 126 | extern const u8 br_group_address[ETH_ALEN]; |
| 126 | 127 | ||
| 127 | /* called under bridge lock */ | 128 | /* called under bridge lock */ |
| 128 | static inline int br_is_root_bridge(const struct net_bridge *br) | 129 | static inline int br_is_root_bridge(const struct net_bridge *br) |
| @@ -217,7 +218,8 @@ extern void br_stp_set_path_cost(struct net_bridge_port *p, | |||
| 217 | extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); | 218 | extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); |
| 218 | 219 | ||
| 219 | /* br_stp_bpdu.c */ | 220 | /* br_stp_bpdu.c */ |
| 220 | extern int br_stp_handle_bpdu(struct sk_buff *skb); | 221 | extern int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, |
| 222 | struct packet_type *pt, struct net_device *orig_dev); | ||
| 221 | 223 | ||
| 222 | /* br_stp_timer.c */ | 224 | /* br_stp_timer.c */ |
| 223 | extern void br_stp_timer_init(struct net_bridge *br); | 225 | extern void br_stp_timer_init(struct net_bridge *br); |
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 296f6a487c52..8934a54792be 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c | |||
| @@ -15,158 +15,162 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/netfilter_bridge.h> | 17 | #include <linux/netfilter_bridge.h> |
| 18 | #include <linux/etherdevice.h> | ||
| 19 | #include <linux/llc.h> | ||
| 20 | #include <net/llc.h> | ||
| 21 | #include <net/llc_pdu.h> | ||
| 18 | 22 | ||
| 19 | #include "br_private.h" | 23 | #include "br_private.h" |
| 20 | #include "br_private_stp.h" | 24 | #include "br_private_stp.h" |
| 21 | 25 | ||
| 22 | #define JIFFIES_TO_TICKS(j) (((j) << 8) / HZ) | 26 | #define STP_HZ 256 |
| 23 | #define TICKS_TO_JIFFIES(j) (((j) * HZ) >> 8) | ||
| 24 | 27 | ||
| 25 | static void br_send_bpdu(struct net_bridge_port *p, unsigned char *data, int length) | 28 | #define LLC_RESERVE sizeof(struct llc_pdu_un) |
| 29 | |||
| 30 | static void br_send_bpdu(struct net_bridge_port *p, | ||
| 31 | const unsigned char *data, int length) | ||
| 26 | { | 32 | { |
| 27 | struct net_device *dev; | ||
| 28 | struct sk_buff *skb; | 33 | struct sk_buff *skb; |
| 29 | int size; | ||
| 30 | 34 | ||
| 31 | if (!p->br->stp_enabled) | 35 | if (!p->br->stp_enabled) |
| 32 | return; | 36 | return; |
| 33 | 37 | ||
| 34 | size = length + 2*ETH_ALEN + 2; | 38 | skb = dev_alloc_skb(length+LLC_RESERVE); |
| 35 | if (size < 60) | 39 | if (!skb) |
| 36 | size = 60; | ||
| 37 | |||
| 38 | dev = p->dev; | ||
| 39 | |||
| 40 | if ((skb = dev_alloc_skb(size)) == NULL) { | ||
| 41 | printk(KERN_INFO "br: memory squeeze!\n"); | ||
| 42 | return; | 40 | return; |
| 43 | } | ||
| 44 | 41 | ||
| 45 | skb->dev = dev; | 42 | skb->dev = p->dev; |
| 46 | skb->protocol = htons(ETH_P_802_2); | 43 | skb->protocol = htons(ETH_P_802_2); |
| 47 | skb->mac.raw = skb_put(skb, size); | 44 | |
| 48 | memcpy(skb->mac.raw, bridge_ula, ETH_ALEN); | 45 | skb_reserve(skb, LLC_RESERVE); |
| 49 | memcpy(skb->mac.raw+ETH_ALEN, dev->dev_addr, ETH_ALEN); | 46 | memcpy(__skb_put(skb, length), data, length); |
| 50 | skb->mac.raw[2*ETH_ALEN] = 0; | 47 | |
| 51 | skb->mac.raw[2*ETH_ALEN+1] = length; | 48 | llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN, |
| 52 | skb->nh.raw = skb->mac.raw + 2*ETH_ALEN + 2; | 49 | LLC_SAP_BSPAN, LLC_PDU_CMD); |
| 53 | memcpy(skb->nh.raw, data, length); | 50 | llc_pdu_init_as_ui_cmd(skb); |
| 54 | memset(skb->nh.raw + length, 0xa5, size - length - 2*ETH_ALEN - 2); | 51 | |
| 52 | llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); | ||
| 55 | 53 | ||
| 56 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, | 54 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, |
| 57 | dev_queue_xmit); | 55 | dev_queue_xmit); |
| 58 | } | 56 | } |
| 59 | 57 | ||
| 60 | static __inline__ void br_set_ticks(unsigned char *dest, int jiff) | 58 | static inline void br_set_ticks(unsigned char *dest, int j) |
| 61 | { | 59 | { |
| 62 | __u16 ticks; | 60 | unsigned long ticks = (STP_HZ * j)/ HZ; |
| 63 | 61 | ||
| 64 | ticks = JIFFIES_TO_TICKS(jiff); | 62 | *((__be16 *) dest) = htons(ticks); |
| 65 | dest[0] = (ticks >> 8) & 0xFF; | ||
| 66 | dest[1] = ticks & 0xFF; | ||
| 67 | } | 63 | } |
| 68 | 64 | ||
| 69 | static __inline__ int br_get_ticks(unsigned char *dest) | 65 | static inline int br_get_ticks(const unsigned char *src) |
| 70 | { | 66 | { |
| 71 | return TICKS_TO_JIFFIES((dest[0] << 8) | dest[1]); | 67 | unsigned long ticks = ntohs(*(__be16 *)src); |
| 68 | |||
| 69 | return (ticks * HZ + STP_HZ - 1) / STP_HZ; | ||
| 72 | } | 70 | } |
| 73 | 71 | ||
| 74 | /* called under bridge lock */ | 72 | /* called under bridge lock */ |
| 75 | void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) | 73 | void br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) |
| 76 | { | 74 | { |
| 77 | unsigned char buf[38]; | 75 | unsigned char buf[35]; |
| 78 | 76 | ||
| 79 | buf[0] = 0x42; | 77 | buf[0] = 0; |
| 80 | buf[1] = 0x42; | 78 | buf[1] = 0; |
| 81 | buf[2] = 0x03; | 79 | buf[2] = 0; |
| 82 | buf[3] = 0; | 80 | buf[3] = BPDU_TYPE_CONFIG; |
| 83 | buf[4] = 0; | 81 | buf[4] = (bpdu->topology_change ? 0x01 : 0) | |
| 84 | buf[5] = 0; | ||
| 85 | buf[6] = BPDU_TYPE_CONFIG; | ||
| 86 | buf[7] = (bpdu->topology_change ? 0x01 : 0) | | ||
| 87 | (bpdu->topology_change_ack ? 0x80 : 0); | 82 | (bpdu->topology_change_ack ? 0x80 : 0); |
| 88 | buf[8] = bpdu->root.prio[0]; | 83 | buf[5] = bpdu->root.prio[0]; |
| 89 | buf[9] = bpdu->root.prio[1]; | 84 | buf[6] = bpdu->root.prio[1]; |
| 90 | buf[10] = bpdu->root.addr[0]; | 85 | buf[7] = bpdu->root.addr[0]; |
| 91 | buf[11] = bpdu->root.addr[1]; | 86 | buf[8] = bpdu->root.addr[1]; |
| 92 | buf[12] = bpdu->root.addr[2]; | 87 | buf[9] = bpdu->root.addr[2]; |
| 93 | buf[13] = bpdu->root.addr[3]; | 88 | buf[10] = bpdu->root.addr[3]; |
| 94 | buf[14] = bpdu->root.addr[4]; | 89 | buf[11] = bpdu->root.addr[4]; |
| 95 | buf[15] = bpdu->root.addr[5]; | 90 | buf[12] = bpdu->root.addr[5]; |
| 96 | buf[16] = (bpdu->root_path_cost >> 24) & 0xFF; | 91 | buf[13] = (bpdu->root_path_cost >> 24) & 0xFF; |
| 97 | buf[17] = (bpdu->root_path_cost >> 16) & 0xFF; | 92 | buf[14] = (bpdu->root_path_cost >> 16) & 0xFF; |
| 98 | buf[18] = (bpdu->root_path_cost >> 8) & 0xFF; | 93 | buf[15] = (bpdu->root_path_cost >> 8) & 0xFF; |
| 99 | buf[19] = bpdu->root_path_cost & 0xFF; | 94 | buf[16] = bpdu->root_path_cost & 0xFF; |
| 100 | buf[20] = bpdu->bridge_id.prio[0]; | 95 | buf[17] = bpdu->bridge_id.prio[0]; |
| 101 | buf[21] = bpdu->bridge_id.prio[1]; | 96 | buf[18] = bpdu->bridge_id.prio[1]; |
| 102 | buf[22] = bpdu->bridge_id.addr[0]; | 97 | buf[19] = bpdu->bridge_id.addr[0]; |
| 103 | buf[23] = bpdu->bridge_id.addr[1]; | 98 | buf[20] = bpdu->bridge_id.addr[1]; |
| 104 | buf[24] = bpdu->bridge_id.addr[2]; | 99 | buf[21] = bpdu->bridge_id.addr[2]; |
| 105 | buf[25] = bpdu->bridge_id.addr[3]; | 100 | buf[22] = bpdu->bridge_id.addr[3]; |
| 106 | buf[26] = bpdu->bridge_id.addr[4]; | 101 | buf[23] = bpdu->bridge_id.addr[4]; |
| 107 | buf[27] = bpdu->bridge_id.addr[5]; | 102 | buf[24] = bpdu->bridge_id.addr[5]; |
| 108 | buf[28] = (bpdu->port_id >> 8) & 0xFF; | 103 | buf[25] = (bpdu->port_id >> 8) & 0xFF; |
| 109 | buf[29] = bpdu->port_id & 0xFF; | 104 | buf[26] = bpdu->port_id & 0xFF; |
| 110 | 105 | ||
| 111 | br_set_ticks(buf+30, bpdu->message_age); | 106 | br_set_ticks(buf+27, bpdu->message_age); |
| 112 | br_set_ticks(buf+32, bpdu->max_age); | 107 | br_set_ticks(buf+29, bpdu->max_age); |
| 113 | br_set_ticks(buf+34, bpdu->hello_time); | 108 | br_set_ticks(buf+31, bpdu->hello_time); |
| 114 | br_set_ticks(buf+36, bpdu->forward_delay); | 109 | br_set_ticks(buf+33, bpdu->forward_delay); |
| 115 | 110 | ||
| 116 | br_send_bpdu(p, buf, 38); | 111 | br_send_bpdu(p, buf, 35); |
| 117 | } | 112 | } |
| 118 | 113 | ||
| 119 | /* called under bridge lock */ | 114 | /* called under bridge lock */ |
| 120 | void br_send_tcn_bpdu(struct net_bridge_port *p) | 115 | void br_send_tcn_bpdu(struct net_bridge_port *p) |
| 121 | { | 116 | { |
| 122 | unsigned char buf[7]; | 117 | unsigned char buf[4]; |
| 123 | 118 | ||
| 124 | buf[0] = 0x42; | 119 | buf[0] = 0; |
| 125 | buf[1] = 0x42; | 120 | buf[1] = 0; |
| 126 | buf[2] = 0x03; | 121 | buf[2] = 0; |
| 127 | buf[3] = 0; | 122 | buf[3] = BPDU_TYPE_TCN; |
| 128 | buf[4] = 0; | ||
| 129 | buf[5] = 0; | ||
| 130 | buf[6] = BPDU_TYPE_TCN; | ||
| 131 | br_send_bpdu(p, buf, 7); | 123 | br_send_bpdu(p, buf, 7); |
| 132 | } | 124 | } |
| 133 | 125 | ||
| 134 | static const unsigned char header[6] = {0x42, 0x42, 0x03, 0x00, 0x00, 0x00}; | 126 | /* |
| 135 | 127 | * Called from llc. | |
| 136 | /* NO locks, but rcu_read_lock (preempt_disabled) */ | 128 | * |
| 137 | int br_stp_handle_bpdu(struct sk_buff *skb) | 129 | * NO locks, but rcu_read_lock (preempt_disabled) |
| 130 | */ | ||
| 131 | int br_stp_rcv(struct sk_buff *skb, struct net_device *dev, | ||
| 132 | struct packet_type *pt, struct net_device *orig_dev) | ||
| 138 | { | 133 | { |
| 139 | struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); | 134 | const struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); |
| 135 | const unsigned char *dest = eth_hdr(skb)->h_dest; | ||
| 136 | struct net_bridge_port *p = rcu_dereference(dev->br_port); | ||
| 140 | struct net_bridge *br; | 137 | struct net_bridge *br; |
| 141 | unsigned char *buf; | 138 | const unsigned char *buf; |
| 142 | 139 | ||
| 143 | if (!p) | 140 | if (!p) |
| 144 | goto err; | 141 | goto err; |
| 145 | 142 | ||
| 146 | br = p->br; | 143 | if (pdu->ssap != LLC_SAP_BSPAN |
| 147 | spin_lock(&br->lock); | 144 | || pdu->dsap != LLC_SAP_BSPAN |
| 145 | || pdu->ctrl_1 != LLC_PDU_TYPE_U) | ||
| 146 | goto err; | ||
| 148 | 147 | ||
| 149 | if (p->state == BR_STATE_DISABLED || !(br->dev->flags & IFF_UP)) | 148 | if (!pskb_may_pull(skb, 4)) |
| 150 | goto out; | 149 | goto err; |
| 150 | |||
| 151 | /* compare of protocol id and version */ | ||
| 152 | buf = skb->data; | ||
| 153 | if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0) | ||
| 154 | goto err; | ||
| 151 | 155 | ||
| 152 | /* insert into forwarding database after filtering to avoid spoofing */ | 156 | br = p->br; |
| 153 | br_fdb_update(br, p, eth_hdr(skb)->h_source); | 157 | spin_lock(&br->lock); |
| 154 | 158 | ||
| 155 | if (!br->stp_enabled) | 159 | if (p->state == BR_STATE_DISABLED |
| 160 | || !br->stp_enabled | ||
| 161 | || !(br->dev->flags & IFF_UP)) | ||
| 156 | goto out; | 162 | goto out; |
| 157 | 163 | ||
| 158 | /* need at least the 802 and STP headers */ | 164 | if (compare_ether_addr(dest, br->group_addr) != 0) |
| 159 | if (!pskb_may_pull(skb, sizeof(header)+1) || | ||
| 160 | memcmp(skb->data, header, sizeof(header))) | ||
| 161 | goto out; | 165 | goto out; |
| 162 | 166 | ||
| 163 | buf = skb_pull(skb, sizeof(header)); | 167 | buf = skb_pull(skb, 3); |
| 164 | 168 | ||
| 165 | if (buf[0] == BPDU_TYPE_CONFIG) { | 169 | if (buf[0] == BPDU_TYPE_CONFIG) { |
| 166 | struct br_config_bpdu bpdu; | 170 | struct br_config_bpdu bpdu; |
| 167 | 171 | ||
| 168 | if (!pskb_may_pull(skb, 32)) | 172 | if (!pskb_may_pull(skb, 32)) |
| 169 | goto out; | 173 | goto out; |
| 170 | 174 | ||
| 171 | buf = skb->data; | 175 | buf = skb->data; |
| 172 | bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0; | 176 | bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0; |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 9bef55f56425..d0fcde82c6fc 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
| @@ -39,13 +39,13 @@ static void br_hello_timer_expired(unsigned long arg) | |||
| 39 | struct net_bridge *br = (struct net_bridge *)arg; | 39 | struct net_bridge *br = (struct net_bridge *)arg; |
| 40 | 40 | ||
| 41 | pr_debug("%s: hello timer expired\n", br->dev->name); | 41 | pr_debug("%s: hello timer expired\n", br->dev->name); |
| 42 | spin_lock_bh(&br->lock); | 42 | spin_lock(&br->lock); |
| 43 | if (br->dev->flags & IFF_UP) { | 43 | if (br->dev->flags & IFF_UP) { |
| 44 | br_config_bpdu_generation(br); | 44 | br_config_bpdu_generation(br); |
| 45 | 45 | ||
| 46 | mod_timer(&br->hello_timer, jiffies + br->hello_time); | 46 | mod_timer(&br->hello_timer, jiffies + br->hello_time); |
| 47 | } | 47 | } |
| 48 | spin_unlock_bh(&br->lock); | 48 | spin_unlock(&br->lock); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static void br_message_age_timer_expired(unsigned long arg) | 51 | static void br_message_age_timer_expired(unsigned long arg) |
| @@ -71,7 +71,7 @@ static void br_message_age_timer_expired(unsigned long arg) | |||
| 71 | * running when we are the root bridge. So.. this was_root | 71 | * running when we are the root bridge. So.. this was_root |
| 72 | * check is redundant. I'm leaving it in for now, though. | 72 | * check is redundant. I'm leaving it in for now, though. |
| 73 | */ | 73 | */ |
| 74 | spin_lock_bh(&br->lock); | 74 | spin_lock(&br->lock); |
| 75 | if (p->state == BR_STATE_DISABLED) | 75 | if (p->state == BR_STATE_DISABLED) |
| 76 | goto unlock; | 76 | goto unlock; |
| 77 | was_root = br_is_root_bridge(br); | 77 | was_root = br_is_root_bridge(br); |
| @@ -82,7 +82,7 @@ static void br_message_age_timer_expired(unsigned long arg) | |||
| 82 | if (br_is_root_bridge(br) && !was_root) | 82 | if (br_is_root_bridge(br) && !was_root) |
| 83 | br_become_root_bridge(br); | 83 | br_become_root_bridge(br); |
| 84 | unlock: | 84 | unlock: |
| 85 | spin_unlock_bh(&br->lock); | 85 | spin_unlock(&br->lock); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static void br_forward_delay_timer_expired(unsigned long arg) | 88 | static void br_forward_delay_timer_expired(unsigned long arg) |
| @@ -92,7 +92,7 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
| 92 | 92 | ||
| 93 | pr_debug("%s: %d(%s) forward delay timer\n", | 93 | pr_debug("%s: %d(%s) forward delay timer\n", |
| 94 | br->dev->name, p->port_no, p->dev->name); | 94 | br->dev->name, p->port_no, p->dev->name); |
| 95 | spin_lock_bh(&br->lock); | 95 | spin_lock(&br->lock); |
| 96 | if (p->state == BR_STATE_LISTENING) { | 96 | if (p->state == BR_STATE_LISTENING) { |
| 97 | p->state = BR_STATE_LEARNING; | 97 | p->state = BR_STATE_LEARNING; |
| 98 | mod_timer(&p->forward_delay_timer, | 98 | mod_timer(&p->forward_delay_timer, |
| @@ -103,7 +103,7 @@ static void br_forward_delay_timer_expired(unsigned long arg) | |||
| 103 | br_topology_change_detection(br); | 103 | br_topology_change_detection(br); |
| 104 | } | 104 | } |
| 105 | br_log_state(p); | 105 | br_log_state(p); |
| 106 | spin_unlock_bh(&br->lock); | 106 | spin_unlock(&br->lock); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | static void br_tcn_timer_expired(unsigned long arg) | 109 | static void br_tcn_timer_expired(unsigned long arg) |
| @@ -111,13 +111,13 @@ static void br_tcn_timer_expired(unsigned long arg) | |||
| 111 | struct net_bridge *br = (struct net_bridge *) arg; | 111 | struct net_bridge *br = (struct net_bridge *) arg; |
| 112 | 112 | ||
| 113 | pr_debug("%s: tcn timer expired\n", br->dev->name); | 113 | pr_debug("%s: tcn timer expired\n", br->dev->name); |
| 114 | spin_lock_bh(&br->lock); | 114 | spin_lock(&br->lock); |
| 115 | if (br->dev->flags & IFF_UP) { | 115 | if (br->dev->flags & IFF_UP) { |
| 116 | br_transmit_tcn(br); | 116 | br_transmit_tcn(br); |
| 117 | 117 | ||
| 118 | mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time); | 118 | mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time); |
| 119 | } | 119 | } |
| 120 | spin_unlock_bh(&br->lock); | 120 | spin_unlock(&br->lock); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static void br_topology_change_timer_expired(unsigned long arg) | 123 | static void br_topology_change_timer_expired(unsigned long arg) |
| @@ -125,10 +125,10 @@ static void br_topology_change_timer_expired(unsigned long arg) | |||
| 125 | struct net_bridge *br = (struct net_bridge *) arg; | 125 | struct net_bridge *br = (struct net_bridge *) arg; |
| 126 | 126 | ||
| 127 | pr_debug("%s: topo change timer expired\n", br->dev->name); | 127 | pr_debug("%s: topo change timer expired\n", br->dev->name); |
| 128 | spin_lock_bh(&br->lock); | 128 | spin_lock(&br->lock); |
| 129 | br->topology_change_detected = 0; | 129 | br->topology_change_detected = 0; |
| 130 | br->topology_change = 0; | 130 | br->topology_change = 0; |
| 131 | spin_unlock_bh(&br->lock); | 131 | spin_unlock(&br->lock); |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | static void br_hold_timer_expired(unsigned long arg) | 134 | static void br_hold_timer_expired(unsigned long arg) |
| @@ -138,45 +138,36 @@ static void br_hold_timer_expired(unsigned long arg) | |||
| 138 | pr_debug("%s: %d(%s) hold timer expired\n", | 138 | pr_debug("%s: %d(%s) hold timer expired\n", |
| 139 | p->br->dev->name, p->port_no, p->dev->name); | 139 | p->br->dev->name, p->port_no, p->dev->name); |
| 140 | 140 | ||
| 141 | spin_lock_bh(&p->br->lock); | 141 | spin_lock(&p->br->lock); |
| 142 | if (p->config_pending) | 142 | if (p->config_pending) |
| 143 | br_transmit_config(p); | 143 | br_transmit_config(p); |
| 144 | spin_unlock_bh(&p->br->lock); | 144 | spin_unlock(&p->br->lock); |
| 145 | } | ||
| 146 | |||
| 147 | static inline void br_timer_init(struct timer_list *timer, | ||
| 148 | void (*_function)(unsigned long), | ||
| 149 | unsigned long _data) | ||
| 150 | { | ||
| 151 | init_timer(timer); | ||
| 152 | timer->function = _function; | ||
| 153 | timer->data = _data; | ||
| 154 | } | 145 | } |
| 155 | 146 | ||
| 156 | void br_stp_timer_init(struct net_bridge *br) | 147 | void br_stp_timer_init(struct net_bridge *br) |
| 157 | { | 148 | { |
| 158 | br_timer_init(&br->hello_timer, br_hello_timer_expired, | 149 | setup_timer(&br->hello_timer, br_hello_timer_expired, |
| 159 | (unsigned long) br); | 150 | (unsigned long) br); |
| 160 | 151 | ||
| 161 | br_timer_init(&br->tcn_timer, br_tcn_timer_expired, | 152 | setup_timer(&br->tcn_timer, br_tcn_timer_expired, |
| 162 | (unsigned long) br); | 153 | (unsigned long) br); |
| 163 | 154 | ||
| 164 | br_timer_init(&br->topology_change_timer, | 155 | setup_timer(&br->topology_change_timer, |
| 165 | br_topology_change_timer_expired, | 156 | br_topology_change_timer_expired, |
| 166 | (unsigned long) br); | 157 | (unsigned long) br); |
| 167 | 158 | ||
| 168 | br_timer_init(&br->gc_timer, br_fdb_cleanup, (unsigned long) br); | 159 | setup_timer(&br->gc_timer, br_fdb_cleanup, (unsigned long) br); |
| 169 | } | 160 | } |
| 170 | 161 | ||
| 171 | void br_stp_port_timer_init(struct net_bridge_port *p) | 162 | void br_stp_port_timer_init(struct net_bridge_port *p) |
| 172 | { | 163 | { |
| 173 | br_timer_init(&p->message_age_timer, br_message_age_timer_expired, | 164 | setup_timer(&p->message_age_timer, br_message_age_timer_expired, |
| 174 | (unsigned long) p); | 165 | (unsigned long) p); |
| 175 | 166 | ||
| 176 | br_timer_init(&p->forward_delay_timer, br_forward_delay_timer_expired, | 167 | setup_timer(&p->forward_delay_timer, br_forward_delay_timer_expired, |
| 177 | (unsigned long) p); | 168 | (unsigned long) p); |
| 178 | 169 | ||
| 179 | br_timer_init(&p->hold_timer, br_hold_timer_expired, | 170 | setup_timer(&p->hold_timer, br_hold_timer_expired, |
| 180 | (unsigned long) p); | 171 | (unsigned long) p); |
| 181 | } | 172 | } |
| 182 | 173 | ||
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 6f577f16c4c0..96bcb2ff59ab 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
| @@ -242,6 +242,54 @@ static ssize_t show_gc_timer(struct class_device *cd, char *buf) | |||
| 242 | } | 242 | } |
| 243 | static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); | 243 | static CLASS_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL); |
| 244 | 244 | ||
| 245 | static ssize_t show_group_addr(struct class_device *cd, char *buf) | ||
| 246 | { | ||
| 247 | struct net_bridge *br = to_bridge(cd); | ||
| 248 | return sprintf(buf, "%x:%x:%x:%x:%x:%x\n", | ||
| 249 | br->group_addr[0], br->group_addr[1], | ||
| 250 | br->group_addr[2], br->group_addr[3], | ||
| 251 | br->group_addr[4], br->group_addr[5]); | ||
| 252 | } | ||
| 253 | |||
| 254 | static ssize_t store_group_addr(struct class_device *cd, const char *buf, | ||
| 255 | size_t len) | ||
| 256 | { | ||
| 257 | struct net_bridge *br = to_bridge(cd); | ||
| 258 | unsigned new_addr[6]; | ||
| 259 | int i; | ||
| 260 | |||
| 261 | if (!capable(CAP_NET_ADMIN)) | ||
| 262 | return -EPERM; | ||
| 263 | |||
| 264 | if (sscanf(buf, "%x:%x:%x:%x:%x:%x", | ||
| 265 | &new_addr[0], &new_addr[1], &new_addr[2], | ||
| 266 | &new_addr[3], &new_addr[4], &new_addr[5]) != 6) | ||
| 267 | return -EINVAL; | ||
| 268 | |||
| 269 | /* Must be 01:80:c2:00:00:0X */ | ||
| 270 | for (i = 0; i < 5; i++) | ||
| 271 | if (new_addr[i] != br_group_address[i]) | ||
| 272 | return -EINVAL; | ||
| 273 | |||
| 274 | if (new_addr[5] & ~0xf) | ||
| 275 | return -EINVAL; | ||
| 276 | |||
| 277 | if (new_addr[5] == 1 /* 802.3x Pause address */ | ||
| 278 | || new_addr[5] == 2 /* 802.3ad Slow protocols */ | ||
| 279 | || new_addr[5] == 3) /* 802.1X PAE address */ | ||
| 280 | return -EINVAL; | ||
| 281 | |||
| 282 | spin_lock_bh(&br->lock); | ||
| 283 | for (i = 0; i < 6; i++) | ||
| 284 | br->group_addr[i] = new_addr[i]; | ||
| 285 | spin_unlock_bh(&br->lock); | ||
| 286 | return len; | ||
| 287 | } | ||
| 288 | |||
| 289 | static CLASS_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR, | ||
| 290 | show_group_addr, store_group_addr); | ||
| 291 | |||
| 292 | |||
| 245 | static struct attribute *bridge_attrs[] = { | 293 | static struct attribute *bridge_attrs[] = { |
| 246 | &class_device_attr_forward_delay.attr, | 294 | &class_device_attr_forward_delay.attr, |
| 247 | &class_device_attr_hello_time.attr, | 295 | &class_device_attr_hello_time.attr, |
| @@ -259,6 +307,7 @@ static struct attribute *bridge_attrs[] = { | |||
| 259 | &class_device_attr_tcn_timer.attr, | 307 | &class_device_attr_tcn_timer.attr, |
| 260 | &class_device_attr_topology_change_timer.attr, | 308 | &class_device_attr_topology_change_timer.attr, |
| 261 | &class_device_attr_gc_timer.attr, | 309 | &class_device_attr_gc_timer.attr, |
| 310 | &class_device_attr_group_addr.attr, | ||
| 262 | NULL | 311 | NULL |
| 263 | }; | 312 | }; |
| 264 | 313 | ||
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index cbd4020cc84d..997953367204 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #define ASSERT_READ_LOCK(x) | 35 | #define ASSERT_READ_LOCK(x) |
| 36 | #define ASSERT_WRITE_LOCK(x) | 36 | #define ASSERT_WRITE_LOCK(x) |
| 37 | #include <linux/netfilter_ipv4/listhelp.h> | 37 | #include <linux/netfilter_ipv4/listhelp.h> |
| 38 | #include <linux/mutex.h> | ||
| 38 | 39 | ||
| 39 | #if 0 | 40 | #if 0 |
| 40 | /* use this for remote debugging | 41 | /* use this for remote debugging |
| @@ -81,7 +82,7 @@ static void print_string(char *str) | |||
| 81 | 82 | ||
| 82 | 83 | ||
| 83 | 84 | ||
| 84 | static DECLARE_MUTEX(ebt_mutex); | 85 | static DEFINE_MUTEX(ebt_mutex); |
| 85 | static LIST_HEAD(ebt_tables); | 86 | static LIST_HEAD(ebt_tables); |
| 86 | static LIST_HEAD(ebt_targets); | 87 | static LIST_HEAD(ebt_targets); |
| 87 | static LIST_HEAD(ebt_matches); | 88 | static LIST_HEAD(ebt_matches); |
| @@ -296,18 +297,18 @@ letscontinue: | |||
| 296 | /* If it succeeds, returns element and locks mutex */ | 297 | /* If it succeeds, returns element and locks mutex */ |
| 297 | static inline void * | 298 | static inline void * |
| 298 | find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | 299 | find_inlist_lock_noload(struct list_head *head, const char *name, int *error, |
| 299 | struct semaphore *mutex) | 300 | struct mutex *mutex) |
| 300 | { | 301 | { |
| 301 | void *ret; | 302 | void *ret; |
| 302 | 303 | ||
| 303 | *error = down_interruptible(mutex); | 304 | *error = mutex_lock_interruptible(mutex); |
| 304 | if (*error != 0) | 305 | if (*error != 0) |
| 305 | return NULL; | 306 | return NULL; |
| 306 | 307 | ||
| 307 | ret = list_named_find(head, name); | 308 | ret = list_named_find(head, name); |
| 308 | if (!ret) { | 309 | if (!ret) { |
| 309 | *error = -ENOENT; | 310 | *error = -ENOENT; |
| 310 | up(mutex); | 311 | mutex_unlock(mutex); |
| 311 | } | 312 | } |
| 312 | return ret; | 313 | return ret; |
| 313 | } | 314 | } |
| @@ -317,7 +318,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | |||
| 317 | #else | 318 | #else |
| 318 | static void * | 319 | static void * |
| 319 | find_inlist_lock(struct list_head *head, const char *name, const char *prefix, | 320 | find_inlist_lock(struct list_head *head, const char *name, const char *prefix, |
| 320 | int *error, struct semaphore *mutex) | 321 | int *error, struct mutex *mutex) |
| 321 | { | 322 | { |
| 322 | void *ret; | 323 | void *ret; |
| 323 | 324 | ||
| @@ -331,25 +332,25 @@ find_inlist_lock(struct list_head *head, const char *name, const char *prefix, | |||
| 331 | #endif | 332 | #endif |
| 332 | 333 | ||
| 333 | static inline struct ebt_table * | 334 | static inline struct ebt_table * |
| 334 | find_table_lock(const char *name, int *error, struct semaphore *mutex) | 335 | find_table_lock(const char *name, int *error, struct mutex *mutex) |
| 335 | { | 336 | { |
| 336 | return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); | 337 | return find_inlist_lock(&ebt_tables, name, "ebtable_", error, mutex); |
| 337 | } | 338 | } |
| 338 | 339 | ||
| 339 | static inline struct ebt_match * | 340 | static inline struct ebt_match * |
| 340 | find_match_lock(const char *name, int *error, struct semaphore *mutex) | 341 | find_match_lock(const char *name, int *error, struct mutex *mutex) |
| 341 | { | 342 | { |
| 342 | return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex); | 343 | return find_inlist_lock(&ebt_matches, name, "ebt_", error, mutex); |
| 343 | } | 344 | } |
| 344 | 345 | ||
| 345 | static inline struct ebt_watcher * | 346 | static inline struct ebt_watcher * |
| 346 | find_watcher_lock(const char *name, int *error, struct semaphore *mutex) | 347 | find_watcher_lock(const char *name, int *error, struct mutex *mutex) |
| 347 | { | 348 | { |
| 348 | return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex); | 349 | return find_inlist_lock(&ebt_watchers, name, "ebt_", error, mutex); |
| 349 | } | 350 | } |
| 350 | 351 | ||
| 351 | static inline struct ebt_target * | 352 | static inline struct ebt_target * |
| 352 | find_target_lock(const char *name, int *error, struct semaphore *mutex) | 353 | find_target_lock(const char *name, int *error, struct mutex *mutex) |
| 353 | { | 354 | { |
| 354 | return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex); | 355 | return find_inlist_lock(&ebt_targets, name, "ebt_", error, mutex); |
| 355 | } | 356 | } |
| @@ -369,10 +370,10 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e, | |||
| 369 | return ret; | 370 | return ret; |
| 370 | m->u.match = match; | 371 | m->u.match = match; |
| 371 | if (!try_module_get(match->me)) { | 372 | if (!try_module_get(match->me)) { |
| 372 | up(&ebt_mutex); | 373 | mutex_unlock(&ebt_mutex); |
| 373 | return -ENOENT; | 374 | return -ENOENT; |
| 374 | } | 375 | } |
| 375 | up(&ebt_mutex); | 376 | mutex_unlock(&ebt_mutex); |
| 376 | if (match->check && | 377 | if (match->check && |
| 377 | match->check(name, hookmask, e, m->data, m->match_size) != 0) { | 378 | match->check(name, hookmask, e, m->data, m->match_size) != 0) { |
| 378 | BUGPRINT("match->check failed\n"); | 379 | BUGPRINT("match->check failed\n"); |
| @@ -398,10 +399,10 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e, | |||
| 398 | return ret; | 399 | return ret; |
| 399 | w->u.watcher = watcher; | 400 | w->u.watcher = watcher; |
| 400 | if (!try_module_get(watcher->me)) { | 401 | if (!try_module_get(watcher->me)) { |
| 401 | up(&ebt_mutex); | 402 | mutex_unlock(&ebt_mutex); |
| 402 | return -ENOENT; | 403 | return -ENOENT; |
| 403 | } | 404 | } |
| 404 | up(&ebt_mutex); | 405 | mutex_unlock(&ebt_mutex); |
| 405 | if (watcher->check && | 406 | if (watcher->check && |
| 406 | watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { | 407 | watcher->check(name, hookmask, e, w->data, w->watcher_size) != 0) { |
| 407 | BUGPRINT("watcher->check failed\n"); | 408 | BUGPRINT("watcher->check failed\n"); |
| @@ -638,11 +639,11 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, | |||
| 638 | if (!target) | 639 | if (!target) |
| 639 | goto cleanup_watchers; | 640 | goto cleanup_watchers; |
| 640 | if (!try_module_get(target->me)) { | 641 | if (!try_module_get(target->me)) { |
| 641 | up(&ebt_mutex); | 642 | mutex_unlock(&ebt_mutex); |
| 642 | ret = -ENOENT; | 643 | ret = -ENOENT; |
| 643 | goto cleanup_watchers; | 644 | goto cleanup_watchers; |
| 644 | } | 645 | } |
| 645 | up(&ebt_mutex); | 646 | mutex_unlock(&ebt_mutex); |
| 646 | 647 | ||
| 647 | t->u.target = target; | 648 | t->u.target = target; |
| 648 | if (t->u.target == &ebt_standard_target) { | 649 | if (t->u.target == &ebt_standard_target) { |
| @@ -1015,7 +1016,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
| 1015 | 1016 | ||
| 1016 | t->private = newinfo; | 1017 | t->private = newinfo; |
| 1017 | write_unlock_bh(&t->lock); | 1018 | write_unlock_bh(&t->lock); |
| 1018 | up(&ebt_mutex); | 1019 | mutex_unlock(&ebt_mutex); |
| 1019 | /* so, a user can change the chains while having messed up her counter | 1020 | /* so, a user can change the chains while having messed up her counter |
| 1020 | allocation. Only reason why this is done is because this way the lock | 1021 | allocation. Only reason why this is done is because this way the lock |
| 1021 | is held only once, while this doesn't bring the kernel into a | 1022 | is held only once, while this doesn't bring the kernel into a |
| @@ -1045,7 +1046,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
| 1045 | return ret; | 1046 | return ret; |
| 1046 | 1047 | ||
| 1047 | free_unlock: | 1048 | free_unlock: |
| 1048 | up(&ebt_mutex); | 1049 | mutex_unlock(&ebt_mutex); |
| 1049 | free_iterate: | 1050 | free_iterate: |
| 1050 | EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, | 1051 | EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, |
| 1051 | ebt_cleanup_entry, NULL); | 1052 | ebt_cleanup_entry, NULL); |
| @@ -1068,69 +1069,69 @@ int ebt_register_target(struct ebt_target *target) | |||
| 1068 | { | 1069 | { |
| 1069 | int ret; | 1070 | int ret; |
| 1070 | 1071 | ||
| 1071 | ret = down_interruptible(&ebt_mutex); | 1072 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1072 | if (ret != 0) | 1073 | if (ret != 0) |
| 1073 | return ret; | 1074 | return ret; |
| 1074 | if (!list_named_insert(&ebt_targets, target)) { | 1075 | if (!list_named_insert(&ebt_targets, target)) { |
| 1075 | up(&ebt_mutex); | 1076 | mutex_unlock(&ebt_mutex); |
| 1076 | return -EEXIST; | 1077 | return -EEXIST; |
| 1077 | } | 1078 | } |
| 1078 | up(&ebt_mutex); | 1079 | mutex_unlock(&ebt_mutex); |
| 1079 | 1080 | ||
| 1080 | return 0; | 1081 | return 0; |
| 1081 | } | 1082 | } |
| 1082 | 1083 | ||
| 1083 | void ebt_unregister_target(struct ebt_target *target) | 1084 | void ebt_unregister_target(struct ebt_target *target) |
| 1084 | { | 1085 | { |
| 1085 | down(&ebt_mutex); | 1086 | mutex_lock(&ebt_mutex); |
| 1086 | LIST_DELETE(&ebt_targets, target); | 1087 | LIST_DELETE(&ebt_targets, target); |
| 1087 | up(&ebt_mutex); | 1088 | mutex_unlock(&ebt_mutex); |
| 1088 | } | 1089 | } |
| 1089 | 1090 | ||
| 1090 | int ebt_register_match(struct ebt_match *match) | 1091 | int ebt_register_match(struct ebt_match *match) |
| 1091 | { | 1092 | { |
| 1092 | int ret; | 1093 | int ret; |
| 1093 | 1094 | ||
| 1094 | ret = down_interruptible(&ebt_mutex); | 1095 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1095 | if (ret != 0) | 1096 | if (ret != 0) |
| 1096 | return ret; | 1097 | return ret; |
| 1097 | if (!list_named_insert(&ebt_matches, match)) { | 1098 | if (!list_named_insert(&ebt_matches, match)) { |
| 1098 | up(&ebt_mutex); | 1099 | mutex_unlock(&ebt_mutex); |
| 1099 | return -EEXIST; | 1100 | return -EEXIST; |
| 1100 | } | 1101 | } |
| 1101 | up(&ebt_mutex); | 1102 | mutex_unlock(&ebt_mutex); |
| 1102 | 1103 | ||
| 1103 | return 0; | 1104 | return 0; |
| 1104 | } | 1105 | } |
| 1105 | 1106 | ||
| 1106 | void ebt_unregister_match(struct ebt_match *match) | 1107 | void ebt_unregister_match(struct ebt_match *match) |
| 1107 | { | 1108 | { |
| 1108 | down(&ebt_mutex); | 1109 | mutex_lock(&ebt_mutex); |
| 1109 | LIST_DELETE(&ebt_matches, match); | 1110 | LIST_DELETE(&ebt_matches, match); |
| 1110 | up(&ebt_mutex); | 1111 | mutex_unlock(&ebt_mutex); |
| 1111 | } | 1112 | } |
| 1112 | 1113 | ||
| 1113 | int ebt_register_watcher(struct ebt_watcher *watcher) | 1114 | int ebt_register_watcher(struct ebt_watcher *watcher) |
| 1114 | { | 1115 | { |
| 1115 | int ret; | 1116 | int ret; |
| 1116 | 1117 | ||
| 1117 | ret = down_interruptible(&ebt_mutex); | 1118 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1118 | if (ret != 0) | 1119 | if (ret != 0) |
| 1119 | return ret; | 1120 | return ret; |
| 1120 | if (!list_named_insert(&ebt_watchers, watcher)) { | 1121 | if (!list_named_insert(&ebt_watchers, watcher)) { |
| 1121 | up(&ebt_mutex); | 1122 | mutex_unlock(&ebt_mutex); |
| 1122 | return -EEXIST; | 1123 | return -EEXIST; |
| 1123 | } | 1124 | } |
| 1124 | up(&ebt_mutex); | 1125 | mutex_unlock(&ebt_mutex); |
| 1125 | 1126 | ||
| 1126 | return 0; | 1127 | return 0; |
| 1127 | } | 1128 | } |
| 1128 | 1129 | ||
| 1129 | void ebt_unregister_watcher(struct ebt_watcher *watcher) | 1130 | void ebt_unregister_watcher(struct ebt_watcher *watcher) |
| 1130 | { | 1131 | { |
| 1131 | down(&ebt_mutex); | 1132 | mutex_lock(&ebt_mutex); |
| 1132 | LIST_DELETE(&ebt_watchers, watcher); | 1133 | LIST_DELETE(&ebt_watchers, watcher); |
| 1133 | up(&ebt_mutex); | 1134 | mutex_unlock(&ebt_mutex); |
| 1134 | } | 1135 | } |
| 1135 | 1136 | ||
| 1136 | int ebt_register_table(struct ebt_table *table) | 1137 | int ebt_register_table(struct ebt_table *table) |
| @@ -1178,7 +1179,7 @@ int ebt_register_table(struct ebt_table *table) | |||
| 1178 | 1179 | ||
| 1179 | table->private = newinfo; | 1180 | table->private = newinfo; |
| 1180 | rwlock_init(&table->lock); | 1181 | rwlock_init(&table->lock); |
| 1181 | ret = down_interruptible(&ebt_mutex); | 1182 | ret = mutex_lock_interruptible(&ebt_mutex); |
| 1182 | if (ret != 0) | 1183 | if (ret != 0) |
| 1183 | goto free_chainstack; | 1184 | goto free_chainstack; |
| 1184 | 1185 | ||
| @@ -1194,10 +1195,10 @@ int ebt_register_table(struct ebt_table *table) | |||
| 1194 | goto free_unlock; | 1195 | goto free_unlock; |
| 1195 | } | 1196 | } |
| 1196 | list_prepend(&ebt_tables, table); | 1197 | list_prepend(&ebt_tables, table); |
| 1197 | up(&ebt_mutex); | 1198 | mutex_unlock(&ebt_mutex); |
| 1198 | return 0; | 1199 | return 0; |
| 1199 | free_unlock: | 1200 | free_unlock: |
| 1200 | up(&ebt_mutex); | 1201 | mutex_unlock(&ebt_mutex); |
| 1201 | free_chainstack: | 1202 | free_chainstack: |
| 1202 | if (newinfo->chainstack) { | 1203 | if (newinfo->chainstack) { |
| 1203 | for_each_cpu(i) | 1204 | for_each_cpu(i) |
| @@ -1218,9 +1219,9 @@ void ebt_unregister_table(struct ebt_table *table) | |||
| 1218 | BUGPRINT("Request to unregister NULL table!!!\n"); | 1219 | BUGPRINT("Request to unregister NULL table!!!\n"); |
| 1219 | return; | 1220 | return; |
| 1220 | } | 1221 | } |
| 1221 | down(&ebt_mutex); | 1222 | mutex_lock(&ebt_mutex); |
| 1222 | LIST_DELETE(&ebt_tables, table); | 1223 | LIST_DELETE(&ebt_tables, table); |
| 1223 | up(&ebt_mutex); | 1224 | mutex_unlock(&ebt_mutex); |
| 1224 | vfree(table->private->entries); | 1225 | vfree(table->private->entries); |
| 1225 | if (table->private->chainstack) { | 1226 | if (table->private->chainstack) { |
| 1226 | for_each_cpu(i) | 1227 | for_each_cpu(i) |
| @@ -1281,7 +1282,7 @@ static int update_counters(void __user *user, unsigned int len) | |||
| 1281 | write_unlock_bh(&t->lock); | 1282 | write_unlock_bh(&t->lock); |
| 1282 | ret = 0; | 1283 | ret = 0; |
| 1283 | unlock_mutex: | 1284 | unlock_mutex: |
| 1284 | up(&ebt_mutex); | 1285 | mutex_unlock(&ebt_mutex); |
| 1285 | free_tmp: | 1286 | free_tmp: |
| 1286 | vfree(tmp); | 1287 | vfree(tmp); |
| 1287 | return ret; | 1288 | return ret; |
| @@ -1328,7 +1329,7 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char *ubase) | |||
| 1328 | return 0; | 1329 | return 0; |
| 1329 | } | 1330 | } |
| 1330 | 1331 | ||
| 1331 | /* called with ebt_mutex down */ | 1332 | /* called with ebt_mutex locked */ |
| 1332 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, | 1333 | static int copy_everything_to_user(struct ebt_table *t, void __user *user, |
| 1333 | int *len, int cmd) | 1334 | int *len, int cmd) |
| 1334 | { | 1335 | { |
| @@ -1440,7 +1441,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1440 | case EBT_SO_GET_INIT_INFO: | 1441 | case EBT_SO_GET_INIT_INFO: |
| 1441 | if (*len != sizeof(struct ebt_replace)){ | 1442 | if (*len != sizeof(struct ebt_replace)){ |
| 1442 | ret = -EINVAL; | 1443 | ret = -EINVAL; |
| 1443 | up(&ebt_mutex); | 1444 | mutex_unlock(&ebt_mutex); |
| 1444 | break; | 1445 | break; |
| 1445 | } | 1446 | } |
| 1446 | if (cmd == EBT_SO_GET_INFO) { | 1447 | if (cmd == EBT_SO_GET_INFO) { |
| @@ -1452,7 +1453,7 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1452 | tmp.entries_size = t->table->entries_size; | 1453 | tmp.entries_size = t->table->entries_size; |
| 1453 | tmp.valid_hooks = t->table->valid_hooks; | 1454 | tmp.valid_hooks = t->table->valid_hooks; |
| 1454 | } | 1455 | } |
| 1455 | up(&ebt_mutex); | 1456 | mutex_unlock(&ebt_mutex); |
| 1456 | if (copy_to_user(user, &tmp, *len) != 0){ | 1457 | if (copy_to_user(user, &tmp, *len) != 0){ |
| 1457 | BUGPRINT("c2u Didn't work\n"); | 1458 | BUGPRINT("c2u Didn't work\n"); |
| 1458 | ret = -EFAULT; | 1459 | ret = -EFAULT; |
| @@ -1464,11 +1465,11 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1464 | case EBT_SO_GET_ENTRIES: | 1465 | case EBT_SO_GET_ENTRIES: |
| 1465 | case EBT_SO_GET_INIT_ENTRIES: | 1466 | case EBT_SO_GET_INIT_ENTRIES: |
| 1466 | ret = copy_everything_to_user(t, user, len, cmd); | 1467 | ret = copy_everything_to_user(t, user, len, cmd); |
| 1467 | up(&ebt_mutex); | 1468 | mutex_unlock(&ebt_mutex); |
| 1468 | break; | 1469 | break; |
| 1469 | 1470 | ||
| 1470 | default: | 1471 | default: |
| 1471 | up(&ebt_mutex); | 1472 | mutex_unlock(&ebt_mutex); |
| 1472 | ret = -EINVAL; | 1473 | ret = -EINVAL; |
| 1473 | } | 1474 | } |
| 1474 | 1475 | ||
| @@ -1476,17 +1477,23 @@ static int do_ebt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
| 1476 | } | 1477 | } |
| 1477 | 1478 | ||
| 1478 | static struct nf_sockopt_ops ebt_sockopts = | 1479 | static struct nf_sockopt_ops ebt_sockopts = |
| 1479 | { { NULL, NULL }, PF_INET, EBT_BASE_CTL, EBT_SO_SET_MAX + 1, do_ebt_set_ctl, | 1480 | { |
| 1480 | EBT_BASE_CTL, EBT_SO_GET_MAX + 1, do_ebt_get_ctl, 0, NULL | 1481 | .pf = PF_INET, |
| 1482 | .set_optmin = EBT_BASE_CTL, | ||
| 1483 | .set_optmax = EBT_SO_SET_MAX + 1, | ||
| 1484 | .set = do_ebt_set_ctl, | ||
| 1485 | .get_optmin = EBT_BASE_CTL, | ||
| 1486 | .get_optmax = EBT_SO_GET_MAX + 1, | ||
| 1487 | .get = do_ebt_get_ctl, | ||
| 1481 | }; | 1488 | }; |
| 1482 | 1489 | ||
| 1483 | static int __init init(void) | 1490 | static int __init init(void) |
| 1484 | { | 1491 | { |
| 1485 | int ret; | 1492 | int ret; |
| 1486 | 1493 | ||
| 1487 | down(&ebt_mutex); | 1494 | mutex_lock(&ebt_mutex); |
| 1488 | list_named_insert(&ebt_targets, &ebt_standard_target); | 1495 | list_named_insert(&ebt_targets, &ebt_standard_target); |
| 1489 | up(&ebt_mutex); | 1496 | mutex_unlock(&ebt_mutex); |
| 1490 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) | 1497 | if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) |
| 1491 | return ret; | 1498 | return ret; |
| 1492 | 1499 | ||
