iface.c 13.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * Copyright 2007-2012 Siemens AG
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * Written by:
 * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 * Sergey Lapin <slapin@ossfans.org>
 * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
 * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
 */

#include <linux/netdevice.h>
#include <linux/module.h>
#include <linux/if_arp.h>
23
#include <linux/ieee802154.h>
24 25 26 27 28

#include <net/rtnetlink.h>
#include <linux/nl802154.h>
#include <net/mac802154.h>
#include <net/ieee802154_netdev.h>
29
#include <net/cfg802154.h>
30

31
#include "ieee802154_i.h"
32
#include "driver-ops.h"
33

34 35
static int mac802154_wpan_update_llsec(struct net_device *dev)
{
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 40 41 42 43 44
	int rc = 0;

	if (ops->llsec) {
		struct ieee802154_llsec_params params;
		int changed = 0;

45
		params.pan_id = wpan_dev->pan_id;
46 47
		changed |= IEEE802154_LLSEC_PARAM_PAN_ID;

48
		params.hwaddr = wpan_dev->extended_addr;
49 50 51 52 53 54 55 56
		changed |= IEEE802154_LLSEC_PARAM_HWADDR;

		rc = ops->llsec->set_params(dev, &params, changed);
	}

	return rc;
}

57 58 59
static int
mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
60
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
61
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
62 63 64 65
	struct sockaddr_ieee802154 *sa =
		(struct sockaddr_ieee802154 *)&ifr->ifr_addr;
	int err = -ENOIOCTLCMD;

66
	spin_lock_bh(&sdata->mib_lock);
67 68 69

	switch (cmd) {
	case SIOCGIFADDR:
70 71 72
	{
		u16 pan_id, short_addr;

73 74
		pan_id = le16_to_cpu(wpan_dev->pan_id);
		short_addr = le16_to_cpu(wpan_dev->short_addr);
75 76
		if (pan_id == IEEE802154_PANID_BROADCAST ||
		    short_addr == IEEE802154_ADDR_BROADCAST) {
77 78 79 80 81 82
			err = -EADDRNOTAVAIL;
			break;
		}

		sa->family = AF_IEEE802154;
		sa->addr.addr_type = IEEE802154_ADDR_SHORT;
83 84
		sa->addr.pan_id = pan_id;
		sa->addr.short_addr = short_addr;
85 86 87

		err = 0;
		break;
88
	}
89 90
	case SIOCSIFADDR:
		dev_warn(&dev->dev,
M
Masanari Iida 已提交
91
			 "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
92 93 94 95 96 97 98 99 100
		if (sa->family != AF_IEEE802154 ||
		    sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
		    sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
		    sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
		    sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
			err = -EINVAL;
			break;
		}

101 102
		wpan_dev->pan_id = cpu_to_le16(sa->addr.pan_id);
		wpan_dev->short_addr = cpu_to_le16(sa->addr.short_addr);
103

104
		err = mac802154_wpan_update_llsec(dev);
105 106 107
		break;
	}

108
	spin_unlock_bh(&sdata->mib_lock);
109 110 111 112 113
	return err;
}

static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
{
114
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
115
	struct sockaddr *addr = p;
116
	__le64 extended_addr;
117 118 119 120

	if (netif_running(dev))
		return -EBUSY;

121
	ieee802154_be64_to_le64(&extended_addr, addr->sa_data);
122 123 124
	if (!ieee802154_is_valid_extended_addr(extended_addr))
		return -EINVAL;

125
	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
126
	sdata->wpan_dev.extended_addr = extended_addr;
127

128
	return mac802154_wpan_update_llsec(dev);
129 130
}

