| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * HWSIM IEEE 802.15.4 interface |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * (C) 2018 Mojatau, Alexander Aring <aring@mojatau.com> |
|---|
| 5 | 6 | * Copyright 2007-2012 Siemens AG |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 |
|---|
| 9 | | - * as published by the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | 7 | * |
|---|
| 16 | 8 | * Based on fakelb, original Written by: |
|---|
| 17 | 9 | * Sergey Lapin <slapin@ossfans.org> |
|---|
| .. | .. |
|---|
| 36 | 28 | |
|---|
| 37 | 29 | static LIST_HEAD(hwsim_phys); |
|---|
| 38 | 30 | static DEFINE_MUTEX(hwsim_phys_lock); |
|---|
| 39 | | - |
|---|
| 40 | | -static LIST_HEAD(hwsim_ifup_phys); |
|---|
| 41 | 31 | |
|---|
| 42 | 32 | static struct platform_device *mac802154hwsim_dev; |
|---|
| 43 | 33 | |
|---|
| .. | .. |
|---|
| 85 | 75 | struct list_head edges; |
|---|
| 86 | 76 | |
|---|
| 87 | 77 | struct list_head list; |
|---|
| 88 | | - struct list_head list_ifup; |
|---|
| 89 | 78 | }; |
|---|
| 90 | 79 | |
|---|
| 91 | 80 | static int hwsim_add_one(struct genl_info *info, struct device *dev, |
|---|
| .. | .. |
|---|
| 159 | 148 | struct hwsim_phy *phy = hw->priv; |
|---|
| 160 | 149 | |
|---|
| 161 | 150 | phy->suspended = false; |
|---|
| 162 | | - list_add_rcu(&phy->list_ifup, &hwsim_ifup_phys); |
|---|
| 163 | | - synchronize_rcu(); |
|---|
| 164 | | - |
|---|
| 165 | 151 | return 0; |
|---|
| 166 | 152 | } |
|---|
| 167 | 153 | |
|---|
| .. | .. |
|---|
| 170 | 156 | struct hwsim_phy *phy = hw->priv; |
|---|
| 171 | 157 | |
|---|
| 172 | 158 | phy->suspended = true; |
|---|
| 173 | | - list_del_rcu(&phy->list_ifup); |
|---|
| 174 | | - synchronize_rcu(); |
|---|
| 175 | 159 | } |
|---|
| 176 | 160 | |
|---|
| 177 | 161 | static int |
|---|
| .. | .. |
|---|
| 235 | 219 | return 0; |
|---|
| 236 | 220 | } |
|---|
| 237 | 221 | |
|---|
| 238 | | - nl_edges = nla_nest_start(skb, MAC802154_HWSIM_ATTR_RADIO_EDGES); |
|---|
| 222 | + nl_edges = nla_nest_start_noflag(skb, |
|---|
| 223 | + MAC802154_HWSIM_ATTR_RADIO_EDGES); |
|---|
| 239 | 224 | if (!nl_edges) { |
|---|
| 240 | 225 | rcu_read_unlock(); |
|---|
| 241 | 226 | return -ENOBUFS; |
|---|
| 242 | 227 | } |
|---|
| 243 | 228 | |
|---|
| 244 | 229 | list_for_each_entry_rcu(e, &phy->edges, list) { |
|---|
| 245 | | - nl_edge = nla_nest_start(skb, MAC802154_HWSIM_ATTR_RADIO_EDGE); |
|---|
| 230 | + nl_edge = nla_nest_start_noflag(skb, |
|---|
| 231 | + MAC802154_HWSIM_ATTR_RADIO_EDGE); |
|---|
| 246 | 232 | if (!nl_edge) { |
|---|
| 247 | 233 | rcu_read_unlock(); |
|---|
| 248 | 234 | nla_nest_cancel(skb, nl_edges); |
|---|
| .. | .. |
|---|
| 436 | 422 | !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE]) |
|---|
| 437 | 423 | return -EINVAL; |
|---|
| 438 | 424 | |
|---|
| 439 | | - if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, |
|---|
| 440 | | - info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], |
|---|
| 441 | | - hwsim_edge_policy, NULL)) |
|---|
| 425 | + if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL)) |
|---|
| 442 | 426 | return -EINVAL; |
|---|
| 443 | 427 | |
|---|
| 444 | 428 | if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID]) |
|---|
| .. | .. |
|---|
| 500 | 484 | !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE]) |
|---|
| 501 | 485 | return -EINVAL; |
|---|
| 502 | 486 | |
|---|
| 503 | | - if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, |
|---|
| 504 | | - info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], |
|---|
| 505 | | - hwsim_edge_policy, NULL)) |
|---|
| 487 | + if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL)) |
|---|
| 506 | 488 | return -EINVAL; |
|---|
| 507 | 489 | |
|---|
| 508 | 490 | if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID]) |
|---|
| .. | .. |
|---|
| 540 | 522 | static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info) |
|---|
| 541 | 523 | { |
|---|
| 542 | 524 | struct nlattr *edge_attrs[MAC802154_HWSIM_EDGE_ATTR_MAX + 1]; |
|---|
| 543 | | - struct hwsim_edge_info *einfo; |
|---|
| 525 | + struct hwsim_edge_info *einfo, *einfo_old; |
|---|
| 544 | 526 | struct hwsim_phy *phy_v0; |
|---|
| 545 | 527 | struct hwsim_edge *e; |
|---|
| 546 | 528 | u32 v0, v1; |
|---|
| .. | .. |
|---|
| 550 | 532 | !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE]) |
|---|
| 551 | 533 | return -EINVAL; |
|---|
| 552 | 534 | |
|---|
| 553 | | - if (nla_parse_nested(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, |
|---|
| 554 | | - info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], |
|---|
| 555 | | - hwsim_edge_policy, NULL)) |
|---|
| 535 | + if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL)) |
|---|
| 556 | 536 | return -EINVAL; |
|---|
| 557 | 537 | |
|---|
| 558 | 538 | if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] || |
|---|
| .. | .. |
|---|
| 580 | 560 | list_for_each_entry_rcu(e, &phy_v0->edges, list) { |
|---|
| 581 | 561 | if (e->endpoint->idx == v1) { |
|---|
| 582 | 562 | einfo->lqi = lqi; |
|---|
| 583 | | - rcu_assign_pointer(e->info, einfo); |
|---|
| 563 | + einfo_old = rcu_replace_pointer(e->info, einfo, |
|---|
| 564 | + lockdep_is_held(&hwsim_phys_lock)); |
|---|
| 584 | 565 | rcu_read_unlock(); |
|---|
| 566 | + kfree_rcu(einfo_old, rcu); |
|---|
| 585 | 567 | mutex_unlock(&hwsim_phys_lock); |
|---|
| 586 | 568 | return 0; |
|---|
| 587 | 569 | } |
|---|
| .. | .. |
|---|
| 603 | 585 | }; |
|---|
| 604 | 586 | |
|---|
| 605 | 587 | /* Generic Netlink operations array */ |
|---|
| 606 | | -static const struct genl_ops hwsim_nl_ops[] = { |
|---|
| 588 | +static const struct genl_small_ops hwsim_nl_ops[] = { |
|---|
| 607 | 589 | { |
|---|
| 608 | 590 | .cmd = MAC802154_HWSIM_CMD_NEW_RADIO, |
|---|
| 609 | | - .policy = hwsim_genl_policy, |
|---|
| 591 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 610 | 592 | .doit = hwsim_new_radio_nl, |
|---|
| 611 | 593 | .flags = GENL_UNS_ADMIN_PERM, |
|---|
| 612 | 594 | }, |
|---|
| 613 | 595 | { |
|---|
| 614 | 596 | .cmd = MAC802154_HWSIM_CMD_DEL_RADIO, |
|---|
| 615 | | - .policy = hwsim_genl_policy, |
|---|
| 597 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 616 | 598 | .doit = hwsim_del_radio_nl, |
|---|
| 617 | 599 | .flags = GENL_UNS_ADMIN_PERM, |
|---|
| 618 | 600 | }, |
|---|
| 619 | 601 | { |
|---|
| 620 | 602 | .cmd = MAC802154_HWSIM_CMD_GET_RADIO, |
|---|
| 621 | | - .policy = hwsim_genl_policy, |
|---|
| 603 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 622 | 604 | .doit = hwsim_get_radio_nl, |
|---|
| 623 | 605 | .dumpit = hwsim_dump_radio_nl, |
|---|
| 624 | 606 | }, |
|---|
| 625 | 607 | { |
|---|
| 626 | 608 | .cmd = MAC802154_HWSIM_CMD_NEW_EDGE, |
|---|
| 627 | | - .policy = hwsim_genl_policy, |
|---|
| 609 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 628 | 610 | .doit = hwsim_new_edge_nl, |
|---|
| 629 | 611 | .flags = GENL_UNS_ADMIN_PERM, |
|---|
| 630 | 612 | }, |
|---|
| 631 | 613 | { |
|---|
| 632 | 614 | .cmd = MAC802154_HWSIM_CMD_DEL_EDGE, |
|---|
| 633 | | - .policy = hwsim_genl_policy, |
|---|
| 615 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 634 | 616 | .doit = hwsim_del_edge_nl, |
|---|
| 635 | 617 | .flags = GENL_UNS_ADMIN_PERM, |
|---|
| 636 | 618 | }, |
|---|
| 637 | 619 | { |
|---|
| 638 | 620 | .cmd = MAC802154_HWSIM_CMD_SET_EDGE, |
|---|
| 639 | | - .policy = hwsim_genl_policy, |
|---|
| 621 | + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
|---|
| 640 | 622 | .doit = hwsim_set_edge_lqi, |
|---|
| 641 | 623 | .flags = GENL_UNS_ADMIN_PERM, |
|---|
| 642 | 624 | }, |
|---|
| .. | .. |
|---|
| 646 | 628 | .name = "MAC802154_HWSIM", |
|---|
| 647 | 629 | .version = 1, |
|---|
| 648 | 630 | .maxattr = MAC802154_HWSIM_ATTR_MAX, |
|---|
| 631 | + .policy = hwsim_genl_policy, |
|---|
| 649 | 632 | .module = THIS_MODULE, |
|---|
| 650 | | - .ops = hwsim_nl_ops, |
|---|
| 651 | | - .n_ops = ARRAY_SIZE(hwsim_nl_ops), |
|---|
| 633 | + .small_ops = hwsim_nl_ops, |
|---|
| 634 | + .n_small_ops = ARRAY_SIZE(hwsim_nl_ops), |
|---|
| 652 | 635 | .mcgrps = hwsim_mcgrps, |
|---|
| 653 | 636 | .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps), |
|---|
| 654 | 637 | }; |
|---|