[PATCH] Netfilter hook for ARP
Tommi Virtanen
tv-nospam-e2aac4@hq.yok.utu.fi
28 Jul 2001 09:48:21 +0300
--=-=-=
Brad Chapman <kakadu@earthlink.net> writes:
> Due to a buggy e-mail tool, a portion of your patch was cut off.
> Did your
Hmm, the copy I got from the list looks okay.
Reattaching as MIME.
> patch also include new shared library protocol extensions for
> iptables and/or ip6tables, so that we can actually manipulate
> traffic in these hooks? AFAIK, the current protocol matches won't
> work for this low-level thing. This looks mildly interesting, but
> without the new extensions, no one will be able to do anything with
> it.
Unfortunately I don't grok the userspace portion nearly as
well. Hopefully someone else will step up. The reason I posted
the patch was that someone mentioned he might be implementing
it; no need for double work.
--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=netfilter-arp-246.patch
Content-Description: Netfilter ARP hooks for Linux 2.4.6
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);}
--=-=-=--