struct net_device *dev;
        char dev_name[IFNAMSIZ];
        const char *name;
-       void (*rx_hook)(struct netpoll *, int, char *, int);
+       void (*rx_skb_hook)(struct netpoll *np, int source, struct sk_buff *skb,
+                           int offset, int len);
 
        union inet_addr local_ip, remote_ip;
        bool ipv6;
        unsigned long rx_flags;
        spinlock_t rx_lock;
        struct semaphore dev_lock;
-       struct list_head rx_np; /* netpolls that registered an rx_hook */
+       struct list_head rx_np; /* netpolls that registered an rx_skb_hook */
 
        struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */
        struct sk_buff_head txq;
 
 
                        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);
 
                        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);
 
 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;
 
                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;
                        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 {
                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))
                        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
 
        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);