diff options
author | Patrick McHardy <kaber@trash.net> | 2007-06-13 15:03:36 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:14:16 -0400 |
commit | 0157f60c0caea24fa8347f4c0ed53297c412fce1 (patch) | |
tree | da02eb5bd1230395e4a431e5d61779ba89d4188b | |
parent | 6472ce6096bf27d85a1f2580964a36f290bd60a9 (diff) |
[RTNETLINK]: Split up rtnl_setlink
Split up rtnl_setlink into a function performing validation and a function
performing the actual changes. This allows to share the modifcation logic
with rtnl_newlink, which is introduced by the next patch.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/rtnetlink.c | 105 |
1 files changed, 57 insertions, 48 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 02e8bf084277..25ca219154e0 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -561,44 +561,11 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
561 | [IFLA_LINKMODE] = { .type = NLA_U8 }, | 561 | [IFLA_LINKMODE] = { .type = NLA_U8 }, |
562 | }; | 562 | }; |
563 | 563 | ||
564 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 564 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
565 | struct nlattr **tb, char *ifname) | ||
565 | { | 566 | { |
566 | struct ifinfomsg *ifm; | 567 | int modified = 0, send_addr_notify = 0; |
567 | struct net_device *dev; | 568 | int err; |
568 | int err, send_addr_notify = 0, modified = 0; | ||
569 | struct nlattr *tb[IFLA_MAX+1]; | ||
570 | char ifname[IFNAMSIZ]; | ||
571 | |||
572 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
573 | if (err < 0) | ||
574 | goto errout; | ||
575 | |||
576 | if (tb[IFLA_IFNAME]) | ||
577 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
578 | else | ||
579 | ifname[0] = '\0'; | ||
580 | |||
581 | err = -EINVAL; | ||
582 | ifm = nlmsg_data(nlh); | ||
583 | if (ifm->ifi_index > 0) | ||
584 | dev = dev_get_by_index(ifm->ifi_index); | ||
585 | else if (tb[IFLA_IFNAME]) | ||
586 | dev = dev_get_by_name(ifname); | ||
587 | else | ||
588 | goto errout; | ||
589 | |||
590 | if (dev == NULL) { | ||
591 | err = -ENODEV; | ||
592 | goto errout; | ||
593 | } | ||
594 | |||
595 | if (tb[IFLA_ADDRESS] && | ||
596 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
597 | goto errout_dev; | ||
598 | |||
599 | if (tb[IFLA_BROADCAST] && | ||
600 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
601 | goto errout_dev; | ||
602 | 569 | ||
603 | if (tb[IFLA_MAP]) { | 570 | if (tb[IFLA_MAP]) { |
604 | struct rtnl_link_ifmap *u_map; | 571 | struct rtnl_link_ifmap *u_map; |
@@ -606,12 +573,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
606 | 573 | ||
607 | if (!dev->set_config) { | 574 | if (!dev->set_config) { |
608 | err = -EOPNOTSUPP; | 575 | err = -EOPNOTSUPP; |
609 | goto errout_dev; | 576 | goto errout; |
610 | } | 577 | } |
611 | 578 | ||
612 | if (!netif_device_present(dev)) { | 579 | if (!netif_device_present(dev)) { |
613 | err = -ENODEV; | 580 | err = -ENODEV; |
614 | goto errout_dev; | 581 | goto errout; |
615 | } | 582 | } |
616 | 583 | ||
617 | u_map = nla_data(tb[IFLA_MAP]); | 584 | u_map = nla_data(tb[IFLA_MAP]); |
@@ -624,7 +591,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
624 | 591 | ||
625 | err = dev->set_config(dev, &k_map); | 592 | err = dev->set_config(dev, &k_map); |
626 | if (err < 0) | 593 | if (err < 0) |
627 | goto errout_dev; | 594 | goto errout; |
628 | 595 | ||
629 | modified = 1; | 596 | modified = 1; |
630 | } | 597 | } |
@@ -635,19 +602,19 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
635 | 602 | ||
636 | if (!dev->set_mac_address) { | 603 | if (!dev->set_mac_address) { |
637 | err = -EOPNOTSUPP; | 604 | err = -EOPNOTSUPP; |
638 | goto errout_dev; | 605 | goto errout; |
639 | } | 606 | } |
640 | 607 | ||
641 | if (!netif_device_present(dev)) { | 608 | if (!netif_device_present(dev)) { |
642 | err = -ENODEV; | 609 | err = -ENODEV; |
643 | goto errout_dev; | 610 | goto errout; |
644 | } | 611 | } |
645 | 612 | ||
646 | len = sizeof(sa_family_t) + dev->addr_len; | 613 | len = sizeof(sa_family_t) + dev->addr_len; |
647 | sa = kmalloc(len, GFP_KERNEL); | 614 | sa = kmalloc(len, GFP_KERNEL); |
648 | if (!sa) { | 615 | if (!sa) { |
649 | err = -ENOMEM; | 616 | err = -ENOMEM; |
650 | goto errout_dev; | 617 | goto errout; |
651 | } | 618 | } |
652 | sa->sa_family = dev->type; | 619 | sa->sa_family = dev->type; |
653 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), | 620 | memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), |
@@ -655,7 +622,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
655 | err = dev->set_mac_address(dev, sa); | 622 | err = dev->set_mac_address(dev, sa); |
656 | kfree(sa); | 623 | kfree(sa); |
657 | if (err) | 624 | if (err) |
658 | goto errout_dev; | 625 | goto errout; |
659 | send_addr_notify = 1; | 626 | send_addr_notify = 1; |
660 | modified = 1; | 627 | modified = 1; |
661 | } | 628 | } |
@@ -663,7 +630,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
663 | if (tb[IFLA_MTU]) { | 630 | if (tb[IFLA_MTU]) { |
664 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); | 631 | err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); |
665 | if (err < 0) | 632 | if (err < 0) |
666 | goto errout_dev; | 633 | goto errout; |
667 | modified = 1; | 634 | modified = 1; |
668 | } | 635 | } |
669 | 636 | ||
@@ -675,7 +642,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
675 | if (ifm->ifi_index > 0 && ifname[0]) { | 642 | if (ifm->ifi_index > 0 && ifname[0]) { |
676 | err = dev_change_name(dev, ifname); | 643 | err = dev_change_name(dev, ifname); |
677 | if (err < 0) | 644 | if (err < 0) |
678 | goto errout_dev; | 645 | goto errout; |
679 | modified = 1; | 646 | modified = 1; |
680 | } | 647 | } |
681 | 648 | ||
@@ -684,7 +651,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
684 | send_addr_notify = 1; | 651 | send_addr_notify = 1; |
685 | } | 652 | } |
686 | 653 | ||
687 | |||
688 | if (ifm->ifi_flags || ifm->ifi_change) { | 654 | if (ifm->ifi_flags || ifm->ifi_change) { |
689 | unsigned int flags = ifm->ifi_flags; | 655 | unsigned int flags = ifm->ifi_flags; |
690 | 656 | ||
@@ -712,7 +678,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
712 | 678 | ||
713 | err = 0; | 679 | err = 0; |
714 | 680 | ||
715 | errout_dev: | 681 | errout: |
716 | if (err < 0 && modified && net_ratelimit()) | 682 | if (err < 0 && modified && net_ratelimit()) |
717 | printk(KERN_WARNING "A link change request failed with " | 683 | printk(KERN_WARNING "A link change request failed with " |
718 | "some changes comitted already. Interface %s may " | 684 | "some changes comitted already. Interface %s may " |
@@ -721,7 +687,50 @@ errout_dev: | |||
721 | 687 | ||
722 | if (send_addr_notify) | 688 | if (send_addr_notify) |
723 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 689 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
690 | return err; | ||
691 | } | ||
724 | 692 | ||
693 | static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
694 | { | ||
695 | struct ifinfomsg *ifm; | ||
696 | struct net_device *dev; | ||
697 | int err; | ||
698 | struct nlattr *tb[IFLA_MAX+1]; | ||
699 | char ifname[IFNAMSIZ]; | ||
700 | |||
701 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | ||
702 | if (err < 0) | ||
703 | goto errout; | ||
704 | |||
705 | if (tb[IFLA_IFNAME]) | ||
706 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
707 | else | ||
708 | ifname[0] = '\0'; | ||
709 | |||
710 | err = -EINVAL; | ||
711 | ifm = nlmsg_data(nlh); | ||
712 | if (ifm->ifi_index > 0) | ||
713 | dev = dev_get_by_index(ifm->ifi_index); | ||
714 | else if (tb[IFLA_IFNAME]) | ||
715 | dev = dev_get_by_name(ifname); | ||
716 | else | ||
717 | goto errout; | ||
718 | |||
719 | if (dev == NULL) { | ||
720 | err = -ENODEV; | ||
721 | goto errout; | ||
722 | } | ||
723 | |||
724 | if (tb[IFLA_ADDRESS] && | ||
725 | nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) | ||
726 | goto errout_dev; | ||
727 | |||
728 | if (tb[IFLA_BROADCAST] && | ||
729 | nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) | ||
730 | goto errout_dev; | ||
731 | |||
732 | err = do_setlink(dev, ifm, tb, ifname); | ||
733 | errout_dev: | ||
725 | dev_put(dev); | 734 | dev_put(dev); |
726 | errout: | 735 | errout: |
727 | return err; | 736 | return err; |