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