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 NL802154_DEV_ADDR_ATTR_PAD)) 727 return -ENOBUFS; 728 break; 729 default: 730 /* userspace should handle unknown */ 731 break; 732 } 733 734 nla_nest_end(msg, nl_dev_addr); 735 break; 736 case NL802154_KEY_ID_MODE_INDEX: 737 break; 738 case NL802154_KEY_ID_MODE_INDEX_SHORT: 739 /* TODO renmae short_source? */ 740 if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT, 741 desc->short_source)) 742 return -ENOBUFS; 743 break; 744 case NL802154_KEY_ID_MODE_INDEX_EXTENDED: 745 if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED, 746 desc->extended_source, 747 NL802154_KEY_ID_ATTR_PAD)) 748 return -ENOBUFS; 749 break; 750 default: 751 /* userspace should handle unknown */ 752 break; 753 } 754 755 /* TODO key_id to key_idx ? Check naming */ 756 if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { 757 if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id)) 758 return -ENOBUFS; 759 } 760 761 return 0; 762 } 763 764 static int nl802154_get_llsec_params(struct sk_buff *msg, 765 struct cfg802154_registered_device *rdev, 766 struct wpan_dev *wpan_dev) 767 { 768 struct nlattr *nl_key_id; 769 struct ieee802154_llsec_params params; 770 int ret; 771 772 ret = rdev_get_llsec_params(rdev, wpan_dev, ¶ms); 773 if (ret < 0) 774 return ret; 775 776 if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) || 777 nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) || 778 nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER, 779 params.frame_counter)) 780 return -ENOBUFS; 781 782 nl_key_id = nla_nest_start(msg, NL802154_ATTR_SEC_OUT_KEY_ID); 783 if (!nl_key_id) 784 return -ENOBUFS; 785 786 ret = ieee802154_llsec_send_key_id(msg, ¶ms.out_key); 787 if (ret < 0) 788 return ret; 789 790 nla_nest_end(msg, nl_key_id); 791 792 return 0; 793 } 794 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 795 796 static int 797 nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, 798 struct cfg802154_registered_device *rdev, 799 struct wpan_dev *wpan_dev) 800 { 801 struct net_device *dev = wpan_dev->netdev; 802 void *hdr; 803 804 hdr = nl802154hdr_put(msg, portid, seq, flags, 805 NL802154_CMD_NEW_INTERFACE); 806 if (!hdr) 807 return -1; 808 809 if (dev && 810 (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) || 811 nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name))) 812 goto nla_put_failure; 813 814 if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || 815 nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) || 816 nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV, 817 wpan_dev_id(wpan_dev), NL802154_ATTR_PAD) || 818 nla_put_u32(msg, NL802154_ATTR_GENERATION, 819 rdev->devlist_generation ^ 820 (cfg802154_rdev_list_generation << 2))) 821 goto nla_put_failure; 822 823 /* address settings */ 824 if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR, 825 wpan_dev->extended_addr, 826 NL802154_ATTR_PAD) || 827 nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR, 828 wpan_dev->short_addr) || 829 nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id)) 830 goto nla_put_failure; 831 832 /* ARET handling */ 833 if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES, 834 wpan_dev->frame_retries) || 835 nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) || 836 nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS, 837 wpan_dev->csma_retries) || 838 nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be)) 839 goto nla_put_failure; 840 841 /* listen before transmit */ 842 if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt)) 843 goto nla_put_failure; 844 845 /* ackreq default behaviour */ 846 if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq)) 847 goto nla_put_failure; 848 849 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 850 if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) 851 goto nla_put_failure; 852 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 853 854 genlmsg_end(msg, hdr); 855 return 0; 856 857 nla_put_failure: 858 genlmsg_cancel(msg, hdr); 859 return -EMSGSIZE; 860 } 861 862 static int 863 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) 864 { 865 int wp_idx = 0; 866 int if_idx = 0; 867 int wp_start = cb->args[0]; 868 int if_start = cb->args[1]; 869 struct cfg802154_registered_device *rdev; 870 struct wpan_dev *wpan_dev; 871 872 rtnl_lock(); 873 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 874 /* TODO netns compare */ 875 if (wp_idx < wp_start) { 876 wp_idx++; 877 continue; 878 } 879 if_idx = 0; 880 881 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { 882 if (if_idx < if_start) { 883 if_idx++; 884 continue; 885 } 886 if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid, 887 cb->nlh->nlmsg_seq, NLM_F_MULTI, 888 rdev, wpan_dev) < 0) { 889 goto out; 890 } 891 if_idx++; 892 } 893 894 wp_idx++; 895 } 896 out: 897 rtnl_unlock(); 898 899 cb->args[0] = wp_idx; 900 cb->args[1] = if_idx; 901 902 return skb->len; 903 } 904 905 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info) 906 { 907 struct sk_buff *msg; 908 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 909 struct wpan_dev *wdev = info->user_ptr[1]; 910 911 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 912 if (!msg) 913 return -ENOMEM; 914 915 if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0, 916 rdev, wdev) < 0) { 917 nlmsg_free(msg); 918 return -ENOBUFS; 919 } 920 921 return genlmsg_reply(msg, info); 922 } 923 924 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) 925 { 926 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 927 enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC; 928 __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL); 929 930 /* TODO avoid failing a new interface 931 * creation due to pending removal? 932 */ 933 934 if (!info->attrs[NL802154_ATTR_IFNAME]) 935 return -EINVAL; 936 937 if (info->attrs[NL802154_ATTR_IFTYPE]) { 938 type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]); 939 if (type > NL802154_IFTYPE_MAX || 940 !(rdev->wpan_phy.supported.iftypes & BIT(type))) 941 return -EINVAL; 942 } 943 944 if (info->attrs[NL802154_ATTR_EXTENDED_ADDR]) 945 extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]); 946 947 if (!rdev->ops->add_virtual_intf) 948 return -EOPNOTSUPP; 949 950 return rdev_add_virtual_intf(rdev, 951 nla_data(info->attrs[NL802154_ATTR_IFNAME]), 952 NET_NAME_USER, type, extended_addr); 953 } 954 955 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) 956 { 957 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 958 struct wpan_dev *wpan_dev = info->user_ptr[1]; 959 960 if (!rdev->ops->del_virtual_intf) 961 return -EOPNOTSUPP; 962 963 /* If we remove a wpan device without a netdev then clear 964 * user_ptr[1] so that nl802154_post_doit won't dereference it 965 * to check if it needs to do dev_put(). Otherwise it crashes 966 * since the wpan_dev has been freed, unlike with a netdev where 967 * we need the dev_put() for the netdev to really be freed. 968 */ 969 if (!wpan_dev->netdev) 970 info->user_ptr[1] = NULL; 971 972 return rdev_del_virtual_intf(rdev, wpan_dev); 973 } 974 975 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info) 976 { 977 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 978 u8 channel, page; 979 980 if (!info->attrs[NL802154_ATTR_PAGE] || 981 !info->attrs[NL802154_ATTR_CHANNEL]) 982 return -EINVAL; 983 984 page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]); 985 channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]); 986 987 /* check 802.15.4 constraints */ 988 if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL || 989 !(rdev->wpan_phy.supported.channels[page] & BIT(channel))) 990 return -EINVAL; 991 992 return rdev_set_channel(rdev, page, channel); 993 } 994 995 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info) 996 { 997 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 998 struct wpan_phy_cca cca; 999 1000 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)) 1001 return -EOPNOTSUPP; 1002 1003 if (!info->attrs[NL802154_ATTR_CCA_MODE]) 1004 return -EINVAL; 1005 1006 cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]); 1007 /* checking 802.15.4 constraints */ 1008 if (cca.mode < NL802154_CCA_ENERGY || 1009 cca.mode > NL802154_CCA_ATTR_MAX || 1010 !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode))) 1011 return -EINVAL; 1012 1013 if (cca.mode == NL802154_CCA_ENERGY_CARRIER) { 1014 if (!info->attrs[NL802154_ATTR_CCA_OPT]) 1015 return -EINVAL; 1016 1017 cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]); 1018 if (cca.opt > NL802154_CCA_OPT_ATTR_MAX || 1019 !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt))) 1020 return -EINVAL; 1021 } 1022 1023 return rdev_set_cca_mode(rdev, &cca); 1024 } 1025 1026 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info) 1027 { 1028 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1029 s32 ed_level; 1030 int i; 1031 1032 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)) 1033 return -EOPNOTSUPP; 1034 1035 if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL]) 1036 return -EINVAL; 1037 1038 ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]); 1039 1040 for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) { 1041 if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i]) 1042 return rdev_set_cca_ed_level(rdev, ed_level); 1043 } 1044 1045 return -EINVAL; 1046 } 1047 1048 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info) 1049 { 1050 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1051 s32 power; 1052 int i; 1053 1054 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)) 1055 return -EOPNOTSUPP; 1056 1057 if (!info->attrs[NL802154_ATTR_TX_POWER]) 1058 return -EINVAL; 1059 1060 power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]); 1061 1062 for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) { 1063 if (power == rdev->wpan_phy.supported.tx_powers[i]) 1064 return rdev_set_tx_power(rdev, power); 1065 } 1066 1067 return -EINVAL; 1068 } 1069 1070 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info) 1071 { 1072 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1073 struct net_device *dev = info->user_ptr[1]; 1074 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1075 __le16 pan_id; 1076 1077 /* conflict here while tx/rx calls */ 1078 if (netif_running(dev)) 1079 return -EBUSY; 1080 1081 if (wpan_dev->lowpan_dev) { 1082 if (netif_running(wpan_dev->lowpan_dev)) 1083 return -EBUSY; 1084 } 1085 1086 /* don't change address fields on monitor */ 1087 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 1088 !info->attrs[NL802154_ATTR_PAN_ID]) 1089 return -EINVAL; 1090 1091 pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]); 1092 1093 /* TODO 1094 * I am not sure about to check here on broadcast pan_id. 1095 * Broadcast is a valid setting, comment from 802.15.4: 1096 * If this value is 0xffff, the device is not associated. 1097 * 1098 * This could useful to simple deassociate an device. 1099 */ 1100 if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST)) 1101 return -EINVAL; 1102 1103 return rdev_set_pan_id(rdev, wpan_dev, pan_id); 1104 } 1105 1106 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info) 1107 { 1108 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1109 struct net_device *dev = info->user_ptr[1]; 1110 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1111 __le16 short_addr; 1112 1113 /* conflict here while tx/rx calls */ 1114 if (netif_running(dev)) 1115 return -EBUSY; 1116 1117 if (wpan_dev->lowpan_dev) { 1118 if (netif_running(wpan_dev->lowpan_dev)) 1119 return -EBUSY; 1120 } 1121 1122 /* don't change address fields on monitor */ 1123 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 1124 !info->attrs[NL802154_ATTR_SHORT_ADDR]) 1125 return -EINVAL; 1126 1127 short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]); 1128 1129 /* TODO 1130 * I am not sure about to check here on broadcast short_addr. 1131 * Broadcast is a valid setting, comment from 802.15.4: 1132 * A value of 0xfffe indicates that the device has 1133 * associated but has not been allocated an address. A 1134 * value of 0xffff indicates that the device does not 1135 * have a short address. 1136 * 1137 * I think we should allow to set these settings but 1138 * don't allow to allow socket communication with it. 1139 */ 1140 if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) || 1141 short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST)) 1142 return -EINVAL; 1143 1144 return rdev_set_short_addr(rdev, wpan_dev, short_addr); 1145 } 1146 1147 static int 1148 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info) 1149 { 1150 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1151 struct net_device *dev = info->user_ptr[1]; 1152 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1153 u8 min_be, max_be; 1154 1155 /* should be set on netif open inside phy settings */ 1156 if (netif_running(dev)) 1157 return -EBUSY; 1158 1159 if (!info->attrs[NL802154_ATTR_MIN_BE] || 1160 !info->attrs[NL802154_ATTR_MAX_BE]) 1161 return -EINVAL; 1162 1163 min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]); 1164 max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]); 1165 1166 /* check 802.15.4 constraints */ 1167 if (min_be < rdev->wpan_phy.supported.min_minbe || 1168 min_be > rdev->wpan_phy.supported.max_minbe || 1169 max_be < rdev->wpan_phy.supported.min_maxbe || 1170 max_be > rdev->wpan_phy.supported.max_maxbe || 1171 min_be > max_be) 1172 return -EINVAL; 1173 1174 return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be); 1175 } 1176 1177 static int 1178 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info) 1179 { 1180 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1181 struct net_device *dev = info->user_ptr[1]; 1182 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1183 u8 max_csma_backoffs; 1184 1185 /* conflict here while other running iface settings */ 1186 if (netif_running(dev)) 1187 return -EBUSY; 1188 1189 if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]) 1190 return -EINVAL; 1191 1192 max_csma_backoffs = nla_get_u8( 1193 info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]); 1194 1195 /* check 802.15.4 constraints */ 1196 if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs || 1197 max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs) 1198 return -EINVAL; 1199 1200 return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs); 1201 } 1202 1203 static int 1204 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info) 1205 { 1206 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1207 struct net_device *dev = info->user_ptr[1]; 1208 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1209 s8 max_frame_retries; 1210 1211 if (netif_running(dev)) 1212 return -EBUSY; 1213 1214 if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]) 1215 return -EINVAL; 1216 1217 max_frame_retries = nla_get_s8( 1218 info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]); 1219 1220 /* check 802.15.4 constraints */ 1221 if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries || 1222 max_frame_retries > rdev->wpan_phy.supported.max_frame_retries) 1223 return -EINVAL; 1224 1225 return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries); 1226 } 1227 1228 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info) 1229 { 1230 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1231 struct net_device *dev = info->user_ptr[1]; 1232 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1233 int mode; 1234 1235 if (netif_running(dev)) 1236 return -EBUSY; 1237 1238 if (!info->attrs[NL802154_ATTR_LBT_MODE]) 1239 return -EINVAL; 1240 1241 mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]); 1242 1243 if (mode != 0 && mode != 1) 1244 return -EINVAL; 1245 1246 if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt)) 1247 return -EINVAL; 1248 1249 return rdev_set_lbt_mode(rdev, wpan_dev, mode); 1250 } 1251 1252 static int 1253 nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info) 1254 { 1255 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1256 struct net_device *dev = info->user_ptr[1]; 1257 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1258 int ackreq; 1259 1260 if (netif_running(dev)) 1261 return -EBUSY; 1262 1263 if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]) 1264 return -EINVAL; 1265 1266 ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]); 1267 1268 if (ackreq != 0 && ackreq != 1) 1269 return -EINVAL; 1270 1271 return rdev_set_ackreq_default(rdev, wpan_dev, ackreq); 1272 } 1273 1274 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 1275 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = { 1276 [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 }, 1277 [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 }, 1278 [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 }, 1279 [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 }, 1280 }; 1281 1282 static int 1283 ieee802154_llsec_parse_dev_addr(struct nlattr *nla, 1284 struct ieee802154_addr *addr) 1285 { 1286 struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1]; 1287 1288 if (!nla || nla_parse_nested(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla, 1289 nl802154_dev_addr_policy)) 1290 return -EINVAL; 1291 1292 if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] || 1293 !attrs[NL802154_DEV_ADDR_ATTR_MODE] || 1294 !(attrs[NL802154_DEV_ADDR_ATTR_SHORT] || 1295 attrs[NL802154_DEV_ADDR_ATTR_EXTENDED])) 1296 return -EINVAL; 1297 1298 addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]); 1299 addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]); 1300 switch (addr->mode) { 1301 case NL802154_DEV_ADDR_SHORT: 1302 addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]); 1303 break; 1304 case NL802154_DEV_ADDR_EXTENDED: 1305 addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]); 1306 break; 1307 default: 1308 return -EINVAL; 1309 } 1310 1311 return 0; 1312 } 1313 1314 static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = { 1315 [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 }, 1316 [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 }, 1317 [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED }, 1318 [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 }, 1319 [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 }, 1320 }; 1321 1322 static int 1323 ieee802154_llsec_parse_key_id(struct nlattr *nla, 1324 struct ieee802154_llsec_key_id *desc) 1325 { 1326 struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1]; 1327 1328 if (!nla || nla_parse_nested(attrs, NL802154_KEY_ID_ATTR_MAX, nla, 1329 nl802154_key_id_policy)) 1330 return -EINVAL; 1331 1332 if (!attrs[NL802154_KEY_ID_ATTR_MODE]) 1333 return -EINVAL; 1334 1335 desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]); 1336 switch (desc->mode) { 1337 case NL802154_KEY_ID_MODE_IMPLICIT: 1338 if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT]) 1339 return -EINVAL; 1340 1341 if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT], 1342 &desc->device_addr) < 0) 1343 return -EINVAL; 1344 break; 1345 case NL802154_KEY_ID_MODE_INDEX: 1346 break; 1347 case NL802154_KEY_ID_MODE_INDEX_SHORT: 1348 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]) 1349 return -EINVAL; 1350 1351 desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]); 1352 break; 1353 case NL802154_KEY_ID_MODE_INDEX_EXTENDED: 1354 if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]) 1355 return -EINVAL; 1356 1357 desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]); 1358 break; 1359 default: 1360 return -EINVAL; 1361 } 1362 1363 if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) { 1364 if (!attrs[NL802154_KEY_ID_ATTR_INDEX]) 1365 return -EINVAL; 1366 1367 /* TODO change id to idx */ 1368 desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]); 1369 } 1370 1371 return 0; 1372 } 1373 1374 static int nl802154_set_llsec_params(struct sk_buff *skb, 1375 struct genl_info *info) 1376 { 1377 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1378 struct net_device *dev = info->user_ptr[1]; 1379 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1380 struct ieee802154_llsec_params params; 1381 u32 changed = 0; 1382 int ret; 1383 1384 if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { 1385 u8 enabled; 1386 1387 enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); 1388 if (enabled != 0 && enabled != 1) 1389 return -EINVAL; 1390 1391 params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]); 1392 changed |= IEEE802154_LLSEC_PARAM_ENABLED; 1393 } 1394 1395 if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) { 1396 ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID], 1397 ¶ms.out_key); 1398 if (ret < 0) 1399 return ret; 1400 1401 changed |= IEEE802154_LLSEC_PARAM_OUT_KEY; 1402 } 1403 1404 if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) { 1405 params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]); 1406 if (params.out_level > NL802154_SECLEVEL_MAX) 1407 return -EINVAL; 1408 1409 changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL; 1410 } 1411 1412 if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) { 1413 params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]); 1414 changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER; 1415 } 1416 1417 return rdev_set_llsec_params(rdev, wpan_dev, ¶ms, changed); 1418 } 1419 1420 static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid, 1421 u32 seq, int flags, 1422 struct cfg802154_registered_device *rdev, 1423 struct net_device *dev, 1424 const struct ieee802154_llsec_key_entry *key) 1425 { 1426 void *hdr; 1427 u32 commands[NL802154_CMD_FRAME_NR_IDS / 32]; 1428 struct nlattr *nl_key, *nl_key_id; 1429 1430 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1431 if (!hdr) 1432 return -1; 1433 1434 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1435 goto nla_put_failure; 1436 1437 nl_key = nla_nest_start(msg, NL802154_ATTR_SEC_KEY); 1438 if (!nl_key) 1439 goto nla_put_failure; 1440 1441 nl_key_id = nla_nest_start(msg, NL802154_KEY_ATTR_ID); 1442 if (!nl_key_id) 1443 goto nla_put_failure; 1444 1445 if (ieee802154_llsec_send_key_id(msg, &key->id) < 0) 1446 goto nla_put_failure; 1447 1448 nla_nest_end(msg, nl_key_id); 1449 1450 if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES, 1451 key->key->frame_types)) 1452 goto nla_put_failure; 1453 1454 if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) { 1455 /* TODO for each nested */ 1456 memset(commands, 0, sizeof(commands)); 1457 commands[7] = key->key->cmd_frame_ids; 1458 if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS, 1459 sizeof(commands), commands)) 1460 goto nla_put_failure; 1461 } 1462 1463 if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE, 1464 key->key->key)) 1465 goto nla_put_failure; 1466 1467 nla_nest_end(msg, nl_key); 1468 genlmsg_end(msg, hdr); 1469 1470 return 0; 1471 1472 nla_put_failure: 1473 genlmsg_cancel(msg, hdr); 1474 return -EMSGSIZE; 1475 } 1476 1477 static int 1478 nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb) 1479 { 1480 struct cfg802154_registered_device *rdev = NULL; 1481 struct ieee802154_llsec_key_entry *key; 1482 struct ieee802154_llsec_table *table; 1483 struct wpan_dev *wpan_dev; 1484 int err; 1485 1486 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1487 if (err) 1488 return err; 1489 1490 if (!wpan_dev->netdev) { 1491 err = -EINVAL; 1492 goto out_err; 1493 } 1494 1495 rdev_lock_llsec_table(rdev, wpan_dev); 1496 rdev_get_llsec_table(rdev, wpan_dev, &table); 1497 1498 /* TODO make it like station dump */ 1499 if (cb->args[2]) 1500 goto out; 1501 1502 list_for_each_entry(key, &table->keys, list) { 1503 if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY, 1504 NETLINK_CB(cb->skb).portid, 1505 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1506 rdev, wpan_dev->netdev, key) < 0) { 1507 /* TODO */ 1508 err = -EIO; 1509 rdev_unlock_llsec_table(rdev, wpan_dev); 1510 goto out_err; 1511 } 1512 } 1513 1514 cb->args[2] = 1; 1515 1516 out: 1517 rdev_unlock_llsec_table(rdev, wpan_dev); 1518 err = skb->len; 1519 out_err: 1520 nl802154_finish_wpan_dev_dump(rdev); 1521 1522 return err; 1523 } 1524 1525 static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = { 1526 [NL802154_KEY_ATTR_ID] = { NLA_NESTED }, 1527 /* TODO handle it as for_each_nested and NLA_FLAG? */ 1528 [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 }, 1529 /* TODO handle it as for_each_nested, not static array? */ 1530 [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 }, 1531 [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE }, 1532 }; 1533 1534 static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) 1535 { 1536 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1537 struct net_device *dev = info->user_ptr[1]; 1538 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1539 struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; 1540 struct ieee802154_llsec_key key = { }; 1541 struct ieee802154_llsec_key_id id = { }; 1542 u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; 1543 1544 if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, 1545 info->attrs[NL802154_ATTR_SEC_KEY], 1546 nl802154_key_policy)) 1547 return -EINVAL; 1548 1549 if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] || 1550 !attrs[NL802154_KEY_ATTR_BYTES]) 1551 return -EINVAL; 1552 1553 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1554 return -ENOBUFS; 1555 1556 key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]); 1557 if (key.frame_types > BIT(NL802154_FRAME_MAX) || 1558 ((key.frame_types & BIT(NL802154_FRAME_CMD)) && 1559 !attrs[NL802154_KEY_ATTR_USAGE_CMDS])) 1560 return -EINVAL; 1561 1562 if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) { 1563 /* TODO for each nested */ 1564 nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS], 1565 NL802154_CMD_FRAME_NR_IDS / 8); 1566 1567 /* TODO understand the -EINVAL logic here? last condition */ 1568 if (commands[0] || commands[1] || commands[2] || commands[3] || 1569 commands[4] || commands[5] || commands[6] || 1570 commands[7] > BIT(NL802154_CMD_FRAME_MAX)) 1571 return -EINVAL; 1572 1573 key.cmd_frame_ids = commands[7]; 1574 } else { 1575 key.cmd_frame_ids = 0; 1576 } 1577 1578 nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE); 1579 1580 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1581 return -ENOBUFS; 1582 1583 return rdev_add_llsec_key(rdev, wpan_dev, &id, &key); 1584 } 1585 1586 static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) 1587 { 1588 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1589 struct net_device *dev = info->user_ptr[1]; 1590 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1591 struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; 1592 struct ieee802154_llsec_key_id id; 1593 1594 if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, 1595 info->attrs[NL802154_ATTR_SEC_KEY], 1596 nl802154_key_policy)) 1597 return -EINVAL; 1598 1599 if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) 1600 return -ENOBUFS; 1601 1602 return rdev_del_llsec_key(rdev, wpan_dev, &id); 1603 } 1604 1605 static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid, 1606 u32 seq, int flags, 1607 struct cfg802154_registered_device *rdev, 1608 struct net_device *dev, 1609 const struct ieee802154_llsec_device *dev_desc) 1610 { 1611 void *hdr; 1612 struct nlattr *nl_device; 1613 1614 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1615 if (!hdr) 1616 return -1; 1617 1618 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1619 goto nla_put_failure; 1620 1621 nl_device = nla_nest_start(msg, NL802154_ATTR_SEC_DEVICE); 1622 if (!nl_device) 1623 goto nla_put_failure; 1624 1625 if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER, 1626 dev_desc->frame_counter) || 1627 nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) || 1628 nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR, 1629 dev_desc->short_addr) || 1630 nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR, 1631 dev_desc->hwaddr, NL802154_DEV_ATTR_PAD) || 1632 nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT, 1633 dev_desc->seclevel_exempt) || 1634 nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode)) 1635 goto nla_put_failure; 1636 1637 nla_nest_end(msg, nl_device); 1638 genlmsg_end(msg, hdr); 1639 1640 return 0; 1641 1642 nla_put_failure: 1643 genlmsg_cancel(msg, hdr); 1644 return -EMSGSIZE; 1645 } 1646 1647 static int 1648 nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb) 1649 { 1650 struct cfg802154_registered_device *rdev = NULL; 1651 struct ieee802154_llsec_device *dev; 1652 struct ieee802154_llsec_table *table; 1653 struct wpan_dev *wpan_dev; 1654 int err; 1655 1656 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1657 if (err) 1658 return err; 1659 1660 if (!wpan_dev->netdev) { 1661 err = -EINVAL; 1662 goto out_err; 1663 } 1664 1665 rdev_lock_llsec_table(rdev, wpan_dev); 1666 rdev_get_llsec_table(rdev, wpan_dev, &table); 1667 1668 /* TODO make it like station dump */ 1669 if (cb->args[2]) 1670 goto out; 1671 1672 list_for_each_entry(dev, &table->devices, list) { 1673 if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL, 1674 NETLINK_CB(cb->skb).portid, 1675 cb->nlh->nlmsg_seq, NLM_F_MULTI, 1676 rdev, wpan_dev->netdev, dev) < 0) { 1677 /* TODO */ 1678 err = -EIO; 1679 rdev_unlock_llsec_table(rdev, wpan_dev); 1680 goto out_err; 1681 } 1682 } 1683 1684 cb->args[2] = 1; 1685 1686 out: 1687 rdev_unlock_llsec_table(rdev, wpan_dev); 1688 err = skb->len; 1689 out_err: 1690 nl802154_finish_wpan_dev_dump(rdev); 1691 1692 return err; 1693 } 1694 1695 static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = { 1696 [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 }, 1697 [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 }, 1698 [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 }, 1699 [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, 1700 [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 }, 1701 [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 }, 1702 }; 1703 1704 static int 1705 ieee802154_llsec_parse_device(struct nlattr *nla, 1706 struct ieee802154_llsec_device *dev) 1707 { 1708 struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; 1709 1710 if (!nla || nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, nla, 1711 nl802154_dev_policy)) 1712 return -EINVAL; 1713 1714 memset(dev, 0, sizeof(*dev)); 1715 1716 if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] || 1717 !attrs[NL802154_DEV_ATTR_PAN_ID] || 1718 !attrs[NL802154_DEV_ATTR_SHORT_ADDR] || 1719 !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] || 1720 !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] || 1721 !attrs[NL802154_DEV_ATTR_KEY_MODE]) 1722 return -EINVAL; 1723 1724 /* TODO be32 */ 1725 dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]); 1726 dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]); 1727 dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]); 1728 /* TODO rename hwaddr to extended_addr */ 1729 dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); 1730 dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]); 1731 dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]); 1732 1733 if (dev->key_mode > NL802154_DEVKEY_MAX || 1734 (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1)) 1735 return -EINVAL; 1736 1737 return 0; 1738 } 1739 1740 static int nl802154_add_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 ieee802154_llsec_device dev_desc; 1746 1747 if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE], 1748 &dev_desc) < 0) 1749 return -EINVAL; 1750 1751 return rdev_add_device(rdev, wpan_dev, &dev_desc); 1752 } 1753 1754 static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) 1755 { 1756 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1757 struct net_device *dev = info->user_ptr[1]; 1758 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1759 struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; 1760 __le64 extended_addr; 1761 1762 if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, 1763 info->attrs[NL802154_ATTR_SEC_DEVICE], 1764 nl802154_dev_policy)) 1765 return -EINVAL; 1766 1767 if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]) 1768 return -EINVAL; 1769 1770 extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]); 1771 return rdev_del_device(rdev, wpan_dev, extended_addr); 1772 } 1773 1774 static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid, 1775 u32 seq, int flags, 1776 struct cfg802154_registered_device *rdev, 1777 struct net_device *dev, __le64 extended_addr, 1778 const struct ieee802154_llsec_device_key *devkey) 1779 { 1780 void *hdr; 1781 struct nlattr *nl_devkey, *nl_key_id; 1782 1783 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1784 if (!hdr) 1785 return -1; 1786 1787 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1788 goto nla_put_failure; 1789 1790 nl_devkey = nla_nest_start(msg, NL802154_ATTR_SEC_DEVKEY); 1791 if (!nl_devkey) 1792 goto nla_put_failure; 1793 1794 if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR, 1795 extended_addr, NL802154_DEVKEY_ATTR_PAD) || 1796 nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER, 1797 devkey->frame_counter)) 1798 goto nla_put_failure; 1799 1800 nl_key_id = nla_nest_start(msg, NL802154_DEVKEY_ATTR_ID); 1801 if (!nl_key_id) 1802 goto nla_put_failure; 1803 1804 if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0) 1805 goto nla_put_failure; 1806 1807 nla_nest_end(msg, nl_key_id); 1808 nla_nest_end(msg, nl_devkey); 1809 genlmsg_end(msg, hdr); 1810 1811 return 0; 1812 1813 nla_put_failure: 1814 genlmsg_cancel(msg, hdr); 1815 return -EMSGSIZE; 1816 } 1817 1818 static int 1819 nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb) 1820 { 1821 struct cfg802154_registered_device *rdev = NULL; 1822 struct ieee802154_llsec_device_key *kpos; 1823 struct ieee802154_llsec_device *dpos; 1824 struct ieee802154_llsec_table *table; 1825 struct wpan_dev *wpan_dev; 1826 int err; 1827 1828 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1829 if (err) 1830 return err; 1831 1832 if (!wpan_dev->netdev) { 1833 err = -EINVAL; 1834 goto out_err; 1835 } 1836 1837 rdev_lock_llsec_table(rdev, wpan_dev); 1838 rdev_get_llsec_table(rdev, wpan_dev, &table); 1839 1840 /* TODO make it like station dump */ 1841 if (cb->args[2]) 1842 goto out; 1843 1844 /* TODO look if remove devkey and do some nested attribute */ 1845 list_for_each_entry(dpos, &table->devices, list) { 1846 list_for_each_entry(kpos, &dpos->keys, list) { 1847 if (nl802154_send_devkey(skb, 1848 NL802154_CMD_NEW_SEC_LEVEL, 1849 NETLINK_CB(cb->skb).portid, 1850 cb->nlh->nlmsg_seq, 1851 NLM_F_MULTI, rdev, 1852 wpan_dev->netdev, 1853 dpos->hwaddr, 1854 kpos) < 0) { 1855 /* TODO */ 1856 err = -EIO; 1857 rdev_unlock_llsec_table(rdev, wpan_dev); 1858 goto out_err; 1859 } 1860 } 1861 } 1862 1863 cb->args[2] = 1; 1864 1865 out: 1866 rdev_unlock_llsec_table(rdev, wpan_dev); 1867 err = skb->len; 1868 out_err: 1869 nl802154_finish_wpan_dev_dump(rdev); 1870 1871 return err; 1872 } 1873 1874 static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = { 1875 [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 }, 1876 [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 }, 1877 [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED }, 1878 }; 1879 1880 static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info) 1881 { 1882 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1883 struct net_device *dev = info->user_ptr[1]; 1884 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1885 struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; 1886 struct ieee802154_llsec_device_key key; 1887 __le64 extended_addr; 1888 1889 if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || 1890 nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, 1891 info->attrs[NL802154_ATTR_SEC_DEVKEY], 1892 nl802154_devkey_policy) < 0) 1893 return -EINVAL; 1894 1895 if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] || 1896 !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) 1897 return -EINVAL; 1898 1899 /* TODO change key.id ? */ 1900 if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], 1901 &key.key_id) < 0) 1902 return -ENOBUFS; 1903 1904 /* TODO be32 */ 1905 key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]); 1906 /* TODO change naming hwaddr -> extended_addr 1907 * check unique identifier short+pan OR extended_addr 1908 */ 1909 extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); 1910 return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key); 1911 } 1912 1913 static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info) 1914 { 1915 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1916 struct net_device *dev = info->user_ptr[1]; 1917 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1918 struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1]; 1919 struct ieee802154_llsec_device_key key; 1920 __le64 extended_addr; 1921 1922 if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, 1923 info->attrs[NL802154_ATTR_SEC_DEVKEY], 1924 nl802154_devkey_policy)) 1925 return -EINVAL; 1926 1927 if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) 1928 return -EINVAL; 1929 1930 /* TODO change key.id ? */ 1931 if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID], 1932 &key.key_id) < 0) 1933 return -ENOBUFS; 1934 1935 /* TODO change naming hwaddr -> extended_addr 1936 * check unique identifier short+pan OR extended_addr 1937 */ 1938 extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]); 1939 return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key); 1940 } 1941 1942 static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid, 1943 u32 seq, int flags, 1944 struct cfg802154_registered_device *rdev, 1945 struct net_device *dev, 1946 const struct ieee802154_llsec_seclevel *sl) 1947 { 1948 void *hdr; 1949 struct nlattr *nl_seclevel; 1950 1951 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 1952 if (!hdr) 1953 return -1; 1954 1955 if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex)) 1956 goto nla_put_failure; 1957 1958 nl_seclevel = nla_nest_start(msg, NL802154_ATTR_SEC_LEVEL); 1959 if (!nl_seclevel) 1960 goto nla_put_failure; 1961 1962 if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) || 1963 nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) || 1964 nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE, 1965 sl->device_override)) 1966 goto nla_put_failure; 1967 1968 if (sl->frame_type == NL802154_FRAME_CMD) { 1969 if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME, 1970 sl->cmd_frame_id)) 1971 goto nla_put_failure; 1972 } 1973 1974 nla_nest_end(msg, nl_seclevel); 1975 genlmsg_end(msg, hdr); 1976 1977 return 0; 1978 1979 nla_put_failure: 1980 genlmsg_cancel(msg, hdr); 1981 return -EMSGSIZE; 1982 } 1983 1984 static int 1985 nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb) 1986 { 1987 struct cfg802154_registered_device *rdev = NULL; 1988 struct ieee802154_llsec_seclevel *sl; 1989 struct ieee802154_llsec_table *table; 1990 struct wpan_dev *wpan_dev; 1991 int err; 1992 1993 err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev); 1994 if (err) 1995 return err; 1996 1997 if (!wpan_dev->netdev) { 1998 err = -EINVAL; 1999 goto out_err; 2000 } 2001 2002 rdev_lock_llsec_table(rdev, wpan_dev); 2003 rdev_get_llsec_table(rdev, wpan_dev, &table); 2004 2005 /* TODO make it like station dump */ 2006 if (cb->args[2]) 2007 goto out; 2008 2009 list_for_each_entry(sl, &table->security_levels, list) { 2010 if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL, 2011 NETLINK_CB(cb->skb).portid, 2012 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2013 rdev, wpan_dev->netdev, sl) < 0) { 2014 /* TODO */ 2015 err = -EIO; 2016 rdev_unlock_llsec_table(rdev, wpan_dev); 2017 goto out_err; 2018 } 2019 } 2020 2021 cb->args[2] = 1; 2022 2023 out: 2024 rdev_unlock_llsec_table(rdev, wpan_dev); 2025 err = skb->len; 2026 out_err: 2027 nl802154_finish_wpan_dev_dump(rdev); 2028 2029 return err; 2030 } 2031 2032 static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = { 2033 [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 }, 2034 [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 }, 2035 [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 }, 2036 [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 }, 2037 }; 2038 2039 static int 2040 llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl) 2041 { 2042 struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1]; 2043 2044 if (!nla || nla_parse_nested(attrs, NL802154_SECLEVEL_ATTR_MAX, nla, 2045 nl802154_seclevel_policy)) 2046 return -EINVAL; 2047 2048 memset(sl, 0, sizeof(*sl)); 2049 2050 if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] || 2051 !attrs[NL802154_SECLEVEL_ATTR_FRAME] || 2052 !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]) 2053 return -EINVAL; 2054 2055 sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]); 2056 sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]); 2057 sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]); 2058 if (sl->frame_type > NL802154_FRAME_MAX || 2059 (sl->device_override != 0 && sl->device_override != 1)) 2060 return -EINVAL; 2061 2062 if (sl->frame_type == NL802154_FRAME_CMD) { 2063 if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]) 2064 return -EINVAL; 2065 2066 sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]); 2067 if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX) 2068 return -EINVAL; 2069 } 2070 2071 return 0; 2072 } 2073 2074 static int nl802154_add_llsec_seclevel(struct sk_buff *skb, 2075 struct genl_info *info) 2076 { 2077 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 2078 struct net_device *dev = info->user_ptr[1]; 2079 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 2080 struct ieee802154_llsec_seclevel sl; 2081 2082 if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], 2083 &sl) < 0) 2084 return -EINVAL; 2085 2086 return rdev_add_seclevel(rdev, wpan_dev, &sl); 2087 } 2088 2089 static int nl802154_del_llsec_seclevel(struct sk_buff *skb, 2090 struct genl_info *info) 2091 { 2092 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 2093 struct net_device *dev = info->user_ptr[1]; 2094 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 2095 struct ieee802154_llsec_seclevel sl; 2096 2097 if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || 2098 llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], 2099 &sl) < 0) 2100 return -EINVAL; 2101 2102 return rdev_del_seclevel(rdev, wpan_dev, &sl); 2103 } 2104 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 2105 2106 #define NL802154_FLAG_NEED_WPAN_PHY 0x01 2107 #define NL802154_FLAG_NEED_NETDEV 0x02 2108 #define NL802154_FLAG_NEED_RTNL 0x04 2109 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08 2110 #define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\ 2111 NL802154_FLAG_CHECK_NETDEV_UP) 2112 #define NL802154_FLAG_NEED_WPAN_DEV 0x10 2113 #define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\ 2114 NL802154_FLAG_CHECK_NETDEV_UP) 2115 2116 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 2117 struct genl_info *info) 2118 { 2119 struct cfg802154_registered_device *rdev; 2120 struct wpan_dev *wpan_dev; 2121 struct net_device *dev; 2122 bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL; 2123 2124 if (rtnl) 2125 rtnl_lock(); 2126 2127 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) { 2128 rdev = cfg802154_get_dev_from_info(genl_info_net(info), info); 2129 if (IS_ERR(rdev)) { 2130 if (rtnl) 2131 rtnl_unlock(); 2132 return PTR_ERR(rdev); 2133 } 2134 info->user_ptr[0] = rdev; 2135 } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV || 2136 ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 2137 ASSERT_RTNL(); 2138 wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info), 2139 info->attrs); 2140 if (IS_ERR(wpan_dev)) { 2141 if (rtnl) 2142 rtnl_unlock(); 2143 return PTR_ERR(wpan_dev); 2144 } 2145 2146 dev = wpan_dev->netdev; 2147 rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy); 2148 2149 if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) { 2150 if (!dev) { 2151 if (rtnl) 2152 rtnl_unlock(); 2153 return -EINVAL; 2154 } 2155 2156 info->user_ptr[1] = dev; 2157 } else { 2158 info->user_ptr[1] = wpan_dev; 2159 } 2160 2161 if (dev) { 2162 if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP && 2163 !netif_running(dev)) { 2164 if (rtnl) 2165 rtnl_unlock(); 2166 return -ENETDOWN; 2167 } 2168 2169 dev_hold(dev); 2170 } 2171 2172 info->user_ptr[0] = rdev; 2173 } 2174 2175 return 0; 2176 } 2177 2178 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 2179 struct genl_info *info) 2180 { 2181 if (info->user_ptr[1]) { 2182 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 2183 struct wpan_dev *wpan_dev = info->user_ptr[1]; 2184 2185 if (wpan_dev->netdev) 2186 dev_put(wpan_dev->netdev); 2187 } else { 2188 dev_put(info->user_ptr[1]); 2189 } 2190 } 2191 2192 if (ops->internal_flags & NL802154_FLAG_NEED_RTNL) 2193 rtnl_unlock(); 2194 } 2195 2196 static const struct genl_ops nl802154_ops[] = { 2197 { 2198 .cmd = NL802154_CMD_GET_WPAN_PHY, 2199 .doit = nl802154_get_wpan_phy, 2200 .dumpit = nl802154_dump_wpan_phy, 2201 .done = nl802154_dump_wpan_phy_done, 2202 .policy = nl802154_policy, 2203 /* can be retrieved by unprivileged users */ 2204 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2205 NL802154_FLAG_NEED_RTNL, 2206 }, 2207 { 2208 .cmd = NL802154_CMD_GET_INTERFACE, 2209 .doit = nl802154_get_interface, 2210 .dumpit = nl802154_dump_interface, 2211 .policy = nl802154_policy, 2212 /* can be retrieved by unprivileged users */ 2213 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 2214 NL802154_FLAG_NEED_RTNL, 2215 }, 2216 { 2217 .cmd = NL802154_CMD_NEW_INTERFACE, 2218 .doit = nl802154_new_interface, 2219 .policy = nl802154_policy, 2220 .flags = GENL_ADMIN_PERM, 2221 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2222 NL802154_FLAG_NEED_RTNL, 2223 }, 2224 { 2225 .cmd = NL802154_CMD_DEL_INTERFACE, 2226 .doit = nl802154_del_interface, 2227 .policy = nl802154_policy, 2228 .flags = GENL_ADMIN_PERM, 2229 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 2230 NL802154_FLAG_NEED_RTNL, 2231 }, 2232 { 2233 .cmd = NL802154_CMD_SET_CHANNEL, 2234 .doit = nl802154_set_channel, 2235 .policy = nl802154_policy, 2236 .flags = GENL_ADMIN_PERM, 2237 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2238 NL802154_FLAG_NEED_RTNL, 2239 }, 2240 { 2241 .cmd = NL802154_CMD_SET_CCA_MODE, 2242 .doit = nl802154_set_cca_mode, 2243 .policy = nl802154_policy, 2244 .flags = GENL_ADMIN_PERM, 2245 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2246 NL802154_FLAG_NEED_RTNL, 2247 }, 2248 { 2249 .cmd = NL802154_CMD_SET_CCA_ED_LEVEL, 2250 .doit = nl802154_set_cca_ed_level, 2251 .policy = nl802154_policy, 2252 .flags = GENL_ADMIN_PERM, 2253 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2254 NL802154_FLAG_NEED_RTNL, 2255 }, 2256 { 2257 .cmd = NL802154_CMD_SET_TX_POWER, 2258 .doit = nl802154_set_tx_power, 2259 .policy = nl802154_policy, 2260 .flags = GENL_ADMIN_PERM, 2261 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 2262 NL802154_FLAG_NEED_RTNL, 2263 }, 2264 { 2265 .cmd = NL802154_CMD_SET_PAN_ID, 2266 .doit = nl802154_set_pan_id, 2267 .policy = nl802154_policy, 2268 .flags = GENL_ADMIN_PERM, 2269 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2270 NL802154_FLAG_NEED_RTNL, 2271 }, 2272 { 2273 .cmd = NL802154_CMD_SET_SHORT_ADDR, 2274 .doit = nl802154_set_short_addr, 2275 .policy = nl802154_policy, 2276 .flags = GENL_ADMIN_PERM, 2277 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2278 NL802154_FLAG_NEED_RTNL, 2279 }, 2280 { 2281 .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT, 2282 .doit = nl802154_set_backoff_exponent, 2283 .policy = nl802154_policy, 2284 .flags = GENL_ADMIN_PERM, 2285 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2286 NL802154_FLAG_NEED_RTNL, 2287 }, 2288 { 2289 .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS, 2290 .doit = nl802154_set_max_csma_backoffs, 2291 .policy = nl802154_policy, 2292 .flags = GENL_ADMIN_PERM, 2293 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2294 NL802154_FLAG_NEED_RTNL, 2295 }, 2296 { 2297 .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES, 2298 .doit = nl802154_set_max_frame_retries, 2299 .policy = nl802154_policy, 2300 .flags = GENL_ADMIN_PERM, 2301 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2302 NL802154_FLAG_NEED_RTNL, 2303 }, 2304 { 2305 .cmd = NL802154_CMD_SET_LBT_MODE, 2306 .doit = nl802154_set_lbt_mode, 2307 .policy = nl802154_policy, 2308 .flags = GENL_ADMIN_PERM, 2309 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2310 NL802154_FLAG_NEED_RTNL, 2311 }, 2312 { 2313 .cmd = NL802154_CMD_SET_ACKREQ_DEFAULT, 2314 .doit = nl802154_set_ackreq_default, 2315 .policy = nl802154_policy, 2316 .flags = GENL_ADMIN_PERM, 2317 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2318 NL802154_FLAG_NEED_RTNL, 2319 }, 2320 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL 2321 { 2322 .cmd = NL802154_CMD_SET_SEC_PARAMS, 2323 .doit = nl802154_set_llsec_params, 2324 .policy = nl802154_policy, 2325 .flags = GENL_ADMIN_PERM, 2326 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2327 NL802154_FLAG_NEED_RTNL, 2328 }, 2329 { 2330 .cmd = NL802154_CMD_GET_SEC_KEY, 2331 /* TODO .doit by matching key id? */ 2332 .dumpit = nl802154_dump_llsec_key, 2333 .policy = nl802154_policy, 2334 .flags = GENL_ADMIN_PERM, 2335 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2336 NL802154_FLAG_NEED_RTNL, 2337 }, 2338 { 2339 .cmd = NL802154_CMD_NEW_SEC_KEY, 2340 .doit = nl802154_add_llsec_key, 2341 .policy = nl802154_policy, 2342 .flags = GENL_ADMIN_PERM, 2343 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2344 NL802154_FLAG_NEED_RTNL, 2345 }, 2346 { 2347 .cmd = NL802154_CMD_DEL_SEC_KEY, 2348 .doit = nl802154_del_llsec_key, 2349 .policy = nl802154_policy, 2350 .flags = GENL_ADMIN_PERM, 2351 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2352 NL802154_FLAG_NEED_RTNL, 2353 }, 2354 /* TODO unique identifier must short+pan OR extended_addr */ 2355 { 2356 .cmd = NL802154_CMD_GET_SEC_DEV, 2357 /* TODO .doit by matching extended_addr? */ 2358 .dumpit = nl802154_dump_llsec_dev, 2359 .policy = nl802154_policy, 2360 .flags = GENL_ADMIN_PERM, 2361 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2362 NL802154_FLAG_NEED_RTNL, 2363 }, 2364 { 2365 .cmd = NL802154_CMD_NEW_SEC_DEV, 2366 .doit = nl802154_add_llsec_dev, 2367 .policy = nl802154_policy, 2368 .flags = GENL_ADMIN_PERM, 2369 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2370 NL802154_FLAG_NEED_RTNL, 2371 }, 2372 { 2373 .cmd = NL802154_CMD_DEL_SEC_DEV, 2374 .doit = nl802154_del_llsec_dev, 2375 .policy = nl802154_policy, 2376 .flags = GENL_ADMIN_PERM, 2377 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2378 NL802154_FLAG_NEED_RTNL, 2379 }, 2380 /* TODO remove complete devkey, put it as nested? */ 2381 { 2382 .cmd = NL802154_CMD_GET_SEC_DEVKEY, 2383 /* TODO doit by matching ??? */ 2384 .dumpit = nl802154_dump_llsec_devkey, 2385 .policy = nl802154_policy, 2386 .flags = GENL_ADMIN_PERM, 2387 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2388 NL802154_FLAG_NEED_RTNL, 2389 }, 2390 { 2391 .cmd = NL802154_CMD_NEW_SEC_DEVKEY, 2392 .doit = nl802154_add_llsec_devkey, 2393 .policy = nl802154_policy, 2394 .flags = GENL_ADMIN_PERM, 2395 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2396 NL802154_FLAG_NEED_RTNL, 2397 }, 2398 { 2399 .cmd = NL802154_CMD_DEL_SEC_DEVKEY, 2400 .doit = nl802154_del_llsec_devkey, 2401 .policy = nl802154_policy, 2402 .flags = GENL_ADMIN_PERM, 2403 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2404 NL802154_FLAG_NEED_RTNL, 2405 }, 2406 { 2407 .cmd = NL802154_CMD_GET_SEC_LEVEL, 2408 /* TODO .doit by matching frame_type? */ 2409 .dumpit = nl802154_dump_llsec_seclevel, 2410 .policy = nl802154_policy, 2411 .flags = GENL_ADMIN_PERM, 2412 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2413 NL802154_FLAG_NEED_RTNL, 2414 }, 2415 { 2416 .cmd = NL802154_CMD_NEW_SEC_LEVEL, 2417 .doit = nl802154_add_llsec_seclevel, 2418 .policy = nl802154_policy, 2419 .flags = GENL_ADMIN_PERM, 2420 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2421 NL802154_FLAG_NEED_RTNL, 2422 }, 2423 { 2424 .cmd = NL802154_CMD_DEL_SEC_LEVEL, 2425 /* TODO match frame_type only? */ 2426 .doit = nl802154_del_llsec_seclevel, 2427 .policy = nl802154_policy, 2428 .flags = GENL_ADMIN_PERM, 2429 .internal_flags = NL802154_FLAG_NEED_NETDEV | 2430 NL802154_FLAG_NEED_RTNL, 2431 }, 2432 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ 2433 }; 2434 2435 /* initialisation/exit functions */ 2436 int nl802154_init(void) 2437 { 2438 return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops, 2439 nl802154_mcgrps); 2440 } 2441 2442 void nl802154_exit(void) 2443 { 2444 genl_unregister_family(&nl802154_fam); 2445 } 2446