aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/rtnetlink.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-06-13 15:03:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:14:16 -0400
commit0157f60c0caea24fa8347f4c0ed53297c412fce1 (patch)
treeda02eb5bd1230395e4a431e5d61779ba89d4188b /net/core/rtnetlink.c
parent6472ce6096bf27d85a1f2580964a36f290bd60a9 (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>
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r--net/core/rtnetlink.c105
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
564static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 564static 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
715errout_dev: 681errout:
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
693static 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);
733errout_dev:
725 dev_put(dev); 734 dev_put(dev);
726errout: 735errout:
727 return err; 736 return err;