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