Hi,

Fixes (of my faults):
 - logical expressions
 - skb ( :( )
 - skb->cb dropped (not valid on output hook)
 - fixed header-chain iteration
(All test passed with the example packets.)

Regards,

        kisza
-- 
    Andras Kis-Szabo       Security Development, Design and Audit
-------------------------/       Zorp, NetFilter and IPv6
 [EMAIL PROTECTED] /---------------------------------------------->
diff -urN netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6 netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6
--- netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6	Mon Mar 25 19:41:12 2002
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6	Mon Mar 25 19:45:33 2002
@@ -1,7 +1,7 @@
 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 @@
+@@ -0,0 +1,209 @@
 +/* Kernel module to match AH parameters. */
 +#include <linux/module.h>
 +#include <linux/skbuff.h>
@@ -18,11 +18,11 @@
 +MODULE_DESCRIPTION("IPv6 AH match");
 +MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>");
 +
-+/*#if 0*/
++#if 0
 +#define DEBUGP printk
-+/*#else
++#else
 +#define DEBUGP(format, args...)
-+#endif*/
++#endif
 +
 +struct ahhdr {
 +       __u8    nexthdr;
@@ -31,6 +31,17 @@
 +       __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)
@@ -53,23 +64,100 @@
 +      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;
++       const struct ip6t_ah *ahinfo = matchinfo;
++       unsigned int temp;
++       int len;
++       u8 nexthdr;
++       unsigned int ptr;
++       unsigned int hdrlen = 0;
 +
 +       /*DEBUGP("IPv6 AH entered\n");*/
-+       if (opt->auth == 0) return 0;
++       /* if (opt->auth == 0) return 0;
++       * It does not filled on output */
++
++       /* type of the 1st exthdr */
++       nexthdr = skb->nh.ipv6h->nexthdr;
++       /* pointer to the 1st exthdr */
++       ptr = sizeof(struct ipv6hdr);
++       /* available length */
++       len = skb->len - ptr;
++       temp = 0;
++
++        while (ipv6_ext_hdr(nexthdr)) {
++               struct ipv6_opt_hdr *hdr;
 +
-+       DEBUGP("IPv6 AH ext hdr found\n");
-+       if (skb_copy_bits(skb, opt->auth, &ah, sizeof(struct ahhdr)))
-+              BUG();
++              DEBUGP("ipv6_ah header iteration \n");
 +
-+       hdrlen = (ah->hdrlen+2)<<2;
++              /* 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) {
++                     break;
++              }
 +
-+       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);
++              hdr=skb->data+ptr;
++
++              /* 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);
++
++              /* AH -> evaluate */
++                if (nexthdr == NEXTHDR_AUTH) {
++                     temp |= MASK_AH;
++                     break;
++              }
++
++
++              /* set the flag */
++              switch (nexthdr){
++                     case NEXTHDR_HOP:
++                     case NEXTHDR_ROUTING:
++                     case NEXTHDR_FRAGMENT:
++                     case NEXTHDR_AUTH:
++                     case NEXTHDR_DEST:
++                            break;
++                     default:
++                            DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
++                            return 0;
++                            break;
++              }
++
++                nexthdr = hdr->nexthdr;
++                len -= hdrlen;
++                ptr += hdrlen;
++        }
++
++       /* AH header not found */
++       if ( temp != MASK_AH ) return 0;
++
++       ah=skb->data+ptr;
++
++       DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
++       DEBUGP("RES %04X ", ah->reserved);
++       DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
++
++       DEBUGP("IPv6 AH spi %02X ",
++       		(spi_match(ahinfo->spis[0], ahinfo->spis[1],
++                           ntohl(ah->spi),
++                           !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
++       DEBUGP("len %02X %04X %02X ",
++       		ahinfo->hdrlen, hdrlen,
++       		(!ahinfo->hdrlen ||
++                           (ahinfo->hdrlen == hdrlen) ^
++                           !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
++       DEBUGP("res %02X %04X %02X\n", 
++       		ahinfo->hdrres, ah->reserved,
++       		!(ahinfo->hdrres && ah->reserved));
 +
 +       return (ah != NULL)
 +              &&
@@ -77,11 +165,11 @@
 +                           ntohl(ah->spi),
 +                           !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
 +              &&
-+              (ahinfo->hdrlen &&
++              (!ahinfo->hdrlen ||
 +                           (ahinfo->hdrlen == hdrlen) ^
 +                           !!(ahinfo->invflags & IP6T_AH_INV_LEN))
 +              &&
-+              (ahinfo->hdrres && !(ah->reserved));
++              !(ahinfo->hdrres && ah->reserved);
 +}
 +
 +/* Called when user tries to insert an entry of this type. */
@@ -126,7 +214,7 @@
 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 @@
+@@ -0,0 +1,177 @@
 +/* Kernel module to match ESP parameters. */
 +#include <linux/module.h>
 +#include <linux/skbuff.h>
@@ -143,11 +231,11 @@
 +MODULE_DESCRIPTION("IPv6 ESP match");
 +MODULE_AUTHOR("Andras Kis-Szabo <[EMAIL PROTECTED]>");
 +
-+/*#if 0*/
++#if 0
 +#define DEBUGP printk
-+/*#else
++#else
 +#define DEBUGP(format, args...)
-+#endif*/
++#endif
 +
 +struct esphdr {
 +	__u32   spi;
@@ -191,7 +279,7 @@
 +	unsigned int temp;
 +	int len;
 +	u8 nexthdr;
-+	int ptr;
++	unsigned int ptr;
 +
 +	/* Make sure this isn't an evil packet */
 +	/*DEBUGP("ipv6_esp entered \n");*/
@@ -199,7 +287,7 @@
 +	/* type of the 1st exthdr */
 +	nexthdr = skb->nh.ipv6h->nexthdr;
 +	/* pointer to the 1st exthdr */
-+	ptr = (u8*)(skb->nh.ipv6h+1) - skb->data;
++	ptr = sizeof(struct ipv6hdr);
 +	/* available length */
 +	len = skb->len - ptr;
 +	temp = 0;
@@ -222,8 +310,8 @@
 +			temp |= MASK_ESP;
 +			break;
 +		}
-+		if (skb_copy_bits(skb, ptr, &hdr, sizeof(struct ipv6_opt_hdr)))
-+			BUG();
++
++		hdr=skb->data+ptr;
 +
 +		/* Calculate the header length */
 +                if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -255,10 +343,9 @@
 +	/* ESP header not found */
 +	if ( temp != MASK_ESP ) return 0;
 +
-+	if (skb_copy_bits(skb, ptr, &esp, sizeof(esp)))
-+		BUG();
++	esp=skb->data+ptr;
 +
-+	DEBUGP("IPv6 ESP SPI %u", esp->spi);
++	DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
 +
 +	return (esp != NULL)
 +		&& spi_match(espinfo->spis[0], espinfo->spis[1],
@@ -308,7 +395,7 @@
 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 @@
+@@ -0,0 +1,30 @@
 +#ifndef _IP6T_AH_H
 +#define _IP6T_AH_H
 +
@@ -328,6 +415,15 @@
 +#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. */
++
++#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
 +
 +#endif /*_IP6T_AH_H*/
 diff -urN linux/include/linux/netfilter_ipv6/ip6t_esp.h linux.dev/include/linux/netfilter_ipv6/ip6t_esp.h
diff -urN netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6.help netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help
--- netfilter/userspace/patch-o-matic/base.old/ahesp6.patch.ipv6.help	Mon Mar 25 19:41:12 2002
+++ netfilter/userspace/patch-o-matic/base/ahesp6.patch.ipv6.help	Mon Mar 25 19:42:03 2002
@@ -1,5 +1,5 @@
 Author: Andras Kis-Szabo <[EMAIL PROTECTED]>
-Status: Under development, please test it!
+Status: It works 4 me!
 
   These two match extensions (`ah' and `esp') allow you to match a
   range of SPIs inside AH or ESP headers of IPv6 packets.

Reply via email to