Thanks Harald, I have applied both your patches and I will push them to Marcelo and Linus.
I am also pushing the following change which is Rusty's ARP netfilter hooks with minor modifications by me. # This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.184 -> 1.186 # net/ipv4/arp.c 1.6 -> 1.8 # (new) -> 1.1 include/linux/netfilter_arp.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/03/14 [EMAIL PROTECTED] 1.185 # Allow ARP packets to be seen by netfilter. # -------------------------------------------- # 02/03/14 [EMAIL PROTECTED] 1.186 # Include linux/netfilter_arp.h # -------------------------------------------- # diff -Nru a/include/linux/netfilter_arp.h b/include/linux/netfilter_arp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/netfilter_arp.h Thu Mar 14 16:49:51 2002 @@ -0,0 +1,19 @@ +#ifndef __LINUX_ARP_NETFILTER_H +#define __LINUX_ARP_NETFILTER_H + +/* ARP-specific defines for netfilter. + * (C)2002 Rusty Russell IBM -- This code is GPL. + */ + +#include <linux/config.h> +#include <linux/netfilter.h> + +/* There is no PF_ARP. */ +#define NF_ARP 0 + +/* ARP Hooks */ +/* Coming in. */ +#define NF_ARP_IN 0 +#define NF_ARP_OUT 1 + +#endif /* __LINUX_ARP_NETFILTER_H */ diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c --- a/net/ipv4/arp.c Thu Mar 14 16:49:51 2002 +++ b/net/ipv4/arp.c Thu Mar 14 16:49:51 2002 @@ -112,7 +112,7 @@ #include <asm/system.h> #include <asm/uaccess.h> - +#include <linux/netfilter_arp.h> /* * Interface to generic neighbour cache. @@ -561,7 +561,8 @@ arp_ptr+=dev->addr_len; memcpy(arp_ptr, &dest_ip, 4); - dev_queue_xmit(skb); + /* Send it off, maybe filter it using firewalling first. */ + NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, dev, dev_queue_xmit); return; out: @@ -574,45 +575,31 @@ } /* - * Receive an arp request by the device layer. + * Process an arp request. */ -int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +int arp_process(struct sk_buff *skb) { - struct arphdr *arp = skb->nh.arph; - unsigned char *arp_ptr= (unsigned char *)(arp+1); + struct net_device *dev = skb->dev; + struct in_device *in_dev = in_dev_get(dev); + struct arphdr *arp; + unsigned char *arp_ptr; struct rtable *rt; unsigned char *sha, *tha; u32 sip, tip; u16 dev_type = dev->type; int addr_type; - struct in_device *in_dev = in_dev_get(dev); struct neighbour *n; -/* - * The hardware length of the packet should match the hardware length - * of the device. Similarly, the hardware types should match. The - * device should be ARP-able. Also, if pln is not 4, then the lookup - * is not from an IP number. We can't currently handle this, so toss - * it. - */ - if (in_dev == NULL || - arp->ar_hln != dev->addr_len || - dev->flags & IFF_NOARP || - skb->pkt_type == PACKET_OTHERHOST || - skb->pkt_type == PACKET_LOOPBACK || - arp->ar_pln != 4) + /* arp_rcv below verifies the ARP header, verifies the device + * is ARP'able, and linearizes the SKB (if needed). + */ + + if (in_dev == NULL) goto out; - if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) - goto out_of_mem; - - if (skb_is_nonlinear(skb)) { - if (skb_linearize(skb, GFP_ATOMIC) != 0) - goto freeskb; - arp = skb->nh.arph; - arp_ptr= (unsigned char *)(arp+1); - } + arp = skb->nh.arph; + arp_ptr= (unsigned char *)(arp+1); switch (dev_type) { default: @@ -827,13 +814,41 @@ out: if (in_dev) in_dev_put(in_dev); -freeskb: kfree_skb(skb); -out_of_mem: return 0; } +/* + * Receive an arp request from the device layer. + */ + +int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +{ + struct arphdr *arp = skb->nh.arph; + + if (arp->ar_hln != dev->addr_len || + dev->flags & IFF_NOARP || + skb->pkt_type == PACKET_OTHERHOST || + skb->pkt_type == PACKET_LOOPBACK || + arp->ar_pln != 4) + goto freeskb; + + if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) + goto out_of_mem; + + if (skb_is_nonlinear(skb)) { + if (skb_linearize(skb, GFP_ATOMIC) != 0) + goto freeskb; + } + + return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process); + +freeskb: + kfree_skb(skb); +out_of_mem: + return 0; +} /* * User level interface (ioctl, /proc)