1 /* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License version 2
3 * as published by the Free Software Foundation.
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
11 #include <linux/if_arp.h>
13 #include <net/6lowpan.h>
14 #include <net/ieee802154_netdev.h>
16 #include "6lowpan_i.h"
18 static int lowpan_give_skb_to_device(struct sk_buff
*skb
,
19 struct net_device
*dev
)
21 skb
->dev
= dev
->ieee802154_ptr
->lowpan_dev
;
22 skb
->protocol
= htons(ETH_P_IPV6
);
23 skb
->pkt_type
= PACKET_HOST
;
29 iphc_decompress(struct sk_buff
*skb
, const struct ieee802154_hdr
*hdr
)
32 struct ieee802154_addr_sa sa
, da
;
35 raw_dump_table(__func__
, "raw skb data dump", skb
->data
, skb
->len
);
36 /* at least two bytes will be used for the encoding */
40 if (lowpan_fetch_skb_u8(skb
, &iphc0
))
43 if (lowpan_fetch_skb_u8(skb
, &iphc1
))
46 ieee802154_addr_to_sa(&sa
, &hdr
->source
);
47 ieee802154_addr_to_sa(&da
, &hdr
->dest
);
49 if (sa
.addr_type
== IEEE802154_ADDR_SHORT
)
54 if (da
.addr_type
== IEEE802154_ADDR_SHORT
)
59 return lowpan_header_decompress(skb
, skb
->dev
, sap
, sa
.addr_type
,
60 IEEE802154_ADDR_LEN
, dap
, da
.addr_type
,
61 IEEE802154_ADDR_LEN
, iphc0
, iphc1
);
64 static int lowpan_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
65 struct packet_type
*pt
, struct net_device
*orig_dev
)
67 struct ieee802154_hdr hdr
;
70 skb
= skb_share_check(skb
, GFP_ATOMIC
);
74 if (!netif_running(dev
))
77 if (skb
->pkt_type
== PACKET_OTHERHOST
)
80 if (dev
->type
!= ARPHRD_IEEE802154
)
83 if (ieee802154_hdr_peek_addrs(skb
, &hdr
) < 0)
86 /* check that it's our buffer */
87 if (skb
->data
[0] == LOWPAN_DISPATCH_IPV6
) {
88 /* Pull off the 1-byte of 6lowpan header. */
90 return lowpan_give_skb_to_device(skb
, dev
);
92 switch (skb
->data
[0] & 0xe0) {
93 case LOWPAN_DISPATCH_IPHC
: /* ipv6 datagram */
94 ret
= iphc_decompress(skb
, &hdr
);
98 return lowpan_give_skb_to_device(skb
, dev
);
99 case LOWPAN_DISPATCH_FRAG1
: /* first fragment header */
100 ret
= lowpan_frag_rcv(skb
, LOWPAN_DISPATCH_FRAG1
);
102 ret
= iphc_decompress(skb
, &hdr
);
106 return lowpan_give_skb_to_device(skb
, dev
);
107 } else if (ret
== -1) {
110 return NET_RX_SUCCESS
;
112 case LOWPAN_DISPATCH_FRAGN
: /* next fragments headers */
113 ret
= lowpan_frag_rcv(skb
, LOWPAN_DISPATCH_FRAGN
);
115 ret
= iphc_decompress(skb
, &hdr
);
119 return lowpan_give_skb_to_device(skb
, dev
);
120 } else if (ret
== -1) {
123 return NET_RX_SUCCESS
;
136 static struct packet_type lowpan_packet_type
= {
137 .type
= htons(ETH_P_IEEE802154
),
141 void lowpan_rx_init(void)
143 dev_add_pack(&lowpan_packet_type
);
146 void lowpan_rx_exit(void)
148 dev_remove_pack(&lowpan_packet_type
);