20 #include <linux/string.h>
21 #include <linux/net.h>
22 #include <linux/socket.h>
23 #include <linux/slab.h>
27 #include <linux/netlink.h>
28 #include <linux/rtnetlink.h>
30 #include <linux/netdevice.h>
34 #include <asm/uaccess.h>
45 #define RT_MIN_TABLE 1
47 #define for_fib_info() { struct dn_fib_info *fi;\
48 for(fi = dn_fib_info_list; fi; fi = fi->fib_next)
49 #define endfor_fib_info() }
51 #define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
52 for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
54 #define change_nexthops(fi) { int nhsel; struct dn_fib_nh *nh;\
55 for(nhsel = 0, nh = (struct dn_fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
57 #define endfor_nexthops(fi) }
102 spin_lock(&dn_fib_info_lock);
108 if (fi == dn_fib_info_list)
113 spin_unlock(&dn_fib_info_lock);
121 if (nh->nh_oif != onh->
nh_oif ||
122 nh->nh_gw != onh->
nh_gw ||
142 (nfi->
fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0))
150 while(
RTA_OK(attr,attrlen)) {
159 static int dn_fib_count_nhs(
struct rtattr *rta)
165 while(nhlen >= (
int)
sizeof(
struct rtnexthop)) {
181 int attrlen = nhlen -
sizeof(
struct rtnexthop);
182 if (attrlen < 0 || (nhlen -= nhp->
rtnh_len) < 0)
224 memset(&fld, 0,
sizeof(fld));
225 fld.daddr = nh->
nh_gw;
226 fld.flowidn_oif = nh->
nh_oif;
285 nhs = dn_fib_count_nhs(rta->
rta_mp);
304 while(
RTA_OK(attr, attrlen)) {
305 unsigned int flavour = attr->
rta_type;
319 if ((err = dn_fib_get_nhs(fi, rta->
rta_mp, r)) != 0)
342 if (dn_fib_props[r->
rtm_type].error) {
355 if (nhs != 1 || nh->
nh_gw)
364 if ((err = dn_fib_check_nh(r, fi, nh)) != 0)
377 if ((ofi = dn_fib_find_info(fi)) !=
NULL) {
386 spin_lock(&dn_fib_info_lock);
389 if (dn_fib_info_list)
391 dn_fib_info_list = fi;
392 spin_unlock(&dn_fib_info_lock);
410 int err = dn_fib_props[
type].error;
428 if (!fld->flowidn_oif ||
429 fld->flowidn_oif == nh->
nh_oif)
432 if (nhsel < fi->fib_nhs) {
455 spin_lock_bh(&dn_fib_multipath_lock);
466 spin_unlock_bh(&dn_fib_multipath_lock);
480 spin_unlock_bh(&dn_fib_multipath_lock);
486 spin_unlock_bh(&dn_fib_multipath_lock);
490 static int dn_fib_check_attr(
struct rtmsg *r,
struct rtattr **rta)
494 for(i = 1; i <=
RTA_MAX; i++) {
518 struct net *
net = sock_net(skb->
sk);
526 if (dn_fib_check_attr(r, rta))
536 static int dn_fib_rtm_newroute(
struct sk_buff *skb,
struct nlmsghdr *nlh,
void *arg)
538 struct net *net = sock_net(skb->
sk);
546 if (dn_fib_check_attr(r, rta))
566 memset(&rta, 0,
sizeof(rta));
576 req.nlh.nlmsg_len =
sizeof(
req);
579 req.nlh.nlmsg_pid = 0;
580 req.nlh.nlmsg_seq = 0;
582 req.rtm.rtm_dst_len = dst_len;
583 req.rtm.rtm_table = tb->
n;
590 rta.rta_oif = &ifa->
ifa_dev->dev->ifindex;
598 static void dn_fib_add_ifaddr(
struct dn_ifaddr *ifa)
611 static void dn_fib_del_ifaddr(
struct dn_ifaddr *ifa)
649 if (dn_fib_sync_down(0, dev, force))
661 dn_fib_add_ifaddr(ifa);
662 dn_fib_sync_up(ifa->
ifa_dev->dev);
666 dn_fib_del_ifaddr(ifa);
668 dn_fib_disable_addr(ifa->
ifa_dev->dev, 1);
677 static int dn_fib_sync_down(
__le16 local,
struct net_device *dev,
int force)
695 }
else if (dev && fi->
fib_nhs) {
701 else if (nh->
nh_dev == dev &&
703 spin_lock_bh(&dn_fib_multipath_lock);
707 spin_unlock_bh(&dn_fib_multipath_lock);
711 if (dead == fi->fib_nhs) {
721 static int dn_fib_sync_up(
struct net_device *dev)
741 spin_lock_bh(&dn_fib_multipath_lock);
744 spin_unlock_bh(&dn_fib_multipath_lock);
756 .notifier_call = dn_fib_dnaddr_event,