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