Merge branch 'work.recursive_removal' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / net / mac802154 / rx.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2007-2012 Siemens AG
4  *
5  * Written by:
6  * Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
7  * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
8  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
9  * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/netdevice.h>
15 #include <linux/crc-ccitt.h>
16 #include <asm/unaligned.h>
17
18 #include <net/mac802154.h>
19 #include <net/ieee802154_netdev.h>
20 #include <net/nl802154.h>
21
22 #include "ieee802154_i.h"
23
24 static int ieee802154_deliver_skb(struct sk_buff *skb)
25 {
26         skb->ip_summed = CHECKSUM_UNNECESSARY;
27         skb->protocol = htons(ETH_P_IEEE802154);
28
29         return netif_receive_skb(skb);
30 }
31
32 static int
33 ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
34                        struct sk_buff *skb, const struct ieee802154_hdr *hdr)
35 {
36         struct wpan_dev *wpan_dev = &sdata->wpan_dev;
37         __le16 span, sshort;
38         int rc;
39
40         pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
41
42         span = wpan_dev->pan_id;
43         sshort = wpan_dev->short_addr;
44
45         switch (mac_cb(skb)->dest.mode) {
46         case IEEE802154_ADDR_NONE:
47                 if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
48                         /* FIXME: check if we are PAN coordinator */
49                         skb->pkt_type = PACKET_OTHERHOST;
50                 else
51                         /* ACK comes with both addresses empty */
52                         skb->pkt_type = PACKET_HOST;
53                 break;
54         case IEEE802154_ADDR_LONG:
55                 if (mac_cb(skb)->dest.pan_id != span &&
56                     mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
57                         skb->pkt_type = PACKET_OTHERHOST;
58                 else if (mac_cb(skb)->dest.extended_addr == wpan_dev->extended_addr)
59                         skb->pkt_type = PACKET_HOST;
60                 else
61                         skb->pkt_type = PACKET_OTHERHOST;
62                 break;
63         case IEEE802154_ADDR_SHORT:
64                 if (mac_cb(skb)->dest.pan_id != span &&
65                     mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
66                         skb->pkt_type = PACKET_OTHERHOST;
67                 else if (mac_cb(skb)->dest.short_addr == sshort)
68                         skb->pkt_type = PACKET_HOST;
69                 else if (mac_cb(skb)->dest.short_addr ==
70                           cpu_to_le16(IEEE802154_ADDR_BROADCAST))
71                         skb->pkt_type = PACKET_BROADCAST;
72                 else
73                         skb->pkt_type = PACKET_OTHERHOST;
74                 break;
75         default:
76                 pr_debug("invalid dest mode\n");
77                 goto fail;
78         }
79
80         skb->dev = sdata->dev;
81
82         /* TODO this should be moved after netif_receive_skb call, otherwise
83          * wireshark will show a mac header with security fields and the
84          * payload is already decrypted.
85          */
86         rc = mac802154_llsec_decrypt(&sdata->sec, skb);
87         if (rc) {
88                 pr_debug("decryption failed: %i\n", rc);
89                 goto fail;
90         }
91
92         sdata->dev->stats.rx_packets++;
93         sdata->dev->stats.rx_bytes += skb->len;
94
95         switch (mac_cb(skb)->type) {
96         case IEEE802154_FC_TYPE_BEACON:
97         case IEEE802154_FC_TYPE_ACK:
98         case IEEE802154_FC_TYPE_MAC_CMD:
99                 goto fail;
100
101         case IEEE802154_FC_TYPE_DATA:
102                 return ieee802154_deliver_skb(skb);
103         default:
104                 pr_warn_ratelimited("ieee802154: bad frame received "
105                                     "(type = %d)\n", mac_cb(skb)->type);
106                 goto fail;
107         }
108
109 fail:
110         kfree_skb(skb);
111         return NET_RX_DROP;
112 }
113
114 static void
115 ieee802154_print_addr(const char *name, const struct ieee802154_addr *addr)
116 {
117         if (addr->mode == IEEE802154_ADDR_NONE)
118                 pr_debug("%s not present\n", name);
119
120         pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
121         if (addr->mode == IEEE802154_ADDR_SHORT) {
122                 pr_debug("%s is short: %04x\n", name,
123                          le16_to_cpu(addr->short_addr));
124         } else {
125                 u64 hw = swab64((__force u64)addr->extended_addr);
126
127                 pr_debug("%s is hardware: %8phC\n", name, &hw);
128         }
129 }
130
131 static int
132 ieee802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr)
133 {
134         int hlen;
135         struct ieee802154_mac_cb *cb = mac_cb_init(skb);
136
137         skb_reset_mac_header(skb);
138
139         hlen = ieee802154_hdr_pull(skb, hdr);
140         if (hlen < 0)
141                 return -EINVAL;
142
143         skb->mac_len = hlen;
144
145         pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
146                  hdr->seq);
147
148         cb->type = hdr->fc.type;
149         cb->ackreq = hdr->fc.ack_request;
150         cb->secen = hdr->fc.security_enabled;
151
152         ieee802154_print_addr("destination", &hdr->dest);
153         ieee802154_print_addr("source", &hdr->source);
154
155         cb->source = hdr->source;
156         cb->dest = hdr->dest;
157
158         if (hdr->fc.security_enabled) {
159                 u64 key;
160
161                 pr_debug("seclevel %i\n", hdr->sec.level);
162
163                 switch (hdr->sec.key_id_mode) {
164                 case IEEE802154_SCF_KEY_IMPLICIT:
165                         pr_debug("implicit key\n");
166                         break;
167
168                 case IEEE802154_SCF_KEY_INDEX:
169                         pr_debug("key %02x\n", hdr->sec.key_id);
170                         break;
171
172                 case IEEE802154_SCF_KEY_SHORT_INDEX:
173                         pr_debug("key %04x:%04x %02x\n",
174                                  le32_to_cpu(hdr->sec.short_src) >> 16,
175                                  le32_to_cpu(hdr->sec.short_src) & 0xffff,
176                                  hdr->sec.key_id);
177                         break;
178
179                 case IEEE802154_SCF_KEY_HW_INDEX:
180                         key = swab64((__force u64)hdr->sec.extended_src);
181                         pr_debug("key source %8phC %02x\n", &key,
182                                  hdr->sec.key_id);
183                         break;
184                 }
185         }
186
187         return 0;
188 }
189
190 static void
191 __ieee802154_rx_handle_packet(struct ieee802154_local *local,
192                               struct sk_buff *skb)
193 {
194         int ret;
195         struct ieee802154_sub_if_data *sdata;
196         struct ieee802154_hdr hdr;
197
198         ret = ieee802154_parse_frame_start(skb, &hdr);
199         if (ret) {
200                 pr_debug("got invalid frame\n");
201                 kfree_skb(skb);
202                 return;
203         }
204
205         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
206                 if (sdata->wpan_dev.iftype != NL802154_IFTYPE_NODE)
207                         continue;
208
209                 if (!ieee802154_sdata_running(sdata))
210                         continue;
211
212                 ieee802154_subif_frame(sdata, skb, &hdr);
213                 skb = NULL;
214                 break;
215         }
216
217         kfree_skb(skb);
218 }
219
220 static void
221 ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
222 {
223         struct sk_buff *skb2;
224         struct ieee802154_sub_if_data *sdata;
225
226         skb_reset_mac_header(skb);
227         skb->ip_summed = CHECKSUM_UNNECESSARY;
228         skb->pkt_type = PACKET_OTHERHOST;
229         skb->protocol = htons(ETH_P_IEEE802154);
230
231         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
232                 if (sdata->wpan_dev.iftype != NL802154_IFTYPE_MONITOR)
233                         continue;
234
235                 if (!ieee802154_sdata_running(sdata))
236                         continue;
237
238                 skb2 = skb_clone(skb, GFP_ATOMIC);
239                 if (skb2) {
240                         skb2->dev = sdata->dev;
241                         ieee802154_deliver_skb(skb2);
242
243                         sdata->dev->stats.rx_packets++;
244                         sdata->dev->stats.rx_bytes += skb->len;
245                 }
246         }
247 }
248
249 void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb)
250 {
251         u16 crc;
252
253         WARN_ON_ONCE(softirq_count() == 0);
254
255         if (local->suspended)
256                 goto drop;
257
258         /* TODO: When a transceiver omits the checksum here, we
259          * add an own calculated one. This is currently an ugly
260          * solution because the monitor needs a crc here.
261          */
262         if (local->hw.flags & IEEE802154_HW_RX_OMIT_CKSUM) {
263                 crc = crc_ccitt(0, skb->data, skb->len);
264                 put_unaligned_le16(crc, skb_put(skb, 2));
265         }
266
267         rcu_read_lock();
268
269         ieee802154_monitors_rx(local, skb);
270
271         /* Check if transceiver doesn't validate the checksum.
272          * If not we validate the checksum here.
273          */
274         if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM) {
275                 crc = crc_ccitt(0, skb->data, skb->len);
276                 if (crc) {
277                         rcu_read_unlock();
278                         goto drop;
279                 }
280         }
281         /* remove crc */
282         skb_trim(skb, skb->len - 2);
283
284         __ieee802154_rx_handle_packet(local, skb);
285
286         rcu_read_unlock();
287
288         return;
289 drop:
290         kfree_skb(skb);
291 }
292
293 void
294 ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi)
295 {
296         struct ieee802154_local *local = hw_to_local(hw);
297
298         mac_cb(skb)->lqi = lqi;
299         skb->pkt_type = IEEE802154_RX_MSG;
300         skb_queue_tail(&local->skb_queue, skb);
301         tasklet_schedule(&local->tasklet);
302 }
303 EXPORT_SYMBOL(ieee802154_rx_irqsafe);