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_devices(struct sk_buff
*skb
,
19 struct net_device
*dev
)
21 struct lowpan_dev_record
*entry
;
22 struct sk_buff
*skb_cp
;
23 int stat
= NET_RX_SUCCESS
;
25 skb
->protocol
= htons(ETH_P_IPV6
);
26 skb
->pkt_type
= PACKET_HOST
;
29 list_for_each_entry_rcu(entry
, &lowpan_devices
, list
)
30 if (lowpan_dev_info(entry
->ldev
)->real_dev
== skb
->dev
) {
31 skb_cp
= skb_copy(skb
, GFP_ATOMIC
);
38 skb_cp
->dev
= entry
->ldev
;
39 stat
= netif_rx(skb_cp
);
40 if (stat
== NET_RX_DROP
)
51 iphc_decompress(struct sk_buff
*skb
, const struct ieee802154_hdr
*hdr
)
54 struct ieee802154_addr_sa sa
, da
;
57 raw_dump_table(__func__
, "raw skb data dump", skb
->data
, skb
->len
);
58 /* at least two bytes will be used for the encoding */
62 if (lowpan_fetch_skb_u8(skb
, &iphc0
))
65 if (lowpan_fetch_skb_u8(skb
, &iphc1
))
68 ieee802154_addr_to_sa(&sa
, &hdr
->source
);
69 ieee802154_addr_to_sa(&da
, &hdr
->dest
);
71 if (sa
.addr_type
== IEEE802154_ADDR_SHORT
)
76 if (da
.addr_type
== IEEE802154_ADDR_SHORT
)
81 return lowpan_header_decompress(skb
, skb
->dev
, sap
, sa
.addr_type
,
82 IEEE802154_ADDR_LEN
, dap
, da
.addr_type
,
83 IEEE802154_ADDR_LEN
, iphc0
, iphc1
);
86 static int lowpan_rcv(struct sk_buff
*skb
, struct net_device
*dev
,
87 struct packet_type
*pt
, struct net_device
*orig_dev
)
89 struct ieee802154_hdr hdr
;
92 skb
= skb_share_check(skb
, GFP_ATOMIC
);
96 if (!netif_running(dev
))
99 if (skb
->pkt_type
== PACKET_OTHERHOST
)
102 if (dev
->type
!= ARPHRD_IEEE802154
)
105 if (ieee802154_hdr_peek_addrs(skb
, &hdr
) < 0)
108 /* check that it's our buffer */
109 if (skb
->data
[0] == LOWPAN_DISPATCH_IPV6
) {
110 /* Pull off the 1-byte of 6lowpan header. */
112 return lowpan_give_skb_to_devices(skb
, NULL
);
114 switch (skb
->data
[0] & 0xe0) {
115 case LOWPAN_DISPATCH_IPHC
: /* ipv6 datagram */
116 ret
= iphc_decompress(skb
, &hdr
);
120 return lowpan_give_skb_to_devices(skb
, NULL
);
121 case LOWPAN_DISPATCH_FRAG1
: /* first fragment header */
122 ret
= lowpan_frag_rcv(skb
, LOWPAN_DISPATCH_FRAG1
);
124 ret
= iphc_decompress(skb
, &hdr
);
128 return lowpan_give_skb_to_devices(skb
, NULL
);
129 } else if (ret
== -1) {
132 return NET_RX_SUCCESS
;
134 case LOWPAN_DISPATCH_FRAGN
: /* next fragments headers */
135 ret
= lowpan_frag_rcv(skb
, LOWPAN_DISPATCH_FRAGN
);
137 ret
= iphc_decompress(skb
, &hdr
);
141 return lowpan_give_skb_to_devices(skb
, NULL
);
142 } else if (ret
== -1) {
145 return NET_RX_SUCCESS
;
158 static struct packet_type lowpan_packet_type
= {
159 .type
= htons(ETH_P_IEEE802154
),
163 void lowpan_rx_init(void)
165 dev_add_pack(&lowpan_packet_type
);
168 void lowpan_rx_exit(void)
170 dev_remove_pack(&lowpan_packet_type
);