1 /* This program is free software; you can redistribute it and/or modify 2 * it under the terms of the GNU General Public License version 2 3 * as published by the Free Software Foundation. 4 * 5 * This program is distributed in the hope that it will be useful, 6 * but WITHOUT ANY WARRANTY; without even the implied warranty of 7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8 * GNU General Public License for more details. 9 * 10 * Authors: 11 * Alexander Aring <aar@pengutronix.de> 12 * 13 * Based on: net/wireless/nl80211.c 14 */ 15 16 #include <linux/rtnetlink.h> 17 18 #include <net/cfg802154.h> 19 #include <net/genetlink.h> 20 #include <net/mac802154.h> 21 #include <net/netlink.h> 22 #include <net/nl802154.h> 23 #include <net/sock.h> 24 25 #include "nl802154.h" 26 #include "rdev-ops.h" 27 #include "core.h" 28 29 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 30 struct genl_info *info); 31 32 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 33 struct genl_info *info); 34 35 /* the netlink family */ 36 static struct genl_family nl802154_fam = { 37 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ 38 .name = NL802154_GENL_NAME, /* have users key off the name instead */ 39 .hdrsize = 0, /* no private header */ 40 .version = 1, /* no particular meaning now */ 41 .maxattr = NL802154_ATTR_MAX, 42 .netnsok = true, 43 .pre_doit = nl802154_pre_doit, 44 .post_doit = nl802154_post_doit, 45 }; 46 47 /* multicast groups */ 48 enum nl802154_multicast_groups { 49 NL802154_MCGRP_CONFIG, 50 }; 51 52 static const struct genl_multicast_group nl802154_mcgrps[] = { 53 [NL802154_MCGRP_CONFIG] = { .name = "config", }, 54 }; 55 56 /* returns ERR_PTR values */ 57 static struct wpan_dev * 58 __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs) 59 { 60 struct cfg802154_registered_device *rdev; 61 struct wpan_dev *result = NULL; 62 bool have_ifidx = attrs[NL802154_ATTR_IFINDEX]; 63 bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV]; 64 u64 wpan_dev_id; 65 int wpan_phy_idx = -1; 66 int ifidx = -1; 67 68 ASSERT_RTNL(); 69 70 if (!have_ifidx && !have_wpan_dev_id) 71 return ERR_PTR(-EINVAL); 72 73 if (have_ifidx) 74 ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]); 75 if (have_wpan_dev_id) { 76 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]); 77 wpan_phy_idx = wpan_dev_id >> 32; 78 } 79 80 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 81 struct wpan_dev *wpan_dev; 82 83 /* TODO netns compare */ 84 85 if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx) 86 continue; 87 88 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { 89 if (have_ifidx && wpan_dev->netdev && 90 wpan_dev->netdev->ifindex == ifidx) { 91 result = wpan_dev; 92 break; 93 } 94 if (have_wpan_dev_id && 95 wpan_dev->identifier == (u32)wpan_dev_id) { 96 result = wpan_dev; 97 break; 98 } 99 } 100 101 if (result) 102 break; 103 } 104 105 if (result) 106 return result; 107 108 return ERR_PTR(-ENODEV); 109 } 110 111 static struct cfg802154_registered_device * 112 __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs) 113 { 114 struct cfg802154_registered_device *rdev = NULL, *tmp; 115 struct net_device *netdev; 116 117 ASSERT_RTNL(); 118 119 if (!attrs[NL802154_ATTR_WPAN_PHY] && 120 !attrs[NL802154_ATTR_IFINDEX] && 121 !attrs[NL802154_ATTR_WPAN_DEV]) 122 return ERR_PTR(-EINVAL); 123 124 if (attrs[NL802154_ATTR_WPAN_PHY]) 125 rdev = cfg802154_rdev_by_wpan_phy_idx( 126 nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY])); 127 128 if (attrs[NL802154_ATTR_WPAN_DEV]) { 129 u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]); 130 struct wpan_dev *wpan_dev; 131 bool found = false; 132 133 tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32); 134 if (tmp) { 135 /* make sure wpan_dev exists */ 136 list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) { 137 if (wpan_dev->identifier != (u32)wpan_dev_id) 138 continue; 139 found = true; 140 break; 141 } 142 143 if (!found) 144 tmp = NULL; 145 146 if (rdev && tmp != rdev) 147 return ERR_PTR(-EINVAL); 148 rdev = tmp; 149 } 150 } 151 152 if (attrs[NL802154_ATTR_IFINDEX]) { 153 int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]); 154 155 netdev = __dev_get_by_index(netns, ifindex); 156 if (netdev) { 157 if (netdev->ieee802154_ptr) 158 tmp = wpan_phy_to_rdev( 159 netdev->ieee802154_ptr->wpan_phy); 160 else 161 tmp = NULL; 162 163 /* not wireless device -- return error */ 164 if (!tmp) 165 return ERR_PTR(-EINVAL); 166 167 /* mismatch -- return error */ 168 if (rdev && tmp != rdev) 169 return ERR_PTR(-EINVAL); 170 171 rdev = tmp; 172 } 173 } 174 175 if (!rdev) 176 return ERR_PTR(-ENODEV); 177 178 /* TODO netns compare */ 179 180 return rdev; 181 } 182 183 /* This function returns a pointer to the driver 184 * that the genl_info item that is passed refers to. 185 * 186 * The result of this can be a PTR_ERR and hence must 187 * be checked with IS_ERR() for errors. 188 */ 189 static struct cfg802154_registered_device * 190 cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info) 191 { 192 return __cfg802154_rdev_from_attrs(netns, info->attrs); 193 } 194 195 /* policy for the attributes */ 196 static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = { 197 [NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 }, 198 [NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING, 199 .len = 20-1 }, 200 201 [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 }, 202 [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 }, 203 [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, 204 205 [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 }, 206 207 [NL802154_ATTR_PAGE] = { .type = NLA_U8, }, 208 [NL802154_ATTR_CHANNEL] = { .type = NLA_U8, }, 209 210 [NL802154_ATTR_TX_POWER] = { .type = NLA_S32, }, 211 212 [NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, }, 213 [NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, }, 214 [NL802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, }, 215 216 [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, }, 217 218 [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, }, 219 [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, 220 [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, 221 222 [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, }, 223 [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, }, 224 [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, }, 225 226 [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, }, 227 228 [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, }, 229 230 [NL802154_ATTR_WPAN_PHY_CAPS] = { .type = NLA_NESTED }, 231 232 [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED }, 233 234 [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 }, 235 236 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 237 [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, }, 238 [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, }, 239 [NL802154_ATTR_SEC_OUT_KEY_ID] = { .type = NLA_NESTED, }, 240 [NL802154_ATTR_SEC_FRAME_COUNTER] = { .type = NLA_U32 }, 241 242 [NL802154_ATTR_SEC_LEVEL] = { .type = NLA_NESTED }, 243 [NL802154_ATTR_SEC_DEVICE] = { .type = NLA_NESTED }, 244 [NL802154_ATTR_SEC_DEVKEY] = { .type = NLA_NESTED }, 245 [NL802154_ATTR_SEC_KEY] = { .type = NLA_NESTED }, 246 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 247 }; 248 249 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 250 static int 251 nl802154_prepare_wpan_dev_dump(struct sk_buff *skb, 252 struct netlink_callback *cb, 253 struct cfg802154_registered_device **rdev, 254 struct wpan_dev **wpan_dev) 255 { 256 int err; 257 258 rtnl_lock(); 259 260 if (!cb->args[0]) { 261 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize, 262 nl802154_fam.attrbuf, nl802154_fam.maxattr, 263 nl802154_policy); 264 if (err) 265 goto out_unlock; 266 267 *wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk), 268 nl802154_fam.attrbuf); 269 if (IS_ERR(*wpan_dev)) { 270 err = PTR_ERR(*wpan_dev); 271 goto out_unlock; 272 } 273 *rdev = wpan_phy_to_rdev((*wpan_dev)->wpan_phy); 274 /* 0 is the first index - add 1 to parse only once */ 275 cb->args[0] = (*rdev)->wpan_phy_idx + 1; 276 cb->args[1] = (*wpan_dev)->identifier; 277 } else { 278 /* subtract the 1 again here */ 279 struct wpan_phy *wpan_phy = wpan_phy_idx_to_wpan_phy(cb->args[0] - 1); 280 struct wpan_dev *tmp; 281 282 if (!wpan_phy) { 283 err = -ENODEV; 284 goto out_unlock; 285 } 286 *rdev = wpan_phy_to_rdev(wpan_phy); 287 *wpan_dev = NULL; 288 289 list_for_each_entry(tmp, &(*rdev)->wpan_dev_list, list) { 290 if (tmp->identifier == cb->args[1]) { 291 *wpan_dev = tmp; 292 break; 293 } 294 } 295 296 if (!*wpan_dev) { 297 err = -ENODEV; 298 goto out_unlock; 299 } 300 } 301 302 return 0; 303 out_unlock: 304 rtnl_unlock(); 305 return err; 306 } 307 308 static void 309 nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev) 310 { 311 rtnl_unlock(); 312 } 313 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 314 315 /* message building helper */ 316 static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq, 317 int flags, u8 cmd) 318 { 319 /* since there is no private header just add the generic one */ 320 return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd); 321 } 322 323 static int 324 nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask) 325 { 326 struct nlattr *nl_flags = nla_nest_start(msg, attr); 327 int i; 328 329 if (!nl_flags) 330 return -ENOBUFS; 331 332 i = 0; 333 while (mask) { 334 if ((mask & 1) && nla_put_flag(msg, i)) 335 return -ENOBUFS; 336 337 mask >>= 1; 338 i++; 339 } 340 341 nla_nest_end(msg, nl_flags); 342 return 0; 343 } 344 345 static int 346 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev, 347 struct sk_buff *msg) 348 { 349 struct nlattr *nl_page; 350 unsigned long page; 351 352 nl_page = nla_nest_start(msg, NL802154_ATTR_CHANNELS_SUPPORTED); 353 if (!nl_page) 354 return -ENOBUFS; 355 356 for (page = 0; page <= IEEE802154_MAX_PAGE; page++) { 357 if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL, 358 rdev->wpan_phy.supported.channels[page])) 359 return -ENOBUFS; 360 } 361 nla_nest_end(msg, nl_page); 362 363 return 0; 364 } 365 366 static int 367 nl802154_put_capabilities(struct sk_buff *msg, 368 struct cfg802154_registered_device *rdev) 369 { 370 const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported; 371 struct nlattr *nl_caps, *nl_channels; 372 int i; 373 374 nl_caps = nla_nest_start(msg, NL802154_ATTR_WPAN_PHY_CAPS); 375 if (!nl_caps) 376 return -ENOBUFS; 377 378 nl_channels = nla_nest_start(msg, NL802154_CAP_ATTR_CHANNELS); 379 if (!nl_channels) 380 return -ENOBUFS; 381 382 for (i = 0; i <= IEEE802154_MAX_PAGE; i++) { 383 if (caps->channels[i]) { 384 if (nl802154_put_flags(msg, i, caps->channels[i])) 385 return -ENOBUFS; 386 } 387 } 388 389 nla_nest_end(msg, nl_channels); 390 391 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) { 392 struct nlattr *nl_ed_lvls; 393 394 nl_ed_lvls = nla_nest_start(msg, 395 NL802154_CAP_ATTR_CCA_ED_LEVELS); 396 if (!nl_ed_lvls) 397 return -ENOBUFS; 398 399 for (i = 0; i < caps->cca_ed_levels_size; i++) { 400 if (nla_put_s32(msg, i, caps->cca_ed_levels[i])) 401 return -ENOBUFS; 402 } 403 404 nla_nest_end(msg, nl_ed_lvls); 405 } 406 407 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) { 408 struct nlattr *nl_tx_pwrs; 409 410 nl_tx_pwrs = nla_nest_start(msg, NL802154_CAP_ATTR_TX_POWERS); 411 if (!nl_tx_pwrs) 412 return -ENOBUFS; 413 414 for (i = 0; i < caps->tx_powers_size; i++) { 415 if (nla_put_s32(msg, i, caps->tx_powers[i])) 416 return -ENOBUFS; 417 } 418 419 nla_nest_end(msg, nl_tx_pwrs); 420 } 421 422 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) { 423 if (nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_MODES, 424 caps->cca_modes) || 425 nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_OPTS, 426 caps->cca_opts)) 427 return -ENOBUFS; 428 } 429 430 if (nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MINBE, caps->min_minbe) || 431 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MINBE, caps->max_minbe) || 432 nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MAXBE, caps->min_maxbe) || 433 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MAXBE, caps->max_maxbe) || 434 nla_put_u8(msg, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS, 435 caps->min_csma_backoffs) || 436 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS, 437 caps->max_csma_backoffs) || 438 nla_put_s8(msg, NL802154_CAP_ATTR_MIN_FRAME_RETRIES, 439 caps->min_frame_retries) || 440 nla_put_s8(msg, NL802154_CAP_ATTR_MAX_FRAME_RETRIES, 441 caps->max_frame_retries) || 442 nl802154_put_flags(msg, NL802154_CAP_ATTR_IFTYPES, 443 caps->iftypes) || 444 nla_put_u32(msg, NL802154_CAP_ATTR_LBT, caps->lbt)) 445 return -ENOBUFS; 446 447 nla_nest_end(msg, nl_caps); 448 449 return 0; 450 } 451 452 static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev, 453 enum nl802154_commands cmd, 454 struct sk_buff *msg, u32 portid, u32 seq, 455 int flags) 456 { 457 struct nlattr *nl_cmds; 458 void *hdr; 459 int i; 460 461 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 462 if (!hdr) 463 return -ENOBUFS; 464 465 if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || 466 nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME, 467 wpan_phy_name(&rdev->wpan_phy)) || 468 nla_put_u32(msg, NL802154_ATTR_GENERATION, 469 cfg802154_rdev_list_generation)) 470 goto nla_put_failure; 471 472 if (cmd != NL802154_CMD_NEW_WPAN_PHY) 473 goto finish; 474 475 /* DUMP PHY PIB */ 476 477 /* current channel settings */ 478 if (nla_put_u8(msg, NL802154_ATTR_PAGE, 479 rdev->wpan_phy.current_page) || 480 nla_put_u8(msg, NL802154_ATTR_CHANNEL, 481 rdev->wpan_phy.current_channel)) 482 goto nla_put_failure; 483 484 /* TODO remove this behaviour, we still keep support it for a while 485 * so users can change the behaviour to the new one. 486 */ 487 if (nl802154_send_wpan_phy_channels(rdev, msg)) 488 goto nla_put_failure; 489 490 /* cca mode */ 491 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) { 492 if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE, 493 rdev->wpan_phy.cca.mode)) 494 goto nla_put_failure; 495 496 if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) { 497 if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT, 498 rdev->wpan_phy.cca.opt)) 499 goto nla_put_failure; 500 } 501 } 502 503 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) { 504 if (nla_put_s32(msg, NL802154_ATTR_TX_POWER, 505 rdev->wpan_phy.transmit_power)) 506 goto nla_put_failure; 507 } 508 509 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) { 510 if (nla_put_s32(msg, NL802154_ATTR_CCA_ED_LEVEL, 511 rdev->wpan_phy.cca_ed_level)) 512 goto nla_put_failure; 513 } 514 515 if (nl802154_put_capabilities(msg, rdev)) 516 goto nla_put_failure; 517 518 nl_cmds = nla_nest_start(msg, NL802154_ATTR_SUPPORTED_COMMANDS); 519 if (!nl_cmds) 520 goto nla_put_failure; 521 522 i = 0; 523 #define CMD(op, n) \ 524 do { \ 525 if (rdev->ops->op) { \ 526 i++; \ 527 if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \ 528 goto nla_put_failure; \ 529 } \ 530 } while (0) 531 532 CMD(add_virtual_intf, NEW_INTERFACE); 533 CMD(del_virtual_intf, DEL_INTERFACE); 534 CMD(set_channel, SET_CHANNEL); 535 CMD(set_pan_id, SET_PAN_ID); 536 CMD(set_short_addr, SET_SHORT_ADDR); 537 CMD(set_backoff_exponent, SET_BACKOFF_EXPONENT); 538 CMD(set_max_csma_backoffs, SET_MAX_CSMA_BACKOFFS); 539 CMD(set_max_frame_retries, SET_MAX_FRAME_RETRIES); 540 CMD(set_lbt_mode, SET_LBT_MODE); 541 CMD(set_ackreq_default, SET_ACKREQ_DEFAULT); 542 543 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) 544 CMD(set_tx_power, SET_TX_POWER); 545 546 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) 547 CMD(set_cca_ed_level, SET_CCA_ED_LEVEL); 548 549 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) 550 CMD(set_cca_mode, SET_CCA_MODE); 551 552 #undef CMD 553 nla_nest_end(msg, nl_cmds); 554 555 finish: 556 genlmsg_end(msg, hdr); 557 return 0; 558 559 nla_put_failure: 560 genlmsg_cancel(msg, hdr); 561 return -EMSGSIZE; 562 } 563 564 struct nl802154_dump_wpan_phy_state { 565 s64 filter_wpan_phy; 566 long start; 567 568 }; 569 570 static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb, 571 struct netlink_callback *cb, 572 struct nl802154_dump_wpan_phy_state *state) 573 { 574 struct nlattr **tb = nl802154_fam.attrbuf; 575 int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize, 576 tb, nl802154_fam.maxattr, nl802154_policy); 577 578 /* TODO check if we can handle error here, 579 * we have no backward compatibility 580 */ 581 if (ret) 582 return 0; 583 584 if (tb[NL802154_ATTR_WPAN_PHY]) 585 state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]); 586 if (tb[NL802154_ATTR_WPAN_DEV]) 587 state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32; 588 if (tb[NL802154_ATTR_IFINDEX]) { 589 struct net_device *netdev; 590 struct cfg802154_registered_device *rdev; 591 int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]); 592 593 /* TODO netns */ 594 netdev = __dev_get_by_index(&init_net, ifidx); 595 if (!netdev) 596 return -ENODEV; 597 if (netdev->ieee802154_ptr) { 598 rdev = wpan_phy_to_rdev( 599 netdev->ieee802154_ptr->wpan_phy); 600 state->filter_wpan_phy = rdev->wpan_phy_idx; 601 } 602 } 603 604 return 0; 605 } 606 607 static int 608 nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb) 609 { 610 int idx = 0, ret; 611 struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0]; 612 struct cfg802154_registered_device *rdev; 613 614 rtnl_lock(); 615 if (!state) { 616 state = kzalloc(sizeof(*state), GFP_KERNEL); 617 if (!state) { 618 rtnl_unlock(); 619 return -ENOMEM; 620 } 621 state->filter_wpan_phy = -1; 622 ret = nl802154_dump_wpan_phy_parse(skb, cb, state); 623 if (ret) { 624 kfree(state); 625 rtnl_unlock(); 626 return ret; 627 } 628 cb->args[0] = (long)state; 629 } 630 631 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 632 /* TODO net ns compare */ 633 if (++idx <= state->start) 634 continue; 635 if (state->filter_wpan_phy != -1 && 636 state->filter_wpan_phy != rdev->wpan_phy_idx) 637 continue; 638 /* attempt to fit multiple wpan_phy data chunks into the skb */ 639 ret = nl802154_send_wpan_phy(rdev, 640 NL802154_CMD_NEW_WPAN_PHY, 641 skb, 642 NETLINK_CB(cb->skb).portid, 643 cb->nlh->nlmsg_seq, NLM_F_MULTI); 644 if (ret < 0) { 645 if ((ret == -ENOBUFS || ret == -EMSGSIZE) && 646 !skb->len && cb->min_dump_alloc < 4096) { 647 cb->min_dump_alloc = 4096; 648 rtnl_unlock(); 649 return 1; 650 } 651 idx--; 652 break; 653 } 654 break; 655 } 656 rtnl_unlock(); 657 658 state->start = idx; 659 660 return skb->len; 661 } 662 663 static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb) 664 { 665 kfree((void *)cb->args[0]); 666 return 0; 667 } 668 669 static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info) 670 { 671 struct sk_buff *msg; 672 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 673 674 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 675 if (!msg) 676 return -ENOMEM; 677 678 if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg, 679 info->snd_portid, info->snd_seq, 0) < 0) { 680 nlmsg_free(msg); 681 return -ENOBUFS; 682 } 683 684 return genlmsg_reply(msg, info); 685 } 686 687 static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev) 688 { 689 return (u64)wpan_dev->identifier | 690 ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32); 691 } 692 693 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 694 #include <net/ieee802154_netdev.h> 695 696 static int 697 ieee802154_llsec_send_key_id(struct sk_buff *msg, 698 const struct ieee802154_llsec_key_id *desc) 699 { 700 struct nlattr *nl_dev_addr; 701 702 if (nla_put_u32(msg, NL802154_KEY_ID_ATTR_MODE, desc->mode)) 703 return -ENOBUFS; 704 705 switch (desc->mode) { 706 case NL802154_KEY_ID_MODE_IMPLICIT: 707 nl_dev_addr = nla_nest_start(msg, NL802154_KEY_ID_ATTR_IMPLICIT); 708 if (!nl_dev_addr) 709 return -ENOBUFS; 710 711 if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_PAN_ID, 712 desc->device_addr.pan_id) || 713 nla_put_u32(msg, NL802154_DEV_ADDR_ATTR_MODE, 714 desc->device_addr.mode)) 715 return -ENOBUFS; 716 717 switch (desc->device_addr.mode) { 718 case NL802154_DEV_ADDR_SHORT: 719 if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_SHORT, 720 desc->device_addr.short_addr)) 721 return -ENOBUFS; 722 break; 723 case NL802154_DEV_ADDR_EXTENDED: 724 if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED, 725 desc->device_addr.extended_addr)) 726 return -ENOBUFS; 727 break; 728 default: 729 /* userspace should handle unknown */ 730 break; 731 } 732 733 nla_nest_end(msg, nl_dev_addr); 734 break; 735 case NL802154_KEY_ID_MODE_INDEX: 736 break; 737 case NL802154_KEY_ID_MODE_INDEX_SHORT: 738 /* TODO renmae short_source? */ 739 if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT, 740 desc->short_source)) 741 return -ENOBUFS; 742 break; 743 case NL802154_KEY_ID_MODE_INDEX_EXTENDED: 744 if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, 745 desc->extended_source)) 746 return -ENOBUFS; 747 break; 748 default: 749 /* userspace should handle unknown */ 750 break; 751 } 752 753 /* TODO key_id to key_idx ? Check naming */ 754 if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { 755 if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id)) 756 return -ENOBUFS; 757 } 758 759 return 0; 760 } 761 762 static int nl802154_get_llsec_params(struct sk_buff *msg, 763 struct cfg802154_registered_device *rdev, 764 struct wpan_dev *wpan_dev) 765 { 766 struct nlattr *nl_key_id; 767 struct ieee802154_llsec_params params; 768 int ret; 769 770 ret = rdev_get_llsec_params(rdev, wpan_dev, ¶ms); 771 if (ret < 0) 772 return ret; 773 774 if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) || 775 nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) || 776 nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER, 777 params.frame_counter)) 778 return -ENOBUFS; 779 780 nl_key_id = nla_nest_start(msg, NL802154_ATTR_SEC_OUT_KEY_ID); 781 if (!nl_key_id) 782 return -ENOBUFS; 783 784 ret = ieee802154_llsec_send_key_id(msg, ¶ms.out_key); 785 if (ret < 0) 786 return ret; 787 788 nla_nest_end(msg, nl_key_id); 789 790 return 0; 791 } 792 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 793 794 static int 795 nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, 796 struct cfg802154_registered_device *rdev, 797 struct wpan_dev *wpan_dev) 798 { 799 struct net_device *dev = wpan_dev->netdev; 800 void *hdr; 801 802 hdr = nl802154hdr_put(msg, portid, seq, flags, 803 NL802154_CMD_NEW_INTERFACE); 804 if (!hdr) 805 return -1; 806 807 if (dev && 808 (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) || 809 nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name))) 810 goto nla_put_failure; 811 812 if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || 813 nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) || 814 nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) || 815 nla_put_u32(msg, NL802154_ATTR_GENERATION, 816 rdev->devlist_generation ^ 817 (cfg802154_rdev_list_generation << 2))) 818 goto nla_put_failure; 819 820 /* address settings */ 821 if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR, 822 wpan_dev->extended_addr) || 823 nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR, 824 wpan_dev->short_addr) || 825 nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id)) 826 goto nla_put_failure; 827 828 /* ARET handling */ 829 if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES, 830 wpan_dev->frame_retries) || 831 nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) || 832 nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS, 833 wpan_dev->csma_retries) || 834 nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be)) 835 goto nla_put_failure; 836 837 /* listen before transmit */ 838 if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt)) 839 goto nla_put_failure; 840 841 /* ackreq default behaviour */ 842 if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq)) 843 goto nla_put_failure; 844 845 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 846 if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) 847 goto nla_put_failure; 848 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 849 850 genlmsg_end(msg, hdr); 851 return 0; 852 853 nla_put_failure: 854 genlmsg_cancel(msg, hdr); 855 return -EMSGSIZE; 856 } 857 858 static int 859 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) 860 { 861 int wp_idx = 0; 862 int if_idx = 0; 863 int wp_start = cb->args[0]; 864 int if_start = cb->args[1]; 865 struct cfg802154_registered_device *rdev; 866 struct wpan_dev *wpan_dev; 867 868 rtnl_lock(); 869 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 870 /* TODO netns compare */ 871 if (wp_idx < wp_start) { 872 wp_idx++; 873 continue; 874 } 875 if_idx = 0; 876 877 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { 878 if (if_idx < if_start) { 879 if_idx++; 880 continue; 881 } 882 if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid, 883 cb->nlh->nlmsg_seq, NLM_F_MULTI, 884 rdev, wpan_dev) < 0) { 885 goto out; 886 } 887 if_idx++; 888 } 889 890 wp_idx++; 891 } 892 out: 893 rtnl_unlock(); 894 895 cb->args[0] = wp_idx; 896 cb->args[1] = if_idx; 897 898 return skb->len; 899 } 900 901 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info) 902 { 903 struct sk_buff *msg; 904 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 905 struct wpan_dev *wdev = info->user_ptr[1]; 906 907 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 908 if (!msg) 909 return -ENOMEM; 910 911 if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0, 912 rdev, wdev) < 0) { 913 nlmsg_free(msg); 914 return -ENOBUFS; 915 } 916 917 return genlmsg_reply(msg, info); 918 } 919 920 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) 921 { 922 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 923 enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC; 924 __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL); 925 926 /* TODO avoid failing a new interface 927 * creation due to pending removal? 928 */ 929 930 if (!info->attrs[NL802154_ATTR_IFNAME]) 931 return -EINVAL; 932 933 if (info->attrs[NL802154_ATTR_IFTYPE]) { 934 type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]); 935 if (type > NL802154_IFTYPE_MAX || 936 !(rdev->wpan_phy.supported.iftypes & BIT(type))) 937 return -EINVAL; 938 } 939 940 if (info->attrs[NL802154_ATTR_EXTENDED_ADDR]) 941 extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]); 942 943 if (!rdev->ops->add_virtual_intf) 944 return -EOPNOTSUPP; 945 946 return rdev_add_virtual_intf(rdev, 947 nla_data(info->attrs[NL802154_ATTR_IFNAME]), 948 NET_NAME_USER, type, extended_addr); 949 } 950 951 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) 952 { 953 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 954 struct wpan_dev *wpan_dev = info->user_ptr[1]; 955 956 if (!rdev->ops->del_virtual_intf) 957 return -EOPNOTSUPP; 958 959 /* If we remove a wpan device without a netdev then clear 960 * user_ptr[1] so that nl802154_post_doit won't dereference it 961 * to check if it needs to do dev_put(). Otherwise it crashes 962 * since the wpan_dev has been freed, unlike with a netdev where 963 * we need the dev_put() for the netdev to really be freed. 964 */ 965 if (!wpan_dev->netdev) 966 info->user_ptr[1] = NULL; 967 968 return rdev_del_virtual_intf(rdev, wpan_dev); 969 } 970 971 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info) 972 { 973 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 974 u8 channel, page; 975 976 if (!info->attrs[NL802154_ATTR_PAGE] || 977 !info->attrs[NL802154_ATTR_CHANNEL]) 978 return -EINVAL; 979 980 page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]); 981 channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]); 982 983 /* check 802.15.4 constraints */ 984 if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL || 985 !(rdev->wpan_phy.supported.channels[page] & BIT(channel))) 986 return -EINVAL; 987 988 return rdev_set_channel(rdev, page, channel); 989 } 990 991 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info) 992 { 993 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 994 struct wpan_phy_cca cca; 995 996 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)) 997 return -EOPNOTSUPP; 998 999 if (!info->attrs[NL802154_ATTR_CCA_MODE]) 1000 return -EINVAL; 1001 1002 cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]); 1003 /* checking 802.15.4 constraints */ 1004 if (cca.mode < NL802154_CCA_ENERGY || 1005 cca.mode > NL802154_CCA_ATTR_MAX || 1006 !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode))) 1007 return -EINVAL; 1008 1009 if (cca.mode == NL802154_CCA_ENERGY_CARRIER) { 1010 if (!info->attrs[NL802154_ATTR_CCA_OPT]) 1011 return -EINVAL; 1012 1013 cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]); 1014 if (cca.opt > NL802154_CCA_OPT_ATTR_MAX || 1015 !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt))) 1016 return -EINVAL; 1017 } 1018 1019 return rdev_set_cca_mode(rdev, &cca); 1020 } 1021 1022 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info) 1023 { 1024 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1025 s32 ed_level; 1026 int i; 1027 1028 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)) 1029 return -EOPNOTSUPP; 1030 1031 if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL]) 1032 return -EINVAL; 1033 1034 ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]); 1035 1036 for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) { 1037 if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i]) 1038 return rdev_set_cca_ed_level(rdev, ed_level); 1039 } 1040 1041 return -EINVAL; 1042 } 1043 1044 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info) 1045 { 1046 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1047 s32 power; 1048 int i; 1049 1050 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)) 1051 return -EOPNOTSUPP; 1052 1053 if (!info->attrs[NL802154_ATTR_TX_POWER]) 1054 return -EINVAL; 1055 1056 power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]); 1057 1058 for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) { 1059 if (power == rdev->wpan_phy.supported.tx_powers[i]) 1060 return rdev_set_tx_power(rdev, power); 1061 } 1062 1063 return -EINVAL; 1064 } 1065 1066 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info) 1067 { 1068 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1069 struct net_device *dev = info->user_ptr[1]; 1070 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1071 __le16 pan_id; 1072 1073 /* conflict here while tx/rx calls */ 1074 if (netif_running(dev)) 1075 return -EBUSY; 1076 1077 /* don't change address fields on monitor */ 1078 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 1079 !info->attrs[NL802154_ATTR_PAN_ID]) 1080 return -EINVAL; 1081 1082 pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]); 1083 1084 /* TODO 1085 * I am not sure about to check here on broadcast pan_id. 1086 * Broadcast is a valid setting, comment from 802.15.4: 1087 * If this value is 0xffff, the device is not associated. 1088 * 1089 * This could useful to simple deassociate an device. 1090 */ 1091 if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST)) 1092 return -EINVAL; 1093 1094 return rdev_set_pan_id(rdev, wpan_dev, pan_id); 1095 } 1096 1097 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info) 1098 { 1099 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1100 struct net_device *dev = info->user_ptr[1]; 1101 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1102 __le16 short_addr; 1103 1104 /* conflict here while tx/rx calls */ 1105 if (netif_running(dev)) 1106 return -EBUSY; 1107 1108 /* don't change address fields on monitor */ 1109 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 1110 !info->attrs[NL802154_ATTR_SHORT_ADDR]) 1111 return -EINVAL; 1112 1113 short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]); 1114 1115 /* TODO 1116 * I am not sure about to check here on broadcast short_addr. 1117 * Broadcast is a valid setting, comment from 802.15.4: 1118 * A value of 0xfffe indicates that the device has 1119 * associated but has not been allocated an address. A 1120 * value of 0xffff indicates that the device does not 1121 * have a short address. 1122 * 1123 * I think we should allow to set these settings but 1124 * don't allow to allow socket communication with it. 1125 */ 1126 if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) || 1127 short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST)) 1128 return -EINVAL; 1129 1130 return rdev_set_short_addr(rdev, wpan_dev, short_addr); 1131 } 1132 1133 static int 1134 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info) 1135 { 1136 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1137 struct net_device *dev = info->user_ptr[1]; 1138 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1139 u8 min_be, max_be; 1140 1141 /* should be set on netif open inside phy settings */ 1142 if (netif_running(dev)) 1143 return -EBUSY; 1144 1145 if (!info->attrs[NL802154_ATTR_MIN_BE] || 1146 !info->attrs[NL802154_ATTR_MAX_BE]) 1147 return -EINVAL; 1148 1149 min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]); 1150 max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]); 1151 1152 /* check 802.15.4 constraints */ 1153 if (min_be < rdev->wpan_phy.supported.min_minbe || 1154 min_be > rdev->wpan_phy.supported.max_minbe || 1155 max_be < rdev->wpan_phy.supported.min_maxbe || 1156 max_be > rdev->wpan_phy.supported.max_maxbe || 1157 min_be > max_be) 1158 return -EINVAL; 1159 1160 return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be); 1161 } 1162 1163 static int 1164 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info) 1165 { 1166 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1167 struct net_device *dev = info->user_ptr[1]; 1168 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1169 u8 max_csma_backoffs; 1170 1171 /* conflict here while other running iface settings */ 1172 if (netif_running(dev)) 1173 return -EBUSY; 1174 1175 if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]) 1176 return -EINVAL; 1177 1178 max_csma_backoffs = nla_get_u8( 1179 info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]); 1180 1181 /* check 802.15.4 constraints */ 1182 if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs || 1183 max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs) 1184 return -EINVAL; 1185 1186 return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs); 1187 } 1188 1189 static int 1190 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info) 1191 { 1192 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1193 struct net_device *dev = info->user_ptr[1]; 1194 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1195 s8 max_frame_retries; 1196 1197 if (netif_running(dev)) 1198 return -EBUSY; 1199 1200 if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]) 1201 return -EINVAL; 1202 1203 max_frame_retries = nla_get_s8( 1204 info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]); 1205 1206 /* check 802.15.4 constraints */ 1207 if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries || 1208 max_frame_retries > rdev->wpan_phy.supported.max_frame_retries) 1209 return -EINVAL; 1210 1211 return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries); 1212 } 1213 1214 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info) 1215 { 1216 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1217 struct net_device *dev = info->user_ptr[1]; 1218 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1219 int mode; 1220 1221 if (netif_running(dev)) 1222 return -EBUSY; 1223 1224 if (!info->attrs[NL802154_ATTR_LBT_MODE]) 1225 return -EINVAL; 1226 1227 mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]); 1228 1229 if (mode != 0 && mode != 1) 1230 return -EINVAL; 1231 1232 if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt)) 1233 return -EINVAL; 1234 1235 return rdev_set_lbt_mode(rdev, wpan_dev, mode); 1236 } 1237 1238 static int 1239 nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info) 1240 { 1241 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1242 struct net_device *dev = info->user_ptr[1]; 1243 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1244 int ackreq; 1245 1246 if (netif_running(dev)) 1247 return -EBUSY; 1248 1249 if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]) 1250 return -EINVAL; 1251 1252 ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]); 1253 1254 if (ackreq != 0 && ackreq != 1) 1255 return -EINVAL; 1256 1257 return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); 1258 } 1259 1260 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 1261 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = { 1262 [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 }, 1263 [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 }, 1264 [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 }, 1265 [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 }, 1266 }; 1267 1268 static int 1269 ieee802154_llsec_parse_dev_addr(struct nlattr *nla, 1270 struct ieee802154_addr *addr) 1271 { 1272 struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1]; 1273 1274 if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla, 1275 nl802154_dev_addr_policy)) 1276 return -EINVAL; 1277 1278 if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] && 1279 !attrs[NL802154_DEV_ADDR_ATTR_MODE] && 1280 !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] || 1281 attrs[NL802154_DEV_ADDR_ATTR_EXTENDED])) 1282 return -EINVAL; 1283 1284 addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]); 1285 addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]); 1286 switch (addr->mode) { 1287 case NL802154_DEV_ADDR_SHORT: 1288 addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]); 1289 break; 1290 case NL802154_DEV_ADDR_EXTENDED: 1291 addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]); 1292 break; 1293 default: 1294 return -EINVAL; 1295 } 1296 1297 return 0; 1298 } 1299 1300 static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = { 1301 [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 }, 1302 [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 }, 1303 [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED }, 1304 [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 }, 1305 [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 }, 1306 }; 1307 1308 static int 1309 ieee802154_llsec_parse_key_id(struct nlattr *nla, 1310 struct ieee802154_llsec_key_id *desc) 1311 { 1312 struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1]; 1313 1314 if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla, 1315 nl802154_key_id_policy)) 1316 return -EINVAL; 1317 1318 if (!attrs[NL802154_KEY_ID_ATTR_MODE]) 1319 return -EINVAL; 1320 1321 desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]); 1322 switch (desc->mode) { 1323 case NL802154_KEY_ID_MODE_IMPLICIT: 1324 if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT]) 1325 return -EINVAL; 1326 1327 if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT], 1328 &desc->device_addr) < 0) 1329 return -EINVAL; 1330 break; 1331 case NL802154_KEY_ID_MODE_INDEX: 1332 break; 1333 case NL802154_KEY_ID_MODE_INDEX_SHORT: 1334 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]) 1335 return -EINVAL; 1336 1337 desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]); 1338 break; 1339 case NL802154_KEY_ID_MODE_INDEX_EXTENDED: 1340 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]) 1341 return -EINVAL; 1342 1343 desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]); 1344 break; 1345 default: 1346 return -EINVAL; 1347 } 1348 1349 if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { 1350 if (!attrs[NL802154_KEY_ID_ATTR_INDEX]) 1351 return -EINVAL; 1352 1353 /* TODO change id to idx */ 1354 desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]); 1355 } 1356 1357 return 0; 1358 } 1359 1360 static int nl802154_set_llsec_params(struct sk_buff *skb, 1361 struct genl_info *info) 1362 { 1363 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1364 struct net_device *dev = info->user_ptr[1]; 1365 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1366 struct ieee802154_llsec_params params; 1367 u32 changed = 0; 1368 int ret; 1369 1370 if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { 1371 u8 enabled; 1372 1373 enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); 1374 if (enabled != 0 && enabled != 1) 1375 return -EINVAL; 1376 1377 params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); 1378 changed |= IEEE802154_LLSEC_PARAM_ENABLED; 1379 } 1380 1381 if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) { 1382 ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID], 1383 ¶ms.out_key); 1384 if (ret < 0) 1385 return ret; 1386 1387 changed |= IEEE802154_LLSEC_PARAM_OUT_KEY; 1388 } 1389 1390 if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) { 1391 params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]); 1392 if (params.out_level > NL802154_SECLEVEL_MAX) 1393 return -EINVAL; 1394 1395 changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL; 1396 } 1397 1398 if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) { 1399 params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]); 1400 changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER; 1401 } 1402 1403 return rdev_set_llsec_params(rdev, wpan_dev, ¶ms, changed); 1404 } 1405 1406 static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid, 1407 u32 seq, int flags, 1408 struct cfg802154_registered_device *rdev, 1409 struct net_device *dev, 1410 const struct ieee802154_llsec_key_entry *key) 1411 { 1412 void *hdr; 1413 u32 commands[NL802154_CMD_FRAME_NR_IDS / 32]; 1414 struct nlattr *nl_key, *nl_key_id; 1415 1416 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1417 if (!hdr) 1418 return -1; 1419 1420 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1421 goto nla_put_failure; 1422 1423 nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY); 1424 if (!nl_key) 1425 goto nla_put_failure; 1426 1427 nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID); 1428 if (!nl_key_id) 1429 goto nla_put_failure; 1430 1431 if (ieee802154_llsec_send_key_id(msg, &key->id) < 0) 1432 goto nla_put_failure; 1433 1434 nla_nest_end(msg, nl_key_id); 1435 1436 if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES, 1437 key->key->frame_types)) 1438 goto nla_put_failure; 1439 1440 if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) { 1441 /* TODO for each nested */ 1442 memset(commands, 0, sizeof(commands)); 1443 commands[7] = key->key->cmd_frame_ids; 1444 if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS, 1445 sizeof(commands), commands)) 1446 goto nla_put_failure; 1447 } 1448 1449 if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE, 1450 key->key->key)) 1451 goto nla_put_failure; 1452 1453 nla_nest_end(msg, nl_key); 1454 genlmsg_end(msg, hdr); 1455 1456 return 0; 1457 1458 nla_put_failure: 1459 genlmsg_cancel(msg, hdr); 1460 return -EMSGSIZE; 1461 } 1462 1463 static int 1464 nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb) 1465 { 1466 struct cfg802154_registered_device *rdev = NULL; 1467 struct ieee802154_llsec_key_entry *key; 1468 struct ieee802154_llsec_table *table; 1469 struct wpan_dev *wpan_dev; 1470 int err; 1471 1472 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1473 if (err) 1474 return err; 1475 1476 if (!wpan_dev->netdev) { 1477 err = -EINVAL; 1478 goto out_err; 1479 } 1480 1481 rdev_lock_llsec_table(rdev, wpan_dev); 1482 rdev_get_llsec_table(rdev, wpan_dev, &table); 1483 1484 /* TODO make it like station dump */ 1485 if (cb->args[2]) 1486 goto out; 1487 1488 list_for_each_entry(key, &table->keys, list) { 1489 if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY, 1490 NETLINK_CB(cb->skb).portid, 1491 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1492 rdev, wpan_dev->netdev, key) < 0) { 1493 /* TODO */ 1494 err = -EIO; 1495 rdev_unlock_llsec_table(rdev, wpan_dev); 1496 goto out_err; 1497 } 1498 } 1499 1500 cb->args[2] = 1; 1501 1502 out: 1503 rdev_unlock_llsec_table(rdev, wpan_dev); 1504 err = skb->len; 1505 out_err: 1506 nl802154_finish_wpan_dev_dump(rdev); 1507 1508 return err; 1509 } 1510 1511 static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = { 1512 [NL802154_KEY_ATTR_ID] = { NLA_NESTED }, 1513 /* TODO handle it as for_each_nested and NLA_FLAG? */ 1514 [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 }, 1515 /* TODO handle it as for_each_nested, not static array? */ 1516 [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 }, 1517 [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE }, 1518 }; 1519 1520 static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) 1521 { 1522 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1523 struct net_device *dev = info->user_ptr[1]; 1524 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1525 struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; 1526 struct ieee802154_llsec_key key = { }; 1527 struct ieee802154_llsec_key_id id = { }; 1528 u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; 1529 1530 if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, 1531 info->attrs[NL802154_ATTR_SEC_KEY], 1532 nl802154_key_policy)) 1533 return -EINVAL; 1534 1535 if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] || 1536 !attrs[NL802154_KEY_ATTR_BYTES]) 1537 return -EINVAL; 1538 1539 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1540 return -ENOBUFS; 1541 1542 key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]); 1543 if (key.frame_types > BIT(NL802154_FRAME_MAX) || 1544 ((key.frame_types & BIT(NL802154_FRAME_CMD)) && 1545 !attrs[NL802154_KEY_ATTR_USAGE_CMDS])) 1546 return -EINVAL; 1547 1548 if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) { 1549 /* TODO for each nested */ 1550 nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS], 1551 NL802154_CMD_FRAME_NR_IDS / 8); 1552 1553 /* TODO understand the -EINVAL logic here? last condition */ 1554 if (commands[0] || commands[1] || commands[2] || commands[3] || 1555 commands[4] || commands[5] || commands[6] || 1556 commands[7] > BIT(NL802154_CMD_FRAME_MAX)) 1557 return -EINVAL; 1558 1559 key.cmd_frame_ids = commands[7]; 1560 } else { 1561 key.cmd_frame_ids = 0; 1562 } 1563 1564 nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE); 1565 1566 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1567 return -ENOBUFS; 1568 1569 return rdev_add_llsec_key(rdev, wpan_dev, &id, &key); 1570 } 1571 1572 static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) 1573 { 1574 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1575 struct net_device *dev = info->user_ptr[1]; 1576 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1577 struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; 1578 struct ieee802154_llsec_key_id id; 1579 1580 if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, 1581 info->attrs[NL802154_ATTR_SEC_KEY], 1582 nl802154_key_policy)) 1583 return -EINVAL; 1584 1585 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1586 return -ENOBUFS; 1587 1588 return rdev_del_llsec_key(rdev, wpan_dev, &id); 1589 } 1590 1591 static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid, 1592 u32 seq, int flags, 1593 struct cfg802154_registered_device *rdev, 1594 struct net_device *dev, 1595 const struct ieee802154_llsec_device *dev_desc) 1596 { 1597 void *hdr; 1598 struct nlattr *nl_device; 1599 1600 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1601 if (!hdr) 1602 return -1; 1603 1604 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1605 goto nla_put_failure; 1606 1607 nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE); 1608 if (!nl_device) 1609 goto nla_put_failure; 1610 1611 if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER, 1612 dev_desc->frame_counter) || 1613 nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) || 1614 nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR, 1615 dev_desc->short_addr) || 1616 nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR, 1617 dev_desc->hwaddr) || 1618 nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, 1619 dev_desc->seclevel_exempt) || 1620 nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode)) 1621 goto nla_put_failure; 1622 1623 nla_nest_end(msg, nl_device); 1624 genlmsg_end(msg, hdr); 1625 1626 return 0; 1627 1628 nla_put_failure: 1629 genlmsg_cancel(msg, hdr); 1630 return -EMSGSIZE; 1631 } 1632 1633 static int 1634 nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb) 1635 { 1636 struct cfg802154_registered_device *rdev = NULL; 1637 struct ieee802154_llsec_device *dev; 1638 struct ieee802154_llsec_table *table; 1639 struct wpan_dev *wpan_dev; 1640 int err; 1641 1642 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1643 if (err) 1644 return err; 1645 1646 if (!wpan_dev->netdev) { 1647 err = -EINVAL; 1648 goto out_err; 1649 } 1650 1651 rdev_lock_llsec_table(rdev, wpan_dev); 1652 rdev_get_llsec_table(rdev, wpan_dev, &table); 1653 1654 /* TODO make it like station dump */ 1655 if (cb->args[2]) 1656 goto out; 1657 1658 list_for_each_entry(dev, &table->devices, list) { 1659 if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL, 1660 NETLINK_CB(cb->skb).portid, 1661 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1662 rdev, wpan_dev->netdev, dev) < 0) { 1663 /* TODO */ 1664 err = -EIO; 1665 rdev_unlock_llsec_table(rdev, wpan_dev); 1666 goto out_err; 1667 } 1668 } 1669 1670 cb->args[2] = 1; 1671 1672 out: 1673 rdev_unlock_llsec_table(rdev, wpan_dev); 1674 err = skb->len; 1675 out_err: 1676 nl802154_finish_wpan_dev_dump(rdev); 1677 1678 return err; 1679 } 1680 1681 static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = { 1682 [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 }, 1683 [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 }, 1684 [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 }, 1685 [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, 1686 [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 }, 1687 [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 }, 1688 }; 1689 1690 static int 1691 ieee802154_llsec_parse_device(struct nlattr *nla, 1692 struct ieee802154_llsec_device *dev) 1693 { 1694 struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; 1695 1696 if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla, 1697 nl802154_dev_policy)) 1698 return -EINVAL; 1699 1700 memset(dev, 0, sizeof(*dev)); 1701 1702 if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] || 1703 !attrs[NL802154_DEV_ATTR_PAN_ID] || 1704 !attrs[NL802154_DEV_ATTR_SHORT_ADDR] || 1705 !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] || 1706 !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] || 1707 !attrs[NL802154_DEV_ATTR_KEY_MODE]) 1708 return -EINVAL; 1709 1710 /* TODO be32 */ 1711 dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]); 1712 dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]); 1713 dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]); 1714 /* TODO rename hwaddr to extended_addr */ 1715 dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); 1716 dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]); 1717 dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]); 1718 1719 if (dev->key_mode > NL802154_DEVKEY_MAX || 1720 (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1)) 1721 return -EINVAL; 1722 1723 return 0; 1724 } 1725 1726 static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info) 1727 { 1728 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1729 struct net_device *dev = info->user_ptr[1]; 1730 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1731 struct ieee802154_llsec_device dev_desc; 1732 1733 if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE], 1734 &dev_desc) < 0) 1735 return -EINVAL; 1736 1737 return rdev_add_device(rdev, wpan_dev, &dev_desc); 1738 } 1739 1740 static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) 1741 { 1742 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1743 struct net_device *dev = info->user_ptr[1]; 1744 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1745 struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; 1746 __le64 extended_addr; 1747 1748 if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, 1749 info->attrs[NL802154_ATTR_SEC_DEVICE], 1750 nl802154_dev_policy)) 1751 return -EINVAL; 1752 1753 if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]) 1754 return -EINVAL; 1755 1756 extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); 1757 return rdev_del_device(rdev, wpan_dev, extended_addr); 1758 } 1759 1760 static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid, 1761 u32 seq, int flags, 1762 struct cfg802154_registered_device *rdev, 1763 struct net_device *dev, __le64 extended_addr, 1764 const struct ieee802154_llsec_device_key *devkey) 1765 { 1766 void *hdr; 1767 struct nlattr *nl_devkey, *nl_key_id; 1768 1769 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1770 if (!hdr) 1771 return -1; 1772 1773 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1774 goto nla_put_failure; 1775 1776 nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY); 1777 if (!nl_devkey) 1778 goto nla_put_failure; 1779 1780 if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, 1781 extended_addr) || 1782 nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER, 1783 devkey->frame_counter)) 1784 goto nla_put_failure; 1785 1786 nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID); 1787 if (!nl_key_id) 1788 goto nla_put_failure; 1789 1790 if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0) 1791 goto nla_put_failure; 1792 1793 nla_nest_end(msg, nl_key_id); 1794 nla_nest_end(msg, nl_devkey); 1795 genlmsg_end(msg, hdr); 1796 1797 return 0; 1798 1799 nla_put_failure: 1800 genlmsg_cancel(msg, hdr); 1801 return -EMSGSIZE; 1802 } 1803 1804 static int 1805 nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb) 1806 { 1807 struct cfg802154_registered_device *rdev = NULL; 1808 struct ieee802154_llsec_device_key *kpos; 1809 struct ieee802154_llsec_device *dpos; 1810 struct ieee802154_llsec_table *table; 1811 struct wpan_dev *wpan_dev; 1812 int err; 1813 1814 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1815 if (err) 1816 return err; 1817 1818 if (!wpan_dev->netdev) { 1819 err = -EINVAL; 1820 goto out_err; 1821 } 1822 1823 rdev_lock_llsec_table(rdev, wpan_dev); 1824 rdev_get_llsec_table(rdev, wpan_dev, &table); 1825 1826 /* TODO make it like station dump */ 1827 if (cb->args[2]) 1828 goto out; 1829 1830 /* TODO look if remove devkey and do some nested attribute */ 1831 list_for_each_entry(dpos, &table->devices, list) { 1832 list_for_each_entry(kpos, &dpos->keys, list) { 1833 if (nl802154_send_devkey(skb, 1834 NL802154_CMD_NEW_SEC_LEVEL, 1835 NETLINK_CB(cb->skb).portid, 1836 cb->nlh->nlmsg_seq, 1837 NLM_F_MULTI, rdev, 1838 wpan_dev->netdev, 1839 dpos->hwaddr, 1840 kpos) < 0) { 1841 /* TODO */ 1842 err = -EIO; 1843 rdev_unlock_llsec_table(rdev, wpan_dev); 1844 goto out_err; 1845 } 1846 } 1847 } 1848 1849 cb->args[2] = 1; 1850 1851 out: 1852 rdev_unlock_llsec_table(rdev, wpan_dev); 1853 err = skb->len; 1854 out_err: 1855 nl802154_finish_wpan_dev_dump(rdev); 1856 1857 return err; 1858 } 1859 1860 static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = { 1861 [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 }, 1862 [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 }, 1863 [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED }, 1864 }; 1865 1866 static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info) 1867 { 1868 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1869 struct net_device *dev = info->user_ptr[1]; 1870 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1871 struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; 1872 struct ieee802154_llsec_device_key key; 1873 __le64 extended_addr; 1874 1875 if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || 1876 nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, 1877 info->attrs[NL802154_ATTR_SEC_DEVKEY], 1878 nl802154_devkey_policy) < 0) 1879 return -EINVAL; 1880 1881 if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] || 1882 !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) 1883 return -EINVAL; 1884 1885 /* TODO change key.id ? */ 1886 if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], 1887 &key.key_id) < 0) 1888 return -ENOBUFS; 1889 1890 /* TODO be32 */ 1891 key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]); 1892 /* TODO change naming hwaddr -> extended_addr 1893 * check unique identifier short+pan OR extended_addr 1894 */ 1895 extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); 1896 return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key); 1897 } 1898 1899 static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info) 1900 { 1901 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1902 struct net_device *dev = info->user_ptr[1]; 1903 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1904 struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; 1905 struct ieee802154_llsec_device_key key; 1906 __le64 extended_addr; 1907 1908 if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, 1909 info->attrs[NL802154_ATTR_SEC_DEVKEY], 1910 nl802154_devkey_policy)) 1911 return -EINVAL; 1912 1913 if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) 1914 return -EINVAL; 1915 1916 /* TODO change key.id ? */ 1917 if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], 1918 &key.key_id) < 0) 1919 return -ENOBUFS; 1920 1921 /* TODO change naming hwaddr -> extended_addr 1922 * check unique identifier short+pan OR extended_addr 1923 */ 1924 extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); 1925 return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key); 1926 } 1927 1928 static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid, 1929 u32 seq, int flags, 1930 struct cfg802154_registered_device *rdev, 1931 struct net_device *dev, 1932 const struct ieee802154_llsec_seclevel *sl) 1933 { 1934 void *hdr; 1935 struct nlattr *nl_seclevel; 1936 1937 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1938 if (!hdr) 1939 return -1; 1940 1941 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1942 goto nla_put_failure; 1943 1944 nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL); 1945 if (!nl_seclevel) 1946 goto nla_put_failure; 1947 1948 if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) || 1949 nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) || 1950 nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, 1951 sl->device_override)) 1952 goto nla_put_failure; 1953 1954 if (sl->frame_type == NL802154_FRAME_CMD) { 1955 if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME, 1956 sl->cmd_frame_id)) 1957 goto nla_put_failure; 1958 } 1959 1960 nla_nest_end(msg, nl_seclevel); 1961 genlmsg_end(msg, hdr); 1962 1963 return 0; 1964 1965 nla_put_failure: 1966 genlmsg_cancel(msg, hdr); 1967 return -EMSGSIZE; 1968 } 1969 1970 static int 1971 nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb) 1972 { 1973 struct cfg802154_registered_device *rdev = NULL; 1974 struct ieee802154_llsec_seclevel *sl; 1975 struct ieee802154_llsec_table *table; 1976 struct wpan_dev *wpan_dev; 1977 int err; 1978 1979 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1980 if (err) 1981 return err; 1982 1983 if (!wpan_dev->netdev) { 1984 err = -EINVAL; 1985 goto out_err; 1986 } 1987 1988 rdev_lock_llsec_table(rdev, wpan_dev); 1989 rdev_get_llsec_table(rdev, wpan_dev, &table); 1990 1991 /* TODO make it like station dump */ 1992 if (cb->args[2]) 1993 goto out; 1994 1995 list_for_each_entry(sl, &table->security_levels, list) { 1996 if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL, 1997 NETLINK_CB(cb->skb).portid, 1998 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1999 rdev, wpan_dev->netdev, sl) < 0) { 2000 /* TODO */ 2001 err = -EIO; 2002 rdev_unlock_llsec_table(rdev, wpan_dev); 2003 goto out_err; 2004 } 2005 } 2006 2007 cb->args[2] = 1; 2008 2009 out: 2010 rdev_unlock_llsec_table(rdev, wpan_dev); 2011 err = skb->len; 2012 out_err: 2013 nl802154_finish_wpan_dev_dump(rdev); 2014 2015 return err; 2016 } 2017 2018 static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = { 2019 [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 }, 2020 [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 }, 2021 [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 }, 2022 [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 }, 2023 }; 2024 2025 static int 2026 llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl) 2027 { 2028 struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1]; 2029 2030 if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla, 2031 nl802154_seclevel_policy)) 2032 return -EINVAL; 2033 2034 memset(sl, 0, sizeof(*sl)); 2035 2036 if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] || 2037 !attrs[NL802154_SECLEVEL_ATTR_FRAME] || 2038 !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]) 2039 return -EINVAL; 2040 2041 sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]); 2042 sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]); 2043 sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]); 2044 if (sl->frame_type > NL802154_FRAME_MAX || 2045 (sl->device_override != 0 && sl->device_override != 1)) 2046 return -EINVAL; 2047 2048 if (sl->frame_type == NL802154_FRAME_CMD) { 2049 if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]) 2050 return -EINVAL; 2051 2052 sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]); 2053 if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX) 2054 return -EINVAL; 2055 } 2056 2057 return 0; 2058 } 2059 2060 static int nl802154_add_llsec_seclevel(struct sk_buff *skb, 2061 struct genl_info *info) 2062 { 2063 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 2064 struct net_device *dev = info->user_ptr[1]; 2065 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 2066 struct ieee802154_llsec_seclevel sl; 2067 2068 if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], 2069 &sl) < 0) 2070 return -EINVAL; 2071 2072 return rdev_add_seclevel(rdev, wpan_dev, &sl); 2073 } 2074 2075 static int nl802154_del_llsec_seclevel(struct sk_buff *skb, 2076 struct genl_info *info) 2077 { 2078 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 2079 struct net_device *dev = info->user_ptr[1]; 2080 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 2081 struct ieee802154_llsec_seclevel sl; 2082 2083 if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || 2084 llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], 2085 &sl) < 0) 2086 return -EINVAL; 2087 2088 return rdev_del_seclevel(rdev, wpan_dev, &sl); 2089 } 2090 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 2091 2092 #define NL802154_FLAG_NEED_WPAN_PHY 0x01 2093 #define NL802154_FLAG_NEED_NETDEV 0x02 2094 #define NL802154_FLAG_NEED_RTNL 0x04 2095 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08 2096 #define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\ 2097 NL802154_FLAG_CHECK_NETDEV_UP) 2098 #define NL802154_FLAG_NEED_WPAN_DEV 0x10 2099 #define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\ 2100 NL802154_FLAG_CHECK_NETDEV_UP) 2101 2102 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 2103 struct genl_info *info) 2104 { 2105 struct cfg802154_registered_device *rdev; 2106 struct wpan_dev *wpan_dev; 2107 struct net_device *dev; 2108 bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL; 2109 2110 if (rtnl) 2111 rtnl_lock(); 2112 2113 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) { 2114 rdev = cfg802154_get_dev_from_info(genl_info_net(info), info); 2115 if (IS_ERR(rdev)) { 2116 if (rtnl) 2117 rtnl_unlock(); 2118 return PTR_ERR(rdev); 2119 } 2120 info->user_ptr[0] = rdev; 2121 } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV || 2122 ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 2123 ASSERT_RTNL(); 2124 wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info), 2125 info->attrs); 2126 if (IS_ERR(wpan_dev)) { 2127 if (rtnl) 2128 rtnl_unlock(); 2129 return PTR_ERR(wpan_dev); 2130 } 2131 2132 dev = wpan_dev->netdev; 2133 rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy); 2134 2135 if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) { 2136 if (!dev) { 2137 if (rtnl) 2138 rtnl_unlock(); 2139 return -EINVAL; 2140 } 2141 2142 info->user_ptr[1] = dev; 2143 } else { 2144 info->user_ptr[1] = wpan_dev; 2145 } 2146 2147 if (dev) { 2148 if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP && 2149 !netif_running(dev)) { 2150 if (rtnl) 2151 rtnl_unlock(); 2152 return -ENETDOWN; 2153 } 2154 2155 dev_hold(dev); 2156 } 2157 2158 info->user_ptr[0] = rdev; 2159 } 2160 2161 return 0; 2162 } 2163 2164 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 2165 struct genl_info *info) 2166 { 2167 if (info->user_ptr[1]) { 2168 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 2169 struct wpan_dev *wpan_dev = info->user_ptr[1]; 2170 2171 if (wpan_dev->netdev) 2172 dev_put(wpan_dev->netdev); 2173 } else { 2174 dev_put(info->user_ptr[1]); 2175 } 2176 } 2177 2178 if (ops->internal_flags & NL802154_FLAG_NEED_RTNL) 2179 rtnl_unlock(); 2180 } 2181 2182 static const struct genl_ops nl802154_ops[] = { 2183 { 2184 .cmd = NL802154_CMD_GET_WPAN_PHY, 2185 .doit = nl802154_get_wpan_phy, 2186 .dumpit = nl802154_dump_wpan_phy, 2187 .done = nl802154_dump_wpan_phy_done, 2188 .policy = nl802154_policy, 2189 /* can be retrieved by unprivileged users */ 2190 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2191 NL802154_FLAG_NEED_RTNL, 2192 }, 2193 { 2194 .cmd = NL802154_CMD_GET_INTERFACE, 2195 .doit = nl802154_get_interface, 2196 .dumpit = nl802154_dump_interface, 2197 .policy = nl802154_policy, 2198 /* can be retrieved by unprivileged users */ 2199 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 2200 NL802154_FLAG_NEED_RTNL, 2201 }, 2202 { 2203 .cmd = NL802154_CMD_NEW_INTERFACE, 2204 .doit = nl802154_new_interface, 2205 .policy = nl802154_policy, 2206 .flags = GENL_ADMIN_PERM, 2207 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2208 NL802154_FLAG_NEED_RTNL, 2209 }, 2210 { 2211 .cmd = NL802154_CMD_DEL_INTERFACE, 2212 .doit = nl802154_del_interface, 2213 .policy = nl802154_policy, 2214 .flags = GENL_ADMIN_PERM, 2215 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 2216 NL802154_FLAG_NEED_RTNL, 2217 }, 2218 { 2219 .cmd = NL802154_CMD_SET_CHANNEL, 2220 .doit = nl802154_set_channel, 2221 .policy = nl802154_policy, 2222 .flags = GENL_ADMIN_PERM, 2223 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2224 NL802154_FLAG_NEED_RTNL, 2225 }, 2226 { 2227 .cmd = NL802154_CMD_SET_CCA_MODE, 2228 .doit = nl802154_set_cca_mode, 2229 .policy = nl802154_policy, 2230 .flags = GENL_ADMIN_PERM, 2231 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2232 NL802154_FLAG_NEED_RTNL, 2233 }, 2234 { 2235 .cmd = NL802154_CMD_SET_CCA_ED_LEVEL, 2236 .doit = nl802154_set_cca_ed_level, 2237 .policy = nl802154_policy, 2238 .flags = GENL_ADMIN_PERM, 2239 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2240 NL802154_FLAG_NEED_RTNL, 2241 }, 2242 { 2243 .cmd = NL802154_CMD_SET_TX_POWER, 2244 .doit = nl802154_set_tx_power, 2245 .policy = nl802154_policy, 2246 .flags = GENL_ADMIN_PERM, 2247 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2248 NL802154_FLAG_NEED_RTNL, 2249 }, 2250 { 2251 .cmd = NL802154_CMD_SET_PAN_ID, 2252 .doit = nl802154_set_pan_id, 2253 .policy = nl802154_policy, 2254 .flags = GENL_ADMIN_PERM, 2255 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2256 NL802154_FLAG_NEED_RTNL, 2257 }, 2258 { 2259 .cmd = NL802154_CMD_SET_SHORT_ADDR, 2260 .doit = nl802154_set_short_addr, 2261 .policy = nl802154_policy, 2262 .flags = GENL_ADMIN_PERM, 2263 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2264 NL802154_FLAG_NEED_RTNL, 2265 }, 2266 { 2267 .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT, 2268 .doit = nl802154_set_backoff_exponent, 2269 .policy = nl802154_policy, 2270 .flags = GENL_ADMIN_PERM, 2271 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2272 NL802154_FLAG_NEED_RTNL, 2273 }, 2274 { 2275 .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS, 2276 .doit = nl802154_set_max_csma_backoffs, 2277 .policy = nl802154_policy, 2278 .flags = GENL_ADMIN_PERM, 2279 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2280 NL802154_FLAG_NEED_RTNL, 2281 }, 2282 { 2283 .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES, 2284 .doit = nl802154_set_max_frame_retries, 2285 .policy = nl802154_policy, 2286 .flags = GENL_ADMIN_PERM, 2287 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2288 NL802154_FLAG_NEED_RTNL, 2289 }, 2290 { 2291 .cmd = NL802154_CMD_SET_LBT_MODE, 2292 .doit = nl802154_set_lbt_mode, 2293 .policy = nl802154_policy, 2294 .flags = GENL_ADMIN_PERM, 2295 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2296 NL802154_FLAG_NEED_RTNL, 2297 }, 2298 { 2299 .cmd = NL802154_CMD_SET_ACKREQ_DEFAULT, 2300 .doit = nl802154_set_ackreq_default, 2301 .policy = nl802154_policy, 2302 .flags = GENL_ADMIN_PERM, 2303 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2304 NL802154_FLAG_NEED_RTNL, 2305 }, 2306 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 2307 { 2308 .cmd = NL802154_CMD_SET_SEC_PARAMS, 2309 .doit = nl802154_set_llsec_params, 2310 .policy = nl802154_policy, 2311 .flags = GENL_ADMIN_PERM, 2312 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2313 NL802154_FLAG_NEED_RTNL, 2314 }, 2315 { 2316 .cmd = NL802154_CMD_GET_SEC_KEY, 2317 /* TODO .doit by matching key id? */ 2318 .dumpit = nl802154_dump_llsec_key, 2319 .policy = nl802154_policy, 2320 .flags = GENL_ADMIN_PERM, 2321 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2322 NL802154_FLAG_NEED_RTNL, 2323 }, 2324 { 2325 .cmd = NL802154_CMD_NEW_SEC_KEY, 2326 .doit = nl802154_add_llsec_key, 2327 .policy = nl802154_policy, 2328 .flags = GENL_ADMIN_PERM, 2329 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2330 NL802154_FLAG_NEED_RTNL, 2331 }, 2332 { 2333 .cmd = NL802154_CMD_DEL_SEC_KEY, 2334 .doit = nl802154_del_llsec_key, 2335 .policy = nl802154_policy, 2336 .flags = GENL_ADMIN_PERM, 2337 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2338 NL802154_FLAG_NEED_RTNL, 2339 }, 2340 /* TODO unique identifier must short+pan OR extended_addr */ 2341 { 2342 .cmd = NL802154_CMD_GET_SEC_DEV, 2343 /* TODO .doit by matching extended_addr? */ 2344 .dumpit = nl802154_dump_llsec_dev, 2345 .policy = nl802154_policy, 2346 .flags = GENL_ADMIN_PERM, 2347 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2348 NL802154_FLAG_NEED_RTNL, 2349 }, 2350 { 2351 .cmd = NL802154_CMD_NEW_SEC_DEV, 2352 .doit = nl802154_add_llsec_dev, 2353 .policy = nl802154_policy, 2354 .flags = GENL_ADMIN_PERM, 2355 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2356 NL802154_FLAG_NEED_RTNL, 2357 }, 2358 { 2359 .cmd = NL802154_CMD_DEL_SEC_DEV, 2360 .doit = nl802154_del_llsec_dev, 2361 .policy = nl802154_policy, 2362 .flags = GENL_ADMIN_PERM, 2363 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2364 NL802154_FLAG_NEED_RTNL, 2365 }, 2366 /* TODO remove complete devkey, put it as nested? */ 2367 { 2368 .cmd = NL802154_CMD_GET_SEC_DEVKEY, 2369 /* TODO doit by matching ??? */ 2370 .dumpit = nl802154_dump_llsec_devkey, 2371 .policy = nl802154_policy, 2372 .flags = GENL_ADMIN_PERM, 2373 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2374 NL802154_FLAG_NEED_RTNL, 2375 }, 2376 { 2377 .cmd = NL802154_CMD_NEW_SEC_DEVKEY, 2378 .doit = nl802154_add_llsec_devkey, 2379 .policy = nl802154_policy, 2380 .flags = GENL_ADMIN_PERM, 2381 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2382 NL802154_FLAG_NEED_RTNL, 2383 }, 2384 { 2385 .cmd = NL802154_CMD_DEL_SEC_DEVKEY, 2386 .doit = nl802154_del_llsec_devkey, 2387 .policy = nl802154_policy, 2388 .flags = GENL_ADMIN_PERM, 2389 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2390 NL802154_FLAG_NEED_RTNL, 2391 }, 2392 { 2393 .cmd = NL802154_CMD_GET_SEC_LEVEL, 2394 /* TODO .doit by matching frame_type? */ 2395 .dumpit = nl802154_dump_llsec_seclevel, 2396 .policy = nl802154_policy, 2397 .flags = GENL_ADMIN_PERM, 2398 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2399 NL802154_FLAG_NEED_RTNL, 2400 }, 2401 { 2402 .cmd = NL802154_CMD_NEW_SEC_LEVEL, 2403 .doit = nl802154_add_llsec_seclevel, 2404 .policy = nl802154_policy, 2405 .flags = GENL_ADMIN_PERM, 2406 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2407 NL802154_FLAG_NEED_RTNL, 2408 }, 2409 { 2410 .cmd = NL802154_CMD_DEL_SEC_LEVEL, 2411 /* TODO match frame_type only? */ 2412 .doit = nl802154_del_llsec_seclevel, 2413 .policy = nl802154_policy, 2414 .flags = GENL_ADMIN_PERM, 2415 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2416 NL802154_FLAG_NEED_RTNL, 2417 }, 2418 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 2419 }; 2420 2421 /* initialisation/exit functions */ 2422 int nl802154_init(void) 2423 { 2424 return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops, 2425 nl802154_mcgrps); 2426 } 2427 2428 void nl802154_exit(void) 2429 { 2430 genl_unregister_family(&nl802154_fam); 2431 } 2432