Commit caab50f0 authored by Hideaki Yoshifuji's avatar Hideaki Yoshifuji

[IPV6] addrconf_dst_alloc() to allocate new route for local address.

Signed-Off-By: default avatarHideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
parent b08bb6d2
...@@ -72,6 +72,10 @@ extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev, ...@@ -72,6 +72,10 @@ extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
extern int ndisc_dst_gc(int *more); extern int ndisc_dst_gc(int *more);
extern void fib6_force_start_gc(void); extern void fib6_force_start_gc(void);
extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
const struct in6_addr *addr,
int anycast);
/* /*
* support functions for ND * support functions for ND
* *
......
...@@ -1303,23 +1303,26 @@ int ip6_pkt_discard_out(struct sk_buff **pskb) ...@@ -1303,23 +1303,26 @@ int ip6_pkt_discard_out(struct sk_buff **pskb)
} }
/* /*
* Add address * Allocate a dst for local (unicast / anycast) address.
*/ */
int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast) struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
const struct in6_addr *addr,
int anycast)
{ {
struct rt6_info *rt = ip6_dst_alloc(); struct rt6_info *rt = ip6_dst_alloc();
if (rt == NULL) if (rt == NULL)
return -ENOMEM; return ERR_PTR(-ENOMEM);
dev_hold(&loopback_dev); dev_hold(&loopback_dev);
in6_dev_hold(idev);
rt->u.dst.flags = DST_HOST; rt->u.dst.flags = DST_HOST;
rt->u.dst.input = ip6_input; rt->u.dst.input = ip6_input;
rt->u.dst.output = ip6_output; rt->u.dst.output = ip6_output;
rt->rt6i_dev = &loopback_dev; rt->rt6i_dev = &loopback_dev;
rt->rt6i_idev = in6_dev_get(&loopback_dev); rt->rt6i_idev = idev;
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst)); rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev); rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev);
...@@ -1331,14 +1334,39 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast) ...@@ -1331,14 +1334,39 @@ int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
if (rt->rt6i_nexthop == NULL) { if (rt->rt6i_nexthop == NULL) {
dst_free((struct dst_entry *) rt); dst_free((struct dst_entry *) rt);
return -ENOMEM; return ERR_PTR(-ENOMEM);
} }
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;
return rt;
}
/*
* Add address
*/
int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, int anycast)
{
struct inet6_dev *idev;
struct rt6_info *rt;
int err = 0;
idev = in6_dev_get(&loopback_dev);
rt = addrconf_dst_alloc(idev, addr, anycast);
if (IS_ERR(rt)) {
err = PTR_ERR(rt);
goto out;
}
ip6_ins_rt(rt, NULL, NULL); ip6_ins_rt(rt, NULL, NULL);
return 0; out:
if (idev)
in6_dev_put(idev);
return err;
} }
/* Delete address. Warning: you should check that this address /* Delete address. Warning: you should check that this address
......
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