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