mac802154: add ifname change notifier
[deliverable/linux.git] / net / mac802154 / iface.c
1 /*
2 * Copyright 2007-2012 Siemens AG
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * Written by:
14 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
15 * Sergey Lapin <slapin@ossfans.org>
16 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
17 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
18 */
19
20 #include <linux/netdevice.h>
21 #include <linux/module.h>
22 #include <linux/if_arp.h>
23 #include <linux/ieee802154.h>
24
25 #include <net/rtnetlink.h>
26 #include <linux/nl802154.h>
27 #include <net/mac802154.h>
28 #include <net/ieee802154_netdev.h>
29 #include <net/cfg802154.h>
30
31 #include "ieee802154_i.h"
32 #include "driver-ops.h"
33
34 static int mac802154_wpan_update_llsec(struct net_device *dev)
35 {
36 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
37 struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
38 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
39 int rc = 0;
40
41 if (ops->llsec) {
42 struct ieee802154_llsec_params params;
43 int changed = 0;
44
45 params.pan_id = wpan_dev->pan_id;
46 changed |= IEEE802154_LLSEC_PARAM_PAN_ID;
47
48 params.hwaddr = wpan_dev->extended_addr;
49 changed |= IEEE802154_LLSEC_PARAM_HWADDR;
50
51 rc = ops->llsec->set_params(dev, &params, changed);
52 }
53
54 return rc;
55 }
56
57 static int
58 mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
59 {
60 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
61 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
62 struct sockaddr_ieee802154 *sa =
63 (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
64 int err = -ENOIOCTLCMD;
65
66 ASSERT_RTNL();
67
68 spin_lock_bh(&sdata->mib_lock);
69
70 switch (cmd) {
71 case SIOCGIFADDR:
72 {
73 u16 pan_id, short_addr;
74
75 pan_id = le16_to_cpu(wpan_dev->pan_id);
76 short_addr = le16_to_cpu(wpan_dev->short_addr);
77 if (pan_id == IEEE802154_PANID_BROADCAST ||
78 short_addr == IEEE802154_ADDR_BROADCAST) {
79 err = -EADDRNOTAVAIL;
80 break;
81 }
82
83 sa->family = AF_IEEE802154;
84 sa->addr.addr_type = IEEE802154_ADDR_SHORT;
85 sa->addr.pan_id = pan_id;
86 sa->addr.short_addr = short_addr;
87
88 err = 0;
89 break;
90 }
91 case SIOCSIFADDR:
92 if (netif_running(dev)) {
93 spin_unlock_bh(&sdata->mib_lock);
94 return -EBUSY;
95 }
96
97 dev_warn(&dev->dev,
98 "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
99 if (sa->family != AF_IEEE802154 ||
100 sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
101 sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
102 sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
103 sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
104 err = -EINVAL;
105 break;
106 }
107
108 wpan_dev->pan_id = cpu_to_le16(sa->addr.pan_id);
109 wpan_dev->short_addr = cpu_to_le16(sa->addr.short_addr);
110
111 err = mac802154_wpan_update_llsec(dev);
112 break;
113 }
114
115 spin_unlock_bh(&sdata->mib_lock);
116 return err;
117 }
118
119 static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
120 {
121 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
122 struct sockaddr *addr = p;
123 __le64 extended_addr;
124
125 if (netif_running(dev))
126 return -EBUSY;
127
128 ieee802154_be64_to_le64(&extended_addr, addr->sa_data);
129 if (!ieee802154_is_valid_extended_addr(extended_addr))
130 return -EINVAL;
131
132 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
133 sdata->wpan_dev.extended_addr = extended_addr;
134
135 return mac802154_wpan_update_llsec(dev);
136 }
137
138 static int mac802154_slave_open(struct net_device *dev)
139 {
140 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
141 struct ieee802154_sub_if_data *subif;
142 struct ieee802154_local *local = sdata->local;
143 int res = 0;
144
145 ASSERT_RTNL();
146
147 if (sdata->vif.type == IEEE802154_DEV_WPAN) {
148 mutex_lock(&sdata->local->iflist_mtx);
149 list_for_each_entry(subif, &sdata->local->interfaces, list) {
150 if (subif != sdata &&
151 subif->vif.type == sdata->vif.type &&
152 ieee802154_sdata_running(subif)) {
153 mutex_unlock(&sdata->local->iflist_mtx);
154 return -EBUSY;
155 }
156 }
157 mutex_unlock(&sdata->local->iflist_mtx);
158 }
159
160 set_bit(SDATA_STATE_RUNNING, &sdata->state);
161
162 if (!local->open_count) {
163 res = drv_start(local);
164 WARN_ON(res);
165 if (res)
166 goto err;
167 }
168
169 local->open_count++;
170 netif_start_queue(dev);
171 return 0;
172 err:
173 /* might already be clear but that doesn't matter */
174 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
175
176 return res;
177 }
178
179 static int mac802154_wpan_open(struct net_device *dev)
180 {
181 int rc;
182 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
183 struct ieee802154_local *local = sdata->local;
184 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
185 struct wpan_phy *phy = sdata->local->phy;
186
187 rc = mac802154_slave_open(dev);
188 if (rc < 0)
189 return rc;
190
191 mutex_lock(&phy->pib_lock);
192
193 if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
194 rc = drv_set_promiscuous_mode(local,
195 wpan_dev->promiscuous_mode);
196 if (rc < 0)
197 goto out;
198 }
199
200 if (local->hw.flags & IEEE802154_HW_AFILT) {
201 rc = drv_set_pan_id(local, wpan_dev->pan_id);
202 if (rc < 0)
203 goto out;
204
205 rc = drv_set_extended_addr(local, wpan_dev->extended_addr);
206 if (rc < 0)
207 goto out;
208
209 rc = drv_set_short_addr(local, wpan_dev->short_addr);
210 if (rc < 0)
211 goto out;
212 }
213
214 if (local->hw.flags & IEEE802154_HW_LBT) {
215 rc = drv_set_lbt_mode(local, wpan_dev->lbt);
216 if (rc < 0)
217 goto out;
218 }
219
220 if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) {
221 rc = drv_set_csma_params(local, wpan_dev->min_be,
222 wpan_dev->max_be,
223 wpan_dev->csma_retries);
224 if (rc < 0)
225 goto out;
226 }
227
228 if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) {
229 rc = drv_set_max_frame_retries(local, wpan_dev->frame_retries);
230 if (rc < 0)
231 goto out;
232 }
233
234 mutex_unlock(&phy->pib_lock);
235 return 0;
236
237 out:
238 mutex_unlock(&phy->pib_lock);
239 return rc;
240 }
241
242 static int mac802154_slave_close(struct net_device *dev)
243 {
244 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
245 struct ieee802154_local *local = sdata->local;
246
247 ASSERT_RTNL();
248
249 netif_stop_queue(dev);
250 local->open_count--;
251
252 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
253
254 if (!local->open_count)
255 drv_stop(local);
256
257 return 0;
258 }
259
260 static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata,
261 struct ieee802154_hdr *hdr,
262 const struct ieee802154_mac_cb *cb)
263 {
264 struct ieee802154_llsec_params params;
265 u8 level;
266
267 mac802154_llsec_get_params(&sdata->sec, &params);
268
269 if (!params.enabled && cb->secen_override && cb->secen)
270 return -EINVAL;
271 if (!params.enabled ||
272 (cb->secen_override && !cb->secen) ||
273 !params.out_level)
274 return 0;
275 if (cb->seclevel_override && !cb->seclevel)
276 return -EINVAL;
277
278 level = cb->seclevel_override ? cb->seclevel : params.out_level;
279
280 hdr->fc.security_enabled = 1;
281 hdr->sec.level = level;
282 hdr->sec.key_id_mode = params.out_key.mode;
283 if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
284 hdr->sec.short_src = params.out_key.short_source;
285 else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
286 hdr->sec.extended_src = params.out_key.extended_source;
287 hdr->sec.key_id = params.out_key.id;
288
289 return 0;
290 }
291
292 static int mac802154_header_create(struct sk_buff *skb,
293 struct net_device *dev,
294 unsigned short type,
295 const void *daddr,
296 const void *saddr,
297 unsigned len)
298 {
299 struct ieee802154_hdr hdr;
300 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
301 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
302 struct ieee802154_mac_cb *cb = mac_cb(skb);
303 int hlen;
304
305 if (!daddr)
306 return -EINVAL;
307
308 memset(&hdr.fc, 0, sizeof(hdr.fc));
309 hdr.fc.type = cb->type;
310 hdr.fc.security_enabled = cb->secen;
311 hdr.fc.ack_request = cb->ackreq;
312 hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
313
314 if (mac802154_set_header_security(sdata, &hdr, cb) < 0)
315 return -EINVAL;
316
317 if (!saddr) {
318 spin_lock_bh(&sdata->mib_lock);
319
320 if (wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
321 wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
322 wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
323 hdr.source.mode = IEEE802154_ADDR_LONG;
324 hdr.source.extended_addr = wpan_dev->extended_addr;
325 } else {
326 hdr.source.mode = IEEE802154_ADDR_SHORT;
327 hdr.source.short_addr = wpan_dev->short_addr;
328 }
329
330 hdr.source.pan_id = wpan_dev->pan_id;
331
332 spin_unlock_bh(&sdata->mib_lock);
333 } else {
334 hdr.source = *(const struct ieee802154_addr *)saddr;
335 }
336
337 hdr.dest = *(const struct ieee802154_addr *)daddr;
338
339 hlen = ieee802154_hdr_push(skb, &hdr);
340 if (hlen < 0)
341 return -EINVAL;
342
343 skb_reset_mac_header(skb);
344 skb->mac_len = hlen;
345
346 if (len > ieee802154_max_payload(&hdr))
347 return -EMSGSIZE;
348
349 return hlen;
350 }
351
352 static int
353 mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
354 {
355 struct ieee802154_hdr hdr;
356 struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
357
358 if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
359 pr_debug("malformed packet\n");
360 return 0;
361 }
362
363 *addr = hdr.source;
364 return sizeof(*addr);
365 }
366
367 static struct header_ops mac802154_header_ops = {
368 .create = mac802154_header_create,
369 .parse = mac802154_header_parse,
370 };
371
372 static const struct net_device_ops mac802154_wpan_ops = {
373 .ndo_open = mac802154_wpan_open,
374 .ndo_stop = mac802154_slave_close,
375 .ndo_start_xmit = ieee802154_subif_start_xmit,
376 .ndo_do_ioctl = mac802154_wpan_ioctl,
377 .ndo_set_mac_address = mac802154_wpan_mac_addr,
378 };
379
380 static const struct net_device_ops mac802154_monitor_ops = {
381 .ndo_open = mac802154_wpan_open,
382 .ndo_stop = mac802154_slave_close,
383 .ndo_start_xmit = ieee802154_monitor_start_xmit,
384 };
385
386 static void mac802154_wpan_free(struct net_device *dev)
387 {
388 struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
389
390 mac802154_llsec_destroy(&sdata->sec);
391
392 free_netdev(dev);
393 }
394
395 static void ieee802154_if_setup(struct net_device *dev)
396 {
397 dev->addr_len = IEEE802154_EXTENDED_ADDR_LEN;
398 memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN);
399
400 dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
401 dev->needed_tailroom = 2 + 16; /* FCS + MIC */
402 dev->mtu = IEEE802154_MTU;
403 dev->tx_queue_len = 300;
404 dev->flags = IFF_NOARP | IFF_BROADCAST;
405 }
406
407 static int
408 ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type)
409 {
410 struct wpan_dev *wpan_dev = &sdata->wpan_dev;
411
412 /* set some type-dependent values */
413 sdata->vif.type = type;
414 sdata->wpan_dev.iftype = type;
415
416 get_random_bytes(&wpan_dev->bsn, 1);
417 get_random_bytes(&wpan_dev->dsn, 1);
418
419 /* defaults per 802.15.4-2011 */
420 wpan_dev->min_be = 3;
421 wpan_dev->max_be = 5;
422 wpan_dev->csma_retries = 4;
423 /* for compatibility, actual default is 3 */
424 wpan_dev->frame_retries = -1;
425
426 wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
427 wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
428
429 switch (type) {
430 case IEEE802154_DEV_WPAN:
431 ieee802154_be64_to_le64(&wpan_dev->extended_addr,
432 sdata->dev->dev_addr);
433
434 sdata->dev->header_ops = &mac802154_header_ops;
435 sdata->dev->destructor = mac802154_wpan_free;
436 sdata->dev->netdev_ops = &mac802154_wpan_ops;
437 sdata->dev->ml_priv = &mac802154_mlme_wpan;
438 wpan_dev->promiscuous_mode = false;
439
440 spin_lock_init(&sdata->mib_lock);
441 mutex_init(&sdata->sec_mtx);
442
443 mac802154_llsec_init(&sdata->sec);
444 break;
445 case IEEE802154_DEV_MONITOR:
446 sdata->dev->destructor = free_netdev;
447 sdata->dev->netdev_ops = &mac802154_monitor_ops;
448 wpan_dev->promiscuous_mode = true;
449 break;
450 default:
451 BUG();
452 }
453
454 return 0;
455 }
456
457 struct net_device *
458 ieee802154_if_add(struct ieee802154_local *local, const char *name,
459 struct wpan_dev **new_wpan_dev, int type)
460 {
461 struct net_device *ndev = NULL;
462 struct ieee802154_sub_if_data *sdata = NULL;
463 int ret = -ENOMEM;
464
465 ASSERT_RTNL();
466
467 ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
468 NET_NAME_UNKNOWN, ieee802154_if_setup);
469 if (!ndev)
470 return ERR_PTR(-ENOMEM);
471
472 ndev->needed_headroom = local->hw.extra_tx_headroom;
473
474 ret = dev_alloc_name(ndev, ndev->name);
475 if (ret < 0)
476 goto err;
477
478 switch (type) {
479 case IEEE802154_DEV_WPAN:
480 ndev->type = ARPHRD_IEEE802154;
481 break;
482 case IEEE802154_DEV_MONITOR:
483 ndev->type = ARPHRD_IEEE802154_MONITOR;
484 break;
485 default:
486 ret = -EINVAL;
487 goto err;
488 }
489
490 ieee802154_le64_to_be64(ndev->perm_addr,
491 &local->hw.phy->perm_extended_addr);
492 memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN);
493 /* TODO check this */
494 SET_NETDEV_DEV(ndev, &local->phy->dev);
495 sdata = netdev_priv(ndev);
496 ndev->ieee802154_ptr = &sdata->wpan_dev;
497 memcpy(sdata->name, ndev->name, IFNAMSIZ);
498 sdata->dev = ndev;
499 sdata->wpan_dev.wpan_phy = local->hw.phy;
500 sdata->local = local;
501
502 /* setup type-dependent data */
503 ret = ieee802154_setup_sdata(sdata, type);
504 if (ret)
505 goto err;
506
507 if (ndev) {
508 ret = register_netdevice(ndev);
509 if (ret < 0)
510 goto err;
511 }
512
513 mutex_lock(&local->iflist_mtx);
514 list_add_tail_rcu(&sdata->list, &local->interfaces);
515 mutex_unlock(&local->iflist_mtx);
516
517 if (new_wpan_dev)
518 *new_wpan_dev = &sdata->wpan_dev;
519
520 return ndev;
521
522 err:
523 free_netdev(ndev);
524 return ERR_PTR(ret);
525 }
526
527 void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
528 {
529 ASSERT_RTNL();
530
531 mutex_lock(&sdata->local->iflist_mtx);
532 list_del_rcu(&sdata->list);
533 mutex_unlock(&sdata->local->iflist_mtx);
534
535 synchronize_rcu();
536 unregister_netdevice(sdata->dev);
537 }
538
539 void ieee802154_remove_interfaces(struct ieee802154_local *local)
540 {
541 struct ieee802154_sub_if_data *sdata, *tmp;
542
543 mutex_lock(&local->iflist_mtx);
544 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
545 list_del(&sdata->list);
546
547 unregister_netdevice(sdata->dev);
548 }
549 mutex_unlock(&local->iflist_mtx);
550 }
551
552 static int netdev_notify(struct notifier_block *nb,
553 unsigned long state, void *ptr)
554 {
555 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
556 struct ieee802154_sub_if_data *sdata;
557
558 if (state != NETDEV_CHANGENAME)
559 return NOTIFY_DONE;
560
561 if (!dev->ieee802154_ptr || !dev->ieee802154_ptr->wpan_phy)
562 return NOTIFY_DONE;
563
564 if (dev->ieee802154_ptr->wpan_phy->privid != mac802154_wpan_phy_privid)
565 return NOTIFY_DONE;
566
567 sdata = IEEE802154_DEV_TO_SUB_IF(dev);
568 memcpy(sdata->name, dev->name, IFNAMSIZ);
569
570 return NOTIFY_OK;
571 }
572
573 static struct notifier_block mac802154_netdev_notifier = {
574 .notifier_call = netdev_notify,
575 };
576
577 int ieee802154_iface_init(void)
578 {
579 return register_netdevice_notifier(&mac802154_netdev_notifier);
580 }
581
582 void ieee802154_iface_exit(void)
583 {
584 unregister_netdevice_notifier(&mac802154_netdev_notifier);
585 }
This page took 0.045175 seconds and 6 git commands to generate.