diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 9 | ||||
| -rw-r--r-- | net/ipv6/ip6_fib.c | 9 | ||||
| -rw-r--r-- | net/ipv6/mcast.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ndisc.c | 3 | ||||
| -rw-r--r-- | net/ipv6/netfilter/ip6_tables.c | 14 | ||||
| -rw-r--r-- | net/ipv6/route.c | 105 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 6 | 
7 files changed, 85 insertions, 63 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6a3bb6077e1..7d5cb975cc6 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -803,8 +803,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)  				ip6_del_rt(rt);  				rt = NULL;  			} else if (!(rt->rt6i_flags & RTF_EXPIRES)) { -				rt->dst.expires = expires; -				rt->rt6i_flags |= RTF_EXPIRES; +				rt6_set_expires(rt, expires);  			}  		}  		dst_release(&rt->dst); @@ -1887,11 +1886,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)  				rt = NULL;  			} else if (addrconf_finite_timeout(rt_expires)) {  				/* not infinity */ -				rt->dst.expires = jiffies + rt_expires; -				rt->rt6i_flags |= RTF_EXPIRES; +				rt6_set_expires(rt, jiffies + rt_expires);  			} else { -				rt->rt6i_flags &= ~RTF_EXPIRES; -				rt->dst.expires = 0; +				rt6_clean_expires(rt);  			}  		} else if (valid_lft) {  			clock_t expires = 0; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 5b27fbcae34..93717435013 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -673,11 +673,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,  					    &rt->rt6i_gateway)) {  				if (!(iter->rt6i_flags & RTF_EXPIRES))  					return -EEXIST; -				iter->dst.expires = rt->dst.expires; -				if (!(rt->rt6i_flags & RTF_EXPIRES)) { -					iter->rt6i_flags &= ~RTF_EXPIRES; -					iter->dst.expires = 0; -				} +				if (!(rt->rt6i_flags & RTF_EXPIRES)) +					rt6_clean_expires(iter); +				else +					rt6_set_expires(iter, rt->dst.expires);  				return -EEXIST;  			}  		} diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 16c33e30812..b2869cab209 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2044,7 +2044,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,  		if (!delta)  			pmc->mca_sfcount[sfmode]--;  		for (j=0; j<i; j++) -			(void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]); +			ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);  	} else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {  		struct ip6_sf_list *psf; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3dcdb81ec3e..176b469322a 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1264,8 +1264,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)  	}  	if (rt) -		rt->dst.expires = jiffies + (HZ * lifetime); - +		rt6_set_expires(rt, jiffies + (HZ * lifetime));  	if (ra_msg->icmph.icmp6_hop_limit) {  		in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;  		if (rt) diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 94874b0bdcd..9d4e1555931 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -78,19 +78,6 @@ EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);     Hence the start of any table is given by get_table() below.  */ -/* Check for an extension */ -int -ip6t_ext_hdr(u8 nexthdr) -{ -	return  (nexthdr == IPPROTO_HOPOPTS)   || -		(nexthdr == IPPROTO_ROUTING)   || -		(nexthdr == IPPROTO_FRAGMENT)  || -		(nexthdr == IPPROTO_ESP)       || -		(nexthdr == IPPROTO_AH)        || -		(nexthdr == IPPROTO_NONE)      || -		(nexthdr == IPPROTO_DSTOPTS); -} -  /* Returns whether matches rule or not. */  /* Performance critical - called for every packet */  static inline bool @@ -2366,7 +2353,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,  EXPORT_SYMBOL(ip6t_register_table);  EXPORT_SYMBOL(ip6t_unregister_table);  EXPORT_SYMBOL(ip6t_do_table); -EXPORT_SYMBOL(ip6t_ext_hdr);  EXPORT_SYMBOL(ipv6_find_hdr);  module_init(ip6_tables_init); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 496b62712fe..bc4888d902b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -62,7 +62,7 @@  #include <linux/sysctl.h>  #endif -static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, +static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,  				    const struct in6_addr *dest);  static struct dst_entry	*ip6_dst_check(struct dst_entry *dst, u32 cookie);  static unsigned int	 ip6_default_advmss(const struct dst_entry *dst); @@ -285,6 +285,10 @@ static void ip6_dst_destroy(struct dst_entry *dst)  		rt->rt6i_idev = NULL;  		in6_dev_put(idev);  	} + +	if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) +		dst_release(dst->from); +  	if (peer) {  		rt->rt6i_peer = NULL;  		inet_putpeer(peer); @@ -329,8 +333,17 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,  static __inline__ int rt6_check_expired(const struct rt6_info *rt)  { -	return (rt->rt6i_flags & RTF_EXPIRES) && -		time_after(jiffies, rt->dst.expires); +	struct rt6_info *ort = NULL; + +	if (rt->rt6i_flags & RTF_EXPIRES) { +		if (time_after(jiffies, rt->dst.expires)) +			return 1; +	} else if (rt->dst.from) { +		ort = (struct rt6_info *) rt->dst.from; +		return (ort->rt6i_flags & RTF_EXPIRES) && +			time_after(jiffies, ort->dst.expires); +	} +	return 0;  }  static inline int rt6_need_strict(const struct in6_addr *daddr) @@ -620,12 +633,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,  				 (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);  	if (rt) { -		if (!addrconf_finite_timeout(lifetime)) { -			rt->rt6i_flags &= ~RTF_EXPIRES; -		} else { -			rt->dst.expires = jiffies + HZ * lifetime; -			rt->rt6i_flags |= RTF_EXPIRES; -		} +		if (!addrconf_finite_timeout(lifetime)) +			rt6_clean_expires(rt); +		else +			rt6_set_expires(rt, jiffies + HZ * lifetime); +  		dst_release(&rt->dst);  	}  	return 0; @@ -730,7 +742,7 @@ int ip6_ins_rt(struct rt6_info *rt)  	return __ip6_ins_rt(rt, &info);  } -static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, +static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,  				      const struct in6_addr *daddr,  				      const struct in6_addr *saddr)  { @@ -881,6 +893,16 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *  	return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);  } +static struct dst_entry *ip6_route_input_lookup(struct net *net, +						struct net_device *dev, +						struct flowi6 *fl6, int flags) +{ +	if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG) +		flags |= RT6_LOOKUP_F_IFACE; + +	return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input); +} +  void ip6_route_input(struct sk_buff *skb)  {  	const struct ipv6hdr *iph = ipv6_hdr(skb); @@ -895,10 +917,7 @@ void ip6_route_input(struct sk_buff *skb)  		.flowi6_proto = iph->nexthdr,  	}; -	if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG) -		flags |= RT6_LOOKUP_F_IFACE; - -	skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input)); +	skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));  }  static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, @@ -947,10 +966,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori  		rt->rt6i_idev = ort->rt6i_idev;  		if (rt->rt6i_idev)  			in6_dev_hold(rt->rt6i_idev); -		rt->dst.expires = 0;  		rt->rt6i_gateway = ort->rt6i_gateway; -		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; +		rt->rt6i_flags = ort->rt6i_flags; +		rt6_clean_expires(rt);  		rt->rt6i_metric = 0;  		memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); @@ -1012,10 +1031,9 @@ 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->dst, 0); -			rt->rt6i_flags |= RTF_EXPIRES; -		} else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) +		if (rt->rt6i_flags & RTF_CACHE) +			rt6_update_expires(rt, 0); +		else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))  			rt->rt6i_node->fn_sernum = -1;  	}  } @@ -1282,9 +1300,12 @@ int ip6_route_add(struct fib6_config *cfg)  	}  	rt->dst.obsolete = -1; -	rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ? -				jiffies + clock_t_to_jiffies(cfg->fc_expires) : -				0; + +	if (cfg->fc_flags & RTF_EXPIRES) +		rt6_set_expires(rt, jiffies + +				clock_t_to_jiffies(cfg->fc_expires)); +	else +		rt6_clean_expires(rt);  	if (cfg->fc_protocol == RTPROT_UNSPEC)  		cfg->fc_protocol = RTPROT_BOOT; @@ -1729,8 +1750,8 @@ again:  			features |= RTAX_FEATURE_ALLFRAG;  			dst_metric_set(&rt->dst, RTAX_FEATURES, features);  		} -		dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); -		rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; +		rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); +		rt->rt6i_flags |= RTF_MODIFIED;  		goto out;  	} @@ -1758,9 +1779,8 @@ again:  		 * which is 10 mins. After 10 mins the decreased pmtu is expired  		 * and detecting PMTU increase will be automatically happened.  		 */ -		dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); -		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; - +		rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires); +		nrt->rt6i_flags |= RTF_DYNAMIC;  		ip6_ins_rt(nrt);  	}  out: @@ -1792,7 +1812,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad   *	Misc support functions   */ -static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, +static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,  				    const struct in6_addr *dest)  {  	struct net *net = dev_net(ort->dst.dev); @@ -1812,10 +1832,14 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,  		if (rt->rt6i_idev)  			in6_dev_hold(rt->rt6i_idev);  		rt->dst.lastuse = jiffies; -		rt->dst.expires = 0;  		rt->rt6i_gateway = ort->rt6i_gateway; -		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; +		rt->rt6i_flags = ort->rt6i_flags; +		if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == +		    (RTF_DEFAULT | RTF_ADDRCONF)) +			rt6_set_from(rt, ort); +		else +			rt6_clean_expires(rt);  		rt->rt6i_metric = 0;  #ifdef CONFIG_IPV6_SUBTREES @@ -2537,7 +2561,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void  	struct sk_buff *skb;  	struct rtmsg *rtm;  	struct flowi6 fl6; -	int err, iif = 0; +	int err, iif = 0, oif = 0;  	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);  	if (err < 0) @@ -2564,15 +2588,29 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void  		iif = nla_get_u32(tb[RTA_IIF]);  	if (tb[RTA_OIF]) -		fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]); +		oif = nla_get_u32(tb[RTA_OIF]);  	if (iif) {  		struct net_device *dev; +		int flags = 0; +  		dev = __dev_get_by_index(net, iif);  		if (!dev) {  			err = -ENODEV;  			goto errout;  		} + +		fl6.flowi6_iif = iif; + +		if (!ipv6_addr_any(&fl6.saddr)) +			flags |= RT6_LOOKUP_F_HAS_SADDR; + +		rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6, +							       flags); +	} else { +		fl6.flowi6_oif = oif; + +		rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);  	}  	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); @@ -2587,7 +2625,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void  	skb_reset_mac_header(skb);  	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); -	rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6);  	skb_dst_set(skb, &rt->dst);  	err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 12c6ece67f3..98256cf72f9 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1383,6 +1383,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,  	tcp_mtup_init(newsk);  	tcp_sync_mss(newsk, dst_mtu(dst));  	newtp->advmss = dst_metric_advmss(dst); +	if (tcp_sk(sk)->rx_opt.user_mss && +	    tcp_sk(sk)->rx_opt.user_mss < newtp->advmss) +		newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; +  	tcp_initialize_rcv_mss(newsk);  	if (tcp_rsk(req)->snt_synack)  		tcp_valid_rtt_meas(newsk, @@ -1645,7 +1649,7 @@ process:  #ifdef CONFIG_NET_DMA  		struct tcp_sock *tp = tcp_sk(sk);  		if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) -			tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY); +			tp->ucopy.dma_chan = net_dma_find_channel();  		if (tp->ucopy.dma_chan)  			ret = tcp_v6_do_rcv(sk, skb);  		else  |