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