blob: 12e10201d263860d64cc7835bd947459e4d95873 [file] [log] [blame]
Alexander Aring4662a0d2015-01-04 17:10:55 +01001/* 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.
4 *
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.
9 */
10
11#include <linux/if_arp.h>
12
13#include <net/6lowpan.h>
14#include <net/ieee802154_netdev.h>
15
16#include "6lowpan_i.h"
17
Alexander Aring51e0e5d2015-08-10 21:15:53 +020018static int lowpan_give_skb_to_device(struct sk_buff *skb,
19 struct net_device *dev)
Alexander Aring4662a0d2015-01-04 17:10:55 +010020{
Alexander Aring51e0e5d2015-08-10 21:15:53 +020021 skb->dev = dev->ieee802154_ptr->lowpan_dev;
Alexander Aring4662a0d2015-01-04 17:10:55 +010022 skb->protocol = htons(ETH_P_IPV6);
23 skb->pkt_type = PACKET_HOST;
24
Alexander Aring51e0e5d2015-08-10 21:15:53 +020025 return netif_rx(skb);
Alexander Aring4662a0d2015-01-04 17:10:55 +010026}
27
28static int
29iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
30{
31 u8 iphc0, iphc1;
32 struct ieee802154_addr_sa sa, da;
33 void *sap, *dap;
34
35 raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
36 /* at least two bytes will be used for the encoding */
37 if (skb->len < 2)
38 return -EINVAL;
39
40 if (lowpan_fetch_skb_u8(skb, &iphc0))
41 return -EINVAL;
42
43 if (lowpan_fetch_skb_u8(skb, &iphc1))
44 return -EINVAL;
45
46 ieee802154_addr_to_sa(&sa, &hdr->source);
47 ieee802154_addr_to_sa(&da, &hdr->dest);
48
49 if (sa.addr_type == IEEE802154_ADDR_SHORT)
50 sap = &sa.short_addr;
51 else
52 sap = &sa.hwaddr;
53
54 if (da.addr_type == IEEE802154_ADDR_SHORT)
55 dap = &da.short_addr;
56 else
57 dap = &da.hwaddr;
58
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);
62}
63
64static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
65 struct packet_type *pt, struct net_device *orig_dev)
66{
67 struct ieee802154_hdr hdr;
68 int ret;
69
Alexander Aringc0015bf2015-08-15 11:00:33 +020070 if (dev->type != ARPHRD_IEEE802154 ||
71 !dev->ieee802154_ptr->lowpan_dev)
72 goto drop;
73
Alexander Aring4662a0d2015-01-04 17:10:55 +010074 skb = skb_share_check(skb, GFP_ATOMIC);
75 if (!skb)
76 goto drop;
77
78 if (!netif_running(dev))
79 goto drop_skb;
80
81 if (skb->pkt_type == PACKET_OTHERHOST)
82 goto drop_skb;
83
Alexander Aring4662a0d2015-01-04 17:10:55 +010084 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0)
85 goto drop_skb;
86
87 /* check that it's our buffer */
88 if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
89 /* Pull off the 1-byte of 6lowpan header. */
90 skb_pull(skb, 1);
Alexander Aring51e0e5d2015-08-10 21:15:53 +020091 return lowpan_give_skb_to_device(skb, dev);
Alexander Aring4662a0d2015-01-04 17:10:55 +010092 } else {
93 switch (skb->data[0] & 0xe0) {
94 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
95 ret = iphc_decompress(skb, &hdr);
96 if (ret < 0)
97 goto drop_skb;
98
Alexander Aring51e0e5d2015-08-10 21:15:53 +020099 return lowpan_give_skb_to_device(skb, dev);
Alexander Aring4662a0d2015-01-04 17:10:55 +0100100 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
101 ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
102 if (ret == 1) {
103 ret = iphc_decompress(skb, &hdr);
104 if (ret < 0)
105 goto drop_skb;
106
Alexander Aring51e0e5d2015-08-10 21:15:53 +0200107 return lowpan_give_skb_to_device(skb, dev);
Alexander Aring4662a0d2015-01-04 17:10:55 +0100108 } else if (ret == -1) {
109 return NET_RX_DROP;
110 } else {
111 return NET_RX_SUCCESS;
112 }
113 case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
114 ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
115 if (ret == 1) {
116 ret = iphc_decompress(skb, &hdr);
117 if (ret < 0)
118 goto drop_skb;
119
Alexander Aring51e0e5d2015-08-10 21:15:53 +0200120 return lowpan_give_skb_to_device(skb, dev);
Alexander Aring4662a0d2015-01-04 17:10:55 +0100121 } else if (ret == -1) {
122 return NET_RX_DROP;
123 } else {
124 return NET_RX_SUCCESS;
125 }
126 default:
127 break;
128 }
129 }
130
131drop_skb:
132 kfree_skb(skb);
133drop:
134 return NET_RX_DROP;
135}
136
137static struct packet_type lowpan_packet_type = {
138 .type = htons(ETH_P_IEEE802154),
139 .func = lowpan_rcv,
140};
141
142void lowpan_rx_init(void)
143{
144 dev_add_pack(&lowpan_packet_type);
145}
146
147void lowpan_rx_exit(void)
148{
149 dev_remove_pack(&lowpan_packet_type);
150}