131 132 133 134 135 136 137 138 139
static int mac802154_slave_open(struct net_device *dev)
{
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
	struct ieee802154_sub_if_data *subif;
	struct ieee802154_local *local = sdata->local;
	int res = 0;

	ASSERT_RTNL();

140
	if (sdata->vif.type == IEEE802154_DEV_WPAN) {
141 142
		mutex_lock(&sdata->local->iflist_mtx);
		list_for_each_entry(subif, &sdata->local->interfaces, list) {
143 144
			if (subif != sdata &&
			    subif->vif.type == sdata->vif.type &&
145
			    ieee802154_sdata_running(subif)) {
146 147 148 149 150 151 152
				mutex_unlock(&sdata->local->iflist_mtx);
				return -EBUSY;
			}
		}
		mutex_unlock(&sdata->local->iflist_mtx);
	}

153
	set_bit(SDATA_STATE_RUNNING, &sdata->state);
154

155
	if (!local->open_count) {
156
		res = drv_start(local);
157 158 159 160 161
		WARN_ON(res);
		if (res)
			goto err;
	}

162
	local->open_count++;
163 164 165
	netif_start_queue(dev);
	return 0;
err:
166 167
	/* might already be clear but that doesn't matter */
	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
168 169 170 171

	return res;
}

172
static int mac802154_wpan_open(struct net_device *dev)
173 174
{
	int rc;
175
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
176
	struct ieee802154_local *local = sdata->local;
177
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
178
	struct wpan_phy *phy = sdata->local->phy;
179 180 181 182 183 184 185

	rc = mac802154_slave_open(dev);
	if (rc < 0)
		return rc;

	mutex_lock(&phy->pib_lock);

186
	if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
187 188
		rc = drv_set_promiscuous_mode(local,
					      wpan_dev->promiscuous_mode);
189 190 191 192
		if (rc < 0)
			goto out;
	}

193
	if (local->hw.flags & IEEE802154_HW_AFILT) {
194
		rc = drv_set_pan_id(local, wpan_dev->pan_id);
195 196 197
		if (rc < 0)
			goto out;

198
		rc = drv_set_extended_addr(local, wpan_dev->extended_addr);
199 200
		if (rc < 0)
			goto out;
201

202
		rc = drv_set_short_addr(local, wpan_dev->short_addr);
203 204
		if (rc < 0)
			goto out;
205 206
	}

207
	if (local->hw.flags & IEEE802154_HW_LBT) {
208
		rc = drv_set_lbt_mode(local, sdata->mac_params.lbt);
209 210 211 212
		if (rc < 0)
			goto out;
	}

213
	if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) {
214 215 216
		rc = drv_set_csma_params(local, sdata->mac_params.min_be,
					 sdata->mac_params.max_be,
					 sdata->mac_params.csma_retries);
217 218 219 220
		if (rc < 0)
			goto out;
	}

221
	if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) {
222 223
		rc = drv_set_max_frame_retries(local,
					       sdata->mac_params.frame_retries);
224 225 226 227 228 229 230 231 232 233 234 235
		if (rc < 0)
			goto out;
	}

	mutex_unlock(&phy->pib_lock);
	return 0;

out:
	mutex_unlock(&phy->pib_lock);
	return rc;
}

236 237 238 239 240 241 242 243
static int mac802154_slave_close(struct net_device *dev)
{
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
	struct ieee802154_local *local = sdata->local;

	ASSERT_RTNL();

	netif_stop_queue(dev);
244
	local->open_count--;
245

246
	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
247

248
	if (!local->open_count)
249
		drv_stop(local);
250 251 252 253

	return 0;
}

254
static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata,
255 256 257 258 259 260
					 struct ieee802154_hdr *hdr,
					 const struct ieee802154_mac_cb *cb)
{
	struct ieee802154_llsec_params params;
	u8 level;

261
	mac802154_llsec_get_params(&sdata->sec, &params);
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

	if (!params.enabled && cb->secen_override && cb->secen)
		return -EINVAL;
	if (!params.enabled ||
	    (cb->secen_override && !cb->secen) ||
	    !params.out_level)
		return 0;
	if (cb->seclevel_override && !cb->seclevel)
		return -EINVAL;

	level = cb->seclevel_override ? cb->seclevel : params.out_level;

	hdr->fc.security_enabled = 1;
	hdr->sec.level = level;
	hdr->sec.key_id_mode = params.out_key.mode;
	if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
		hdr->sec.short_src = params.out_key.short_source;
	else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
		hdr->sec.extended_src = params.out_key.extended_source;
	hdr->sec.key_id = params.out_key.id;

	return 0;
}

