blob: 801404ceea23e076e72e06f1075517d236cec9fe [file] [log] [blame]
Alexander Aringb72f6f52015-08-11 21:44:08 +02001/* This program is free software; you can redistribute it and/or modify
2 * it under the terms of the GNU General Public License version 2
3 * as published by the Free Software Foundation.
4 *
5 * This program is distributed in the hope that it will be useful,
6 * but WITHOUT ANY WARRANTY; without even the implied warranty of
7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8 * GNU General Public License for more details.
9 *
10 * Authors:
11 * (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
12 */
13
Alexander Aring4ae935c2015-08-11 21:44:09 +020014#include <linux/module.h>
15
Alexander Aringb72f6f52015-08-11 21:44:08 +020016#include <net/6lowpan.h>
Alexander Aring2ad3ed52016-06-15 21:20:17 +020017#include <net/addrconf.h>
Alexander Aringb72f6f52015-08-11 21:44:08 +020018
Alexander Aringb1815fd2015-12-09 22:46:30 +010019#include "6lowpan_i.h"
20
Alexander Aring00f59312015-12-09 22:46:29 +010021int lowpan_register_netdevice(struct net_device *dev,
22 enum lowpan_lltypes lltype)
Alexander Aringb72f6f52015-08-11 21:44:08 +020023{
Alexander Aring5609c182016-02-22 09:13:54 +010024 int i, ret;
Alexander Aringb1815fd2015-12-09 22:46:30 +010025
Alexander Aring4d6a6ae2015-10-02 20:28:04 +020026 dev->addr_len = EUI64_ADDR_LEN;
27 dev->type = ARPHRD_6LOWPAN;
28 dev->mtu = IPV6_MIN_MTU;
29 dev->priv_flags |= IFF_NO_QUEUE;
30
Alexander Aring2e4d60c2016-04-11 11:04:18 +020031 lowpan_dev(dev)->lltype = lltype;
Alexander Aring00f59312015-12-09 22:46:29 +010032
Alexander Aring2e4d60c2016-04-11 11:04:18 +020033 spin_lock_init(&lowpan_dev(dev)->ctx.lock);
Alexander Aring5609c182016-02-22 09:13:54 +010034 for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
Alexander Aring2e4d60c2016-04-11 11:04:18 +020035 lowpan_dev(dev)->ctx.table[i].id = i;
Alexander Aring5609c182016-02-22 09:13:54 +010036
Alexander Aring92e17ee2015-12-15 12:25:35 +010037 ret = register_netdevice(dev);
Alexander Aringb1815fd2015-12-09 22:46:30 +010038 if (ret < 0)
39 return ret;
40
Alexander Aring92e17ee2015-12-15 12:25:35 +010041 ret = lowpan_dev_debugfs_init(dev);
Alexander Aringb1815fd2015-12-09 22:46:30 +010042 if (ret < 0)
Alexander Aring92e17ee2015-12-15 12:25:35 +010043 unregister_netdevice(dev);
Alexander Aringb1815fd2015-12-09 22:46:30 +010044
45 return ret;
Alexander Aringb72f6f52015-08-11 21:44:08 +020046}
Alexander Aring00f59312015-12-09 22:46:29 +010047EXPORT_SYMBOL(lowpan_register_netdevice);
48
49int lowpan_register_netdev(struct net_device *dev,
50 enum lowpan_lltypes lltype)
51{
52 int ret;
53
54 rtnl_lock();
55 ret = lowpan_register_netdevice(dev, lltype);
56 rtnl_unlock();
57 return ret;
58}
59EXPORT_SYMBOL(lowpan_register_netdev);
60
61void lowpan_unregister_netdevice(struct net_device *dev)
62{
63 unregister_netdevice(dev);
Alexander Aringb1815fd2015-12-09 22:46:30 +010064 lowpan_dev_debugfs_exit(dev);
Alexander Aring00f59312015-12-09 22:46:29 +010065}
66EXPORT_SYMBOL(lowpan_unregister_netdevice);
67
68void lowpan_unregister_netdev(struct net_device *dev)
69{
70 rtnl_lock();
71 lowpan_unregister_netdevice(dev);
72 rtnl_unlock();
73}
74EXPORT_SYMBOL(lowpan_unregister_netdev);
Alexander Aring4ae935c2015-08-11 21:44:09 +020075
Alexander Aring2ad3ed52016-06-15 21:20:17 +020076static int addrconf_ifid_802154_6lowpan(u8 *eui, struct net_device *dev)
77{
78 struct wpan_dev *wpan_dev = lowpan_802154_dev(dev)->wdev->ieee802154_ptr;
79
80 /* Set short_addr autoconfiguration if short_addr is present only */
81 if (!lowpan_802154_is_valid_src_short_addr(wpan_dev->short_addr))
82 return -1;
83
84 /* For either address format, all zero addresses MUST NOT be used */
85 if (wpan_dev->pan_id == cpu_to_le16(0x0000) &&
86 wpan_dev->short_addr == cpu_to_le16(0x0000))
87 return -1;
88
89 /* Alternatively, if no PAN ID is known, 16 zero bits may be used */
90 if (wpan_dev->pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
91 memset(eui, 0, 2);
92 else
93 ieee802154_le16_to_be16(eui, &wpan_dev->pan_id);
94
95 /* The "Universal/Local" (U/L) bit shall be set to zero */
96 eui[0] &= ~2;
97 eui[2] = 0;
98 eui[3] = 0xFF;
99 eui[4] = 0xFE;
100 eui[5] = 0;
101 ieee802154_le16_to_be16(&eui[6], &wpan_dev->short_addr);
102 return 0;
103}
104
Alexander Aring5609c182016-02-22 09:13:54 +0100105static int lowpan_event(struct notifier_block *unused,
106 unsigned long event, void *ptr)
107{
108 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
Alexander Aring2ad3ed52016-06-15 21:20:17 +0200109 struct inet6_dev *idev;
110 struct in6_addr addr;
Alexander Aring5609c182016-02-22 09:13:54 +0100111 int i;
112
113 if (dev->type != ARPHRD_6LOWPAN)
114 return NOTIFY_DONE;
115
Alexander Aring2ad3ed52016-06-15 21:20:17 +0200116 idev = __in6_dev_get(dev);
117 if (!idev)
118 return NOTIFY_DONE;
119
Alexander Aring5609c182016-02-22 09:13:54 +0100120 switch (event) {
Alexander Aring2ad3ed52016-06-15 21:20:17 +0200121 case NETDEV_UP:
122 case NETDEV_CHANGE:
123 /* (802.15.4 6LoWPAN short address slaac handling */
124 if (lowpan_is_ll(dev, LOWPAN_LLTYPE_IEEE802154) &&
125 addrconf_ifid_802154_6lowpan(addr.s6_addr + 8, dev) == 0) {
126 __ipv6_addr_set_half(&addr.s6_addr32[0],
127 htonl(0xFE800000), 0);
128 addrconf_add_linklocal(idev, &addr, 0);
129 }
130 break;
Alexander Aring5609c182016-02-22 09:13:54 +0100131 case NETDEV_DOWN:
132 for (i = 0; i < LOWPAN_IPHC_CTX_TABLE_SIZE; i++)
133 clear_bit(LOWPAN_IPHC_CTX_FLAG_ACTIVE,
Alexander Aring2e4d60c2016-04-11 11:04:18 +0200134 &lowpan_dev(dev)->ctx.table[i].flags);
Alexander Aring5609c182016-02-22 09:13:54 +0100135 break;
136 default:
137 return NOTIFY_DONE;
138 }
139
140 return NOTIFY_OK;
141}
142
143static struct notifier_block lowpan_notifier = {
144 .notifier_call = lowpan_event,
145};
146
Alexander Aring4ae935c2015-08-11 21:44:09 +0200147static int __init lowpan_module_init(void)
148{
Alexander Aringb1815fd2015-12-09 22:46:30 +0100149 int ret;
150
151 ret = lowpan_debugfs_init();
152 if (ret < 0)
153 return ret;
154
Alexander Aring5609c182016-02-22 09:13:54 +0100155 ret = register_netdevice_notifier(&lowpan_notifier);
156 if (ret < 0) {
157 lowpan_debugfs_exit();
158 return ret;
159 }
160
Alexander Aring4ae935c2015-08-11 21:44:09 +0200161 request_module_nowait("ipv6");
162
163 request_module_nowait("nhc_dest");
164 request_module_nowait("nhc_fragment");
165 request_module_nowait("nhc_hop");
166 request_module_nowait("nhc_ipv6");
167 request_module_nowait("nhc_mobility");
168 request_module_nowait("nhc_routing");
169 request_module_nowait("nhc_udp");
170
171 return 0;
172}
Alexander Aringb1815fd2015-12-09 22:46:30 +0100173
174static void __exit lowpan_module_exit(void)
175{
176 lowpan_debugfs_exit();
Alexander Aring5609c182016-02-22 09:13:54 +0100177 unregister_netdevice_notifier(&lowpan_notifier);
Alexander Aringb1815fd2015-12-09 22:46:30 +0100178}
179
Alexander Aring4ae935c2015-08-11 21:44:09 +0200180module_init(lowpan_module_init);
Alexander Aringb1815fd2015-12-09 22:46:30 +0100181module_exit(lowpan_module_exit);
Alexander Aring4ae935c2015-08-11 21:44:09 +0200182
183MODULE_LICENSE("GPL");