root/net/ieee802154/nl-mac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nla_put_hwaddr
  2. nla_get_hwaddr
  3. nla_put_shortaddr
  4. nla_get_shortaddr
  5. ieee802154_nl_start_confirm
  6. ieee802154_nl_fill_iface
  7. ieee802154_nl_get_dev
  8. ieee802154_associate_req
  9. ieee802154_associate_resp
  10. ieee802154_disassociate_req
  11. ieee802154_start_req
  12. ieee802154_scan_req
  13. ieee802154_list_iface
  14. ieee802154_dump_iface
  15. ieee802154_set_macparams
  16. ieee802154_llsec_parse_key_id
  17. ieee802154_llsec_fill_key_id
  18. ieee802154_llsec_getparams
  19. ieee802154_llsec_setparams
  20. ieee802154_llsec_dump_table
  21. ieee802154_nl_llsec_change
  22. ieee802154_llsec_parse_key
  23. llsec_add_key
  24. ieee802154_llsec_add_key
  25. llsec_remove_key
  26. ieee802154_llsec_del_key
  27. ieee802154_nl_fill_key
  28. llsec_iter_keys
  29. ieee802154_llsec_dump_keys
  30. llsec_parse_dev
  31. llsec_add_dev
  32. ieee802154_llsec_add_dev
  33. llsec_del_dev
  34. ieee802154_llsec_del_dev
  35. ieee802154_nl_fill_dev
  36. llsec_iter_devs
  37. ieee802154_llsec_dump_devs
  38. llsec_add_devkey
  39. ieee802154_llsec_add_devkey
  40. llsec_del_devkey
  41. ieee802154_llsec_del_devkey
  42. ieee802154_nl_fill_devkey
  43. llsec_iter_devkeys
  44. ieee802154_llsec_dump_devkeys
  45. llsec_parse_seclevel
  46. llsec_add_seclevel
  47. ieee802154_llsec_add_seclevel
  48. llsec_del_seclevel
  49. ieee802154_llsec_del_seclevel
  50. ieee802154_nl_fill_seclevel
  51. llsec_iter_seclevels
  52. ieee802154_llsec_dump_seclevels

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Netlink interface for IEEE 802.15.4 stack
   4  *
   5  * Copyright 2007, 2008 Siemens AG
   6  *
   7  * Written by:
   8  * Sergey Lapin <slapin@ossfans.org>
   9  * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
  10  * Maxim Osipov <maxim.osipov@siemens.com>
  11  */
  12 
  13 #include <linux/gfp.h>
  14 #include <linux/kernel.h>
  15 #include <linux/if_arp.h>
  16 #include <linux/netdevice.h>
  17 #include <linux/ieee802154.h>
  18 #include <net/netlink.h>
  19 #include <net/genetlink.h>
  20 #include <net/sock.h>
  21 #include <linux/nl802154.h>
  22 #include <linux/export.h>
  23 #include <net/af_ieee802154.h>
  24 #include <net/ieee802154_netdev.h>
  25 #include <net/cfg802154.h>
  26 
  27 #include "ieee802154.h"
  28 
  29 static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr,
  30                           int padattr)
  31 {
  32         return nla_put_u64_64bit(msg, type, swab64((__force u64)hwaddr),
  33                                  padattr);
  34 }
  35 
  36 static __le64 nla_get_hwaddr(const struct nlattr *nla)
  37 {
  38         return ieee802154_devaddr_from_raw(nla_data(nla));
  39 }
  40 
  41 static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr)
  42 {
  43         return nla_put_u16(msg, type, le16_to_cpu(addr));
  44 }
  45 
  46 static __le16 nla_get_shortaddr(const struct nlattr *nla)
  47 {
  48         return cpu_to_le16(nla_get_u16(nla));
  49 }
  50 
  51 static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
  52 {
  53         struct sk_buff *msg;
  54 
  55         pr_debug("%s\n", __func__);
  56 
  57         msg = ieee802154_nl_create(0, IEEE802154_START_CONF);
  58         if (!msg)
  59                 return -ENOBUFS;
  60 
  61         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
  62             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
  63             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
  64                     dev->dev_addr) ||
  65             nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
  66                 goto nla_put_failure;
  67         return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
  68 
  69 nla_put_failure:
  70         nlmsg_free(msg);
  71         return -ENOBUFS;
  72 }
  73 
  74 static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid,
  75                                     u32 seq, int flags, struct net_device *dev)
  76 {
  77         void *hdr;
  78         struct wpan_phy *phy;
  79         struct ieee802154_mlme_ops *ops;
  80         __le16 short_addr, pan_id;
  81 
  82         pr_debug("%s\n", __func__);
  83 
  84         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
  85                           IEEE802154_LIST_IFACE);
  86         if (!hdr)
  87                 goto out;
  88 
  89         ops = ieee802154_mlme_ops(dev);
  90         phy = dev->ieee802154_ptr->wpan_phy;
  91         BUG_ON(!phy);
  92         get_device(&phy->dev);
  93 
  94         rtnl_lock();
  95         short_addr = dev->ieee802154_ptr->short_addr;
  96         pan_id = dev->ieee802154_ptr->pan_id;
  97         rtnl_unlock();
  98 
  99         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
 100             nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) ||
 101             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
 102             nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
 103                     dev->dev_addr) ||
 104             nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
 105             nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id))
 106                 goto nla_put_failure;
 107 
 108         if (ops->get_mac_params) {
 109                 struct ieee802154_mac_params params;
 110 
 111                 rtnl_lock();
 112                 ops->get_mac_params(dev, &params);
 113                 rtnl_unlock();
 114 
 115                 if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
 116                                params.transmit_power / 100) ||
 117                     nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) ||
 118                     nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE,
 119                                params.cca.mode) ||
 120                     nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL,
 121                                 params.cca_ed_level / 100) ||
 122                     nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES,
 123                                params.csma_retries) ||
 124                     nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE,
 125                                params.min_be) ||
 126                     nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE,
 127                                params.max_be) ||
 128                     nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES,
 129                                params.frame_retries))
 130                         goto nla_put_failure;
 131         }
 132 
 133         wpan_phy_put(phy);
 134         genlmsg_end(msg, hdr);
 135         return 0;
 136 
 137 nla_put_failure:
 138         wpan_phy_put(phy);
 139         genlmsg_cancel(msg, hdr);
 140 out:
 141         return -EMSGSIZE;
 142 }
 143 
 144 /* Requests from userspace */
 145 static struct net_device *ieee802154_nl_get_dev(struct genl_info *info)
 146 {
 147         struct net_device *dev;
 148 
 149         if (info->attrs[IEEE802154_ATTR_DEV_NAME]) {
 150                 char name[IFNAMSIZ + 1];
 151 
 152                 nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME],
 153                             sizeof(name));
 154                 dev = dev_get_by_name(&init_net, name);
 155         } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) {
 156                 dev = dev_get_by_index(&init_net,
 157                         nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX]));
 158         } else {
 159                 return NULL;
 160         }
 161 
 162         if (!dev)
 163                 return NULL;
 164 
 165         if (dev->type != ARPHRD_IEEE802154) {
 166                 dev_put(dev);
 167                 return NULL;
 168         }
 169 
 170         return dev;
 171 }
 172 
 173 int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info)
 174 {
 175         struct net_device *dev;
 176         struct ieee802154_addr addr;
 177         u8 page;
 178         int ret = -EOPNOTSUPP;
 179 
 180         if (!info->attrs[IEEE802154_ATTR_CHANNEL] ||
 181             !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
 182             (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] &&
 183                 !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) ||
 184             !info->attrs[IEEE802154_ATTR_CAPABILITY])
 185                 return -EINVAL;
 186 
 187         dev = ieee802154_nl_get_dev(info);
 188         if (!dev)
 189                 return -ENODEV;
 190         if (!ieee802154_mlme_ops(dev)->assoc_req)
 191                 goto out;
 192 
 193         if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) {
 194                 addr.mode = IEEE802154_ADDR_LONG;
 195                 addr.extended_addr = nla_get_hwaddr(
 196                                 info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]);
 197         } else {
 198                 addr.mode = IEEE802154_ADDR_SHORT;
 199                 addr.short_addr = nla_get_shortaddr(
 200                                 info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
 201         }
 202         addr.pan_id = nla_get_shortaddr(
 203                         info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
 204 
 205         if (info->attrs[IEEE802154_ATTR_PAGE])
 206                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
 207         else
 208                 page = 0;
 209 
 210         ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr,
 211                         nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]),
 212                         page,
 213                         nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY]));
 214 
 215 out:
 216         dev_put(dev);
 217         return ret;
 218 }
 219 
 220 int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info)
 221 {
 222         struct net_device *dev;
 223         struct ieee802154_addr addr;
 224         int ret = -EOPNOTSUPP;
 225 
 226         if (!info->attrs[IEEE802154_ATTR_STATUS] ||
 227             !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] ||
 228             !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR])
 229                 return -EINVAL;
 230 
 231         dev = ieee802154_nl_get_dev(info);
 232         if (!dev)
 233                 return -ENODEV;
 234         if (!ieee802154_mlme_ops(dev)->assoc_resp)
 235                 goto out;
 236 
 237         addr.mode = IEEE802154_ADDR_LONG;
 238         addr.extended_addr = nla_get_hwaddr(
 239                         info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
 240         rtnl_lock();
 241         addr.pan_id = dev->ieee802154_ptr->pan_id;
 242         rtnl_unlock();
 243 
 244         ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr,
 245                 nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]),
 246                 nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS]));
 247 
 248 out:
 249         dev_put(dev);
 250         return ret;
 251 }
 252 
 253 int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info)
 254 {
 255         struct net_device *dev;
 256         struct ieee802154_addr addr;
 257         int ret = -EOPNOTSUPP;
 258 
 259         if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] &&
 260             !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) ||
 261             !info->attrs[IEEE802154_ATTR_REASON])
 262                 return -EINVAL;
 263 
 264         dev = ieee802154_nl_get_dev(info);
 265         if (!dev)
 266                 return -ENODEV;
 267         if (!ieee802154_mlme_ops(dev)->disassoc_req)
 268                 goto out;
 269 
 270         if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) {
 271                 addr.mode = IEEE802154_ADDR_LONG;
 272                 addr.extended_addr = nla_get_hwaddr(
 273                                 info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]);
 274         } else {
 275                 addr.mode = IEEE802154_ADDR_SHORT;
 276                 addr.short_addr = nla_get_shortaddr(
 277                                 info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]);
 278         }
 279         rtnl_lock();
 280         addr.pan_id = dev->ieee802154_ptr->pan_id;
 281         rtnl_unlock();
 282 
 283         ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr,
 284                         nla_get_u8(info->attrs[IEEE802154_ATTR_REASON]));
 285 
 286 out:
 287         dev_put(dev);
 288         return ret;
 289 }
 290 
 291 /* PANid, channel, beacon_order = 15, superframe_order = 15,
 292  * PAN_coordinator, battery_life_extension = 0,
 293  * coord_realignment = 0, security_enable = 0
 294 */
 295 int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info)
 296 {
 297         struct net_device *dev;
 298         struct ieee802154_addr addr;
 299 
 300         u8 channel, bcn_ord, sf_ord;
 301         u8 page;
 302         int pan_coord, blx, coord_realign;
 303         int ret = -EBUSY;
 304 
 305         if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
 306             !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
 307             !info->attrs[IEEE802154_ATTR_CHANNEL] ||
 308             !info->attrs[IEEE802154_ATTR_BCN_ORD] ||
 309             !info->attrs[IEEE802154_ATTR_SF_ORD] ||
 310             !info->attrs[IEEE802154_ATTR_PAN_COORD] ||
 311             !info->attrs[IEEE802154_ATTR_BAT_EXT] ||
 312             !info->attrs[IEEE802154_ATTR_COORD_REALIGN]
 313          )
 314                 return -EINVAL;
 315 
 316         dev = ieee802154_nl_get_dev(info);
 317         if (!dev)
 318                 return -ENODEV;
 319 
 320         if (netif_running(dev))
 321                 goto out;
 322 
 323         if (!ieee802154_mlme_ops(dev)->start_req) {
 324                 ret = -EOPNOTSUPP;
 325                 goto out;
 326         }
 327 
 328         addr.mode = IEEE802154_ADDR_SHORT;
 329         addr.short_addr = nla_get_shortaddr(
 330                         info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
 331         addr.pan_id = nla_get_shortaddr(
 332                         info->attrs[IEEE802154_ATTR_COORD_PAN_ID]);
 333 
 334         channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]);
 335         bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]);
 336         sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]);
 337         pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]);
 338         blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]);
 339         coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]);
 340 
 341         if (info->attrs[IEEE802154_ATTR_PAGE])
 342                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
 343         else
 344                 page = 0;
 345 
 346         if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
 347                 ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
 348                 dev_put(dev);
 349                 return -EINVAL;
 350         }
 351 
 352         rtnl_lock();
 353         ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
 354                 bcn_ord, sf_ord, pan_coord, blx, coord_realign);
 355         rtnl_unlock();
 356 
 357         /* FIXME: add validation for unused parameters to be sane
 358          * for SoftMAC
 359          */
 360         ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
 361 
 362 out:
 363         dev_put(dev);
 364         return ret;
 365 }
 366 
 367 int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info)
 368 {
 369         struct net_device *dev;
 370         int ret = -EOPNOTSUPP;
 371         u8 type;
 372         u32 channels;
 373         u8 duration;
 374         u8 page;
 375 
 376         if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] ||
 377             !info->attrs[IEEE802154_ATTR_CHANNELS] ||
 378             !info->attrs[IEEE802154_ATTR_DURATION])
 379                 return -EINVAL;
 380 
 381         dev = ieee802154_nl_get_dev(info);
 382         if (!dev)
 383                 return -ENODEV;
 384         if (!ieee802154_mlme_ops(dev)->scan_req)
 385                 goto out;
 386 
 387         type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]);
 388         channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]);
 389         duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]);
 390 
 391         if (info->attrs[IEEE802154_ATTR_PAGE])
 392                 page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]);
 393         else
 394                 page = 0;
 395 
 396         ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels,
 397                                                  page, duration);
 398 
 399 out:
 400         dev_put(dev);
 401         return ret;
 402 }
 403 
 404 int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info)
 405 {
 406         /* Request for interface name, index, type, IEEE address,
 407          * PAN Id, short address
 408          */
 409         struct sk_buff *msg;
 410         struct net_device *dev = NULL;
 411         int rc = -ENOBUFS;
 412 
 413         pr_debug("%s\n", __func__);
 414 
 415         dev = ieee802154_nl_get_dev(info);
 416         if (!dev)
 417                 return -ENODEV;
 418 
 419         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 420         if (!msg)
 421                 goto out_dev;
 422 
 423         rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq,
 424                                       0, dev);
 425         if (rc < 0)
 426                 goto out_free;
 427 
 428         dev_put(dev);
 429 
 430         return genlmsg_reply(msg, info);
 431 out_free:
 432         nlmsg_free(msg);
 433 out_dev:
 434         dev_put(dev);
 435         return rc;
 436 }
 437 
 438 int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb)
 439 {
 440         struct net *net = sock_net(skb->sk);
 441         struct net_device *dev;
 442         int idx;
 443         int s_idx = cb->args[0];
 444 
 445         pr_debug("%s\n", __func__);
 446 
 447         idx = 0;
 448         for_each_netdev(net, dev) {
 449                 if (idx < s_idx || dev->type != ARPHRD_IEEE802154)
 450                         goto cont;
 451 
 452                 if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid,
 453                                              cb->nlh->nlmsg_seq,
 454                                              NLM_F_MULTI, dev) < 0)
 455                         break;
 456 cont:
 457                 idx++;
 458         }
 459         cb->args[0] = idx;
 460 
 461         return skb->len;
 462 }
 463 
 464 int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info)
 465 {
 466         struct net_device *dev = NULL;
 467         struct ieee802154_mlme_ops *ops;
 468         struct ieee802154_mac_params params;
 469         struct wpan_phy *phy;
 470         int rc = -EINVAL;
 471 
 472         pr_debug("%s\n", __func__);
 473 
 474         dev = ieee802154_nl_get_dev(info);
 475         if (!dev)
 476                 return -ENODEV;
 477 
 478         ops = ieee802154_mlme_ops(dev);
 479 
 480         if (!ops->get_mac_params || !ops->set_mac_params) {
 481                 rc = -EOPNOTSUPP;
 482                 goto out;
 483         }
 484 
 485         if (netif_running(dev)) {
 486                 rc = -EBUSY;
 487                 goto out;
 488         }
 489 
 490         if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] &&
 491             !info->attrs[IEEE802154_ATTR_CCA_MODE] &&
 492             !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] &&
 493             !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] &&
 494             !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] &&
 495             !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] &&
 496             !info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
 497                 goto out;
 498 
 499         phy = dev->ieee802154_ptr->wpan_phy;
 500         get_device(&phy->dev);
 501 
 502         rtnl_lock();
 503         ops->get_mac_params(dev, &params);
 504 
 505         if (info->attrs[IEEE802154_ATTR_TXPOWER])
 506                 params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]) * 100;
 507 
 508         if (info->attrs[IEEE802154_ATTR_LBT_ENABLED])
 509                 params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]);
 510 
 511         if (info->attrs[IEEE802154_ATTR_CCA_MODE])
 512                 params.cca.mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]);
 513 
 514         if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL])
 515                 params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) * 100;
 516 
 517         if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES])
 518                 params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]);
 519 
 520         if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE])
 521                 params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]);
 522 
 523         if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])
 524                 params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]);
 525 
 526         if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
 527                 params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
 528 
 529         rc = ops->set_mac_params(dev, &params);
 530         rtnl_unlock();
 531 
 532         wpan_phy_put(phy);
 533         dev_put(dev);
 534 
 535         return 0;
 536 
 537 out:
 538         dev_put(dev);
 539         return rc;
 540 }
 541 
 542 static int
 543 ieee802154_llsec_parse_key_id(struct genl_info *info,
 544                               struct ieee802154_llsec_key_id *desc)
 545 {
 546         memset(desc, 0, sizeof(*desc));
 547 
 548         if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE])
 549                 return -EINVAL;
 550 
 551         desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]);
 552 
 553         if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
 554                 if (!info->attrs[IEEE802154_ATTR_PAN_ID] &&
 555                     !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] ||
 556                       info->attrs[IEEE802154_ATTR_HW_ADDR]))
 557                         return -EINVAL;
 558 
 559                 desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
 560 
 561                 if (info->attrs[IEEE802154_ATTR_SHORT_ADDR]) {
 562                         desc->device_addr.mode = IEEE802154_ADDR_SHORT;
 563                         desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
 564                 } else {
 565                         desc->device_addr.mode = IEEE802154_ADDR_LONG;
 566                         desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
 567                 }
 568         }
 569 
 570         if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
 571             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID])
 572                 return -EINVAL;
 573 
 574         if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
 575             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT])
 576                 return -EINVAL;
 577 
 578         if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
 579             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED])
 580                 return -EINVAL;
 581 
 582         if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT)
 583                 desc->id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_ID]);
 584 
 585         switch (desc->mode) {
 586         case IEEE802154_SCF_KEY_SHORT_INDEX:
 587         {
 588                 u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]);
 589 
 590                 desc->short_source = cpu_to_le32(source);
 591                 break;
 592         }
 593         case IEEE802154_SCF_KEY_HW_INDEX:
 594                 desc->extended_source = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED]);
 595                 break;
 596         }
 597 
 598         return 0;
 599 }
 600 
 601 static int
 602 ieee802154_llsec_fill_key_id(struct sk_buff *msg,
 603                              const struct ieee802154_llsec_key_id *desc)
 604 {
 605         if (nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_MODE, desc->mode))
 606                 return -EMSGSIZE;
 607 
 608         if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) {
 609                 if (nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID,
 610                                       desc->device_addr.pan_id))
 611                         return -EMSGSIZE;
 612 
 613                 if (desc->device_addr.mode == IEEE802154_ADDR_SHORT &&
 614                     nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
 615                                       desc->device_addr.short_addr))
 616                         return -EMSGSIZE;
 617 
 618                 if (desc->device_addr.mode == IEEE802154_ADDR_LONG &&
 619                     nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR,
 620                                    desc->device_addr.extended_addr,
 621                                    IEEE802154_ATTR_PAD))
 622                         return -EMSGSIZE;
 623         }
 624 
 625         if (desc->mode != IEEE802154_SCF_KEY_IMPLICIT &&
 626             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_ID, desc->id))
 627                 return -EMSGSIZE;
 628 
 629         if (desc->mode == IEEE802154_SCF_KEY_SHORT_INDEX &&
 630             nla_put_u32(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT,
 631                         le32_to_cpu(desc->short_source)))
 632                 return -EMSGSIZE;
 633 
 634         if (desc->mode == IEEE802154_SCF_KEY_HW_INDEX &&
 635             nla_put_hwaddr(msg, IEEE802154_ATTR_LLSEC_KEY_SOURCE_EXTENDED,
 636                            desc->extended_source, IEEE802154_ATTR_PAD))
 637                 return -EMSGSIZE;
 638 
 639         return 0;
 640 }
 641 
 642 int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info)
 643 {
 644         struct sk_buff *msg;
 645         struct net_device *dev = NULL;
 646         int rc = -ENOBUFS;
 647         struct ieee802154_mlme_ops *ops;
 648         void *hdr;
 649         struct ieee802154_llsec_params params;
 650 
 651         pr_debug("%s\n", __func__);
 652 
 653         dev = ieee802154_nl_get_dev(info);
 654         if (!dev)
 655                 return -ENODEV;
 656 
 657         ops = ieee802154_mlme_ops(dev);
 658         if (!ops->llsec) {
 659                 rc = -EOPNOTSUPP;
 660                 goto out_dev;
 661         }
 662 
 663         msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 664         if (!msg)
 665                 goto out_dev;
 666 
 667         hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0,
 668                           IEEE802154_LLSEC_GETPARAMS);
 669         if (!hdr)
 670                 goto out_free;
 671 
 672         rc = ops->llsec->get_params(dev, &params);
 673         if (rc < 0)
 674                 goto out_free;
 675 
 676         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
 677             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
 678             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_ENABLED, params.enabled) ||
 679             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) ||
 680             nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
 681                         be32_to_cpu(params.frame_counter)) ||
 682             ieee802154_llsec_fill_key_id(msg, &params.out_key))
 683                 goto out_free;
 684 
 685         dev_put(dev);
 686 
 687         return ieee802154_nl_reply(msg, info);
 688 out_free:
 689         nlmsg_free(msg);
 690 out_dev:
 691         dev_put(dev);
 692         return rc;
 693 }
 694 
 695 int ieee802154_llsec_setparams(struct sk_buff *skb, struct genl_info *info)
 696 {
 697         struct net_device *dev = NULL;
 698         int rc = -EINVAL;
 699         struct ieee802154_mlme_ops *ops;
 700         struct ieee802154_llsec_params params;
 701         int changed = 0;
 702 
 703         pr_debug("%s\n", __func__);
 704 
 705         dev = ieee802154_nl_get_dev(info);
 706         if (!dev)
 707                 return -ENODEV;
 708 
 709         if (!info->attrs[IEEE802154_ATTR_LLSEC_ENABLED] &&
 710             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE] &&
 711             !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL])
 712                 goto out;
 713 
 714         ops = ieee802154_mlme_ops(dev);
 715         if (!ops->llsec) {
 716                 rc = -EOPNOTSUPP;
 717                 goto out;
 718         }
 719 
 720         if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL] &&
 721             nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) > 7)
 722                 goto out;
 723 
 724         if (info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]) {
 725                 params.enabled = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_ENABLED]);
 726                 changed |= IEEE802154_LLSEC_PARAM_ENABLED;
 727         }
 728 
 729         if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]) {
 730                 if (ieee802154_llsec_parse_key_id(info, &params.out_key))
 731                         goto out;
 732 
 733                 changed |= IEEE802154_LLSEC_PARAM_OUT_KEY;
 734         }
 735 
 736         if (info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]) {
 737                 params.out_level = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVEL]);
 738                 changed |= IEEE802154_LLSEC_PARAM_OUT_LEVEL;
 739         }
 740 
 741         if (info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]) {
 742                 u32 fc = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
 743 
 744                 params.frame_counter = cpu_to_be32(fc);
 745                 changed |= IEEE802154_LLSEC_PARAM_FRAME_COUNTER;
 746         }
 747 
 748         rc = ops->llsec->set_params(dev, &params, changed);
 749 
 750         dev_put(dev);
 751 
 752         return rc;
 753 out:
 754         dev_put(dev);
 755         return rc;
 756 }
 757 
 758 struct llsec_dump_data {
 759         struct sk_buff *skb;
 760         int s_idx, s_idx2;
 761         int portid;
 762         int nlmsg_seq;
 763         struct net_device *dev;
 764         struct ieee802154_mlme_ops *ops;
 765         struct ieee802154_llsec_table *table;
 766 };
 767 
 768 static int
 769 ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb,
 770                             int (*step)(struct llsec_dump_data *))
 771 {
 772         struct net *net = sock_net(skb->sk);
 773         struct net_device *dev;
 774         struct llsec_dump_data data;
 775         int idx = 0;
 776         int first_dev = cb->args[0];
 777         int rc;
 778 
 779         for_each_netdev(net, dev) {
 780                 if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
 781                         goto skip;
 782 
 783                 data.ops = ieee802154_mlme_ops(dev);
 784                 if (!data.ops->llsec)
 785                         goto skip;
 786 
 787                 data.skb = skb;
 788                 data.s_idx = cb->args[1];
 789                 data.s_idx2 = cb->args[2];
 790                 data.dev = dev;
 791                 data.portid = NETLINK_CB(cb->skb).portid;
 792                 data.nlmsg_seq = cb->nlh->nlmsg_seq;
 793 
 794                 data.ops->llsec->lock_table(dev);
 795                 data.ops->llsec->get_table(data.dev, &data.table);
 796                 rc = step(&data);
 797                 data.ops->llsec->unlock_table(dev);
 798 
 799                 if (rc < 0)
 800                         break;
 801 
 802 skip:
 803                 idx++;
 804         }
 805         cb->args[0] = idx;
 806 
 807         return skb->len;
 808 }
 809 
 810 static int
 811 ieee802154_nl_llsec_change(struct sk_buff *skb, struct genl_info *info,
 812                            int (*fn)(struct net_device*, struct genl_info*))
 813 {
 814         struct net_device *dev = NULL;
 815         int rc = -EINVAL;
 816 
 817         dev = ieee802154_nl_get_dev(info);
 818         if (!dev)
 819                 return -ENODEV;
 820 
 821         if (!ieee802154_mlme_ops(dev)->llsec)
 822                 rc = -EOPNOTSUPP;
 823         else
 824                 rc = fn(dev, info);
 825 
 826         dev_put(dev);
 827         return rc;
 828 }
 829 
 830 static int
 831 ieee802154_llsec_parse_key(struct genl_info *info,
 832                            struct ieee802154_llsec_key *key)
 833 {
 834         u8 frames;
 835         u32 commands[256 / 32];
 836 
 837         memset(key, 0, sizeof(*key));
 838 
 839         if (!info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES] ||
 840             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES])
 841                 return -EINVAL;
 842 
 843         frames = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES]);
 844         if ((frames & BIT(IEEE802154_FC_TYPE_MAC_CMD)) &&
 845             !info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS])
 846                 return -EINVAL;
 847 
 848         if (info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS]) {
 849                 nla_memcpy(commands,
 850                            info->attrs[IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS],
 851                            256 / 8);
 852 
 853                 if (commands[0] || commands[1] || commands[2] || commands[3] ||
 854                     commands[4] || commands[5] || commands[6] ||
 855                     commands[7] >= BIT(IEEE802154_CMD_GTS_REQ + 1))
 856                         return -EINVAL;
 857 
 858                 key->cmd_frame_ids = commands[7];
 859         }
 860 
 861         key->frame_types = frames;
 862 
 863         nla_memcpy(key->key, info->attrs[IEEE802154_ATTR_LLSEC_KEY_BYTES],
 864                    IEEE802154_LLSEC_KEY_SIZE);
 865 
 866         return 0;
 867 }
 868 
 869 static int llsec_add_key(struct net_device *dev, struct genl_info *info)
 870 {
 871         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
 872         struct ieee802154_llsec_key key;
 873         struct ieee802154_llsec_key_id id;
 874 
 875         if (ieee802154_llsec_parse_key(info, &key) ||
 876             ieee802154_llsec_parse_key_id(info, &id))
 877                 return -EINVAL;
 878 
 879         return ops->llsec->add_key(dev, &id, &key);
 880 }
 881 
 882 int ieee802154_llsec_add_key(struct sk_buff *skb, struct genl_info *info)
 883 {
 884         if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
 885             (NLM_F_CREATE | NLM_F_EXCL))
 886                 return -EINVAL;
 887 
 888         return ieee802154_nl_llsec_change(skb, info, llsec_add_key);
 889 }
 890 
 891 static int llsec_remove_key(struct net_device *dev, struct genl_info *info)
 892 {
 893         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
 894         struct ieee802154_llsec_key_id id;
 895 
 896         if (ieee802154_llsec_parse_key_id(info, &id))
 897                 return -EINVAL;
 898 
 899         return ops->llsec->del_key(dev, &id);
 900 }
 901 
 902 int ieee802154_llsec_del_key(struct sk_buff *skb, struct genl_info *info)
 903 {
 904         return ieee802154_nl_llsec_change(skb, info, llsec_remove_key);
 905 }
 906 
 907 static int
 908 ieee802154_nl_fill_key(struct sk_buff *msg, u32 portid, u32 seq,
 909                        const struct ieee802154_llsec_key_entry *key,
 910                        const struct net_device *dev)
 911 {
 912         void *hdr;
 913         u32 commands[256 / 32];
 914 
 915         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
 916                           IEEE802154_LLSEC_LIST_KEY);
 917         if (!hdr)
 918                 goto out;
 919 
 920         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
 921             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
 922             ieee802154_llsec_fill_key_id(msg, &key->id) ||
 923             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_FRAME_TYPES,
 924                        key->key->frame_types))
 925                 goto nla_put_failure;
 926 
 927         if (key->key->frame_types & BIT(IEEE802154_FC_TYPE_MAC_CMD)) {
 928                 memset(commands, 0, sizeof(commands));
 929                 commands[7] = key->key->cmd_frame_ids;
 930                 if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS,
 931                             sizeof(commands), commands))
 932                         goto nla_put_failure;
 933         }
 934 
 935         if (nla_put(msg, IEEE802154_ATTR_LLSEC_KEY_BYTES,
 936                     IEEE802154_LLSEC_KEY_SIZE, key->key->key))
 937                 goto nla_put_failure;
 938 
 939         genlmsg_end(msg, hdr);
 940         return 0;
 941 
 942 nla_put_failure:
 943         genlmsg_cancel(msg, hdr);
 944 out:
 945         return -EMSGSIZE;
 946 }
 947 
 948 static int llsec_iter_keys(struct llsec_dump_data *data)
 949 {
 950         struct ieee802154_llsec_key_entry *pos;
 951         int rc = 0, idx = 0;
 952 
 953         list_for_each_entry(pos, &data->table->keys, list) {
 954                 if (idx++ < data->s_idx)
 955                         continue;
 956 
 957                 if (ieee802154_nl_fill_key(data->skb, data->portid,
 958                                            data->nlmsg_seq, pos, data->dev)) {
 959                         rc = -EMSGSIZE;
 960                         break;
 961                 }
 962 
 963                 data->s_idx++;
 964         }
 965 
 966         return rc;
 967 }
 968 
 969 int ieee802154_llsec_dump_keys(struct sk_buff *skb, struct netlink_callback *cb)
 970 {
 971         return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys);
 972 }
 973 
 974 static int
 975 llsec_parse_dev(struct genl_info *info,
 976                 struct ieee802154_llsec_device *dev)
 977 {
 978         memset(dev, 0, sizeof(*dev));
 979 
 980         if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
 981             !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
 982             !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE] ||
 983             !info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE] ||
 984             (!!info->attrs[IEEE802154_ATTR_PAN_ID] !=
 985              !!info->attrs[IEEE802154_ATTR_SHORT_ADDR]))
 986                 return -EINVAL;
 987 
 988         if (info->attrs[IEEE802154_ATTR_PAN_ID]) {
 989                 dev->pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]);
 990                 dev->short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]);
 991         } else {
 992                 dev->short_addr = cpu_to_le16(IEEE802154_ADDR_UNDEF);
 993         }
 994 
 995         dev->hwaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
 996         dev->frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
 997         dev->seclevel_exempt = !!nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
 998         dev->key_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_KEY_MODE]);
 999 
