reply target
Grzegorz Borowiak <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <[email protected]> |
And now, for something completely different... It's... Patches for reply target for both kernel and userspace utility. This target allows instant reply for ARP requests, with arbitrary MAC addresss. You write: ebtables -t nat -A PREROUTING -p ARP --arp-ip-dst 192.168.1.2 \ -j reply --reply-mac 00:47:72:7a:65:73 and since now any ARP request "who-has 192.168.1.2" is replied with an ARP-reply frame "192.168.1.2 is-at 00:47:72:7a:65:73". The target returns EBT_DROP if this was an ARP-request frame or EBT_CONTINUE otherwise (i.e. if it was not an ARP-request frame, or if it was not even an ARP frame). Target should be placed in nat table of PREROUTING chain or in broute table of BROUTE chain. I have alpha-tested it. It's nice. Works for me. This target is useful for emulating non-existent hosts (along with redirect and snat targets) or for ARP-proxying, for example in VPNs. Coming soon: Two large targets for total snatting/dnatting IP and ARP frames by their src/dst IP addresses in opaque way. These target will carry a 256-entry table which will tell what IP address should be mapped onto what MAC address. This will be simply faster than inserting a sequence of rules with snat and dnat targets, because computational complexity of the former will be O(1) and for the latter is O(n), where n is the number of IP addresses to be natted. Thus, it will be useful in cases where we have to nat large number of different addresses and we have fast link and slow machine (like I have :-)). -- Grzesław
ebt-user-reply.patch
(text/plain, 3.8 KB)
diff -Naur ebtables-v2.0.5/extensions/ebt_reply.c ebtables-v2.0.5-with-reply/extensions/ebt_reply.c
--- ebtables-v2.0.5/extensions/ebt_reply.c 1970-01-01 01:00:00.000000000 +0100
+++ ebtables-v2.0.5-with-reply/extensions/ebt_reply.c 2003-08-07 19:39:59.000000000 +0200
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/ether.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_reply.h>
+
+static int mac_supplied;
+
+#define REPLY_MAC '2'
+static struct option opts[] =
+{
+ { "reply-mac" , required_argument, 0, REPLY_MAC },
+ { 0 }
+};
+
+static void print_help()
+{
+ printf(
+ "reply target options:\n"
+ " --reply-mac XX:XX:XX:XX:XX:XX : source MAC of generated reply\n");
+}
+
+static void init(struct ebt_entry_target *target)
+{
+ struct ebt_reply_info *replyinfo =
+ (struct ebt_reply_info *)target->data;
+
+ memset(replyinfo->mac, 0, ETH_ALEN);
+ mac_supplied = 0;
+}
+
+#define OPT_REPLY_MAC 0x01
+static int parse(int c, char **argv, int argc,
+ const struct ebt_u_entry *entry, unsigned int *flags,
+ struct ebt_entry_target **target)
+{
+ struct ebt_reply_info *replyinfo =
+ (struct ebt_reply_info *)(*target)->data;
+ struct ether_addr *addr;
+
+ switch (c) {
+ case REPLY_MAC:
+ if (!(addr = ether_aton(optarg)))
+ print_error("Problem with specified "
+ "--reply-mac mac");
+ memcpy(replyinfo->mac, addr, ETH_ALEN);
+ mac_supplied = 1;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+ const struct ebt_entry_target *target, const char *name,
+ unsigned int hookmask, unsigned int time)
+{
+ if (time == 0 && mac_supplied == 0)
+ print_error("No reply mac supplied");
+}
+
+static void print(const struct ebt_u_entry *entry,
+ const struct ebt_entry_target *target)
+{
+ struct ebt_reply_info *replyinfo =
+ (struct ebt_reply_info *)target->data;
+
+ printf("--reply-mac ");
+ printf("%s", ether_ntoa((struct ether_addr *)replyinfo->mac));
+}
+
+static int compare(const struct ebt_entry_target *t1,
+ const struct ebt_entry_target *t2)
+{
+ struct ebt_reply_info *replyinfo1 =
+ (struct ebt_reply_info *)t1->data;
+ struct ebt_reply_info *replyinfo2 =
+ (struct ebt_reply_info *)t2->data;
+
+ return memcmp(replyinfo1->mac, replyinfo2->mac, ETH_ALEN) == 0;
+}
+
+static struct ebt_u_target reply_target =
+{
+ EBT_REPLY_TARGET,
+ sizeof(struct ebt_reply_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_target(&reply_target);
+}
diff -Naur ebtables-v2.0.5/extensions/Makefile ebtables-v2.0.5-with-reply/extensions/Makefile
--- ebtables-v2.0.5/extensions/Makefile 2003-07-26 14:04:08.000000000 +0200
+++ ebtables-v2.0.5-with-reply/extensions/Makefile 2003-08-07 19:35:46.000000000 +0200
@@ -1,6 +1,7 @@
#! /usr/bin/make
EXT_FUNC+=802_3 nat arp ip standard log redirect vlan mark_m mark pkttype stp
+EXT_FUNC+=reply
EXT_TABLES+=filter nat broute
EXT_OBJS+=$(foreach T,$(EXT_FUNC), extensions/ebt_$(T).o)
EXT_OBJS+=$(foreach T,$(EXT_TABLES), extensions/ebtable_$(T).o)
diff -Naur ebtables-v2.0.5/include/linux/netfilter_bridge/ebt_reply.h ebtables-v2.0.5-with-reply/include/linux/netfilter_bridge/ebt_reply.h
--- ebtables-v2.0.5/include/linux/netfilter_bridge/ebt_reply.h 1970-01-01 01:00:00.000000000 +0100
+++ ebtables-v2.0.5-with-reply/include/linux/netfilter_bridge/ebt_reply.h 2003-08-07 20:40:00.000000000 +0200
@@ -0,0 +1,11 @@
+#ifndef __LINUX_BRIDGE_EBT_REPLY_H
+#define __LINUX_BRIDGE_EBT_REPLY_H
+
+struct ebt_reply_info
+{
+ unsigned char mac[ETH_ALEN];
+ char pad[2];
+};
+#define EBT_REPLY_TARGET "reply"
+
+#endif
ebt-kernel-reply.patch
(text/plain, 4.5 KB)
diff -Naur linux-2.4.21-ebt/include/linux/netfilter_bridge/ebt_reply.h linux-2.4.21-ebt-with-reply/include/linux/netfilter_bridge/ebt_reply.h
--- linux-2.4.21-ebt/include/linux/netfilter_bridge/ebt_reply.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.21-ebt-with-reply/include/linux/netfilter_bridge/ebt_reply.h 2003-08-07 20:55:07.000000000 +0200
@@ -0,0 +1,11 @@
+#ifndef __LINUX_BRIDGE_EBT_REPLY_H
+#define __LINUX_BRIDGE_EBT_REPLY_H
+
+struct ebt_reply_info
+{
+ unsigned char mac[ETH_ALEN];
+ char pad[2];
+};
+#define EBT_REPLY_TARGET "reply"
+
+#endif
diff -Naur linux-2.4.21-ebt/net/bridge/netfilter/Config.in linux-2.4.21-ebt-with-reply/net/bridge/netfilter/Config.in
--- linux-2.4.21-ebt/net/bridge/netfilter/Config.in 2003-08-07 20:51:03.000000000 +0200
+++ linux-2.4.21-ebt-with-reply/net/bridge/netfilter/Config.in 2003-08-07 20:54:29.000000000 +0200
@@ -17,3 +17,4 @@
dep_tristate ' ebt: dnat target support' CONFIG_BRIDGE_EBT_DNAT $CONFIG_BRIDGE_NF_EBTABLES
dep_tristate ' ebt: redirect target support' CONFIG_BRIDGE_EBT_REDIRECT $CONFIG_BRIDGE_NF_EBTABLES
dep_tristate ' ebt: mark target support' CONFIG_BRIDGE_EBT_MARK_T $CONFIG_BRIDGE_NF_EBTABLES
+dep_tristate ' ebt: reply target support (EXPERIMENTAL)' CONFIG_BRIDGE_EBT_REPLY $CONFIG_BRIDGE_NF_EBTABLES
diff -Naur linux-2.4.21-ebt/net/bridge/netfilter/ebt_reply.c linux-2.4.21-ebt-with-reply/net/bridge/netfilter/ebt_reply.c
--- linux-2.4.21-ebt/net/bridge/netfilter/ebt_reply.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.4.21-ebt-with-reply/net/bridge/netfilter/ebt_reply.c 2003-08-07 20:53:09.000000000 +0200
@@ -0,0 +1,95 @@
+/*
+ * ebt_reply
+ *
+ * Authors:
+ * Grzegorz Borowiak <[email protected]>
+ *
+ * August, 2003
+ *
+ */
+
+#include <linux/netfilter_bridge/ebtables.h>
+#include <linux/netfilter_bridge/ebt_reply.h>
+#include <linux/if_arp.h>
+#include <linux/module.h>
+
+static int ebt_target_reply(struct sk_buff **pskb, unsigned int hooknr,
+ const struct net_device *in, const struct net_device *out,
+ const void *data, unsigned int datalen)
+{
+ struct ebt_reply_info *info = (struct ebt_reply_info *)data;
+ struct ethhdr *e = (**pskb).mac.ethernet;
+
+ if (e->h_proto != __constant_htons(ETH_P_ARP))
+ return EBT_CONTINUE;
+ else {
+ struct arphdr *ah;
+ unsigned char *sha, *tha, *arp_ptr;
+ u32 sip, tip;
+ struct net_device *dev;
+
+ ah = (**pskb).nh.arph;
+ if (ah->ar_op != __constant_htons(ARPOP_REQUEST)) {
+ printk(KERN_WARNING "%d\n", ah->ar_op);
+ return EBT_CONTINUE;
+ }
+
+ dev = (**pskb).real_dev;
+ if (!dev) {
+ dev = (**pskb).dev;
+ }
+ if (!dev) {
+ printk(KERN_WARNING "ebt_reply: real_dev == NULL && dev == NULL\n");
+ return EBT_CONTINUE;
+ }
+
+ arp_ptr=(unsigned char *)(ah+1);
+
+ 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);
+
+ arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, info->mac, sha);
+
+ return EBT_DROP;
+ }
+}
+
+static int ebt_target_reply_check(const char *tablename, unsigned int hookmask,
+ const struct ebt_entry *e, void *data, unsigned int datalen)
+{
+ struct ebt_reply_info *info = (struct ebt_reply_info *)data;
+ CLEAR_BASE_CHAIN_BIT;
+ if ( (strcmp(tablename, "nat") ||
+ (hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) &&
+ (strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
+ return -EINVAL;
+ if (datalen != sizeof(struct ebt_reply_info))
+ return -EINVAL;
+ return 0;
+}
+
+static struct ebt_target reply_target =
+{
+ {NULL, NULL}, EBT_REPLY_TARGET, ebt_target_reply,
+ ebt_target_reply_check, NULL, THIS_MODULE
+};
+
+static int __init init(void)
+{
+ return ebt_register_target(&reply_target);
+}
+
+static void __exit fini(void)
+{
+ ebt_unregister_target(&reply_target);
+}
+
+module_init(init);
+module_exit(fini);
+EXPORT_NO_SYMBOLS;
+MODULE_LICENSE("GPL");
diff -Naur linux-2.4.21-ebt/net/bridge/netfilter/Makefile linux-2.4.21-ebt-with-reply/net/bridge/netfilter/Makefile
--- linux-2.4.21-ebt/net/bridge/netfilter/Makefile 2003-08-07 20:51:03.000000000 +0200
+++ linux-2.4.21-ebt-with-reply/net/bridge/netfilter/Makefile 2003-08-07 20:53:50.000000000 +0200
@@ -27,4 +27,5 @@
obj-$(CONFIG_BRIDGE_EBT_DNAT) += ebt_dnat.o
obj-$(CONFIG_BRIDGE_EBT_REDIRECT) += ebt_redirect.o
obj-$(CONFIG_BRIDGE_EBT_MARK_T) += ebt_mark.o
+obj-$(CONFIG_BRIDGE_EBT_REPLY) += ebt_reply.o
include $(TOPDIR)/Rules.make