|
@@ -89,6 +89,40 @@ static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb)
|
|
|
return skb;
|
|
|
}
|
|
|
|
|
|
+static inline void vlan_set_encap_proto(struct sk_buff *skb,
|
|
|
+ struct vlan_hdr *vhdr)
|
|
|
+{
|
|
|
+ __be16 proto;
|
|
|
+ unsigned char *rawp;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Was a VLAN packet, grab the encapsulated protocol, which the layer
|
|
|
+ * three protocols care about.
|
|
|
+ */
|
|
|
+
|
|
|
+ proto = vhdr->h_vlan_encapsulated_proto;
|
|
|
+ if (ntohs(proto) >= 1536) {
|
|
|
+ skb->protocol = proto;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ rawp = skb->data;
|
|
|
+ if (*(unsigned short *)rawp == 0xFFFF)
|
|
|
+ /*
|
|
|
+ * This is a magic hack to spot IPX packets. Older Novell
|
|
|
+ * breaks the protocol design and runs IPX over 802.3 without
|
|
|
+ * an 802.2 LLC layer. We look for FFFF which isn't a used
|
|
|
+ * 802.2 SSAP/DSAP. This won't work for fault tolerant netware
|
|
|
+ * but does for the rest.
|
|
|
+ */
|
|
|
+ skb->protocol = htons(ETH_P_802_3);
|
|
|
+ else
|
|
|
+ /*
|
|
|
+ * Real 802.2 LLC
|
|
|
+ */
|
|
|
+ skb->protocol = htons(ETH_P_802_2);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Determine the packet's protocol ID. The rule here is that we
|
|
|
* 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)
|
|
|
int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
|
|
struct packet_type *ptype, struct net_device *orig_dev)
|
|
|
{
|
|
|
- unsigned char *rawp;
|
|
|
struct vlan_hdr *vhdr;
|
|
|
unsigned short vid;
|
|
|
struct net_device_stats *stats;
|
|
|
unsigned short vlan_TCI;
|
|
|
- __be16 proto;
|
|
|
|
|
|
if (dev->nd_net != &init_net)
|
|
|
goto err_free;
|
|
@@ -179,33 +211,8 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- /* Was a VLAN packet, grab the encapsulated protocol, which the layer
|
|
|
- * three protocols care about.
|
|
|
- */
|
|
|
- proto = vhdr->h_vlan_encapsulated_proto;
|
|
|
- if (ntohs(proto) >= 1536) {
|
|
|
- skb->protocol = proto;
|
|
|
- goto recv;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * This is a magic hack to spot IPX packets. Older Novell breaks
|
|
|
- * the protocol design and runs IPX over 802.3 without an 802.2 LLC
|
|
|
- * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
|
|
|
- * won't work for fault tolerant netware but does for the rest.
|
|
|
- */
|
|
|
- rawp = skb->data;
|
|
|
- if (*(unsigned short *)rawp == 0xFFFF) {
|
|
|
- skb->protocol = htons(ETH_P_802_3);
|
|
|
- goto recv;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * Real 802.2 LLC
|
|
|
- */
|
|
|
- skb->protocol = htons(ETH_P_802_2);
|
|
|
+ vlan_set_encap_proto(skb, vhdr);
|
|
|
|
|
|
-recv:
|
|
|
skb = vlan_check_reorder_header(skb);
|
|
|
if (!skb) {
|
|
|
stats->rx_errors++;
|