1 /* This program is free software; you can redistribute it and/or modify 2 * it under the terms of the GNU General Public License version 2 3 * as published by the Free Software Foundation. 4 * 5 * This program is distributed in the hope that it will be useful, 6 * but WITHOUT ANY WARRANTY; without even the implied warranty of 7 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8 * GNU General Public License for more details. 9 * 10 * Authors: 11 * Alexander Aring <aar@pengutronix.de> 12 * 13 * Based on: net/wireless/nl80211.c 14 */ 15 16 #include <linux/rtnetlink.h> 17 18 #include <net/cfg802154.h> 19 #include <net/genetlink.h> 20 #include <net/mac802154.h> 21 #include <net/netlink.h> 22 #include <net/nl802154.h> 23 #include <net/sock.h> 24 25 #include "nl802154.h" 26 #include "rdev-ops.h" 27 #include "core.h" 28 29 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 30 struct genl_info *info); 31 32 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 33 struct genl_info *info); 34 35 /* the netlink family */ 36 static struct genl_family nl802154_fam = { 37 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ 38 .name = NL802154_GENL_NAME, /* have users key off the name instead */ 39 .hdrsize = 0, /* no private header */ 40 .version = 1, /* no particular meaning now */ 41 .maxattr = NL802154_ATTR_MAX, 42 .netnsok = true, 43 .pre_doit = nl802154_pre_doit, 44 .post_doit = nl802154_post_doit, 45 }; 46 47 /* multicast groups */ 48 enum nl802154_multicast_groups { 49 NL802154_MCGRP_CONFIG, 50 }; 51 52 static const struct genl_multicast_group nl802154_mcgrps[] = { 53 [NL802154_MCGRP_CONFIG] = { .name = "config", }, 54 }; 55 56 /* returns ERR_PTR values */ 57 static struct wpan_dev * 58 __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs) 59 { 60 struct cfg802154_registered_device *rdev; 61 struct wpan_dev *result = NULL; 62 bool have_ifidx = attrs[NL802154_ATTR_IFINDEX]; 63 bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV]; 64 u64 wpan_dev_id; 65 int wpan_phy_idx = -1; 66 int ifidx = -1; 67 68 ASSERT_RTNL(); 69 70 if (!have_ifidx && !have_wpan_dev_id) 71 return ERR_PTR(-EINVAL); 72 73 if (have_ifidx) 74 ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]); 75 if (have_wpan_dev_id) { 76 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]); 77 wpan_phy_idx = wpan_dev_id >> 32; 78 } 79 80 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 81 struct wpan_dev *wpan_dev; 82 83 /* TODO netns compare */ 84 85 if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx) 86 continue; 87 88 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { 89 if (have_ifidx && wpan_dev->netdev && 90 wpan_dev->netdev->ifindex == ifidx) { 91 result = wpan_dev; 92 break; 93 } 94 if (have_wpan_dev_id && 95 wpan_dev->identifier == (u32)wpan_dev_id) { 96 result = wpan_dev; 97 break; 98 } 99 } 100 101 if (result) 102 break; 103 } 104 105 if (result) 106 return result; 107 108 return ERR_PTR(-ENODEV); 109 } 110 111 static struct cfg802154_registered_device * 112 __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs) 113 { 114 struct cfg802154_registered_device *rdev = NULL, *tmp; 115 struct net_device *netdev; 116 117 ASSERT_RTNL(); 118 119 if (!attrs[NL802154_ATTR_WPAN_PHY] && 120 !attrs[NL802154_ATTR_IFINDEX] && 121 !attrs[NL802154_ATTR_WPAN_DEV]) 122 return ERR_PTR(-EINVAL); 123 124 if (attrs[NL802154_ATTR_WPAN_PHY]) 125 rdev = cfg802154_rdev_by_wpan_phy_idx( 126 nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY])); 127 128 if (attrs[NL802154_ATTR_WPAN_DEV]) { 129 u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]); 130 struct wpan_dev *wpan_dev; 131 bool found = false; 132 133 tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32); 134 if (tmp) { 135 /* make sure wpan_dev exists */ 136 list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) { 137 if (wpan_dev->identifier != (u32)wpan_dev_id) 138 continue; 139 found = true; 140 break; 141 } 142 143 if (!found) 144 tmp = NULL; 145 146 if (rdev && tmp != rdev) 147 return ERR_PTR(-EINVAL); 148 rdev = tmp; 149 } 150 } 151 152 if (attrs[NL802154_ATTR_IFINDEX]) { 153 int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]); 154 155 netdev = __dev_get_by_index(netns, ifindex); 156 if (netdev) { 157 if (netdev->ieee802154_ptr) 158 tmp = wpan_phy_to_rdev( 159 netdev->ieee802154_ptr->wpan_phy); 160 else 161 tmp = NULL; 162 163 /* not wireless device -- return error */ 164 if (!tmp) 165 return ERR_PTR(-EINVAL); 166 167 /* mismatch -- return error */ 168 if (rdev && tmp != rdev) 169 return ERR_PTR(-EINVAL); 170 171 rdev = tmp; 172 } 173 } 174 175 if (!rdev) 176 return ERR_PTR(-ENODEV); 177 178 /* TODO netns compare */ 179 180 return rdev; 181 } 182 183 /* This function returns a pointer to the driver 184 * that the genl_info item that is passed refers to. 185 * 186 * The result of this can be a PTR_ERR and hence must 187 * be checked with IS_ERR() for errors. 188 */ 189 static struct cfg802154_registered_device * 190 cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info) 191 { 192 return __cfg802154_rdev_from_attrs(netns, info->attrs); 193 } 194 195 /* policy for the attributes */ 196 static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = { 197 [NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 }, 198 [NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING, 199 .len = 20-1 }, 200 201 [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 }, 202 [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 }, 203 [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, 204 205 [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 }, 206 207 [NL802154_ATTR_PAGE] = { .type = NLA_U8, }, 208 [NL802154_ATTR_CHANNEL] = { .type = NLA_U8, }, 209 210 [NL802154_ATTR_TX_POWER] = { .type = NLA_S32, }, 211 212 [NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, }, 213 [NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, }, 214 [NL802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, }, 215 216 [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, }, 217 218 [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, }, 219 [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 }, 220 [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, 221 222 [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, }, 223 [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, }, 224 [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, }, 225 226 [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, }, 227 228 [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, }, 229 230 [NL802154_ATTR_WPAN_PHY_CAPS] = { .type = NLA_NESTED }, 231 232 [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED }, 233 }; 234 235 /* message building helper */ 236 static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq, 237 int flags, u8 cmd) 238 { 239 /* since there is no private header just add the generic one */ 240 return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd); 241 } 242 243 static int 244 nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask) 245 { 246 struct nlattr *nl_flags = nla_nest_start(msg, attr); 247 int i; 248 249 if (!nl_flags) 250 return -ENOBUFS; 251 252 i = 0; 253 while (mask) { 254 if ((mask & 1) && nla_put_flag(msg, i)) 255 return -ENOBUFS; 256 257 mask >>= 1; 258 i++; 259 } 260 261 nla_nest_end(msg, nl_flags); 262 return 0; 263 } 264 265 static int 266 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev, 267 struct sk_buff *msg) 268 { 269 struct nlattr *nl_page; 270 unsigned long page; 271 272 nl_page = nla_nest_start(msg, NL802154_ATTR_CHANNELS_SUPPORTED); 273 if (!nl_page) 274 return -ENOBUFS; 275 276 for (page = 0; page <= IEEE802154_MAX_PAGE; page++) { 277 if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL, 278 rdev->wpan_phy.supported.channels[page])) 279 return -ENOBUFS; 280 } 281 nla_nest_end(msg, nl_page); 282 283 return 0; 284 } 285 286 static int 287 nl802154_put_capabilities(struct sk_buff *msg, 288 struct cfg802154_registered_device *rdev) 289 { 290 const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported; 291 struct nlattr *nl_caps, *nl_channels; 292 int i; 293 294 nl_caps = nla_nest_start(msg, NL802154_ATTR_WPAN_PHY_CAPS); 295 if (!nl_caps) 296 return -ENOBUFS; 297 298 nl_channels = nla_nest_start(msg, NL802154_CAP_ATTR_CHANNELS); 299 if (!nl_channels) 300 return -ENOBUFS; 301 302 for (i = 0; i <= IEEE802154_MAX_PAGE; i++) { 303 if (caps->channels[i]) { 304 if (nl802154_put_flags(msg, i, caps->channels[i])) 305 return -ENOBUFS; 306 } 307 } 308 309 nla_nest_end(msg, nl_channels); 310 311 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) { 312 struct nlattr *nl_ed_lvls; 313 314 nl_ed_lvls = nla_nest_start(msg, 315 NL802154_CAP_ATTR_CCA_ED_LEVELS); 316 if (!nl_ed_lvls) 317 return -ENOBUFS; 318 319 for (i = 0; i < caps->cca_ed_levels_size; i++) { 320 if (nla_put_s32(msg, i, caps->cca_ed_levels[i])) 321 return -ENOBUFS; 322 } 323 324 nla_nest_end(msg, nl_ed_lvls); 325 } 326 327 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) { 328 struct nlattr *nl_tx_pwrs; 329 330 nl_tx_pwrs = nla_nest_start(msg, NL802154_CAP_ATTR_TX_POWERS); 331 if (!nl_tx_pwrs) 332 return -ENOBUFS; 333 334 for (i = 0; i < caps->tx_powers_size; i++) { 335 if (nla_put_s32(msg, i, caps->tx_powers[i])) 336 return -ENOBUFS; 337 } 338 339 nla_nest_end(msg, nl_tx_pwrs); 340 } 341 342 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) { 343 if (nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_MODES, 344 caps->cca_modes) || 345 nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_OPTS, 346 caps->cca_opts)) 347 return -ENOBUFS; 348 } 349 350 if (nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MINBE, caps->min_minbe) || 351 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MINBE, caps->max_minbe) || 352 nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MAXBE, caps->min_maxbe) || 353 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MAXBE, caps->max_maxbe) || 354 nla_put_u8(msg, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS, 355 caps->min_csma_backoffs) || 356 nla_put_u8(msg, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS, 357 caps->max_csma_backoffs) || 358 nla_put_s8(msg, NL802154_CAP_ATTR_MIN_FRAME_RETRIES, 359 caps->min_frame_retries) || 360 nla_put_s8(msg, NL802154_CAP_ATTR_MAX_FRAME_RETRIES, 361 caps->max_frame_retries) || 362 nl802154_put_flags(msg, NL802154_CAP_ATTR_IFTYPES, 363 caps->iftypes) || 364 nla_put_u32(msg, NL802154_CAP_ATTR_LBT, caps->lbt)) 365 return -ENOBUFS; 366 367 nla_nest_end(msg, nl_caps); 368 369 return 0; 370 } 371 372 static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev, 373 enum nl802154_commands cmd, 374 struct sk_buff *msg, u32 portid, u32 seq, 375 int flags) 376 { 377 struct nlattr *nl_cmds; 378 void *hdr; 379 int i; 380 381 hdr = nl802154hdr_put(msg, portid, seq, flags, cmd); 382 if (!hdr) 383 return -ENOBUFS; 384 385 if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || 386 nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME, 387 wpan_phy_name(&rdev->wpan_phy)) || 388 nla_put_u32(msg, NL802154_ATTR_GENERATION, 389 cfg802154_rdev_list_generation)) 390 goto nla_put_failure; 391 392 if (cmd != NL802154_CMD_NEW_WPAN_PHY) 393 goto finish; 394 395 /* DUMP PHY PIB */ 396 397 /* current channel settings */ 398 if (nla_put_u8(msg, NL802154_ATTR_PAGE, 399 rdev->wpan_phy.current_page) || 400 nla_put_u8(msg, NL802154_ATTR_CHANNEL, 401 rdev->wpan_phy.current_channel)) 402 goto nla_put_failure; 403 404 /* TODO remove this behaviour, we still keep support it for a while 405 * so users can change the behaviour to the new one. 406 */ 407 if (nl802154_send_wpan_phy_channels(rdev, msg)) 408 goto nla_put_failure; 409 410 /* cca mode */ 411 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) { 412 if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE, 413 rdev->wpan_phy.cca.mode)) 414 goto nla_put_failure; 415 416 if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) { 417 if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT, 418 rdev->wpan_phy.cca.opt)) 419 goto nla_put_failure; 420 } 421 } 422 423 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) { 424 if (nla_put_s32(msg, NL802154_ATTR_TX_POWER, 425 rdev->wpan_phy.transmit_power)) 426 goto nla_put_failure; 427 } 428 429 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) { 430 if (nla_put_s32(msg, NL802154_ATTR_CCA_ED_LEVEL, 431 rdev->wpan_phy.cca_ed_level)) 432 goto nla_put_failure; 433 } 434 435 if (nl802154_put_capabilities(msg, rdev)) 436 goto nla_put_failure; 437 438 nl_cmds = nla_nest_start(msg, NL802154_ATTR_SUPPORTED_COMMANDS); 439 if (!nl_cmds) 440 goto nla_put_failure; 441 442 i = 0; 443 #define CMD(op, n) \ 444 do { \ 445 if (rdev->ops->op) { \ 446 i++; \ 447 if (nla_put_u32(msg, i, NL802154_CMD_ ## n)) \ 448 goto nla_put_failure; \ 449 } \ 450 } while (0) 451 452 CMD(add_virtual_intf, NEW_INTERFACE); 453 CMD(del_virtual_intf, DEL_INTERFACE); 454 CMD(set_channel, SET_CHANNEL); 455 CMD(set_pan_id, SET_PAN_ID); 456 CMD(set_short_addr, SET_SHORT_ADDR); 457 CMD(set_backoff_exponent, SET_BACKOFF_EXPONENT); 458 CMD(set_max_csma_backoffs, SET_MAX_CSMA_BACKOFFS); 459 CMD(set_max_frame_retries, SET_MAX_FRAME_RETRIES); 460 CMD(set_lbt_mode, SET_LBT_MODE); 461 462 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) 463 CMD(set_tx_power, SET_TX_POWER); 464 465 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) 466 CMD(set_cca_ed_level, SET_CCA_ED_LEVEL); 467 468 if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) 469 CMD(set_cca_mode, SET_CCA_MODE); 470 471 #undef CMD 472 nla_nest_end(msg, nl_cmds); 473 474 finish: 475 genlmsg_end(msg, hdr); 476 return 0; 477 478 nla_put_failure: 479 genlmsg_cancel(msg, hdr); 480 return -EMSGSIZE; 481 } 482 483 struct nl802154_dump_wpan_phy_state { 484 s64 filter_wpan_phy; 485 long start; 486 487 }; 488 489 static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb, 490 struct netlink_callback *cb, 491 struct nl802154_dump_wpan_phy_state *state) 492 { 493 struct nlattr **tb = nl802154_fam.attrbuf; 494 int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize, 495 tb, nl802154_fam.maxattr, nl802154_policy); 496 497 /* TODO check if we can handle error here, 498 * we have no backward compatibility 499 */ 500 if (ret) 501 return 0; 502 503 if (tb[NL802154_ATTR_WPAN_PHY]) 504 state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]); 505 if (tb[NL802154_ATTR_WPAN_DEV]) 506 state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32; 507 if (tb[NL802154_ATTR_IFINDEX]) { 508 struct net_device *netdev; 509 struct cfg802154_registered_device *rdev; 510 int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]); 511 512 /* TODO netns */ 513 netdev = __dev_get_by_index(&init_net, ifidx); 514 if (!netdev) 515 return -ENODEV; 516 if (netdev->ieee802154_ptr) { 517 rdev = wpan_phy_to_rdev( 518 netdev->ieee802154_ptr->wpan_phy); 519 state->filter_wpan_phy = rdev->wpan_phy_idx; 520 } 521 } 522 523 return 0; 524 } 525 526 static int 527 nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb) 528 { 529 int idx = 0, ret; 530 struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0]; 531 struct cfg802154_registered_device *rdev; 532 533 rtnl_lock(); 534 if (!state) { 535 state = kzalloc(sizeof(*state), GFP_KERNEL); 536 if (!state) { 537 rtnl_unlock(); 538 return -ENOMEM; 539 } 540 state->filter_wpan_phy = -1; 541 ret = nl802154_dump_wpan_phy_parse(skb, cb, state); 542 if (ret) { 543 kfree(state); 544 rtnl_unlock(); 545 return ret; 546 } 547 cb->args[0] = (long)state; 548 } 549 550 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 551 /* TODO net ns compare */ 552 if (++idx <= state->start) 553 continue; 554 if (state->filter_wpan_phy != -1 && 555 state->filter_wpan_phy != rdev->wpan_phy_idx) 556 continue; 557 /* attempt to fit multiple wpan_phy data chunks into the skb */ 558 ret = nl802154_send_wpan_phy(rdev, 559 NL802154_CMD_NEW_WPAN_PHY, 560 skb, 561 NETLINK_CB(cb->skb).portid, 562 cb->nlh->nlmsg_seq, NLM_F_MULTI); 563 if (ret < 0) { 564 if ((ret == -ENOBUFS || ret == -EMSGSIZE) && 565 !skb->len && cb->min_dump_alloc < 4096) { 566 cb->min_dump_alloc = 4096; 567 rtnl_unlock(); 568 return 1; 569 } 570 idx--; 571 break; 572 } 573 break; 574 } 575 rtnl_unlock(); 576 577 state->start = idx; 578 579 return skb->len; 580 } 581 582 static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb) 583 { 584 kfree((void *)cb->args[0]); 585 return 0; 586 } 587 588 static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info) 589 { 590 struct sk_buff *msg; 591 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 592 593 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 594 if (!msg) 595 return -ENOMEM; 596 597 if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg, 598 info->snd_portid, info->snd_seq, 0) < 0) { 599 nlmsg_free(msg); 600 return -ENOBUFS; 601 } 602 603 return genlmsg_reply(msg, info); 604 } 605 606 static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev) 607 { 608 return (u64)wpan_dev->identifier | 609 ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32); 610 } 611 612 static int 613 nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, 614 struct cfg802154_registered_device *rdev, 615 struct wpan_dev *wpan_dev) 616 { 617 struct net_device *dev = wpan_dev->netdev; 618 void *hdr; 619 620 hdr = nl802154hdr_put(msg, portid, seq, flags, 621 NL802154_CMD_NEW_INTERFACE); 622 if (!hdr) 623 return -1; 624 625 if (dev && 626 (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) || 627 nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name))) 628 goto nla_put_failure; 629 630 if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) || 631 nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) || 632 nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) || 633 nla_put_u32(msg, NL802154_ATTR_GENERATION, 634 rdev->devlist_generation ^ 635 (cfg802154_rdev_list_generation << 2))) 636 goto nla_put_failure; 637 638 /* address settings */ 639 if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR, 640 wpan_dev->extended_addr) || 641 nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR, 642 wpan_dev->short_addr) || 643 nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id)) 644 goto nla_put_failure; 645 646 /* ARET handling */ 647 if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES, 648 wpan_dev->frame_retries) || 649 nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) || 650 nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS, 651 wpan_dev->csma_retries) || 652 nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be)) 653 goto nla_put_failure; 654 655 /* listen before transmit */ 656 if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt)) 657 goto nla_put_failure; 658 659 genlmsg_end(msg, hdr); 660 return 0; 661 662 nla_put_failure: 663 genlmsg_cancel(msg, hdr); 664 return -EMSGSIZE; 665 } 666 667 static int 668 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) 669 { 670 int wp_idx = 0; 671 int if_idx = 0; 672 int wp_start = cb->args[0]; 673 int if_start = cb->args[1]; 674 struct cfg802154_registered_device *rdev; 675 struct wpan_dev *wpan_dev; 676 677 rtnl_lock(); 678 list_for_each_entry(rdev, &cfg802154_rdev_list, list) { 679 /* TODO netns compare */ 680 if (wp_idx < wp_start) { 681 wp_idx++; 682 continue; 683 } 684 if_idx = 0; 685 686 list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) { 687 if (if_idx < if_start) { 688 if_idx++; 689 continue; 690 } 691 if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid, 692 cb->nlh->nlmsg_seq, NLM_F_MULTI, 693 rdev, wpan_dev) < 0) { 694 goto out; 695 } 696 if_idx++; 697 } 698 699 wp_idx++; 700 } 701 out: 702 rtnl_unlock(); 703 704 cb->args[0] = wp_idx; 705 cb->args[1] = if_idx; 706 707 return skb->len; 708 } 709 710 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info) 711 { 712 struct sk_buff *msg; 713 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 714 struct wpan_dev *wdev = info->user_ptr[1]; 715 716 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 717 if (!msg) 718 return -ENOMEM; 719 720 if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0, 721 rdev, wdev) < 0) { 722 nlmsg_free(msg); 723 return -ENOBUFS; 724 } 725 726 return genlmsg_reply(msg, info); 727 } 728 729 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info) 730 { 731 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 732 enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC; 733 __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL); 734 735 /* TODO avoid failing a new interface 736 * creation due to pending removal? 737 */ 738 739 if (!info->attrs[NL802154_ATTR_IFNAME]) 740 return -EINVAL; 741 742 if (info->attrs[NL802154_ATTR_IFTYPE]) { 743 type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]); 744 if (type > NL802154_IFTYPE_MAX || 745 !(rdev->wpan_phy.supported.iftypes & BIT(type))) 746 return -EINVAL; 747 } 748 749 /* TODO add nla_get_le64 to netlink */ 750 if (info->attrs[NL802154_ATTR_EXTENDED_ADDR]) 751 extended_addr = (__force __le64)nla_get_u64( 752 info->attrs[NL802154_ATTR_EXTENDED_ADDR]); 753 754 if (!rdev->ops->add_virtual_intf) 755 return -EOPNOTSUPP; 756 757 return rdev_add_virtual_intf(rdev, 758 nla_data(info->attrs[NL802154_ATTR_IFNAME]), 759 NET_NAME_USER, type, extended_addr); 760 } 761 762 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info) 763 { 764 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 765 struct wpan_dev *wpan_dev = info->user_ptr[1]; 766 767 if (!rdev->ops->del_virtual_intf) 768 return -EOPNOTSUPP; 769 770 /* If we remove a wpan device without a netdev then clear 771 * user_ptr[1] so that nl802154_post_doit won't dereference it 772 * to check if it needs to do dev_put(). Otherwise it crashes 773 * since the wpan_dev has been freed, unlike with a netdev where 774 * we need the dev_put() for the netdev to really be freed. 775 */ 776 if (!wpan_dev->netdev) 777 info->user_ptr[1] = NULL; 778 779 return rdev_del_virtual_intf(rdev, wpan_dev); 780 } 781 782 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info) 783 { 784 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 785 u8 channel, page; 786 787 if (!info->attrs[NL802154_ATTR_PAGE] || 788 !info->attrs[NL802154_ATTR_CHANNEL]) 789 return -EINVAL; 790 791 page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]); 792 channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]); 793 794 /* check 802.15.4 constraints */ 795 if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL || 796 !(rdev->wpan_phy.supported.channels[page] & BIT(channel))) 797 return -EINVAL; 798 799 return rdev_set_channel(rdev, page, channel); 800 } 801 802 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info) 803 { 804 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 805 struct wpan_phy_cca cca; 806 807 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)) 808 return -EOPNOTSUPP; 809 810 if (!info->attrs[NL802154_ATTR_CCA_MODE]) 811 return -EINVAL; 812 813 cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]); 814 /* checking 802.15.4 constraints */ 815 if (cca.mode < NL802154_CCA_ENERGY || 816 cca.mode > NL802154_CCA_ATTR_MAX || 817 !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode))) 818 return -EINVAL; 819 820 if (cca.mode == NL802154_CCA_ENERGY_CARRIER) { 821 if (!info->attrs[NL802154_ATTR_CCA_OPT]) 822 return -EINVAL; 823 824 cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]); 825 if (cca.opt > NL802154_CCA_OPT_ATTR_MAX || 826 !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt))) 827 return -EINVAL; 828 } 829 830 return rdev_set_cca_mode(rdev, &cca); 831 } 832 833 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info) 834 { 835 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 836 s32 ed_level; 837 int i; 838 839 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)) 840 return -EOPNOTSUPP; 841 842 if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL]) 843 return -EINVAL; 844 845 ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]); 846 847 for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) { 848 if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i]) 849 return rdev_set_cca_ed_level(rdev, ed_level); 850 } 851 852 return -EINVAL; 853 } 854 855 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info) 856 { 857 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 858 s32 power; 859 int i; 860 861 if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)) 862 return -EOPNOTSUPP; 863 864 if (!info->attrs[NL802154_ATTR_TX_POWER]) 865 return -EINVAL; 866 867 power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]); 868 869 for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) { 870 if (power == rdev->wpan_phy.supported.tx_powers[i]) 871 return rdev_set_tx_power(rdev, power); 872 } 873 874 return -EINVAL; 875 } 876 877 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info) 878 { 879 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 880 struct net_device *dev = info->user_ptr[1]; 881 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 882 __le16 pan_id; 883 884 /* conflict here while tx/rx calls */ 885 if (netif_running(dev)) 886 return -EBUSY; 887 888 /* don't change address fields on monitor */ 889 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 890 !info->attrs[NL802154_ATTR_PAN_ID]) 891 return -EINVAL; 892 893 pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]); 894 895 /* TODO 896 * I am not sure about to check here on broadcast pan_id. 897 * Broadcast is a valid setting, comment from 802.15.4: 898 * If this value is 0xffff, the device is not associated. 899 * 900 * This could useful to simple deassociate an device. 901 */ 902 if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST)) 903 return -EINVAL; 904 905 return rdev_set_pan_id(rdev, wpan_dev, pan_id); 906 } 907 908 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info) 909 { 910 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 911 struct net_device *dev = info->user_ptr[1]; 912 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 913 __le16 short_addr; 914 915 /* conflict here while tx/rx calls */ 916 if (netif_running(dev)) 917 return -EBUSY; 918 919 /* don't change address fields on monitor */ 920 if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR || 921 !info->attrs[NL802154_ATTR_SHORT_ADDR]) 922 return -EINVAL; 923 924 short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]); 925 926 /* TODO 927 * I am not sure about to check here on broadcast short_addr. 928 * Broadcast is a valid setting, comment from 802.15.4: 929 * A value of 0xfffe indicates that the device has 930 * associated but has not been allocated an address. A 931 * value of 0xffff indicates that the device does not 932 * have a short address. 933 * 934 * I think we should allow to set these settings but 935 * don't allow to allow socket communication with it. 936 */ 937 if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) || 938 short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST)) 939 return -EINVAL; 940 941 return rdev_set_short_addr(rdev, wpan_dev, short_addr); 942 } 943 944 static int 945 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info) 946 { 947 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 948 struct net_device *dev = info->user_ptr[1]; 949 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 950 u8 min_be, max_be; 951 952 /* should be set on netif open inside phy settings */ 953 if (netif_running(dev)) 954 return -EBUSY; 955 956 if (!info->attrs[NL802154_ATTR_MIN_BE] || 957 !info->attrs[NL802154_ATTR_MAX_BE]) 958 return -EINVAL; 959 960 min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]); 961 max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]); 962 963 /* check 802.15.4 constraints */ 964 if (min_be < rdev->wpan_phy.supported.min_minbe || 965 min_be > rdev->wpan_phy.supported.max_minbe || 966 max_be < rdev->wpan_phy.supported.min_maxbe || 967 max_be > rdev->wpan_phy.supported.max_maxbe || 968 min_be > max_be) 969 return -EINVAL; 970 971 return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be); 972 } 973 974 static int 975 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info) 976 { 977 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 978 struct net_device *dev = info->user_ptr[1]; 979 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 980 u8 max_csma_backoffs; 981 982 /* conflict here while other running iface settings */ 983 if (netif_running(dev)) 984 return -EBUSY; 985 986 if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]) 987 return -EINVAL; 988 989 max_csma_backoffs = nla_get_u8( 990 info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]); 991 992 /* check 802.15.4 constraints */ 993 if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs || 994 max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs) 995 return -EINVAL; 996 997 return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs); 998 } 999 1000 static int 1001 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info) 1002 { 1003 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1004 struct net_device *dev = info->user_ptr[1]; 1005 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1006 s8 max_frame_retries; 1007 1008 if (netif_running(dev)) 1009 return -EBUSY; 1010 1011 if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]) 1012 return -EINVAL; 1013 1014 max_frame_retries = nla_get_s8( 1015 info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]); 1016 1017 /* check 802.15.4 constraints */ 1018 if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries || 1019 max_frame_retries > rdev->wpan_phy.supported.max_frame_retries) 1020 return -EINVAL; 1021 1022 return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries); 1023 } 1024 1025 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info) 1026 { 1027 struct cfg802154_registered_device *rdev = info->user_ptr[0]; 1028 struct net_device *dev = info->user_ptr[1]; 1029 struct wpan_dev *wpan_dev = dev->ieee802154_ptr; 1030 bool mode; 1031 1032 if (netif_running(dev)) 1033 return -EBUSY; 1034 1035 if (!info->attrs[NL802154_ATTR_LBT_MODE]) 1036 return -EINVAL; 1037 1038 mode = !!nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]); 1039 if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt)) 1040 return -EINVAL; 1041 1042 return rdev_set_lbt_mode(rdev, wpan_dev, mode); 1043 } 1044 1045 #define NL802154_FLAG_NEED_WPAN_PHY 0x01 1046 #define NL802154_FLAG_NEED_NETDEV 0x02 1047 #define NL802154_FLAG_NEED_RTNL 0x04 1048 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08 1049 #define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\ 1050 NL802154_FLAG_CHECK_NETDEV_UP) 1051 #define NL802154_FLAG_NEED_WPAN_DEV 0x10 1052 #define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\ 1053 NL802154_FLAG_CHECK_NETDEV_UP) 1054 1055 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 1056 struct genl_info *info) 1057 { 1058 struct cfg802154_registered_device *rdev; 1059 struct wpan_dev *wpan_dev; 1060 struct net_device *dev; 1061 bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL; 1062 1063 if (rtnl) 1064 rtnl_lock(); 1065 1066 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) { 1067 rdev = cfg802154_get_dev_from_info(genl_info_net(info), info); 1068 if (IS_ERR(rdev)) { 1069 if (rtnl) 1070 rtnl_unlock(); 1071 return PTR_ERR(rdev); 1072 } 1073 info->user_ptr[0] = rdev; 1074 } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV || 1075 ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 1076 ASSERT_RTNL(); 1077 wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info), 1078 info->attrs); 1079 if (IS_ERR(wpan_dev)) { 1080 if (rtnl) 1081 rtnl_unlock(); 1082 return PTR_ERR(wpan_dev); 1083 } 1084 1085 dev = wpan_dev->netdev; 1086 rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy); 1087 1088 if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) { 1089 if (!dev) { 1090 if (rtnl) 1091 rtnl_unlock(); 1092 return -EINVAL; 1093 } 1094 1095 info->user_ptr[1] = dev; 1096 } else { 1097 info->user_ptr[1] = wpan_dev; 1098 } 1099 1100 if (dev) { 1101 if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP && 1102 !netif_running(dev)) { 1103 if (rtnl) 1104 rtnl_unlock(); 1105 return -ENETDOWN; 1106 } 1107 1108 dev_hold(dev); 1109 } 1110 1111 info->user_ptr[0] = rdev; 1112 } 1113 1114 return 0; 1115 } 1116 1117 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb, 1118 struct genl_info *info) 1119 { 1120 if (info->user_ptr[1]) { 1121 if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) { 1122 struct wpan_dev *wpan_dev = info->user_ptr[1]; 1123 1124 if (wpan_dev->netdev) 1125 dev_put(wpan_dev->netdev); 1126 } else { 1127 dev_put(info->user_ptr[1]); 1128 } 1129 } 1130 1131 if (ops->internal_flags & NL802154_FLAG_NEED_RTNL) 1132 rtnl_unlock(); 1133 } 1134 1135 static const struct genl_ops nl802154_ops[] = { 1136 { 1137 .cmd = NL802154_CMD_GET_WPAN_PHY, 1138 .doit = nl802154_get_wpan_phy, 1139 .dumpit = nl802154_dump_wpan_phy, 1140 .done = nl802154_dump_wpan_phy_done, 1141 .policy = nl802154_policy, 1142 /* can be retrieved by unprivileged users */ 1143 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1144 NL802154_FLAG_NEED_RTNL, 1145 }, 1146 { 1147 .cmd = NL802154_CMD_GET_INTERFACE, 1148 .doit = nl802154_get_interface, 1149 .dumpit = nl802154_dump_interface, 1150 .policy = nl802154_policy, 1151 /* can be retrieved by unprivileged users */ 1152 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 1153 NL802154_FLAG_NEED_RTNL, 1154 }, 1155 { 1156 .cmd = NL802154_CMD_NEW_INTERFACE, 1157 .doit = nl802154_new_interface, 1158 .policy = nl802154_policy, 1159 .flags = GENL_ADMIN_PERM, 1160 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1161 NL802154_FLAG_NEED_RTNL, 1162 }, 1163 { 1164 .cmd = NL802154_CMD_DEL_INTERFACE, 1165 .doit = nl802154_del_interface, 1166 .policy = nl802154_policy, 1167 .flags = GENL_ADMIN_PERM, 1168 .internal_flags = NL802154_FLAG_NEED_WPAN_DEV | 1169 NL802154_FLAG_NEED_RTNL, 1170 }, 1171 { 1172 .cmd = NL802154_CMD_SET_CHANNEL, 1173 .doit = nl802154_set_channel, 1174 .policy = nl802154_policy, 1175 .flags = GENL_ADMIN_PERM, 1176 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1177 NL802154_FLAG_NEED_RTNL, 1178 }, 1179 { 1180 .cmd = NL802154_CMD_SET_CCA_MODE, 1181 .doit = nl802154_set_cca_mode, 1182 .policy = nl802154_policy, 1183 .flags = GENL_ADMIN_PERM, 1184 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1185 NL802154_FLAG_NEED_RTNL, 1186 }, 1187 { 1188 .cmd = NL802154_CMD_SET_CCA_ED_LEVEL, 1189 .doit = nl802154_set_cca_ed_level, 1190 .policy = nl802154_policy, 1191 .flags = GENL_ADMIN_PERM, 1192 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1193 NL802154_FLAG_NEED_RTNL, 1194 }, 1195 { 1196 .cmd = NL802154_CMD_SET_TX_POWER, 1197 .doit = nl802154_set_tx_power, 1198 .policy = nl802154_policy, 1199 .flags = GENL_ADMIN_PERM, 1200 .internal_flags = NL802154_FLAG_NEED_WPAN_PHY | 1201 NL802154_FLAG_NEED_RTNL, 1202 }, 1203 { 1204 .cmd = NL802154_CMD_SET_PAN_ID, 1205 .doit = nl802154_set_pan_id, 1206 .policy = nl802154_policy, 1207 .flags = GENL_ADMIN_PERM, 1208 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1209 NL802154_FLAG_NEED_RTNL, 1210 }, 1211 { 1212 .cmd = NL802154_CMD_SET_SHORT_ADDR, 1213 .doit = nl802154_set_short_addr, 1214 .policy = nl802154_policy, 1215 .flags = GENL_ADMIN_PERM, 1216 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1217 NL802154_FLAG_NEED_RTNL, 1218 }, 1219 { 1220 .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT, 1221 .doit = nl802154_set_backoff_exponent, 1222 .policy = nl802154_policy, 1223 .flags = GENL_ADMIN_PERM, 1224 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1225 NL802154_FLAG_NEED_RTNL, 1226 }, 1227 { 1228 .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS, 1229 .doit = nl802154_set_max_csma_backoffs, 1230 .policy = nl802154_policy, 1231 .flags = GENL_ADMIN_PERM, 1232 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1233 NL802154_FLAG_NEED_RTNL, 1234 }, 1235 { 1236 .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES, 1237 .doit = nl802154_set_max_frame_retries, 1238 .policy = nl802154_policy, 1239 .flags = GENL_ADMIN_PERM, 1240 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1241 NL802154_FLAG_NEED_RTNL, 1242 }, 1243 { 1244 .cmd = NL802154_CMD_SET_LBT_MODE, 1245 .doit = nl802154_set_lbt_mode, 1246 .policy = nl802154_policy, 1247 .flags = GENL_ADMIN_PERM, 1248 .internal_flags = NL802154_FLAG_NEED_NETDEV | 1249 NL802154_FLAG_NEED_RTNL, 1250 }, 1251 }; 1252 1253 /* initialisation/exit functions */ 1254 int nl802154_init(void) 1255 { 1256 return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops, 1257 nl802154_mcgrps); 1258 } 1259 1260 void nl802154_exit(void) 1261 { 1262 genl_unregister_family(&nl802154_fam); 1263 } 1264