286 287 288
static int mac802154_header_create(struct sk_buff *skb,
				   struct net_device *dev,
				   unsigned short type,
289 290
				   const void *daddr,
				   const void *saddr,
291 292
				   unsigned len)
{
293
	struct ieee802154_hdr hdr;
294
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
295
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
296
	struct ieee802154_mac_cb *cb = mac_cb(skb);
297
	int hlen;
298 299 300 301

	if (!daddr)
		return -EINVAL;

302
	memset(&hdr.fc, 0, sizeof(hdr.fc));
303 304 305 306
	hdr.fc.type = cb->type;
	hdr.fc.security_enabled = cb->secen;
	hdr.fc.ack_request = cb->ackreq;
	hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
307

308
	if (mac802154_set_header_security(sdata, &hdr, cb) < 0)
309 310
		return -EINVAL;

311
	if (!saddr) {
312
		spin_lock_bh(&sdata->mib_lock);
313

314 315 316
		if (wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
		    wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
		    wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
317
			hdr.source.mode = IEEE802154_ADDR_LONG;
318
			hdr.source.extended_addr = wpan_dev->extended_addr;
319
		} else {
320
			hdr.source.mode = IEEE802154_ADDR_SHORT;
321
			hdr.source.short_addr = wpan_dev->short_addr;
322 323
		}

324
		hdr.source.pan_id = wpan_dev->pan_id;
325

326
		spin_unlock_bh(&sdata->mib_lock);
327 328
	} else {
		hdr.source = *(const struct ieee802154_addr *)saddr;
329 330
	}

331
	hdr.dest = *(const struct ieee802154_addr *)daddr;
332

333 334 335
	hlen = ieee802154_hdr_push(skb, &hdr);
	if (hlen < 0)
		return -EINVAL;
336

337
	skb_reset_mac_header(skb);
338
	skb->mac_len = hlen;
339

340
	if (len > ieee802154_max_payload(&hdr))
341 342
		return -EMSGSIZE;

343
	return hlen;
344 345 346 347 348
}

static int
mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
{
349 350
	struct ieee802154_hdr hdr;
	struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
351

352 353 354
	if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
		pr_debug("malformed packet\n");
		return 0;
355 356
	}

357 358
	*addr = hdr.source;
	return sizeof(*addr);
359 360 361 362 363 364 365 366
}

static struct header_ops mac802154_header_ops = {
	.create		= mac802154_header_create,
	.parse		= mac802154_header_parse,
};

static const struct net_device_ops mac802154_wpan_ops = {
367
	.ndo_open		= mac802154_wpan_open,
368
	.ndo_stop		= mac802154_slave_close,
369
	.ndo_start_xmit		= ieee802154_subif_start_xmit,
370 371 372 373
	.ndo_do_ioctl		= mac802154_wpan_ioctl,
	.ndo_set_mac_address	= mac802154_wpan_mac_addr,
};

374
static const struct net_device_ops mac802154_monitor_ops = {
375
	.ndo_open		= mac802154_wpan_open,
376 377 378 379
	.ndo_stop		= mac802154_slave_close,
	.ndo_start_xmit		= ieee802154_monitor_start_xmit,
};

380 381
static void mac802154_wpan_free(struct net_device *dev)
{
382
	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
383

384
	mac802154_llsec_destroy(&sdata->sec);
385 386 387 388

	free_netdev(dev);
}

389
static void ieee802154_if_setup(struct net_device *dev)
390
{
391 392
	dev->addr_len		= IEEE802154_EXTENDED_ADDR_LEN;
	memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN);
393 394

	dev->hard_header_len	= MAC802154_FRAME_HARD_HEADER_LEN;
395
	dev->needed_tailroom	= 2 + 16; /* FCS + MIC */
396
	dev->mtu		= IEEE802154_MTU;
A
Alan Ott 已提交
397
	dev->tx_queue_len	= 300;
398
	dev->flags		= IFF_NOARP | IFF_BROADCAST;
399
}
400

