aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet/dn_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/decnet/dn_dev.c')
-rw-r--r--net/decnet/dn_dev.c173
1 files changed, 102 insertions, 71 deletions
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index 01861feb608d..0b9d4c955154 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -38,7 +38,6 @@
38#include <linux/if_arp.h> 38#include <linux/if_arp.h>
39#include <linux/if_ether.h> 39#include <linux/if_ether.h>
40#include <linux/skbuff.h> 40#include <linux/skbuff.h>
41#include <linux/rtnetlink.h>
42#include <linux/sysctl.h> 41#include <linux/sysctl.h>
43#include <linux/notifier.h> 42#include <linux/notifier.h>
44#include <asm/uaccess.h> 43#include <asm/uaccess.h>
@@ -47,6 +46,7 @@
47#include <net/dst.h> 46#include <net/dst.h>
48#include <net/flow.h> 47#include <net/flow.h>
49#include <net/fib_rules.h> 48#include <net/fib_rules.h>
49#include <net/netlink.h>
50#include <net/dn.h> 50#include <net/dn.h>
51#include <net/dn_dev.h> 51#include <net/dn_dev.h>
52#include <net/dn_route.h> 52#include <net/dn_route.h>
@@ -73,7 +73,7 @@ static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
73 73
74static struct dn_dev *dn_dev_create(struct net_device *dev, int *err); 74static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
75static void dn_dev_delete(struct net_device *dev); 75static void dn_dev_delete(struct net_device *dev);
76static void rtmsg_ifa(int event, struct dn_ifaddr *ifa); 76static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa);
77 77
78static int dn_eth_up(struct net_device *); 78static int dn_eth_up(struct net_device *);
79static void dn_eth_down(struct net_device *); 79static void dn_eth_down(struct net_device *);
@@ -255,12 +255,10 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
255 struct dn_dev_sysctl_table *t; 255 struct dn_dev_sysctl_table *t;
256 int i; 256 int i;
257 257
258 t = kmalloc(sizeof(*t), GFP_KERNEL); 258 t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL);
259 if (t == NULL) 259 if (t == NULL)
260 return; 260 return;
261 261
262 memcpy(t, &dn_dev_sysctl, sizeof(*t));
263
264 for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) { 262 for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
265 long offset = (long)t->dn_dev_vars[i].data; 263 long offset = (long)t->dn_dev_vars[i].data;
266 t->dn_dev_vars[i].data = ((char *)parms) + offset; 264 t->dn_dev_vars[i].data = ((char *)parms) + offset;
@@ -442,7 +440,7 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
442 } 440 }
443 } 441 }
444 442
445 rtmsg_ifa(RTM_DELADDR, ifa1); 443 dn_ifaddr_notify(RTM_DELADDR, ifa1);
446 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); 444 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
447 if (destroy) { 445 if (destroy) {
448 dn_dev_free_ifa(ifa1); 446 dn_dev_free_ifa(ifa1);
@@ -477,7 +475,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
477 ifa->ifa_next = dn_db->ifa_list; 475 ifa->ifa_next = dn_db->ifa_list;
478 dn_db->ifa_list = ifa; 476 dn_db->ifa_list = ifa;
479 477
480 rtmsg_ifa(RTM_NEWADDR, ifa); 478 dn_ifaddr_notify(RTM_NEWADDR, ifa);
481 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); 479 blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
482 480
483 return 0; 481 return 0;
@@ -647,41 +645,62 @@ static struct dn_dev *dn_dev_by_index(int ifindex)
647 return dn_dev; 645 return dn_dev;
648} 646}
649 647
650static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 648static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
649 [IFA_ADDRESS] = { .type = NLA_U16 },
650 [IFA_LOCAL] = { .type = NLA_U16 },
651 [IFA_LABEL] = { .type = NLA_STRING,
652 .len = IFNAMSIZ - 1 },
653};
654
655static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
651{ 656{
652 struct rtattr **rta = arg; 657 struct nlattr *tb[IFA_MAX+1];
653 struct dn_dev *dn_db; 658 struct dn_dev *dn_db;
654 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 659 struct ifaddrmsg *ifm;
655 struct dn_ifaddr *ifa, **ifap; 660 struct dn_ifaddr *ifa, **ifap;
661 int err = -EADDRNOTAVAIL;
662
663 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
664 if (err < 0)
665 goto errout;
656 666
667 ifm = nlmsg_data(nlh);
657 if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL) 668 if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
658 return -EADDRNOTAVAIL; 669 goto errout;
670
671 for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) {
672 if (tb[IFA_LOCAL] &&
673 nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
674 continue;
659 675
660 for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) { 676 if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
661 void *tmp = rta[IFA_LOCAL-1];
662 if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
663 (rta[IFA_LABEL-1] && rtattr_strcmp(rta[IFA_LABEL-1], ifa->ifa_label)))
664 continue; 677 continue;
665 678
666 dn_dev_del_ifa(dn_db, ifap, 1); 679 dn_dev_del_ifa(dn_db, ifap, 1);
667 return 0; 680 return 0;
668 } 681 }
669 682
670 return -EADDRNOTAVAIL; 683errout:
684 return err;
671} 685}
672 686
673static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 687static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
674{ 688{
675 struct rtattr **rta = arg; 689 struct nlattr *tb[IFA_MAX+1];
676 struct net_device *dev; 690 struct net_device *dev;
677 struct dn_dev *dn_db; 691 struct dn_dev *dn_db;
678 struct ifaddrmsg *ifm = NLMSG_DATA(nlh); 692 struct ifaddrmsg *ifm;
679 struct dn_ifaddr *ifa; 693 struct dn_ifaddr *ifa;
680 int rv; 694 int err;
681 695
682 if (rta[IFA_LOCAL-1] == NULL) 696 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
697 if (err < 0)
698 return err;
699
700 if (tb[IFA_LOCAL] == NULL)
683 return -EINVAL; 701 return -EINVAL;
684 702
703 ifm = nlmsg_data(nlh);
685 if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) 704 if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
686 return -ENODEV; 705 return -ENODEV;
687 706
@@ -695,69 +714,77 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
695 if ((ifa = dn_dev_alloc_ifa()) == NULL) 714 if ((ifa = dn_dev_alloc_ifa()) == NULL)
696 return -ENOBUFS; 715 return -ENOBUFS;
697 716
698 if (!rta[IFA_ADDRESS - 1]) 717 if (tb[IFA_ADDRESS] == NULL)
699 rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; 718 tb[IFA_ADDRESS] = tb[IFA_LOCAL];
700 memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2); 719
701 memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2); 720 ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
721 ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
702 ifa->ifa_flags = ifm->ifa_flags; 722 ifa->ifa_flags = ifm->ifa_flags;
703 ifa->ifa_scope = ifm->ifa_scope; 723 ifa->ifa_scope = ifm->ifa_scope;
704 ifa->ifa_dev = dn_db; 724 ifa->ifa_dev = dn_db;
705 if (rta[IFA_LABEL-1]) 725
706 rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL-1], IFNAMSIZ); 726 if (tb[IFA_LABEL])
727 nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
707 else 728 else
708 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); 729 memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
709 730
710 rv = dn_dev_insert_ifa(dn_db, ifa); 731 err = dn_dev_insert_ifa(dn_db, ifa);
711 if (rv) 732 if (err)
712 dn_dev_free_ifa(ifa); 733 dn_dev_free_ifa(ifa);
713 return rv; 734
735 return err;
714} 736}
715 737
716static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, 738static inline size_t dn_ifaddr_nlmsg_size(void)
717 u32 pid, u32 seq, int event, unsigned int flags) 739{
740 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
741 + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
742 + nla_total_size(2) /* IFA_ADDRESS */
743 + nla_total_size(2); /* IFA_LOCAL */
744}
745
746static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
747 u32 pid, u32 seq, int event, unsigned int flags)
718{ 748{
719 struct ifaddrmsg *ifm; 749 struct ifaddrmsg *ifm;
720 struct nlmsghdr *nlh; 750 struct nlmsghdr *nlh;
721 unsigned char *b = skb->tail;
722 751
723 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); 752 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
724 ifm = NLMSG_DATA(nlh); 753 if (nlh == NULL)
754 return -ENOBUFS;
725 755
756 ifm = nlmsg_data(nlh);
726 ifm->ifa_family = AF_DECnet; 757 ifm->ifa_family = AF_DECnet;
727 ifm->ifa_prefixlen = 16; 758 ifm->ifa_prefixlen = 16;
728 ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT; 759 ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
729 ifm->ifa_scope = ifa->ifa_scope; 760 ifm->ifa_scope = ifa->ifa_scope;
730 ifm->ifa_index = ifa->ifa_dev->dev->ifindex; 761 ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
762
731 if (ifa->ifa_address) 763 if (ifa->ifa_address)
732 RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address); 764 NLA_PUT_LE16(skb, IFA_ADDRESS, ifa->ifa_address);
733 if (ifa->ifa_local) 765 if (ifa->ifa_local)
734 RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local); 766 NLA_PUT_LE16(skb, IFA_LOCAL, ifa->ifa_local);
735 if (ifa->ifa_label[0]) 767 if (ifa->ifa_label[0])
736 RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); 768 NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
737 nlh->nlmsg_len = skb->tail - b; 769
738 return skb->len; 770 return nlmsg_end(skb, nlh);
739 771
740nlmsg_failure: 772nla_put_failure:
741rtattr_failure: 773 return nlmsg_cancel(skb, nlh);
742 skb_trim(skb, b - skb->data);
743 return -1;
744} 774}
745 775
746static void rtmsg_ifa(int event, struct dn_ifaddr *ifa) 776static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
747{ 777{
748 struct sk_buff *skb; 778 struct sk_buff *skb;
749 int payload = sizeof(struct ifaddrmsg) + 128;
750 int err = -ENOBUFS; 779 int err = -ENOBUFS;
751 780
752 skb = alloc_skb(nlmsg_total_size(payload), GFP_KERNEL); 781 skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL);
753 if (skb == NULL) 782 if (skb == NULL)
754 goto errout; 783 goto errout;
755 784
756 err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0); 785 err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
757 if (err < 0) { 786 /* failure implies BUG in dn_ifaddr_nlmsg_size() */
758 kfree_skb(skb); 787 BUG_ON(err < 0);
759 goto errout;
760 }
761 788
762 err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL); 789 err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
763errout: 790errout:
@@ -765,39 +792,43 @@ errout:
765 rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err); 792 rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
766} 793}
767 794
768static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 795static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
769{ 796{
770 int idx, dn_idx; 797 int idx, dn_idx = 0, skip_ndevs, skip_naddr;
771 int s_idx, s_dn_idx;
772 struct net_device *dev; 798 struct net_device *dev;
773 struct dn_dev *dn_db; 799 struct dn_dev *dn_db;
774 struct dn_ifaddr *ifa; 800 struct dn_ifaddr *ifa;
775 801
776 s_idx = cb->args[0]; 802 skip_ndevs = cb->args[0];
777 s_dn_idx = dn_idx = cb->args[1]; 803 skip_naddr = cb->args[1];
804
778 read_lock(&dev_base_lock); 805 read_lock(&dev_base_lock);
779 for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) { 806 for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
780 if (idx < s_idx) 807 if (idx < skip_ndevs)
781 continue; 808 continue;
782 if (idx > s_idx) 809 else if (idx > skip_ndevs) {
783 s_dn_idx = 0; 810 /* Only skip over addresses for first dev dumped
811 * in this iteration (idx == skip_ndevs) */
812 skip_naddr = 0;
813 }
814
784 if ((dn_db = dev->dn_ptr) == NULL) 815 if ((dn_db = dev->dn_ptr) == NULL)
785 continue; 816 continue;
786 817
787 for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) { 818 for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
788 if (dn_idx < s_dn_idx) 819 ifa = ifa->ifa_next, dn_idx++) {
820 if (dn_idx < skip_naddr)
789 continue; 821 continue;
790 822
791 if (dn_dev_fill_ifaddr(skb, ifa, 823 if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
792 NETLINK_CB(cb->skb).pid, 824 cb->nlh->nlmsg_seq, RTM_NEWADDR,
793 cb->nlh->nlmsg_seq, 825 NLM_F_MULTI) < 0)
794 RTM_NEWADDR,
795 NLM_F_MULTI) <= 0)
796 goto done; 826 goto done;
797 } 827 }
798 } 828 }
799done: 829done:
800 read_unlock(&dev_base_lock); 830 read_unlock(&dev_base_lock);
831
801 cb->args[0] = idx; 832 cb->args[0] = idx;
802 cb->args[1] = dn_idx; 833 cb->args[1] = dn_idx;
803 834
@@ -1414,9 +1445,9 @@ static struct file_operations dn_dev_seq_fops = {
1414 1445
1415static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] = 1446static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] =
1416{ 1447{
1417 [RTM_NEWADDR - RTM_BASE] = { .doit = dn_dev_rtm_newaddr, }, 1448 [RTM_NEWADDR - RTM_BASE] = { .doit = dn_nl_newaddr, },
1418 [RTM_DELADDR - RTM_BASE] = { .doit = dn_dev_rtm_deladdr, }, 1449 [RTM_DELADDR - RTM_BASE] = { .doit = dn_nl_deladdr, },
1419 [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_dev_dump_ifaddr, }, 1450 [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_nl_dump_ifaddr, },
1420#ifdef CONFIG_DECNET_ROUTER 1451#ifdef CONFIG_DECNET_ROUTER
1421 [RTM_NEWROUTE - RTM_BASE] = { .doit = dn_fib_rtm_newroute, }, 1452 [RTM_NEWROUTE - RTM_BASE] = { .doit = dn_fib_rtm_newroute, },
1422 [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, }, 1453 [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, },