Hi,

1.
IPv6 AH/ESP matches
  AH options:
 --ahspi [!] spi[:spi]         match spi (range)
 --ahlen [!] length            total length of this header
 --ahres                       check the reserved filed, too

 ESP option:
 --espspi [!] spi[:spi]        match spi (range)

Highly experimental, please test them, if You've got a lot of free time!
:)

2.
Extensions-HOWTO update for these matches
(And added a status filed to the ipv6 extensions)

3. 
The CVS still borken, somehow the library did not renamed with the match
( agr -> eui64)

Regards,

        kisza

-- 
    Andras Kis-Szabo       Security Development, Design and Audit
-------------------------/       Zorp, NetFilter and IPv6
 [EMAIL PROTECTED] /---------------------------------------------->
diff -urN netfilter/userspace.old/extensions/.ah-test6 netfilter/userspace/extensions/.ah-test6
--- netfilter/userspace.old/extensions/.ah-test6	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/.ah-test6	Wed Mar 20 22:52:13 2002
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_ah.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_ah.h ] && echo ah
diff -urN netfilter/userspace.old/extensions/.esp-test6 netfilter/userspace/extensions/.esp-test6
--- netfilter/userspace.old/extensions/.esp-test6	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/.esp-test6	Wed Mar 20 22:52:35 2002
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_esp.c -a -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_esp.h ] && echo esp
diff -urN netfilter/userspace.old/extensions/.eui64-test6 netfilter/userspace/extensions/.eui64-test6
--- netfilter/userspace.old/extensions/.eui64-test6	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/.eui64-test6	Thu Mar 21 00:35:34 2002
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -f $KERNEL_DIR/net/ipv6/netfilter/ip6t_eui64.c ] && echo eui64
diff -urN netfilter/userspace.old/extensions/libip6t_ah.c netfilter/userspace/extensions/libip6t_ah.c
--- netfilter/userspace.old/extensions/libip6t_ah.c	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/libip6t_ah.c	Thu Mar 21 21:46:16 2002
@@ -0,0 +1,238 @@
+/* Shared library add-on to ip6tables to add AH support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6t_ah.h>
+                                        
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"AH v%s options:\n"
+" --ahspi [!] spi[:spi]         match spi (range)\n"
+" --ahlen [!] length            total length of this header\n"
+" --ahres                       check the reserved filed, too\n",
+NETFILTER_VERSION);
+}
+
+static struct option opts[] = {
+	{ "ahspi", 1, 0, '1' },
+	{ "ahlen", 1, 0, '2' },
+	{ "ahres", 0, 0, '3' },
+	{0}
+};
+
+static u_int32_t
+parse_ah_spi(const char *spistr, const char *typestr)
+{
+	unsigned long int spi;
+	char* ep;
+
+	spi =  strtoul(spistr,&ep,0) ;
+
+	if ( spistr == ep ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "AH no valid digits in %s `%s'", typestr, spistr);
+	}
+	if ( spi == ULONG_MAX  && errno == ERANGE ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "%s `%s' specified too big: would overflow",
+			   typestr, spistr);
+	}	
+	if ( *spistr != '\0'  && *ep != '\0' ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "AH error parsing %s `%s'", typestr, spistr);
+	}
+	return (u_int32_t) spi;
+}
+
+static void
+parse_ah_spis(const char *spistring, u_int32_t *spis)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(spistring);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		spis[0] = spis[1] = parse_ah_spi(buffer,"spi");
+	else {
+		*cp = '\0';
+		cp++;
+
+		spis[0] = buffer[0] ? parse_ah_spi(buffer,"spi") : 0;
+		spis[1] = cp[0] ? parse_ah_spi(cp,"spi") : 0xFFFFFFFF;
+	}
+	free(buffer);
+}
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+	struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data;
+
+	ahinfo->spis[1] = 0xFFFFFFFF;
+	ahinfo->hdrlen = 0;
+	ahinfo->hdrres = 0;
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+	struct ip6t_ah *ahinfo = (struct ip6t_ah *)(*match)->data;
+
+	switch (c) {
+	case '1':
+		if (*flags & IP6T_AH_SPI)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--ahspi' allowed");
+		check_inverse(optarg, &invert, &optind, 0);
+		parse_ah_spis(argv[optind-1], ahinfo->spis);
+		if (invert)
+			ahinfo->invflags |= IP6T_AH_INV_SPI;
+		*flags |= IP6T_AH_SPI;
+		break;
+	case '2':
+		if (*flags & IP6T_AH_LEN)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--ahlen' allowed");
+		check_inverse(optarg, &invert, &optind, 0);
+		ahinfo->hdrlen = parse_ah_spi(argv[optind-1], "length");
+		if (invert)
+			ahinfo->invflags |= IP6T_AH_INV_LEN;
+		*flags |= IP6T_AH_LEN;
+		break;
+	case '3':
+		if (*flags & IP6T_AH_RES)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--ahres' allowed");
+		ahinfo->hdrres = 1;
+		*flags |= IP6T_AH_RES;
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Final check; we don't care. */
+static void
+final_check(unsigned int flags)
+{
+}
+
+static void
+print_spis(const char *name, u_int32_t min, u_int32_t max,
+	    int invert)
+{
+	const char *inv = invert ? "!" : "";
+
+	if (min != 0 || max != 0xFFFFFFFF || invert) {
+		printf("%s", name);
+		if (min == max) {
+			printf(":%s", inv);
+			printf("%u", min);
+		} else {
+			printf("s:%s", inv);
+			printf("%u",min);
+			printf(":");
+			printf("%u",max);
+		}
+		printf(" ");
+	}
+}
+
+static void
+print_len(const char *name, u_int32_t len, int invert)
+{
+	const char *inv = invert ? "!" : "";
+
+	if (len != 0 || invert) {
+		printf("%s", name);
+		printf(":%s", inv);
+		printf("%u", len);
+		printf(" ");
+	}
+}
+
+/* Prints out the union ip6t_matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match, int numeric)
+{
+	const struct ip6t_ah *ah = (struct ip6t_ah *)match->data;
+
+	printf("ah ");
+	print_spis("spi", ah->spis[0], ah->spis[1],
+		    ah->invflags & IP6T_AH_INV_SPI);
+	print_len("length", ah->hdrlen, 
+		    ah->invflags & IP6T_AH_INV_LEN);
+	if (ah->hdrres) printf("reserved ");
+	if (ah->invflags & ~IP6T_AH_INV_MASK)
+		printf("Unknown invflags: 0x%X ",
+		       ah->invflags & ~IP6T_AH_INV_MASK);
+}
+
+/* Saves the union ip6t_matchinfo in parsable form to stdout. */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+	const struct ip6t_ah *ahinfo = (struct ip6t_ah *)match->data;
+
+	if (!(ahinfo->spis[0] == 0
+	    && ahinfo->spis[1] == 0xFFFFFFFF)) {
+		printf("--ahspi %s", 
+			(ahinfo->invflags & IP6T_AH_INV_SPI) ? "! " : "");
+		if (ahinfo->spis[0]
+		    != ahinfo->spis[1])
+			printf("%u:%u ",
+			       ahinfo->spis[0],
+			       ahinfo->spis[1]);
+		else
+			printf("%u ",
+			       ahinfo->spis[0]);
+	}
+
+	if (ahinfo->hdrlen != 0 ) {
+		printf("--ahlen %s%u ", 
+			(ahinfo->invflags & IP6T_AH_INV_LEN) ? "! " : "", 
+			ahinfo->hdrlen);
+	}
+
+	if (ahinfo->hdrres != 0 ) {
+		printf("--ahres ");
+	}
+
+}
+
+static
+struct ip6tables_match ah
+= { NULL,
+    "ah",
+    NETFILTER_VERSION,
+    IP6T_ALIGN(sizeof(struct ip6t_ah)),
+    IP6T_ALIGN(sizeof(struct ip6t_ah)),
+    &help,
+    &init,
+    &parse,
+    &final_check,
+    &print,
+    &save,
+    opts
+};
+
+void
+_init(void)
+{
+	register_match6(&ah);
+}
diff -urN netfilter/userspace.old/extensions/libip6t_esp.c netfilter/userspace/extensions/libip6t_esp.c
--- netfilter/userspace.old/extensions/libip6t_esp.c	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/libip6t_esp.c	Thu Mar 21 21:46:29 2002
@@ -0,0 +1,190 @@
+/* Shared library add-on to ip6tables to add ESP support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <errno.h>
+#include <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6t_esp.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"ESP v%s options:\n"
+" --espspi [!] spi[:spi]        match spi (range)\n",
+NETFILTER_VERSION);
+}
+
+static struct option opts[] = {
+	{ "espspi", 1, 0, '1' },
+	{0}
+};
+
+static u_int32_t
+parse_esp_spi(const char *spistr)
+{
+	unsigned long int spi;
+	char* ep;
+
+	spi =  strtoul(spistr,&ep,0) ;
+
+	if ( spistr == ep ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "ESP no valid digits in spi `%s'", spistr);
+	}
+	if ( spi == ULONG_MAX  && errno == ERANGE ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "spi `%s' specified too big: would overflow", spistr);
+	}	
+	if ( *spistr != '\0'  && *ep != '\0' ) {
+		exit_error(PARAMETER_PROBLEM,
+			   "ESP error parsing spi `%s'", spistr);
+	}
+	return (u_int32_t) spi;
+}
+
+static void
+parse_esp_spis(const char *spistring, u_int32_t *spis)
+{
+	char *buffer;
+	char *cp;
+
+	buffer = strdup(spistring);
+	if ((cp = strchr(buffer, ':')) == NULL)
+		spis[0] = spis[1] = parse_esp_spi(buffer);
+	else {
+		*cp = '\0';
+		cp++;
+
+		spis[0] = buffer[0] ? parse_esp_spi(buffer) : 0;
+		spis[1] = cp[0] ? parse_esp_spi(cp) : 0xFFFFFFFF;
+	}
+	free(buffer);
+}
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+	struct ip6t_esp *espinfo = (struct ip6t_esp *)m->data;
+
+	espinfo->spis[1] = 0xFFFFFFFF;
+}
+
+#define ESP_SPI 0x01
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+	struct ip6t_esp *espinfo = (struct ip6t_esp *)(*match)->data;
+
+	switch (c) {
+	case '1':
+		if (*flags & ESP_SPI)
+			exit_error(PARAMETER_PROBLEM,
+				   "Only one `--espspi' allowed");
+		check_inverse(optarg, &invert, &optind, 0);
+		parse_esp_spis(argv[optind-1], espinfo->spis);
+		if (invert)
+			espinfo->invflags |= IP6T_ESP_INV_SPI;
+		*flags |= ESP_SPI;
+		break;
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Final check; we don't care. */
+static void
+final_check(unsigned int flags)
+{
+}
+
+static void
+print_spis(const char *name, u_int32_t min, u_int32_t max,
+	    int invert)
+{
+	const char *inv = invert ? "!" : "";
+
+	if (min != 0 || max != 0xFFFFFFFF || invert) {
+		printf("%s", name);
+		if (min == max) {
+			printf(":%s", inv);
+			printf("%u", min);
+		} else {
+			printf("s:%s", inv);
+			printf("%u",min);
+			printf(":");
+			printf("%u",max);
+		}
+		printf(" ");
+	}
+}
+
+/* Prints out the union ip6t_matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match, int numeric)
+{
+	const struct ip6t_esp *esp = (struct ip6t_esp *)match->data;
+
+	printf("esp ");
+	print_spis("spi", esp->spis[0], esp->spis[1],
+		    esp->invflags & IP6T_ESP_INV_SPI);
+	if (esp->invflags & ~IP6T_ESP_INV_MASK)
+		printf("Unknown invflags: 0x%X ",
+		       esp->invflags & ~IP6T_ESP_INV_MASK);
+}
+
+/* Saves the union ip6t_matchinfo in parsable form to stdout. */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+	const struct ip6t_esp *espinfo = (struct ip6t_esp *)match->data;
+
+	if (!(espinfo->spis[0] == 0
+	    && espinfo->spis[1] == 0xFFFFFFFF)) {
+		printf("--espspi %s", 
+			(espinfo->invflags & IP6T_ESP_INV_SPI) ? "! " : "");
+		if (espinfo->spis[0]
+		    != espinfo->spis[1])
+			printf("%u:%u ",
+			       espinfo->spis[0],
+			       espinfo->spis[1]);
+		else
+			printf("%u ",
+			       espinfo->spis[0]);
+	}
+
+}
+
+static
+struct ip6tables_match esp
+= { NULL,
+    "esp",
+    NETFILTER_VERSION,
+    IP6T_ALIGN(sizeof(struct ip6t_esp)),
+    IP6T_ALIGN(sizeof(struct ip6t_esp)),
+    &help,
+    &init,
+    &parse,
+    &final_check,
+    &print,
+    &save,
+    opts
+};
+
+void
+_init(void)
+{
+	register_match6(&esp);
+}
diff -urN netfilter/userspace.old/include/linux/netfilter_ipv6/ip6t_ah.h netfilter/userspace/include/linux/netfilter_ipv6/ip6t_ah.h
--- netfilter/userspace.old/include/linux/netfilter_ipv6/ip6t_ah.h	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/include/linux/netfilter_ipv6/ip6t_ah.h	Thu Mar 21 20:22:54 2002
@@ -0,0 +1,21 @@
+#ifndef _IP6T_AH_H
+#define _IP6T_AH_H
+
+struct ip6t_ah
+{
+	u_int32_t spis[2];			/* Security Parameter Index */
+	u_int32_t hdrlen;			/* Header Length */
+	u_int8_t  hdrres;			/* Test of the Reserved Filed */
+	u_int8_t  invflags;			/* Inverse flags */
+};
+
+#define IP6T_AH_SPI 0x01
+#define IP6T_AH_LEN 0x02
+#define IP6T_AH_RES 0x04
+
+/* Values for "invflags" field in struct ip6t_ah. */
+#define IP6T_AH_INV_SPI		0x01	/* Invert the sense of spi. */
+#define IP6T_AH_INV_LEN		0x02	/* Invert the sense of length. */
+#define IP6T_AH_INV_MASK	0x03	/* All possible flags. */
+
+#endif /*_IP6T_AH_H*/
diff -urN netfilter/userspace.old/include/linux/netfilter_ipv6/ip6t_esp.h netfilter/userspace/include/linux/netfilter_ipv6/ip6t_esp.h
--- netfilter/userspace.old/include/linux/netfilter_ipv6/ip6t_esp.h	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/include/linux/netfilter_ipv6/ip6t_esp.h	Wed Mar 20 23:21:12 2002
@@ -0,0 +1,23 @@
+#ifndef _IP6T_ESP_H
+#define _IP6T_ESP_H
+
+struct ip6t_esp
+{
+	u_int32_t spis[2];			/* Security Parameter Index */
+	u_int8_t  invflags;			/* Inverse flags */
+};
+
+#define MASK_HOPOPTS    128
+#define MASK_DSTOPTS    64
+#define MASK_ROUTING    32
+#define MASK_FRAGMENT   16
+#define MASK_AH         8
+#define MASK_ESP        4
+#define MASK_NONE       2
+#define MASK_PROTO      1
+
+/* Values for "invflags" field in struct ip6t_esp. */
+#define IP6T_ESP_INV_SPI		0x01	/* Invert the sense of spi. */
+#define IP6T_ESP_INV_MASK	0x01	/* All possible flags. */
+
+#endif /*_IP6T_ESP_H*/
diff -urN netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6 netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6
--- netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6	Thu Mar 21 23:56:17 2002
@@ -0,0 +1,359 @@
+diff -urN linux/net/ipv6/netfilter/ip6t_ah.c linux.dev/net/ipv6/netfilter/ip6t_ah.c
+--- linux/net/ipv6/netfilter/ip6t_ah.c	Thu Jan  1 01:00:00 1970
++++ linux.dev/net/ipv6/netfilter/ip6t_ah.c	Thu Mar 21 21:58:56 2002
+@@ -0,0 +1,121 @@
++/* Kernel module to match AH parameters. */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ipv6.h>
++#include <linux/types.h>
++#include <net/checksum.h>
++#include <net/ipv6.h>
++
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_ah.h>
++
++EXPORT_NO_SYMBOLS;
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("IPv6 AH match");
++MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>");
++
++/*#if 0*/
++#define DEBUGP printk
++/*#else
++#define DEBUGP(format, args...)
++#endif*/
++
++struct ahhdr {
++       __u8    nexthdr;
++       __u8    hdrlen;
++       __u16   reserved;
++       __u32   spi;
++};
++
++/* Returns 1 if the spi is matched by the range, 0 otherwise */
++static inline int
++spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
++{
++       int r=0;
++       DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
++              min,spi,max);
++       r=(spi >= min && spi <= max) ^ invert;
++       DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
++       return r;
++}
++
++static int
++match(const struct sk_buff *skb,
++      const struct net_device *in,
++      const struct net_device *out,
++      const void *matchinfo,
++      int offset,
++      const void *protohdr,
++      u_int16_t datalen,
++      int *hotdrop)
++{
++       const struct ip6t_ah *ahinfo = matchinfo;
++       struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
++       __u32 hdrlen = 0x0L;
++       struct ahhdr *ah = NULL;
++
++       /*DEBUGP("IPv6 AH entered\n");*/
++       if (opt->auth == 0) return 0;
++
++       DEBUGP("IPv6 AH ext hdr found\n");
++       if (skb_copy_bits(skb, opt->auth, &ah, sizeof(struct ahhdr)))
++              BUG();
++
++       hdrlen = (ah->hdrlen+2)<<2;
++
++       DEBUGP("IPv6 AH LEN %u %u\n", hdrlen, ah->hdrlen);
++       DEBUGP("IPv6 AH RES %04X\n", ah->reserved);
++       DEBUGP("IPv6 AH SPI %u\n", ah->spi);
++
++       return (ah != NULL)
++              &&
++              (spi_match(ahinfo->spis[0], ahinfo->spis[1],
++                           ntohl(ah->spi),
++                           !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
++              &&
++              (ahinfo->hdrlen &&
++                           (ahinfo->hdrlen == hdrlen) ^
++                           !!(ahinfo->invflags & IP6T_AH_INV_LEN))
++              &&
++              (ahinfo->hdrres && !(ah->reserved));
++}
++
++/* Called when user tries to insert an entry of this type. */
++static int
++checkentry(const char *tablename,
++          const struct ip6t_ip6 *ip,
++          void *matchinfo,
++          unsigned int matchinfosize,
++          unsigned int hook_mask)
++{
++       const struct ip6t_ah *ahinfo = matchinfo;
++
++       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
++              DEBUGP("ip6t_ah: matchsize %u != %u\n",
++                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
++              return 0;
++       }
++       if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
++              DEBUGP("ip6t_ah: unknown flags %X\n",
++                      ahinfo->invflags);
++              return 0;
++       }
++
++       return 1;
++}
++
++static struct ip6t_match ah_match
++= { { NULL, NULL }, "ah", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++       return ip6t_register_match(&ah_match);
++}
++
++static void __exit cleanup(void)
++{
++       ip6t_unregister_match(&ah_match);
++}
++
++module_init(init);
++module_exit(cleanup);
+diff -urN linux/net/ipv6/netfilter/ip6t_esp.c linux.dev/net/ipv6/netfilter/ip6t_esp.c
+--- linux/net/ipv6/netfilter/ip6t_esp.c	Thu Jan  1 01:00:00 1970
++++ linux.dev/net/ipv6/netfilter/ip6t_esp.c	Thu Mar 21 21:59:11 2002
+@@ -0,0 +1,178 @@
++/* Kernel module to match ESP parameters. */
++#include <linux/module.h>
++#include <linux/skbuff.h>
++#include <linux/ipv6.h>
++#include <linux/types.h>
++#include <net/checksum.h>
++#include <net/ipv6.h>
++
++#include <linux/netfilter_ipv6/ip6_tables.h>
++#include <linux/netfilter_ipv6/ip6t_esp.h>
++
++EXPORT_NO_SYMBOLS;
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("IPv6 ESP match");
++MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>");
++
++/*#if 0*/
++#define DEBUGP printk
++/*#else
++#define DEBUGP(format, args...)
++#endif*/
++
++struct esphdr {
++	__u32   spi;
++};
++
++int ipv6_ext_hdr(u8 nexthdr)
++{
++        return ( (nexthdr == NEXTHDR_HOP)       ||
++                 (nexthdr == NEXTHDR_ROUTING)   ||
++                 (nexthdr == NEXTHDR_FRAGMENT)  ||
++                 (nexthdr == NEXTHDR_AUTH)      ||
++                 (nexthdr == NEXTHDR_ESP)       ||
++                 (nexthdr == NEXTHDR_NONE)      ||
++                 (nexthdr == NEXTHDR_DEST) );
++}
++
++/* Returns 1 if the spi is matched by the range, 0 otherwise */
++static inline int
++spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
++{
++	int r=0;
++        DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
++        	min,spi,max);
++	r=(spi >= min && spi <= max) ^ invert;
++	DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
++	return r;
++}
++
++static int
++match(const struct sk_buff *skb,
++      const struct net_device *in,
++      const struct net_device *out,
++      const void *matchinfo,
++      int offset,
++      const void *protohdr,
++      u_int16_t datalen,
++      int *hotdrop)
++{
++	struct esphdr *esp = NULL;
++	const struct ip6t_esp *espinfo = matchinfo;
++	unsigned int temp;
++	int len;
++	u8 nexthdr;
++	int ptr;
++
++	/* Make sure this isn't an evil packet */
++	/*DEBUGP("ipv6_esp entered \n");*/
++
++	/* type of the 1st exthdr */
++	nexthdr = skb->nh.ipv6h->nexthdr;
++	/* pointer to the 1st exthdr */
++	ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
++	/* available length */
++	len = skb->len - ptr;
++	temp = 0;
++
++        while (ipv6_ext_hdr(nexthdr)) {
++        	struct ipv6_opt_hdr *hdr;
++        	int hdrlen;
++
++		DEBUGP("ipv6_esp header iteration \n");
++
++		/* Is there enough space for the next ext header? */
++                if (len < (int)sizeof(struct ipv6_opt_hdr))
++                        return 0;
++		/* No more exthdr -> evaluate */
++                if (nexthdr == NEXTHDR_NONE) {
++			break;
++		}
++		/* ESP -> evaluate */
++                if (nexthdr == NEXTHDR_ESP) {
++			temp |= MASK_ESP;
++			break;
++		}
++		if (skb_copy_bits(skb, ptr, &hdr, sizeof(struct ipv6_opt_hdr)))
++			BUG();
++
++		/* Calculate the header length */
++                if (nexthdr == NEXTHDR_FRAGMENT) {
++                        hdrlen = 8;
++                } else if (nexthdr == NEXTHDR_AUTH)
++                        hdrlen = (hdr->hdrlen+2)<<2;
++                else
++                        hdrlen = ipv6_optlen(hdr);
++
++		/* set the flag */
++		switch (nexthdr){
++			case NEXTHDR_HOP:
++			case NEXTHDR_ROUTING:
++			case NEXTHDR_FRAGMENT:
++			case NEXTHDR_AUTH:
++			case NEXTHDR_DEST:
++				break;
++			default:
++				DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
++				return 0;
++				break;
++		}
++
++                nexthdr = hdr->nexthdr;
++                len -= hdrlen;
++                ptr += hdrlen;
++        }
++
++	/* ESP header not found */
++	if ( temp != MASK_ESP ) return 0;
++
++	if (skb_copy_bits(skb, ptr, &esp, sizeof(esp)))
++		BUG();
++
++	DEBUGP("IPv6 ESP SPI %u", esp->spi);
++
++	return (esp != NULL)
++		&& spi_match(espinfo->spis[0], espinfo->spis[1],
++			      ntohl(esp->spi),
++			      !!(espinfo->invflags & IP6T_ESP_INV_SPI));
++}
++
++/* Called when user tries to insert an entry of this type. */
++static int
++checkentry(const char *tablename,
++	   const struct ip6t_ip6 *ip,
++	   void *matchinfo,
++	   unsigned int matchinfosize,
++	   unsigned int hook_mask)
++{
++	const struct ip6t_esp *espinfo = matchinfo;
++
++	if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_esp))) {
++		DEBUGP("ip6t_esp: matchsize %u != %u\n",
++			 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_esp)));
++		return 0;
++	}
++	if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
++		DEBUGP("ip6t_esp: unknown flags %X\n",
++			 espinfo->invflags);
++		return 0;
++	}
++
++	return 1;
++}
++
++static struct ip6t_match esp_match
++= { { NULL, NULL }, "esp", &match, &checkentry, NULL, THIS_MODULE };
++
++static int __init init(void)
++{
++	return ip6t_register_match(&esp_match);
++}
++
++static void __exit cleanup(void)
++{
++	ip6t_unregister_match(&esp_match);
++}
++
++module_init(init);
++module_exit(cleanup);
+diff -urN linux/include/linux/netfilter_ipv6/ip6t_ah.h linux.dev/include/linux/netfilter_ipv6/ip6t_ah.h
+--- linux/include/linux/netfilter_ipv6/ip6t_ah.h	Thu Jan  1 01:00:00 1970
++++ linux.dev/include/linux/netfilter_ipv6/ip6t_ah.h	Thu Mar 21 21:12:40 2002
+@@ -0,0 +1,21 @@
++#ifndef _IP6T_AH_H
++#define _IP6T_AH_H
++
++struct ip6t_ah
++{
++	u_int32_t spis[2];			/* Security Parameter Index */
++	u_int32_t hdrlen;			/* Header Length */
++	u_int8_t  hdrres;			/* Test of the Reserved Filed */
++	u_int8_t  invflags;			/* Inverse flags */
++};
++
++#define IP6T_AH_SPI 0x01
++#define IP6T_AH_LEN 0x02
++#define IP6T_AH_RES 0x04
++
++/* Values for "invflags" field in struct ip6t_ah. */
++#define IP6T_AH_INV_SPI		0x01	/* Invert the sense of spi. */
++#define IP6T_AH_INV_LEN		0x02	/* Invert the sense of length. */
++#define IP6T_AH_INV_MASK	0x03	/* All possible flags. */
++
++#endif /*_IP6T_AH_H*/
+diff -urN linux/include/linux/netfilter_ipv6/ip6t_esp.h linux.dev/include/linux/netfilter_ipv6/ip6t_esp.h
+--- linux/include/linux/netfilter_ipv6/ip6t_esp.h	Thu Jan  1 01:00:00 1970
++++ linux.dev/include/linux/netfilter_ipv6/ip6t_esp.h	Wed Mar 20 23:22:07 2002
+@@ -0,0 +1,23 @@
++#ifndef _IP6T_ESP_H
++#define _IP6T_ESP_H
++
++struct ip6t_esp
++{
++	u_int32_t spis[2];			/* Security Parameter Index */
++	u_int8_t  invflags;			/* Inverse flags */
++};
++
++#define MASK_HOPOPTS    128
++#define MASK_DSTOPTS    64
++#define MASK_ROUTING    32
++#define MASK_FRAGMENT   16
++#define MASK_AH         8
++#define MASK_ESP        4
++#define MASK_NONE       2
++#define MASK_PROTO      1
++
++/* Values for "invflags" field in struct ip6t_esp. */
++#define IP6T_ESP_INV_SPI		0x01	/* Invert the sense of spi. */
++#define IP6T_ESP_INV_MASK	0x01	/* All possible flags. */
++
++#endif /*_IP6T_ESP_H*/
diff -urN netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.config.in netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.config.in
--- netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.config.in	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.config.in	Thu Mar 21 23:45:59 2002
@@ -0,0 +1,4 @@
+  dep_tristate '  netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    dep_tristate '  AH/ESP match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_AHESP $CONFIG_IP6_NF_IPTABLES
+  fi
diff -urN netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.configure.help netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.configure.help
--- netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.configure.help	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.configure.help	Thu Mar 21 23:49:23 2002
@@ -0,0 +1,9 @@
+CONFIG_IP6_NF_MATCH_MAC
+AH/ESP match support (EXPERIMENTAL)
+CONFIG_IP6_NF_MATCH_AHESP
+  These two match extensions (`ah' and `esp') allow you to match a
+  range of SPIs inside AH or ESP headers of IPv6 packets.
+ 
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
diff -urN netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.help netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help
--- netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.help	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help	Thu Mar 21 23:51:28 2002
@@ -0,0 +1,14 @@
+Author: Andras Kis-Szabo <[EMAIL PROTECTED]>
+Status: Under development, please test it!
+
+  These two match extensions (`ah' and `esp') allow you to match a
+  range of SPIs inside AH or ESP headers of IPv6 packets.
+
+  AH options:
+ --ahspi [!] spi[:spi]         match spi (range)
+ --ahlen [!] length            total length of this header
+ --ahres                       check the reserved filed, too
+
+ ESP option:
+ --espspi [!] spi[:spi]        match spi (range)
+
diff -urN netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.makefile netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.makefile
--- netfilter/userspace.old/patch-o-matic/base/ahesp6.patch.ipv6.makefile	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.makefile	Thu Mar 21 23:47:01 2002
@@ -0,0 +1,2 @@
+obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
+obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
diff -urN netfilter/HOWTO.old/netfilter-extensions-HOWTO.sgml netfilter/HOWTO/netfilter-extensions-HOWTO.sgml
--- netfilter/HOWTO.old/netfilter-extensions-HOWTO.sgml	Fri Mar 22 00:16:46 2002
+++ netfilter/HOWTO/netfilter-extensions-HOWTO.sgml	Fri Mar 22 00:39:29 2002
@@ -1163,8 +1163,10 @@
 This patch by Andras Kis-Szabo &lt;[EMAIL PROTECTED]&gt; adds 1 new match :
 
 <itemize>
-<item>``agr'' : lets you match the IPv6 packet based on it's addressing parameters.
+<item>``eui64'' : lets you match the IPv6 packet based on it's addressing parameters.
 </itemize>
+<p>
+Current status: pending (2.4.19)
 
 <p>
 This patch can be quite useful for people using EUI-64 IPv6 addressing scheme
@@ -1175,7 +1177,7 @@
 
 <tscreen><verb>
 # ip6tables -N ipv6ok
-# ip6tables -A INPUT -m agr -j ipv6ok
+# ip6tables -A INPUT -m eui64 -j ipv6ok
 # ip6tables -A INPUT -s ! 3FFE:2F00:A0::/64 -j ipv6ok
 # ip6tables -A INPUT -j LOG
 # ip6tables -A ipv6ok -j ACCEPT
@@ -1183,7 +1185,7 @@
 # ip6tables --list
 Chain INPUT (policy ACCEPT)
 target     prot opt source               destination         
-ipv6ok     all      anywhere             anywhere           AGR 
+ipv6ok     all      anywhere             anywhere           eui64 
 ipv6ok     all     !3ffe:2f00:a0::/64    anywhere           
 LOG        all      anywhere             anywhere           LOG level warning 
 
@@ -1199,6 +1201,12 @@
 <p>
 This patch by Andras Kis-Szabo &lt;[EMAIL PROTECTED]&gt; adds a new match
 that allows you to match a packet based on its extension headers. 
+The name of the match:
+<itemize>
+<item>``ipv6header'' : lets you match the IPv6 packet based on its headers.
+</itemize>
+<p>
+Current status: base, highly experimental
 
 <p>
 For example, let's drop the packets which have got hop-by-hop, ipv6-route 
@@ -1251,6 +1259,9 @@
 </itemize>
 
 <p>
+Current status: in the kernel
+
+<p>
 These matches are the ports of the IPv4 versions. See the main documentation for the details!
 
 <sect1>length patch
@@ -1284,6 +1295,70 @@
 Values of the range not present will be implied. The implied value for minimum
 is 0, and for maximum is 65535.
 
+<sect1>ahesp6 patch
+<p>
+This patch by Andras Kis-Szabo &lt;[EMAIL PROTECTED]&gt; adds a new match
+that allows you to match a packet based on its ah and esp headers' content.
+The name of the matches:
+<itemize>
+<item>``ah'' : lets you match the IPv6 packet based on its ah header.
+<item>``esp'' : lets you match the IPv6 packet based on its esp header.
+</itemize>
+<p>
+Current status: base, highly experimental
+
+<p>
+For example, we will drop all the AH packets that have a SPI equal to
+500, and check the contents of the restricted area in the header :
+
+<tscreen><verb>
+# ip6tables -A INPUT -m ah --ahspi 500 --ahres -j DROP
+
+# ip6tables --list
+Chain INPUT (policy ACCEPT)
+target     prot opt source               destination         
+DROP       all      anywhere             anywhere           ah spi:500 reserved
+</verb></tscreen>
+
+<p>
+Supported options for the ah match are :
+
+<descrip>
+<tag>--ahspi [!] spi[:spi]</> -&gt; match spi (range)
+<tag>--ahlen [!] length</> -&gt; length ot this header
+<tag>--ahres </> -&gt; check the contents of the reserved field
+</descrip>
+
+<p>
+The esp match works exactly the same as in IPv4 :
+
+<tscreen><verb>
+# ip6tables -A INPUT -m esp --espspi 500 -j DROP
+
+# iptables --list
+Chain INPUT (policy ACCEPT)
+target     prot opt source               destination         
+DROP       all      anywhere             anywhere           esp spi:500 
+</verb></tscreen>
+
+<p>
+Supported options for the esp match are :
+
+<descrip>
+<tag>--espspi [!] spi[:spi]</>  -&gt; match spi (range)
+</descrip>
+
+In IPv6 these matches can be concatenated:
+
+<tscreen><verb>
+# ip6tables -A INPUT -m ah --ahspi 500 --ahres --ahlen ! 40 -m esp --espspi 500 -j DROP
+
+# iptables --list
+Chain INPUT (policy ACCEPT)
+target     prot opt source               destination         
+DROP       all      anywhere             anywhere           ah spi:500 length:!40 reserved esp spi:500
+</verb></tscreen>
+
 <sect>New IPv6 netfilter targets
 <p>
 In this section, we will attempt to explain the usage of new netfilter targets.
@@ -1310,12 +1385,18 @@
 to LOG the packets as in the IPv4 version of iptables.
 
 <p>
+Current status: in the kernel
+
+<p>
 The examples are the same as in iptables. See the man page for details!
 
 <sect1>REJECT patch
 <p>
 This patch by Harald Welte &lt;[EMAIL PROTECTED]&gt; adds a new target that allows you
 to REJECT the packets as in the IPv4 version of iptables.
+
+<p>
+Current status: base, testing
 
 <p>
 The examples are the same as in iptables. See the man page for details!
diff -urN netfilter/userspace.old/extensions/libip6t_agr.c netfilter/userspace/extensions/libip6t_agr.c
--- netfilter/userspace.old/extensions/libip6t_agr.c	Fri Mar 22 01:08:39 2002
+++ netfilter/userspace/extensions/libip6t_agr.c	Thu Jan  1 01:00:00 1970
@@ -1,87 +0,0 @@
-/* Shared library add-on to ip6tables to add MAC address checking support. */
-#include <stdio.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <getopt.h>
-#if defined(__GLIBC__) && __GLIBC__ == 2
-#include <net/ethernet.h>
-#else
-#include <linux/if_ether.h>
-#endif
-#include <ip6tables.h>
-
-/* Function which prints out usage message. */
-static void
-help(void)
-{
-	printf(
-"AGR v%s options:\n"
-" This module hasn't got any option\n"
-" This module checks for aggregated IPv6 addresses\n"
-"\n", NETFILTER_VERSION);
-}
-
-static struct option opts[] = {
-	{0}
-};
-
-/* Initialize the match. */
-static void
-init(struct ip6t_entry_match *m, unsigned int *nfcache)
-{
-	/* Can't cache this */
-	*nfcache |= NFC_UNKNOWN;
-}
-
-/* Function which parses command options; returns true if it
-   ate an option */
-static int
-parse(int c, char **argv, int invert, unsigned int *flags,
-      const struct ip6t_entry *entry,
-      unsigned int *nfcache,
-      struct ip6t_entry_match **match)
-{
-	return 0;
-}
-
-/* Final check */
-static void final_check(unsigned int flags)
-{
-}
-
-/* Prints out the matchinfo. */
-static void
-print(const struct ip6t_ip6 *ip,
-      const struct ip6t_entry_match *match,
-      int numeric)
-{
-	printf("AGR ");
-}
-
-/* Saves the union ip6t_matchinfo in parsable form to stdout. */
-static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
-{
-	/* printf("--agr "); */
-}
-
-static
-struct ip6tables_match agr
-= { NULL,
-    "agr",
-    NETFILTER_VERSION,
-    IP6T_ALIGN(sizeof(int)),
-    IP6T_ALIGN(sizeof(int)),
-    &help,
-    &init,
-    &parse,
-    &final_check,
-    &print,
-    &save,
-    opts
-};
-
-void _init(void)
-{
-	register_match6(&agr);
-}
diff -urN netfilter/userspace.old/extensions/libip6t_eui64.c netfilter/userspace/extensions/libip6t_eui64.c
--- netfilter/userspace.old/extensions/libip6t_eui64.c	Thu Jan  1 01:00:00 1970
+++ netfilter/userspace/extensions/libip6t_eui64.c	Fri Mar 22 01:08:30 2002
@@ -0,0 +1,87 @@
+/* Shared library add-on to ip6tables to add EUI64 address checking support. */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+#include <ip6tables.h>
+
+/* Function which prints out usage message. */
+static void
+help(void)
+{
+	printf(
+"eui64 v%s options:\n"
+" This module hasn't got any option\n"
+" This module checks for EUI64 IPv6 addresses\n"
+"\n", NETFILTER_VERSION);
+}
+
+static struct option opts[] = {
+	{0}
+};
+
+/* Initialize the match. */
+static void
+init(struct ip6t_entry_match *m, unsigned int *nfcache)
+{
+	/* Can't cache this */
+	*nfcache |= NFC_UNKNOWN;
+}
+
+/* Function which parses command options; returns true if it
+   ate an option */
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+      const struct ip6t_entry *entry,
+      unsigned int *nfcache,
+      struct ip6t_entry_match **match)
+{
+	return 0;
+}
+
+/* Final check */
+static void final_check(unsigned int flags)
+{
+}
+
+/* Prints out the matchinfo. */
+static void
+print(const struct ip6t_ip6 *ip,
+      const struct ip6t_entry_match *match,
+      int numeric)
+{
+	printf("eui64 ");
+}
+
+/* Saves the union ip6t_matchinfo in parsable form to stdout. */
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+
+}
+
+static
+struct ip6tables_match eui64
+= { NULL,
+    "eui64",
+    NETFILTER_VERSION,
+    IP6T_ALIGN(sizeof(int)),
+    IP6T_ALIGN(sizeof(int)),
+    &help,
+    &init,
+    &parse,
+    &final_check,
+    &print,
+    &save,
+    opts
+};
+
+void _init(void)
+{
+	register_match6(&eui64);
+}

Reply via email to