1 /* 2 * This is the new netlink-based wireless configuration interface. 3 * 4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net> 5 */ 6 7 #include <linux/if.h> 8 #include <linux/module.h> 9 #include <linux/err.h> 10 #include <linux/mutex.h> 11 #include <linux/list.h> 12 #include <linux/if_ether.h> 13 #include <linux/ieee80211.h> 14 #include <linux/nl80211.h> 15 #include <linux/rtnetlink.h> 16 #include <linux/netlink.h> 17 #include <net/genetlink.h> 18 #include <net/cfg80211.h> 19 #include "core.h" 20 #include "nl80211.h" 21 22 /* the netlink family */ 23 static struct genl_family nl80211_fam = { 24 .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */ 25 .name = "nl80211", /* have users key off the name instead */ 26 .hdrsize = 0, /* no private header */ 27 .version = 1, /* no particular meaning now */ 28 .maxattr = NL80211_ATTR_MAX, 29 }; 30 31 /* internal helper: get drv and dev */ 32 static int get_drv_dev_by_info_ifindex(struct genl_info *info, 33 struct cfg80211_registered_device **drv, 34 struct net_device **dev) 35 { 36 int ifindex; 37 38 if (!info->attrs[NL80211_ATTR_IFINDEX]) 39 return -EINVAL; 40 41 ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); 42 *dev = dev_get_by_index(&init_net, ifindex); 43 if (!*dev) 44 return -ENODEV; 45 46 *drv = cfg80211_get_dev_from_ifindex(ifindex); 47 if (IS_ERR(*drv)) { 48 dev_put(*dev); 49 return PTR_ERR(*drv); 50 } 51 52 return 0; 53 } 54 55 /* policy for the attributes */ 56 static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { 57 [NL80211_ATTR_WIPHY] = { .type = NLA_U32 }, 58 [NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING, 59 .len = BUS_ID_SIZE-1 }, 60 61 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 62 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 63 [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 }, 64 65 [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN }, 66 67 [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY, 68 .len = WLAN_MAX_KEY_LEN }, 69 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, 70 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 71 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 72 }; 73 74 /* message building helper */ 75 static inline void *nl80211hdr_put(struct sk_buff *skb, u32 pid, u32 seq, 76 int flags, u8 cmd) 77 { 78 /* since there is no private header just add the generic one */ 79 return genlmsg_put(skb, pid, seq, &nl80211_fam, flags, cmd); 80 } 81 82 /* netlink command implementations */ 83 84 static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, 85 struct cfg80211_registered_device *dev) 86 { 87 void *hdr; 88 89 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_WIPHY); 90 if (!hdr) 91 return -1; 92 93 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); 94 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 95 return genlmsg_end(msg, hdr); 96 97 nla_put_failure: 98 return genlmsg_cancel(msg, hdr); 99 } 100 101 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) 102 { 103 int idx = 0; 104 int start = cb->args[0]; 105 struct cfg80211_registered_device *dev; 106 107 mutex_lock(&cfg80211_drv_mutex); 108 list_for_each_entry(dev, &cfg80211_drv_list, list) { 109 if (++idx < start) 110 continue; 111 if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, 112 cb->nlh->nlmsg_seq, NLM_F_MULTI, 113 dev) < 0) 114 break; 115 } 116 mutex_unlock(&cfg80211_drv_mutex); 117 118 cb->args[0] = idx; 119 120 return skb->len; 121 } 122 123 static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info) 124 { 125 struct sk_buff *msg; 126 struct cfg80211_registered_device *dev; 127 128 dev = cfg80211_get_dev_from_info(info); 129 if (IS_ERR(dev)) 130 return PTR_ERR(dev); 131 132 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 133 if (!msg) 134 goto out_err; 135 136 if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0) 137 goto out_free; 138 139 cfg80211_put_dev(dev); 140 141 return genlmsg_unicast(msg, info->snd_pid); 142 143 out_free: 144 nlmsg_free(msg); 145 out_err: 146 cfg80211_put_dev(dev); 147 return -ENOBUFS; 148 } 149 150 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) 151 { 152 struct cfg80211_registered_device *rdev; 153 int result; 154 155 if (!info->attrs[NL80211_ATTR_WIPHY_NAME]) 156 return -EINVAL; 157 158 rdev = cfg80211_get_dev_from_info(info); 159 if (IS_ERR(rdev)) 160 return PTR_ERR(rdev); 161 162 result = cfg80211_dev_rename(rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 163 164 cfg80211_put_dev(rdev); 165 return result; 166 } 167 168 169 static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, 170 struct net_device *dev) 171 { 172 void *hdr; 173 174 hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_INTERFACE); 175 if (!hdr) 176 return -1; 177 178 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 179 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); 180 /* TODO: interface type */ 181 return genlmsg_end(msg, hdr); 182 183 nla_put_failure: 184 return genlmsg_cancel(msg, hdr); 185 } 186 187 static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *cb) 188 { 189 int wp_idx = 0; 190 int if_idx = 0; 191 int wp_start = cb->args[0]; 192 int if_start = cb->args[1]; 193 struct cfg80211_registered_device *dev; 194 struct wireless_dev *wdev; 195 196 mutex_lock(&cfg80211_drv_mutex); 197 list_for_each_entry(dev, &cfg80211_drv_list, list) { 198 if (++wp_idx < wp_start) 199 continue; 200 if_idx = 0; 201 202 mutex_lock(&dev->devlist_mtx); 203 list_for_each_entry(wdev, &dev->netdev_list, list) { 204 if (++if_idx < if_start) 205 continue; 206 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, 207 cb->nlh->nlmsg_seq, NLM_F_MULTI, 208 wdev->netdev) < 0) 209 break; 210 } 211 mutex_unlock(&dev->devlist_mtx); 212 } 213 mutex_unlock(&cfg80211_drv_mutex); 214 215 cb->args[0] = wp_idx; 216 cb->args[1] = if_idx; 217 218 return skb->len; 219 } 220 221 static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info) 222 { 223 struct sk_buff *msg; 224 struct cfg80211_registered_device *dev; 225 struct net_device *netdev; 226 int err; 227 228 err = get_drv_dev_by_info_ifindex(info, &dev, &netdev); 229 if (err) 230 return err; 231 232 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 233 if (!msg) 234 goto out_err; 235 236 if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, netdev) < 0) 237 goto out_free; 238 239 dev_put(netdev); 240 cfg80211_put_dev(dev); 241 242 return genlmsg_unicast(msg, info->snd_pid); 243 244 out_free: 245 nlmsg_free(msg); 246 out_err: 247 dev_put(netdev); 248 cfg80211_put_dev(dev); 249 return -ENOBUFS; 250 } 251 252 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 253 { 254 struct cfg80211_registered_device *drv; 255 int err, ifindex; 256 enum nl80211_iftype type; 257 struct net_device *dev; 258 259 if (info->attrs[NL80211_ATTR_IFTYPE]) { 260 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 261 if (type > NL80211_IFTYPE_MAX) 262 return -EINVAL; 263 } else 264 return -EINVAL; 265 266 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 267 if (err) 268 return err; 269 ifindex = dev->ifindex; 270 dev_put(dev); 271 272 if (!drv->ops->change_virtual_intf) { 273 err = -EOPNOTSUPP; 274 goto unlock; 275 } 276 277 rtnl_lock(); 278 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type); 279 rtnl_unlock(); 280 281 unlock: 282 cfg80211_put_dev(drv); 283 return err; 284 } 285 286 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) 287 { 288 struct cfg80211_registered_device *drv; 289 int err; 290 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; 291 292 if (!info->attrs[NL80211_ATTR_IFNAME]) 293 return -EINVAL; 294 295 if (info->attrs[NL80211_ATTR_IFTYPE]) { 296 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 297 if (type > NL80211_IFTYPE_MAX) 298 return -EINVAL; 299 } 300 301 drv = cfg80211_get_dev_from_info(info); 302 if (IS_ERR(drv)) 303 return PTR_ERR(drv); 304 305 if (!drv->ops->add_virtual_intf) { 306 err = -EOPNOTSUPP; 307 goto unlock; 308 } 309 310 rtnl_lock(); 311 err = drv->ops->add_virtual_intf(&drv->wiphy, 312 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type); 313 rtnl_unlock(); 314 315 unlock: 316 cfg80211_put_dev(drv); 317 return err; 318 } 319 320 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) 321 { 322 struct cfg80211_registered_device *drv; 323 int ifindex, err; 324 struct net_device *dev; 325 326 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 327 if (err) 328 return err; 329 ifindex = dev->ifindex; 330 dev_put(dev); 331 332 if (!drv->ops->del_virtual_intf) { 333 err = -EOPNOTSUPP; 334 goto out; 335 } 336 337 rtnl_lock(); 338 err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); 339 rtnl_unlock(); 340 341 out: 342 cfg80211_put_dev(drv); 343 return err; 344 } 345 346 struct get_key_cookie { 347 struct sk_buff *msg; 348 int error; 349 }; 350 351 static void get_key_callback(void *c, struct key_params *params) 352 { 353 struct get_key_cookie *cookie = c; 354 355 if (params->key) 356 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_DATA, 357 params->key_len, params->key); 358 359 if (params->seq) 360 NLA_PUT(cookie->msg, NL80211_ATTR_KEY_SEQ, 361 params->seq_len, params->seq); 362 363 if (params->cipher) 364 NLA_PUT_U32(cookie->msg, NL80211_ATTR_KEY_CIPHER, 365 params->cipher); 366 367 return; 368 nla_put_failure: 369 cookie->error = 1; 370 } 371 372 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) 373 { 374 struct cfg80211_registered_device *drv; 375 int err; 376 struct net_device *dev; 377 u8 key_idx = 0; 378 u8 *mac_addr = NULL; 379 struct get_key_cookie cookie = { 380 .error = 0, 381 }; 382 void *hdr; 383 struct sk_buff *msg; 384 385 if (info->attrs[NL80211_ATTR_KEY_IDX]) 386 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 387 388 if (key_idx > 3) 389 return -EINVAL; 390 391 if (info->attrs[NL80211_ATTR_MAC]) 392 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 393 394 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 395 if (err) 396 return err; 397 398 if (!drv->ops->get_key) { 399 err = -EOPNOTSUPP; 400 goto out; 401 } 402 403 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 404 if (!msg) { 405 err = -ENOMEM; 406 goto out; 407 } 408 409 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, 410 NL80211_CMD_NEW_KEY); 411 412 if (IS_ERR(hdr)) { 413 err = PTR_ERR(hdr); 414 goto out; 415 } 416 417 cookie.msg = msg; 418 419 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 420 NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, key_idx); 421 if (mac_addr) 422 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 423 424 rtnl_lock(); 425 err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, 426 &cookie, get_key_callback); 427 rtnl_unlock(); 428 429 if (err) 430 goto out; 431 432 if (cookie.error) 433 goto nla_put_failure; 434 435 genlmsg_end(msg, hdr); 436 err = genlmsg_unicast(msg, info->snd_pid); 437 goto out; 438 439 nla_put_failure: 440 err = -ENOBUFS; 441 nlmsg_free(msg); 442 out: 443 cfg80211_put_dev(drv); 444 dev_put(dev); 445 return err; 446 } 447 448 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) 449 { 450 struct cfg80211_registered_device *drv; 451 int err; 452 struct net_device *dev; 453 u8 key_idx; 454 455 if (!info->attrs[NL80211_ATTR_KEY_IDX]) 456 return -EINVAL; 457 458 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 459 460 if (key_idx > 3) 461 return -EINVAL; 462 463 /* currently only support setting default key */ 464 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) 465 return -EINVAL; 466 467 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 468 if (err) 469 return err; 470 471 if (!drv->ops->set_default_key) { 472 err = -EOPNOTSUPP; 473 goto out; 474 } 475 476 rtnl_lock(); 477 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); 478 rtnl_unlock(); 479 480 out: 481 cfg80211_put_dev(drv); 482 dev_put(dev); 483 return err; 484 } 485 486 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) 487 { 488 struct cfg80211_registered_device *drv; 489 int err; 490 struct net_device *dev; 491 struct key_params params; 492 u8 key_idx = 0; 493 u8 *mac_addr = NULL; 494 495 memset(¶ms, 0, sizeof(params)); 496 497 if (!info->attrs[NL80211_ATTR_KEY_CIPHER]) 498 return -EINVAL; 499 500 if (info->attrs[NL80211_ATTR_KEY_DATA]) { 501 params.key = nla_data(info->attrs[NL80211_ATTR_KEY_DATA]); 502 params.key_len = nla_len(info->attrs[NL80211_ATTR_KEY_DATA]); 503 } 504 505 if (info->attrs[NL80211_ATTR_KEY_IDX]) 506 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 507 508 params.cipher = nla_get_u32(info->attrs[NL80211_ATTR_KEY_CIPHER]); 509 510 if (info->attrs[NL80211_ATTR_MAC]) 511 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 512 513 if (key_idx > 3) 514 return -EINVAL; 515 516 /* 517 * Disallow pairwise keys with non-zero index unless it's WEP 518 * (because current deployments use pairwise WEP keys with 519 * non-zero indizes but 802.11i clearly specifies to use zero) 520 */ 521 if (mac_addr && key_idx && 522 params.cipher != WLAN_CIPHER_SUITE_WEP40 && 523 params.cipher != WLAN_CIPHER_SUITE_WEP104) 524 return -EINVAL; 525 526 /* TODO: add definitions for the lengths to linux/ieee80211.h */ 527 switch (params.cipher) { 528 case WLAN_CIPHER_SUITE_WEP40: 529 if (params.key_len != 5) 530 return -EINVAL; 531 break; 532 case WLAN_CIPHER_SUITE_TKIP: 533 if (params.key_len != 32) 534 return -EINVAL; 535 break; 536 case WLAN_CIPHER_SUITE_CCMP: 537 if (params.key_len != 16) 538 return -EINVAL; 539 break; 540 case WLAN_CIPHER_SUITE_WEP104: 541 if (params.key_len != 13) 542 return -EINVAL; 543 break; 544 default: 545 return -EINVAL; 546 } 547 548 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 549 if (err) 550 return err; 551 552 if (!drv->ops->add_key) { 553 err = -EOPNOTSUPP; 554 goto out; 555 } 556 557 rtnl_lock(); 558 err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); 559 rtnl_unlock(); 560 561 out: 562 cfg80211_put_dev(drv); 563 dev_put(dev); 564 return err; 565 } 566 567 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) 568 { 569 struct cfg80211_registered_device *drv; 570 int err; 571 struct net_device *dev; 572 u8 key_idx = 0; 573 u8 *mac_addr = NULL; 574 575 if (info->attrs[NL80211_ATTR_KEY_IDX]) 576 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 577 578 if (key_idx > 3) 579 return -EINVAL; 580 581 if (info->attrs[NL80211_ATTR_MAC]) 582 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 583 584 err = get_drv_dev_by_info_ifindex(info, &drv, &dev); 585 if (err) 586 return err; 587 588 if (!drv->ops->del_key) { 589 err = -EOPNOTSUPP; 590 goto out; 591 } 592 593 rtnl_lock(); 594 err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); 595 rtnl_unlock(); 596 597 out: 598 cfg80211_put_dev(drv); 599 dev_put(dev); 600 return err; 601 } 602 603 static struct genl_ops nl80211_ops[] = { 604 { 605 .cmd = NL80211_CMD_GET_WIPHY, 606 .doit = nl80211_get_wiphy, 607 .dumpit = nl80211_dump_wiphy, 608 .policy = nl80211_policy, 609 /* can be retrieved by unprivileged users */ 610 }, 611 { 612 .cmd = NL80211_CMD_SET_WIPHY, 613 .doit = nl80211_set_wiphy, 614 .policy = nl80211_policy, 615 .flags = GENL_ADMIN_PERM, 616 }, 617 { 618 .cmd = NL80211_CMD_GET_INTERFACE, 619 .doit = nl80211_get_interface, 620 .dumpit = nl80211_dump_interface, 621 .policy = nl80211_policy, 622 /* can be retrieved by unprivileged users */ 623 }, 624 { 625 .cmd = NL80211_CMD_SET_INTERFACE, 626 .doit = nl80211_set_interface, 627 .policy = nl80211_policy, 628 .flags = GENL_ADMIN_PERM, 629 }, 630 { 631 .cmd = NL80211_CMD_NEW_INTERFACE, 632 .doit = nl80211_new_interface, 633 .policy = nl80211_policy, 634 .flags = GENL_ADMIN_PERM, 635 }, 636 { 637 .cmd = NL80211_CMD_DEL_INTERFACE, 638 .doit = nl80211_del_interface, 639 .policy = nl80211_policy, 640 .flags = GENL_ADMIN_PERM, 641 }, 642 { 643 .cmd = NL80211_CMD_GET_KEY, 644 .doit = nl80211_get_key, 645 .policy = nl80211_policy, 646 .flags = GENL_ADMIN_PERM, 647 }, 648 { 649 .cmd = NL80211_CMD_SET_KEY, 650 .doit = nl80211_set_key, 651 .policy = nl80211_policy, 652 .flags = GENL_ADMIN_PERM, 653 }, 654 { 655 .cmd = NL80211_CMD_NEW_KEY, 656 .doit = nl80211_new_key, 657 .policy = nl80211_policy, 658 .flags = GENL_ADMIN_PERM, 659 }, 660 { 661 .cmd = NL80211_CMD_DEL_KEY, 662 .doit = nl80211_del_key, 663 .policy = nl80211_policy, 664 .flags = GENL_ADMIN_PERM, 665 }, 666 }; 667 668 /* multicast groups */ 669 static struct genl_multicast_group nl80211_config_mcgrp = { 670 .name = "config", 671 }; 672 673 /* notification functions */ 674 675 void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev) 676 { 677 struct sk_buff *msg; 678 679 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 680 if (!msg) 681 return; 682 683 if (nl80211_send_wiphy(msg, 0, 0, 0, rdev) < 0) { 684 nlmsg_free(msg); 685 return; 686 } 687 688 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); 689 } 690 691 /* initialisation/exit functions */ 692 693 int nl80211_init(void) 694 { 695 int err, i; 696 697 err = genl_register_family(&nl80211_fam); 698 if (err) 699 return err; 700 701 for (i = 0; i < ARRAY_SIZE(nl80211_ops); i++) { 702 err = genl_register_ops(&nl80211_fam, &nl80211_ops[i]); 703 if (err) 704 goto err_out; 705 } 706 707 err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp); 708 if (err) 709 goto err_out; 710 711 return 0; 712 err_out: 713 genl_unregister_family(&nl80211_fam); 714 return err; 715 } 716 717 void nl80211_exit(void) 718 { 719 genl_unregister_family(&nl80211_fam); 720 } 721