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