401 402 403
static int
ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type)
{
404 405
	struct wpan_dev *wpan_dev = &sdata->wpan_dev;

406
	/* set some type-dependent values */
407
	sdata->vif.type = type;
408

409 410
	get_random_bytes(&wpan_dev->bsn, 1);
	get_random_bytes(&wpan_dev->dsn, 1);
411

412
	/* defaults per 802.15.4-2011 */
413 414 415 416 417
	sdata->mac_params.min_be = 3;
	sdata->mac_params.max_be = 5;
	sdata->mac_params.csma_retries = 4;
	/* for compatibility, actual default is 3 */
	sdata->mac_params.frame_retries = -1;
418

419 420 421
	ieee802154_be64_to_le64(&wpan_dev->extended_addr, sdata->dev->dev_addr);
	wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
	wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
422

423 424 425 426 427 428
	switch (type) {
	case IEEE802154_DEV_WPAN:
		sdata->dev->header_ops = &mac802154_header_ops;
		sdata->dev->destructor = mac802154_wpan_free;
		sdata->dev->netdev_ops = &mac802154_wpan_ops;
		sdata->dev->ml_priv = &mac802154_mlme_wpan;
429
		wpan_dev->promiscuous_mode = false;
430

431 432
		spin_lock_init(&sdata->mib_lock);
		mutex_init(&sdata->sec_mtx);
433

434 435 436 437 438
		mac802154_llsec_init(&sdata->sec);
		break;
	case IEEE802154_DEV_MONITOR:
		sdata->dev->destructor = free_netdev;
		sdata->dev->netdev_ops = &mac802154_monitor_ops;
439
		wpan_dev->promiscuous_mode = true;
440 441 442 443
		break;
	default:
		BUG();
	}
444 445 446 447 448 449 450 451

	return 0;
}

struct net_device *
ieee802154_if_add(struct ieee802154_local *local, const char *name,
		  struct wpan_dev **new_wpan_dev, int type)
{
452 453 454 455 456 457
	struct net_device *ndev = NULL;
	struct ieee802154_sub_if_data *sdata = NULL;
	int ret = -ENOMEM;

	ASSERT_RTNL();

458 459
	ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
			    NET_NAME_UNKNOWN, ieee802154_if_setup);
460 461 462 463 464 465 466 467
	if (!ndev)
		return ERR_PTR(-ENOMEM);

	ndev->needed_headroom = local->hw.extra_tx_headroom;

	ret = dev_alloc_name(ndev, ndev->name);
	if (ret < 0)
		goto err;
468 469 470

	switch (type) {
	case IEEE802154_DEV_WPAN:
471
		ndev->type = ARPHRD_IEEE802154;
472
		break;
473 474
	case IEEE802154_DEV_MONITOR:
		ndev->type = ARPHRD_IEEE802154_MONITOR;
475
		break;
476 477 478
	default:
		ret = -EINVAL;
		goto err;
479
	}
480

481 482 483
	ieee802154_le64_to_be64(ndev->perm_addr,
				&local->hw.phy->perm_extended_addr);
	memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN);
484 485 486 487 488 489 490 491 492 493 494 495
	/* TODO check this */
	SET_NETDEV_DEV(ndev, &local->phy->dev);
	sdata = netdev_priv(ndev);
	ndev->ieee802154_ptr = &sdata->wpan_dev;
	memcpy(sdata->name, ndev->name, IFNAMSIZ);
	sdata->dev = ndev;
	sdata->wpan_dev.wpan_phy = local->hw.phy;
	sdata->local = local;

	/* setup type-dependent data */
	ret = ieee802154_setup_sdata(sdata, type);
	if (ret)
496 497
		goto err;

498 499 500 501 502 503 504 505 506
	if (ndev) {
		ret = register_netdevice(ndev);
		if (ret < 0)
			goto err;
	}

	mutex_lock(&local->iflist_mtx);
	list_add_tail_rcu(&sdata->list, &local->interfaces);
	mutex_unlock(&local->iflist_mtx);
507

508 509 510 511
	if (new_wpan_dev)
		*new_wpan_dev = &sdata->wpan_dev;

	return ndev;
512 513

err:
514 515
	free_netdev(ndev);
	return ERR_PTR(ret);
516 517
}

518 519 520 521 522 523 524 525 526 527 528
void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
{
	ASSERT_RTNL();

	mutex_lock(&sdata->local->iflist_mtx);
	list_del_rcu(&sdata->list);
	mutex_unlock(&sdata->local->iflist_mtx);

	synchronize_rcu();
	unregister_netdevice(sdata->dev);
}