diff options
Diffstat (limited to 'net/core/netpoll.c')
| -rw-r--r-- | net/core/netpoll.c | 42 | 
1 files changed, 23 insertions, 19 deletions
| diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2c637e9a0b27..8f971990677c 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -550,7 +550,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo  		return;  	proto = ntohs(eth_hdr(skb)->h_proto); -	if (proto == ETH_P_IP) { +	if (proto == ETH_P_ARP) {  		struct arphdr *arp;  		unsigned char *arp_ptr;  		/* No arp on this interface */ @@ -636,8 +636,9 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo  			netpoll_send_skb(np, send_skb); -			/* If there are several rx_hooks for the same address, -			   we're fine by sending a single reply */ +			/* If there are several rx_skb_hooks for the same +			 * address we're fine by sending a single reply +			 */  			break;  		}  		spin_unlock_irqrestore(&npinfo->rx_lock, flags); @@ -719,8 +720,9 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo  			netpoll_send_skb(np, send_skb); -			/* If there are several rx_hooks for the same address, -			   we're fine by sending a single reply */ +			/* If there are several rx_skb_hooks for the same +			 * address, we're fine by sending a single reply +			 */  			break;  		}  		spin_unlock_irqrestore(&npinfo->rx_lock, flags); @@ -756,11 +758,12 @@ static bool pkt_is_ns(struct sk_buff *skb)  int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  { -	int proto, len, ulen; -	int hits = 0; +	int proto, len, ulen, data_len; +	int hits = 0, offset;  	const struct iphdr *iph;  	struct udphdr *uh;  	struct netpoll *np, *tmp; +	uint16_t source;  	if (list_empty(&npinfo->rx_np))  		goto out; @@ -820,7 +823,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  		len -= iph->ihl*4;  		uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); +		offset = (unsigned char *)(uh + 1) - skb->data;  		ulen = ntohs(uh->len); +		data_len = skb->len - offset; +		source = ntohs(uh->source);  		if (ulen != len)  			goto out; @@ -834,9 +840,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  			if (np->local_port && np->local_port != ntohs(uh->dest))  				continue; -			np->rx_hook(np, ntohs(uh->source), -				       (char *)(uh+1), -				       ulen - sizeof(struct udphdr)); +			np->rx_skb_hook(np, source, skb, offset, data_len);  			hits++;  		}  	} else { @@ -859,7 +863,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  		if (!pskb_may_pull(skb, sizeof(struct udphdr)))  			goto out;  		uh = udp_hdr(skb); +		offset = (unsigned char *)(uh + 1) - skb->data;  		ulen = ntohs(uh->len); +		data_len = skb->len - offset; +		source = ntohs(uh->source);  		if (ulen != skb->len)  			goto out;  		if (udp6_csum_init(skb, uh, IPPROTO_UDP)) @@ -872,9 +879,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)  			if (np->local_port && np->local_port != ntohs(uh->dest))  				continue; -			np->rx_hook(np, ntohs(uh->source), -				       (char *)(uh+1), -				       ulen - sizeof(struct udphdr)); +			np->rx_skb_hook(np, source, skb, offset, data_len);  			hits++;  		}  #endif @@ -1062,7 +1067,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)  	npinfo->netpoll = np; -	if (np->rx_hook) { +	if (np->rx_skb_hook) {  		spin_lock_irqsave(&npinfo->rx_lock, flags);  		npinfo->rx_flags |= NETPOLL_RX_ENABLED;  		list_add_tail(&np->rx, &npinfo->rx_np); @@ -1284,15 +1289,14 @@ EXPORT_SYMBOL_GPL(__netpoll_free_async);  void netpoll_cleanup(struct netpoll *np)  { -	if (!np->dev) -		return; -  	rtnl_lock(); +	if (!np->dev) +		goto out;  	__netpoll_cleanup(np); -	rtnl_unlock(); -  	dev_put(np->dev);  	np->dev = NULL; +out: +	rtnl_unlock();  }  EXPORT_SYMBOL(netpoll_cleanup); |