aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154
diff options
context:
space:
mode:
authorAlan Ott <alan@signal11.us>2013-01-16 14:09:48 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-18 14:18:30 -0500
commitee21c7e0d1f6e742e9f441f580a3bac316a39a21 (patch)
tree36baeee5552a9256ee607d35eb4e21221f537adc /net/ieee802154
parent0c446212c4f68e51ba03a9b172599437d6660a9d (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.c41
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;