
tv at stonesoft
Jul 27, 2001, 11:36 AM
Post #1 of 7
(228 views)
Permalink
|
|
[PATCH] Netfilter hook for ARP
|
|
Hi. Here's a patch you might like, as there has been lots of talk about ARP filtering etc lately. The send hook is just before dev_queue_xmit(), and arp_rcv() is split in two, with the hook in between. Please include.. diff -Naur linux-2.4.6/include/linux/netfilter_arp.h linux/include/linux/netfilter_arp.h --- linux-2.4.6/include/linux/netfilter_arp.h Thu Jan 1 02:00:00 1970 +++ linux/include/linux/netfilter_arp.h Tue Jul 10 11:03:33 2001 @@ -0,0 +1,15 @@ +#ifndef __LINUX_ARP_NETFILTER_H +#define __LINUX_ARP_NETFILTER_H + +/* ARP-specific defines for netfilter. + * Copyright 2000 Stonesoft Corp. + * Licensed under the GNU General Public License. + */ + +#include <linux/netfilter.h> + +#define NF_ARP_IN 0 +#define NF_ARP_OUT 1 +#define NF_ARP_NUMHOOKS 2 + +#endif /*__LINUX_ARP_NETFILTER_H*/ diff -Naur linux-2.4.6/net/ipv4/arp.c linux/net/ipv4/arp.c --- linux-2.4.6/net/ipv4/arp.c Wed May 16 20:21:45 2001 +++ linux/net/ipv4/arp.c Tue Jul 10 11:04:16 2001 @@ -111,6 +111,8 @@ #include <asm/system.h> #include <asm/uaccess.h> +#include <linux/netfilter.h> +#include <linux/netfilter_arp.h> @@ -562,7 +564,8 @@ memcpy(arp_ptr, &dest_ip, 4); skb->dev = dev; - dev_queue_xmit(skb); + NF_HOOK(PF_UNSPEC, NF_ARP_OUT, skb, dev, NULL, + dev_queue_xmit); return; out: @@ -578,17 +581,16 @@ * Receive an arp request by the device layer. */ +static int arp_rcv2(struct sk_buff *skb); + int arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) { struct arphdr *arp = skb->nh.arph; unsigned char *arp_ptr= (unsigned char *)(arp+1); - 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 @@ -739,6 +741,42 @@ * and in the case of requests for us we add the requester to the arp * cache. */ + + if (in_dev) + in_dev_put(in_dev); + return NF_HOOK(PF_UNSPEC, NF_ARP_IN, skb, dev, NULL, + arp_rcv2); + + out: + if (in_dev) + in_dev_put(in_dev); + freeskb: + kfree_skb(skb); + out_of_mem: + return 0; +} + +int arp_rcv2(struct sk_buff *skb) { + int addr_type; + struct rtable *rt; + struct neighbour *n; + 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); + unsigned char *sha, *tha; + u32 sip, tip; + +/* + * Extract fields + */ + sha=arp_ptr; + arp_ptr += dev->addr_len; + memcpy(&sip, arp_ptr, 4); + arp_ptr += 4; + tha=arp_ptr; + arp_ptr += dev->addr_len; + memcpy(&tip, arp_ptr, 4); /* Special case: IPv4 duplicate address detection packet (RFC2131) */ if (sip == 0) { @@ -747,7 +785,7 @@ arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr); goto out; } - + if (arp->ar_op == __constant_htons(ARPOP_REQUEST) && ip_route_input(skb, tip, sip, 0, dev) == 0) { @@ -768,7 +806,8 @@ goto out; } else if (IN_DEV_FORWARD(in_dev)) { if ((rt->rt_flags&RTCF_DNAT) || - (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && + ((addr_type == RTN_UNICAST || addr_type == RTN_BLACKHOLE || addr_type == RTN_UNREACHABLE) + && rt->u.dst.dev != dev && (IN_DEV_PROXY_ARP(in_dev) || pneigh_lookup(&arp_tbl, &tip, dev, 0)))) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) @@ -828,9 +867,7 @@ out: if (in_dev) in_dev_put(in_dev); -freeskb: kfree_skb(skb); -out_of_mem: return 0; } -- tv@{{hq.yok.utu,havoc,gaeshido}.fi,{debian,wanderer}.org,stonesoft.com} double a,b=4,c;main(){for(;++a<2e6;c-=(b=-b)/a++);printf("%f\n",c);}
|