Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Authors:
0005  * Alexander Aring <aar@pengutronix.de>
0006  *
0007  * Based on: net/wireless/nl80211.c
0008  */
0009 
0010 #include <linux/rtnetlink.h>
0011 
0012 #include <net/cfg802154.h>
0013 #include <net/genetlink.h>
0014 #include <net/mac802154.h>
0015 #include <net/netlink.h>
0016 #include <net/nl802154.h>
0017 #include <net/sock.h>
0018 
0019 #include "nl802154.h"
0020 #include "rdev-ops.h"
0021 #include "core.h"
0022 
0023 /* the netlink family */
0024 static struct genl_family nl802154_fam;
0025 
0026 /* multicast groups */
0027 enum nl802154_multicast_groups {
0028     NL802154_MCGRP_CONFIG,
0029 };
0030 
0031 static const struct genl_multicast_group nl802154_mcgrps[] = {
0032     [NL802154_MCGRP_CONFIG] = { .name = "config", },
0033 };
0034 
0035 /* returns ERR_PTR values */
0036 static struct wpan_dev *
0037 __cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
0038 {
0039     struct cfg802154_registered_device *rdev;
0040     struct wpan_dev *result = NULL;
0041     bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
0042     bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
0043     u64 wpan_dev_id;
0044     int wpan_phy_idx = -1;
0045     int ifidx = -1;
0046 
0047     ASSERT_RTNL();
0048 
0049     if (!have_ifidx && !have_wpan_dev_id)
0050         return ERR_PTR(-EINVAL);
0051 
0052     if (have_ifidx)
0053         ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
0054     if (have_wpan_dev_id) {
0055         wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
0056         wpan_phy_idx = wpan_dev_id >> 32;
0057     }
0058 
0059     list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
0060         struct wpan_dev *wpan_dev;
0061 
0062         if (wpan_phy_net(&rdev->wpan_phy) != netns)
0063             continue;
0064 
0065         if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
0066             continue;
0067 
0068         list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
0069             if (have_ifidx && wpan_dev->netdev &&
0070                 wpan_dev->netdev->ifindex == ifidx) {
0071                 result = wpan_dev;
0072                 break;
0073             }
0074             if (have_wpan_dev_id &&
0075                 wpan_dev->identifier == (u32)wpan_dev_id) {
0076                 result = wpan_dev;
0077                 break;
0078             }
0079         }
0080 
0081         if (result)
0082             break;
0083     }
0084 
0085     if (result)
0086         return result;
0087 
0088     return ERR_PTR(-ENODEV);
0089 }
0090 
0091 static struct cfg802154_registered_device *
0092 __cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
0093 {
0094     struct cfg802154_registered_device *rdev = NULL, *tmp;
0095     struct net_device *netdev;
0096 
0097     ASSERT_RTNL();
0098 
0099     if (!attrs[NL802154_ATTR_WPAN_PHY] &&
0100         !attrs[NL802154_ATTR_IFINDEX] &&
0101         !attrs[NL802154_ATTR_WPAN_DEV])
0102         return ERR_PTR(-EINVAL);
0103 
0104     if (attrs[NL802154_ATTR_WPAN_PHY])
0105         rdev = cfg802154_rdev_by_wpan_phy_idx(
0106                 nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY]));
0107 
0108     if (attrs[NL802154_ATTR_WPAN_DEV]) {
0109         u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
0110         struct wpan_dev *wpan_dev;
0111         bool found = false;
0112 
0113         tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32);
0114         if (tmp) {
0115             /* make sure wpan_dev exists */
0116             list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) {
0117                 if (wpan_dev->identifier != (u32)wpan_dev_id)
0118                     continue;
0119                 found = true;
0120                 break;
0121             }
0122 
0123             if (!found)
0124                 tmp = NULL;
0125 
0126             if (rdev && tmp != rdev)
0127                 return ERR_PTR(-EINVAL);
0128             rdev = tmp;
0129         }
0130     }
0131 
0132     if (attrs[NL802154_ATTR_IFINDEX]) {
0133         int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
0134 
0135         netdev = __dev_get_by_index(netns, ifindex);
0136         if (netdev) {
0137             if (netdev->ieee802154_ptr)
0138                 tmp = wpan_phy_to_rdev(
0139                         netdev->ieee802154_ptr->wpan_phy);
0140             else
0141                 tmp = NULL;
0142 
0143             /* not wireless device -- return error */
0144             if (!tmp)
0145                 return ERR_PTR(-EINVAL);
0146 
0147             /* mismatch -- return error */
0148             if (rdev && tmp != rdev)
0149                 return ERR_PTR(-EINVAL);
0150 
0151             rdev = tmp;
0152         }
0153     }
0154 
0155     if (!rdev)
0156         return ERR_PTR(-ENODEV);
0157 
0158     if (netns != wpan_phy_net(&rdev->wpan_phy))
0159         return ERR_PTR(-ENODEV);
0160 
0161     return rdev;
0162 }
0163 
0164 /* This function returns a pointer to the driver
0165  * that the genl_info item that is passed refers to.
0166  *
0167  * The result of this can be a PTR_ERR and hence must
0168  * be checked with IS_ERR() for errors.
0169  */
0170 static struct cfg802154_registered_device *
0171 cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info)
0172 {
0173     return __cfg802154_rdev_from_attrs(netns, info->attrs);
0174 }
0175 
0176 /* policy for the attributes */
0177 static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
0178     [NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 },
0179     [NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING,
0180                       .len = 20-1 },
0181 
0182     [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 },
0183     [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 },
0184     [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
0185 
0186     [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 },
0187 
0188     [NL802154_ATTR_PAGE] = { .type = NLA_U8, },
0189     [NL802154_ATTR_CHANNEL] = { .type = NLA_U8, },
0190 
0191     [NL802154_ATTR_TX_POWER] = { .type = NLA_S32, },
0192 
0193     [NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, },
0194     [NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, },
0195     [NL802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, },
0196 
0197     [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
0198 
0199     [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, },
0200     [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
0201     [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
0202 
0203     [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, },
0204     [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, },
0205     [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, },
0206 
0207     [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, },
0208 
0209     [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, },
0210 
0211     [NL802154_ATTR_WPAN_PHY_CAPS] = { .type = NLA_NESTED },
0212 
0213     [NL802154_ATTR_SUPPORTED_COMMANDS] = { .type = NLA_NESTED },
0214 
0215     [NL802154_ATTR_ACKREQ_DEFAULT] = { .type = NLA_U8 },
0216 
0217     [NL802154_ATTR_PID] = { .type = NLA_U32 },
0218     [NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
0219 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0220     [NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
0221     [NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
0222     [NL802154_ATTR_SEC_OUT_KEY_ID] = { .type = NLA_NESTED, },
0223     [NL802154_ATTR_SEC_FRAME_COUNTER] = { .type = NLA_U32 },
0224 
0225     [NL802154_ATTR_SEC_LEVEL] = { .type = NLA_NESTED },
0226     [NL802154_ATTR_SEC_DEVICE] = { .type = NLA_NESTED },
0227     [NL802154_ATTR_SEC_DEVKEY] = { .type = NLA_NESTED },
0228     [NL802154_ATTR_SEC_KEY] = { .type = NLA_NESTED },
0229 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
0230 };
0231 
0232 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0233 static int
0234 nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
0235                    struct netlink_callback *cb,
0236                    struct cfg802154_registered_device **rdev,
0237                    struct wpan_dev **wpan_dev)
0238 {
0239     const struct genl_dumpit_info *info = genl_dumpit_info(cb);
0240     int err;
0241 
0242     rtnl_lock();
0243 
0244     if (!cb->args[0]) {
0245         *wpan_dev = __cfg802154_wpan_dev_from_attrs(sock_net(skb->sk),
0246                                 info->attrs);
0247         if (IS_ERR(*wpan_dev)) {
0248             err = PTR_ERR(*wpan_dev);
0249             goto out_unlock;
0250         }
0251         *rdev = wpan_phy_to_rdev((*wpan_dev)->wpan_phy);
0252         /* 0 is the first index - add 1 to parse only once */
0253         cb->args[0] = (*rdev)->wpan_phy_idx + 1;
0254         cb->args[1] = (*wpan_dev)->identifier;
0255     } else {
0256         /* subtract the 1 again here */
0257         struct wpan_phy *wpan_phy = wpan_phy_idx_to_wpan_phy(cb->args[0] - 1);
0258         struct wpan_dev *tmp;
0259 
0260         if (!wpan_phy) {
0261             err = -ENODEV;
0262             goto out_unlock;
0263         }
0264         *rdev = wpan_phy_to_rdev(wpan_phy);
0265         *wpan_dev = NULL;
0266 
0267         list_for_each_entry(tmp, &(*rdev)->wpan_dev_list, list) {
0268             if (tmp->identifier == cb->args[1]) {
0269                 *wpan_dev = tmp;
0270                 break;
0271             }
0272         }
0273 
0274         if (!*wpan_dev) {
0275             err = -ENODEV;
0276             goto out_unlock;
0277         }
0278     }
0279 
0280     return 0;
0281  out_unlock:
0282     rtnl_unlock();
0283     return err;
0284 }
0285 
0286 static void
0287 nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev)
0288 {
0289     rtnl_unlock();
0290 }
0291 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
0292 
0293 /* message building helper */
0294 static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
0295                     int flags, u8 cmd)
0296 {
0297     /* since there is no private header just add the generic one */
0298     return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd);
0299 }
0300 
0301 static int
0302 nl802154_put_flags(struct sk_buff *msg, int attr, u32 mask)
0303 {
0304     struct nlattr *nl_flags = nla_nest_start_noflag(msg, attr);
0305     int i;
0306 
0307     if (!nl_flags)
0308         return -ENOBUFS;
0309 
0310     i = 0;
0311     while (mask) {
0312         if ((mask & 1) && nla_put_flag(msg, i))
0313             return -ENOBUFS;
0314 
0315         mask >>= 1;
0316         i++;
0317     }
0318 
0319     nla_nest_end(msg, nl_flags);
0320     return 0;
0321 }
0322 
0323 static int
0324 nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
0325                 struct sk_buff *msg)
0326 {
0327     struct nlattr *nl_page;
0328     unsigned long page;
0329 
0330     nl_page = nla_nest_start_noflag(msg, NL802154_ATTR_CHANNELS_SUPPORTED);
0331     if (!nl_page)
0332         return -ENOBUFS;
0333 
0334     for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
0335         if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
0336                 rdev->wpan_phy.supported.channels[page]))
0337             return -ENOBUFS;
0338     }
0339     nla_nest_end(msg, nl_page);
0340 
0341     return 0;
0342 }
0343 
0344 static int
0345 nl802154_put_capabilities(struct sk_buff *msg,
0346               struct cfg802154_registered_device *rdev)
0347 {
0348     const struct wpan_phy_supported *caps = &rdev->wpan_phy.supported;
0349     struct nlattr *nl_caps, *nl_channels;
0350     int i;
0351 
0352     nl_caps = nla_nest_start_noflag(msg, NL802154_ATTR_WPAN_PHY_CAPS);
0353     if (!nl_caps)
0354         return -ENOBUFS;
0355 
0356     nl_channels = nla_nest_start_noflag(msg, NL802154_CAP_ATTR_CHANNELS);
0357     if (!nl_channels)
0358         return -ENOBUFS;
0359 
0360     for (i = 0; i <= IEEE802154_MAX_PAGE; i++) {
0361         if (caps->channels[i]) {
0362             if (nl802154_put_flags(msg, i, caps->channels[i]))
0363                 return -ENOBUFS;
0364         }
0365     }
0366 
0367     nla_nest_end(msg, nl_channels);
0368 
0369     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
0370         struct nlattr *nl_ed_lvls;
0371 
0372         nl_ed_lvls = nla_nest_start_noflag(msg,
0373                            NL802154_CAP_ATTR_CCA_ED_LEVELS);
0374         if (!nl_ed_lvls)
0375             return -ENOBUFS;
0376 
0377         for (i = 0; i < caps->cca_ed_levels_size; i++) {
0378             if (nla_put_s32(msg, i, caps->cca_ed_levels[i]))
0379                 return -ENOBUFS;
0380         }
0381 
0382         nla_nest_end(msg, nl_ed_lvls);
0383     }
0384 
0385     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
0386         struct nlattr *nl_tx_pwrs;
0387 
0388         nl_tx_pwrs = nla_nest_start_noflag(msg,
0389                            NL802154_CAP_ATTR_TX_POWERS);
0390         if (!nl_tx_pwrs)
0391             return -ENOBUFS;
0392 
0393         for (i = 0; i < caps->tx_powers_size; i++) {
0394             if (nla_put_s32(msg, i, caps->tx_powers[i]))
0395                 return -ENOBUFS;
0396         }
0397 
0398         nla_nest_end(msg, nl_tx_pwrs);
0399     }
0400 
0401     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
0402         if (nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_MODES,
0403                        caps->cca_modes) ||
0404             nl802154_put_flags(msg, NL802154_CAP_ATTR_CCA_OPTS,
0405                        caps->cca_opts))
0406             return -ENOBUFS;
0407     }
0408 
0409     if (nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MINBE, caps->min_minbe) ||
0410         nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MINBE, caps->max_minbe) ||
0411         nla_put_u8(msg, NL802154_CAP_ATTR_MIN_MAXBE, caps->min_maxbe) ||
0412         nla_put_u8(msg, NL802154_CAP_ATTR_MAX_MAXBE, caps->max_maxbe) ||
0413         nla_put_u8(msg, NL802154_CAP_ATTR_MIN_CSMA_BACKOFFS,
0414                caps->min_csma_backoffs) ||
0415         nla_put_u8(msg, NL802154_CAP_ATTR_MAX_CSMA_BACKOFFS,
0416                caps->max_csma_backoffs) ||
0417         nla_put_s8(msg, NL802154_CAP_ATTR_MIN_FRAME_RETRIES,
0418                caps->min_frame_retries) ||
0419         nla_put_s8(msg, NL802154_CAP_ATTR_MAX_FRAME_RETRIES,
0420                caps->max_frame_retries) ||
0421         nl802154_put_flags(msg, NL802154_CAP_ATTR_IFTYPES,
0422                    caps->iftypes) ||
0423         nla_put_u32(msg, NL802154_CAP_ATTR_LBT, caps->lbt))
0424         return -ENOBUFS;
0425 
0426     nla_nest_end(msg, nl_caps);
0427 
0428     return 0;
0429 }
0430 
0431 static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
0432                   enum nl802154_commands cmd,
0433                   struct sk_buff *msg, u32 portid, u32 seq,
0434                   int flags)
0435 {
0436     struct nlattr *nl_cmds;
0437     void *hdr;
0438     int i;
0439 
0440     hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
0441     if (!hdr)
0442         return -ENOBUFS;
0443 
0444     if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
0445         nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME,
0446                wpan_phy_name(&rdev->wpan_phy)) ||
0447         nla_put_u32(msg, NL802154_ATTR_GENERATION,
0448             cfg802154_rdev_list_generation))
0449         goto nla_put_failure;
0450 
0451     if (cmd != NL802154_CMD_NEW_WPAN_PHY)
0452         goto finish;
0453 
0454     /* DUMP PHY PIB */
0455 
0456     /* current channel settings */
0457     if (nla_put_u8(msg, NL802154_ATTR_PAGE,
0458                rdev->wpan_phy.current_page) ||
0459         nla_put_u8(msg, NL802154_ATTR_CHANNEL,
0460                rdev->wpan_phy.current_channel))
0461         goto nla_put_failure;
0462 
0463     /* TODO remove this behaviour, we still keep support it for a while
0464      * so users can change the behaviour to the new one.
0465      */
0466     if (nl802154_send_wpan_phy_channels(rdev, msg))
0467         goto nla_put_failure;
0468 
0469     /* cca mode */
0470     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE) {
0471         if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE,
0472                 rdev->wpan_phy.cca.mode))
0473             goto nla_put_failure;
0474 
0475         if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) {
0476             if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT,
0477                     rdev->wpan_phy.cca.opt))
0478                 goto nla_put_failure;
0479         }
0480     }
0481 
0482     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER) {
0483         if (nla_put_s32(msg, NL802154_ATTR_TX_POWER,
0484                 rdev->wpan_phy.transmit_power))
0485             goto nla_put_failure;
0486     }
0487 
0488     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL) {
0489         if (nla_put_s32(msg, NL802154_ATTR_CCA_ED_LEVEL,
0490                 rdev->wpan_phy.cca_ed_level))
0491             goto nla_put_failure;
0492     }
0493 
0494     if (nl802154_put_capabilities(msg, rdev))
0495         goto nla_put_failure;
0496 
0497     nl_cmds = nla_nest_start_noflag(msg, NL802154_ATTR_SUPPORTED_COMMANDS);
0498     if (!nl_cmds)
0499         goto nla_put_failure;
0500 
0501     i = 0;
0502 #define CMD(op, n)                          \
0503     do {                                \
0504         if (rdev->ops->op) {                    \
0505             i++;                        \
0506             if (nla_put_u32(msg, i, NL802154_CMD_ ## n))    \
0507                 goto nla_put_failure;           \
0508         }                           \
0509     } while (0)
0510 
0511     CMD(add_virtual_intf, NEW_INTERFACE);
0512     CMD(del_virtual_intf, DEL_INTERFACE);
0513     CMD(set_channel, SET_CHANNEL);
0514     CMD(set_pan_id, SET_PAN_ID);
0515     CMD(set_short_addr, SET_SHORT_ADDR);
0516     CMD(set_backoff_exponent, SET_BACKOFF_EXPONENT);
0517     CMD(set_max_csma_backoffs, SET_MAX_CSMA_BACKOFFS);
0518     CMD(set_max_frame_retries, SET_MAX_FRAME_RETRIES);
0519     CMD(set_lbt_mode, SET_LBT_MODE);
0520     CMD(set_ackreq_default, SET_ACKREQ_DEFAULT);
0521 
0522     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER)
0523         CMD(set_tx_power, SET_TX_POWER);
0524 
0525     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL)
0526         CMD(set_cca_ed_level, SET_CCA_ED_LEVEL);
0527 
0528     if (rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE)
0529         CMD(set_cca_mode, SET_CCA_MODE);
0530 
0531 #undef CMD
0532     nla_nest_end(msg, nl_cmds);
0533 
0534 finish:
0535     genlmsg_end(msg, hdr);
0536     return 0;
0537 
0538 nla_put_failure:
0539     genlmsg_cancel(msg, hdr);
0540     return -EMSGSIZE;
0541 }
0542 
0543 struct nl802154_dump_wpan_phy_state {
0544     s64 filter_wpan_phy;
0545     long start;
0546 
0547 };
0548 
0549 static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
0550                     struct netlink_callback *cb,
0551                     struct nl802154_dump_wpan_phy_state *state)
0552 {
0553     const struct genl_dumpit_info *info = genl_dumpit_info(cb);
0554     struct nlattr **tb = info->attrs;
0555 
0556     if (tb[NL802154_ATTR_WPAN_PHY])
0557         state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
0558     if (tb[NL802154_ATTR_WPAN_DEV])
0559         state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32;
0560     if (tb[NL802154_ATTR_IFINDEX]) {
0561         struct net_device *netdev;
0562         struct cfg802154_registered_device *rdev;
0563         int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
0564 
0565         netdev = __dev_get_by_index(&init_net, ifidx);
0566         if (!netdev)
0567             return -ENODEV;
0568         if (netdev->ieee802154_ptr) {
0569             rdev = wpan_phy_to_rdev(
0570                     netdev->ieee802154_ptr->wpan_phy);
0571             state->filter_wpan_phy = rdev->wpan_phy_idx;
0572         }
0573     }
0574 
0575     return 0;
0576 }
0577 
0578 static int
0579 nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
0580 {
0581     int idx = 0, ret;
0582     struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0];
0583     struct cfg802154_registered_device *rdev;
0584 
0585     rtnl_lock();
0586     if (!state) {
0587         state = kzalloc(sizeof(*state), GFP_KERNEL);
0588         if (!state) {
0589             rtnl_unlock();
0590             return -ENOMEM;
0591         }
0592         state->filter_wpan_phy = -1;
0593         ret = nl802154_dump_wpan_phy_parse(skb, cb, state);
0594         if (ret) {
0595             kfree(state);
0596             rtnl_unlock();
0597             return ret;
0598         }
0599         cb->args[0] = (long)state;
0600     }
0601 
0602     list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
0603         if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
0604             continue;
0605         if (++idx <= state->start)
0606             continue;
0607         if (state->filter_wpan_phy != -1 &&
0608             state->filter_wpan_phy != rdev->wpan_phy_idx)
0609             continue;
0610         /* attempt to fit multiple wpan_phy data chunks into the skb */
0611         ret = nl802154_send_wpan_phy(rdev,
0612                          NL802154_CMD_NEW_WPAN_PHY,
0613                          skb,
0614                          NETLINK_CB(cb->skb).portid,
0615                          cb->nlh->nlmsg_seq, NLM_F_MULTI);
0616         if (ret < 0) {
0617             if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
0618                 !skb->len && cb->min_dump_alloc < 4096) {
0619                 cb->min_dump_alloc = 4096;
0620                 rtnl_unlock();
0621                 return 1;
0622             }
0623             idx--;
0624             break;
0625         }
0626         break;
0627     }
0628     rtnl_unlock();
0629 
0630     state->start = idx;
0631 
0632     return skb->len;
0633 }
0634 
0635 static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
0636 {
0637     kfree((void *)cb->args[0]);
0638     return 0;
0639 }
0640 
0641 static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info)
0642 {
0643     struct sk_buff *msg;
0644     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0645 
0646     msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0647     if (!msg)
0648         return -ENOMEM;
0649 
0650     if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg,
0651                    info->snd_portid, info->snd_seq, 0) < 0) {
0652         nlmsg_free(msg);
0653         return -ENOBUFS;
0654     }
0655 
0656     return genlmsg_reply(msg, info);
0657 }
0658 
0659 static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev)
0660 {
0661     return (u64)wpan_dev->identifier |
0662            ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32);
0663 }
0664 
0665 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0666 #include <net/ieee802154_netdev.h>
0667 
0668 static int
0669 ieee802154_llsec_send_key_id(struct sk_buff *msg,
0670                  const struct ieee802154_llsec_key_id *desc)
0671 {
0672     struct nlattr *nl_dev_addr;
0673 
0674     if (nla_put_u32(msg, NL802154_KEY_ID_ATTR_MODE, desc->mode))
0675         return -ENOBUFS;
0676 
0677     switch (desc->mode) {
0678     case NL802154_KEY_ID_MODE_IMPLICIT:
0679         nl_dev_addr = nla_nest_start_noflag(msg,
0680                             NL802154_KEY_ID_ATTR_IMPLICIT);
0681         if (!nl_dev_addr)
0682             return -ENOBUFS;
0683 
0684         if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_PAN_ID,
0685                  desc->device_addr.pan_id) ||
0686             nla_put_u32(msg,  NL802154_DEV_ADDR_ATTR_MODE,
0687                 desc->device_addr.mode))
0688             return -ENOBUFS;
0689 
0690         switch (desc->device_addr.mode) {
0691         case NL802154_DEV_ADDR_SHORT:
0692             if (nla_put_le16(msg, NL802154_DEV_ADDR_ATTR_SHORT,
0693                      desc->device_addr.short_addr))
0694                 return -ENOBUFS;
0695             break;
0696         case NL802154_DEV_ADDR_EXTENDED:
0697             if (nla_put_le64(msg, NL802154_DEV_ADDR_ATTR_EXTENDED,
0698                      desc->device_addr.extended_addr,
0699                      NL802154_DEV_ADDR_ATTR_PAD))
0700                 return -ENOBUFS;
0701             break;
0702         default:
0703             /* userspace should handle unknown */
0704             break;
0705         }
0706 
0707         nla_nest_end(msg, nl_dev_addr);
0708         break;
0709     case NL802154_KEY_ID_MODE_INDEX:
0710         break;
0711     case NL802154_KEY_ID_MODE_INDEX_SHORT:
0712         /* TODO renmae short_source? */
0713         if (nla_put_le32(msg, NL802154_KEY_ID_ATTR_SOURCE_SHORT,
0714                  desc->short_source))
0715             return -ENOBUFS;
0716         break;
0717     case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
0718         if (nla_put_le64(msg, NL802154_KEY_ID_ATTR_SOURCE_EXTENDED,
0719                  desc->extended_source,
0720                  NL802154_KEY_ID_ATTR_PAD))
0721             return -ENOBUFS;
0722         break;
0723     default:
0724         /* userspace should handle unknown */
0725         break;
0726     }
0727 
0728     /* TODO key_id to key_idx ? Check naming */
0729     if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
0730         if (nla_put_u8(msg, NL802154_KEY_ID_ATTR_INDEX, desc->id))
0731             return -ENOBUFS;
0732     }
0733 
0734     return 0;
0735 }
0736 
0737 static int nl802154_get_llsec_params(struct sk_buff *msg,
0738                      struct cfg802154_registered_device *rdev,
0739                      struct wpan_dev *wpan_dev)
0740 {
0741     struct nlattr *nl_key_id;
0742     struct ieee802154_llsec_params params;
0743     int ret;
0744 
0745     ret = rdev_get_llsec_params(rdev, wpan_dev, &params);
0746     if (ret < 0)
0747         return ret;
0748 
0749     if (nla_put_u8(msg, NL802154_ATTR_SEC_ENABLED, params.enabled) ||
0750         nla_put_u32(msg, NL802154_ATTR_SEC_OUT_LEVEL, params.out_level) ||
0751         nla_put_be32(msg, NL802154_ATTR_SEC_FRAME_COUNTER,
0752              params.frame_counter))
0753         return -ENOBUFS;
0754 
0755     nl_key_id = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_OUT_KEY_ID);
0756     if (!nl_key_id)
0757         return -ENOBUFS;
0758 
0759     ret = ieee802154_llsec_send_key_id(msg, &params.out_key);
0760     if (ret < 0)
0761         return ret;
0762 
0763     nla_nest_end(msg, nl_key_id);
0764 
0765     return 0;
0766 }
0767 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
0768 
0769 static int
0770 nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
0771             struct cfg802154_registered_device *rdev,
0772             struct wpan_dev *wpan_dev)
0773 {
0774     struct net_device *dev = wpan_dev->netdev;
0775     void *hdr;
0776 
0777     hdr = nl802154hdr_put(msg, portid, seq, flags,
0778                   NL802154_CMD_NEW_INTERFACE);
0779     if (!hdr)
0780         return -1;
0781 
0782     if (dev &&
0783         (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
0784          nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
0785         goto nla_put_failure;
0786 
0787     if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
0788         nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
0789         nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
0790                   wpan_dev_id(wpan_dev), NL802154_ATTR_PAD) ||
0791         nla_put_u32(msg, NL802154_ATTR_GENERATION,
0792             rdev->devlist_generation ^
0793             (cfg802154_rdev_list_generation << 2)))
0794         goto nla_put_failure;
0795 
0796     /* address settings */
0797     if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
0798              wpan_dev->extended_addr,
0799              NL802154_ATTR_PAD) ||
0800         nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
0801              wpan_dev->short_addr) ||
0802         nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
0803         goto nla_put_failure;
0804 
0805     /* ARET handling */
0806     if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
0807                wpan_dev->frame_retries) ||
0808         nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
0809         nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
0810                wpan_dev->csma_retries) ||
0811         nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
0812         goto nla_put_failure;
0813 
0814     /* listen before transmit */
0815     if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
0816         goto nla_put_failure;
0817 
0818     /* ackreq default behaviour */
0819     if (nla_put_u8(msg, NL802154_ATTR_ACKREQ_DEFAULT, wpan_dev->ackreq))
0820         goto nla_put_failure;
0821 
0822 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
0823     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
0824         goto out;
0825 
0826     if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0)
0827         goto nla_put_failure;
0828 
0829 out:
0830 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
0831 
0832     genlmsg_end(msg, hdr);
0833     return 0;
0834 
0835 nla_put_failure:
0836     genlmsg_cancel(msg, hdr);
0837     return -EMSGSIZE;
0838 }
0839 
0840 static int
0841 nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
0842 {
0843     int wp_idx = 0;
0844     int if_idx = 0;
0845     int wp_start = cb->args[0];
0846     int if_start = cb->args[1];
0847     struct cfg802154_registered_device *rdev;
0848     struct wpan_dev *wpan_dev;
0849 
0850     rtnl_lock();
0851     list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
0852         if (!net_eq(wpan_phy_net(&rdev->wpan_phy), sock_net(skb->sk)))
0853             continue;
0854         if (wp_idx < wp_start) {
0855             wp_idx++;
0856             continue;
0857         }
0858         if_idx = 0;
0859 
0860         list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
0861             if (if_idx < if_start) {
0862                 if_idx++;
0863                 continue;
0864             }
0865             if (nl802154_send_iface(skb, NETLINK_CB(cb->skb).portid,
0866                         cb->nlh->nlmsg_seq, NLM_F_MULTI,
0867                         rdev, wpan_dev) < 0) {
0868                 goto out;
0869             }
0870             if_idx++;
0871         }
0872 
0873         wp_idx++;
0874     }
0875 out:
0876     rtnl_unlock();
0877 
0878     cb->args[0] = wp_idx;
0879     cb->args[1] = if_idx;
0880 
0881     return skb->len;
0882 }
0883 
0884 static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
0885 {
0886     struct sk_buff *msg;
0887     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0888     struct wpan_dev *wdev = info->user_ptr[1];
0889 
0890     msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0891     if (!msg)
0892         return -ENOMEM;
0893 
0894     if (nl802154_send_iface(msg, info->snd_portid, info->snd_seq, 0,
0895                 rdev, wdev) < 0) {
0896         nlmsg_free(msg);
0897         return -ENOBUFS;
0898     }
0899 
0900     return genlmsg_reply(msg, info);
0901 }
0902 
0903 static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
0904 {
0905     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0906     enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
0907     __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
0908 
0909     /* TODO avoid failing a new interface
0910      * creation due to pending removal?
0911      */
0912 
0913     if (!info->attrs[NL802154_ATTR_IFNAME])
0914         return -EINVAL;
0915 
0916     if (info->attrs[NL802154_ATTR_IFTYPE]) {
0917         type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
0918         if (type > NL802154_IFTYPE_MAX ||
0919             !(rdev->wpan_phy.supported.iftypes & BIT(type)))
0920             return -EINVAL;
0921     }
0922 
0923     if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
0924         extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
0925 
0926     if (!rdev->ops->add_virtual_intf)
0927         return -EOPNOTSUPP;
0928 
0929     return rdev_add_virtual_intf(rdev,
0930                      nla_data(info->attrs[NL802154_ATTR_IFNAME]),
0931                      NET_NAME_USER, type, extended_addr);
0932 }
0933 
0934 static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
0935 {
0936     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0937     struct wpan_dev *wpan_dev = info->user_ptr[1];
0938 
0939     if (!rdev->ops->del_virtual_intf)
0940         return -EOPNOTSUPP;
0941 
0942     /* If we remove a wpan device without a netdev then clear
0943      * user_ptr[1] so that nl802154_post_doit won't dereference it
0944      * to check if it needs to do dev_put(). Otherwise it crashes
0945      * since the wpan_dev has been freed, unlike with a netdev where
0946      * we need the dev_put() for the netdev to really be freed.
0947      */
0948     if (!wpan_dev->netdev)
0949         info->user_ptr[1] = NULL;
0950 
0951     return rdev_del_virtual_intf(rdev, wpan_dev);
0952 }
0953 
0954 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
0955 {
0956     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0957     u8 channel, page;
0958 
0959     if (!info->attrs[NL802154_ATTR_PAGE] ||
0960         !info->attrs[NL802154_ATTR_CHANNEL])
0961         return -EINVAL;
0962 
0963     page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
0964     channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
0965 
0966     /* check 802.15.4 constraints */
0967     if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL ||
0968         !(rdev->wpan_phy.supported.channels[page] & BIT(channel)))
0969         return -EINVAL;
0970 
0971     return rdev_set_channel(rdev, page, channel);
0972 }
0973 
0974 static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
0975 {
0976     struct cfg802154_registered_device *rdev = info->user_ptr[0];
0977     struct wpan_phy_cca cca;
0978 
0979     if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_MODE))
0980         return -EOPNOTSUPP;
0981 
0982     if (!info->attrs[NL802154_ATTR_CCA_MODE])
0983         return -EINVAL;
0984 
0985     cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
0986     /* checking 802.15.4 constraints */
0987     if (cca.mode < NL802154_CCA_ENERGY ||
0988         cca.mode > NL802154_CCA_ATTR_MAX ||
0989         !(rdev->wpan_phy.supported.cca_modes & BIT(cca.mode)))
0990         return -EINVAL;
0991 
0992     if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
0993         if (!info->attrs[NL802154_ATTR_CCA_OPT])
0994             return -EINVAL;
0995 
0996         cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
0997         if (cca.opt > NL802154_CCA_OPT_ATTR_MAX ||
0998             !(rdev->wpan_phy.supported.cca_opts & BIT(cca.opt)))
0999             return -EINVAL;
1000     }
1001 
1002     return rdev_set_cca_mode(rdev, &cca);
1003 }
1004 
1005 static int nl802154_set_cca_ed_level(struct sk_buff *skb, struct genl_info *info)
1006 {
1007     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1008     s32 ed_level;
1009     int i;
1010 
1011     if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_CCA_ED_LEVEL))
1012         return -EOPNOTSUPP;
1013 
1014     if (!info->attrs[NL802154_ATTR_CCA_ED_LEVEL])
1015         return -EINVAL;
1016 
1017     ed_level = nla_get_s32(info->attrs[NL802154_ATTR_CCA_ED_LEVEL]);
1018 
1019     for (i = 0; i < rdev->wpan_phy.supported.cca_ed_levels_size; i++) {
1020         if (ed_level == rdev->wpan_phy.supported.cca_ed_levels[i])
1021             return rdev_set_cca_ed_level(rdev, ed_level);
1022     }
1023 
1024     return -EINVAL;
1025 }
1026 
1027 static int nl802154_set_tx_power(struct sk_buff *skb, struct genl_info *info)
1028 {
1029     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1030     s32 power;
1031     int i;
1032 
1033     if (!(rdev->wpan_phy.flags & WPAN_PHY_FLAG_TXPOWER))
1034         return -EOPNOTSUPP;
1035 
1036     if (!info->attrs[NL802154_ATTR_TX_POWER])
1037         return -EINVAL;
1038 
1039     power = nla_get_s32(info->attrs[NL802154_ATTR_TX_POWER]);
1040 
1041     for (i = 0; i < rdev->wpan_phy.supported.tx_powers_size; i++) {
1042         if (power == rdev->wpan_phy.supported.tx_powers[i])
1043             return rdev_set_tx_power(rdev, power);
1044     }
1045 
1046     return -EINVAL;
1047 }
1048 
1049 static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
1050 {
1051     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1052     struct net_device *dev = info->user_ptr[1];
1053     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1054     __le16 pan_id;
1055 
1056     /* conflict here while tx/rx calls */
1057     if (netif_running(dev))
1058         return -EBUSY;
1059 
1060     if (wpan_dev->lowpan_dev) {
1061         if (netif_running(wpan_dev->lowpan_dev))
1062             return -EBUSY;
1063     }
1064 
1065     /* don't change address fields on monitor */
1066     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1067         !info->attrs[NL802154_ATTR_PAN_ID])
1068         return -EINVAL;
1069 
1070     pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
1071 
1072     /* TODO
1073      * I am not sure about to check here on broadcast pan_id.
1074      * Broadcast is a valid setting, comment from 802.15.4:
1075      * If this value is 0xffff, the device is not associated.
1076      *
1077      * This could useful to simple deassociate an device.
1078      */
1079     if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
1080         return -EINVAL;
1081 
1082     return rdev_set_pan_id(rdev, wpan_dev, pan_id);
1083 }
1084 
1085 static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
1086 {
1087     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1088     struct net_device *dev = info->user_ptr[1];
1089     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1090     __le16 short_addr;
1091 
1092     /* conflict here while tx/rx calls */
1093     if (netif_running(dev))
1094         return -EBUSY;
1095 
1096     if (wpan_dev->lowpan_dev) {
1097         if (netif_running(wpan_dev->lowpan_dev))
1098             return -EBUSY;
1099     }
1100 
1101     /* don't change address fields on monitor */
1102     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR ||
1103         !info->attrs[NL802154_ATTR_SHORT_ADDR])
1104         return -EINVAL;
1105 
1106     short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
1107 
1108     /* TODO
1109      * I am not sure about to check here on broadcast short_addr.
1110      * Broadcast is a valid setting, comment from 802.15.4:
1111      * A value of 0xfffe indicates that the device has
1112      * associated but has not been allocated an address. A
1113      * value of 0xffff indicates that the device does not
1114      * have a short address.
1115      *
1116      * I think we should allow to set these settings but
1117      * don't allow to allow socket communication with it.
1118      */
1119     if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
1120         short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
1121         return -EINVAL;
1122 
1123     return rdev_set_short_addr(rdev, wpan_dev, short_addr);
1124 }
1125 
1126 static int
1127 nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
1128 {
1129     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1130     struct net_device *dev = info->user_ptr[1];
1131     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1132     u8 min_be, max_be;
1133 
1134     /* should be set on netif open inside phy settings */
1135     if (netif_running(dev))
1136         return -EBUSY;
1137 
1138     if (!info->attrs[NL802154_ATTR_MIN_BE] ||
1139         !info->attrs[NL802154_ATTR_MAX_BE])
1140         return -EINVAL;
1141 
1142     min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
1143     max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
1144 
1145     /* check 802.15.4 constraints */
1146     if (min_be < rdev->wpan_phy.supported.min_minbe ||
1147         min_be > rdev->wpan_phy.supported.max_minbe ||
1148         max_be < rdev->wpan_phy.supported.min_maxbe ||
1149         max_be > rdev->wpan_phy.supported.max_maxbe ||
1150         min_be > max_be)
1151         return -EINVAL;
1152 
1153     return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
1154 }
1155 
1156 static int
1157 nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
1158 {
1159     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1160     struct net_device *dev = info->user_ptr[1];
1161     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1162     u8 max_csma_backoffs;
1163 
1164     /* conflict here while other running iface settings */
1165     if (netif_running(dev))
1166         return -EBUSY;
1167 
1168     if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
1169         return -EINVAL;
1170 
1171     max_csma_backoffs = nla_get_u8(
1172             info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
1173 
1174     /* check 802.15.4 constraints */
1175     if (max_csma_backoffs < rdev->wpan_phy.supported.min_csma_backoffs ||
1176         max_csma_backoffs > rdev->wpan_phy.supported.max_csma_backoffs)
1177         return -EINVAL;
1178 
1179     return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
1180 }
1181 
1182 static int
1183 nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
1184 {
1185     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1186     struct net_device *dev = info->user_ptr[1];
1187     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1188     s8 max_frame_retries;
1189 
1190     if (netif_running(dev))
1191         return -EBUSY;
1192 
1193     if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
1194         return -EINVAL;
1195 
1196     max_frame_retries = nla_get_s8(
1197             info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
1198 
1199     /* check 802.15.4 constraints */
1200     if (max_frame_retries < rdev->wpan_phy.supported.min_frame_retries ||
1201         max_frame_retries > rdev->wpan_phy.supported.max_frame_retries)
1202         return -EINVAL;
1203 
1204     return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
1205 }
1206 
1207 static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
1208 {
1209     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1210     struct net_device *dev = info->user_ptr[1];
1211     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1212     int mode;
1213 
1214     if (netif_running(dev))
1215         return -EBUSY;
1216 
1217     if (!info->attrs[NL802154_ATTR_LBT_MODE])
1218         return -EINVAL;
1219 
1220     mode = nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
1221 
1222     if (mode != 0 && mode != 1)
1223         return -EINVAL;
1224 
1225     if (!wpan_phy_supported_bool(mode, rdev->wpan_phy.supported.lbt))
1226         return -EINVAL;
1227 
1228     return rdev_set_lbt_mode(rdev, wpan_dev, mode);
1229 }
1230 
1231 static int
1232 nl802154_set_ackreq_default(struct sk_buff *skb, struct genl_info *info)
1233 {
1234     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1235     struct net_device *dev = info->user_ptr[1];
1236     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1237     int ackreq;
1238 
1239     if (netif_running(dev))
1240         return -EBUSY;
1241 
1242     if (!info->attrs[NL802154_ATTR_ACKREQ_DEFAULT])
1243         return -EINVAL;
1244 
1245     ackreq = nla_get_u8(info->attrs[NL802154_ATTR_ACKREQ_DEFAULT]);
1246 
1247     if (ackreq != 0 && ackreq != 1)
1248         return -EINVAL;
1249 
1250     return rdev_set_ackreq_default(rdev, wpan_dev, ackreq);
1251 }
1252 
1253 static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
1254 {
1255     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1256     struct net *net;
1257     int err;
1258 
1259     if (info->attrs[NL802154_ATTR_PID]) {
1260         u32 pid = nla_get_u32(info->attrs[NL802154_ATTR_PID]);
1261 
1262         net = get_net_ns_by_pid(pid);
1263     } else if (info->attrs[NL802154_ATTR_NETNS_FD]) {
1264         u32 fd = nla_get_u32(info->attrs[NL802154_ATTR_NETNS_FD]);
1265 
1266         net = get_net_ns_by_fd(fd);
1267     } else {
1268         return -EINVAL;
1269     }
1270 
1271     if (IS_ERR(net))
1272         return PTR_ERR(net);
1273 
1274     err = 0;
1275 
1276     /* check if anything to do */
1277     if (!net_eq(wpan_phy_net(&rdev->wpan_phy), net))
1278         err = cfg802154_switch_netns(rdev, net);
1279 
1280     put_net(net);
1281     return err;
1282 }
1283 
1284 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
1285 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
1286     [NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
1287     [NL802154_DEV_ADDR_ATTR_MODE] = { .type = NLA_U32 },
1288     [NL802154_DEV_ADDR_ATTR_SHORT] = { .type = NLA_U16 },
1289     [NL802154_DEV_ADDR_ATTR_EXTENDED] = { .type = NLA_U64 },
1290 };
1291 
1292 static int
1293 ieee802154_llsec_parse_dev_addr(struct nlattr *nla,
1294                 struct ieee802154_addr *addr)
1295 {
1296     struct nlattr *attrs[NL802154_DEV_ADDR_ATTR_MAX + 1];
1297 
1298     if (!nla || nla_parse_nested_deprecated(attrs, NL802154_DEV_ADDR_ATTR_MAX, nla, nl802154_dev_addr_policy, NULL))
1299         return -EINVAL;
1300 
1301     if (!attrs[NL802154_DEV_ADDR_ATTR_PAN_ID] || !attrs[NL802154_DEV_ADDR_ATTR_MODE])
1302         return -EINVAL;
1303 
1304     addr->pan_id = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_PAN_ID]);
1305     addr->mode = nla_get_u32(attrs[NL802154_DEV_ADDR_ATTR_MODE]);
1306     switch (addr->mode) {
1307     case NL802154_DEV_ADDR_SHORT:
1308         if (!attrs[NL802154_DEV_ADDR_ATTR_SHORT])
1309             return -EINVAL;
1310         addr->short_addr = nla_get_le16(attrs[NL802154_DEV_ADDR_ATTR_SHORT]);
1311         break;
1312     case NL802154_DEV_ADDR_EXTENDED:
1313         if (!attrs[NL802154_DEV_ADDR_ATTR_EXTENDED])
1314             return -EINVAL;
1315         addr->extended_addr = nla_get_le64(attrs[NL802154_DEV_ADDR_ATTR_EXTENDED]);
1316         break;
1317     default:
1318         return -EINVAL;
1319     }
1320 
1321     return 0;
1322 }
1323 
1324 static const struct nla_policy nl802154_key_id_policy[NL802154_KEY_ID_ATTR_MAX + 1] = {
1325     [NL802154_KEY_ID_ATTR_MODE] = { .type = NLA_U32 },
1326     [NL802154_KEY_ID_ATTR_INDEX] = { .type = NLA_U8 },
1327     [NL802154_KEY_ID_ATTR_IMPLICIT] = { .type = NLA_NESTED },
1328     [NL802154_KEY_ID_ATTR_SOURCE_SHORT] = { .type = NLA_U32 },
1329     [NL802154_KEY_ID_ATTR_SOURCE_EXTENDED] = { .type = NLA_U64 },
1330 };
1331 
1332 static int
1333 ieee802154_llsec_parse_key_id(struct nlattr *nla,
1334                   struct ieee802154_llsec_key_id *desc)
1335 {
1336     struct nlattr *attrs[NL802154_KEY_ID_ATTR_MAX + 1];
1337 
1338     if (!nla || nla_parse_nested_deprecated(attrs, NL802154_KEY_ID_ATTR_MAX, nla, nl802154_key_id_policy, NULL))
1339         return -EINVAL;
1340 
1341     if (!attrs[NL802154_KEY_ID_ATTR_MODE])
1342         return -EINVAL;
1343 
1344     desc->mode = nla_get_u32(attrs[NL802154_KEY_ID_ATTR_MODE]);
1345     switch (desc->mode) {
1346     case NL802154_KEY_ID_MODE_IMPLICIT:
1347         if (!attrs[NL802154_KEY_ID_ATTR_IMPLICIT])
1348             return -EINVAL;
1349 
1350         if (ieee802154_llsec_parse_dev_addr(attrs[NL802154_KEY_ID_ATTR_IMPLICIT],
1351                             &desc->device_addr) < 0)
1352             return -EINVAL;
1353         break;
1354     case NL802154_KEY_ID_MODE_INDEX:
1355         break;
1356     case NL802154_KEY_ID_MODE_INDEX_SHORT:
1357         if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT])
1358             return -EINVAL;
1359 
1360         desc->short_source = nla_get_le32(attrs[NL802154_KEY_ID_ATTR_SOURCE_SHORT]);
1361         break;
1362     case NL802154_KEY_ID_MODE_INDEX_EXTENDED:
1363         if (!attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED])
1364             return -EINVAL;
1365 
1366         desc->extended_source = nla_get_le64(attrs[NL802154_KEY_ID_ATTR_SOURCE_EXTENDED]);
1367         break;
1368     default:
1369         return -EINVAL;
1370     }
1371 
1372     if (desc->mode != NL802154_KEY_ID_MODE_IMPLICIT) {
1373         if (!attrs[NL802154_KEY_ID_ATTR_INDEX])
1374             return -EINVAL;
1375 
1376         /* TODO change id to idx */
1377         desc->id = nla_get_u8(attrs[NL802154_KEY_ID_ATTR_INDEX]);
1378     }
1379 
1380     return 0;
1381 }
1382 
1383 static int nl802154_set_llsec_params(struct sk_buff *skb,
1384                      struct genl_info *info)
1385 {
1386     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1387     struct net_device *dev = info->user_ptr[1];
1388     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1389     struct ieee802154_llsec_params params;
1390     u32 changed = 0;
1391     int ret;
1392 
1393     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1394         return -EOPNOTSUPP;
1395 
1396     if (info->attrs[NL802154_ATTR_SEC_ENABLED]) {
1397         u8 enabled;
1398 
1399         enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1400         if (enabled != 0 && enabled != 1)
1401             return -EINVAL;
1402 
1403         params.enabled = nla_get_u8(info->attrs[NL802154_ATTR_SEC_ENABLED]);
1404         changed |= IEEE802154_LLSEC_PARAM_ENABLED;
1405     }
1406 
1407     if (info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID]) {
1408         ret = ieee802154_llsec_parse_key_id(info->attrs[NL802154_ATTR_SEC_OUT_KEY_ID],
1409                             &params.out_key);
1410         if (ret < 0)
1411             return ret;
1412 
1413         changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
1414     }
1415 
1416     if (info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]) {
1417         params.out_level = nla_get_u32(info->attrs[NL802154_ATTR_SEC_OUT_LEVEL]);
1418         if (params.out_level > NL802154_SECLEVEL_MAX)
1419             return -EINVAL;
1420 
1421         changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
1422     }
1423 
1424     if (info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]) {
1425         params.frame_counter = nla_get_be32(info->attrs[NL802154_ATTR_SEC_FRAME_COUNTER]);
1426         changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
1427     }
1428 
1429     return rdev_set_llsec_params(rdev, wpan_dev, &params, changed);
1430 }
1431 
1432 static int nl802154_send_key(struct sk_buff *msg, u32 cmd, u32 portid,
1433                  u32 seq, int flags,
1434                  struct cfg802154_registered_device *rdev,
1435                  struct net_device *dev,
1436                  const struct ieee802154_llsec_key_entry *key)
1437 {
1438     void *hdr;
1439     u32 commands[NL802154_CMD_FRAME_NR_IDS / 32];
1440     struct nlattr *nl_key, *nl_key_id;
1441 
1442     hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1443     if (!hdr)
1444         return -ENOBUFS;
1445 
1446     if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1447         goto nla_put_failure;
1448 
1449     nl_key = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_KEY);
1450     if (!nl_key)
1451         goto nla_put_failure;
1452 
1453     nl_key_id = nla_nest_start_noflag(msg, NL802154_KEY_ATTR_ID);
1454     if (!nl_key_id)
1455         goto nla_put_failure;
1456 
1457     if (ieee802154_llsec_send_key_id(msg, &key->id) < 0)
1458         goto nla_put_failure;
1459 
1460     nla_nest_end(msg, nl_key_id);
1461 
1462     if (nla_put_u8(msg, NL802154_KEY_ATTR_USAGE_FRAMES,
1463                key->key->frame_types))
1464         goto nla_put_failure;
1465 
1466     if (key->key->frame_types & BIT(NL802154_FRAME_CMD)) {
1467         /* TODO for each nested */
1468         memset(commands, 0, sizeof(commands));
1469         commands[7] = key->key->cmd_frame_ids;
1470         if (nla_put(msg, NL802154_KEY_ATTR_USAGE_CMDS,
1471                 sizeof(commands), commands))
1472             goto nla_put_failure;
1473     }
1474 
1475     if (nla_put(msg, NL802154_KEY_ATTR_BYTES, NL802154_KEY_SIZE,
1476             key->key->key))
1477         goto nla_put_failure;
1478 
1479     nla_nest_end(msg, nl_key);
1480     genlmsg_end(msg, hdr);
1481 
1482     return 0;
1483 
1484 nla_put_failure:
1485     genlmsg_cancel(msg, hdr);
1486     return -EMSGSIZE;
1487 }
1488 
1489 static int
1490 nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb)
1491 {
1492     struct cfg802154_registered_device *rdev = NULL;
1493     struct ieee802154_llsec_key_entry *key;
1494     struct ieee802154_llsec_table *table;
1495     struct wpan_dev *wpan_dev;
1496     int err;
1497 
1498     err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1499     if (err)
1500         return err;
1501 
1502     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1503         err = skb->len;
1504         goto out_err;
1505     }
1506 
1507     if (!wpan_dev->netdev) {
1508         err = -EINVAL;
1509         goto out_err;
1510     }
1511 
1512     rdev_lock_llsec_table(rdev, wpan_dev);
1513     rdev_get_llsec_table(rdev, wpan_dev, &table);
1514 
1515     /* TODO make it like station dump */
1516     if (cb->args[2])
1517         goto out;
1518 
1519     list_for_each_entry(key, &table->keys, list) {
1520         if (nl802154_send_key(skb, NL802154_CMD_NEW_SEC_KEY,
1521                       NETLINK_CB(cb->skb).portid,
1522                       cb->nlh->nlmsg_seq, NLM_F_MULTI,
1523                       rdev, wpan_dev->netdev, key) < 0) {
1524             /* TODO */
1525             err = -EIO;
1526             rdev_unlock_llsec_table(rdev, wpan_dev);
1527             goto out_err;
1528         }
1529     }
1530 
1531     cb->args[2] = 1;
1532 
1533 out:
1534     rdev_unlock_llsec_table(rdev, wpan_dev);
1535     err = skb->len;
1536 out_err:
1537     nl802154_finish_wpan_dev_dump(rdev);
1538 
1539     return err;
1540 }
1541 
1542 static const struct nla_policy nl802154_key_policy[NL802154_KEY_ATTR_MAX + 1] = {
1543     [NL802154_KEY_ATTR_ID] = { NLA_NESTED },
1544     /* TODO handle it as for_each_nested and NLA_FLAG? */
1545     [NL802154_KEY_ATTR_USAGE_FRAMES] = { NLA_U8 },
1546     /* TODO handle it as for_each_nested, not static array? */
1547     [NL802154_KEY_ATTR_USAGE_CMDS] = { .len = NL802154_CMD_FRAME_NR_IDS / 8 },
1548     [NL802154_KEY_ATTR_BYTES] = { .len = NL802154_KEY_SIZE },
1549 };
1550 
1551 static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info)
1552 {
1553     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1554     struct net_device *dev = info->user_ptr[1];
1555     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1556     struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1557     struct ieee802154_llsec_key key = { };
1558     struct ieee802154_llsec_key_id id = { };
1559     u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { };
1560 
1561     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1562         return -EOPNOTSUPP;
1563 
1564     if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
1565         nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack))
1566         return -EINVAL;
1567 
1568     if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] ||
1569         !attrs[NL802154_KEY_ATTR_BYTES])
1570         return -EINVAL;
1571 
1572     if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1573         return -ENOBUFS;
1574 
1575     key.frame_types = nla_get_u8(attrs[NL802154_KEY_ATTR_USAGE_FRAMES]);
1576     if (key.frame_types > BIT(NL802154_FRAME_MAX) ||
1577         ((key.frame_types & BIT(NL802154_FRAME_CMD)) &&
1578          !attrs[NL802154_KEY_ATTR_USAGE_CMDS]))
1579         return -EINVAL;
1580 
1581     if (attrs[NL802154_KEY_ATTR_USAGE_CMDS]) {
1582         /* TODO for each nested */
1583         nla_memcpy(commands, attrs[NL802154_KEY_ATTR_USAGE_CMDS],
1584                NL802154_CMD_FRAME_NR_IDS / 8);
1585 
1586         /* TODO understand the -EINVAL logic here? last condition */
1587         if (commands[0] || commands[1] || commands[2] || commands[3] ||
1588             commands[4] || commands[5] || commands[6] ||
1589             commands[7] > BIT(NL802154_CMD_FRAME_MAX))
1590             return -EINVAL;
1591 
1592         key.cmd_frame_ids = commands[7];
1593     } else {
1594         key.cmd_frame_ids = 0;
1595     }
1596 
1597     nla_memcpy(key.key, attrs[NL802154_KEY_ATTR_BYTES], NL802154_KEY_SIZE);
1598 
1599     if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1600         return -ENOBUFS;
1601 
1602     return rdev_add_llsec_key(rdev, wpan_dev, &id, &key);
1603 }
1604 
1605 static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info)
1606 {
1607     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1608     struct net_device *dev = info->user_ptr[1];
1609     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1610     struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1];
1611     struct ieee802154_llsec_key_id id;
1612 
1613     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1614         return -EOPNOTSUPP;
1615 
1616     if (!info->attrs[NL802154_ATTR_SEC_KEY] ||
1617         nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack))
1618         return -EINVAL;
1619 
1620     if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0)
1621         return -ENOBUFS;
1622 
1623     return rdev_del_llsec_key(rdev, wpan_dev, &id);
1624 }
1625 
1626 static int nl802154_send_device(struct sk_buff *msg, u32 cmd, u32 portid,
1627                 u32 seq, int flags,
1628                 struct cfg802154_registered_device *rdev,
1629                 struct net_device *dev,
1630                 const struct ieee802154_llsec_device *dev_desc)
1631 {
1632     void *hdr;
1633     struct nlattr *nl_device;
1634 
1635     hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1636     if (!hdr)
1637         return -ENOBUFS;
1638 
1639     if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1640         goto nla_put_failure;
1641 
1642     nl_device = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_DEVICE);
1643     if (!nl_device)
1644         goto nla_put_failure;
1645 
1646     if (nla_put_u32(msg, NL802154_DEV_ATTR_FRAME_COUNTER,
1647             dev_desc->frame_counter) ||
1648         nla_put_le16(msg, NL802154_DEV_ATTR_PAN_ID, dev_desc->pan_id) ||
1649         nla_put_le16(msg, NL802154_DEV_ATTR_SHORT_ADDR,
1650              dev_desc->short_addr) ||
1651         nla_put_le64(msg, NL802154_DEV_ATTR_EXTENDED_ADDR,
1652              dev_desc->hwaddr, NL802154_DEV_ATTR_PAD) ||
1653         nla_put_u8(msg, NL802154_DEV_ATTR_SECLEVEL_EXEMPT,
1654                dev_desc->seclevel_exempt) ||
1655         nla_put_u32(msg, NL802154_DEV_ATTR_KEY_MODE, dev_desc->key_mode))
1656         goto nla_put_failure;
1657 
1658     nla_nest_end(msg, nl_device);
1659     genlmsg_end(msg, hdr);
1660 
1661     return 0;
1662 
1663 nla_put_failure:
1664     genlmsg_cancel(msg, hdr);
1665     return -EMSGSIZE;
1666 }
1667 
1668 static int
1669 nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb)
1670 {
1671     struct cfg802154_registered_device *rdev = NULL;
1672     struct ieee802154_llsec_device *dev;
1673     struct ieee802154_llsec_table *table;
1674     struct wpan_dev *wpan_dev;
1675     int err;
1676 
1677     err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1678     if (err)
1679         return err;
1680 
1681     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1682         err = skb->len;
1683         goto out_err;
1684     }
1685 
1686     if (!wpan_dev->netdev) {
1687         err = -EINVAL;
1688         goto out_err;
1689     }
1690 
1691     rdev_lock_llsec_table(rdev, wpan_dev);
1692     rdev_get_llsec_table(rdev, wpan_dev, &table);
1693 
1694     /* TODO make it like station dump */
1695     if (cb->args[2])
1696         goto out;
1697 
1698     list_for_each_entry(dev, &table->devices, list) {
1699         if (nl802154_send_device(skb, NL802154_CMD_NEW_SEC_LEVEL,
1700                      NETLINK_CB(cb->skb).portid,
1701                      cb->nlh->nlmsg_seq, NLM_F_MULTI,
1702                      rdev, wpan_dev->netdev, dev) < 0) {
1703             /* TODO */
1704             err = -EIO;
1705             rdev_unlock_llsec_table(rdev, wpan_dev);
1706             goto out_err;
1707         }
1708     }
1709 
1710     cb->args[2] = 1;
1711 
1712 out:
1713     rdev_unlock_llsec_table(rdev, wpan_dev);
1714     err = skb->len;
1715 out_err:
1716     nl802154_finish_wpan_dev_dump(rdev);
1717 
1718     return err;
1719 }
1720 
1721 static const struct nla_policy nl802154_dev_policy[NL802154_DEV_ATTR_MAX + 1] = {
1722     [NL802154_DEV_ATTR_FRAME_COUNTER] = { NLA_U32 },
1723     [NL802154_DEV_ATTR_PAN_ID] = { .type = NLA_U16 },
1724     [NL802154_DEV_ATTR_SHORT_ADDR] = { .type = NLA_U16 },
1725     [NL802154_DEV_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
1726     [NL802154_DEV_ATTR_SECLEVEL_EXEMPT] = { NLA_U8 },
1727     [NL802154_DEV_ATTR_KEY_MODE] = { NLA_U32 },
1728 };
1729 
1730 static int
1731 ieee802154_llsec_parse_device(struct nlattr *nla,
1732                   struct ieee802154_llsec_device *dev)
1733 {
1734     struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1735 
1736     if (!nla || nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, nla, nl802154_dev_policy, NULL))
1737         return -EINVAL;
1738 
1739     memset(dev, 0, sizeof(*dev));
1740 
1741     if (!attrs[NL802154_DEV_ATTR_FRAME_COUNTER] ||
1742         !attrs[NL802154_DEV_ATTR_PAN_ID] ||
1743         !attrs[NL802154_DEV_ATTR_SHORT_ADDR] ||
1744         !attrs[NL802154_DEV_ATTR_EXTENDED_ADDR] ||
1745         !attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT] ||
1746         !attrs[NL802154_DEV_ATTR_KEY_MODE])
1747         return -EINVAL;
1748 
1749     /* TODO be32 */
1750     dev->frame_counter = nla_get_u32(attrs[NL802154_DEV_ATTR_FRAME_COUNTER]);
1751     dev->pan_id = nla_get_le16(attrs[NL802154_DEV_ATTR_PAN_ID]);
1752     dev->short_addr = nla_get_le16(attrs[NL802154_DEV_ATTR_SHORT_ADDR]);
1753     /* TODO rename hwaddr to extended_addr */
1754     dev->hwaddr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1755     dev->seclevel_exempt = nla_get_u8(attrs[NL802154_DEV_ATTR_SECLEVEL_EXEMPT]);
1756     dev->key_mode = nla_get_u32(attrs[NL802154_DEV_ATTR_KEY_MODE]);
1757 
1758     if (dev->key_mode > NL802154_DEVKEY_MAX ||
1759         (dev->seclevel_exempt != 0 && dev->seclevel_exempt != 1))
1760         return -EINVAL;
1761 
1762     return 0;
1763 }
1764 
1765 static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info)
1766 {
1767     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1768     struct net_device *dev = info->user_ptr[1];
1769     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1770     struct ieee802154_llsec_device dev_desc;
1771 
1772     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1773         return -EOPNOTSUPP;
1774 
1775     if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE],
1776                       &dev_desc) < 0)
1777         return -EINVAL;
1778 
1779     return rdev_add_device(rdev, wpan_dev, &dev_desc);
1780 }
1781 
1782 static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info)
1783 {
1784     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1785     struct net_device *dev = info->user_ptr[1];
1786     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1787     struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1];
1788     __le64 extended_addr;
1789 
1790     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1791         return -EOPNOTSUPP;
1792 
1793     if (!info->attrs[NL802154_ATTR_SEC_DEVICE] ||
1794         nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack))
1795         return -EINVAL;
1796 
1797     if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR])
1798         return -EINVAL;
1799 
1800     extended_addr = nla_get_le64(attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]);
1801     return rdev_del_device(rdev, wpan_dev, extended_addr);
1802 }
1803 
1804 static int nl802154_send_devkey(struct sk_buff *msg, u32 cmd, u32 portid,
1805                 u32 seq, int flags,
1806                 struct cfg802154_registered_device *rdev,
1807                 struct net_device *dev, __le64 extended_addr,
1808                 const struct ieee802154_llsec_device_key *devkey)
1809 {
1810     void *hdr;
1811     struct nlattr *nl_devkey, *nl_key_id;
1812 
1813     hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1814     if (!hdr)
1815         return -ENOBUFS;
1816 
1817     if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1818         goto nla_put_failure;
1819 
1820     nl_devkey = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_DEVKEY);
1821     if (!nl_devkey)
1822         goto nla_put_failure;
1823 
1824     if (nla_put_le64(msg, NL802154_DEVKEY_ATTR_EXTENDED_ADDR,
1825              extended_addr, NL802154_DEVKEY_ATTR_PAD) ||
1826         nla_put_u32(msg, NL802154_DEVKEY_ATTR_FRAME_COUNTER,
1827             devkey->frame_counter))
1828         goto nla_put_failure;
1829 
1830     nl_key_id = nla_nest_start_noflag(msg, NL802154_DEVKEY_ATTR_ID);
1831     if (!nl_key_id)
1832         goto nla_put_failure;
1833 
1834     if (ieee802154_llsec_send_key_id(msg, &devkey->key_id) < 0)
1835         goto nla_put_failure;
1836 
1837     nla_nest_end(msg, nl_key_id);
1838     nla_nest_end(msg, nl_devkey);
1839     genlmsg_end(msg, hdr);
1840 
1841     return 0;
1842 
1843 nla_put_failure:
1844     genlmsg_cancel(msg, hdr);
1845     return -EMSGSIZE;
1846 }
1847 
1848 static int
1849 nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb)
1850 {
1851     struct cfg802154_registered_device *rdev = NULL;
1852     struct ieee802154_llsec_device_key *kpos;
1853     struct ieee802154_llsec_device *dpos;
1854     struct ieee802154_llsec_table *table;
1855     struct wpan_dev *wpan_dev;
1856     int err;
1857 
1858     err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
1859     if (err)
1860         return err;
1861 
1862     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
1863         err = skb->len;
1864         goto out_err;
1865     }
1866 
1867     if (!wpan_dev->netdev) {
1868         err = -EINVAL;
1869         goto out_err;
1870     }
1871 
1872     rdev_lock_llsec_table(rdev, wpan_dev);
1873     rdev_get_llsec_table(rdev, wpan_dev, &table);
1874 
1875     /* TODO make it like station dump */
1876     if (cb->args[2])
1877         goto out;
1878 
1879     /* TODO look if remove devkey and do some nested attribute */
1880     list_for_each_entry(dpos, &table->devices, list) {
1881         list_for_each_entry(kpos, &dpos->keys, list) {
1882             if (nl802154_send_devkey(skb,
1883                          NL802154_CMD_NEW_SEC_LEVEL,
1884                          NETLINK_CB(cb->skb).portid,
1885                          cb->nlh->nlmsg_seq,
1886                          NLM_F_MULTI, rdev,
1887                          wpan_dev->netdev,
1888                          dpos->hwaddr,
1889                          kpos) < 0) {
1890                 /* TODO */
1891                 err = -EIO;
1892                 rdev_unlock_llsec_table(rdev, wpan_dev);
1893                 goto out_err;
1894             }
1895         }
1896     }
1897 
1898     cb->args[2] = 1;
1899 
1900 out:
1901     rdev_unlock_llsec_table(rdev, wpan_dev);
1902     err = skb->len;
1903 out_err:
1904     nl802154_finish_wpan_dev_dump(rdev);
1905 
1906     return err;
1907 }
1908 
1909 static const struct nla_policy nl802154_devkey_policy[NL802154_DEVKEY_ATTR_MAX + 1] = {
1910     [NL802154_DEVKEY_ATTR_FRAME_COUNTER] = { NLA_U32 },
1911     [NL802154_DEVKEY_ATTR_EXTENDED_ADDR] = { NLA_U64 },
1912     [NL802154_DEVKEY_ATTR_ID] = { NLA_NESTED },
1913 };
1914 
1915 static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1916 {
1917     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1918     struct net_device *dev = info->user_ptr[1];
1919     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1920     struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1921     struct ieee802154_llsec_device_key key;
1922     __le64 extended_addr;
1923 
1924     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1925         return -EOPNOTSUPP;
1926 
1927     if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
1928         nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack) < 0)
1929         return -EINVAL;
1930 
1931     if (!attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER] ||
1932         !attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1933         return -EINVAL;
1934 
1935     /* TODO change key.id ? */
1936     if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1937                       &key.key_id) < 0)
1938         return -ENOBUFS;
1939 
1940     /* TODO be32 */
1941     key.frame_counter = nla_get_u32(attrs[NL802154_DEVKEY_ATTR_FRAME_COUNTER]);
1942     /* TODO change naming hwaddr -> extended_addr
1943      * check unique identifier short+pan OR extended_addr
1944      */
1945     extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1946     return rdev_add_devkey(rdev, wpan_dev, extended_addr, &key);
1947 }
1948 
1949 static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info)
1950 {
1951     struct cfg802154_registered_device *rdev = info->user_ptr[0];
1952     struct net_device *dev = info->user_ptr[1];
1953     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
1954     struct nlattr *attrs[NL802154_DEVKEY_ATTR_MAX + 1];
1955     struct ieee802154_llsec_device_key key;
1956     __le64 extended_addr;
1957 
1958     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
1959         return -EOPNOTSUPP;
1960 
1961     if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] ||
1962         nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack))
1963         return -EINVAL;
1964 
1965     if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR])
1966         return -EINVAL;
1967 
1968     /* TODO change key.id ? */
1969     if (ieee802154_llsec_parse_key_id(attrs[NL802154_DEVKEY_ATTR_ID],
1970                       &key.key_id) < 0)
1971         return -ENOBUFS;
1972 
1973     /* TODO change naming hwaddr -> extended_addr
1974      * check unique identifier short+pan OR extended_addr
1975      */
1976     extended_addr = nla_get_le64(attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]);
1977     return rdev_del_devkey(rdev, wpan_dev, extended_addr, &key);
1978 }
1979 
1980 static int nl802154_send_seclevel(struct sk_buff *msg, u32 cmd, u32 portid,
1981                   u32 seq, int flags,
1982                   struct cfg802154_registered_device *rdev,
1983                   struct net_device *dev,
1984                   const struct ieee802154_llsec_seclevel *sl)
1985 {
1986     void *hdr;
1987     struct nlattr *nl_seclevel;
1988 
1989     hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
1990     if (!hdr)
1991         return -ENOBUFS;
1992 
1993     if (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex))
1994         goto nla_put_failure;
1995 
1996     nl_seclevel = nla_nest_start_noflag(msg, NL802154_ATTR_SEC_LEVEL);
1997     if (!nl_seclevel)
1998         goto nla_put_failure;
1999 
2000     if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_FRAME, sl->frame_type) ||
2001         nla_put_u32(msg, NL802154_SECLEVEL_ATTR_LEVELS, sl->sec_levels) ||
2002         nla_put_u8(msg, NL802154_SECLEVEL_ATTR_DEV_OVERRIDE,
2003                sl->device_override))
2004         goto nla_put_failure;
2005 
2006     if (sl->frame_type == NL802154_FRAME_CMD) {
2007         if (nla_put_u32(msg, NL802154_SECLEVEL_ATTR_CMD_FRAME,
2008                 sl->cmd_frame_id))
2009             goto nla_put_failure;
2010     }
2011 
2012     nla_nest_end(msg, nl_seclevel);
2013     genlmsg_end(msg, hdr);
2014 
2015     return 0;
2016 
2017 nla_put_failure:
2018     genlmsg_cancel(msg, hdr);
2019     return -EMSGSIZE;
2020 }
2021 
2022 static int
2023 nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb)
2024 {
2025     struct cfg802154_registered_device *rdev = NULL;
2026     struct ieee802154_llsec_seclevel *sl;
2027     struct ieee802154_llsec_table *table;
2028     struct wpan_dev *wpan_dev;
2029     int err;
2030 
2031     err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
2032     if (err)
2033         return err;
2034 
2035     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) {
2036         err = skb->len;
2037         goto out_err;
2038     }
2039 
2040     if (!wpan_dev->netdev) {
2041         err = -EINVAL;
2042         goto out_err;
2043     }
2044 
2045     rdev_lock_llsec_table(rdev, wpan_dev);
2046     rdev_get_llsec_table(rdev, wpan_dev, &table);
2047 
2048     /* TODO make it like station dump */
2049     if (cb->args[2])
2050         goto out;
2051 
2052     list_for_each_entry(sl, &table->security_levels, list) {
2053         if (nl802154_send_seclevel(skb, NL802154_CMD_NEW_SEC_LEVEL,
2054                        NETLINK_CB(cb->skb).portid,
2055                        cb->nlh->nlmsg_seq, NLM_F_MULTI,
2056                        rdev, wpan_dev->netdev, sl) < 0) {
2057             /* TODO */
2058             err = -EIO;
2059             rdev_unlock_llsec_table(rdev, wpan_dev);
2060             goto out_err;
2061         }
2062     }
2063 
2064     cb->args[2] = 1;
2065 
2066 out:
2067     rdev_unlock_llsec_table(rdev, wpan_dev);
2068     err = skb->len;
2069 out_err:
2070     nl802154_finish_wpan_dev_dump(rdev);
2071 
2072     return err;
2073 }
2074 
2075 static const struct nla_policy nl802154_seclevel_policy[NL802154_SECLEVEL_ATTR_MAX + 1] = {
2076     [NL802154_SECLEVEL_ATTR_LEVELS] = { .type = NLA_U8 },
2077     [NL802154_SECLEVEL_ATTR_FRAME] = { .type = NLA_U32 },
2078     [NL802154_SECLEVEL_ATTR_CMD_FRAME] = { .type = NLA_U32 },
2079     [NL802154_SECLEVEL_ATTR_DEV_OVERRIDE] = { .type = NLA_U8 },
2080 };
2081 
2082 static int
2083 llsec_parse_seclevel(struct nlattr *nla, struct ieee802154_llsec_seclevel *sl)
2084 {
2085     struct nlattr *attrs[NL802154_SECLEVEL_ATTR_MAX + 1];
2086 
2087     if (!nla || nla_parse_nested_deprecated(attrs, NL802154_SECLEVEL_ATTR_MAX, nla, nl802154_seclevel_policy, NULL))
2088         return -EINVAL;
2089 
2090     memset(sl, 0, sizeof(*sl));
2091 
2092     if (!attrs[NL802154_SECLEVEL_ATTR_LEVELS] ||
2093         !attrs[NL802154_SECLEVEL_ATTR_FRAME] ||
2094         !attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE])
2095         return -EINVAL;
2096 
2097     sl->sec_levels = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_LEVELS]);
2098     sl->frame_type = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_FRAME]);
2099     sl->device_override = nla_get_u8(attrs[NL802154_SECLEVEL_ATTR_DEV_OVERRIDE]);
2100     if (sl->frame_type > NL802154_FRAME_MAX ||
2101         (sl->device_override != 0 && sl->device_override != 1))
2102         return -EINVAL;
2103 
2104     if (sl->frame_type == NL802154_FRAME_CMD) {
2105         if (!attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME])
2106             return -EINVAL;
2107 
2108         sl->cmd_frame_id = nla_get_u32(attrs[NL802154_SECLEVEL_ATTR_CMD_FRAME]);
2109         if (sl->cmd_frame_id > NL802154_CMD_FRAME_MAX)
2110             return -EINVAL;
2111     }
2112 
2113     return 0;
2114 }
2115 
2116 static int nl802154_add_llsec_seclevel(struct sk_buff *skb,
2117                        struct genl_info *info)
2118 {
2119     struct cfg802154_registered_device *rdev = info->user_ptr[0];
2120     struct net_device *dev = info->user_ptr[1];
2121     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2122     struct ieee802154_llsec_seclevel sl;
2123 
2124     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2125         return -EOPNOTSUPP;
2126 
2127     if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2128                  &sl) < 0)
2129         return -EINVAL;
2130 
2131     return rdev_add_seclevel(rdev, wpan_dev, &sl);
2132 }
2133 
2134 static int nl802154_del_llsec_seclevel(struct sk_buff *skb,
2135                        struct genl_info *info)
2136 {
2137     struct cfg802154_registered_device *rdev = info->user_ptr[0];
2138     struct net_device *dev = info->user_ptr[1];
2139     struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
2140     struct ieee802154_llsec_seclevel sl;
2141 
2142     if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
2143         return -EOPNOTSUPP;
2144 
2145     if (!info->attrs[NL802154_ATTR_SEC_LEVEL] ||
2146         llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL],
2147                  &sl) < 0)
2148         return -EINVAL;
2149 
2150     return rdev_del_seclevel(rdev, wpan_dev, &sl);
2151 }
2152 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2153 
2154 #define NL802154_FLAG_NEED_WPAN_PHY 0x01
2155 #define NL802154_FLAG_NEED_NETDEV   0x02
2156 #define NL802154_FLAG_NEED_RTNL     0x04
2157 #define NL802154_FLAG_CHECK_NETDEV_UP   0x08
2158 #define NL802154_FLAG_NEED_WPAN_DEV 0x10
2159 
2160 static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
2161                  struct genl_info *info)
2162 {
2163     struct cfg802154_registered_device *rdev;
2164     struct wpan_dev *wpan_dev;
2165     struct net_device *dev;
2166     bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
2167 
2168     if (rtnl)
2169         rtnl_lock();
2170 
2171     if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
2172         rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
2173         if (IS_ERR(rdev)) {
2174             if (rtnl)
2175                 rtnl_unlock();
2176             return PTR_ERR(rdev);
2177         }
2178         info->user_ptr[0] = rdev;
2179     } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
2180            ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2181         ASSERT_RTNL();
2182         wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
2183                                info->attrs);
2184         if (IS_ERR(wpan_dev)) {
2185             if (rtnl)
2186                 rtnl_unlock();
2187             return PTR_ERR(wpan_dev);
2188         }
2189 
2190         dev = wpan_dev->netdev;
2191         rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
2192 
2193         if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
2194             if (!dev) {
2195                 if (rtnl)
2196                     rtnl_unlock();
2197                 return -EINVAL;
2198             }
2199 
2200             info->user_ptr[1] = dev;
2201         } else {
2202             info->user_ptr[1] = wpan_dev;
2203         }
2204 
2205         if (dev) {
2206             if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
2207                 !netif_running(dev)) {
2208                 if (rtnl)
2209                     rtnl_unlock();
2210                 return -ENETDOWN;
2211             }
2212 
2213             dev_hold(dev);
2214         }
2215 
2216         info->user_ptr[0] = rdev;
2217     }
2218 
2219     return 0;
2220 }
2221 
2222 static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
2223                    struct genl_info *info)
2224 {
2225     if (info->user_ptr[1]) {
2226         if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
2227             struct wpan_dev *wpan_dev = info->user_ptr[1];
2228 
2229             dev_put(wpan_dev->netdev);
2230         } else {
2231             dev_put(info->user_ptr[1]);
2232         }
2233     }
2234 
2235     if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
2236         rtnl_unlock();
2237 }
2238 
2239 static const struct genl_ops nl802154_ops[] = {
2240     {
2241         .cmd = NL802154_CMD_GET_WPAN_PHY,
2242         .validate = GENL_DONT_VALIDATE_STRICT |
2243                 GENL_DONT_VALIDATE_DUMP_STRICT,
2244         .doit = nl802154_get_wpan_phy,
2245         .dumpit = nl802154_dump_wpan_phy,
2246         .done = nl802154_dump_wpan_phy_done,
2247         /* can be retrieved by unprivileged users */
2248         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2249                   NL802154_FLAG_NEED_RTNL,
2250     },
2251     {
2252         .cmd = NL802154_CMD_GET_INTERFACE,
2253         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2254         .doit = nl802154_get_interface,
2255         .dumpit = nl802154_dump_interface,
2256         /* can be retrieved by unprivileged users */
2257         .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2258                   NL802154_FLAG_NEED_RTNL,
2259     },
2260     {
2261         .cmd = NL802154_CMD_NEW_INTERFACE,
2262         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2263         .doit = nl802154_new_interface,
2264         .flags = GENL_ADMIN_PERM,
2265         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2266                   NL802154_FLAG_NEED_RTNL,
2267     },
2268     {
2269         .cmd = NL802154_CMD_DEL_INTERFACE,
2270         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2271         .doit = nl802154_del_interface,
2272         .flags = GENL_ADMIN_PERM,
2273         .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
2274                   NL802154_FLAG_NEED_RTNL,
2275     },
2276     {
2277         .cmd = NL802154_CMD_SET_CHANNEL,
2278         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2279         .doit = nl802154_set_channel,
2280         .flags = GENL_ADMIN_PERM,
2281         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2282                   NL802154_FLAG_NEED_RTNL,
2283     },
2284     {
2285         .cmd = NL802154_CMD_SET_CCA_MODE,
2286         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2287         .doit = nl802154_set_cca_mode,
2288         .flags = GENL_ADMIN_PERM,
2289         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2290                   NL802154_FLAG_NEED_RTNL,
2291     },
2292     {
2293         .cmd = NL802154_CMD_SET_CCA_ED_LEVEL,
2294         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2295         .doit = nl802154_set_cca_ed_level,
2296         .flags = GENL_ADMIN_PERM,
2297         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2298                   NL802154_FLAG_NEED_RTNL,
2299     },
2300     {
2301         .cmd = NL802154_CMD_SET_TX_POWER,
2302         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2303         .doit = nl802154_set_tx_power,
2304         .flags = GENL_ADMIN_PERM,
2305         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2306                   NL802154_FLAG_NEED_RTNL,
2307     },
2308     {
2309         .cmd = NL802154_CMD_SET_WPAN_PHY_NETNS,
2310         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2311         .doit = nl802154_wpan_phy_netns,
2312         .flags = GENL_ADMIN_PERM,
2313         .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
2314                   NL802154_FLAG_NEED_RTNL,
2315     },
2316     {
2317         .cmd = NL802154_CMD_SET_PAN_ID,
2318         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2319         .doit = nl802154_set_pan_id,
2320         .flags = GENL_ADMIN_PERM,
2321         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2322                   NL802154_FLAG_NEED_RTNL,
2323     },
2324     {
2325         .cmd = NL802154_CMD_SET_SHORT_ADDR,
2326         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2327         .doit = nl802154_set_short_addr,
2328         .flags = GENL_ADMIN_PERM,
2329         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2330                   NL802154_FLAG_NEED_RTNL,
2331     },
2332     {
2333         .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
2334         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2335         .doit = nl802154_set_backoff_exponent,
2336         .flags = GENL_ADMIN_PERM,
2337         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2338                   NL802154_FLAG_NEED_RTNL,
2339     },
2340     {
2341         .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
2342         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2343         .doit = nl802154_set_max_csma_backoffs,
2344         .flags = GENL_ADMIN_PERM,
2345         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2346                   NL802154_FLAG_NEED_RTNL,
2347     },
2348     {
2349         .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
2350         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2351         .doit = nl802154_set_max_frame_retries,
2352         .flags = GENL_ADMIN_PERM,
2353         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2354                   NL802154_FLAG_NEED_RTNL,
2355     },
2356     {
2357         .cmd = NL802154_CMD_SET_LBT_MODE,
2358         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2359         .doit = nl802154_set_lbt_mode,
2360         .flags = GENL_ADMIN_PERM,
2361         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2362                   NL802154_FLAG_NEED_RTNL,
2363     },
2364     {
2365         .cmd = NL802154_CMD_SET_ACKREQ_DEFAULT,
2366         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2367         .doit = nl802154_set_ackreq_default,
2368         .flags = GENL_ADMIN_PERM,
2369         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2370                   NL802154_FLAG_NEED_RTNL,
2371     },
2372 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
2373     {
2374         .cmd = NL802154_CMD_SET_SEC_PARAMS,
2375         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2376         .doit = nl802154_set_llsec_params,
2377         .flags = GENL_ADMIN_PERM,
2378         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2379                   NL802154_FLAG_NEED_RTNL,
2380     },
2381     {
2382         .cmd = NL802154_CMD_GET_SEC_KEY,
2383         .validate = GENL_DONT_VALIDATE_STRICT |
2384                 GENL_DONT_VALIDATE_DUMP_STRICT,
2385         /* TODO .doit by matching key id? */
2386         .dumpit = nl802154_dump_llsec_key,
2387         .flags = GENL_ADMIN_PERM,
2388         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2389                   NL802154_FLAG_NEED_RTNL,
2390     },
2391     {
2392         .cmd = NL802154_CMD_NEW_SEC_KEY,
2393         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2394         .doit = nl802154_add_llsec_key,
2395         .flags = GENL_ADMIN_PERM,
2396         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2397                   NL802154_FLAG_NEED_RTNL,
2398     },
2399     {
2400         .cmd = NL802154_CMD_DEL_SEC_KEY,
2401         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2402         .doit = nl802154_del_llsec_key,
2403         .flags = GENL_ADMIN_PERM,
2404         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2405                   NL802154_FLAG_NEED_RTNL,
2406     },
2407     /* TODO unique identifier must short+pan OR extended_addr */
2408     {
2409         .cmd = NL802154_CMD_GET_SEC_DEV,
2410         .validate = GENL_DONT_VALIDATE_STRICT |
2411                 GENL_DONT_VALIDATE_DUMP_STRICT,
2412         /* TODO .doit by matching extended_addr? */
2413         .dumpit = nl802154_dump_llsec_dev,
2414         .flags = GENL_ADMIN_PERM,
2415         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2416                   NL802154_FLAG_NEED_RTNL,
2417     },
2418     {
2419         .cmd = NL802154_CMD_NEW_SEC_DEV,
2420         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2421         .doit = nl802154_add_llsec_dev,
2422         .flags = GENL_ADMIN_PERM,
2423         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2424                   NL802154_FLAG_NEED_RTNL,
2425     },
2426     {
2427         .cmd = NL802154_CMD_DEL_SEC_DEV,
2428         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2429         .doit = nl802154_del_llsec_dev,
2430         .flags = GENL_ADMIN_PERM,
2431         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2432                   NL802154_FLAG_NEED_RTNL,
2433     },
2434     /* TODO remove complete devkey, put it as nested? */
2435     {
2436         .cmd = NL802154_CMD_GET_SEC_DEVKEY,
2437         .validate = GENL_DONT_VALIDATE_STRICT |
2438                 GENL_DONT_VALIDATE_DUMP_STRICT,
2439         /* TODO doit by matching ??? */
2440         .dumpit = nl802154_dump_llsec_devkey,
2441         .flags = GENL_ADMIN_PERM,
2442         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2443                   NL802154_FLAG_NEED_RTNL,
2444     },
2445     {
2446         .cmd = NL802154_CMD_NEW_SEC_DEVKEY,
2447         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2448         .doit = nl802154_add_llsec_devkey,
2449         .flags = GENL_ADMIN_PERM,
2450         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2451                   NL802154_FLAG_NEED_RTNL,
2452     },
2453     {
2454         .cmd = NL802154_CMD_DEL_SEC_DEVKEY,
2455         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2456         .doit = nl802154_del_llsec_devkey,
2457         .flags = GENL_ADMIN_PERM,
2458         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2459                   NL802154_FLAG_NEED_RTNL,
2460     },
2461     {
2462         .cmd = NL802154_CMD_GET_SEC_LEVEL,
2463         .validate = GENL_DONT_VALIDATE_STRICT |
2464                 GENL_DONT_VALIDATE_DUMP_STRICT,
2465         /* TODO .doit by matching frame_type? */
2466         .dumpit = nl802154_dump_llsec_seclevel,
2467         .flags = GENL_ADMIN_PERM,
2468         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2469                   NL802154_FLAG_NEED_RTNL,
2470     },
2471     {
2472         .cmd = NL802154_CMD_NEW_SEC_LEVEL,
2473         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2474         .doit = nl802154_add_llsec_seclevel,
2475         .flags = GENL_ADMIN_PERM,
2476         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2477                   NL802154_FLAG_NEED_RTNL,
2478     },
2479     {
2480         .cmd = NL802154_CMD_DEL_SEC_LEVEL,
2481         .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2482         /* TODO match frame_type only? */
2483         .doit = nl802154_del_llsec_seclevel,
2484         .flags = GENL_ADMIN_PERM,
2485         .internal_flags = NL802154_FLAG_NEED_NETDEV |
2486                   NL802154_FLAG_NEED_RTNL,
2487     },
2488 #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
2489 };
2490 
2491 static struct genl_family nl802154_fam __ro_after_init = {
2492     .name = NL802154_GENL_NAME, /* have users key off the name instead */
2493     .hdrsize = 0,           /* no private header */
2494     .version = 1,           /* no particular meaning now */
2495     .maxattr = NL802154_ATTR_MAX,
2496     .policy = nl802154_policy,
2497     .netnsok = true,
2498     .pre_doit = nl802154_pre_doit,
2499     .post_doit = nl802154_post_doit,
2500     .module = THIS_MODULE,
2501     .ops = nl802154_ops,
2502     .n_ops = ARRAY_SIZE(nl802154_ops),
2503     .mcgrps = nl802154_mcgrps,
2504     .n_mcgrps = ARRAY_SIZE(nl802154_mcgrps),
2505 };
2506 
2507 /* initialisation/exit functions */
2508 int __init nl802154_init(void)
2509 {
2510     return genl_register_family(&nl802154_fam);
2511 }
2512 
2513 void nl802154_exit(void)
2514 {
2515     genl_unregister_family(&nl802154_fam);
2516 }