mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Merge branch 'master' of /repos/git/net-next-2.6
Conflicts: include/net/netfilter/xt_rateest.h net/bridge/br_netfilter.c net/netfilter/nf_conntrack_core.c Signed-off-by: Patrick McHardy <[email protected]>
This commit is contained in:
commit
f9181f4ffc
531 changed files with 14835 additions and 8682 deletions
|
|
@ -557,7 +557,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
|
|||
pr_warning("Freeing alive inet6 address %p\n", ifp);
|
||||
return;
|
||||
}
|
||||
dst_release(&ifp->rt->u.dst);
|
||||
dst_release(&ifp->rt->dst);
|
||||
|
||||
call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu);
|
||||
}
|
||||
|
|
@ -823,7 +823,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
|
|||
rt->rt6i_flags |= RTF_EXPIRES;
|
||||
}
|
||||
}
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
|
||||
out:
|
||||
|
|
@ -1863,7 +1863,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
|
|||
dev, expires, flags);
|
||||
}
|
||||
if (rt)
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
|
||||
/* Try to figure out our local address for this prefix */
|
||||
|
|
@ -4093,11 +4093,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
|
|||
if (ifp->idev->cnf.forwarding)
|
||||
addrconf_leave_anycast(ifp);
|
||||
addrconf_leave_solict(ifp->idev, &ifp->addr);
|
||||
dst_hold(&ifp->rt->u.dst);
|
||||
dst_hold(&ifp->rt->dst);
|
||||
|
||||
if (ifp->state == INET6_IFADDR_STATE_DEAD &&
|
||||
ip6_del_rt(ifp->rt))
|
||||
dst_free(&ifp->rt->u.dst);
|
||||
dst_free(&ifp->rt->dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,11 +53,7 @@ static struct ip6addrlbl_table
|
|||
static inline
|
||||
struct net *ip6addrlbl_net(const struct ip6addrlbl_entry *lbl)
|
||||
{
|
||||
#ifdef CONFIG_NET_NS
|
||||
return lbl->lbl_net;
|
||||
#else
|
||||
return &init_net;
|
||||
#endif
|
||||
return read_pnet(&lbl->lbl_net);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -651,7 +651,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
|
|||
|
||||
if (dst == NULL) {
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct in6_addr *final_p = NULL, final;
|
||||
struct in6_addr *final_p, final;
|
||||
struct flowi fl;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
|
|
@ -665,12 +665,7 @@ int inet6_sk_rebuild_header(struct sock *sk)
|
|||
fl.fl_ip_sport = inet->inet_sport;
|
||||
security_sk_classify_flow(sk, &fl);
|
||||
|
||||
if (np->opt && np->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, np->opt, &final);
|
||||
|
||||
err = ip6_dst_lookup(sk, &dst, &fl);
|
||||
if (err) {
|
||||
|
|
|
|||
|
|
@ -77,41 +77,40 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
|
|||
pac->acl_next = NULL;
|
||||
ipv6_addr_copy(&pac->acl_addr, addr);
|
||||
|
||||
rcu_read_lock();
|
||||
if (ifindex == 0) {
|
||||
struct rt6_info *rt;
|
||||
|
||||
rt = rt6_lookup(net, addr, NULL, 0, 0);
|
||||
if (rt) {
|
||||
dev = rt->rt6i_dev;
|
||||
dev_hold(dev);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
} else if (ishost) {
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto out_free_pac;
|
||||
goto error;
|
||||
} else {
|
||||
/* router, no matching interface: just pick one */
|
||||
|
||||
dev = dev_get_by_flags(net, IFF_UP, IFF_UP|IFF_LOOPBACK);
|
||||
dev = dev_get_by_flags_rcu(net, IFF_UP,
|
||||
IFF_UP | IFF_LOOPBACK);
|
||||
}
|
||||
} else
|
||||
dev = dev_get_by_index(net, ifindex);
|
||||
dev = dev_get_by_index_rcu(net, ifindex);
|
||||
|
||||
if (dev == NULL) {
|
||||
err = -ENODEV;
|
||||
goto out_free_pac;
|
||||
goto error;
|
||||
}
|
||||
|
||||
idev = in6_dev_get(dev);
|
||||
idev = __in6_dev_get(dev);
|
||||
if (!idev) {
|
||||
if (ifindex)
|
||||
err = -ENODEV;
|
||||
else
|
||||
err = -EADDRNOTAVAIL;
|
||||
goto out_dev_put;
|
||||
goto error;
|
||||
}
|
||||
/* reset ishost, now that we have a specific device */
|
||||
ishost = !idev->cnf.forwarding;
|
||||
in6_dev_put(idev);
|
||||
|
||||
pac->acl_ifindex = dev->ifindex;
|
||||
|
||||
|
|
@ -124,26 +123,22 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr)
|
|||
if (ishost)
|
||||
err = -EADDRNOTAVAIL;
|
||||
if (err)
|
||||
goto out_dev_put;
|
||||
goto error;
|
||||
}
|
||||
|
||||
err = ipv6_dev_ac_inc(dev, addr);
|
||||
if (err)
|
||||
goto out_dev_put;
|
||||
if (!err) {
|
||||
write_lock_bh(&ipv6_sk_ac_lock);
|
||||
pac->acl_next = np->ipv6_ac_list;
|
||||
np->ipv6_ac_list = pac;
|
||||
write_unlock_bh(&ipv6_sk_ac_lock);
|
||||
pac = NULL;
|
||||
}
|
||||
|
||||
write_lock_bh(&ipv6_sk_ac_lock);
|
||||
pac->acl_next = np->ipv6_ac_list;
|
||||
np->ipv6_ac_list = pac;
|
||||
write_unlock_bh(&ipv6_sk_ac_lock);
|
||||
|
||||
dev_put(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
out_dev_put:
|
||||
dev_put(dev);
|
||||
out_free_pac:
|
||||
sock_kfree_s(sk, pac, sizeof(*pac));
|
||||
error:
|
||||
rcu_read_unlock();
|
||||
if (pac)
|
||||
sock_kfree_s(sk, pac, sizeof(*pac));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -176,11 +171,12 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
|
|||
|
||||
write_unlock_bh(&ipv6_sk_ac_lock);
|
||||
|
||||
dev = dev_get_by_index(net, pac->acl_ifindex);
|
||||
if (dev) {
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(net, pac->acl_ifindex);
|
||||
if (dev)
|
||||
ipv6_dev_ac_dec(dev, &pac->acl_addr);
|
||||
dev_put(dev);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
sock_kfree_s(sk, pac, sizeof(*pac));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -199,13 +195,12 @@ void ipv6_sock_ac_close(struct sock *sk)
|
|||
write_unlock_bh(&ipv6_sk_ac_lock);
|
||||
|
||||
prev_index = 0;
|
||||
rcu_read_lock();
|
||||
while (pac) {
|
||||
struct ipv6_ac_socklist *next = pac->acl_next;
|
||||
|
||||
if (pac->acl_ifindex != prev_index) {
|
||||
if (dev)
|
||||
dev_put(dev);
|
||||
dev = dev_get_by_index(net, pac->acl_ifindex);
|
||||
dev = dev_get_by_index_rcu(net, pac->acl_ifindex);
|
||||
prev_index = pac->acl_ifindex;
|
||||
}
|
||||
if (dev)
|
||||
|
|
@ -213,8 +208,7 @@ void ipv6_sock_ac_close(struct sock *sk)
|
|||
sock_kfree_s(sk, pac, sizeof(*pac));
|
||||
pac = next;
|
||||
}
|
||||
if (dev)
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
@ -250,7 +244,7 @@ static void aca_put(struct ifacaddr6 *ac)
|
|||
{
|
||||
if (atomic_dec_and_test(&ac->aca_refcnt)) {
|
||||
in6_dev_put(ac->aca_idev);
|
||||
dst_release(&ac->aca_rt->u.dst);
|
||||
dst_release(&ac->aca_rt->dst);
|
||||
kfree(ac);
|
||||
}
|
||||
}
|
||||
|
|
@ -356,40 +350,39 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
|
|||
write_unlock_bh(&idev->lock);
|
||||
addrconf_leave_solict(idev, &aca->aca_addr);
|
||||
|
||||
dst_hold(&aca->aca_rt->u.dst);
|
||||
dst_hold(&aca->aca_rt->dst);
|
||||
ip6_del_rt(aca->aca_rt);
|
||||
|
||||
aca_put(aca);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called with rcu_read_lock() */
|
||||
static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr)
|
||||
{
|
||||
int ret;
|
||||
struct inet6_dev *idev = in6_dev_get(dev);
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
|
||||
if (idev == NULL)
|
||||
return -ENODEV;
|
||||
ret = __ipv6_dev_ac_dec(idev, addr);
|
||||
in6_dev_put(idev);
|
||||
return ret;
|
||||
return __ipv6_dev_ac_dec(idev, addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* check if the interface has this anycast address
|
||||
* called with rcu_read_lock()
|
||||
*/
|
||||
static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr)
|
||||
{
|
||||
struct inet6_dev *idev;
|
||||
struct ifacaddr6 *aca;
|
||||
|
||||
idev = in6_dev_get(dev);
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev) {
|
||||
read_lock_bh(&idev->lock);
|
||||
for (aca = idev->ac_list; aca; aca = aca->aca_next)
|
||||
if (ipv6_addr_equal(&aca->aca_addr, addr))
|
||||
break;
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
return aca != NULL;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -403,14 +396,15 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
|
|||
{
|
||||
int found = 0;
|
||||
|
||||
if (dev)
|
||||
return ipv6_chk_acast_dev(dev, addr);
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(net, dev)
|
||||
if (ipv6_chk_acast_dev(dev, addr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
if (dev)
|
||||
found = ipv6_chk_acast_dev(dev, addr);
|
||||
else
|
||||
for_each_netdev_rcu(net, dev)
|
||||
if (ipv6_chk_acast_dev(dev, addr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return found;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,10 +38,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct in6_addr *daddr, *final_p = NULL, final;
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
struct dst_entry *dst;
|
||||
struct flowi fl;
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct ipv6_txoptions *opt;
|
||||
int addr_type;
|
||||
int err;
|
||||
|
||||
|
|
@ -155,19 +156,8 @@ ipv4_connected:
|
|||
|
||||
security_sk_classify_flow(sk, &fl);
|
||||
|
||||
if (flowlabel) {
|
||||
if (flowlabel->opt && flowlabel->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
} else if (np->opt && np->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
opt = flowlabel ? flowlabel->opt : np->opt;
|
||||
final_p = fl6_update_dst(&fl, opt, &final);
|
||||
|
||||
err = ip6_dst_lookup(sk, &dst, &fl);
|
||||
if (err)
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
|
|||
Routing header.
|
||||
********************************/
|
||||
|
||||
/* called with rcu_read_lock() */
|
||||
static int ipv6_rthdr_rcv(struct sk_buff *skb)
|
||||
{
|
||||
struct inet6_skb_parm *opt = IP6CB(skb);
|
||||
|
|
@ -324,12 +325,9 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
|
|||
struct net *net = dev_net(skb->dev);
|
||||
int accept_source_route = net->ipv6.devconf_all->accept_source_route;
|
||||
|
||||
idev = in6_dev_get(skb->dev);
|
||||
if (idev) {
|
||||
if (accept_source_route > idev->cnf.accept_source_route)
|
||||
accept_source_route = idev->cnf.accept_source_route;
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
if (idev && accept_source_route > idev->cnf.accept_source_route)
|
||||
accept_source_route = idev->cnf.accept_source_route;
|
||||
|
||||
if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) ||
|
||||
!pskb_may_pull(skb, (skb_transport_offset(skb) +
|
||||
|
|
@ -874,3 +872,27 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
|
|||
return opt;
|
||||
}
|
||||
|
||||
/**
|
||||
* fl6_update_dst - update flowi destination address with info given
|
||||
* by srcrt option, if any.
|
||||
*
|
||||
* @fl: flowi for which fl6_dst is to be updated
|
||||
* @opt: struct ipv6_txoptions in which to look for srcrt opt
|
||||
* @orig: copy of original fl6_dst address if modified
|
||||
*
|
||||
* Returns NULL if no txoptions or no srcrt, otherwise returns orig
|
||||
* and initial value of fl->fl6_dst set in orig
|
||||
*/
|
||||
struct in6_addr *fl6_update_dst(struct flowi *fl,
|
||||
const struct ipv6_txoptions *opt,
|
||||
struct in6_addr *orig)
|
||||
{
|
||||
if (!opt || !opt->srcrt)
|
||||
return NULL;
|
||||
|
||||
ipv6_addr_copy(orig, &fl->fl6_dst);
|
||||
ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr);
|
||||
return orig;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(fl6_update_dst);
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
|
|||
if (arg.result)
|
||||
return arg.result;
|
||||
|
||||
dst_hold(&net->ipv6.ip6_null_entry->u.dst);
|
||||
return &net->ipv6.ip6_null_entry->u.dst;
|
||||
dst_hold(&net->ipv6.ip6_null_entry->dst);
|
||||
return &net->ipv6.ip6_null_entry->dst;
|
||||
}
|
||||
|
||||
static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
|
||||
|
|
@ -86,7 +86,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
|
|||
struct in6_addr saddr;
|
||||
|
||||
if (ipv6_dev_get_saddr(net,
|
||||
ip6_dst_idev(&rt->u.dst)->dev,
|
||||
ip6_dst_idev(&rt->dst)->dev,
|
||||
&flp->fl6_dst,
|
||||
rt6_flags2srcprefs(flags),
|
||||
&saddr))
|
||||
|
|
@ -99,12 +99,12 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
|
|||
goto out;
|
||||
}
|
||||
again:
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
rt = NULL;
|
||||
goto out;
|
||||
|
||||
discard_pkt:
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
out:
|
||||
arg->result = rt;
|
||||
return rt == NULL ? -EAGAIN : 0;
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ route_done:
|
|||
np->tclass, NULL, &fl, (struct rt6_info*)dst,
|
||||
MSG_DONTWAIT, np->dontfrag);
|
||||
if (err) {
|
||||
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
|
||||
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
|
||||
ip6_flush_pending_frames(sk);
|
||||
goto out_put;
|
||||
}
|
||||
|
|
@ -565,7 +565,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
|
|||
np->dontfrag);
|
||||
|
||||
if (err) {
|
||||
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
|
||||
ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
|
||||
ip6_flush_pending_frames(sk);
|
||||
goto out_put;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb)
|
|||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct flowi fl;
|
||||
struct dst_entry *dst;
|
||||
struct in6_addr *final_p = NULL, final;
|
||||
struct in6_addr *final_p, final;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.proto = sk->sk_protocol;
|
||||
|
|
@ -199,12 +199,7 @@ int inet6_csk_xmit(struct sk_buff *skb)
|
|||
fl.fl_ip_dport = inet->inet_dport;
|
||||
security_sk_classify_flow(sk, &fl);
|
||||
|
||||
if (np->opt && np->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, np->opt, &final);
|
||||
|
||||
dst = __inet6_csk_dst_check(sk, np->dst_cookie);
|
||||
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ static __inline__ void node_free(struct fib6_node * fn)
|
|||
static __inline__ void rt6_release(struct rt6_info *rt)
|
||||
{
|
||||
if (atomic_dec_and_test(&rt->rt6i_ref))
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
}
|
||||
|
||||
static void fib6_link_table(struct net *net, struct fib6_table *tb)
|
||||
|
|
@ -278,7 +278,7 @@ static int fib6_dump_node(struct fib6_walker_t *w)
|
|||
int res;
|
||||
struct rt6_info *rt;
|
||||
|
||||
for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = w->leaf; rt; rt = rt->dst.rt6_next) {
|
||||
res = rt6_dump_route(rt, w->args);
|
||||
if (res < 0) {
|
||||
/* Frame is full, suspend walking */
|
||||
|
|
@ -619,7 +619,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|||
|
||||
ins = &fn->leaf;
|
||||
|
||||
for (iter = fn->leaf; iter; iter=iter->u.dst.rt6_next) {
|
||||
for (iter = fn->leaf; iter; iter=iter->dst.rt6_next) {
|
||||
/*
|
||||
* Search for duplicates
|
||||
*/
|
||||
|
|
@ -647,7 +647,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|||
if (iter->rt6i_metric > rt->rt6i_metric)
|
||||
break;
|
||||
|
||||
ins = &iter->u.dst.rt6_next;
|
||||
ins = &iter->dst.rt6_next;
|
||||
}
|
||||
|
||||
/* Reset round-robin state, if necessary */
|
||||
|
|
@ -658,7 +658,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
|
|||
* insert node
|
||||
*/
|
||||
|
||||
rt->u.dst.rt6_next = iter;
|
||||
rt->dst.rt6_next = iter;
|
||||
*ins = rt;
|
||||
rt->rt6i_node = fn;
|
||||
atomic_inc(&rt->rt6i_ref);
|
||||
|
|
@ -799,7 +799,7 @@ out:
|
|||
atomic_inc(&pn->leaf->rt6i_ref);
|
||||
}
|
||||
#endif
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
}
|
||||
return err;
|
||||
|
||||
|
|
@ -810,7 +810,7 @@ out:
|
|||
st_failure:
|
||||
if (fn && !(fn->fn_flags & (RTN_RTINFO|RTN_ROOT)))
|
||||
fib6_repair_tree(info->nl_net, fn);
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
return err;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1108,7 +1108,7 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
|
|||
RT6_TRACE("fib6_del_route\n");
|
||||
|
||||
/* Unlink it */
|
||||
*rtp = rt->u.dst.rt6_next;
|
||||
*rtp = rt->dst.rt6_next;
|
||||
rt->rt6i_node = NULL;
|
||||
net->ipv6.rt6_stats->fib_rt_entries--;
|
||||
net->ipv6.rt6_stats->fib_discarded_routes++;
|
||||
|
|
@ -1122,14 +1122,14 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
|
|||
FOR_WALKERS(w) {
|
||||
if (w->state == FWS_C && w->leaf == rt) {
|
||||
RT6_TRACE("walker %p adjusted by delroute\n", w);
|
||||
w->leaf = rt->u.dst.rt6_next;
|
||||
w->leaf = rt->dst.rt6_next;
|
||||
if (w->leaf == NULL)
|
||||
w->state = FWS_U;
|
||||
}
|
||||
}
|
||||
read_unlock(&fib6_walker_lock);
|
||||
|
||||
rt->u.dst.rt6_next = NULL;
|
||||
rt->dst.rt6_next = NULL;
|
||||
|
||||
/* If it was last route, expunge its radix tree node */
|
||||
if (fn->leaf == NULL) {
|
||||
|
|
@ -1168,7 +1168,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
|
|||
struct rt6_info **rtp;
|
||||
|
||||
#if RT6_DEBUG >= 2
|
||||
if (rt->u.dst.obsolete>0) {
|
||||
if (rt->dst.obsolete>0) {
|
||||
WARN_ON(fn != NULL);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
@ -1195,7 +1195,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
|
|||
* Walk the leaf entries looking for ourself
|
||||
*/
|
||||
|
||||
for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.dst.rt6_next) {
|
||||
for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->dst.rt6_next) {
|
||||
if (*rtp == rt) {
|
||||
fib6_del_route(fn, rtp, info);
|
||||
return 0;
|
||||
|
|
@ -1334,7 +1334,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
|
|||
.nl_net = c->net,
|
||||
};
|
||||
|
||||
for (rt = w->leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = w->leaf; rt; rt = rt->dst.rt6_next) {
|
||||
res = c->func(rt, c->arg);
|
||||
if (res < 0) {
|
||||
w->leaf = rt;
|
||||
|
|
@ -1448,8 +1448,8 @@ static int fib6_age(struct rt6_info *rt, void *arg)
|
|||
}
|
||||
gc_args.more++;
|
||||
} else if (rt->rt6i_flags & RTF_CACHE) {
|
||||
if (atomic_read(&rt->u.dst.__refcnt) == 0 &&
|
||||
time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) {
|
||||
if (atomic_read(&rt->dst.__refcnt) == 0 &&
|
||||
time_after_eq(now, rt->dst.lastuse + gc_args.timeout)) {
|
||||
RT6_TRACE("aging clone %p\n", rt);
|
||||
return -1;
|
||||
} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
|
||||
|
|
|
|||
|
|
@ -698,7 +698,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|||
ipv6_hdr(skb)->payload_len = htons(first_len -
|
||||
sizeof(struct ipv6hdr));
|
||||
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
|
||||
for (;;) {
|
||||
/* Prepare header of the next frame,
|
||||
|
|
@ -726,7 +726,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|||
|
||||
err = output(skb);
|
||||
if(!err)
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
|
||||
IPSTATS_MIB_FRAGCREATES);
|
||||
|
||||
if (err || !frag)
|
||||
|
|
@ -740,9 +740,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|||
kfree(tmp_hdr);
|
||||
|
||||
if (err == 0) {
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
|
||||
IPSTATS_MIB_FRAGOKS);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -752,9 +752,9 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|||
frag = skb;
|
||||
}
|
||||
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->u.dst),
|
||||
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
|
||||
IPSTATS_MIB_FRAGFAILS);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -785,7 +785,7 @@ slow_path:
|
|||
* Allocate buffer.
|
||||
*/
|
||||
|
||||
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) {
|
||||
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) {
|
||||
NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
|
||||
IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
|
||||
IPSTATS_MIB_FRAGFAILS);
|
||||
|
|
@ -798,7 +798,7 @@ slow_path:
|
|||
*/
|
||||
|
||||
ip6_copy_metadata(frag, skb);
|
||||
skb_reserve(frag, LL_RESERVED_SPACE(rt->u.dst.dev));
|
||||
skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev));
|
||||
skb_put(frag, len + hlen + sizeof(struct frag_hdr));
|
||||
skb_reset_network_header(frag);
|
||||
fh = (struct frag_hdr *)(skb_network_header(frag) + hlen);
|
||||
|
|
@ -1156,24 +1156,24 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|||
|
||||
/* need source address above miyazawa*/
|
||||
}
|
||||
dst_hold(&rt->u.dst);
|
||||
inet->cork.dst = &rt->u.dst;
|
||||
dst_hold(&rt->dst);
|
||||
inet->cork.dst = &rt->dst;
|
||||
inet->cork.fl = *fl;
|
||||
np->cork.hop_limit = hlimit;
|
||||
np->cork.tclass = tclass;
|
||||
mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
|
||||
rt->u.dst.dev->mtu : dst_mtu(rt->u.dst.path);
|
||||
rt->dst.dev->mtu : dst_mtu(rt->dst.path);
|
||||
if (np->frag_size < mtu) {
|
||||
if (np->frag_size)
|
||||
mtu = np->frag_size;
|
||||
}
|
||||
inet->cork.fragsize = mtu;
|
||||
if (dst_allfrag(rt->u.dst.path))
|
||||
if (dst_allfrag(rt->dst.path))
|
||||
inet->cork.flags |= IPCORK_ALLFRAG;
|
||||
inet->cork.length = 0;
|
||||
sk->sk_sndmsg_page = NULL;
|
||||
sk->sk_sndmsg_off = 0;
|
||||
exthdrlen = rt->u.dst.header_len + (opt ? opt->opt_flen : 0) -
|
||||
exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) -
|
||||
rt->rt6i_nfheader_len;
|
||||
length += exthdrlen;
|
||||
transhdrlen += exthdrlen;
|
||||
|
|
@ -1186,7 +1186,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|||
mtu = inet->cork.fragsize;
|
||||
}
|
||||
|
||||
hh_len = LL_RESERVED_SPACE(rt->u.dst.dev);
|
||||
hh_len = LL_RESERVED_SPACE(rt->dst.dev);
|
||||
|
||||
fragheaderlen = sizeof(struct ipv6hdr) + rt->rt6i_nfheader_len +
|
||||
(opt ? opt->opt_nflen : 0);
|
||||
|
|
@ -1224,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
|
|||
}
|
||||
|
||||
if (proto == IPPROTO_UDP &&
|
||||
(rt->u.dst.dev->features & NETIF_F_UFO)) {
|
||||
(rt->dst.dev->features & NETIF_F_UFO)) {
|
||||
|
||||
err = ip6_ufo_append_data(sk, getfrag, from, length,
|
||||
hh_len, fragheaderlen,
|
||||
|
|
@ -1270,7 +1270,7 @@ alloc_new_skb:
|
|||
|
||||
fraglen = datalen + fragheaderlen;
|
||||
if ((flags & MSG_MORE) &&
|
||||
!(rt->u.dst.dev->features&NETIF_F_SG))
|
||||
!(rt->dst.dev->features&NETIF_F_SG))
|
||||
alloclen = mtu;
|
||||
else
|
||||
alloclen = datalen + fragheaderlen;
|
||||
|
|
@ -1281,7 +1281,7 @@ alloc_new_skb:
|
|||
* because we have no idea if we're the last one.
|
||||
*/
|
||||
if (datalen == length + fraggap)
|
||||
alloclen += rt->u.dst.trailer_len;
|
||||
alloclen += rt->dst.trailer_len;
|
||||
|
||||
/*
|
||||
* We just reserve space for fragment header.
|
||||
|
|
@ -1358,7 +1358,7 @@ alloc_new_skb:
|
|||
if (copy > length)
|
||||
copy = length;
|
||||
|
||||
if (!(rt->u.dst.dev->features&NETIF_F_SG)) {
|
||||
if (!(rt->dst.dev->features&NETIF_F_SG)) {
|
||||
unsigned int off;
|
||||
|
||||
off = skb->len;
|
||||
|
|
@ -1503,7 +1503,7 @@ int ip6_push_pending_frames(struct sock *sk)
|
|||
skb->priority = sk->sk_priority;
|
||||
skb->mark = sk->sk_mark;
|
||||
|
||||
skb_dst_set(skb, dst_clone(&rt->u.dst));
|
||||
skb_dst_set(skb, dst_clone(&rt->dst));
|
||||
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
|
||||
if (proto == IPPROTO_ICMPV6) {
|
||||
struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb));
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
if (ip_route_output_key(dev_net(skb->dev), &rt, &fl))
|
||||
goto out;
|
||||
|
||||
skb2->dev = rt->u.dst.dev;
|
||||
skb2->dev = rt->dst.dev;
|
||||
|
||||
/* route "incoming" packet */
|
||||
if (rt->rt_flags & RTCF_LOCAL) {
|
||||
|
|
@ -562,7 +562,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
fl.fl4_src = eiph->saddr;
|
||||
fl.fl4_tos = eiph->tos;
|
||||
if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
|
||||
rt->u.dst.dev->type != ARPHRD_TUNNEL) {
|
||||
rt->dst.dev->type != ARPHRD_TUNNEL) {
|
||||
ip_rt_put(rt);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -626,7 +626,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
icmpv6_send(skb2, rel_type, rel_code, rel_info);
|
||||
|
||||
if (rt)
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
|
||||
kfree_skb(skb2);
|
||||
}
|
||||
|
|
@ -1135,7 +1135,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
|
|||
if (dev->mtu < IPV6_MIN_MTU)
|
||||
dev->mtu = IPV6_MIN_MTU;
|
||||
}
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ static void mroute_clean_tables(struct mr6_table *mrt);
|
|||
static void ipmr_expire_process(unsigned long arg);
|
||||
|
||||
#ifdef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
|
||||
#define ip6mr_for_each_table(mrt, met) \
|
||||
#define ip6mr_for_each_table(mrt, net) \
|
||||
list_for_each_entry_rcu(mrt, &net->ipv6.mr6_tables, list)
|
||||
|
||||
static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
|
||||
|
|
@ -254,8 +254,10 @@ static void __net_exit ip6mr_rules_exit(struct net *net)
|
|||
{
|
||||
struct mr6_table *mrt, *next;
|
||||
|
||||
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list)
|
||||
list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) {
|
||||
list_del(&mrt->list);
|
||||
ip6mr_free_table(mrt);
|
||||
}
|
||||
fib_rules_unregister(net->ipv6.mr6_rules_ops);
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
195
net/ipv6/mcast.c
195
net/ipv6/mcast.c
|
|
@ -152,18 +152,19 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
|
|||
mc_lst->next = NULL;
|
||||
ipv6_addr_copy(&mc_lst->addr, addr);
|
||||
|
||||
rcu_read_lock();
|
||||
if (ifindex == 0) {
|
||||
struct rt6_info *rt;
|
||||
rt = rt6_lookup(net, addr, NULL, 0, 0);
|
||||
if (rt) {
|
||||
dev = rt->rt6i_dev;
|
||||
dev_hold(dev);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
} else
|
||||
dev = dev_get_by_index(net, ifindex);
|
||||
dev = dev_get_by_index_rcu(net, ifindex);
|
||||
|
||||
if (dev == NULL) {
|
||||
rcu_read_unlock();
|
||||
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
@ -180,8 +181,8 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
|
|||
err = ipv6_dev_mc_inc(dev, addr);
|
||||
|
||||
if (err) {
|
||||
rcu_read_unlock();
|
||||
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
|
||||
dev_put(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +191,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
|
|||
np->ipv6_mc_list = mc_lst;
|
||||
write_unlock_bh(&ipv6_sk_mc_lock);
|
||||
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -213,18 +214,17 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
|
|||
*lnk = mc_lst->next;
|
||||
write_unlock_bh(&ipv6_sk_mc_lock);
|
||||
|
||||
dev = dev_get_by_index(net, mc_lst->ifindex);
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
|
||||
if (dev != NULL) {
|
||||
struct inet6_dev *idev = in6_dev_get(dev);
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
|
||||
(void) ip6_mc_leave_src(sk, mc_lst, idev);
|
||||
if (idev) {
|
||||
if (idev)
|
||||
__ipv6_dev_mc_dec(idev, &mc_lst->addr);
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
dev_put(dev);
|
||||
} else
|
||||
(void) ip6_mc_leave_src(sk, mc_lst, NULL);
|
||||
rcu_read_unlock();
|
||||
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -234,43 +234,36 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
|
|||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
static struct inet6_dev *ip6_mc_find_dev(struct net *net,
|
||||
struct in6_addr *group,
|
||||
int ifindex)
|
||||
/* called with rcu_read_lock() */
|
||||
static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
|
||||
struct in6_addr *group,
|
||||
int ifindex)
|
||||
{
|
||||
struct net_device *dev = NULL;
|
||||
struct inet6_dev *idev = NULL;
|
||||
|
||||
if (ifindex == 0) {
|
||||
struct rt6_info *rt;
|
||||
struct rt6_info *rt = rt6_lookup(net, group, NULL, 0, 0);
|
||||
|
||||
rt = rt6_lookup(net, group, NULL, 0, 0);
|
||||
if (rt) {
|
||||
dev = rt->rt6i_dev;
|
||||
dev_hold(dev);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
} else
|
||||
dev = dev_get_by_index(net, ifindex);
|
||||
dev = dev_get_by_index_rcu(net, ifindex);
|
||||
|
||||
if (!dev)
|
||||
goto nodev;
|
||||
idev = in6_dev_get(dev);
|
||||
return NULL;
|
||||
idev = __in6_dev_get(dev);
|
||||
if (!idev)
|
||||
goto release;
|
||||
return NULL;;
|
||||
read_lock_bh(&idev->lock);
|
||||
if (idev->dead)
|
||||
goto unlock_release;
|
||||
|
||||
if (idev->dead) {
|
||||
read_unlock_bh(&idev->lock);
|
||||
return NULL;
|
||||
}
|
||||
return idev;
|
||||
|
||||
unlock_release:
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
release:
|
||||
dev_put(dev);
|
||||
nodev:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ipv6_sock_mc_close(struct sock *sk)
|
||||
|
|
@ -286,19 +279,17 @@ void ipv6_sock_mc_close(struct sock *sk)
|
|||
np->ipv6_mc_list = mc_lst->next;
|
||||
write_unlock_bh(&ipv6_sk_mc_lock);
|
||||
|
||||
dev = dev_get_by_index(net, mc_lst->ifindex);
|
||||
rcu_read_lock();
|
||||
dev = dev_get_by_index_rcu(net, mc_lst->ifindex);
|
||||
if (dev) {
|
||||
struct inet6_dev *idev = in6_dev_get(dev);
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
|
||||
(void) ip6_mc_leave_src(sk, mc_lst, idev);
|
||||
if (idev) {
|
||||
if (idev)
|
||||
__ipv6_dev_mc_dec(idev, &mc_lst->addr);
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
dev_put(dev);
|
||||
} else
|
||||
(void) ip6_mc_leave_src(sk, mc_lst, NULL);
|
||||
|
||||
rcu_read_unlock();
|
||||
sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
|
||||
|
||||
write_lock_bh(&ipv6_sk_mc_lock);
|
||||
|
|
@ -327,14 +318,17 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
|
|||
if (!ipv6_addr_is_multicast(group))
|
||||
return -EINVAL;
|
||||
|
||||
idev = ip6_mc_find_dev(net, group, pgsr->gsr_interface);
|
||||
if (!idev)
|
||||
rcu_read_lock();
|
||||
idev = ip6_mc_find_dev_rcu(net, group, pgsr->gsr_interface);
|
||||
if (!idev) {
|
||||
rcu_read_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
dev = idev->dev;
|
||||
|
||||
err = -EADDRNOTAVAIL;
|
||||
|
||||
read_lock_bh(&ipv6_sk_mc_lock);
|
||||
read_lock(&ipv6_sk_mc_lock);
|
||||
for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
|
||||
if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
|
||||
continue;
|
||||
|
|
@ -358,7 +352,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
|
|||
pmc->sfmode = omode;
|
||||
}
|
||||
|
||||
write_lock_bh(&pmc->sflock);
|
||||
write_lock(&pmc->sflock);
|
||||
pmclocked = 1;
|
||||
|
||||
psl = pmc->sflist;
|
||||
|
|
@ -433,11 +427,10 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
|
|||
ip6_mc_add_src(idev, group, omode, 1, source, 1);
|
||||
done:
|
||||
if (pmclocked)
|
||||
write_unlock_bh(&pmc->sflock);
|
||||
read_unlock_bh(&ipv6_sk_mc_lock);
|
||||
write_unlock(&pmc->sflock);
|
||||
read_unlock(&ipv6_sk_mc_lock);
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
if (leavegroup)
|
||||
return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
|
||||
return err;
|
||||
|
|
@ -463,14 +456,17 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
|||
gsf->gf_fmode != MCAST_EXCLUDE)
|
||||
return -EINVAL;
|
||||
|
||||
idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
|
||||
rcu_read_lock();
|
||||
idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
|
||||
|
||||
if (!idev)
|
||||
if (!idev) {
|
||||
rcu_read_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
dev = idev->dev;
|
||||
|
||||
err = 0;
|
||||
read_lock_bh(&ipv6_sk_mc_lock);
|
||||
read_lock(&ipv6_sk_mc_lock);
|
||||
|
||||
if (gsf->gf_fmode == MCAST_INCLUDE && gsf->gf_numsrc == 0) {
|
||||
leavegroup = 1;
|
||||
|
|
@ -512,7 +508,7 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
|||
(void) ip6_mc_add_src(idev, group, gsf->gf_fmode, 0, NULL, 0);
|
||||
}
|
||||
|
||||
write_lock_bh(&pmc->sflock);
|
||||
write_lock(&pmc->sflock);
|
||||
psl = pmc->sflist;
|
||||
if (psl) {
|
||||
(void) ip6_mc_del_src(idev, group, pmc->sfmode,
|
||||
|
|
@ -522,13 +518,12 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
|
|||
(void) ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0);
|
||||
pmc->sflist = newpsl;
|
||||
pmc->sfmode = gsf->gf_fmode;
|
||||
write_unlock_bh(&pmc->sflock);
|
||||
write_unlock(&pmc->sflock);
|
||||
err = 0;
|
||||
done:
|
||||
read_unlock_bh(&ipv6_sk_mc_lock);
|
||||
read_unlock(&ipv6_sk_mc_lock);
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
if (leavegroup)
|
||||
err = ipv6_sock_mc_drop(sk, gsf->gf_interface, group);
|
||||
return err;
|
||||
|
|
@ -551,11 +546,13 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
|
|||
if (!ipv6_addr_is_multicast(group))
|
||||
return -EINVAL;
|
||||
|
||||
idev = ip6_mc_find_dev(net, group, gsf->gf_interface);
|
||||
rcu_read_lock();
|
||||
idev = ip6_mc_find_dev_rcu(net, group, gsf->gf_interface);
|
||||
|
||||
if (!idev)
|
||||
if (!idev) {
|
||||
rcu_read_unlock();
|
||||
return -ENODEV;
|
||||
|
||||
}
|
||||
dev = idev->dev;
|
||||
|
||||
err = -EADDRNOTAVAIL;
|
||||
|
|
@ -577,8 +574,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
|
|||
psl = pmc->sflist;
|
||||
count = psl ? psl->sl_count : 0;
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
|
||||
copycount = count < gsf->gf_numsrc ? count : gsf->gf_numsrc;
|
||||
gsf->gf_numsrc = count;
|
||||
|
|
@ -604,8 +600,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
|
|||
return 0;
|
||||
done:
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
dev_put(dev);
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -822,6 +817,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
|
|||
struct ifmcaddr6 *mc;
|
||||
struct inet6_dev *idev;
|
||||
|
||||
/* we need to take a reference on idev */
|
||||
idev = in6_dev_get(dev);
|
||||
|
||||
if (idev == NULL)
|
||||
|
|
@ -860,7 +856,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
|
|||
setup_timer(&mc->mca_timer, igmp6_timer_handler, (unsigned long)mc);
|
||||
|
||||
ipv6_addr_copy(&mc->mca_addr, addr);
|
||||
mc->idev = idev;
|
||||
mc->idev = idev; /* (reference taken) */
|
||||
mc->mca_users = 1;
|
||||
/* mca_stamp should be updated upon changes */
|
||||
mc->mca_cstamp = mc->mca_tstamp = jiffies;
|
||||
|
|
@ -915,16 +911,18 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
|
|||
|
||||
int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
|
||||
{
|
||||
struct inet6_dev *idev = in6_dev_get(dev);
|
||||
struct inet6_dev *idev;
|
||||
int err;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
idev = __in6_dev_get(dev);
|
||||
if (!idev)
|
||||
return -ENODEV;
|
||||
|
||||
err = __ipv6_dev_mc_dec(idev, addr);
|
||||
|
||||
in6_dev_put(idev);
|
||||
err = -ENODEV;
|
||||
else
|
||||
err = __ipv6_dev_mc_dec(idev, addr);
|
||||
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -965,7 +963,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
|
|||
struct ifmcaddr6 *mc;
|
||||
int rv = 0;
|
||||
|
||||
idev = in6_dev_get(dev);
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev) {
|
||||
read_lock_bh(&idev->lock);
|
||||
for (mc = idev->mc_list; mc; mc=mc->next) {
|
||||
|
|
@ -992,8 +991,8 @@ int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
|
|||
rv = 1; /* don't filter unspecified source */
|
||||
}
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
@ -1104,6 +1103,7 @@ static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* called with rcu_read_lock() */
|
||||
int igmp6_event_query(struct sk_buff *skb)
|
||||
{
|
||||
struct mld2_query *mlh2 = NULL;
|
||||
|
|
@ -1127,7 +1127,7 @@ int igmp6_event_query(struct sk_buff *skb)
|
|||
if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL))
|
||||
return -EINVAL;
|
||||
|
||||
idev = in6_dev_get(skb->dev);
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
|
||||
if (idev == NULL)
|
||||
return 0;
|
||||
|
|
@ -1137,10 +1137,8 @@ int igmp6_event_query(struct sk_buff *skb)
|
|||
group_type = ipv6_addr_type(group);
|
||||
|
||||
if (group_type != IPV6_ADDR_ANY &&
|
||||
!(group_type&IPV6_ADDR_MULTICAST)) {
|
||||
in6_dev_put(idev);
|
||||
!(group_type&IPV6_ADDR_MULTICAST))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (len == 24) {
|
||||
int switchback;
|
||||
|
|
@ -1161,10 +1159,9 @@ int igmp6_event_query(struct sk_buff *skb)
|
|||
} else if (len >= 28) {
|
||||
int srcs_offset = sizeof(struct mld2_query) -
|
||||
sizeof(struct icmp6hdr);
|
||||
if (!pskb_may_pull(skb, srcs_offset)) {
|
||||
in6_dev_put(idev);
|
||||
if (!pskb_may_pull(skb, srcs_offset))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mlh2 = (struct mld2_query *)skb_transport_header(skb);
|
||||
max_delay = (MLDV2_MRC(ntohs(mlh2->mld2q_mrc))*HZ)/1000;
|
||||
if (!max_delay)
|
||||
|
|
@ -1173,28 +1170,23 @@ int igmp6_event_query(struct sk_buff *skb)
|
|||
if (mlh2->mld2q_qrv)
|
||||
idev->mc_qrv = mlh2->mld2q_qrv;
|
||||
if (group_type == IPV6_ADDR_ANY) { /* general query */
|
||||
if (mlh2->mld2q_nsrcs) {
|
||||
in6_dev_put(idev);
|
||||
if (mlh2->mld2q_nsrcs)
|
||||
return -EINVAL; /* no sources allowed */
|
||||
}
|
||||
|
||||
mld_gq_start_timer(idev);
|
||||
in6_dev_put(idev);
|
||||
return 0;
|
||||
}
|
||||
/* mark sources to include, if group & source-specific */
|
||||
if (mlh2->mld2q_nsrcs != 0) {
|
||||
if (!pskb_may_pull(skb, srcs_offset +
|
||||
ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr))) {
|
||||
in6_dev_put(idev);
|
||||
ntohs(mlh2->mld2q_nsrcs) * sizeof(struct in6_addr)))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mlh2 = (struct mld2_query *)skb_transport_header(skb);
|
||||
mark = 1;
|
||||
}
|
||||
} else {
|
||||
in6_dev_put(idev);
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
read_lock_bh(&idev->lock);
|
||||
if (group_type == IPV6_ADDR_ANY) {
|
||||
|
|
@ -1227,12 +1219,11 @@ int igmp6_event_query(struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* called with rcu_read_lock() */
|
||||
int igmp6_event_report(struct sk_buff *skb)
|
||||
{
|
||||
struct ifmcaddr6 *ma;
|
||||
|
|
@ -1260,7 +1251,7 @@ int igmp6_event_report(struct sk_buff *skb)
|
|||
!(addr_type&IPV6_ADDR_LINKLOCAL))
|
||||
return -EINVAL;
|
||||
|
||||
idev = in6_dev_get(skb->dev);
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
if (idev == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
|
|
@ -1280,7 +1271,6 @@ int igmp6_event_report(struct sk_buff *skb)
|
|||
}
|
||||
}
|
||||
read_unlock_bh(&idev->lock);
|
||||
in6_dev_put(idev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1356,7 +1346,10 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
|
|||
IPV6_TLV_PADN, 0 };
|
||||
|
||||
/* we assume size > sizeof(ra) here */
|
||||
skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
|
||||
size += LL_ALLOCATED_SPACE(dev);
|
||||
/* limit our allocations to order-0 page */
|
||||
size = min_t(int, size, SKB_MAX_ORDER(0, 0));
|
||||
skb = sock_alloc_send_skb(sk, size, 1, &err);
|
||||
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
|
@ -1393,12 +1386,14 @@ static void mld_sendpack(struct sk_buff *skb)
|
|||
struct mld2_report *pmr =
|
||||
(struct mld2_report *)skb_transport_header(skb);
|
||||
int payload_len, mldlen;
|
||||
struct inet6_dev *idev = in6_dev_get(skb->dev);
|
||||
struct inet6_dev *idev;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
int err;
|
||||
struct flowi fl;
|
||||
struct dst_entry *dst;
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
|
||||
|
||||
payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
|
||||
|
|
@ -1438,8 +1433,7 @@ out:
|
|||
} else
|
||||
IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS);
|
||||
|
||||
if (likely(idev != NULL))
|
||||
in6_dev_put(idev);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
|
||||
err_out:
|
||||
|
|
@ -1776,7 +1770,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
|
|||
IPPROTO_ICMPV6,
|
||||
csum_partial(hdr, len, 0));
|
||||
|
||||
idev = in6_dev_get(skb->dev);
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
|
||||
dst = icmp6_dst_alloc(skb->dev, NULL, &ipv6_hdr(skb)->daddr);
|
||||
if (!dst) {
|
||||
|
|
@ -1803,8 +1798,7 @@ out:
|
|||
} else
|
||||
IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
|
||||
|
||||
if (likely(idev != NULL))
|
||||
in6_dev_put(idev);
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
|
||||
err_out:
|
||||
|
|
@ -1995,8 +1989,7 @@ static int sf_setstate(struct ifmcaddr6 *pmc)
|
|||
&psf->sf_addr))
|
||||
break;
|
||||
if (!dpsf) {
|
||||
dpsf = (struct ip6_sf_list *)
|
||||
kmalloc(sizeof(*dpsf), GFP_ATOMIC);
|
||||
dpsf = kmalloc(sizeof(*dpsf), GFP_ATOMIC);
|
||||
if (!dpsf)
|
||||
continue;
|
||||
*dpsf = *psf;
|
||||
|
|
|
|||
|
|
@ -1229,7 +1229,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
|||
ND_PRINTK0(KERN_ERR
|
||||
"ICMPv6 RA: %s() got default router without neighbour.\n",
|
||||
__func__);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
in6_dev_put(in6_dev);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1244,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
|
|||
if (ra_msg->icmph.icmp6_hop_limit) {
|
||||
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
|
||||
if (rt)
|
||||
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
|
||||
rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
|
||||
}
|
||||
|
||||
skip_defrtr:
|
||||
|
|
@ -1363,7 +1363,7 @@ skip_linkparms:
|
|||
in6_dev->cnf.mtu6 = mtu;
|
||||
|
||||
if (rt)
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = mtu;
|
||||
rt->dst.metrics[RTAX_MTU-1] = mtu;
|
||||
|
||||
rt6_mtu_change(skb->dev, mtu);
|
||||
}
|
||||
|
|
@ -1384,7 +1384,7 @@ skip_linkparms:
|
|||
}
|
||||
out:
|
||||
if (rt)
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
else if (neigh)
|
||||
neigh_release(neigh);
|
||||
in6_dev_put(in6_dev);
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ ip6t_do_table(struct sk_buff *skb,
|
|||
cpu = smp_processor_id();
|
||||
table_base = private->entries[cpu];
|
||||
jumpstack = (struct ip6t_entry **)private->jumpstack[cpu];
|
||||
stackptr = &private->stackptr[cpu];
|
||||
stackptr = per_cpu_ptr(private->stackptr, cpu);
|
||||
origptr = *stackptr;
|
||||
|
||||
e = get_entry(table_base, private->hook_entry[hook]);
|
||||
|
|
|
|||
|
|
@ -602,31 +602,33 @@ out:
|
|||
}
|
||||
|
||||
static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
|
||||
struct flowi *fl, struct rt6_info *rt,
|
||||
struct flowi *fl, struct dst_entry **dstp,
|
||||
unsigned int flags)
|
||||
{
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct ipv6hdr *iph;
|
||||
struct sk_buff *skb;
|
||||
int err;
|
||||
struct rt6_info *rt = (struct rt6_info *)*dstp;
|
||||
|
||||
if (length > rt->u.dst.dev->mtu) {
|
||||
ipv6_local_error(sk, EMSGSIZE, fl, rt->u.dst.dev->mtu);
|
||||
if (length > rt->dst.dev->mtu) {
|
||||
ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
if (flags&MSG_PROBE)
|
||||
goto out;
|
||||
|
||||
skb = sock_alloc_send_skb(sk,
|
||||
length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15,
|
||||
length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15,
|
||||
flags & MSG_DONTWAIT, &err);
|
||||
if (skb == NULL)
|
||||
goto error;
|
||||
skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev));
|
||||
skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev));
|
||||
|
||||
skb->priority = sk->sk_priority;
|
||||
skb->mark = sk->sk_mark;
|
||||
skb_dst_set(skb, dst_clone(&rt->u.dst));
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
*dstp = NULL;
|
||||
|
||||
skb_put(skb, length);
|
||||
skb_reset_network_header(skb);
|
||||
|
|
@ -641,7 +643,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
|
|||
|
||||
IP6_UPD_PO_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
|
||||
err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL,
|
||||
rt->u.dst.dev, dst_output);
|
||||
rt->dst.dev, dst_output);
|
||||
if (err > 0)
|
||||
err = net_xmit_errno(err);
|
||||
if (err)
|
||||
|
|
@ -725,7 +727,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
{
|
||||
struct ipv6_txoptions opt_space;
|
||||
struct sockaddr_in6 * sin6 = (struct sockaddr_in6 *) msg->msg_name;
|
||||
struct in6_addr *daddr, *final_p = NULL, final;
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct raw6_sock *rp = raw6_sk(sk);
|
||||
|
|
@ -847,13 +849,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
|
||||
ipv6_addr_copy(&fl.fl6_src, &np->saddr);
|
||||
|
||||
/* merge ip6_build_xmit from ip6_output */
|
||||
if (opt && opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, opt, &final);
|
||||
|
||||
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
|
||||
fl.oif = np->mcast_oif;
|
||||
|
|
@ -892,9 +888,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
goto do_confirm;
|
||||
|
||||
back_from_confirm:
|
||||
if (inet->hdrincl) {
|
||||
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags);
|
||||
} else {
|
||||
if (inet->hdrincl)
|
||||
err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags);
|
||||
else {
|
||||
lock_sock(sk);
|
||||
err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
|
||||
len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
|
||||
|
|
|
|||
317
net/ipv6/route.c
317
net/ipv6/route.c
|
|
@ -126,16 +126,14 @@ static struct dst_ops ip6_dst_blackhole_ops = {
|
|||
};
|
||||
|
||||
static struct rt6_info ip6_null_entry_template = {
|
||||
.u = {
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -ENETUNREACH,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_discard,
|
||||
.output = ip6_pkt_discard_out,
|
||||
}
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -ENETUNREACH,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_discard,
|
||||
.output = ip6_pkt_discard_out,
|
||||
},
|
||||
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
||||
.rt6i_protocol = RTPROT_KERNEL,
|
||||
|
|
@ -149,16 +147,14 @@ static int ip6_pkt_prohibit(struct sk_buff *skb);
|
|||
static int ip6_pkt_prohibit_out(struct sk_buff *skb);
|
||||
|
||||
static struct rt6_info ip6_prohibit_entry_template = {
|
||||
.u = {
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -EACCES,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_prohibit,
|
||||
.output = ip6_pkt_prohibit_out,
|
||||
}
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -EACCES,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = ip6_pkt_prohibit,
|
||||
.output = ip6_pkt_prohibit_out,
|
||||
},
|
||||
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
||||
.rt6i_protocol = RTPROT_KERNEL,
|
||||
|
|
@ -167,16 +163,14 @@ static struct rt6_info ip6_prohibit_entry_template = {
|
|||
};
|
||||
|
||||
static struct rt6_info ip6_blk_hole_entry_template = {
|
||||
.u = {
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -EINVAL,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = dst_discard,
|
||||
.output = dst_discard,
|
||||
}
|
||||
.dst = {
|
||||
.__refcnt = ATOMIC_INIT(1),
|
||||
.__use = 1,
|
||||
.obsolete = -1,
|
||||
.error = -EINVAL,
|
||||
.metrics = { [RTAX_HOPLIMIT - 1] = 255, },
|
||||
.input = dst_discard,
|
||||
.output = dst_discard,
|
||||
},
|
||||
.rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
|
||||
.rt6i_protocol = RTPROT_KERNEL,
|
||||
|
|
@ -249,7 +243,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
|
|||
if (!oif && ipv6_addr_any(saddr))
|
||||
goto out;
|
||||
|
||||
for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
|
||||
for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) {
|
||||
struct net_device *dev = sprt->rt6i_dev;
|
||||
|
||||
if (oif) {
|
||||
|
|
@ -407,10 +401,10 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
|
|||
|
||||
match = NULL;
|
||||
for (rt = rr_head; rt && rt->rt6i_metric == metric;
|
||||
rt = rt->u.dst.rt6_next)
|
||||
rt = rt->dst.rt6_next)
|
||||
match = find_match(rt, oif, strict, &mpri, match);
|
||||
for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric;
|
||||
rt = rt->u.dst.rt6_next)
|
||||
rt = rt->dst.rt6_next)
|
||||
match = find_match(rt, oif, strict, &mpri, match);
|
||||
|
||||
return match;
|
||||
|
|
@ -432,7 +426,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
|
|||
|
||||
if (!match &&
|
||||
(strict & RT6_LOOKUP_F_REACHABLE)) {
|
||||
struct rt6_info *next = rt0->u.dst.rt6_next;
|
||||
struct rt6_info *next = rt0->dst.rt6_next;
|
||||
|
||||
/* no entries matched; do round-robin */
|
||||
if (!next || next->rt6i_metric != rt0->rt6i_metric)
|
||||
|
|
@ -517,7 +511,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
|
|||
rt->rt6i_expires = jiffies + HZ * lifetime;
|
||||
rt->rt6i_flags |= RTF_EXPIRES;
|
||||
}
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -555,7 +549,7 @@ restart:
|
|||
rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
|
||||
BACKTRACK(net, &fl->fl6_src);
|
||||
out:
|
||||
dst_use(&rt->u.dst, jiffies);
|
||||
dst_use(&rt->dst, jiffies);
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
return rt;
|
||||
|
||||
|
|
@ -643,7 +637,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
|
|||
ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
|
||||
rt->rt6i_dst.plen = 128;
|
||||
rt->rt6i_flags |= RTF_CACHE;
|
||||
rt->u.dst.flags |= DST_HOST;
|
||||
rt->dst.flags |= DST_HOST;
|
||||
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
if (rt->rt6i_src.plen && saddr) {
|
||||
|
|
@ -677,7 +671,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad
|
|||
if (net_ratelimit())
|
||||
printk(KERN_WARNING
|
||||
"Neighbour table overflow.\n");
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
return NULL;
|
||||
}
|
||||
rt->rt6i_nexthop = neigh;
|
||||
|
|
@ -694,7 +688,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
|
|||
ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
|
||||
rt->rt6i_dst.plen = 128;
|
||||
rt->rt6i_flags |= RTF_CACHE;
|
||||
rt->u.dst.flags |= DST_HOST;
|
||||
rt->dst.flags |= DST_HOST;
|
||||
rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
|
||||
}
|
||||
return rt;
|
||||
|
|
@ -726,7 +720,7 @@ restart:
|
|||
rt->rt6i_flags & RTF_CACHE)
|
||||
goto out;
|
||||
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
|
||||
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
|
||||
|
|
@ -739,10 +733,10 @@ restart:
|
|||
#endif
|
||||
}
|
||||
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
rt = nrt ? : net->ipv6.ip6_null_entry;
|
||||
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
if (nrt) {
|
||||
err = ip6_ins_rt(nrt);
|
||||
if (!err)
|
||||
|
|
@ -756,7 +750,7 @@ restart:
|
|||
* Race condition! In the gap, when table->tb6_lock was
|
||||
* released someone could insert this route. Relookup.
|
||||
*/
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
goto relookup;
|
||||
|
||||
out:
|
||||
|
|
@ -764,11 +758,11 @@ out:
|
|||
reachable = 0;
|
||||
goto restart_2;
|
||||
}
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
out2:
|
||||
rt->u.dst.lastuse = jiffies;
|
||||
rt->u.dst.__use++;
|
||||
rt->dst.lastuse = jiffies;
|
||||
rt->dst.__use++;
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
|
@ -835,15 +829,15 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
|
|||
struct dst_entry *new = NULL;
|
||||
|
||||
if (rt) {
|
||||
new = &rt->u.dst;
|
||||
new = &rt->dst;
|
||||
|
||||
atomic_set(&new->__refcnt, 1);
|
||||
new->__use = 1;
|
||||
new->input = dst_discard;
|
||||
new->output = dst_discard;
|
||||
|
||||
memcpy(new->metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
|
||||
new->dev = ort->u.dst.dev;
|
||||
memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
|
||||
new->dev = ort->dst.dev;
|
||||
if (new->dev)
|
||||
dev_hold(new->dev);
|
||||
rt->rt6i_idev = ort->rt6i_idev;
|
||||
|
|
@ -912,7 +906,7 @@ static void ip6_link_failure(struct sk_buff *skb)
|
|||
rt = (struct rt6_info *) skb_dst(skb);
|
||||
if (rt) {
|
||||
if (rt->rt6i_flags&RTF_CACHE) {
|
||||
dst_set_expires(&rt->u.dst, 0);
|
||||
dst_set_expires(&rt->dst, 0);
|
||||
rt->rt6i_flags |= RTF_EXPIRES;
|
||||
} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
|
||||
rt->rt6i_node->fn_sernum = -1;
|
||||
|
|
@ -986,14 +980,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
|
|||
rt->rt6i_dev = dev;
|
||||
rt->rt6i_idev = idev;
|
||||
rt->rt6i_nexthop = neigh;
|
||||
atomic_set(&rt->u.dst.__refcnt, 1);
|
||||
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = 255;
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
|
||||
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
|
||||
rt->u.dst.output = ip6_output;
|
||||
atomic_set(&rt->dst.__refcnt, 1);
|
||||
rt->dst.metrics[RTAX_HOPLIMIT-1] = 255;
|
||||
rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
|
||||
rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
|
||||
rt->dst.output = ip6_output;
|
||||
|
||||
#if 0 /* there's no chance to use these for ndisc */
|
||||
rt->u.dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
|
||||
rt->dst.flags = ipv6_addr_type(addr) & IPV6_ADDR_UNICAST
|
||||
? DST_HOST
|
||||
: 0;
|
||||
ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
|
||||
|
|
@ -1001,14 +995,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
|
|||
#endif
|
||||
|
||||
spin_lock_bh(&icmp6_dst_lock);
|
||||
rt->u.dst.next = icmp6_dst_gc_list;
|
||||
icmp6_dst_gc_list = &rt->u.dst;
|
||||
rt->dst.next = icmp6_dst_gc_list;
|
||||
icmp6_dst_gc_list = &rt->dst;
|
||||
spin_unlock_bh(&icmp6_dst_lock);
|
||||
|
||||
fib6_force_start_gc(net);
|
||||
|
||||
out:
|
||||
return &rt->u.dst;
|
||||
return &rt->dst;
|
||||
}
|
||||
|
||||
int icmp6_dst_gc(void)
|
||||
|
|
@ -1090,11 +1084,11 @@ static int ipv6_get_mtu(struct net_device *dev)
|
|||
int mtu = IPV6_MIN_MTU;
|
||||
struct inet6_dev *idev;
|
||||
|
||||
idev = in6_dev_get(dev);
|
||||
if (idev) {
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev)
|
||||
mtu = idev->cnf.mtu6;
|
||||
in6_dev_put(idev);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return mtu;
|
||||
}
|
||||
|
||||
|
|
@ -1103,12 +1097,15 @@ int ip6_dst_hoplimit(struct dst_entry *dst)
|
|||
int hoplimit = dst_metric(dst, RTAX_HOPLIMIT);
|
||||
if (hoplimit < 0) {
|
||||
struct net_device *dev = dst->dev;
|
||||
struct inet6_dev *idev = in6_dev_get(dev);
|
||||
if (idev) {
|
||||
struct inet6_dev *idev;
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev)
|
||||
hoplimit = idev->cnf.hop_limit;
|
||||
in6_dev_put(idev);
|
||||
} else
|
||||
else
|
||||
hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
|
||||
rcu_read_unlock();
|
||||
}
|
||||
return hoplimit;
|
||||
}
|
||||
|
|
@ -1159,7 +1156,7 @@ int ip6_route_add(struct fib6_config *cfg)
|
|||
goto out;
|
||||
}
|
||||
|
||||
rt->u.dst.obsolete = -1;
|
||||
rt->dst.obsolete = -1;
|
||||
rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ?
|
||||
jiffies + clock_t_to_jiffies(cfg->fc_expires) :
|
||||
0;
|
||||
|
|
@ -1171,16 +1168,16 @@ int ip6_route_add(struct fib6_config *cfg)
|
|||
addr_type = ipv6_addr_type(&cfg->fc_dst);
|
||||
|
||||
if (addr_type & IPV6_ADDR_MULTICAST)
|
||||
rt->u.dst.input = ip6_mc_input;
|
||||
rt->dst.input = ip6_mc_input;
|
||||
else
|
||||
rt->u.dst.input = ip6_forward;
|
||||
rt->dst.input = ip6_forward;
|
||||
|
||||
rt->u.dst.output = ip6_output;
|
||||
rt->dst.output = ip6_output;
|
||||
|
||||
ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
|
||||
rt->rt6i_dst.plen = cfg->fc_dst_len;
|
||||
if (rt->rt6i_dst.plen == 128)
|
||||
rt->u.dst.flags = DST_HOST;
|
||||
rt->dst.flags = DST_HOST;
|
||||
|
||||
#ifdef CONFIG_IPV6_SUBTREES
|
||||
ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
||||
|
|
@ -1208,9 +1205,9 @@ int ip6_route_add(struct fib6_config *cfg)
|
|||
goto out;
|
||||
}
|
||||
}
|
||||
rt->u.dst.output = ip6_pkt_discard_out;
|
||||
rt->u.dst.input = ip6_pkt_discard;
|
||||
rt->u.dst.error = -ENETUNREACH;
|
||||
rt->dst.output = ip6_pkt_discard_out;
|
||||
rt->dst.input = ip6_pkt_discard;
|
||||
rt->dst.error = -ENETUNREACH;
|
||||
rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
|
||||
goto install_route;
|
||||
}
|
||||
|
|
@ -1244,7 +1241,7 @@ int ip6_route_add(struct fib6_config *cfg)
|
|||
goto out;
|
||||
if (dev) {
|
||||
if (dev != grt->rt6i_dev) {
|
||||
dst_release(&grt->u.dst);
|
||||
dst_release(&grt->dst);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1255,7 +1252,7 @@ int ip6_route_add(struct fib6_config *cfg)
|
|||
}
|
||||
if (!(grt->rt6i_flags&RTF_GATEWAY))
|
||||
err = 0;
|
||||
dst_release(&grt->u.dst);
|
||||
dst_release(&grt->dst);
|
||||
|
||||
if (err)
|
||||
goto out;
|
||||
|
|
@ -1294,18 +1291,18 @@ install_route:
|
|||
goto out;
|
||||
}
|
||||
|
||||
rt->u.dst.metrics[type - 1] = nla_get_u32(nla);
|
||||
rt->dst.metrics[type - 1] = nla_get_u32(nla);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
|
||||
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
|
||||
if (!dst_mtu(&rt->u.dst))
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
|
||||
if (!dst_metric(&rt->u.dst, RTAX_ADVMSS))
|
||||
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
|
||||
rt->u.dst.dev = dev;
|
||||
if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0)
|
||||
rt->dst.metrics[RTAX_HOPLIMIT-1] = -1;
|
||||
if (!dst_mtu(&rt->dst))
|
||||
rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
|
||||
if (!dst_metric(&rt->dst, RTAX_ADVMSS))
|
||||
rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
|
||||
rt->dst.dev = dev;
|
||||
rt->rt6i_idev = idev;
|
||||
rt->rt6i_table = table;
|
||||
|
||||
|
|
@ -1319,7 +1316,7 @@ out:
|
|||
if (idev)
|
||||
in6_dev_put(idev);
|
||||
if (rt)
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -1336,7 +1333,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
|
|||
write_lock_bh(&table->tb6_lock);
|
||||
|
||||
err = fib6_del(rt, info);
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
|
||||
write_unlock_bh(&table->tb6_lock);
|
||||
|
||||
|
|
@ -1369,7 +1366,7 @@ static int ip6_route_del(struct fib6_config *cfg)
|
|||
&cfg->fc_src, cfg->fc_src_len);
|
||||
|
||||
if (fn) {
|
||||
for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
|
||||
if (cfg->fc_ifindex &&
|
||||
(rt->rt6i_dev == NULL ||
|
||||
rt->rt6i_dev->ifindex != cfg->fc_ifindex))
|
||||
|
|
@ -1379,7 +1376,7 @@ static int ip6_route_del(struct fib6_config *cfg)
|
|||
continue;
|
||||
if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
|
||||
continue;
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
|
||||
return __ip6_del_rt(rt, &cfg->fc_nlinfo);
|
||||
|
|
@ -1421,7 +1418,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
|
|||
read_lock_bh(&table->tb6_lock);
|
||||
fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
|
||||
restart:
|
||||
for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
|
||||
/*
|
||||
* Current route is on-link; redirect is always invalid.
|
||||
*
|
||||
|
|
@ -1445,7 +1442,7 @@ restart:
|
|||
rt = net->ipv6.ip6_null_entry;
|
||||
BACKTRACK(net, &fl->fl6_src);
|
||||
out:
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
|
||||
|
|
@ -1513,10 +1510,10 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
|
|||
* Look, redirects are sent only in response to data packets,
|
||||
* so that this nexthop apparently is reachable. --ANK
|
||||
*/
|
||||
dst_confirm(&rt->u.dst);
|
||||
dst_confirm(&rt->dst);
|
||||
|
||||
/* Duplicate redirect: silently ignore. */
|
||||
if (neigh == rt->u.dst.neighbour)
|
||||
if (neigh == rt->dst.neighbour)
|
||||
goto out;
|
||||
|
||||
nrt = ip6_rt_copy(rt);
|
||||
|
|
@ -1529,20 +1526,20 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
|
|||
|
||||
ipv6_addr_copy(&nrt->rt6i_dst.addr, dest);
|
||||
nrt->rt6i_dst.plen = 128;
|
||||
nrt->u.dst.flags |= DST_HOST;
|
||||
nrt->dst.flags |= DST_HOST;
|
||||
|
||||
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
|
||||
nrt->rt6i_nexthop = neigh_clone(neigh);
|
||||
/* Reset pmtu, it may be better */
|
||||
nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
|
||||
nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev),
|
||||
dst_mtu(&nrt->u.dst));
|
||||
nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
|
||||
nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev),
|
||||
dst_mtu(&nrt->dst));
|
||||
|
||||
if (ip6_ins_rt(nrt))
|
||||
goto out;
|
||||
|
||||
netevent.old = &rt->u.dst;
|
||||
netevent.new = &nrt->u.dst;
|
||||
netevent.old = &rt->dst;
|
||||
netevent.new = &nrt->dst;
|
||||
call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
|
||||
|
||||
if (rt->rt6i_flags&RTF_CACHE) {
|
||||
|
|
@ -1551,7 +1548,7 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src,
|
|||
}
|
||||
|
||||
out:
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1570,7 +1567,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
|
|||
if (rt == NULL)
|
||||
return;
|
||||
|
||||
if (pmtu >= dst_mtu(&rt->u.dst))
|
||||
if (pmtu >= dst_mtu(&rt->dst))
|
||||
goto out;
|
||||
|
||||
if (pmtu < IPV6_MIN_MTU) {
|
||||
|
|
@ -1588,7 +1585,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
|
|||
They are sent only in response to data packets,
|
||||
so that this nexthop apparently is reachable. --ANK
|
||||
*/
|
||||
dst_confirm(&rt->u.dst);
|
||||
dst_confirm(&rt->dst);
|
||||
|
||||
/* Host route. If it is static, it would be better
|
||||
not to override it, but add new one, so that
|
||||
|
|
@ -1596,10 +1593,10 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
|
|||
would return automatically.
|
||||
*/
|
||||
if (rt->rt6i_flags & RTF_CACHE) {
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
|
||||
rt->dst.metrics[RTAX_MTU-1] = pmtu;
|
||||
if (allfrag)
|
||||
rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
|
||||
dst_set_expires(&rt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
|
||||
dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -1615,9 +1612,9 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
|
|||
nrt = rt6_alloc_clone(rt, daddr);
|
||||
|
||||
if (nrt) {
|
||||
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
|
||||
nrt->dst.metrics[RTAX_MTU-1] = pmtu;
|
||||
if (allfrag)
|
||||
nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
|
||||
nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
|
||||
|
||||
/* According to RFC 1981, detecting PMTU increase shouldn't be
|
||||
* happened within 5 mins, the recommended timer is 10 mins.
|
||||
|
|
@ -1625,13 +1622,13 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
|
|||
* which is 10 mins. After 10 mins the decreased pmtu is expired
|
||||
* and detecting PMTU increase will be automatically happened.
|
||||
*/
|
||||
dst_set_expires(&nrt->u.dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
|
||||
nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
|
||||
|
||||
ip6_ins_rt(nrt);
|
||||
}
|
||||
out:
|
||||
dst_release(&rt->u.dst);
|
||||
dst_release(&rt->dst);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1644,18 +1641,18 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
|
|||
struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops);
|
||||
|
||||
if (rt) {
|
||||
rt->u.dst.input = ort->u.dst.input;
|
||||
rt->u.dst.output = ort->u.dst.output;
|
||||
rt->dst.input = ort->dst.input;
|
||||
rt->dst.output = ort->dst.output;
|
||||
|
||||
memcpy(rt->u.dst.metrics, ort->u.dst.metrics, RTAX_MAX*sizeof(u32));
|
||||
rt->u.dst.error = ort->u.dst.error;
|
||||
rt->u.dst.dev = ort->u.dst.dev;
|
||||
if (rt->u.dst.dev)
|
||||
dev_hold(rt->u.dst.dev);
|
||||
memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32));
|
||||
rt->dst.error = ort->dst.error;
|
||||
rt->dst.dev = ort->dst.dev;
|
||||
if (rt->dst.dev)
|
||||
dev_hold(rt->dst.dev);
|
||||
rt->rt6i_idev = ort->rt6i_idev;
|
||||
if (rt->rt6i_idev)
|
||||
in6_dev_hold(rt->rt6i_idev);
|
||||
rt->u.dst.lastuse = jiffies;
|
||||
rt->dst.lastuse = jiffies;
|
||||
rt->rt6i_expires = 0;
|
||||
|
||||
ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
|
||||
|
|
@ -1689,14 +1686,14 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
|
|||
if (!fn)
|
||||
goto out;
|
||||
|
||||
for (rt = fn->leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
|
||||
if (rt->rt6i_dev->ifindex != ifindex)
|
||||
continue;
|
||||
if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
|
||||
continue;
|
||||
if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr))
|
||||
continue;
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
|
|
@ -1744,14 +1741,14 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d
|
|||
return NULL;
|
||||
|
||||
write_lock_bh(&table->tb6_lock);
|
||||
for (rt = table->tb6_root.leaf; rt; rt=rt->u.dst.rt6_next) {
|
||||
for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) {
|
||||
if (dev == rt->rt6i_dev &&
|
||||
((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
|
||||
ipv6_addr_equal(&rt->rt6i_gateway, addr))
|
||||
break;
|
||||
}
|
||||
if (rt)
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
write_unlock_bh(&table->tb6_lock);
|
||||
return rt;
|
||||
}
|
||||
|
|
@ -1790,9 +1787,9 @@ void rt6_purge_dflt_routers(struct net *net)
|
|||
|
||||
restart:
|
||||
read_lock_bh(&table->tb6_lock);
|
||||
for (rt = table->tb6_root.leaf; rt; rt = rt->u.dst.rt6_next) {
|
||||
for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
|
||||
if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
|
||||
dst_hold(&rt->u.dst);
|
||||
dst_hold(&rt->dst);
|
||||
read_unlock_bh(&table->tb6_lock);
|
||||
ip6_del_rt(rt);
|
||||
goto restart;
|
||||
|
|
@ -1930,15 +1927,15 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
|
|||
dev_hold(net->loopback_dev);
|
||||
in6_dev_hold(idev);
|
||||
|
||||
rt->u.dst.flags = DST_HOST;
|
||||
rt->u.dst.input = ip6_input;
|
||||
rt->u.dst.output = ip6_output;
|
||||
rt->dst.flags = DST_HOST;
|
||||
rt->dst.input = ip6_input;
|
||||
rt->dst.output = ip6_output;
|
||||
rt->rt6i_dev = net->loopback_dev;
|
||||
rt->rt6i_idev = idev;
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
|
||||
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
|
||||
rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
|
||||
rt->u.dst.obsolete = -1;
|
||||
rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
|
||||
rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst));
|
||||
rt->dst.metrics[RTAX_HOPLIMIT-1] = -1;
|
||||
rt->dst.obsolete = -1;
|
||||
|
||||
rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
|
||||
if (anycast)
|
||||
|
|
@ -1947,7 +1944,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
|
|||
rt->rt6i_flags |= RTF_LOCAL;
|
||||
neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway);
|
||||
if (IS_ERR(neigh)) {
|
||||
dst_free(&rt->u.dst);
|
||||
dst_free(&rt->dst);
|
||||
|
||||
/* We are casting this because that is the return
|
||||
* value type. But an errno encoded pointer is the
|
||||
|
|
@ -1962,7 +1959,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
|
|||
rt->rt6i_dst.plen = 128;
|
||||
rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
|
||||
|
||||
atomic_set(&rt->u.dst.__refcnt, 1);
|
||||
atomic_set(&rt->dst.__refcnt, 1);
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
|
@ -2033,12 +2030,12 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
|
|||
PMTU discouvery.
|
||||
*/
|
||||
if (rt->rt6i_dev == arg->dev &&
|
||||
!dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
|
||||
(dst_mtu(&rt->u.dst) >= arg->mtu ||
|
||||
(dst_mtu(&rt->u.dst) < arg->mtu &&
|
||||
dst_mtu(&rt->u.dst) == idev->cnf.mtu6))) {
|
||||
rt->u.dst.metrics[RTAX_MTU-1] = arg->mtu;
|
||||
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
|
||||
!dst_metric_locked(&rt->dst, RTAX_MTU) &&
|
||||
(dst_mtu(&rt->dst) >= arg->mtu ||
|
||||
(dst_mtu(&rt->dst) < arg->mtu &&
|
||||
dst_mtu(&rt->dst) == idev->cnf.mtu6))) {
|
||||
rt->dst.metrics[RTAX_MTU-1] = arg->mtu;
|
||||
rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2252,20 +2249,20 @@ static int rt6_fill_node(struct net *net,
|
|||
#endif
|
||||
NLA_PUT_U32(skb, RTA_IIF, iif);
|
||||
} else if (dst) {
|
||||
struct inet6_dev *idev = ip6_dst_idev(&rt->u.dst);
|
||||
struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
|
||||
struct in6_addr saddr_buf;
|
||||
if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
|
||||
dst, 0, &saddr_buf) == 0)
|
||||
NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf);
|
||||
}
|
||||
|
||||
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
|
||||
if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rt->u.dst.neighbour)
|
||||
NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key);
|
||||
if (rt->dst.neighbour)
|
||||
NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key);
|
||||
|
||||
if (rt->u.dst.dev)
|
||||
if (rt->dst.dev)
|
||||
NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
|
||||
|
||||
NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric);
|
||||
|
|
@ -2277,8 +2274,8 @@ static int rt6_fill_node(struct net *net,
|
|||
else
|
||||
expires = INT_MAX;
|
||||
|
||||
if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0,
|
||||
expires, rt->u.dst.error) < 0)
|
||||
if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0,
|
||||
expires, rt->dst.error) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
return nlmsg_end(skb, nlh);
|
||||
|
|
@ -2364,7 +2361,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
|
|||
skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
|
||||
|
||||
rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl);
|
||||
skb_dst_set(skb, &rt->u.dst);
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
|
||||
err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
|
||||
RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
|
||||
|
|
@ -2416,12 +2413,12 @@ static int ip6_route_dev_notify(struct notifier_block *this,
|
|||
struct net *net = dev_net(dev);
|
||||
|
||||
if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
|
||||
net->ipv6.ip6_null_entry->u.dst.dev = dev;
|
||||
net->ipv6.ip6_null_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
net->ipv6.ip6_prohibit_entry->u.dst.dev = dev;
|
||||
net->ipv6.ip6_prohibit_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
|
||||
net->ipv6.ip6_blk_hole_entry->u.dst.dev = dev;
|
||||
net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
|
||||
net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -2464,8 +2461,8 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
|
|||
seq_puts(m, "00000000000000000000000000000000");
|
||||
}
|
||||
seq_printf(m, " %08x %08x %08x %08x %8s\n",
|
||||
rt->rt6i_metric, atomic_read(&rt->u.dst.__refcnt),
|
||||
rt->u.dst.__use, rt->rt6i_flags,
|
||||
rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
|
||||
rt->dst.__use, rt->rt6i_flags,
|
||||
rt->rt6i_dev ? rt->rt6i_dev->name : "");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2646,9 +2643,9 @@ static int __net_init ip6_route_net_init(struct net *net)
|
|||
GFP_KERNEL);
|
||||
if (!net->ipv6.ip6_null_entry)
|
||||
goto out_ip6_dst_ops;
|
||||
net->ipv6.ip6_null_entry->u.dst.path =
|
||||
net->ipv6.ip6_null_entry->dst.path =
|
||||
(struct dst_entry *)net->ipv6.ip6_null_entry;
|
||||
net->ipv6.ip6_null_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
|
||||
|
|
@ -2656,18 +2653,18 @@ static int __net_init ip6_route_net_init(struct net *net)
|
|||
GFP_KERNEL);
|
||||
if (!net->ipv6.ip6_prohibit_entry)
|
||||
goto out_ip6_null_entry;
|
||||
net->ipv6.ip6_prohibit_entry->u.dst.path =
|
||||
net->ipv6.ip6_prohibit_entry->dst.path =
|
||||
(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
|
||||
net->ipv6.ip6_prohibit_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
|
||||
net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
|
||||
sizeof(*net->ipv6.ip6_blk_hole_entry),
|
||||
GFP_KERNEL);
|
||||
if (!net->ipv6.ip6_blk_hole_entry)
|
||||
goto out_ip6_prohibit_entry;
|
||||
net->ipv6.ip6_blk_hole_entry->u.dst.path =
|
||||
net->ipv6.ip6_blk_hole_entry->dst.path =
|
||||
(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
|
||||
net->ipv6.ip6_blk_hole_entry->u.dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
|
||||
#endif
|
||||
|
||||
net->ipv6.sysctl.flush_delay = 0;
|
||||
|
|
@ -2742,12 +2739,12 @@ int __init ip6_route_init(void)
|
|||
/* Registering of the loopback is done before this portion of code,
|
||||
* the loopback reference in rt6_info will not be taken, do it
|
||||
* manually for init_net */
|
||||
init_net.ipv6.ip6_null_entry->u.dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
||||
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
|
||||
init_net.ipv6.ip6_prohibit_entry->u.dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
||||
init_net.ipv6.ip6_blk_hole_entry->u.dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
|
||||
init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
|
||||
#endif
|
||||
ret = fib6_init();
|
||||
|
|
|
|||
|
|
@ -249,8 +249,6 @@ failed:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(ipip6_prl_lock);
|
||||
|
||||
#define for_each_prl_rcu(start) \
|
||||
for (prl = rcu_dereference(start); \
|
||||
prl; \
|
||||
|
|
@ -340,7 +338,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
|
|||
if (a->addr == htonl(INADDR_ANY))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock(&ipip6_prl_lock);
|
||||
ASSERT_RTNL();
|
||||
|
||||
for (p = t->prl; p; p = p->next) {
|
||||
if (p->addr == a->addr) {
|
||||
|
|
@ -370,7 +368,6 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
|
|||
t->prl_count++;
|
||||
rcu_assign_pointer(t->prl, p);
|
||||
out:
|
||||
spin_unlock(&ipip6_prl_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -397,7 +394,7 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
|
|||
struct ip_tunnel_prl_entry *x, **p;
|
||||
int err = 0;
|
||||
|
||||
spin_lock(&ipip6_prl_lock);
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (a && a->addr != htonl(INADDR_ANY)) {
|
||||
for (p = &t->prl; *p; p = &(*p)->next) {
|
||||
|
|
@ -419,7 +416,6 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
|
|||
}
|
||||
}
|
||||
out:
|
||||
spin_unlock(&ipip6_prl_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -716,7 +712,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
|||
stats->tx_carrier_errors++;
|
||||
goto tx_error_icmp;
|
||||
}
|
||||
tdev = rt->u.dst.dev;
|
||||
tdev = rt->dst.dev;
|
||||
|
||||
if (tdev == dev) {
|
||||
ip_rt_put(rt);
|
||||
|
|
@ -725,7 +721,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
if (df) {
|
||||
mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr);
|
||||
mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
|
||||
|
||||
if (mtu < 68) {
|
||||
stats->collisions++;
|
||||
|
|
@ -784,7 +780,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
|
|||
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
|
||||
IPCB(skb)->flags = 0;
|
||||
skb_dst_drop(skb);
|
||||
skb_dst_set(skb, &rt->u.dst);
|
||||
skb_dst_set(skb, &rt->dst);
|
||||
|
||||
/*
|
||||
* Push down and install the IPIP header.
|
||||
|
|
@ -833,7 +829,7 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
|
|||
.proto = IPPROTO_IPV6 };
|
||||
struct rtable *rt;
|
||||
if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
|
||||
tdev = rt->u.dst.dev;
|
||||
tdev = rt->dst.dev;
|
||||
ip_rt_put(rt);
|
||||
}
|
||||
dev->flags |= IFF_POINTOPOINT;
|
||||
|
|
|
|||
|
|
@ -27,28 +27,17 @@ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
|
|||
#define COOKIEBITS 24 /* Upper bits store count */
|
||||
#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
|
||||
|
||||
/*
|
||||
* This table has to be sorted and terminated with (__u16)-1.
|
||||
* XXX generate a better table.
|
||||
* Unresolved Issues: HIPPI with a 64k MSS is not well supported.
|
||||
*
|
||||
* Taken directly from ipv4 implementation.
|
||||
* Should this list be modified for ipv6 use or is it close enough?
|
||||
* rfc 2460 8.3 suggests mss values 20 bytes less than ipv4 counterpart
|
||||
*/
|
||||
/* Table must be sorted. */
|
||||
static __u16 const msstab[] = {
|
||||
64 - 1,
|
||||
256 - 1,
|
||||
512 - 1,
|
||||
536 - 1,
|
||||
1024 - 1,
|
||||
1440 - 1,
|
||||
1460 - 1,
|
||||
4312 - 1,
|
||||
(__u16)-1
|
||||
64,
|
||||
512,
|
||||
536,
|
||||
1280 - 60,
|
||||
1480 - 60,
|
||||
1500 - 60,
|
||||
4460 - 60,
|
||||
9000 - 60,
|
||||
};
|
||||
/* The number doesn't include the -1 terminator */
|
||||
#define NUM_MSS (ARRAY_SIZE(msstab) - 1)
|
||||
|
||||
/*
|
||||
* This (misnamed) value is the age of syncookie which is permitted.
|
||||
|
|
@ -134,9 +123,11 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
|
|||
|
||||
tcp_synq_overflow(sk);
|
||||
|
||||
for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
|
||||
;
|
||||
*mssp = msstab[mssind] + 1;
|
||||
for (mssind = ARRAY_SIZE(msstab) - 1; mssind ; mssind--)
|
||||
if (mss >= msstab[mssind])
|
||||
break;
|
||||
|
||||
*mssp = msstab[mssind];
|
||||
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT);
|
||||
|
||||
|
|
@ -154,7 +145,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
|
|||
th->source, th->dest, seq,
|
||||
jiffies / (HZ * 60), COUNTER_TRIES);
|
||||
|
||||
return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
|
||||
return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
|
||||
}
|
||||
|
||||
struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
||||
|
|
@ -174,7 +165,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
|||
struct dst_entry *dst;
|
||||
__u8 rcv_wscale;
|
||||
|
||||
if (!sysctl_tcp_syncookies || !th->ack)
|
||||
if (!sysctl_tcp_syncookies || !th->ack || th->rst)
|
||||
goto out;
|
||||
|
||||
if (tcp_synq_no_recent_overflow(sk) ||
|
||||
|
|
@ -240,17 +231,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
|
|||
* me if there is a preferred way.
|
||||
*/
|
||||
{
|
||||
struct in6_addr *final_p = NULL, final;
|
||||
struct in6_addr *final_p, final;
|
||||
struct flowi fl;
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.proto = IPPROTO_TCP;
|
||||
ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
|
||||
if (np->opt && np->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, np->opt, &final);
|
||||
ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
|
||||
fl.oif = sk->sk_bound_dev_if;
|
||||
fl.mark = sk->sk_mark;
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct in6_addr *saddr = NULL, *final_p = NULL, final;
|
||||
struct in6_addr *saddr = NULL, *final_p, final;
|
||||
struct flowi fl;
|
||||
struct dst_entry *dst;
|
||||
int addr_type;
|
||||
|
|
@ -250,12 +250,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
|
|||
fl.fl_ip_dport = usin->sin6_port;
|
||||
fl.fl_ip_sport = inet->inet_sport;
|
||||
|
||||
if (np->opt && np->opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, np->opt, &final);
|
||||
|
||||
security_sk_classify_flow(sk, &fl);
|
||||
|
||||
|
|
@ -477,7 +472,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
|
|||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct sk_buff * skb;
|
||||
struct ipv6_txoptions *opt = NULL;
|
||||
struct in6_addr * final_p = NULL, final;
|
||||
struct in6_addr * final_p, final;
|
||||
struct flowi fl;
|
||||
struct dst_entry *dst;
|
||||
int err = -1;
|
||||
|
|
@ -494,12 +489,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
|
|||
security_req_classify_flow(req, &fl);
|
||||
|
||||
opt = np->opt;
|
||||
if (opt && opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, opt, &final);
|
||||
|
||||
err = ip6_dst_lookup(sk, &dst, &fl);
|
||||
if (err)
|
||||
|
|
@ -1167,7 +1157,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SYN_COOKIES
|
||||
if (!th->rst && !th->syn && th->ack)
|
||||
if (!th->syn)
|
||||
sk = cookie_v6_check(sk, skb);
|
||||
#endif
|
||||
return sk;
|
||||
|
|
@ -1392,18 +1382,13 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
|
|||
goto out_overflow;
|
||||
|
||||
if (dst == NULL) {
|
||||
struct in6_addr *final_p = NULL, final;
|
||||
struct in6_addr *final_p, final;
|
||||
struct flowi fl;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
fl.proto = IPPROTO_TCP;
|
||||
ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
|
||||
if (opt && opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
}
|
||||
final_p = fl6_update_dst(&fl, opt, &final);
|
||||
ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
|
||||
fl.oif = sk->sk_bound_dev_if;
|
||||
fl.mark = sk->sk_mark;
|
||||
|
|
|
|||
|
|
@ -466,11 +466,9 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|||
if (sk->sk_state != TCP_ESTABLISHED && !np->recverr)
|
||||
goto out;
|
||||
|
||||
if (np->recverr) {
|
||||
bh_lock_sock(sk);
|
||||
if (np->recverr)
|
||||
ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
|
||||
bh_unlock_sock(sk);
|
||||
}
|
||||
|
||||
sk->sk_err = err;
|
||||
sk->sk_error_report(sk);
|
||||
out:
|
||||
|
|
@ -929,7 +927,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
|
|||
struct inet_sock *inet = inet_sk(sk);
|
||||
struct ipv6_pinfo *np = inet6_sk(sk);
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
|
||||
struct in6_addr *daddr, *final_p = NULL, final;
|
||||
struct in6_addr *daddr, *final_p, final;
|
||||
struct ipv6_txoptions *opt = NULL;
|
||||
struct ip6_flowlabel *flowlabel = NULL;
|
||||
struct flowi fl;
|
||||
|
|
@ -1099,14 +1097,9 @@ do_udp_sendmsg:
|
|||
ipv6_addr_copy(&fl.fl6_src, &np->saddr);
|
||||
fl.fl_ip_sport = inet->inet_sport;
|
||||
|
||||
/* merge ip6_build_xmit from ip6_output */
|
||||
if (opt && opt->srcrt) {
|
||||
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
|
||||
ipv6_addr_copy(&final, &fl.fl6_dst);
|
||||
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
|
||||
final_p = &final;
|
||||
final_p = fl6_update_dst(&fl, opt, &final);
|
||||
if (final_p)
|
||||
connected = 0;
|
||||
}
|
||||
|
||||
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
|
||||
fl.oif = np->mcast_oif;
|
||||
|
|
|
|||
Loading…
Reference in a new issue