Blame view

net/6lowpan/core.c 4.33 KB
b72f6f51d   Alexander Aring   6lowpan: add gene...
1
2
3
4
5
6
7
8
9
10
11
12
  /* 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.
   *
   * Authors:
   * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
   */
4ae935c12   Alexander Aring   6lowpan: move mod...
13
  #include <linux/module.h>
b72f6f51d   Alexander Aring   6lowpan: add gene...
14
  #include <net/6lowpan.h>
2ad3ed591   Alexander Aring   6lowpan: add 802....
15
  #include <net/addrconf.h>
b72f6f51d   Alexander Aring   6lowpan: add gene...
16

b1815fd94   Alexander Aring   6lowpan: add debu...
17
  #include "6lowpan_i.h"
00f593141   Alexander Aring   6lowpan: add lowp...
18
19
  int lowpan_register_netdevice(struct net_device *dev,
  			      enum lowpan_lltypes lltype)
b72f6f51d   Alexander Aring   6lowpan: add gene...
20
  {
5609c185f   Alexander Aring   6lowpan: iphc: ad...
21
  	int i, ret;
b1815fd94   Alexander Aring   6lowpan: add debu...
22

4d6a6aed2   Alexander Aring   6lowpan: move sha...
23
24
25
26
  	dev->addr_len = EUI64_ADDR_LEN;
  	dev->type = ARPHRD_6LOWPAN;
  	dev->mtu = IPV6_MIN_MTU;
  	dev->priv_flags |= IFF_NO_QUEUE;
2e4d60cbc   Alexander Aring   6lowpan: change n...
27
  	lowpan_dev(dev)->lltype = lltype;
00f593141   Alexander Aring   6lowpan: add lowp...
28

2e4d60cbc   Alexander Aring   6lowpan: change n...
29
  	spin_lock_init(&lowpan_dev(dev)->ctx.lock);
5609c185f   Alexander Aring   6lowpan: iphc: ad...
30
  	for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
2e4d60cbc   Alexander Aring   6lowpan: change n...
31
  		lowpan_dev(dev)->ctx.table[i].id = i;
5609c185f   Alexander Aring   6lowpan: iphc: ad...
32

bbe5f5cef   Alexander Aring   6lowpan: introduc...
33
  	dev->ndisc_ops = &lowpan_ndisc_ops;
92e17ee72   Alexander Aring   6lowpan: fix debu...
34
  	ret = register_netdevice(dev);
b1815fd94   Alexander Aring   6lowpan: add debu...
35
36
  	if (ret < 0)
  		return ret;
92e17ee72   Alexander Aring   6lowpan: fix debu...
37
  	ret = lowpan_dev_debugfs_init(dev);
b1815fd94   Alexander Aring   6lowpan: add debu...
38
  	if (ret < 0)
92e17ee72   Alexander Aring   6lowpan: fix debu...
39
  		unregister_netdevice(dev);
b1815fd94   Alexander Aring   6lowpan: add debu...
40
41
  
  	return ret;
00f593141   Alexander Aring   6lowpan: add lowp...
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  }
  EXPORT_SYMBOL(lowpan_register_netdevice);
  
  int lowpan_register_netdev(struct net_device *dev,
  			   enum lowpan_lltypes lltype)
  {
  	int ret;
  
  	rtnl_lock();
  	ret = lowpan_register_netdevice(dev, lltype);
  	rtnl_unlock();
  	return ret;
  }
  EXPORT_SYMBOL(lowpan_register_netdev);
  
  void lowpan_unregister_netdevice(struct net_device *dev)
  {
  	unregister_netdevice(dev);
b1815fd94   Alexander Aring   6lowpan: add debu...
60
  	lowpan_dev_debugfs_exit(dev);
00f593141   Alexander Aring   6lowpan: add lowp...
61
62
63
64
65
66
67
68
  }
  EXPORT_SYMBOL(lowpan_unregister_netdevice);
  
  void lowpan_unregister_netdev(struct net_device *dev)
  {
  	rtnl_lock();
  	lowpan_unregister_netdevice(dev);
  	rtnl_unlock();
b72f6f51d   Alexander Aring   6lowpan: add gene...
69
  }
00f593141   Alexander Aring   6lowpan: add lowp...
70
  EXPORT_SYMBOL(lowpan_unregister_netdev);
4ae935c12   Alexander Aring   6lowpan: move mod...
71

bbe5f5cef   Alexander Aring   6lowpan: introduc...
72
  int addrconf_ifid_802154_6lowpan(u8 *eui, struct net_device *dev)
