xref: /openbmc/linux/net/mac802154/mib.c (revision 776e59de)
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/if_arp.h>
21 
22 #include <net/mac802154.h>
23 #include <net/ieee802154_netdev.h>
24 #include <net/cfg802154.h>
25 
26 #include "ieee802154_i.h"
27 #include "driver-ops.h"
28 
29 struct hw_addr_filt_notify_work {
30 	struct work_struct work;
31 	struct net_device *dev;
32 	unsigned long changed;
33 };
34 
35 static struct ieee802154_local *mac802154_slave_get_priv(struct net_device *dev)
36 {
37 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
38 
39 	BUG_ON(dev->type != ARPHRD_IEEE802154);
40 
41 	return sdata->local;
42 }
43 
44 static void hw_addr_notify(struct work_struct *work)
45 {
46 	struct hw_addr_filt_notify_work *nw = container_of(work,
47 			struct hw_addr_filt_notify_work, work);
48 	struct ieee802154_local *local = mac802154_slave_get_priv(nw->dev);
49 	int res;
50 
51 	res = local->ops->set_hw_addr_filt(&local->hw, &local->hw.hw_filt,
52 					   nw->changed);
53 	if (res)
54 		pr_debug("failed changed mask %lx\n", nw->changed);
55 
56 	kfree(nw);
57 }
58 
59 static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
60 {
61 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
62 	struct hw_addr_filt_notify_work *work;
63 
64 	work = kzalloc(sizeof(*work), GFP_ATOMIC);
65 	if (!work)
66 		return;
67 
68 	INIT_WORK(&work->work, hw_addr_notify);
69 	work->dev = dev;
70 	work->changed = changed;
71 	queue_work(sdata->local->workqueue, &work->work);
72 }
73 
74 void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
75 {
76 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
77 
78 	BUG_ON(dev->type != ARPHRD_IEEE802154);
79 
80 	spin_lock_bh(&sdata->mib_lock);
81 	sdata->short_addr = val;
82 	spin_unlock_bh(&sdata->mib_lock);
83 
84 	if ((sdata->local->ops->set_hw_addr_filt) &&
85 	    (sdata->local->hw.hw_filt.short_addr != sdata->short_addr)) {
86 		sdata->local->hw.hw_filt.short_addr = sdata->short_addr;
87 		set_hw_addr_filt(dev, IEEE802154_AFILT_SADDR_CHANGED);
88 	}
89 }
90 
91 __le16 mac802154_dev_get_short_addr(const struct net_device *dev)
92 {
93 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
94 	__le16 ret;
95 
96 	BUG_ON(dev->type != ARPHRD_IEEE802154);
97 
98 	spin_lock_bh(&sdata->mib_lock);
99 	ret = sdata->short_addr;
100 	spin_unlock_bh(&sdata->mib_lock);
101 
102 	return ret;
103 }
104 
105 __le16 mac802154_dev_get_pan_id(const struct net_device *dev)
106 {
107 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
108 	__le16 ret;
109 
110 	BUG_ON(dev->type != ARPHRD_IEEE802154);
111 
112 	spin_lock_bh(&sdata->mib_lock);
113 	ret = sdata->pan_id;
114 	spin_unlock_bh(&sdata->mib_lock);
115 
116 	return ret;
117 }
118 
119 void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
120 {
121 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
122 
123 	BUG_ON(dev->type != ARPHRD_IEEE802154);
124 
125 	spin_lock_bh(&sdata->mib_lock);
126 	sdata->pan_id = val;
127 	spin_unlock_bh(&sdata->mib_lock);
128 
129 	if ((sdata->local->ops->set_hw_addr_filt) &&
130 	    (sdata->local->hw.hw_filt.pan_id != sdata->pan_id)) {
131 		sdata->local->hw.hw_filt.pan_id = sdata->pan_id;
132 		set_hw_addr_filt(dev, IEEE802154_AFILT_PANID_CHANGED);
133 	}
134 }
135 
136 u8 mac802154_dev_get_dsn(const struct net_device *dev)
137 {
138 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
139 
140 	BUG_ON(dev->type != ARPHRD_IEEE802154);
141 
142 	return sdata->dsn++;
143 }
144 
145 void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
146 {
147 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
148 	struct ieee802154_local *local = sdata->local;
149 	int res;
150 
151 	BUG_ON(dev->type != ARPHRD_IEEE802154);
152 
153 	res = drv_set_channel(local, page, chan);
154 	if (res) {
155 		pr_debug("set_channel failed\n");
156 	} else {
157 		mutex_lock(&local->phy->pib_lock);
158 		local->phy->current_channel = chan;
159 		local->phy->current_page = page;
160 		mutex_unlock(&local->phy->pib_lock);
161 	}
162 }
163 
164 
165 int mac802154_get_params(struct net_device *dev,
166 			 struct ieee802154_llsec_params *params)
167 {
168 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
169 	int res;
170 
171 	BUG_ON(dev->type != ARPHRD_IEEE802154);
172 
173 	mutex_lock(&sdata->sec_mtx);
174 	res = mac802154_llsec_get_params(&sdata->sec, params);
175 	mutex_unlock(&sdata->sec_mtx);
176 
177 	return res;
178 }
179 
180 int mac802154_set_params(struct net_device *dev,
181 			 const struct ieee802154_llsec_params *params,
182 			 int changed)
183 {
184 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
185 	int res;
186 
187 	BUG_ON(dev->type != ARPHRD_IEEE802154);
188 
189 	mutex_lock(&sdata->sec_mtx);
190 	res = mac802154_llsec_set_params(&sdata->sec, params, changed);
191 	mutex_unlock(&sdata->sec_mtx);
192 
193 	return res;
194 }
195 
196 
197 int mac802154_add_key(struct net_device *dev,
198 		      const struct ieee802154_llsec_key_id *id,
199 		      const struct ieee802154_llsec_key *key)
200 {
201 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
202 	int res;
203 
204 	BUG_ON(dev->type != ARPHRD_IEEE802154);
205 
206 	mutex_lock(&sdata->sec_mtx);
207 	res = mac802154_llsec_key_add(&sdata->sec, id, key);
208 	mutex_unlock(&sdata->sec_mtx);
209 
210 	return res;
211 }
212 
213 int mac802154_del_key(struct net_device *dev,
214 		      const struct ieee802154_llsec_key_id *id)
215 {
216 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
217 	int res;
218 
219 	BUG_ON(dev->type != ARPHRD_IEEE802154);
220 
221 	mutex_lock(&sdata->sec_mtx);
222 	res = mac802154_llsec_key_del(&sdata->sec, id);
223 	mutex_unlock(&sdata->sec_mtx);
224 
225 	return res;
226 }
227 
228 
229 int mac802154_add_dev(struct net_device *dev,
230 		      const struct ieee802154_llsec_device *llsec_dev)
231 {
232 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
233 	int res;
234 
235 	BUG_ON(dev->type != ARPHRD_IEEE802154);
236 
237 	mutex_lock(&sdata->sec_mtx);
238 	res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
239 	mutex_unlock(&sdata->sec_mtx);
240 
241 	return res;
242 }
243 
244 int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
245 {
246 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
247 	int res;
248 
249 	BUG_ON(dev->type != ARPHRD_IEEE802154);
250 
251 	mutex_lock(&sdata->sec_mtx);
252 	res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
253 	mutex_unlock(&sdata->sec_mtx);
254 
255 	return res;
256 }
257 
258 
259 int mac802154_add_devkey(struct net_device *dev,
260 			 __le64 device_addr,
261 			 const struct ieee802154_llsec_device_key *key)
262 {
263 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
264 	int res;
265 
266 	BUG_ON(dev->type != ARPHRD_IEEE802154);
267 
268 	mutex_lock(&sdata->sec_mtx);
269 	res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
270 	mutex_unlock(&sdata->sec_mtx);
271 
272 	return res;
273 }
274 
275 int mac802154_del_devkey(struct net_device *dev,
276 			 __le64 device_addr,
277 			 const struct ieee802154_llsec_device_key *key)
278 {
279 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
280 	int res;
281 
282 	BUG_ON(dev->type != ARPHRD_IEEE802154);
283 
284 	mutex_lock(&sdata->sec_mtx);
285 	res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
286 	mutex_unlock(&sdata->sec_mtx);
287 
288 	return res;
289 }
290 
291 
292 int mac802154_add_seclevel(struct net_device *dev,
293 			   const struct ieee802154_llsec_seclevel *sl)
294 {
295 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
296 	int res;
297 
298 	BUG_ON(dev->type != ARPHRD_IEEE802154);
299 
300 	mutex_lock(&sdata->sec_mtx);
301 	res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
302 	mutex_unlock(&sdata->sec_mtx);
303 
304 	return res;
305 }
306 
307 int mac802154_del_seclevel(struct net_device *dev,
308 			   const struct ieee802154_llsec_seclevel *sl)
309 {
310 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
311 	int res;
312 
313 	BUG_ON(dev->type != ARPHRD_IEEE802154);
314 
315 	mutex_lock(&sdata->sec_mtx);
316 	res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
317 	mutex_unlock(&sdata->sec_mtx);
318 
319 	return res;
320 }
321 
322 
323 void mac802154_lock_table(struct net_device *dev)
324 {
325 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
326 
327 	BUG_ON(dev->type != ARPHRD_IEEE802154);
328 
329 	mutex_lock(&sdata->sec_mtx);
330 }
331 
332 void mac802154_get_table(struct net_device *dev,
333 			 struct ieee802154_llsec_table **t)
334 {
335 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
336 
337 	BUG_ON(dev->type != ARPHRD_IEEE802154);
338 
339 	*t = &sdata->sec.table;
340 }
341 
342 void mac802154_unlock_table(struct net_device *dev)
343 {
344 	struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
345 
346 	BUG_ON(dev->type != ARPHRD_IEEE802154);
347 
348 	mutex_unlock(&sdata->sec_mtx);
349 }
350