diff options
Diffstat (limited to 'net/ipv4/udp.c')
| -rw-r--r-- | net/ipv4/udp.c | 45 | 
1 files changed, 25 insertions, 20 deletions
| diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ef29df8648e4..ebfbccae62fd 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -231,10 +231,7 @@ static int udp_reuseport_add_sock(struct sock *sk, struct udp_hslot *hslot)  		}  	} -	/* Initial allocation may have already happened via setsockopt */ -	if (!rcu_access_pointer(sk->sk_reuseport_cb)) -		return reuseport_alloc(sk); -	return 0; +	return reuseport_alloc(sk);  }  /** @@ -1061,7 +1058,7 @@ back_from_confirm:  		/* ... which is an evident application bug. --ANK */  		release_sock(sk); -		net_dbg_ratelimited("cork app bug 2\n"); +		net_dbg_ratelimited("socket already corked\n");  		err = -EINVAL;  		goto out;  	} @@ -1144,7 +1141,7 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset,  	if (unlikely(!up->pending)) {  		release_sock(sk); -		net_dbg_ratelimited("udp cork app bug 3\n"); +		net_dbg_ratelimited("cork failed\n");  		return -EINVAL;  	} @@ -2221,9 +2218,10 @@ static struct sock *__udp4_lib_demux_lookup(struct net *net,  	return NULL;  } -void udp_v4_early_demux(struct sk_buff *skb) +int udp_v4_early_demux(struct sk_buff *skb)  {  	struct net *net = dev_net(skb->dev); +	struct in_device *in_dev = NULL;  	const struct iphdr *iph;  	const struct udphdr *uh;  	struct sock *sk = NULL; @@ -2234,25 +2232,21 @@ void udp_v4_early_demux(struct sk_buff *skb)  	/* validate the packet */  	if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct udphdr))) -		return; +		return 0;  	iph = ip_hdr(skb);  	uh = udp_hdr(skb); -	if (skb->pkt_type == PACKET_BROADCAST || -	    skb->pkt_type == PACKET_MULTICAST) { -		struct in_device *in_dev = __in_dev_get_rcu(skb->dev); +	if (skb->pkt_type == PACKET_MULTICAST) { +		in_dev = __in_dev_get_rcu(skb->dev);  		if (!in_dev) -			return; +			return 0; -		/* we are supposed to accept bcast packets */ -		if (skb->pkt_type == PACKET_MULTICAST) { -			ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, -					       iph->protocol); -			if (!ours) -				return; -		} +		ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr, +				       iph->protocol); +		if (!ours) +			return 0;  		sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,  						   uh->source, iph->saddr, @@ -2263,7 +2257,7 @@ void udp_v4_early_demux(struct sk_buff *skb)  	}  	if (!sk || !refcount_inc_not_zero(&sk->sk_refcnt)) -		return; +		return 0;  	skb->sk = sk;  	skb->destructor = sock_efree; @@ -2272,12 +2266,23 @@ void udp_v4_early_demux(struct sk_buff *skb)  	if (dst)  		dst = dst_check(dst, 0);  	if (dst) { +		u32 itag = 0; +  		/* set noref for now.  		 * any place which wants to hold dst has to call  		 * dst_hold_safe()  		 */  		skb_dst_set_noref(skb, dst); + +		/* for unconnected multicast sockets we need to validate +		 * the source on each packet +		 */ +		if (!inet_sk(sk)->inet_daddr && in_dev) +			return ip_mc_validate_source(skb, iph->daddr, +						     iph->saddr, iph->tos, +						     skb->dev, in_dev, &itag);  	} +	return 0;  }  int udp_rcv(struct sk_buff *skb) |