diff options
-rw-r--r-- | net/8021q/vlan_dev.c | 63 |
1 files changed, 35 insertions, 28 deletions
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 57799af51088..8059fa42b085 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -89,6 +89,40 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | |||
89 | return skb; | 89 | return skb; |
90 | } | 90 | } |
91 | 91 | ||
92 | static inline void vlan_set_encap_proto(struct sk_buff *skb, | ||
93 | struct vlan_hdr *vhdr) | ||
94 | { | ||
95 | __be16 proto; | ||
96 | unsigned char *rawp; | ||
97 | |||
98 | /* | ||
99 | * Was a VLAN packet, grab the encapsulated protocol, which the layer | ||
100 | * three protocols care about. | ||
101 | */ | ||
102 | |||
103 | proto = vhdr->h_vlan_encapsulated_proto; | ||
104 | if (ntohs(proto) >= 1536) { | ||
105 | skb->protocol = proto; | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | rawp = skb->data; | ||
110 | if (*(unsigned short *)rawp == 0xFFFF) | ||
111 | /* | ||
112 | * This is a magic hack to spot IPX packets. Older Novell | ||
113 | * breaks the protocol design and runs IPX over 802.3 without | ||
114 | * an 802.2 LLC layer. We look for FFFF which isn't a used | ||
115 | * 802.2 SSAP/DSAP. This won't work for fault tolerant netware | ||
116 | * but does for the rest. | ||
117 | */ | ||
118 | skb->protocol = htons(ETH_P_802_3); | ||
119 | else | ||
120 | /* | ||
121 | * Real 802.2 LLC | ||
122 | */ | ||
123 | skb->protocol = htons(ETH_P_802_2); | ||
124 | } | ||
125 | |||
92 | /* | 126 | /* |
93 | * Determine the packet's protocol ID. The rule here is that we | 127 | * Determine the packet's protocol ID. The rule here is that we |
94 | * assume 802.3 if the type field is short enough to be a length. | 128 | * assume 802.3 if the type field is short enough to be a length. |
@@ -114,12 +148,10 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | |||
114 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | 148 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, |
115 | struct packet_type *ptype, struct net_device *orig_dev) | 149 | struct packet_type *ptype, struct net_device *orig_dev) |
116 | { | 150 | { |
117 | unsigned char *rawp; | ||
118 | struct vlan_hdr *vhdr; | 151 | struct vlan_hdr *vhdr; |
119 | unsigned short vid; | 152 | unsigned short vid; |
120 | struct net_device_stats *stats; | 153 | struct net_device_stats *stats; |
121 | unsigned short vlan_TCI; | 154 | unsigned short vlan_TCI; |
122 | __be16 proto; | ||
123 | 155 | ||
124 | if (dev->nd_net != &init_net) | 156 | if (dev->nd_net != &init_net) |
125 | goto err_free; | 157 | goto err_free; |
@@ -179,33 +211,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
179 | break; | 211 | break; |
180 | } | 212 | } |
181 | 213 | ||
182 | /* Was a VLAN packet, grab the encapsulated protocol, which the layer | 214 | vlan_set_encap_proto(skb, vhdr); |
183 | * three protocols care about. | ||
184 | */ | ||
185 | proto = vhdr->h_vlan_encapsulated_proto; | ||
186 | if (ntohs(proto) >= 1536) { | ||
187 | skb->protocol = proto; | ||
188 | goto recv; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * This is a magic hack to spot IPX packets. Older Novell breaks | ||
193 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC | ||
194 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | ||
195 | * won't work for fault tolerant netware but does for the rest. | ||
196 | */ | ||
197 | rawp = skb->data; | ||
198 | if (*(unsigned short *)rawp == 0xFFFF) { | ||
199 | skb->protocol = htons(ETH_P_802_3); | ||
200 | goto recv; | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Real 802.2 LLC | ||
205 | */ | ||
206 | skb->protocol = htons(ETH_P_802_2); | ||
207 | 215 | ||
208 | recv: | ||
209 | skb = vlan_check_reorder_header(skb); | 216 | skb = vlan_check_reorder_header(skb); |
210 | if (!skb) { | 217 | if (!skb) { |
211 | stats->rx_errors++; | 218 | stats->rx_errors++; |