diff options
Diffstat (limited to 'net/ipv4/raw.c')
| -rw-r--r-- | net/ipv4/raw.c | 20 | 
1 files changed, 14 insertions, 6 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index aea89326c697..dcb11f22cbf2 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -175,6 +175,13 @@ static int raw_v4_input(struct net *net, struct sk_buff *skb,  		if (!raw_v4_match(net, sk, iph->protocol,  				  iph->saddr, iph->daddr, dif, sdif))  			continue; + +		if (atomic_read(&sk->sk_rmem_alloc) >= +		    READ_ONCE(sk->sk_rcvbuf)) { +			atomic_inc(&sk->sk_drops); +			continue; +		} +  		delivered = 1;  		if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) &&  		    ip_mc_sf_allow(sk, iph->daddr, iph->saddr, @@ -310,7 +317,7 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)  	}  	nf_reset_ct(skb); -	skb_push(skb, skb->data - skb_network_header(skb)); +	skb_push(skb, -skb_network_offset(skb));  	raw_rcv_skb(sk, skb);  	return 0; @@ -350,6 +357,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,  		goto error;  	skb_reserve(skb, hlen); +	skb->protocol = htons(ETH_P_IP);  	skb->priority = READ_ONCE(sk->sk_priority);  	skb->mark = sockc->mark;  	skb->tstamp = sockc->transmit_time; @@ -815,7 +823,7 @@ static int raw_geticmpfilter(struct sock *sk, char __user *optval, int __user *o  out:	return ret;  } -static int do_raw_setsockopt(struct sock *sk, int level, int optname, +static int do_raw_setsockopt(struct sock *sk, int optname,  			     sockptr_t optval, unsigned int optlen)  {  	if (optname == ICMP_FILTER) { @@ -832,11 +840,11 @@ static int raw_setsockopt(struct sock *sk, int level, int optname,  {  	if (level != SOL_RAW)  		return ip_setsockopt(sk, level, optname, optval, optlen); -	return do_raw_setsockopt(sk, level, optname, optval, optlen); +	return do_raw_setsockopt(sk, optname, optval, optlen);  } -static int do_raw_getsockopt(struct sock *sk, int level, int optname, -			  char __user *optval, int __user *optlen) +static int do_raw_getsockopt(struct sock *sk, int optname, +			     char __user *optval, int __user *optlen)  {  	if (optname == ICMP_FILTER) {  		if (inet_sk(sk)->inet_num != IPPROTO_ICMP) @@ -852,7 +860,7 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,  {  	if (level != SOL_RAW)  		return ip_getsockopt(sk, level, optname, optval, optlen); -	return do_raw_getsockopt(sk, level, optname, optval, optlen); +	return do_raw_getsockopt(sk, optname, optval, optlen);  }  static int raw_ioctl(struct sock *sk, int cmd, int *karg)  | 
