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