2ad3ed591   Alexander Aring   6lowpan: add 802....
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  {
  	struct wpan_dev *wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr;
  
  	/* Set short_addr autoconfiguration if short_addr is present only */
  	if (!lowpan_802154_is_valid_src_short_addr(wpan_dev->short_addr))
  		return -1;
  
  	/* For either address format, all zero addresses MUST NOT be used */
  	if (wpan_dev->pan_id == cpu_to_le16(0x0000) &&
  	    wpan_dev->short_addr == cpu_to_le16(0x0000))
  		return -1;
  
  	/* Alternatively, if no PAN ID is known, 16 zero bits may be used */
  	if (wpan_dev->pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
  		memset(eui, 0, 2);
  	else
  		ieee802154_le16_to_be16(eui, &wpan_dev->pan_id);
  
  	/* The "Universal/Local" (U/L) bit shall be set to zero */
  	eui[0] &= ~2;
  	eui[2] = 0;
  	eui[3] = 0xFF;
  	eui[4] = 0xFE;
  	eui[5] = 0;
  	ieee802154_le16_to_be16(&eui[6], &wpan_dev->short_addr);
  	return 0;
  }
5609c185f   Alexander Aring   6lowpan: iphc: ad...
100
101
102
103
  static int lowpan_event(struct notifier_block *unused,
  			unsigned long event, void *ptr)
  {
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2ad3ed591   Alexander Aring   6lowpan: add 802....
104
105
  	struct inet6_dev *idev;
  	struct in6_addr addr;
5609c185f   Alexander Aring   6lowpan: iphc: ad...
106
107
108
109
  	int i;
  
  	if (dev->type != ARPHRD_6LOWPAN)
  		return NOTIFY_DONE;
2ad3ed591   Alexander Aring   6lowpan: add 802....
110
111
112
  	idev = __in6_dev_get(dev);
  	if (!idev)
  		return NOTIFY_DONE;
5609c185f   Alexander Aring   6lowpan: iphc: ad...
113
  	switch (event) {
2ad3ed591   Alexander Aring   6lowpan: add 802....
114
115
116
117
118
119
120
121
122
123
  	case NETDEV_UP:
  	case NETDEV_CHANGE:
  		/* (802.15.4 6LoWPAN short address slaac handling */
  		if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) &&
  		    addrconf_ifid_802154_6lowpan(addr.s6_addr + 8, dev) == 0) {
  			__ipv6_addr_set_half(&addr.s6_addr32[0],
  					     htonl(0xFE800000), 0);
  			addrconf_add_linklocal(idev, &addr, 0);
  		}
  		break;
5609c185f   Alexander Aring   6lowpan: iphc: ad...
124
125
126
  	case NETDEV_DOWN:
  		for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
  			clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE,
2e4d60cbc   Alexander Aring   6lowpan: change n...
127
  				  &lowpan_dev(dev)->ctx.table[i].flags);
5609c185f   Alexander Aring   6lowpan: iphc: ad...
128
129
130
131
132
133
134
135
136
137
138
  		break;
  	default:
  		return NOTIFY_DONE;
  	}
  
  	return NOTIFY_OK;
  }
  
  static struct notifier_block lowpan_notifier = {
  	.notifier_call = lowpan_event,
  };
4ae935c12   Alexander Aring   6lowpan: move mod...
139
140
  static int __init lowpan_module_init(void)
  {
b1815fd94   Alexander Aring   6lowpan: add debu...
141
142
143
144
145
  	int ret;
  
  	ret = lowpan_debugfs_init();
  	if (ret < 0)
  		return ret;
5609c185f   Alexander Aring   6lowpan: iphc: ad...
146
147
148
149
150
  	ret = register_netdevice_notifier(&lowpan_notifier);
  	if (ret < 0) {
  		lowpan_debugfs_exit();
  		return ret;
  	}
4ae935c12   Alexander Aring   6lowpan: move mod...
151
152
153
154
155
156
157
158
159
160
  	request_module_nowait("nhc_dest");
  	request_module_nowait("nhc_fragment");
  	request_module_nowait("nhc_hop");
  	request_module_nowait("nhc_ipv6");
  	request_module_nowait("nhc_mobility");
  	request_module_nowait("nhc_routing");
  	request_module_nowait("nhc_udp");
  
  	return 0;
  }
b1815fd94   Alexander Aring   6lowpan: add debu...
161
162
163
164
  
  static void __exit lowpan_module_exit(void)
  {
  	lowpan_debugfs_exit();
5609c185f   Alexander Aring   6lowpan: iphc: ad...
165
  	unregister_netdevice_notifier(&lowpan_notifier);
b1815fd94   Alexander Aring   6lowpan: add debu...
166
  }
4ae935c12   Alexander Aring   6lowpan: move mod...
167
  module_init(lowpan_module_init);
b1815fd94   Alexander Aring   6lowpan: add debu...
168
  module_exit(lowpan_module_exit);
4ae935c12   Alexander Aring   6lowpan: move mod...
169
170
  
  MODULE_LICENSE("GPL");