cleanup
[linux-2.4.21-pre4.git] / net / bridge / br_input.c
1 /*
2  *      Handle incoming frames
3  *      Linux ethernet bridge
4  *
5  *      Authors:
6  *      Lennert Buytenhek               <buytenh@gnu.org>
7  *
8  *      $Id: br_input.c,v 1.1.1.1 2005/04/11 02:51:12 jack Exp $
9  *
10  *      This program is free software; you can redistribute it and/or
11  *      modify it under the terms of the GNU General Public License
12  *      as published by the Free Software Foundation; either version
13  *      2 of the License, or (at your option) any later version.
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/netdevice.h>
18 #include <linux/etherdevice.h>
19 #include <linux/if_bridge.h>
20 #include <linux/netfilter_bridge.h>
21 #include "br_private.h"
22
23 unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
24 extern long Packets; //jack20040813+
25
26 static int br_pass_frame_up_finish(struct sk_buff *skb)
27 {
28 #ifdef CONFIG_NETFILTER_DEBUG
29         skb->nf_debug = 0;
30 #endif
31         netif_rx(skb);
32
33         return 0;
34 }
35
36 static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
37 {
38         struct net_device *indev;
39
40         br->statistics.rx_packets++;
41         Packets++;      //jack20040813+
42         br->statistics.rx_bytes += skb->len;
43
44         indev = skb->dev;
45         skb->dev = &br->dev;
46         skb->pkt_type = PACKET_HOST;
47         skb_push(skb, ETH_HLEN);
48         skb->protocol = eth_type_trans(skb, &br->dev);
49
50         NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
51                         br_pass_frame_up_finish);
52 }
53
54 static int br_handle_frame_finish(struct sk_buff *skb)
55 {
56         struct net_bridge *br;
57         unsigned char *dest;
58         struct net_bridge_fdb_entry *dst;
59         struct net_bridge_port *p;
60         int passedup;
61
62         dest = skb->mac.ethernet->h_dest;
63
64         p = skb->dev->br_port;
65         if (p == NULL)
66                 goto err_nolock;
67
68         br = p->br;
69         read_lock(&br->lock);
70         if (skb->dev->br_port == NULL)
71                 goto err;
72
73         passedup = 0;
74         if (br->dev.flags & IFF_PROMISC) {
75                 struct sk_buff *skb2;
76
77                 skb2 = skb_clone(skb, GFP_ATOMIC);
78                 if (skb2 != NULL) {
79                         passedup = 1;
80                         br_pass_frame_up(br, skb2);
81                 }
82         }
83
84         if (dest[0] & 1) {
85                 br_flood_forward(br, skb, !passedup);
86                 if (!passedup)
87                         br_pass_frame_up(br, skb);
88                 goto out;
89         }
90
91         dst = br_fdb_get(br, dest);
92         if (dst != NULL && dst->is_local) {
93                 if (!passedup)
94                         br_pass_frame_up(br, skb);
95                 else
96                         kfree_skb(skb);
97                 br_fdb_put(dst);
98                 goto out;
99         }
100
101         if (dst != NULL) {
102                 br_forward(dst->dst, skb);
103                 br_fdb_put(dst);
104                 goto out;
105         }
106
107         br_flood_forward(br, skb, 0);
108
109 out:
110         read_unlock(&br->lock);
111         return 0;
112
113 err:
114         read_unlock(&br->lock);
115 err_nolock:
116         kfree_skb(skb);
117         return 0;
118 }
119
120 int br_handle_frame(struct sk_buff *skb)
121 {
122         struct net_bridge *br;
123         unsigned char *dest;
124         struct net_bridge_port *p;
125
126         dest = skb->mac.ethernet->h_dest;
127
128         p = skb->dev->br_port;
129         if (p == NULL)
130                 goto err_nolock;
131
132         br = p->br;
133         read_lock(&br->lock);
134         if (skb->dev->br_port == NULL)
135                 goto err;
136
137         if (!(br->dev.flags & IFF_UP) ||
138             p->state == BR_STATE_DISABLED)
139                 goto err;
140
141         if (skb->mac.ethernet->h_source[0] & 1)
142                 goto err;
143
144         if (p->state == BR_STATE_LEARNING ||
145             p->state == BR_STATE_FORWARDING)
146                 br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
147
148         if (br->stp_enabled &&
149             !memcmp(dest, bridge_ula, 5) &&
150             !(dest[5] & 0xF0))
151                 goto handle_special_frame;
152
153         if (p->state == BR_STATE_FORWARDING) {
154                 if (br_should_route_hook && br_should_route_hook(&skb)) {
155                         read_unlock(&br->lock);
156                         return -1;
157                 }
158
159                 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
160                         br_handle_frame_finish);
161                 read_unlock(&br->lock);
162                 return 0;
163         }
164
165 err:
166         read_unlock(&br->lock);
167 err_nolock:
168         kfree_skb(skb);
169         return 0;
170
171 handle_special_frame:
172         if (!dest[5]) {
173                 br_stp_handle_bpdu(skb);
174                 read_unlock(&br->lock);
175                 return 0;
176         }
177
178         read_unlock(&br->lock);
179         kfree_skb(skb);
180         return 0;
181 }