diff options
Diffstat (limited to 'net/ipv6')
| -rw-r--r-- | net/ipv6/addrconf.c | 59 | ||||
| -rw-r--r-- | net/ipv6/ip6_output.c | 15 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 4 | 
3 files changed, 50 insertions, 28 deletions
| diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f7a84a4acffc..faa47f9ea73a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3127,17 +3127,17 @@ static void add_v4_addrs(struct inet6_dev *idev)  		offset = sizeof(struct in6_addr) - 4;  	memcpy(&addr.s6_addr32[3], idev->dev->dev_addr + offset, 4); -	if (idev->dev->flags&IFF_POINTOPOINT) { +	if (!(idev->dev->flags & IFF_POINTOPOINT) && idev->dev->type == ARPHRD_SIT) { +		scope = IPV6_ADDR_COMPATv4; +		plen = 96; +		pflags |= RTF_NONEXTHOP; +	} else {  		if (idev->cnf.addr_gen_mode == IN6_ADDR_GEN_MODE_NONE)  			return;  		addr.s6_addr32[0] = htonl(0xfe800000);  		scope = IFA_LINK;  		plen = 64; -	} else { -		scope = IPV6_ADDR_COMPATv4; -		plen = 96; -		pflags |= RTF_NONEXTHOP;  	}  	if (addr.s6_addr32[3]) { @@ -3447,6 +3447,30 @@ static void addrconf_gre_config(struct net_device *dev)  }  #endif +static void addrconf_init_auto_addrs(struct net_device *dev) +{ +	switch (dev->type) { +#if IS_ENABLED(CONFIG_IPV6_SIT) +	case ARPHRD_SIT: +		addrconf_sit_config(dev); +		break; +#endif +#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE) +	case ARPHRD_IP6GRE: +	case ARPHRD_IPGRE: +		addrconf_gre_config(dev); +		break; +#endif +	case ARPHRD_LOOPBACK: +		init_loopback(dev); +		break; + +	default: +		addrconf_dev_config(dev); +		break; +	} +} +  static int fixup_permanent_addr(struct net *net,  				struct inet6_dev *idev,  				struct inet6_ifaddr *ifp) @@ -3615,26 +3639,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,  			run_pending = 1;  		} -		switch (dev->type) { -#if IS_ENABLED(CONFIG_IPV6_SIT) -		case ARPHRD_SIT: -			addrconf_sit_config(dev); -			break; -#endif -#if IS_ENABLED(CONFIG_NET_IPGRE) || IS_ENABLED(CONFIG_IPV6_GRE) -		case ARPHRD_IP6GRE: -		case ARPHRD_IPGRE: -			addrconf_gre_config(dev); -			break; -#endif -		case ARPHRD_LOOPBACK: -			init_loopback(dev); -			break; - -		default: -			addrconf_dev_config(dev); -			break; -		} +		addrconf_init_auto_addrs(dev);  		if (!IS_ERR_OR_NULL(idev)) {  			if (run_pending) @@ -6397,7 +6402,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,  			if (idev->cnf.addr_gen_mode != new_val) {  				idev->cnf.addr_gen_mode = new_val; -				addrconf_dev_config(idev->dev); +				addrconf_init_auto_addrs(idev->dev);  			}  		} else if (&net->ipv6.devconf_all->addr_gen_mode == ctl->data) {  			struct net_device *dev; @@ -6408,7 +6413,7 @@ static int addrconf_sysctl_addr_gen_mode(struct ctl_table *ctl, int write,  				if (idev &&  				    idev->cnf.addr_gen_mode != new_val) {  					idev->cnf.addr_gen_mode = new_val; -					addrconf_dev_config(idev->dev); +					addrconf_init_auto_addrs(idev->dev);  				}  			}  		} diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 60fd91bb5171..c314fdde0097 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -547,7 +547,20 @@ int ip6_forward(struct sk_buff *skb)  	    pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {  		int proxied = ip6_forward_proxy_check(skb);  		if (proxied > 0) { -			hdr->hop_limit--; +			/* It's tempting to decrease the hop limit +			 * here by 1, as we do at the end of the +			 * function too. +			 * +			 * But that would be incorrect, as proxying is +			 * not forwarding.  The ip6_input function +			 * will handle this packet locally, and it +			 * depends on the hop limit being unchanged. +			 * +			 * One example is the NDP hop limit, that +			 * always has to stay 255, but other would be +			 * similar checks around RA packets, where the +			 * user can even change the desired limit. +			 */  			return ip6_input(skb);  		} else if (proxied < 0) {  			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index a06a9f847db5..ada087b50541 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -505,6 +505,7 @@ csum_copy_err:  static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,  				     struct raw6_sock *rp)  { +	struct ipv6_txoptions *opt;  	struct sk_buff *skb;  	int err = 0;  	int offset; @@ -522,6 +523,9 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,  	offset = rp->offset;  	total_len = inet_sk(sk)->cork.base.length; +	opt = inet6_sk(sk)->cork.opt; +	total_len -= opt ? opt->opt_flen : 0; +  	if (offset >= total_len - 1) {  		err = -EINVAL;  		ip6_flush_pending_frames(sk); |