Commit 5ac8a1be authored by David S. Miller's avatar David S. Miller

[IPV6]: Pass route attributes all the way down.

parent b3652f38
...@@ -201,9 +201,10 @@ enum rtattr_type_t ...@@ -201,9 +201,10 @@ enum rtattr_type_t
RTA_FLOW, RTA_FLOW,
RTA_CACHEINFO, RTA_CACHEINFO,
RTA_SESSION, RTA_SESSION,
RTA_HOPLIMIT,
}; };
#define RTA_MAX RTA_SESSION #define RTA_MAX RTA_HOPLIMIT
#define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg)))) #define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
#define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg)) #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
......
#ifndef _NET_DN_FIB_H #ifndef _NET_DN_FIB_H
#define _NET_DN_FIB_H #define _NET_DN_FIB_H
/* WARNING: The ordering of these elements must match ordering
* of RTA_* rtnetlink attribute numbers.
*/
struct dn_kern_rta struct dn_kern_rta
{ {
void *rta_dst; void *rta_dst;
...@@ -13,8 +16,10 @@ struct dn_kern_rta ...@@ -13,8 +16,10 @@ struct dn_kern_rta
struct rtattr *rta_mx; struct rtattr *rta_mx;
struct rtattr *rta_mp; struct rtattr *rta_mp;
unsigned char *rta_protoinfo; unsigned char *rta_protoinfo;
unsigned char *rta_flow; u32 *rta_flow;
struct rta_cacheinfo *rta_ci; struct rta_cacheinfo *rta_ci;
struct rta_session *rta_sess;
u8 *rta_hoplimit;
}; };
struct dn_fib_res { struct dn_fib_res {
......
...@@ -163,10 +163,12 @@ extern int fib6_walk_continue(struct fib6_walker_t *w); ...@@ -163,10 +163,12 @@ extern int fib6_walk_continue(struct fib6_walker_t *w);
extern int fib6_add(struct fib6_node *root, extern int fib6_add(struct fib6_node *root,
struct rt6_info *rt, struct rt6_info *rt,
struct nlmsghdr *nlh); struct nlmsghdr *nlh,
void *rtattr);
extern int fib6_del(struct rt6_info *rt, extern int fib6_del(struct rt6_info *rt,
struct nlmsghdr *nlh); struct nlmsghdr *nlh,
void *rtattr);
extern void inet6_rt_notify(int event, struct rt6_info *rt, extern void inet6_rt_notify(int event, struct rt6_info *rt,
struct nlmsghdr *nlh); struct nlmsghdr *nlh);
......
...@@ -38,9 +38,11 @@ extern void ip6_route_cleanup(void); ...@@ -38,9 +38,11 @@ extern void ip6_route_cleanup(void);
extern int ipv6_route_ioctl(unsigned int cmd, void *arg); extern int ipv6_route_ioctl(unsigned int cmd, void *arg);
extern int ip6_route_add(struct in6_rtmsg *rtmsg, extern int ip6_route_add(struct in6_rtmsg *rtmsg,
struct nlmsghdr *); struct nlmsghdr *,
void *rtattr);
extern int ip6_del_rt(struct rt6_info *, extern int ip6_del_rt(struct rt6_info *,
struct nlmsghdr *); struct nlmsghdr *,
void *rtattr);
extern int ip6_rt_addr_add(struct in6_addr *addr, extern int ip6_rt_addr_add(struct in6_addr *addr,
struct net_device *dev); struct net_device *dev);
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#include <net/flow.h> #include <net/flow.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
/* WARNING: The ordering of these elements must match ordering
* of RTA_* rtnetlink attribute numbers.
*/
struct kern_rta struct kern_rta
{ {
void *rta_dst; void *rta_dst;
...@@ -32,8 +35,10 @@ struct kern_rta ...@@ -32,8 +35,10 @@ struct kern_rta
struct rtattr *rta_mx; struct rtattr *rta_mx;
struct rtattr *rta_mp; struct rtattr *rta_mp;
unsigned char *rta_protoinfo; unsigned char *rta_protoinfo;
unsigned char *rta_flow; u32 *rta_flow;
struct rta_cacheinfo *rta_ci; struct rta_cacheinfo *rta_ci;
struct rta_session *rta_sess;
u8 *rta_hoplimit;
}; };
struct fib_nh struct fib_nh
......
...@@ -1210,7 +1210,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, ...@@ -1210,7 +1210,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
rtmsg.rtmsg_flags |= RTF_NONEXTHOP; rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
ip6_route_add(&rtmsg, NULL); ip6_route_add(&rtmsg, NULL, NULL);
} }
/* Create "default" multicast route to the interface */ /* Create "default" multicast route to the interface */
...@@ -1227,7 +1227,7 @@ static void addrconf_add_mroute(struct net_device *dev) ...@@ -1227,7 +1227,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF; rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF;
rtmsg.rtmsg_type = RTMSG_NEWROUTE; rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg, NULL); ip6_route_add(&rtmsg, NULL, NULL);
} }
static void sit_route_add(struct net_device *dev) static void sit_route_add(struct net_device *dev)
...@@ -1244,7 +1244,7 @@ static void sit_route_add(struct net_device *dev) ...@@ -1244,7 +1244,7 @@ static void sit_route_add(struct net_device *dev)
rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP; rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
ip6_route_add(&rtmsg, NULL); ip6_route_add(&rtmsg, NULL, NULL);
} }
static void addrconf_add_lroute(struct net_device *dev) static void addrconf_add_lroute(struct net_device *dev)
...@@ -1336,7 +1336,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) ...@@ -1336,7 +1336,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) { if (rt->rt6i_flags&RTF_EXPIRES) {
if (pinfo->onlink == 0 || valid_lft == 0) { if (pinfo->onlink == 0 || valid_lft == 0) {
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
rt = NULL; rt = NULL;
} else { } else {
rt->rt6i_expires = rt_expires; rt->rt6i_expires = rt_expires;
...@@ -1960,7 +1960,7 @@ static void addrconf_rs_timer(unsigned long data) ...@@ -1960,7 +1960,7 @@ static void addrconf_rs_timer(unsigned long data)
rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex; rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
ip6_route_add(&rtmsg, NULL); ip6_route_add(&rtmsg, NULL, NULL);
} }
out: out:
......
...@@ -502,7 +502,7 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt) ...@@ -502,7 +502,7 @@ static __inline__ void fib6_start_gc(struct rt6_info *rt)
* with source addr info in sub-trees * with source addr info in sub-trees
*/ */
int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh) int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
{ {
struct fib6_node *fn; struct fib6_node *fn;
int err = -ENOMEM; int err = -ENOMEM;
...@@ -884,7 +884,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) ...@@ -884,7 +884,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
} }
static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
struct nlmsghdr *nlh) struct nlmsghdr *nlh, void *_rtattr)
{ {
struct fib6_walker_t *w; struct fib6_walker_t *w;
struct rt6_info *rt = *rtp; struct rt6_info *rt = *rtp;
...@@ -943,7 +943,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, ...@@ -943,7 +943,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
rt6_release(rt); rt6_release(rt);
} }
int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh) int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
{ {
struct fib6_node *fn = rt->rt6i_node; struct fib6_node *fn = rt->rt6i_node;
struct rt6_info **rtp; struct rt6_info **rtp;
...@@ -968,7 +968,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh) ...@@ -968,7 +968,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh)
for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
if (*rtp == rt) { if (*rtp == rt) {
fib6_del_route(fn, rtp, nlh); fib6_del_route(fn, rtp, nlh, _rtattr);
return 0; return 0;
} }
} }
...@@ -1097,7 +1097,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) ...@@ -1097,7 +1097,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
res = c->func(rt, c->arg); res = c->func(rt, c->arg);
if (res < 0) { if (res < 0) {
w->leaf = rt; w->leaf = rt;
res = fib6_del(rt, NULL); res = fib6_del(rt, NULL, NULL);
if (res) { if (res) {
#if RT6_DEBUG >= 2 #if RT6_DEBUG >= 2
printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
......
...@@ -976,7 +976,7 @@ void ndisc_recv_na(struct sk_buff *skb) ...@@ -976,7 +976,7 @@ void ndisc_recv_na(struct sk_buff *skb)
struct rt6_info *rt; struct rt6_info *rt;
rt = rt6_get_dflt_router(saddr, dev); rt = rt6_get_dflt_router(saddr, dev);
if (rt) if (rt)
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
} }
} else { } else {
if (msg->icmph.icmp6_router) if (msg->icmph.icmp6_router)
...@@ -1050,7 +1050,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) ...@@ -1050,7 +1050,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev); rt = rt6_get_dflt_router(&skb->nh.ipv6h->saddr, skb->dev);
if (rt && lifetime == 0) { if (rt && lifetime == 0) {
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
rt = NULL; rt = NULL;
} }
......
...@@ -324,12 +324,12 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, ...@@ -324,12 +324,12 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
be destroyed. be destroyed.
*/ */
static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh) static int rt6_ins(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
{ {
int err; int err;
write_lock_bh(&rt6_lock); write_lock_bh(&rt6_lock);
err = fib6_add(&ip6_routing_table, rt, nlh); err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr);
write_unlock_bh(&rt6_lock); write_unlock_bh(&rt6_lock);
return err; return err;
...@@ -372,7 +372,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, ...@@ -372,7 +372,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
dst_hold(&rt->u.dst); dst_hold(&rt->u.dst);
err = rt6_ins(rt, NULL); err = rt6_ins(rt, NULL, NULL);
if (err == 0) if (err == 0)
return rt; return rt;
...@@ -526,7 +526,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) ...@@ -526,7 +526,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
if (rt) { if (rt) {
if (rt->rt6i_flags & RTF_CACHE) if (rt->rt6i_flags & RTF_CACHE)
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
else else
dst_release(dst); dst_release(dst);
} }
...@@ -629,14 +629,17 @@ static int ipv6_get_hoplimit(struct net_device *dev) ...@@ -629,14 +629,17 @@ static int ipv6_get_hoplimit(struct net_device *dev)
* *
*/ */
int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
{ {
int err; int err;
struct rtmsg *r; struct rtmsg *r;
struct rtattr **rta;
struct rt6_info *rt; struct rt6_info *rt;
struct net_device *dev = NULL; struct net_device *dev = NULL;
int addr_type; int addr_type;
rta = (struct rtattr **) _rtattr;
if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128) if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128)
return -EINVAL; return -EINVAL;
#ifndef CONFIG_IPV6_SUBTREES #ifndef CONFIG_IPV6_SUBTREES
...@@ -768,13 +771,38 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) ...@@ -768,13 +771,38 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
rt->rt6i_hoplimit = IPV6_DEFAULT_MCASTHOPS; rt->rt6i_hoplimit = IPV6_DEFAULT_MCASTHOPS;
else if (rta && rta[RTA_HOPLIMIT-1])
memcpy(&rt->rt6i_hoplimit, RTA_DATA(rta[RTA_HOPLIMIT-1]), 1);
else else
rt->rt6i_hoplimit = ipv6_get_hoplimit(dev); rt->rt6i_hoplimit = ipv6_get_hoplimit(dev);
rt->rt6i_flags = rtmsg->rtmsg_flags; rt->rt6i_flags = rtmsg->rtmsg_flags;
install_route: install_route:
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); if (rta && rta[RTA_METRICS-1]) {
rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, dst_pmtu(&rt->u.dst) - 60, ip6_rt_min_advmss); int attrlen = RTA_PAYLOAD(rta[RTA_METRICS-1]);
struct rtattr *attr = RTA_DATA(rta[RTA_METRICS-1]);
while (RTA_OK(attr, attrlen)) {
unsigned flavor = attr->rta_type;
if (flavor) {
if (flavor > RTAX_MAX) {
err = -EINVAL;
goto out;
}
rt->u.dst.metrics[flavor-1] =
*(u32 *)RTA_DATA(attr);
}
attr = RTA_NEXT(attr, attrlen);
}
}
if (!rt->u.dst.metrics[RTAX_MTU-1])
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
rt->u.dst.metrics[RTAX_ADVMSS-1] =
max_t(unsigned int, dst_pmtu(&rt->u.dst) - 60,
ip6_rt_min_advmss);
/* Maximal non-jumbo IPv6 payload is 65535 and corresponding /* Maximal non-jumbo IPv6 payload is 65535 and corresponding
MSS is 65535 - tcp_header_size. 65535 is also valid and MSS is 65535 - tcp_header_size. 65535 is also valid and
means: "any MSS, rely only on pmtu discovery" means: "any MSS, rely only on pmtu discovery"
...@@ -782,7 +810,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) ...@@ -782,7 +810,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535-20) if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535-20)
rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535; rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
rt->u.dst.dev = dev; rt->u.dst.dev = dev;
return rt6_ins(rt, nlh); return rt6_ins(rt, nlh, _rtattr);
out: out:
if (dev) if (dev)
...@@ -791,7 +819,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) ...@@ -791,7 +819,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
return err; return err;
} }
int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh) int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
{ {
int err; int err;
...@@ -803,13 +831,13 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh) ...@@ -803,13 +831,13 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh)
dst_release(&rt->u.dst); dst_release(&rt->u.dst);
err = fib6_del(rt, nlh); err = fib6_del(rt, nlh, _rtattr);
write_unlock_bh(&rt6_lock); write_unlock_bh(&rt6_lock);
return err; return err;
} }
static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
{ {
struct fib6_node *fn; struct fib6_node *fn;
struct rt6_info *rt; struct rt6_info *rt;
...@@ -836,7 +864,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) ...@@ -836,7 +864,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
dst_hold(&rt->u.dst); dst_hold(&rt->u.dst);
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
return ip6_del_rt(rt, nlh); return ip6_del_rt(rt, nlh, _rtattr);
} }
} }
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
...@@ -938,11 +966,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, ...@@ -938,11 +966,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
nrt->u.dst.metrics[RTAX_ADVMSS-1] = 65535; nrt->u.dst.metrics[RTAX_ADVMSS-1] = 65535;
nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev); nrt->rt6i_hoplimit = ipv6_get_hoplimit(neigh->dev);
if (rt6_ins(nrt, NULL)) if (rt6_ins(nrt, NULL, NULL))
goto out; goto out;
if (rt->rt6i_flags&RTF_CACHE) { if (rt->rt6i_flags&RTF_CACHE) {
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
return; return;
} }
...@@ -1028,7 +1056,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, ...@@ -1028,7 +1056,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES; nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
rt6_ins(nrt, NULL); rt6_ins(nrt, NULL, NULL);
} }
out: out:
...@@ -1099,7 +1127,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, ...@@ -1099,7 +1127,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_ifindex = dev->ifindex;
ip6_route_add(&rtmsg, NULL); ip6_route_add(&rtmsg, NULL, NULL);
return rt6_get_dflt_router(gwaddr, dev); return rt6_get_dflt_router(gwaddr, dev);
} }
...@@ -1125,7 +1153,7 @@ void rt6_purge_dflt_routers(int last_resort) ...@@ -1125,7 +1153,7 @@ void rt6_purge_dflt_routers(int last_resort)
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
ip6_del_rt(rt, NULL); ip6_del_rt(rt, NULL, NULL);
goto restart; goto restart;
} }
...@@ -1151,10 +1179,10 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg) ...@@ -1151,10 +1179,10 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
rtnl_lock(); rtnl_lock();
switch (cmd) { switch (cmd) {
case SIOCADDRT: case SIOCADDRT:
err = ip6_route_add(&rtmsg, NULL); err = ip6_route_add(&rtmsg, NULL, NULL);
break; break;
case SIOCDELRT: case SIOCDELRT:
err = ip6_route_del(&rtmsg, NULL); err = ip6_route_del(&rtmsg, NULL, NULL);
break; break;
default: default:
err = -EINVAL; err = -EINVAL;
...@@ -1210,7 +1238,7 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev) ...@@ -1210,7 +1238,7 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
ipv6_addr_copy(&rt->rt6i_dst.addr, addr); ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128; rt->rt6i_dst.plen = 128;
rt6_ins(rt, NULL); rt6_ins(rt, NULL, NULL);
return 0; return 0;
} }
...@@ -1227,7 +1255,7 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev) ...@@ -1227,7 +1255,7 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1); rt = rt6_lookup(addr, NULL, loopback_dev.ifindex, 1);
if (rt) { if (rt) {
if (rt->rt6i_dst.plen == 128) if (rt->rt6i_dst.plen == 128)
err = ip6_del_rt(rt, NULL); err = ip6_del_rt(rt, NULL, NULL);
else else
dst_release(&rt->u.dst); dst_release(&rt->u.dst);
} }
...@@ -1357,7 +1385,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1357,7 +1385,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; return -EINVAL;
return ip6_route_del(&rtmsg, nlh); return ip6_route_del(&rtmsg, nlh, arg);
} }
int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
...@@ -1367,7 +1395,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) ...@@ -1367,7 +1395,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL; return -EINVAL;
return ip6_route_add(&rtmsg, nlh); return ip6_route_add(&rtmsg, nlh, arg);
} }
struct rt6_rtnl_dump_arg struct rt6_rtnl_dump_arg
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment