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