diff options
author | Alan Ott <alan@signal11.us> | 2013-01-16 14:09:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-18 14:18:30 -0500 |
commit | ee21c7e0d1f6e742e9f441f580a3bac316a39a21 (patch) | |
tree | 36baeee5552a9256ee607d35eb4e21221f537adc /net/ieee802154 | |
parent | 0c446212c4f68e51ba03a9b172599437d6660a9d (diff) |
6lowpan: Handle uncompressed IPv6 packets over 6LoWPAN
Handle the reception of uncompressed packets (dispatch type = IPv6).
Signed-off-by: Alan Ott <alan@signal11.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/6lowpan.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 1714cfab1220..09cba81d2c4a 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c | |||
@@ -1147,19 +1147,42 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1147 | goto drop; | 1147 | goto drop; |
1148 | 1148 | ||
1149 | /* check that it's our buffer */ | 1149 | /* check that it's our buffer */ |
1150 | switch (skb->data[0] & 0xe0) { | 1150 | if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { |
1151 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | 1151 | /* Copy the packet so that the IPv6 header is |
1152 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ | 1152 | * properly aligned. |
1153 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ | 1153 | */ |
1154 | local_skb = skb_clone(skb, GFP_ATOMIC); | 1154 | local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1, |
1155 | skb_tailroom(skb), GFP_ATOMIC); | ||
1155 | if (!local_skb) | 1156 | if (!local_skb) |
1156 | goto drop; | 1157 | goto drop; |
1157 | lowpan_process_data(local_skb); | ||
1158 | 1158 | ||
1159 | local_skb->protocol = htons(ETH_P_IPV6); | ||
1160 | local_skb->pkt_type = PACKET_HOST; | ||
1161 | |||
1162 | /* Pull off the 1-byte of 6lowpan header. */ | ||
1163 | skb_pull(local_skb, 1); | ||
1164 | skb_reset_network_header(local_skb); | ||
1165 | skb_set_transport_header(local_skb, sizeof(struct ipv6hdr)); | ||
1166 | |||
1167 | lowpan_give_skb_to_devices(local_skb); | ||
1168 | |||
1169 | kfree_skb(local_skb); | ||
1159 | kfree_skb(skb); | 1170 | kfree_skb(skb); |
1160 | break; | 1171 | } else { |
1161 | default: | 1172 | switch (skb->data[0] & 0xe0) { |
1162 | break; | 1173 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ |
1174 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ | ||
1175 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ | ||
1176 | local_skb = skb_clone(skb, GFP_ATOMIC); | ||
1177 | if (!local_skb) | ||
1178 | goto drop; | ||
1179 | lowpan_process_data(local_skb); | ||
1180 | |||
1181 | kfree_skb(skb); | ||
1182 | break; | ||
1183 | default: | ||
1184 | break; | ||
1185 | } | ||
1163 | } | 1186 | } |
1164 | 1187 | ||
1165 | return NET_RX_SUCCESS; | 1188 | return NET_RX_SUCCESS; |