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