diff -uNr linux-2.4.15-pre6.pristine/include/linux/netfilter_ipv4/ipt_length.h linux-2.4.15-pre6.newlength/include/linux/netfilter_ipv4/ipt_length.h
--- linux-2.4.15-pre6.pristine/include/linux/netfilter_ipv4/ipt_length.h	Tue Oct 30 18:08:12 2001
+++ linux-2.4.15-pre6.newlength/include/linux/netfilter_ipv4/ipt_length.h	Tue Nov 20 18:13:10 2001
@@ -1,9 +1,19 @@
 #ifndef _IPT_LENGTH_H
 #define _IPT_LENGTH_H
 
+/* Value reserved for future merge of invert and ip/proto/payload flags. */
+// #define IPT_LENGTH_INVERT	0x01	/* Invert sense of match; only match packets outside of the specified range */
+
+/* The following can be combined.  0x0C, for example, would be the   
+   length of the protocol header and payload. */
+#define IPT_LENGTH_IP		0x02	/* Include the length of the IP header */
+#define IPT_LENGTH_PROTO	0x04	/* Include the length of the protocol (TCP, UDP, ICMP, etc.) header */
+#define IPT_LENGTH_PAYLOAD	0x08	/* Include the length of the payload */
+
 struct ipt_length_info {
     u_int16_t	min, max;
     u_int8_t	invert;
+    u_int8_t	lengthflags;
 };
 
 #endif /*_IPT_LENGTH_H*/
diff -uNr linux-2.4.15-pre6.pristine/net/ipv4/netfilter/ipt_length.c linux-2.4.15-pre6.newlength/net/ipv4/netfilter/ipt_length.c
--- linux-2.4.15-pre6.pristine/net/ipv4/netfilter/ipt_length.c	Tue Oct 30 18:08:12 2001
+++ linux-2.4.15-pre6.newlength/net/ipv4/netfilter/ipt_length.c	Tue Nov 20 20:36:28 2001
@@ -1,6 +1,7 @@
 /* Kernel module to match packet length. */
 #include <linux/module.h>
 #include <linux/skbuff.h>
+#include <net/tcp.h>
 
 #include <linux/netfilter_ipv4/ipt_length.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
@@ -20,9 +21,66 @@
       int *hotdrop)
 {
 	const struct ipt_length_info *info = matchinfo;
-	u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);
-	
-	return (pktlen >= info->min && pktlen <= info->max) ^ info->invert;
+
+/* Set pktlen */
+	u_int16_t pktlen = ntohs(skb->nh.iph->tot_len);		/* Entire packet length */
+	u_int16_t ipheaderlen = 0;				/* IP header length */
+	u_int16_t protoheaderlen = 0;				/* Protocol header length */
+	u_int16_t payloadlen = 0;				/* Payload only length */
+	u_int16_t comparelen = 0;				/* The length we'll compare against; it's the sum of one or more of the above 3 */
+
+/* Set ipheaderlen */
+	if (pktlen > datalen)
+		ipheaderlen = pktlen - datalen;
+
+/* Set protoheaderlen */
+	switch (skb->nh.iph->protocol) {
+	case IPPROTO_TCP: {
+		struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)skb->nh.iph + skb->nh.iph->ihl);
+		protoheaderlen = (tcph->doff) * 4;
+		break;
+	}
+	case IPPROTO_UDP: {
+		protoheaderlen = 8;
+		break;
+	}
+	case IPPROTO_ICMP: {
+		protoheaderlen = 4;     
+		break;
+	}       
+	default:
+		/* Snort decides to treat all non-TCP/UDP/ICMP
+		   as having no header; any protocol header is
+		   treated as part of the data portion of the packet.
+		*/
+		protoheaderlen = 0;
+	}
+
+/* Set payloadlen */
+	if (datalen > protoheaderlen)
+		payloadlen = (datalen - protoheaderlen);
+
+/* Quick sanity check; if all flags off, we assume the userspace tool failed to
+   set any of them.  If all three flags were cleared, we assume we need to
+   match the old behavior of checking the length of all three. */
+	if ((info->lengthflags & (IPT_LENGTH_IP | IPT_LENGTH_IP | IPT_LENGTH_PAYLOAD)) = 0)
+		comparelen = ipheader + protoheaderlen + payloadlen;
+	else {
+/* Decide what fields we're going to compare against. */
+		if ((info->lengthflags & IPT_LENGTH_IP) != 0)
+			comparelen = comparelen + ipheaderlen;
+		if ((info->lengthflags & IPT_LENGTH_PROTO) != 0)
+			comparelen = comparelen + protoheaderlen;
+		if ((info->lengthflags & IPT_LENGTH_PAYLOAD) != 0)
+			comparelen = comparelen + payloadlen;
+	}
+
+	/* If we merge the invert and flags fields, replace
+	   ^ info->invert
+		with
+	   ^ (((info->invert) & IPT_LENGTH_INVERT) == IPT_LENGTH_INVERT )
+	*/
+	return (comparelen >= info->min && comparelen <= info->max) ^ info->invert;
 }
 
 static int