aboutsummaryrefslogtreecommitdiffstats
path: root/net/decnet
diff options
context:
space:
mode:
Diffstat (limited to 'net/decnet')
-rw-r--r--net/decnet/Kconfig8
-rw-r--r--net/decnet/dn_dev.c173
-rw-r--r--net/decnet/dn_neigh.c1
-rw-r--r--net/decnet/dn_nsp_in.c2
-rw-r--r--net/decnet/dn_route.c46
-rw-r--r--net/decnet/dn_rules.c43
-rw-r--r--net/decnet/dn_table.c42
7 files changed, 150 insertions, 165 deletions
diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig
index 36e72cb145b0..7914fd619c5c 100644
--- a/net/decnet/Kconfig
+++ b/net/decnet/Kconfig
@@ -41,11 +41,3 @@ config DECNET_ROUTER
41 41
42 See <file:Documentation/networking/decnet.txt> for more information. 42 See <file:Documentation/networking/decnet.txt> for more information.
43 43
44config DECNET_ROUTE_FWMARK
45 bool "DECnet: use FWMARK value as routing key (EXPERIMENTAL)"
46 depends on DECNET_ROUTER && NETFILTER
47 help
48 If you say Y here, you will be able to specify different routes for
49 packets with different FWMARK ("firewalling mark") values
50 (see ipchains(8), "-m" argument).
51
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, },
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index ff0ebe99137d..7322bb36e825 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -591,7 +591,6 @@ static int dn_neigh_seq_open(struct inode *inode, struct file *file)
591 591
592 seq = file->private_data; 592 seq = file->private_data;
593 seq->private = s; 593 seq->private = s;
594 memset(s, 0, sizeof(*s));
595out: 594out:
596 return rc; 595 return rc;
597out_kfree: 596out_kfree:
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 7683d4f754d2..39a6cf7fb566 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -804,7 +804,7 @@ got_it:
804 goto free_out; 804 goto free_out;
805 } 805 }
806 806
807 return sk_receive_skb(sk, skb); 807 return sk_receive_skb(sk, skb, 0);
808 } 808 }
809 809
810 return dn_nsp_no_socket(skb, reason); 810 return dn_nsp_no_socket(skb, reason);
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 23489f7232d2..9881933167bd 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -269,9 +269,7 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
269{ 269{
270 return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) | 270 return ((fl1->nl_u.dn_u.daddr ^ fl2->nl_u.dn_u.daddr) |
271 (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) | 271 (fl1->nl_u.dn_u.saddr ^ fl2->nl_u.dn_u.saddr) |
272#ifdef CONFIG_DECNET_ROUTE_FWMARK 272 (fl1->mark ^ fl2->mark) |
273 (fl1->nl_u.dn_u.fwmark ^ fl2->nl_u.dn_u.fwmark) |
274#endif
275 (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) | 273 (fl1->nl_u.dn_u.scope ^ fl2->nl_u.dn_u.scope) |
276 (fl1->oif ^ fl2->oif) | 274 (fl1->oif ^ fl2->oif) |
277 (fl1->iif ^ fl2->iif)) == 0; 275 (fl1->iif ^ fl2->iif)) == 0;
@@ -882,10 +880,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
882 { .daddr = oldflp->fld_dst, 880 { .daddr = oldflp->fld_dst,
883 .saddr = oldflp->fld_src, 881 .saddr = oldflp->fld_src,
884 .scope = RT_SCOPE_UNIVERSE, 882 .scope = RT_SCOPE_UNIVERSE,
885#ifdef CONFIG_DECNET_ROUTE_FWMARK
886 .fwmark = oldflp->fld_fwmark
887#endif
888 } }, 883 } },
884 .mark = oldflp->mark,
889 .iif = loopback_dev.ifindex, 885 .iif = loopback_dev.ifindex,
890 .oif = oldflp->oif }; 886 .oif = oldflp->oif };
891 struct dn_route *rt = NULL; 887 struct dn_route *rt = NULL;
@@ -903,7 +899,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
903 "dn_route_output_slow: dst=%04x src=%04x mark=%d" 899 "dn_route_output_slow: dst=%04x src=%04x mark=%d"
904 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst), 900 " iif=%d oif=%d\n", dn_ntohs(oldflp->fld_dst),
905 dn_ntohs(oldflp->fld_src), 901 dn_ntohs(oldflp->fld_src),
906 oldflp->fld_fwmark, loopback_dev.ifindex, oldflp->oif); 902 oldflp->mark, loopback_dev.ifindex, oldflp->oif);
907 903
908 /* If we have an output interface, verify its a DECnet device */ 904 /* If we have an output interface, verify its a DECnet device */
909 if (oldflp->oif) { 905 if (oldflp->oif) {
@@ -1108,9 +1104,7 @@ make_route:
1108 rt->fl.fld_dst = oldflp->fld_dst; 1104 rt->fl.fld_dst = oldflp->fld_dst;
1109 rt->fl.oif = oldflp->oif; 1105 rt->fl.oif = oldflp->oif;
1110 rt->fl.iif = 0; 1106 rt->fl.iif = 0;
1111#ifdef CONFIG_DECNET_ROUTE_FWMARK 1107 rt->fl.mark = oldflp->mark;
1112 rt->fl.fld_fwmark = oldflp->fld_fwmark;
1113#endif
1114 1108
1115 rt->rt_saddr = fl.fld_src; 1109 rt->rt_saddr = fl.fld_src;
1116 rt->rt_daddr = fl.fld_dst; 1110 rt->rt_daddr = fl.fld_dst;
@@ -1178,9 +1172,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
1178 rt = rcu_dereference(rt->u.rt_next)) { 1172 rt = rcu_dereference(rt->u.rt_next)) {
1179 if ((flp->fld_dst == rt->fl.fld_dst) && 1173 if ((flp->fld_dst == rt->fl.fld_dst) &&
1180 (flp->fld_src == rt->fl.fld_src) && 1174 (flp->fld_src == rt->fl.fld_src) &&
1181#ifdef CONFIG_DECNET_ROUTE_FWMARK 1175 (flp->mark == rt->fl.mark) &&
1182 (flp->fld_fwmark == rt->fl.fld_fwmark) &&
1183#endif
1184 (rt->fl.iif == 0) && 1176 (rt->fl.iif == 0) &&
1185 (rt->fl.oif == flp->oif)) { 1177 (rt->fl.oif == flp->oif)) {
1186 rt->u.dst.lastuse = jiffies; 1178 rt->u.dst.lastuse = jiffies;
@@ -1235,10 +1227,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
1235 { .daddr = cb->dst, 1227 { .daddr = cb->dst,
1236 .saddr = cb->src, 1228 .saddr = cb->src,
1237 .scope = RT_SCOPE_UNIVERSE, 1229 .scope = RT_SCOPE_UNIVERSE,
1238#ifdef CONFIG_DECNET_ROUTE_FWMARK
1239 .fwmark = skb->nfmark
1240#endif
1241 } }, 1230 } },
1231 .mark = skb->mark,
1242 .iif = skb->dev->ifindex }; 1232 .iif = skb->dev->ifindex };
1243 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE }; 1233 struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE };
1244 int err = -EINVAL; 1234 int err = -EINVAL;
@@ -1385,7 +1375,7 @@ make_route:
1385 rt->fl.fld_dst = cb->dst; 1375 rt->fl.fld_dst = cb->dst;
1386 rt->fl.oif = 0; 1376 rt->fl.oif = 0;
1387 rt->fl.iif = in_dev->ifindex; 1377 rt->fl.iif = in_dev->ifindex;
1388 rt->fl.fld_fwmark = fl.fld_fwmark; 1378 rt->fl.mark = fl.mark;
1389 1379
1390 rt->u.dst.flags = DST_HOST; 1380 rt->u.dst.flags = DST_HOST;
1391 rt->u.dst.neighbour = neigh; 1381 rt->u.dst.neighbour = neigh;
@@ -1457,9 +1447,7 @@ int dn_route_input(struct sk_buff *skb)
1457 if ((rt->fl.fld_src == cb->src) && 1447 if ((rt->fl.fld_src == cb->src) &&
1458 (rt->fl.fld_dst == cb->dst) && 1448 (rt->fl.fld_dst == cb->dst) &&
1459 (rt->fl.oif == 0) && 1449 (rt->fl.oif == 0) &&
1460#ifdef CONFIG_DECNET_ROUTE_FWMARK 1450 (rt->fl.mark == skb->mark) &&
1461 (rt->fl.fld_fwmark == skb->nfmark) &&
1462#endif
1463 (rt->fl.iif == cb->iif)) { 1451 (rt->fl.iif == cb->iif)) {
1464 rt->u.dst.lastuse = jiffies; 1452 rt->u.dst.lastuse = jiffies;
1465 dst_hold(&rt->u.dst); 1453 dst_hold(&rt->u.dst);
@@ -1481,7 +1469,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1481 struct rtmsg *r; 1469 struct rtmsg *r;
1482 struct nlmsghdr *nlh; 1470 struct nlmsghdr *nlh;
1483 unsigned char *b = skb->tail; 1471 unsigned char *b = skb->tail;
1484 struct rta_cacheinfo ci; 1472 long expires;
1485 1473
1486 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); 1474 nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
1487 r = NLMSG_DATA(nlh); 1475 r = NLMSG_DATA(nlh);
@@ -1514,16 +1502,10 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
1514 RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); 1502 RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
1515 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) 1503 if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
1516 goto rtattr_failure; 1504 goto rtattr_failure;
1517 ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); 1505 expires = rt->u.dst.expires ? rt->u.dst.expires - jiffies : 0;
1518 ci.rta_used = rt->u.dst.__use; 1506 if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, expires,
1519 ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); 1507 rt->u.dst.error) < 0)
1520 if (rt->u.dst.expires) 1508 goto rtattr_failure;
1521 ci.rta_expires = jiffies_to_clock_t(rt->u.dst.expires - jiffies);
1522 else
1523 ci.rta_expires = 0;
1524 ci.rta_error = rt->u.dst.error;
1525 ci.rta_id = ci.rta_ts = ci.rta_tsage = 0;
1526 RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci);
1527 if (rt->fl.iif) 1509 if (rt->fl.iif)
1528 RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); 1510 RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);
1529 1511
@@ -1604,8 +1586,6 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
1604 if (rtm->rtm_flags & RTM_F_NOTIFY) 1586 if (rtm->rtm_flags & RTM_F_NOTIFY)
1605 rt->rt_flags |= RTCF_NOTIFY; 1587 rt->rt_flags |= RTCF_NOTIFY;
1606 1588
1607 NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
1608
1609 err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0); 1589 err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);
1610 1590
1611 if (err == 0) 1591 if (err == 0)
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 590e0a72495c..e32d0c3d5a96 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -45,10 +45,6 @@ struct dn_fib_rule
45 __le16 dstmask; 45 __le16 dstmask;
46 __le16 srcmap; 46 __le16 srcmap;
47 u8 flags; 47 u8 flags;
48#ifdef CONFIG_DECNET_ROUTE_FWMARK
49 u32 fwmark;
50 u32 fwmask;
51#endif
52}; 48};
53 49
54static struct dn_fib_rule default_rule = { 50static struct dn_fib_rule default_rule = {
@@ -112,13 +108,9 @@ errout:
112} 108}
113 109
114static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { 110static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = {
115 [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, 111 FRA_GENERIC_POLICY,
116 [FRA_PRIORITY] = { .type = NLA_U32 },
117 [FRA_SRC] = { .type = NLA_U16 }, 112 [FRA_SRC] = { .type = NLA_U16 },
118 [FRA_DST] = { .type = NLA_U16 }, 113 [FRA_DST] = { .type = NLA_U16 },
119 [FRA_FWMARK] = { .type = NLA_U32 },
120 [FRA_FWMASK] = { .type = NLA_U32 },
121 [FRA_TABLE] = { .type = NLA_U32 },
122}; 114};
123 115
124static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) 116static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
@@ -131,11 +123,6 @@ static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
131 ((daddr ^ r->dst) & r->dstmask)) 123 ((daddr ^ r->dst) & r->dstmask))
132 return 0; 124 return 0;
133 125
134#ifdef CONFIG_DECNET_ROUTE_FWMARK
135 if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask)
136 return 0;
137#endif
138
139 return 1; 126 return 1;
140} 127}
141 128
@@ -169,20 +156,6 @@ static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
169 if (tb[FRA_DST]) 156 if (tb[FRA_DST])
170 r->dst = nla_get_u16(tb[FRA_DST]); 157 r->dst = nla_get_u16(tb[FRA_DST]);
171 158
172#ifdef CONFIG_DECNET_ROUTE_FWMARK
173 if (tb[FRA_FWMARK]) {
174 r->fwmark = nla_get_u32(tb[FRA_FWMARK]);
175 if (r->fwmark)
176 /* compatibility: if the mark value is non-zero all bits
177 * are compared unless a mask is explicitly specified.
178 */
179 r->fwmask = 0xFFFFFFFF;
180 }
181
182 if (tb[FRA_FWMASK])
183 r->fwmask = nla_get_u32(tb[FRA_FWMASK]);
184#endif
185
186 r->src_len = frh->src_len; 159 r->src_len = frh->src_len;
187 r->srcmask = dnet_make_mask(r->src_len); 160 r->srcmask = dnet_make_mask(r->src_len);
188 r->dst_len = frh->dst_len; 161 r->dst_len = frh->dst_len;
@@ -203,14 +176,6 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
203 if (frh->dst_len && (r->dst_len != frh->dst_len)) 176 if (frh->dst_len && (r->dst_len != frh->dst_len))
204 return 0; 177 return 0;
205 178
206#ifdef CONFIG_DECNET_ROUTE_FWMARK
207 if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK])))
208 return 0;
209
210 if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK])))
211 return 0;
212#endif
213
214 if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) 179 if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC])))
215 return 0; 180 return 0;
216 181
@@ -248,12 +213,6 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
248 frh->src_len = r->src_len; 213 frh->src_len = r->src_len;
249 frh->tos = 0; 214 frh->tos = 0;
250 215
251#ifdef CONFIG_DECNET_ROUTE_FWMARK
252 if (r->fwmark)
253 NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark);
254 if (r->fwmask || r->fwmark)
255 NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask);
256#endif
257 if (r->dst_len) 216 if (r->dst_len)
258 NLA_PUT_U16(skb, FRA_DST, r->dst); 217 NLA_PUT_U16(skb, FRA_DST, r->dst);
259 if (r->src_len) 218 if (r->src_len)
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 317904bb5896..bdbc3f431668 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
263 return 0; 263 return 0;
264} 264}
265 265
266static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
267{
268 size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
269 + nla_total_size(4) /* RTA_TABLE */
270 + nla_total_size(2) /* RTA_DST */
271 + nla_total_size(4); /* RTA_PRIORITY */
272
273 /* space for nested metrics */
274 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
275
276 if (fi->fib_nhs) {
277 /* Also handles the special case fib_nhs == 1 */
278
279 /* each nexthop is packed in an attribute */
280 size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
281
282 /* may contain a gateway attribute */
283 nhsize += nla_total_size(4);
284
285 /* all nexthops are packed in a nested attribute */
286 payload += nla_total_size(fi->fib_nhs * nhsize);
287 }
288
289 return payload;
290}
291
266static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 292static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
267 u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, 293 u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
268 struct dn_fib_info *fi, unsigned int flags) 294 struct dn_fib_info *fi, unsigned int flags)
@@ -335,17 +361,15 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
335 u32 pid = req ? req->pid : 0; 361 u32 pid = req ? req->pid : 0;
336 int err = -ENOBUFS; 362 int err = -ENOBUFS;
337 363
338 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 364 skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
339 if (skb == NULL) 365 if (skb == NULL)
340 goto errout; 366 goto errout;
341 367
342 err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, 368 err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
343 f->fn_type, f->fn_scope, &f->fn_key, z, 369 f->fn_type, f->fn_scope, &f->fn_key, z,
344 DN_FIB_INFO(f), 0); 370 DN_FIB_INFO(f), 0);
345 if (err < 0) { 371 /* failure implies BUG in dn_fib_nlmsg_size() */
346 kfree_skb(skb); 372 BUG_ON(err < 0);
347 goto errout;
348 }
349 373
350 err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); 374 err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
351errout: 375errout:
@@ -807,10 +831,11 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
807 printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n"); 831 printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table from interrupt\n");
808 return NULL; 832 return NULL;
809 } 833 }
810 if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL)
811 return NULL;
812 834
813 memset(t, 0, sizeof(struct dn_fib_table)); 835 t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
836 GFP_KERNEL);
837 if (t == NULL)
838 return NULL;
814 839
815 t->n = n; 840 t->n = n;
816 t->insert = dn_fib_table_insert; 841 t->insert = dn_fib_table_insert;
@@ -818,7 +843,6 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create)
818 t->lookup = dn_fib_table_lookup; 843 t->lookup = dn_fib_table_lookup;
819 t->flush = dn_fib_table_flush; 844 t->flush = dn_fib_table_flush;
820 t->dump = dn_fib_table_dump; 845 t->dump = dn_fib_table_dump;
821 memset(t->data, 0, sizeof(struct dn_hash));
822 hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]); 846 hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
823 847
824 return t; 848 return t;