1000         if (dev->key_mode >= __IEEE802154_LLSEC_DEVKEY_MAX)
1001                 return -EINVAL;
1002 
1003         return 0;
1004 }
1005 
1006 static int llsec_add_dev(struct net_device *dev, struct genl_info *info)
1007 {
1008         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1009         struct ieee802154_llsec_device desc;
1010 
1011         if (llsec_parse_dev(info, &desc))
1012                 return -EINVAL;
1013 
1014         return ops->llsec->add_dev(dev, &desc);
1015 }
1016 
1017 int ieee802154_llsec_add_dev(struct sk_buff *skb, struct genl_info *info)
1018 {
1019         if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
1020             (NLM_F_CREATE | NLM_F_EXCL))
1021                 return -EINVAL;
1022 
1023         return ieee802154_nl_llsec_change(skb, info, llsec_add_dev);
1024 }
1025 
1026 static int llsec_del_dev(struct net_device *dev, struct genl_info *info)
1027 {
1028         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1029         __le64 devaddr;
1030 
1031         if (!info->attrs[IEEE802154_ATTR_HW_ADDR])
1032                 return -EINVAL;
1033 
1034         devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
1035 
1036         return ops->llsec->del_dev(dev, devaddr);
1037 }
1038 
1039 int ieee802154_llsec_del_dev(struct sk_buff *skb, struct genl_info *info)
1040 {
1041         return ieee802154_nl_llsec_change(skb, info, llsec_del_dev);
1042 }
1043 
1044 static int
1045 ieee802154_nl_fill_dev(struct sk_buff *msg, u32 portid, u32 seq,
1046                        const struct ieee802154_llsec_device *desc,
1047                        const struct net_device *dev)
1048 {
1049         void *hdr;
1050 
1051         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
1052                           IEEE802154_LLSEC_LIST_DEV);
1053         if (!hdr)
1054                 goto out;
1055 
1056         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
1057             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
1058             nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, desc->pan_id) ||
1059             nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR,
1060                               desc->short_addr) ||
1061             nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, desc->hwaddr,
1062                            IEEE802154_ATTR_PAD) ||
1063             nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
1064                         desc->frame_counter) ||
1065             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
1066                        desc->seclevel_exempt) ||
1067             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_KEY_MODE, desc->key_mode))
1068                 goto nla_put_failure;
1069 
1070         genlmsg_end(msg, hdr);
1071         return 0;
1072 
1073 nla_put_failure:
1074         genlmsg_cancel(msg, hdr);
1075 out:
1076         return -EMSGSIZE;
1077 }
1078 
1079 static int llsec_iter_devs(struct llsec_dump_data *data)
1080 {
1081         struct ieee802154_llsec_device *pos;
1082         int rc = 0, idx = 0;
1083 
1084         list_for_each_entry(pos, &data->table->devices, list) {
1085                 if (idx++ < data->s_idx)
1086                         continue;
1087 
1088                 if (ieee802154_nl_fill_dev(data->skb, data->portid,
1089                                            data->nlmsg_seq, pos, data->dev)) {
1090                         rc = -EMSGSIZE;
1091                         break;
1092                 }
1093 
1094                 data->s_idx++;
1095         }
1096 
1097         return rc;
1098 }
1099 
1100 int ieee802154_llsec_dump_devs(struct sk_buff *skb, struct netlink_callback *cb)
1101 {
1102         return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs);
1103 }
1104 
1105 static int llsec_add_devkey(struct net_device *dev, struct genl_info *info)
1106 {
1107         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1108         struct ieee802154_llsec_device_key key;
1109         __le64 devaddr;
1110 
1111         if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER] ||
1112             !info->attrs[IEEE802154_ATTR_HW_ADDR] ||
1113             ieee802154_llsec_parse_key_id(info, &key.key_id))
1114                 return -EINVAL;
1115 
1116         devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
1117         key.frame_counter = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_COUNTER]);
1118 
1119         return ops->llsec->add_devkey(dev, devaddr, &key);
1120 }
1121 
1122 int ieee802154_llsec_add_devkey(struct sk_buff *skb, struct genl_info *info)
1123 {
1124         if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
1125             (NLM_F_CREATE | NLM_F_EXCL))
1126                 return -EINVAL;
1127 
1128         return ieee802154_nl_llsec_change(skb, info, llsec_add_devkey);
1129 }
1130 
1131 static int llsec_del_devkey(struct net_device *dev, struct genl_info *info)
1132 {
1133         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1134         struct ieee802154_llsec_device_key key;
1135         __le64 devaddr;
1136 
1137         if (!info->attrs[IEEE802154_ATTR_HW_ADDR] ||
1138             ieee802154_llsec_parse_key_id(info, &key.key_id))
1139                 return -EINVAL;
1140 
1141         devaddr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]);
1142 
1143         return ops->llsec->del_devkey(dev, devaddr, &key);
1144 }
1145 
1146 int ieee802154_llsec_del_devkey(struct sk_buff *skb, struct genl_info *info)
1147 {
1148         return ieee802154_nl_llsec_change(skb, info, llsec_del_devkey);
1149 }
1150 
1151 static int
1152 ieee802154_nl_fill_devkey(struct sk_buff *msg, u32 portid, u32 seq,
1153                           __le64 devaddr,
1154                           const struct ieee802154_llsec_device_key *devkey,
1155                           const struct net_device *dev)
1156 {
1157         void *hdr;
1158 
1159         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
1160                           IEEE802154_LLSEC_LIST_DEVKEY);
1161         if (!hdr)
1162                 goto out;
1163 
1164         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
1165             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
1166             nla_put_hwaddr(msg, IEEE802154_ATTR_HW_ADDR, devaddr,
1167                            IEEE802154_ATTR_PAD) ||
1168             nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER,
1169                         devkey->frame_counter) ||
1170             ieee802154_llsec_fill_key_id(msg, &devkey->key_id))
1171                 goto nla_put_failure;
1172 
1173         genlmsg_end(msg, hdr);
1174         return 0;
1175 
1176 nla_put_failure:
1177         genlmsg_cancel(msg, hdr);
1178 out:
1179         return -EMSGSIZE;
1180 }
1181 
1182 static int llsec_iter_devkeys(struct llsec_dump_data *data)
1183 {
1184         struct ieee802154_llsec_device *dpos;
1185         struct ieee802154_llsec_device_key *kpos;
1186         int rc = 0, idx = 0, idx2;
1187 
1188         list_for_each_entry(dpos, &data->table->devices, list) {
1189                 if (idx++ < data->s_idx)
1190                         continue;
1191 
1192                 idx2 = 0;
1193 
1194                 list_for_each_entry(kpos, &dpos->keys, list) {
1195                         if (idx2++ < data->s_idx2)
1196                                 continue;
1197 
1198                         if (ieee802154_nl_fill_devkey(data->skb, data->portid,
1199                                                       data->nlmsg_seq,
1200                                                       dpos->hwaddr, kpos,
1201                                                       data->dev)) {
1202                                 return rc = -EMSGSIZE;
1203                         }
1204 
1205                         data->s_idx2++;
1206                 }
1207 
1208                 data->s_idx++;
1209         }
1210 
1211         return rc;
1212 }
1213 
1214 int ieee802154_llsec_dump_devkeys(struct sk_buff *skb,
1215                                   struct netlink_callback *cb)
1216 {
1217         return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys);
1218 }
1219 
1220 static int
1221 llsec_parse_seclevel(struct genl_info *info,
1222                      struct ieee802154_llsec_seclevel *sl)
1223 {
1224         memset(sl, 0, sizeof(*sl));
1225 
1226         if (!info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE] ||
1227             !info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS] ||
1228             !info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE])
1229                 return -EINVAL;
1230 
1231         sl->frame_type = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_FRAME_TYPE]);
1232         if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD) {
1233                 if (!info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID])
1234                         return -EINVAL;
1235 
1236                 sl->cmd_frame_id = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_CMD_FRAME_ID]);
1237         }
1238 
1239         sl->sec_levels = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_SECLEVELS]);
1240         sl->device_override = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_DEV_OVERRIDE]);
1241 
1242         return 0;
1243 }
1244 
1245 static int llsec_add_seclevel(struct net_device *dev, struct genl_info *info)
1246 {
1247         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1248         struct ieee802154_llsec_seclevel sl;
1249 
1250         if (llsec_parse_seclevel(info, &sl))
1251                 return -EINVAL;
1252 
1253         return ops->llsec->add_seclevel(dev, &sl);
1254 }
1255 
1256 int ieee802154_llsec_add_seclevel(struct sk_buff *skb, struct genl_info *info)
1257 {
1258         if ((info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) !=
1259             (NLM_F_CREATE | NLM_F_EXCL))
1260                 return -EINVAL;
1261 
1262         return ieee802154_nl_llsec_change(skb, info, llsec_add_seclevel);
1263 }
1264 
1265 static int llsec_del_seclevel(struct net_device *dev, struct genl_info *info)
1266 {
1267         struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
1268         struct ieee802154_llsec_seclevel sl;
1269 
1270         if (llsec_parse_seclevel(info, &sl))
1271                 return -EINVAL;
1272 
1273         return ops->llsec->del_seclevel(dev, &sl);
1274 }
1275 
1276 int ieee802154_llsec_del_seclevel(struct sk_buff *skb, struct genl_info *info)
1277 {
1278         return ieee802154_nl_llsec_change(skb, info, llsec_del_seclevel);
1279 }
1280 
1281 static int
1282 ieee802154_nl_fill_seclevel(struct sk_buff *msg, u32 portid, u32 seq,
1283                             const struct ieee802154_llsec_seclevel *sl,
1284                             const struct net_device *dev)
1285 {
1286         void *hdr;
1287 
1288         hdr = genlmsg_put(msg, 0, seq, &nl802154_family, NLM_F_MULTI,
1289                           IEEE802154_LLSEC_LIST_SECLEVEL);
1290         if (!hdr)
1291                 goto out;
1292 
1293         if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
1294             nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
1295             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_FRAME_TYPE, sl->frame_type) ||
1296             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVELS, sl->sec_levels) ||
1297             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_DEV_OVERRIDE,
1298                        sl->device_override))
1299                 goto nla_put_failure;
1300 
1301         if (sl->frame_type == IEEE802154_FC_TYPE_MAC_CMD &&
1302             nla_put_u8(msg, IEEE802154_ATTR_LLSEC_CMD_FRAME_ID,
1303                        sl->cmd_frame_id))
1304                 goto nla_put_failure;
1305 
1306         genlmsg_end(msg, hdr);
1307         return 0;
1308 
1309 nla_put_failure:
1310         genlmsg_cancel(msg, hdr);
1311 out:
1312         return -EMSGSIZE;
1313 }
1314 
1315 static int llsec_iter_seclevels(struct llsec_dump_data *data)
1316 {
1317         struct ieee802154_llsec_seclevel *pos;
1318         int rc = 0, idx = 0;
1319 
1320         list_for_each_entry(pos, &data->table->security_levels, list) {
1321                 if (idx++ < data->s_idx)
1322                         continue;
1323 
1324                 if (ieee802154_nl_fill_seclevel(data->skb, data->portid,
1325                                                 data->nlmsg_seq, pos,
1326                                                 data->dev)) {
1327                         rc = -EMSGSIZE;
1328                         break;
1329                 }
1330 
1331                 data->s_idx++;
1332         }
1333 
1334         return rc;
1335 }
1336 
1337 int ieee802154_llsec_dump_seclevels(struct sk_buff *skb,
1338                                     struct netlink_callback *cb)
1339 {
1340         return ieee802154_llsec_dump_table(skb, cb, llsec_iter_seclevels);
1341 }

/* [<][>][^][v][top][bottom][index][help] */