diff options
Diffstat (limited to 'net/ipv6/exthdrs.c')
| -rw-r--r-- | net/ipv6/exthdrs.c | 34 | 
1 files changed, 28 insertions, 6 deletions
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 8a659f92d17..262f105d23b 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -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);  |