Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/net/ieee802154/nl802154.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
*
4
* Authors:
5
* Alexander Aring <[email protected]>
6
*
7
* Based on: net/wireless/nl80211.c
8
*/
9
10
#include <linux/rtnetlink.h>
11
12
#include <net/cfg802154.h>
13
#include <net/genetlink.h>
14
#include <net/mac802154.h>
15
#include <net/netlink.h>
16
#include <net/nl802154.h>
17
#include <net/sock.h>
18
19
#include "nl802154.h"
20
#include "rdev-ops.h"
21
#include "core.h"
22
23
/* the netlink family */
24
static struct genl_family nl802154_fam;
25
26
/* multicast groups */
27
enum nl802154_multicast_groups {
28
NL802154_MCGRP_CONFIG,
29
NL802154_MCGRP_SCAN,
30
};
31
32
static const struct genl_multicast_group nl802154_mcgrps[] = {
33
[NL802154_MCGRP_CONFIG] = { .name = "config", },
34
[NL802154_MCGRP_SCAN] = { .name = "scan", },
35
};
36
37
/* returns ERR_PTR values */
38
static struct wpan_dev *
39
__cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
40
{
41
struct cfg802154_registered_device *rdev;
42
struct wpan_dev *result = NULL;
43
bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
44
bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
45
u64 wpan_dev_id;
46
int wpan_phy_idx = -1;
47
int ifidx = -1;
48
49
ASSERT_RTNL();
50
51
if (!have_ifidx && !have_wpan_dev_id)
52
return ERR_PTR(-EINVAL);
53
54
if (have_ifidx)
55
ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
56
if (have_wpan_dev_id) {
57
wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
58
wpan_phy_idx = wpan_dev_id >> 32;
59
}
60
61
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
62
struct wpan_dev *wpan_dev;
63
64
if (wpan_phy_net(&rdev->wpan_phy) != netns)
65
continue;
66
67
if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
68
continue;
69
70
list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
71
if (have_ifidx && wpan_dev->netdev &&
72
wpan_dev->netdev->ifindex == ifidx) {
73
result = wpan_dev;
74
break;
75
}
76
if (have_wpan_dev_id &&
77
wpan_dev->identifier == (u32)wpan_dev_id) {
78
result = wpan_dev;
79
break;
80
}
81
}
82
83
if (result)
84
break;
85
}
86
87
if (result)
88
return result;
89
90
return ERR_PTR(-ENODEV);
91
}
92
93
static struct cfg802154_registered_device *
94
__cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
95
{
96
struct cfg802154_registered_device *rdev = NULL, *tmp;
97
struct net_device *netdev;
98
99
ASSERT_RTNL();
100
101
if (!attrs[NL802154_ATTR_WPAN_PHY] &&
102
!attrs[NL802154_ATTR_IFINDEX] &&
103
!attrs[NL802154_ATTR_WPAN_DEV])
104
return ERR_PTR(-EINVAL);
105
106
if (attrs[NL802154_ATTR_WPAN_PHY])
107
rdev = cfg802154_rdev_by_wpan_phy_idx(
108
nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY]));
109
110
if (attrs[NL802154_ATTR_WPAN_DEV]) {
111
u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
112
struct wpan_dev *wpan_dev;
113
bool found = false;
114
115
tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32);
116
if (tmp) {
117
/* make sure wpan_dev exists */
118
list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) {
119
if (wpan_dev->identifier != (u32)wpan_dev_id)
120
continue;
121
found = true;
122
break;
123
}
124
125
if (!found)
126
tmp = NULL;
127
128
if (rdev && tmp != rdev)
129
return ERR_PTR(-EINVAL);
130
rdev = tmp;
131
}
132
}
133
134
if (attrs[NL802154_ATTR_IFINDEX]) {
135
int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
136
137
netdev = __dev_get_by_index(netns, ifindex);
138
if (netdev) {
139
if (netdev->ieee802154_ptr)
140
tmp = wpan_phy_to_rdev(
141
netdev->ieee802154_ptr->wpan_phy);
142
else
143
tmp = NULL;
144
145
/* not wireless device -- return error */
146
if (!tmp)
147
return ERR_PTR(-EINVAL);
148
149
/* mismatch -- return error */
150
if (rdev && tmp != rdev)
151
return ERR_PTR(-EINVAL);
152
153
rdev = tmp;
154
}
155
}
156
157
if (!rdev)
158
return ERR_PTR(-ENODEV);
159
160
if (netns != wpan_phy_net(&rdev->wpan_phy))
161
return ERR_PTR(-ENODEV);
162
163
return rdev;
164
}
165
166
/* This function returns a pointer to the driver
167
* that the genl_info item that is passed refers to.
168
*
169
* The result of this can be a PTR_ERR and hence must
170
* be checked with IS_ERR() for errors.
171
*/
172
static struct cfg802154_registered_device *
173
cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info)
174
{
175
return __cfg802154_rdev_from_attrs(netns, info->attrs);
176
}
177
178
/* policy for the attributes */
179
static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
180
[NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 },
181
[NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING,
182
.len = 20-1 },
183
184
[NL802154_ATTR_IFINDEX] = { .type = NLA_U32 },
185
[NL802154_ATTR_IFTYPE] = { .type = NLA_U32 },
186
[NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
187
188
[NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 },
189
190
[NL802154_ATTR_PAGE] = NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_PAGE),
191
[NL802154_ATTR_CHANNEL] = NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_CHANNEL),
192
193
[NL802154_ATTR_TX_POWER] = { .type = NLA_S32, },
194
195
[NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, },
196
[NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, },
197
[NL802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
198
199
[NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
200
201
[NL802154_ATTR_PAN_ID] = { .type = NLA_U16, },
202
[NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
203
[NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
204
205
[NL802154_ATTR_MIN_BE] = { .type = NLA_U8, },
206
[NL802154_ATTR_MAX_BE] = { .type = NLA_U8, },
207
[NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, },
208
209
[NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, },
210
211
[NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, },
212
213
[NL802154_ATTR_WPAN_PHY_CAPS] = { .type = NLA_NESTED },
214
215
[NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED },
216
217
[NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 },
218
219
[NL802154_ATTR_PID] = { .type = NLA_U32 },
220
[NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
221
222
[NL802154_ATTR_COORDINATOR] = { .type = NLA_NESTED },
223
224
[NL802154_ATTR_SCAN_TYPE] =
225
NLA_POLICY_RANGE(NLA_U8, NL802154_SCAN_ED, NL802154_SCAN_RIT_PASSIVE),
226
[NL802154_ATTR_SCAN_CHANNELS] =
227
NLA_POLICY_MASK(NLA_U32, GENMASK(IEEE802154_MAX_CHANNEL, 0)),
228
[NL802154_ATTR_SCAN_PREAMBLE_CODES] = { .type = NLA_REJECT },
229
[NL802154_ATTR_SCAN_MEAN_PRF] = { .type = NLA_REJECT },
230
[NL802154_ATTR_SCAN_DURATION] =
231
NLA_POLICY_MAX(NLA_U8, IEEE802154_MAX_SCAN_DURATION),
232
[NL802154_ATTR_SCAN_DONE_REASON] =
233
NLA_POLICY_RANGE(NLA_U8, NL802154_SCAN_DONE_REASON_FINISHED,
234
NL802154_SCAN_DONE_REASON_ABORTED),
235
[NL802154_ATTR_BEACON_INTERVAL] =
236
NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION),
237
[NL802154_ATTR_MAX_ASSOCIATIONS] = { .type = NLA_U32 },
238
[NL802154_ATTR_PEER] = { .type = NLA_NESTED },
239
240
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
241
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
242
[NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
243
[NL802154_ATTR_SEC_OUT_KEY_ID] = { .type = NLA_NESTED, },
244
[NL802154_ATTR_SEC_FRAME_COUNTER] = { .type = NLA_U32 },
245
246
[NL802154_ATTR_SEC_LEVEL] = { .type = NLA_NESTED },
247
[NL802154_ATTR_SEC_DEVICE] = { .type = NLA_NESTED },
248
[NL802154_ATTR_SEC_DEVKEY] = { .type = NLA_NESTED },
249
[NL802154_ATTR_SEC_KEY] = { .type = NLA_NESTED },
250
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
251
};
252
253
static int
254
nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
255
struct netlink_callback *cb,
256
struct cfg802154_registered_device **rdev,
257
struct wpan_dev **wpan_dev)
258
{
259
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
260
int err;
261
262
rtnl_lock();
263
264
if (!cb->args[0]) {
265
*wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
266
info->info.attrs);
267
if (IS_ERR(*wpan_dev)) {
268
err = PTR_ERR(*wpan_dev);
269
goto out_unlock;
270
}
271
*rdev = wpan_phy_to_rdev((*wpan_dev)->wpan_phy);
272
/* 0 is the first index - add 1 to parse only once */
273
cb->args[0] = (*rdev)->wpan_phy_idx + 1;
274
cb->args[1] = (*wpan_dev)->identifier;
275
} else {
276
/* subtract the 1 again here */
277
struct wpan_phy *wpan_phy = wpan_phy_idx_to_wpan_phy(cb->args[0] - 1);
278
struct wpan_dev *tmp;
279
280
if (!wpan_phy) {
281
err = -ENODEV;
282
goto out_unlock;
283
}
284
*rdev = wpan_phy_to_rdev(wpan_phy);
285
*wpan_dev = NULL;
286
287
list_for_each_entry(tmp, &(*rdev)->wpan_dev_list, list) {
288
if (tmp->identifier == cb->args[1]) {
289
*wpan_dev = tmp;
290
break;
291
}
292
}
293
294
if (!*wpan_dev) {
295
err = -ENODEV;
296
goto out_unlock;
297
}
298
}
299
300
return 0;
301
out_unlock:
302
rtnl_unlock();
303
return err;
304
}
305
306
static void
307
nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev)
308
{
309
rtnl_unlock();
310
}
311
312
/* message building helper */
313
static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
314
int flags, u8 cmd)
315
{
316
/* since there is no private header just add the generic one */
317
return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd);
318
}
319
320
static int
321
nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask)
322
{
323
struct nlattr *nl_flags = nla_nest_start_noflag(msg, attr);
324
int i;
325
326
if (!nl_flags)
327
return -ENOBUFS;
328
329
i = 0;
330
while (mask) {
331
if ((mask & 1) && nla_put_flag(msg, i))
332
return -ENOBUFS;
333
334
mask >>= 1;
335
i++;
336
}
337
338
nla_nest_end(msg, nl_flags);
339
return 0;
340
}
341
342
static int
343
nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
344
struct sk_buff *msg)
345
{
346
struct nlattr *nl_page;
347
unsigned long page;
348
349
nl_page = nla_nest_start_noflag(msg, NL802154_ATTR_CHANNELS_SUPPORTED);
350
if (!nl_page)
351
return -ENOBUFS;
352
353
for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
354
if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
355
rdev->wpan_phy.supported.channels[page]))
356
return -ENOBUFS;
357
}
358
nla_nest_end(msg, nl_page);
359
360
return 0;
361
}
362
363
static int
364
nl802154_put_capabilities(struct sk_buff *msg,
365
struct cfg802154_registered_device *rdev)
366
{
367
const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported;
368
struct nlattr *nl_caps, *nl_channels;
369
int i;
370
371
nl_caps = nla_nest_start_noflag(msg, NL802154_ATTR_WPAN_PHY_CAPS);
372
if (!nl_caps)
373
return -ENOBUFS;
374
375
nl_channels = nla_nest_start_noflag(msg, NL802154_CAP_ATTR_CHANNELS);
376
if (!nl_channels)
377
return -ENOBUFS;
378
379
for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
380
if (caps->channels[i]) {
381
if (nl802154_put_flags(msg, i, caps->channels[i]))
382
return -ENOBUFS;
383
}
384
}
385
386
nla_nest_end(msg, nl_channels);
387
388
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
389
struct nlattr *nl_ed_lvls;
390
391
nl_ed_lvls = nla_nest_start_noflag(msg,
392
NL802154_CAP_ATTR_CCA_ED_LEVELS);
393
if (!nl_ed_lvls)
394
return -ENOBUFS;
395
396
for (i = 0; i < caps->cca_ed_levels_size; i++) {
397
if (nla_put_s32(msg, i, caps->cca_ed_levels[i]))
398
return -ENOBUFS;
399
}
400
401
nla_nest_end(msg, nl_ed_lvls);
402
}
403
404
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
405
struct nlattr *nl_tx_pwrs;
406
407
nl_tx_pwrs = nla_nest_start_noflag(msg,
408
NL802154_CAP_ATTR_TX_POWERS);
409
if (!nl_tx_pwrs)
410
return -ENOBUFS;
411
412
for (i = 0; i < caps->tx_powers_size; i++) {
413
if (nla_put_s32(msg, i, caps->tx_powers[i]))
414
return -ENOBUFS;
415
}
416
417
nla_nest_end(msg, nl_tx_pwrs);
418
}
419
420
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
421
if (nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_MODES,
422
caps->cca_modes) ||
423
nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_OPTS,
424
caps->cca_opts))
425
return -ENOBUFS;
426
}
427
428
if (nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MINBE, caps->min_minbe) ||
429
nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MINBE, caps->max_minbe) ||
430
nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MAXBE, caps->min_maxbe) ||
431
nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MAXBE, caps->max_maxbe) ||
432
nla_put_u8(msg, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS,
433
caps->min_csma_backoffs) ||
434
nla_put_u8(msg, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS,
435
caps->max_csma_backoffs) ||
436
nla_put_s8(msg, NL802154_CAP_ATTR_MIN_FRAME_RETRIES,
437
caps->min_frame_retries) ||
438
nla_put_s8(msg, NL802154_CAP_ATTR_MAX_FRAME_RETRIES,
439
caps->max_frame_retries) ||
440
nl802154_put_flags(msg, NL802154_CAP_ATTR_IFTYPES,
441
caps->iftypes) ||
442
nla_put_u32(msg, NL802154_CAP_ATTR_LBT, caps->lbt))
443
return -ENOBUFS;
444
445
nla_nest_end(msg, nl_caps);
446
447
return 0;
448
}
449
450
static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
451
enum nl802154_commands cmd,
452
struct sk_buff *msg, u32 portid, u32 seq,
453
int flags)
454
{
455
struct nlattr *nl_cmds;
456
void *hdr;
457
int i;
458
459
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
460
if (!hdr)
461
return -ENOBUFS;
462
463
if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
464
nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME,
465
wpan_phy_name(&rdev->wpan_phy)) ||
466
nla_put_u32(msg, NL802154_ATTR_GENERATION,
467
cfg802154_rdev_list_generation))
468
goto nla_put_failure;
469
470
if (cmd != NL802154_CMD_NEW_WPAN_PHY)
471
goto finish;
472
473
/* DUMP PHY PIB */
474
475
/* current channel settings */
476
if (nla_put_u8(msg, NL802154_ATTR_PAGE,
477
rdev->wpan_phy.current_page) ||
478
nla_put_u8(msg, NL802154_ATTR_CHANNEL,
479
rdev->wpan_phy.current_channel))
480
goto nla_put_failure;
481
482
/* TODO remove this behaviour, we still keep support it for a while
483
* so users can change the behaviour to the new one.
484
*/
485
if (nl802154_send_wpan_phy_channels(rdev, msg))
486
goto nla_put_failure;
487
488
/* cca mode */
489
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
490
if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE,
491
rdev->wpan_phy.cca.mode))
492
goto nla_put_failure;
493
494
if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) {
495
if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT,
496
rdev->wpan_phy.cca.opt))
497
goto nla_put_failure;
498
}
499
}
500
501
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
502
if (nla_put_s32(msg, NL802154_ATTR_TX_POWER,
503
rdev->wpan_phy.transmit_power))
504
goto nla_put_failure;
505
}
506
507
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
508
if (nla_put_s32(msg, NL802154_ATTR_CCA_ED_LEVEL,
509
rdev->wpan_phy.cca_ed_level))
510
goto nla_put_failure;
511
}
512
513
if (nl802154_put_capabilities(msg, rdev))
514
goto nla_put_failure;
515
516
nl_cmds = nla_nest_start_noflag(msg, NL802154_ATTR_SUPPORTED_COMMANDS);
517
if (!nl_cmds)
518
goto nla_put_failure;
519
520
i = 0;
521
#define CMD(op, n) \
522
do { \
523
if (rdev->ops->op) { \
524
i++; \
525
if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \
526
goto nla_put_failure; \
527
} \
528
} while (0)
529
530
CMD(add_virtual_intf, NEW_INTERFACE);
531
CMD(del_virtual_intf, DEL_INTERFACE);
532
CMD(set_channel, SET_CHANNEL);
533
CMD(set_pan_id, SET_PAN_ID);
534
CMD(set_short_addr, SET_SHORT_ADDR);
535
CMD(set_backoff_exponent, SET_BACKOFF_EXPONENT);
536
CMD(set_max_csma_backoffs, SET_MAX_CSMA_BACKOFFS);
537
CMD(set_max_frame_retries, SET_MAX_FRAME_RETRIES);
538
CMD(set_lbt_mode, SET_LBT_MODE);
539
CMD(set_ackreq_default, SET_ACKREQ_DEFAULT);
540
541
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)
542
CMD(set_tx_power, SET_TX_POWER);
543
544
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)
545
CMD(set_cca_ed_level, SET_CCA_ED_LEVEL);
546
547
if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)
548
CMD(set_cca_mode, SET_CCA_MODE);
549
550
#undef CMD
551
nla_nest_end(msg, nl_cmds);
552
553
finish:
554
genlmsg_end(msg, hdr);
555
return 0;
556
557
nla_put_failure:
558
genlmsg_cancel(msg, hdr);
559
return -EMSGSIZE;
560
}
561
562
struct nl802154_dump_wpan_phy_state {
563
s64 filter_wpan_phy;
564
long start;
565
566
};
567
568
static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
569
struct netlink_callback *cb,
570
struct nl802154_dump_wpan_phy_state *state)
571
{
572
const struct genl_dumpit_info *info = genl_dumpit_info(cb);
573
struct nlattr **tb = info->info.attrs;
574
575
if (tb[NL802154_ATTR_WPAN_PHY])
576
state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
577
if (tb[NL802154_ATTR_WPAN_DEV])
578
state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32;
579
if (tb[NL802154_ATTR_IFINDEX]) {
580
struct net_device *netdev;
581
struct cfg802154_registered_device *rdev;
582
int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
583
584
netdev = __dev_get_by_index(&init_net, ifidx);
585
if (!netdev)
586
return -ENODEV;
587
if (netdev->ieee802154_ptr) {
588
rdev = wpan_phy_to_rdev(
589
netdev->ieee802154_ptr->wpan_phy);
590
state->filter_wpan_phy = rdev->wpan_phy_idx;
591
}
592
}
593
594
return 0;
595
}
596
597
static int
598
nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
599
{
600
int idx = 0, ret;
601
struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0];
602
struct cfg802154_registered_device *rdev;
603
604
rtnl_lock();
605
if (!state) {
606
state = kzalloc(sizeof(*state), GFP_KERNEL);
607
if (!state) {
608
rtnl_unlock();
609
return -ENOMEM;
610
}
611
state->filter_wpan_phy = -1;
612
ret = nl802154_dump_wpan_phy_parse(skb, cb, state);
613
if (ret) {
614
kfree(state);
615
rtnl_unlock();
616
return ret;
617
}
618
cb->args[0] = (long)state;
619
}
620
621
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
622
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
623
continue;
624
if (++idx <= state->start)
625
continue;
626
if (state->filter_wpan_phy != -1 &&
627
state->filter_wpan_phy != rdev->wpan_phy_idx)
628
continue;
629
/* attempt to fit multiple wpan_phy data chunks into the skb */
630
ret = nl802154_send_wpan_phy(rdev,
631
NL802154_CMD_NEW_WPAN_PHY,
632
skb,
633
NETLINK_CB(cb->skb).portid,
634
cb->nlh->nlmsg_seq, NLM_F_MULTI);
635
if (ret < 0) {
636
if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
637
!skb->len && cb->min_dump_alloc < 4096) {
638
cb->min_dump_alloc = 4096;
639
rtnl_unlock();
640
return 1;
641
}
642
idx--;
643
break;
644
}
645
break;
646
}
647
rtnl_unlock();
648
649
state->start = idx;
650
651
return skb->len;
652
}
653
654
static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
655
{
656
kfree((void *)cb->args[0]);
657
return 0;
658
}
659
660
static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info)
661
{
662
struct sk_buff *msg;
663
struct cfg802154_registered_device *rdev = info->user_ptr[0];
664
665
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
666
if (!msg)
667
return -ENOMEM;
668
669
if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg,
670
info->snd_portid, info->snd_seq, 0) < 0) {
671
nlmsg_free(msg);
672
return -ENOBUFS;
673
}
674
675
return genlmsg_reply(msg, info);
676
}
677
678
static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev)
679
{
680
return (u64)wpan_dev->identifier |
681
((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32);
682
}
683
684
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
685
#include <net/ieee802154_netdev.h>
686
687
static int
688
ieee802154_llsec_send_key_id(struct sk_buff *msg,
689
const struct ieee802154_llsec_key_id *desc)
690
{
691
struct nlattr *nl_dev_addr;
692
693
if (nla_put_u32(msg, NL802154_KEY_ID_ATTR_MODE, desc->mode))
694
return -ENOBUFS;
695
696
switch (desc->mode) {
697
case NL802154_KEY_ID_MODE_IMPLICIT:
698
nl_dev_addr = nla_nest_start_noflag(msg,
699
NL802154_KEY_ID_ATTR_IMPLICIT);
700
if (!nl_dev_addr)
701
return -ENOBUFS;
702
703
if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_PAN_ID,
704
desc->device_addr.pan_id) ||
705
nla_put_u32(msg, NL802154_DEV_ADDR_ATTR_MODE,
706
desc->device_addr.mode))
707
return -ENOBUFS;
708
709
switch (desc->device_addr.mode) {
710
case NL802154_DEV_ADDR_SHORT:
711
if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_SHORT,
712
desc->device_addr.short_addr))
713
return -ENOBUFS;
714
break;
715
case NL802154_DEV_ADDR_EXTENDED:
716
if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED,
717
desc->device_addr.extended_addr,
718
NL802154_DEV_ADDR_ATTR_PAD))
719
return -ENOBUFS;
720
break;
721
default:
722
/* userspace should handle unknown */
723
break;
724
}
725
726
nla_nest_end(msg, nl_dev_addr);
727
break;
728
case NL802154_KEY_ID_MODE_INDEX:
729
break;
730
case NL802154_KEY_ID_MODE_INDEX_SHORT:
731
/* TODO renmae short_source? */
732
if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT,
733
desc->short_source))
734
return -ENOBUFS;
735
break;
736
case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
737
if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
738
desc->extended_source,
739
NL802154_KEY_ID_ATTR_PAD))
740
return -ENOBUFS;
741
break;
742
default:
743
/* userspace should handle unknown */
744
break;
745
}
746
747
/* TODO key_id to key_idx ? Check naming */
748
if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
749
if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id))
750
return -ENOBUFS;
751
}
752
753
return 0;
754
}
755
756
static int nl802154_get_llsec_params(struct sk_buff *msg,
757
struct cfg802154_registered_device *rdev,
758
struct wpan_dev *wpan_dev)
759
{
760
struct nlattr *nl_key_id;
761
struct ieee802154_llsec_params params;
762
int ret;
763
764
ret = rdev_get_llsec_params(rdev, wpan_dev, &params);
765
if (ret < 0)
766
return ret;
767
768
if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) ||
769
nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) ||
770
nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER,
771
params.frame_counter))
772
return -ENOBUFS;
773
774
nl_key_id = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_OUT_KEY_ID);
775
if (!nl_key_id)
776
return -ENOBUFS;
777
778
ret = ieee802154_llsec_send_key_id(msg, &params.out_key);
779
if (ret < 0)
780
return ret;
781
782
nla_nest_end(msg, nl_key_id);
783
784
return 0;
785
}
786
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
787
788
static int
789
nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
790
struct cfg802154_registered_device *rdev,
791
struct wpan_dev *wpan_dev)
792
{
793
struct net_device *dev = wpan_dev->netdev;
794
void *hdr;
795
796
hdr = nl802154hdr_put(msg, portid, seq, flags,
797
NL802154_CMD_NEW_INTERFACE);
798
if (!hdr)
799
return -1;
800
801
if (dev &&
802
(nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
803
nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
804
goto nla_put_failure;
805
806
if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
807
nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
808
nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
809
wpan_dev_id(wpan_dev), NL802154_ATTR_PAD) ||
810
nla_put_u32(msg, NL802154_ATTR_GENERATION,
811
rdev->devlist_generation ^
812
(cfg802154_rdev_list_generation << 2)))
813
goto nla_put_failure;
814
815
/* address settings */
816
if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
817
wpan_dev->extended_addr,
818
NL802154_ATTR_PAD) ||
819
nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
820
wpan_dev->short_addr) ||
821
nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
822
goto nla_put_failure;
823
824
/* ARET handling */
825
if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
826
wpan_dev->frame_retries) ||
827
nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
828
nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
829
wpan_dev->csma_retries) ||
830
nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
831
goto nla_put_failure;
832
833
/* listen before transmit */
834
if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
835
goto nla_put_failure;
836
837
/* ackreq default behaviour */
838
if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq))
839
goto nla_put_failure;
840
841
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
842
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
843
goto out;
844
845
if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0)
846
goto nla_put_failure;
847
848
out:
849
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
850
851
genlmsg_end(msg, hdr);
852
return 0;
853
854
nla_put_failure:
855
genlmsg_cancel(msg, hdr);
856
return -EMSGSIZE;
857
}
858
859
static int
860
nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
861
{
862
int wp_idx = 0;
863
int if_idx = 0;
864
int wp_start = cb->args[0];
865
int if_start = cb->args[1];
866
struct cfg802154_registered_device *rdev;
867
struct wpan_dev *wpan_dev;
868
869
rtnl_lock();
870
list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
871
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
872
continue;
873
if (wp_idx < wp_start) {
874
wp_idx++;
875
continue;
876
}
877
if_idx = 0;
878
879
list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
880
if (if_idx < if_start) {
881
if_idx++;
882
continue;
883
}
884
if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid,
885
cb->nlh->nlmsg_seq, NLM_F_MULTI,
886
rdev, wpan_dev) < 0) {
887
goto out;
888
}
889
if_idx++;
890
}
891
892
wp_idx++;
893
}
894
out:
895
rtnl_unlock();
896
897
cb->args[0] = wp_idx;
898
cb->args[1] = if_idx;
899
900
return skb->len;
901
}
902
903
static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
904
{
905
struct sk_buff *msg;
906
struct cfg802154_registered_device *rdev = info->user_ptr[0];
907
struct wpan_dev *wdev = info->user_ptr[1];
908
909
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
910
if (!msg)
911
return -ENOMEM;
912
913
if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0,
914
rdev, wdev) < 0) {
915
nlmsg_free(msg);
916
return -ENOBUFS;
917
}
918
919
return genlmsg_reply(msg, info);
920
}
921
922
static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
923
{
924
struct cfg802154_registered_device *rdev = info->user_ptr[0];
925
enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
926
__le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
927
928
/* TODO avoid failing a new interface
929
* creation due to pending removal?
930
*/
931
932
if (!info->attrs[NL802154_ATTR_IFNAME])
933
return -EINVAL;
934
935
if (info->attrs[NL802154_ATTR_IFTYPE]) {
936
type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
937
if (type > NL802154_IFTYPE_MAX ||
938
!(rdev->wpan_phy.supported.iftypes & BIT(type)))
939
return -EINVAL;
940
}
941
942
if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
943
extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
944
945
if (!rdev->ops->add_virtual_intf)
946
return -EOPNOTSUPP;
947
948
return rdev_add_virtual_intf(rdev,
949
nla_data(info->attrs[NL802154_ATTR_IFNAME]),
950
NET_NAME_USER, type, extended_addr);
951
}
952
953
static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
954
{
955
struct cfg802154_registered_device *rdev = info->user_ptr[0];
956
struct wpan_dev *wpan_dev = info->user_ptr[1];
957
958
if (!rdev->ops->del_virtual_intf)
959
return -EOPNOTSUPP;
960
961
/* If we remove a wpan device without a netdev then clear
962
* user_ptr[1] so that nl802154_post_doit won't dereference it
963
* to check if it needs to do dev_put(). Otherwise it crashes
964
* since the wpan_dev has been freed, unlike with a netdev where
965
* we need the dev_put() for the netdev to really be freed.
966
*/
967
if (!wpan_dev->netdev)
968
info->user_ptr[1] = NULL;
969
970
return rdev_del_virtual_intf(rdev, wpan_dev);
971
}
972
973
static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
974
{
975
struct cfg802154_registered_device *rdev = info->user_ptr[0];
976
u8 channel, page;
977
978
if (!info->attrs[NL802154_ATTR_PAGE] ||
979
!info->attrs[NL802154_ATTR_CHANNEL])
980
return -EINVAL;
981
982
page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
983
channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
984
985
/* check 802.15.4 constraints */
986
if (!ieee802154_chan_is_valid(&rdev->wpan_phy, page, channel))
987
return -EINVAL;
988
989
return rdev_set_channel(rdev, page, channel);
990
}
991
992
static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
993
{
994
struct cfg802154_registered_device *rdev = info->user_ptr[0];
995
struct wpan_phy_cca cca;
996
997
if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE))
998
return -EOPNOTSUPP;
999
1000
if (!info->attrs[NL802154_ATTR_CCA_MODE])
1001
return -EINVAL;
1002
1003
cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
1004
/* checking 802.15.4 constraints */
1005
if (cca.mode < NL802154_CCA_ENERGY ||
1006
cca.mode > NL802154_CCA_ATTR_MAX ||
1007
!(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode)))
1008
return -EINVAL;
1009
1010
if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
1011
if (!info->attrs[NL802154_ATTR_CCA_OPT])
1012
return -EINVAL;
1013
1014
cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
1015
if (cca.opt > NL802154_CCA_OPT_ATTR_MAX ||
1016
!(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt)))
1017
return -EINVAL;
1018
}
1019
1020
return rdev_set_cca_mode(rdev, &cca);
1021
}
1022
1023
static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info)
1024
{
1025
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1026
s32 ed_level;
1027
int i;
1028
1029
if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL))
1030
return -EOPNOTSUPP;
1031
1032
if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL])
1033
return -EINVAL;
1034
1035
ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]);
1036
1037
for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) {
1038
if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i])
1039
return rdev_set_cca_ed_level(rdev, ed_level);
1040
}
1041
1042
return -EINVAL;
1043
}
1044
1045
static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info)
1046
{
1047
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1048
s32 power;
1049
int i;
1050
1051
if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER))
1052
return -EOPNOTSUPP;
1053
1054
if (!info->attrs[NL802154_ATTR_TX_POWER])
1055
return -EINVAL;
1056
1057
power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]);
1058
1059
for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) {
1060
if (power == rdev->wpan_phy.supported.tx_powers[i])
1061
return rdev_set_tx_power(rdev, power);
1062
}
1063
1064
return -EINVAL;
1065
}
1066
1067
static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
1068
{
1069
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1070
struct net_device *dev = info->user_ptr[1];
1071
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1072
__le16 pan_id;
1073
1074
/* conflict here while tx/rx calls */
1075
if (netif_running(dev))
1076
return -EBUSY;
1077
1078
if (wpan_dev->lowpan_dev) {
1079
if (netif_running(wpan_dev->lowpan_dev))
1080
return -EBUSY;
1081
}
1082
1083
/* don't change address fields on monitor */
1084
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1085
!info->attrs[NL802154_ATTR_PAN_ID])
1086
return -EINVAL;
1087
1088
pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
1089
1090
/* Only allow changing the PAN ID when the device has no more
1091
* associations ongoing to avoid confusing peers.
1092
*/
1093
if (cfg802154_device_is_associated(wpan_dev)) {
1094
NL_SET_ERR_MSG(info->extack,
1095
"Existing associations, changing PAN ID forbidden");
1096
return -EINVAL;
1097
}
1098
1099
return rdev_set_pan_id(rdev, wpan_dev, pan_id);
1100
}
1101
1102
static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
1103
{
1104
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1105
struct net_device *dev = info->user_ptr[1];
1106
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1107
__le16 short_addr;
1108
1109
/* conflict here while tx/rx calls */
1110
if (netif_running(dev))
1111
return -EBUSY;
1112
1113
if (wpan_dev->lowpan_dev) {
1114
if (netif_running(wpan_dev->lowpan_dev))
1115
return -EBUSY;
1116
}
1117
1118
/* don't change address fields on monitor */
1119
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1120
!info->attrs[NL802154_ATTR_SHORT_ADDR])
1121
return -EINVAL;
1122
1123
short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
1124
1125
/* The short address only has a meaning when part of a PAN, after a
1126
* proper association procedure. However, we want to still offer the
1127
* possibility to create static networks so changing the short address
1128
* is only allowed when not already associated to other devices with
1129
* the official handshake.
1130
*/
1131
if (cfg802154_device_is_associated(wpan_dev)) {
1132
NL_SET_ERR_MSG(info->extack,
1133
"Existing associations, changing short address forbidden");
1134
return -EINVAL;
1135
}
1136
1137
return rdev_set_short_addr(rdev, wpan_dev, short_addr);
1138
}
1139
1140
static int
1141
nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
1142
{
1143
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1144
struct net_device *dev = info->user_ptr[1];
1145
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1146
u8 min_be, max_be;
1147
1148
/* should be set on netif open inside phy settings */
1149
if (netif_running(dev))
1150
return -EBUSY;
1151
1152
if (!info->attrs[NL802154_ATTR_MIN_BE] ||
1153
!info->attrs[NL802154_ATTR_MAX_BE])
1154
return -EINVAL;
1155
1156
min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
1157
max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
1158
1159
/* check 802.15.4 constraints */
1160
if (min_be < rdev->wpan_phy.supported.min_minbe ||
1161
min_be > rdev->wpan_phy.supported.max_minbe ||
1162
max_be < rdev->wpan_phy.supported.min_maxbe ||
1163
max_be > rdev->wpan_phy.supported.max_maxbe ||
1164
min_be > max_be)
1165
return -EINVAL;
1166
1167
return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
1168
}
1169
1170
static int
1171
nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
1172
{
1173
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1174
struct net_device *dev = info->user_ptr[1];
1175
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1176
u8 max_csma_backoffs;
1177
1178
/* conflict here while other running iface settings */
1179
if (netif_running(dev))
1180
return -EBUSY;
1181
1182
if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
1183
return -EINVAL;
1184
1185
max_csma_backoffs = nla_get_u8(
1186
info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
1187
1188
/* check 802.15.4 constraints */
1189
if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs ||
1190
max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs)
1191
return -EINVAL;
1192
1193
return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
1194
}
1195
1196
static int
1197
nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
1198
{
1199
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1200
struct net_device *dev = info->user_ptr[1];
1201
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1202
s8 max_frame_retries;
1203
1204
if (netif_running(dev))
1205
return -EBUSY;
1206
1207
if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
1208
return -EINVAL;
1209
1210
max_frame_retries = nla_get_s8(
1211
info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
1212
1213
/* check 802.15.4 constraints */
1214
if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries ||
1215
max_frame_retries > rdev->wpan_phy.supported.max_frame_retries)
1216
return -EINVAL;
1217
1218
return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
1219
}
1220
1221
static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
1222
{
1223
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1224
struct net_device *dev = info->user_ptr[1];
1225
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1226
int mode;
1227
1228
if (netif_running(dev))
1229
return -EBUSY;
1230
1231
if (!info->attrs[NL802154_ATTR_LBT_MODE])
1232
return -EINVAL;
1233
1234
mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
1235
1236
if (mode != 0 && mode != 1)
1237
return -EINVAL;
1238
1239
if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt))
1240
return -EINVAL;
1241
1242
return rdev_set_lbt_mode(rdev, wpan_dev, mode);
1243
}
1244
1245
static int
1246
nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
1247
{
1248
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1249
struct net_device *dev = info->user_ptr[1];
1250
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1251
int ackreq;
1252
1253
if (netif_running(dev))
1254
return -EBUSY;
1255
1256
if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT])
1257
return -EINVAL;
1258
1259
ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]);
1260
1261
if (ackreq != 0 && ackreq != 1)
1262
return -EINVAL;
1263
1264
return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
1265
}
1266
1267
static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
1268
{
1269
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1270
struct net *net;
1271
int err;
1272
1273
if (info->attrs[NL802154_ATTR_PID]) {
1274
u32 pid = nla_get_u32(info->attrs[NL802154_ATTR_PID]);
1275
1276
net = get_net_ns_by_pid(pid);
1277
} else if (info->attrs[NL802154_ATTR_NETNS_FD]) {
1278
u32 fd = nla_get_u32(info->attrs[NL802154_ATTR_NETNS_FD]);
1279
1280
net = get_net_ns_by_fd(fd);
1281
} else {
1282
return -EINVAL;
1283
}
1284
1285
if (IS_ERR(net))
1286
return PTR_ERR(net);
1287
1288
err = 0;
1289
1290
/* check if anything to do */
1291
if (!net_eq(wpan_phy_net(&rdev->wpan_phy), net))
1292
err = cfg802154_switch_netns(rdev, net);
1293
1294
put_net(net);
1295
return err;
1296
}
1297
1298
static int nl802154_prep_scan_event_msg(struct sk_buff *msg,
1299
struct cfg802154_registered_device *rdev,
1300
struct wpan_dev *wpan_dev,
1301
u32 portid, u32 seq, int flags, u8 cmd,
1302
struct ieee802154_coord_desc *desc)
1303
{
1304
struct nlattr *nla;
1305
void *hdr;
1306
1307
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1308
if (!hdr)
1309
return -ENOBUFS;
1310
1311
if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx))
1312
goto nla_put_failure;
1313
1314
if (wpan_dev->netdev &&
1315
nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
1316
goto nla_put_failure;
1317
1318
if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
1319
wpan_dev_id(wpan_dev), NL802154_ATTR_PAD))
1320
goto nla_put_failure;
1321
1322
nla = nla_nest_start_noflag(msg, NL802154_ATTR_COORDINATOR);
1323
if (!nla)
1324
goto nla_put_failure;
1325
1326
if (nla_put(msg, NL802154_COORD_PANID, IEEE802154_PAN_ID_LEN,
1327
&desc->addr.pan_id))
1328
goto nla_put_failure;
1329
1330
if (desc->addr.mode == IEEE802154_ADDR_SHORT) {
1331
if (nla_put(msg, NL802154_COORD_ADDR,
1332
IEEE802154_SHORT_ADDR_LEN,
1333
&desc->addr.short_addr))
1334
goto nla_put_failure;
1335
} else {
1336
if (nla_put(msg, NL802154_COORD_ADDR,
1337
IEEE802154_EXTENDED_ADDR_LEN,
1338
&desc->addr.extended_addr))
1339
goto nla_put_failure;
1340
}
1341
1342
if (nla_put_u8(msg, NL802154_COORD_CHANNEL, desc->channel))
1343
goto nla_put_failure;
1344
1345
if (nla_put_u8(msg, NL802154_COORD_PAGE, desc->page))
1346
goto nla_put_failure;
1347
1348
if (nla_put_u16(msg, NL802154_COORD_SUPERFRAME_SPEC,
1349
desc->superframe_spec))
1350
goto nla_put_failure;
1351
1352
if (nla_put_u8(msg, NL802154_COORD_LINK_QUALITY, desc->link_quality))
1353
goto nla_put_failure;
1354
1355
if (desc->gts_permit && nla_put_flag(msg, NL802154_COORD_GTS_PERMIT))
1356
goto nla_put_failure;
1357
1358
/* TODO: NL802154_COORD_PAYLOAD_DATA if any */
1359
1360
nla_nest_end(msg, nla);
1361
1362
genlmsg_end(msg, hdr);
1363
1364
return 0;
1365
1366
nla_put_failure:
1367
genlmsg_cancel(msg, hdr);
1368
1369
return -EMSGSIZE;
1370
}
1371
1372
int nl802154_scan_event(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
1373
struct ieee802154_coord_desc *desc)
1374
{
1375
struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
1376
struct sk_buff *msg;
1377
int ret;
1378
1379
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1380
if (!msg)
1381
return -ENOMEM;
1382
1383
ret = nl802154_prep_scan_event_msg(msg, rdev, wpan_dev, 0, 0, 0,
1384
NL802154_CMD_SCAN_EVENT,
1385
desc);
1386
if (ret < 0) {
1387
nlmsg_free(msg);
1388
return ret;
1389
}
1390
1391
return genlmsg_multicast_netns(&nl802154_fam, wpan_phy_net(wpan_phy),
1392
msg, 0, NL802154_MCGRP_SCAN, GFP_ATOMIC);
1393
}
1394
EXPORT_SYMBOL_GPL(nl802154_scan_event);
1395
1396
static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
1397
{
1398
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1399
struct net_device *dev = info->user_ptr[1];
1400
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1401
struct wpan_phy *wpan_phy = &rdev->wpan_phy;
1402
struct cfg802154_scan_request *request;
1403
u8 type;
1404
int err;
1405
1406
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1407
NL_SET_ERR_MSG(info->extack, "Monitors are not allowed to perform scans");
1408
return -EOPNOTSUPP;
1409
}
1410
1411
if (!info->attrs[NL802154_ATTR_SCAN_TYPE]) {
1412
NL_SET_ERR_MSG(info->extack, "Malformed request, missing scan type");
1413
return -EINVAL;
1414
}
1415
1416
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1417
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1418
return -EOPNOTSUPP;
1419
}
1420
1421
request = kzalloc(sizeof(*request), GFP_KERNEL);
1422
if (!request)
1423
return -ENOMEM;
1424
1425
request->wpan_dev = wpan_dev;
1426
request->wpan_phy = wpan_phy;
1427
1428
type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]);
1429
switch (type) {
1430
case NL802154_SCAN_ACTIVE:
1431
case NL802154_SCAN_PASSIVE:
1432
request->type = type;
1433
break;
1434
default:
1435
NL_SET_ERR_MSG_FMT(info->extack, "Unsupported scan type: %d", type);
1436
err = -EINVAL;
1437
goto free_request;
1438
}
1439
1440
/* Use current page by default */
1441
request->page = nla_get_u8_default(info->attrs[NL802154_ATTR_PAGE],
1442
wpan_phy->current_page);
1443
1444
/* Scan all supported channels by default */
1445
request->channels =
1446
nla_get_u32_default(info->attrs[NL802154_ATTR_SCAN_CHANNELS],
1447
wpan_phy->supported.channels[request->page]);
1448
1449
/* Use maximum duration order by default */
1450
request->duration =
1451
nla_get_u8_default(info->attrs[NL802154_ATTR_SCAN_DURATION],
1452
IEEE802154_MAX_SCAN_DURATION);
1453
1454
err = rdev_trigger_scan(rdev, request);
1455
if (err) {
1456
pr_err("Failure starting scanning (%d)\n", err);
1457
goto free_request;
1458
}
1459
1460
return 0;
1461
1462
free_request:
1463
kfree(request);
1464
1465
return err;
1466
}
1467
1468
static int nl802154_prep_scan_msg(struct sk_buff *msg,
1469
struct cfg802154_registered_device *rdev,
1470
struct wpan_dev *wpan_dev, u32 portid,
1471
u32 seq, int flags, u8 cmd, u8 arg)
1472
{
1473
void *hdr;
1474
1475
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1476
if (!hdr)
1477
return -ENOBUFS;
1478
1479
if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx))
1480
goto nla_put_failure;
1481
1482
if (wpan_dev->netdev &&
1483
nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
1484
goto nla_put_failure;
1485
1486
if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
1487
wpan_dev_id(wpan_dev), NL802154_ATTR_PAD))
1488
goto nla_put_failure;
1489
1490
if (cmd == NL802154_CMD_SCAN_DONE &&
1491
nla_put_u8(msg, NL802154_ATTR_SCAN_DONE_REASON, arg))
1492
goto nla_put_failure;
1493
1494
genlmsg_end(msg, hdr);
1495
1496
return 0;
1497
1498
nla_put_failure:
1499
genlmsg_cancel(msg, hdr);
1500
1501
return -EMSGSIZE;
1502
}
1503
1504
static int nl802154_send_scan_msg(struct cfg802154_registered_device *rdev,
1505
struct wpan_dev *wpan_dev, u8 cmd, u8 arg)
1506
{
1507
struct sk_buff *msg;
1508
int ret;
1509
1510
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1511
if (!msg)
1512
return -ENOMEM;
1513
1514
ret = nl802154_prep_scan_msg(msg, rdev, wpan_dev, 0, 0, 0, cmd, arg);
1515
if (ret < 0) {
1516
nlmsg_free(msg);
1517
return ret;
1518
}
1519
1520
return genlmsg_multicast_netns(&nl802154_fam,
1521
wpan_phy_net(&rdev->wpan_phy), msg, 0,
1522
NL802154_MCGRP_SCAN, GFP_KERNEL);
1523
}
1524
1525
int nl802154_scan_started(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
1526
{
1527
struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
1528
int err;
1529
1530
/* Ignore errors when there are no listeners */
1531
err = nl802154_send_scan_msg(rdev, wpan_dev, NL802154_CMD_TRIGGER_SCAN, 0);
1532
if (err == -ESRCH)
1533
err = 0;
1534
1535
return err;
1536
}
1537
EXPORT_SYMBOL_GPL(nl802154_scan_started);
1538
1539
int nl802154_scan_done(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
1540
enum nl802154_scan_done_reasons reason)
1541
{
1542
struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
1543
int err;
1544
1545
/* Ignore errors when there are no listeners */
1546
err = nl802154_send_scan_msg(rdev, wpan_dev, NL802154_CMD_SCAN_DONE, reason);
1547
if (err == -ESRCH)
1548
err = 0;
1549
1550
return err;
1551
}
1552
EXPORT_SYMBOL_GPL(nl802154_scan_done);
1553
1554
static int nl802154_abort_scan(struct sk_buff *skb, struct genl_info *info)
1555
{
1556
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1557
struct net_device *dev = info->user_ptr[1];
1558
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1559
1560
/* Resources are released in the notification helper above */
1561
return rdev_abort_scan(rdev, wpan_dev);
1562
}
1563
1564
static int
1565
nl802154_send_beacons(struct sk_buff *skb, struct genl_info *info)
1566
{
1567
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1568
struct net_device *dev = info->user_ptr[1];
1569
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1570
struct wpan_phy *wpan_phy = &rdev->wpan_phy;
1571
struct cfg802154_beacon_request *request;
1572
int err;
1573
1574
if (wpan_dev->iftype != NL802154_IFTYPE_COORD) {
1575
NL_SET_ERR_MSG(info->extack, "Only coordinators can send beacons");
1576
return -EOPNOTSUPP;
1577
}
1578
1579
if (wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
1580
NL_SET_ERR_MSG(info->extack, "Device is not part of any PAN");
1581
return -EPERM;
1582
}
1583
1584
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1585
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1586
return -EOPNOTSUPP;
1587
}
1588
1589
request = kzalloc(sizeof(*request), GFP_KERNEL);
1590
if (!request)
1591
return -ENOMEM;
1592
1593
request->wpan_dev = wpan_dev;
1594
request->wpan_phy = wpan_phy;
1595
1596
/* Use maximum duration order by default */
1597
request->interval = nla_get_u8_default(info->attrs[NL802154_ATTR_BEACON_INTERVAL],
1598
IEEE802154_MAX_SCAN_DURATION);
1599
1600
err = rdev_send_beacons(rdev, request);
1601
if (err) {
1602
pr_err("Failure starting sending beacons (%d)\n", err);
1603
goto free_request;
1604
}
1605
1606
return 0;
1607
1608
free_request:
1609
kfree(request);
1610
1611
return err;
1612
}
1613
1614
void nl802154_beaconing_done(struct wpan_dev *wpan_dev)
1615
{
1616
/* NOP */
1617
}
1618
EXPORT_SYMBOL_GPL(nl802154_beaconing_done);
1619
1620
static int
1621
nl802154_stop_beacons(struct sk_buff *skb, struct genl_info *info)
1622
{
1623
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1624
struct net_device *dev = info->user_ptr[1];
1625
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1626
1627
/* Resources are released in the notification helper above */
1628
return rdev_stop_beacons(rdev, wpan_dev);
1629
}
1630
1631
static int nl802154_associate(struct sk_buff *skb, struct genl_info *info)
1632
{
1633
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1634
struct net_device *dev = info->user_ptr[1];
1635
struct wpan_dev *wpan_dev;
1636
struct wpan_phy *wpan_phy;
1637
struct ieee802154_addr coord;
1638
int err;
1639
1640
wpan_dev = dev->ieee802154_ptr;
1641
wpan_phy = &rdev->wpan_phy;
1642
1643
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1644
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1645
return -EOPNOTSUPP;
1646
}
1647
1648
if (!info->attrs[NL802154_ATTR_PAN_ID] ||
1649
!info->attrs[NL802154_ATTR_EXTENDED_ADDR])
1650
return -EINVAL;
1651
1652
coord.pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
1653
coord.mode = IEEE802154_ADDR_LONG;
1654
coord.extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
1655
1656
mutex_lock(&wpan_dev->association_lock);
1657
err = rdev_associate(rdev, wpan_dev, &coord);
1658
mutex_unlock(&wpan_dev->association_lock);
1659
if (err)
1660
pr_err("Association with PAN ID 0x%x failed (%d)\n",
1661
le16_to_cpu(coord.pan_id), err);
1662
1663
return err;
1664
}
1665
1666
static int nl802154_disassociate(struct sk_buff *skb, struct genl_info *info)
1667
{
1668
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1669
struct net_device *dev = info->user_ptr[1];
1670
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1671
struct wpan_phy *wpan_phy = &rdev->wpan_phy;
1672
struct ieee802154_addr target;
1673
1674
if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
1675
NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
1676
return -EOPNOTSUPP;
1677
}
1678
1679
target.pan_id = wpan_dev->pan_id;
1680
1681
if (info->attrs[NL802154_ATTR_EXTENDED_ADDR]) {
1682
target.mode = IEEE802154_ADDR_LONG;
1683
target.extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
1684
} else if (info->attrs[NL802154_ATTR_SHORT_ADDR]) {
1685
target.mode = IEEE802154_ADDR_SHORT;
1686
target.short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
1687
} else {
1688
NL_SET_ERR_MSG(info->extack, "Device address is missing");
1689
return -EINVAL;
1690
}
1691
1692
mutex_lock(&wpan_dev->association_lock);
1693
rdev_disassociate(rdev, wpan_dev, &target);
1694
mutex_unlock(&wpan_dev->association_lock);
1695
1696
return 0;
1697
}
1698
1699
static int nl802154_set_max_associations(struct sk_buff *skb, struct genl_info *info)
1700
{
1701
struct net_device *dev = info->user_ptr[1];
1702
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1703
unsigned int max_assoc;
1704
1705
if (!info->attrs[NL802154_ATTR_MAX_ASSOCIATIONS]) {
1706
NL_SET_ERR_MSG(info->extack, "No maximum number of association given");
1707
return -EINVAL;
1708
}
1709
1710
max_assoc = nla_get_u32(info->attrs[NL802154_ATTR_MAX_ASSOCIATIONS]);
1711
1712
mutex_lock(&wpan_dev->association_lock);
1713
cfg802154_set_max_associations(wpan_dev, max_assoc);
1714
mutex_unlock(&wpan_dev->association_lock);
1715
1716
return 0;
1717
}
1718
1719
static int nl802154_send_peer_info(struct sk_buff *msg,
1720
struct netlink_callback *cb,
1721
u32 seq, int flags,
1722
struct cfg802154_registered_device *rdev,
1723
struct wpan_dev *wpan_dev,
1724
struct ieee802154_pan_device *peer,
1725
enum nl802154_peer_type type)
1726
{
1727
struct nlattr *nla;
1728
void *hdr;
1729
1730
ASSERT_RTNL();
1731
1732
hdr = nl802154hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
1733
NL802154_CMD_LIST_ASSOCIATIONS);
1734
if (!hdr)
1735
return -ENOBUFS;
1736
1737
genl_dump_check_consistent(cb, hdr);
1738
1739
nla = nla_nest_start_noflag(msg, NL802154_ATTR_PEER);
1740
if (!nla)
1741
goto nla_put_failure;
1742
1743
if (nla_put_u8(msg, NL802154_DEV_ADDR_ATTR_PEER_TYPE, type))
1744
goto nla_put_failure;
1745
1746
if (nla_put_u8(msg, NL802154_DEV_ADDR_ATTR_MODE, peer->mode))
1747
goto nla_put_failure;
1748
1749
if (nla_put(msg, NL802154_DEV_ADDR_ATTR_SHORT,
1750
IEEE802154_SHORT_ADDR_LEN, &peer->short_addr))
1751
goto nla_put_failure;
1752
1753
if (nla_put(msg, NL802154_DEV_ADDR_ATTR_EXTENDED,
1754
IEEE802154_EXTENDED_ADDR_LEN, &peer->extended_addr))
1755
goto nla_put_failure;
1756
1757
nla_nest_end(msg, nla);
1758
1759
genlmsg_end(msg, hdr);
1760
1761
return 0;
1762
1763
nla_put_failure:
1764
genlmsg_cancel(msg, hdr);
1765
return -EMSGSIZE;
1766
}
1767
1768
static int nl802154_list_associations(struct sk_buff *skb,
1769
struct netlink_callback *cb)
1770
{
1771
struct cfg802154_registered_device *rdev;
1772
struct ieee802154_pan_device *child;
1773
struct wpan_dev *wpan_dev;
1774
int err;
1775
1776
err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1777
if (err)
1778
return err;
1779
1780
mutex_lock(&wpan_dev->association_lock);
1781
1782
if (cb->args[2])
1783
goto out;
1784
1785
if (wpan_dev->parent) {
1786
err = nl802154_send_peer_info(skb, cb, cb->nlh->nlmsg_seq,
1787
NLM_F_MULTI, rdev, wpan_dev,
1788
wpan_dev->parent,
1789
NL802154_PEER_TYPE_PARENT);
1790
if (err < 0)
1791
goto out_err;
1792
}
1793
1794
list_for_each_entry(child, &wpan_dev->children, node) {
1795
err = nl802154_send_peer_info(skb, cb, cb->nlh->nlmsg_seq,
1796
NLM_F_MULTI, rdev, wpan_dev,
1797
child,
1798
NL802154_PEER_TYPE_CHILD);
1799
if (err < 0)
1800
goto out_err;
1801
}
1802
1803
cb->args[2] = 1;
1804
out:
1805
err = skb->len;
1806
out_err:
1807
mutex_unlock(&wpan_dev->association_lock);
1808
1809
nl802154_finish_wpan_dev_dump(rdev);
1810
1811
return err;
1812
}
1813
1814
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1815
static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
1816
[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
1817
[NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
1818
[NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
1819
[NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
1820
};
1821
1822
static int
1823
ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
1824
struct ieee802154_addr *addr)
1825
{
1826
struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1];
1827
1828
if (!nla || nla_parse_nested_deprecated(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla, nl802154_dev_addr_policy, NULL))
1829
return -EINVAL;
1830
1831
if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] || !attrs[NL802154_DEV_ADDR_ATTR_MODE])
1832
return -EINVAL;
1833
1834
addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]);
1835
addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]);
1836
switch (addr->mode) {
1837
case NL802154_DEV_ADDR_SHORT:
1838
if (!attrs[NL802154_DEV_ADDR_ATTR_SHORT])
1839
return -EINVAL;
1840
addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]);
1841
break;
1842
case NL802154_DEV_ADDR_EXTENDED:
1843
if (!attrs[NL802154_DEV_ADDR_ATTR_EXTENDED])
1844
return -EINVAL;
1845
addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]);
1846
break;
1847
default:
1848
return -EINVAL;
1849
}
1850
1851
return 0;
1852
}
1853
1854
static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
1855
[NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
1856
[NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
1857
[NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
1858
[NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
1859
[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
1860
};
1861
1862
static int
1863
ieee802154_llsec_parse_key_id(struct nlattr *nla,
1864
struct ieee802154_llsec_key_id *desc)
1865
{
1866
struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1];
1867
1868
if (!nla || nla_parse_nested_deprecated(attrs, NL802154_KEY_ID_ATTR_MAX, nla, nl802154_key_id_policy, NULL))
1869
return -EINVAL;
1870
1871
if (!attrs[NL802154_KEY_ID_ATTR_MODE])
1872
return -EINVAL;
1873
1874
desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]);
1875
switch (desc->mode) {
1876
case NL802154_KEY_ID_MODE_IMPLICIT:
1877
if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT])
1878
return -EINVAL;
1879
1880
if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT],
1881
&desc->device_addr) < 0)
1882
return -EINVAL;
1883
break;
1884
case NL802154_KEY_ID_MODE_INDEX:
1885
break;
1886
case NL802154_KEY_ID_MODE_INDEX_SHORT:
1887
if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
1888
return -EINVAL;
1889
1890
desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]);
1891
break;
1892
case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
1893
if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
1894
return -EINVAL;
1895
1896
desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]);
1897
break;
1898
default:
1899
return -EINVAL;
1900
}
1901
1902
if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
1903
if (!attrs[NL802154_KEY_ID_ATTR_INDEX])
1904
return -EINVAL;
1905
1906
/* TODO change id to idx */
1907
desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]);
1908
}
1909
1910
return 0;
1911
}
1912
1913
static int nl802154_set_llsec_params(struct sk_buff *skb,
1914
struct genl_info *info)
1915
{
1916
struct cfg802154_registered_device *rdev = info->user_ptr[0];
1917
struct net_device *dev = info->user_ptr[1];
1918
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1919
struct ieee802154_llsec_params params;
1920
u32 changed = 0;
1921
int ret;
1922
1923
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1924
return -EOPNOTSUPP;
1925
1926
if (info->attrs[NL802154_ATTR_SEC_ENABLED]) {
1927
u8 enabled;
1928
1929
enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1930
if (enabled != 0 && enabled != 1)
1931
return -EINVAL;
1932
1933
params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1934
changed |= IEEE802154_LLSEC_PARAM_ENABLED;
1935
}
1936
1937
if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) {
1938
ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID],
1939
&params.out_key);
1940
if (ret < 0)
1941
return ret;
1942
1943
changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
1944
}
1945
1946
if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) {
1947
params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]);
1948
if (params.out_level > NL802154_SECLEVEL_MAX)
1949
return -EINVAL;
1950
1951
changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
1952
}
1953
1954
if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) {
1955
params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]);
1956
changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
1957
}
1958
1959
return rdev_set_llsec_params(rdev, wpan_dev, &params, changed);
1960
}
1961
1962
static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
1963
u32 seq, int flags,
1964
struct cfg802154_registered_device *rdev,
1965
struct net_device *dev,
1966
const struct ieee802154_llsec_key_entry *key)
1967
{
1968
void *hdr;
1969
u32 commands[NL802154_CMD_FRAME_NR_IDS / 32];
1970
struct nlattr *nl_key, *nl_key_id;
1971
1972
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1973
if (!hdr)
1974
return -ENOBUFS;
1975
1976
if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1977
goto nla_put_failure;
1978
1979
nl_key = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_KEY);
1980
if (!nl_key)
1981
goto nla_put_failure;
1982
1983
nl_key_id = nla_nest_start_noflag(msg, NL802154_KEY_ATTR_ID);
1984
if (!nl_key_id)
1985
goto nla_put_failure;
1986
1987
if (ieee802154_llsec_send_key_id(msg, &key->id) < 0)
1988
goto nla_put_failure;
1989
1990
nla_nest_end(msg, nl_key_id);
1991
1992
if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES,
1993
key->key->frame_types))
1994
goto nla_put_failure;
1995
1996
if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) {
1997
/* TODO for each nested */
1998
memset(commands, 0, sizeof(commands));
1999
commands[7] = key->key->cmd_frame_ids;
2000
if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS,
2001
sizeof(commands), commands))
2002
goto nla_put_failure;
2003
}
2004
2005
if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE,
2006
key->key->key))
2007
goto nla_put_failure;
2008
2009
nla_nest_end(msg, nl_key);
2010
genlmsg_end(msg, hdr);
2011
2012
return 0;
2013
2014
nla_put_failure:
2015
genlmsg_cancel(msg, hdr);
2016
return -EMSGSIZE;
2017
}
2018
2019
static int
2020
nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb)
2021
{
2022
struct cfg802154_registered_device *rdev = NULL;
2023
struct ieee802154_llsec_key_entry *key;
2024
struct ieee802154_llsec_table *table;
2025
struct wpan_dev *wpan_dev;
2026
int err;
2027
2028
err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2029
if (err)
2030
return err;
2031
2032
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2033
err = skb->len;
2034
goto out_err;
2035
}
2036
2037
if (!wpan_dev->netdev) {
2038
err = -EINVAL;
2039
goto out_err;
2040
}
2041
2042
rdev_lock_llsec_table(rdev, wpan_dev);
2043
rdev_get_llsec_table(rdev, wpan_dev, &table);
2044
2045
/* TODO make it like station dump */
2046
if (cb->args[2])
2047
goto out;
2048
2049
list_for_each_entry(key, &table->keys, list) {
2050
if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY,
2051
NETLINK_CB(cb->skb).portid,
2052
cb->nlh->nlmsg_seq, NLM_F_MULTI,
2053
rdev, wpan_dev->netdev, key) < 0) {
2054
/* TODO */
2055
err = -EIO;
2056
rdev_unlock_llsec_table(rdev, wpan_dev);
2057
goto out_err;
2058
}
2059
}
2060
2061
cb->args[2] = 1;
2062
2063
out:
2064
rdev_unlock_llsec_table(rdev, wpan_dev);
2065
err = skb->len;
2066
out_err:
2067
nl802154_finish_wpan_dev_dump(rdev);
2068
2069
return err;
2070
}
2071
2072
static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = {
2073
[NL802154_KEY_ATTR_ID] = { NLA_NESTED },
2074
/* TODO handle it as for_each_nested and NLA_FLAG? */
2075
[NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
2076
/* TODO handle it as for_each_nested, not static array? */
2077
[NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 },
2078
[NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE },
2079
};
2080
2081
static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info)
2082
{
2083
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2084
struct net_device *dev = info->user_ptr[1];
2085
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2086
struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
2087
struct ieee802154_llsec_key key = { };
2088
struct ieee802154_llsec_key_id id = { };
2089
u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
2090
2091
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2092
return -EOPNOTSUPP;
2093
2094
if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
2095
nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack))
2096
return -EINVAL;
2097
2098
if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] ||
2099
!attrs[NL802154_KEY_ATTR_BYTES])
2100
return -EINVAL;
2101
2102
if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
2103
return -ENOBUFS;
2104
2105
key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]);
2106
if (key.frame_types > BIT(NL802154_FRAME_MAX) ||
2107
((key.frame_types & BIT(NL802154_FRAME_CMD)) &&
2108
!attrs[NL802154_KEY_ATTR_USAGE_CMDS]))
2109
return -EINVAL;
2110
2111
if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) {
2112
/* TODO for each nested */
2113
nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS],
2114
NL802154_CMD_FRAME_NR_IDS / 8);
2115
2116
/* TODO understand the -EINVAL logic here? last condition */
2117
if (commands[0] || commands[1] || commands[2] || commands[3] ||
2118
commands[4] || commands[5] || commands[6] ||
2119
commands[7] > BIT(NL802154_CMD_FRAME_MAX))
2120
return -EINVAL;
2121
2122
key.cmd_frame_ids = commands[7];
2123
} else {
2124
key.cmd_frame_ids = 0;
2125
}
2126
2127
nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE);
2128
2129
if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
2130
return -ENOBUFS;
2131
2132
return rdev_add_llsec_key(rdev, wpan_dev, &id, &key);
2133
}
2134
2135
static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info)
2136
{
2137
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2138
struct net_device *dev = info->user_ptr[1];
2139
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2140
struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
2141
struct ieee802154_llsec_key_id id;
2142
2143
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2144
return -EOPNOTSUPP;
2145
2146
if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
2147
nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack))
2148
return -EINVAL;
2149
2150
if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
2151
return -ENOBUFS;
2152
2153
return rdev_del_llsec_key(rdev, wpan_dev, &id);
2154
}
2155
2156
static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
2157
u32 seq, int flags,
2158
struct cfg802154_registered_device *rdev,
2159
struct net_device *dev,
2160
const struct ieee802154_llsec_device *dev_desc)
2161
{
2162
void *hdr;
2163
struct nlattr *nl_device;
2164
2165
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
2166
if (!hdr)
2167
return -ENOBUFS;
2168
2169
if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
2170
goto nla_put_failure;
2171
2172
nl_device = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_DEVICE);
2173
if (!nl_device)
2174
goto nla_put_failure;
2175
2176
if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER,
2177
dev_desc->frame_counter) ||
2178
nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) ||
2179
nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR,
2180
dev_desc->short_addr) ||
2181
nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR,
2182
dev_desc->hwaddr, NL802154_DEV_ATTR_PAD) ||
2183
nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
2184
dev_desc->seclevel_exempt) ||
2185
nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode))
2186
goto nla_put_failure;
2187
2188
nla_nest_end(msg, nl_device);
2189
genlmsg_end(msg, hdr);
2190
2191
return 0;
2192
2193
nla_put_failure:
2194
genlmsg_cancel(msg, hdr);
2195
return -EMSGSIZE;
2196
}
2197
2198
static int
2199
nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb)
2200
{
2201
struct cfg802154_registered_device *rdev = NULL;
2202
struct ieee802154_llsec_device *dev;
2203
struct ieee802154_llsec_table *table;
2204
struct wpan_dev *wpan_dev;
2205
int err;
2206
2207
err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2208
if (err)
2209
return err;
2210
2211
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2212
err = skb->len;
2213
goto out_err;
2214
}
2215
2216
if (!wpan_dev->netdev) {
2217
err = -EINVAL;
2218
goto out_err;
2219
}
2220
2221
rdev_lock_llsec_table(rdev, wpan_dev);
2222
rdev_get_llsec_table(rdev, wpan_dev, &table);
2223
2224
/* TODO make it like station dump */
2225
if (cb->args[2])
2226
goto out;
2227
2228
list_for_each_entry(dev, &table->devices, list) {
2229
if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL,
2230
NETLINK_CB(cb->skb).portid,
2231
cb->nlh->nlmsg_seq, NLM_F_MULTI,
2232
rdev, wpan_dev->netdev, dev) < 0) {
2233
/* TODO */
2234
err = -EIO;
2235
rdev_unlock_llsec_table(rdev, wpan_dev);
2236
goto out_err;
2237
}
2238
}
2239
2240
cb->args[2] = 1;
2241
2242
out:
2243
rdev_unlock_llsec_table(rdev, wpan_dev);
2244
err = skb->len;
2245
out_err:
2246
nl802154_finish_wpan_dev_dump(rdev);
2247
2248
return err;
2249
}
2250
2251
static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = {
2252
[NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
2253
[NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
2254
[NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
2255
[NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
2256
[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
2257
[NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
2258
};
2259
2260
static int
2261
ieee802154_llsec_parse_device(struct nlattr *nla,
2262
struct ieee802154_llsec_device *dev)
2263
{
2264
struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
2265
2266
if (!nla || nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, nla, nl802154_dev_policy, NULL))
2267
return -EINVAL;
2268
2269
memset(dev, 0, sizeof(*dev));
2270
2271
if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] ||
2272
!attrs[NL802154_DEV_ATTR_PAN_ID] ||
2273
!attrs[NL802154_DEV_ATTR_SHORT_ADDR] ||
2274
!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] ||
2275
!attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] ||
2276
!attrs[NL802154_DEV_ATTR_KEY_MODE])
2277
return -EINVAL;
2278
2279
/* TODO be32 */
2280
dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]);
2281
dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]);
2282
dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]);
2283
/* TODO rename hwaddr to extended_addr */
2284
dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
2285
dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]);
2286
dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]);
2287
2288
if (dev->key_mode > NL802154_DEVKEY_MAX ||
2289
(dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1))
2290
return -EINVAL;
2291
2292
return 0;
2293
}
2294
2295
static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info)
2296
{
2297
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2298
struct net_device *dev = info->user_ptr[1];
2299
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2300
struct ieee802154_llsec_device dev_desc;
2301
2302
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2303
return -EOPNOTSUPP;
2304
2305
if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE],
2306
&dev_desc) < 0)
2307
return -EINVAL;
2308
2309
return rdev_add_device(rdev, wpan_dev, &dev_desc);
2310
}
2311
2312
static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info)
2313
{
2314
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2315
struct net_device *dev = info->user_ptr[1];
2316
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2317
struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
2318
__le64 extended_addr;
2319
2320
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2321
return -EOPNOTSUPP;
2322
2323
if (!info->attrs[NL802154_ATTR_SEC_DEVICE] ||
2324
nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack))
2325
return -EINVAL;
2326
2327
if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR])
2328
return -EINVAL;
2329
2330
extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
2331
return rdev_del_device(rdev, wpan_dev, extended_addr);
2332
}
2333
2334
static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
2335
u32 seq, int flags,
2336
struct cfg802154_registered_device *rdev,
2337
struct net_device *dev, __le64 extended_addr,
2338
const struct ieee802154_llsec_device_key *devkey)
2339
{
2340
void *hdr;
2341
struct nlattr *nl_devkey, *nl_key_id;
2342
2343
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
2344
if (!hdr)
2345
return -ENOBUFS;
2346
2347
if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
2348
goto nla_put_failure;
2349
2350
nl_devkey = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_DEVKEY);
2351
if (!nl_devkey)
2352
goto nla_put_failure;
2353
2354
if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
2355
extended_addr, NL802154_DEVKEY_ATTR_PAD) ||
2356
nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER,
2357
devkey->frame_counter))
2358
goto nla_put_failure;
2359
2360
nl_key_id = nla_nest_start_noflag(msg, NL802154_DEVKEY_ATTR_ID);
2361
if (!nl_key_id)
2362
goto nla_put_failure;
2363
2364
if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0)
2365
goto nla_put_failure;
2366
2367
nla_nest_end(msg, nl_key_id);
2368
nla_nest_end(msg, nl_devkey);
2369
genlmsg_end(msg, hdr);
2370
2371
return 0;
2372
2373
nla_put_failure:
2374
genlmsg_cancel(msg, hdr);
2375
return -EMSGSIZE;
2376
}
2377
2378
static int
2379
nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb)
2380
{
2381
struct cfg802154_registered_device *rdev = NULL;
2382
struct ieee802154_llsec_device_key *kpos;
2383
struct ieee802154_llsec_device *dpos;
2384
struct ieee802154_llsec_table *table;
2385
struct wpan_dev *wpan_dev;
2386
int err;
2387
2388
err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2389
if (err)
2390
return err;
2391
2392
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2393
err = skb->len;
2394
goto out_err;
2395
}
2396
2397
if (!wpan_dev->netdev) {
2398
err = -EINVAL;
2399
goto out_err;
2400
}
2401
2402
rdev_lock_llsec_table(rdev, wpan_dev);
2403
rdev_get_llsec_table(rdev, wpan_dev, &table);
2404
2405
/* TODO make it like station dump */
2406
if (cb->args[2])
2407
goto out;
2408
2409
/* TODO look if remove devkey and do some nested attribute */
2410
list_for_each_entry(dpos, &table->devices, list) {
2411
list_for_each_entry(kpos, &dpos->keys, list) {
2412
if (nl802154_send_devkey(skb,
2413
NL802154_CMD_NEW_SEC_LEVEL,
2414
NETLINK_CB(cb->skb).portid,
2415
cb->nlh->nlmsg_seq,
2416
NLM_F_MULTI, rdev,
2417
wpan_dev->netdev,
2418
dpos->hwaddr,
2419
kpos) < 0) {
2420
/* TODO */
2421
err = -EIO;
2422
rdev_unlock_llsec_table(rdev, wpan_dev);
2423
goto out_err;
2424
}
2425
}
2426
}
2427
2428
cb->args[2] = 1;
2429
2430
out:
2431
rdev_unlock_llsec_table(rdev, wpan_dev);
2432
err = skb->len;
2433
out_err:
2434
nl802154_finish_wpan_dev_dump(rdev);
2435
2436
return err;
2437
}
2438
2439
static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
2440
[NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
2441
[NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 },
2442
[NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED },
2443
};
2444
2445
static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
2446
{
2447
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2448
struct net_device *dev = info->user_ptr[1];
2449
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2450
struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
2451
struct ieee802154_llsec_device_key key;
2452
__le64 extended_addr;
2453
2454
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2455
return -EOPNOTSUPP;
2456
2457
if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
2458
nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack) < 0)
2459
return -EINVAL;
2460
2461
if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] ||
2462
!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
2463
return -EINVAL;
2464
2465
/* TODO change key.id ? */
2466
if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
2467
&key.key_id) < 0)
2468
return -ENOBUFS;
2469
2470
/* TODO be32 */
2471
key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]);
2472
/* TODO change naming hwaddr -> extended_addr
2473
* check unique identifier short+pan OR extended_addr
2474
*/
2475
extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
2476
return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key);
2477
}
2478
2479
static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
2480
{
2481
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2482
struct net_device *dev = info->user_ptr[1];
2483
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2484
struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
2485
struct ieee802154_llsec_device_key key;
2486
__le64 extended_addr;
2487
2488
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2489
return -EOPNOTSUPP;
2490
2491
if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
2492
nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack))
2493
return -EINVAL;
2494
2495
if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
2496
return -EINVAL;
2497
2498
/* TODO change key.id ? */
2499
if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
2500
&key.key_id) < 0)
2501
return -ENOBUFS;
2502
2503
/* TODO change naming hwaddr -> extended_addr
2504
* check unique identifier short+pan OR extended_addr
2505
*/
2506
extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
2507
return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key);
2508
}
2509
2510
static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
2511
u32 seq, int flags,
2512
struct cfg802154_registered_device *rdev,
2513
struct net_device *dev,
2514
const struct ieee802154_llsec_seclevel *sl)
2515
{
2516
void *hdr;
2517
struct nlattr *nl_seclevel;
2518
2519
hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
2520
if (!hdr)
2521
return -ENOBUFS;
2522
2523
if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
2524
goto nla_put_failure;
2525
2526
nl_seclevel = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_LEVEL);
2527
if (!nl_seclevel)
2528
goto nla_put_failure;
2529
2530
if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) ||
2531
nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) ||
2532
nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
2533
sl->device_override))
2534
goto nla_put_failure;
2535
2536
if (sl->frame_type == NL802154_FRAME_CMD) {
2537
if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME,
2538
sl->cmd_frame_id))
2539
goto nla_put_failure;
2540
}
2541
2542
nla_nest_end(msg, nl_seclevel);
2543
genlmsg_end(msg, hdr);
2544
2545
return 0;
2546
2547
nla_put_failure:
2548
genlmsg_cancel(msg, hdr);
2549
return -EMSGSIZE;
2550
}
2551
2552
static int
2553
nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb)
2554
{
2555
struct cfg802154_registered_device *rdev = NULL;
2556
struct ieee802154_llsec_seclevel *sl;
2557
struct ieee802154_llsec_table *table;
2558
struct wpan_dev *wpan_dev;
2559
int err;
2560
2561
err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2562
if (err)
2563
return err;
2564
2565
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2566
err = skb->len;
2567
goto out_err;
2568
}
2569
2570
if (!wpan_dev->netdev) {
2571
err = -EINVAL;
2572
goto out_err;
2573
}
2574
2575
rdev_lock_llsec_table(rdev, wpan_dev);
2576
rdev_get_llsec_table(rdev, wpan_dev, &table);
2577
2578
/* TODO make it like station dump */
2579
if (cb->args[2])
2580
goto out;
2581
2582
list_for_each_entry(sl, &table->security_levels, list) {
2583
if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL,
2584
NETLINK_CB(cb->skb).portid,
2585
cb->nlh->nlmsg_seq, NLM_F_MULTI,
2586
rdev, wpan_dev->netdev, sl) < 0) {
2587
/* TODO */
2588
err = -EIO;
2589
rdev_unlock_llsec_table(rdev, wpan_dev);
2590
goto out_err;
2591
}
2592
}
2593
2594
cb->args[2] = 1;
2595
2596
out:
2597
rdev_unlock_llsec_table(rdev, wpan_dev);
2598
err = skb->len;
2599
out_err:
2600
nl802154_finish_wpan_dev_dump(rdev);
2601
2602
return err;
2603
}
2604
2605
static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
2606
[NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 },
2607
[NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
2608
[NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
2609
[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
2610
};
2611
2612
static int
2613
llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl)
2614
{
2615
struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1];
2616
2617
if (!nla || nla_parse_nested_deprecated(attrs, NL802154_SECLEVEL_ATTR_MAX, nla, nl802154_seclevel_policy, NULL))
2618
return -EINVAL;
2619
2620
memset(sl, 0, sizeof(*sl));
2621
2622
if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] ||
2623
!attrs[NL802154_SECLEVEL_ATTR_FRAME] ||
2624
!attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
2625
return -EINVAL;
2626
2627
sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]);
2628
sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]);
2629
sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]);
2630
if (sl->frame_type > NL802154_FRAME_MAX ||
2631
(sl->device_override != 0 && sl->device_override != 1))
2632
return -EINVAL;
2633
2634
if (sl->frame_type == NL802154_FRAME_CMD) {
2635
if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME])
2636
return -EINVAL;
2637
2638
sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]);
2639
if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX)
2640
return -EINVAL;
2641
}
2642
2643
return 0;
2644
}
2645
2646
static int nl802154_add_llsec_seclevel(struct sk_buff *skb,
2647
struct genl_info *info)
2648
{
2649
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2650
struct net_device *dev = info->user_ptr[1];
2651
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2652
struct ieee802154_llsec_seclevel sl;
2653
2654
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2655
return -EOPNOTSUPP;
2656
2657
if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2658
&sl) < 0)
2659
return -EINVAL;
2660
2661
return rdev_add_seclevel(rdev, wpan_dev, &sl);
2662
}
2663
2664
static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
2665
struct genl_info *info)
2666
{
2667
struct cfg802154_registered_device *rdev = info->user_ptr[0];
2668
struct net_device *dev = info->user_ptr[1];
2669
struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2670
struct ieee802154_llsec_seclevel sl;
2671
2672
if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2673
return -EOPNOTSUPP;
2674
2675
if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2676
&sl) < 0)
2677
return -EINVAL;
2678
2679
return rdev_del_seclevel(rdev, wpan_dev, &sl);
2680
}
2681
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2682
2683
#define NL802154_FLAG_NEED_WPAN_PHY 0x01
2684
#define NL802154_FLAG_NEED_NETDEV 0x02
2685
#define NL802154_FLAG_NEED_RTNL 0x04
2686
#define NL802154_FLAG_CHECK_NETDEV_UP 0x08
2687
#define NL802154_FLAG_NEED_WPAN_DEV 0x10
2688
2689
static int nl802154_pre_doit(const struct genl_split_ops *ops,
2690
struct sk_buff *skb,
2691
struct genl_info *info)
2692
{
2693
struct cfg802154_registered_device *rdev;
2694
struct wpan_dev *wpan_dev;
2695
struct net_device *dev;
2696
bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
2697
2698
if (rtnl)
2699
rtnl_lock();
2700
2701
if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
2702
rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
2703
if (IS_ERR(rdev)) {
2704
if (rtnl)
2705
rtnl_unlock();
2706
return PTR_ERR(rdev);
2707
}
2708
info->user_ptr[0] = rdev;
2709
} else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
2710
ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2711
ASSERT_RTNL();
2712
wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
2713
info->attrs);
2714
if (IS_ERR(wpan_dev)) {
2715
if (rtnl)
2716
rtnl_unlock();
2717
return PTR_ERR(wpan_dev);
2718
}
2719
2720
dev = wpan_dev->netdev;
2721
rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
2722
2723
if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
2724
if (!dev) {
2725
if (rtnl)
2726
rtnl_unlock();
2727
return -EINVAL;
2728
}
2729
2730
info->user_ptr[1] = dev;
2731
} else {
2732
info->user_ptr[1] = wpan_dev;
2733
}
2734
2735
if (dev) {
2736
if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
2737
!netif_running(dev)) {
2738
if (rtnl)
2739
rtnl_unlock();
2740
return -ENETDOWN;
2741
}
2742
2743
dev_hold(dev);
2744
}
2745
2746
info->user_ptr[0] = rdev;
2747
}
2748
2749
return 0;
2750
}
2751
2752
static void nl802154_post_doit(const struct genl_split_ops *ops,
2753
struct sk_buff *skb,
2754
struct genl_info *info)
2755
{
2756
if (info->user_ptr[1]) {
2757
if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2758
struct wpan_dev *wpan_dev = info->user_ptr[1];
2759
2760
dev_put(wpan_dev->netdev);
2761
} else {
2762
dev_put(info->user_ptr[1]);
2763
}
2764
}
2765
2766
if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
2767
rtnl_unlock();
2768
}
2769
2770
static const struct genl_ops nl802154_ops[] = {
2771
{
2772
.cmd = NL802154_CMD_GET_WPAN_PHY,
2773
.validate = GENL_DONT_VALIDATE_STRICT |
2774
GENL_DONT_VALIDATE_DUMP_STRICT,
2775
.doit = nl802154_get_wpan_phy,
2776
.dumpit = nl802154_dump_wpan_phy,
2777
.done = nl802154_dump_wpan_phy_done,
2778
/* can be retrieved by unprivileged users */
2779
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2780
NL802154_FLAG_NEED_RTNL,
2781
},
2782
{
2783
.cmd = NL802154_CMD_GET_INTERFACE,
2784
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2785
.doit = nl802154_get_interface,
2786
.dumpit = nl802154_dump_interface,
2787
/* can be retrieved by unprivileged users */
2788
.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2789
NL802154_FLAG_NEED_RTNL,
2790
},
2791
{
2792
.cmd = NL802154_CMD_NEW_INTERFACE,
2793
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2794
.doit = nl802154_new_interface,
2795
.flags = GENL_ADMIN_PERM,
2796
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2797
NL802154_FLAG_NEED_RTNL,
2798
},
2799
{
2800
.cmd = NL802154_CMD_DEL_INTERFACE,
2801
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2802
.doit = nl802154_del_interface,
2803
.flags = GENL_ADMIN_PERM,
2804
.internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2805
NL802154_FLAG_NEED_RTNL,
2806
},
2807
{
2808
.cmd = NL802154_CMD_SET_CHANNEL,
2809
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2810
.doit = nl802154_set_channel,
2811
.flags = GENL_ADMIN_PERM,
2812
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2813
NL802154_FLAG_NEED_RTNL,
2814
},
2815
{
2816
.cmd = NL802154_CMD_SET_CCA_MODE,
2817
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2818
.doit = nl802154_set_cca_mode,
2819
.flags = GENL_ADMIN_PERM,
2820
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2821
NL802154_FLAG_NEED_RTNL,
2822
},
2823
{
2824
.cmd = NL802154_CMD_SET_CCA_ED_LEVEL,
2825
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2826
.doit = nl802154_set_cca_ed_level,
2827
.flags = GENL_ADMIN_PERM,
2828
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2829
NL802154_FLAG_NEED_RTNL,
2830
},
2831
{
2832
.cmd = NL802154_CMD_SET_TX_POWER,
2833
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2834
.doit = nl802154_set_tx_power,
2835
.flags = GENL_ADMIN_PERM,
2836
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2837
NL802154_FLAG_NEED_RTNL,
2838
},
2839
{
2840
.cmd = NL802154_CMD_SET_WPAN_PHY_NETNS,
2841
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2842
.doit = nl802154_wpan_phy_netns,
2843
.flags = GENL_ADMIN_PERM,
2844
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2845
NL802154_FLAG_NEED_RTNL,
2846
},
2847
{
2848
.cmd = NL802154_CMD_SET_PAN_ID,
2849
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2850
.doit = nl802154_set_pan_id,
2851
.flags = GENL_ADMIN_PERM,
2852
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2853
NL802154_FLAG_NEED_RTNL,
2854
},
2855
{
2856
.cmd = NL802154_CMD_SET_SHORT_ADDR,
2857
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2858
.doit = nl802154_set_short_addr,
2859
.flags = GENL_ADMIN_PERM,
2860
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2861
NL802154_FLAG_NEED_RTNL,
2862
},
2863
{
2864
.cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
2865
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2866
.doit = nl802154_set_backoff_exponent,
2867
.flags = GENL_ADMIN_PERM,
2868
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2869
NL802154_FLAG_NEED_RTNL,
2870
},
2871
{
2872
.cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
2873
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2874
.doit = nl802154_set_max_csma_backoffs,
2875
.flags = GENL_ADMIN_PERM,
2876
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2877
NL802154_FLAG_NEED_RTNL,
2878
},
2879
{
2880
.cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
2881
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2882
.doit = nl802154_set_max_frame_retries,
2883
.flags = GENL_ADMIN_PERM,
2884
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2885
NL802154_FLAG_NEED_RTNL,
2886
},
2887
{
2888
.cmd = NL802154_CMD_SET_LBT_MODE,
2889
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2890
.doit = nl802154_set_lbt_mode,
2891
.flags = GENL_ADMIN_PERM,
2892
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2893
NL802154_FLAG_NEED_RTNL,
2894
},
2895
{
2896
.cmd = NL802154_CMD_SET_ACKREQ_DEFAULT,
2897
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2898
.doit = nl802154_set_ackreq_default,
2899
.flags = GENL_ADMIN_PERM,
2900
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2901
NL802154_FLAG_NEED_RTNL,
2902
},
2903
{
2904
.cmd = NL802154_CMD_TRIGGER_SCAN,
2905
.doit = nl802154_trigger_scan,
2906
.flags = GENL_ADMIN_PERM,
2907
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2908
NL802154_FLAG_CHECK_NETDEV_UP |
2909
NL802154_FLAG_NEED_RTNL,
2910
},
2911
{
2912
.cmd = NL802154_CMD_ABORT_SCAN,
2913
.doit = nl802154_abort_scan,
2914
.flags = GENL_ADMIN_PERM,
2915
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2916
NL802154_FLAG_CHECK_NETDEV_UP |
2917
NL802154_FLAG_NEED_RTNL,
2918
},
2919
{
2920
.cmd = NL802154_CMD_SEND_BEACONS,
2921
.doit = nl802154_send_beacons,
2922
.flags = GENL_ADMIN_PERM,
2923
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2924
NL802154_FLAG_CHECK_NETDEV_UP |
2925
NL802154_FLAG_NEED_RTNL,
2926
},
2927
{
2928
.cmd = NL802154_CMD_STOP_BEACONS,
2929
.doit = nl802154_stop_beacons,
2930
.flags = GENL_ADMIN_PERM,
2931
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2932
NL802154_FLAG_CHECK_NETDEV_UP |
2933
NL802154_FLAG_NEED_RTNL,
2934
},
2935
{
2936
.cmd = NL802154_CMD_ASSOCIATE,
2937
.doit = nl802154_associate,
2938
.flags = GENL_ADMIN_PERM,
2939
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2940
NL802154_FLAG_CHECK_NETDEV_UP |
2941
NL802154_FLAG_NEED_RTNL,
2942
},
2943
{
2944
.cmd = NL802154_CMD_DISASSOCIATE,
2945
.doit = nl802154_disassociate,
2946
.flags = GENL_ADMIN_PERM,
2947
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2948
NL802154_FLAG_CHECK_NETDEV_UP |
2949
NL802154_FLAG_NEED_RTNL,
2950
},
2951
{
2952
.cmd = NL802154_CMD_SET_MAX_ASSOCIATIONS,
2953
.doit = nl802154_set_max_associations,
2954
.flags = GENL_ADMIN_PERM,
2955
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2956
NL802154_FLAG_NEED_RTNL,
2957
},
2958
{
2959
.cmd = NL802154_CMD_LIST_ASSOCIATIONS,
2960
.dumpit = nl802154_list_associations,
2961
/* can be retrieved by unprivileged users */
2962
},
2963
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2964
{
2965
.cmd = NL802154_CMD_SET_SEC_PARAMS,
2966
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2967
.doit = nl802154_set_llsec_params,
2968
.flags = GENL_ADMIN_PERM,
2969
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2970
NL802154_FLAG_NEED_RTNL,
2971
},
2972
{
2973
.cmd = NL802154_CMD_GET_SEC_KEY,
2974
.validate = GENL_DONT_VALIDATE_STRICT |
2975
GENL_DONT_VALIDATE_DUMP_STRICT,
2976
/* TODO .doit by matching key id? */
2977
.dumpit = nl802154_dump_llsec_key,
2978
.flags = GENL_ADMIN_PERM,
2979
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2980
NL802154_FLAG_NEED_RTNL,
2981
},
2982
{
2983
.cmd = NL802154_CMD_NEW_SEC_KEY,
2984
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2985
.doit = nl802154_add_llsec_key,
2986
.flags = GENL_ADMIN_PERM,
2987
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2988
NL802154_FLAG_NEED_RTNL,
2989
},
2990
{
2991
.cmd = NL802154_CMD_DEL_SEC_KEY,
2992
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2993
.doit = nl802154_del_llsec_key,
2994
.flags = GENL_ADMIN_PERM,
2995
.internal_flags = NL802154_FLAG_NEED_NETDEV |
2996
NL802154_FLAG_NEED_RTNL,
2997
},
2998
/* TODO unique identifier must short+pan OR extended_addr */
2999
{
3000
.cmd = NL802154_CMD_GET_SEC_DEV,
3001
.validate = GENL_DONT_VALIDATE_STRICT |
3002
GENL_DONT_VALIDATE_DUMP_STRICT,
3003
/* TODO .doit by matching extended_addr? */
3004
.dumpit = nl802154_dump_llsec_dev,
3005
.flags = GENL_ADMIN_PERM,
3006
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3007
NL802154_FLAG_NEED_RTNL,
3008
},
3009
{
3010
.cmd = NL802154_CMD_NEW_SEC_DEV,
3011
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3012
.doit = nl802154_add_llsec_dev,
3013
.flags = GENL_ADMIN_PERM,
3014
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3015
NL802154_FLAG_NEED_RTNL,
3016
},
3017
{
3018
.cmd = NL802154_CMD_DEL_SEC_DEV,
3019
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3020
.doit = nl802154_del_llsec_dev,
3021
.flags = GENL_ADMIN_PERM,
3022
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3023
NL802154_FLAG_NEED_RTNL,
3024
},
3025
/* TODO remove complete devkey, put it as nested? */
3026
{
3027
.cmd = NL802154_CMD_GET_SEC_DEVKEY,
3028
.validate = GENL_DONT_VALIDATE_STRICT |
3029
GENL_DONT_VALIDATE_DUMP_STRICT,
3030
/* TODO doit by matching ??? */
3031
.dumpit = nl802154_dump_llsec_devkey,
3032
.flags = GENL_ADMIN_PERM,
3033
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3034
NL802154_FLAG_NEED_RTNL,
3035
},
3036
{
3037
.cmd = NL802154_CMD_NEW_SEC_DEVKEY,
3038
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3039
.doit = nl802154_add_llsec_devkey,
3040
.flags = GENL_ADMIN_PERM,
3041
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3042
NL802154_FLAG_NEED_RTNL,
3043
},
3044
{
3045
.cmd = NL802154_CMD_DEL_SEC_DEVKEY,
3046
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3047
.doit = nl802154_del_llsec_devkey,
3048
.flags = GENL_ADMIN_PERM,
3049
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3050
NL802154_FLAG_NEED_RTNL,
3051
},
3052
{
3053
.cmd = NL802154_CMD_GET_SEC_LEVEL,
3054
.validate = GENL_DONT_VALIDATE_STRICT |
3055
GENL_DONT_VALIDATE_DUMP_STRICT,
3056
/* TODO .doit by matching frame_type? */
3057
.dumpit = nl802154_dump_llsec_seclevel,
3058
.flags = GENL_ADMIN_PERM,
3059
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3060
NL802154_FLAG_NEED_RTNL,
3061
},
3062
{
3063
.cmd = NL802154_CMD_NEW_SEC_LEVEL,
3064
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3065
.doit = nl802154_add_llsec_seclevel,
3066
.flags = GENL_ADMIN_PERM,
3067
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3068
NL802154_FLAG_NEED_RTNL,
3069
},
3070
{
3071
.cmd = NL802154_CMD_DEL_SEC_LEVEL,
3072
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3073
/* TODO match frame_type only? */
3074
.doit = nl802154_del_llsec_seclevel,
3075
.flags = GENL_ADMIN_PERM,
3076
.internal_flags = NL802154_FLAG_NEED_NETDEV |
3077
NL802154_FLAG_NEED_RTNL,
3078
},
3079
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
3080
};
3081
3082
static struct genl_family nl802154_fam __ro_after_init = {
3083
.name = NL802154_GENL_NAME, /* have users key off the name instead */
3084
.hdrsize = 0, /* no private header */
3085
.version = 1, /* no particular meaning now */
3086
.maxattr = NL802154_ATTR_MAX,
3087
.policy = nl802154_policy,
3088
.netnsok = true,
3089
.pre_doit = nl802154_pre_doit,
3090
.post_doit = nl802154_post_doit,
3091
.module = THIS_MODULE,
3092
.ops = nl802154_ops,
3093
.n_ops = ARRAY_SIZE(nl802154_ops),
3094
.resv_start_op = NL802154_CMD_DEL_SEC_LEVEL + 1,
3095
.mcgrps = nl802154_mcgrps,
3096
.n_mcgrps = ARRAY_SIZE(nl802154_mcgrps),
3097
};
3098
3099
/* initialisation/exit functions */
3100
int __init nl802154_init(void)
3101
{
3102
return genl_register_family(&nl802154_fam);
3103
}
3104
3105
void nl802154_exit(void)
3106
{
3107
genl_unregister_family(&nl802154_fam);
3108
}
3109
3110