]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/linux/linux-4.9.8-layer7-filter.patch
kernel: updated to 4.9.8
[people/pmueller/ipfire-2.x.git] / src / patches / linux / linux-4.9.8-layer7-filter.patch
similarity index 86%
rename from src/patches/linux-3.14-layer7-filter.patch
rename to src/patches/linux/linux-4.9.8-layer7-filter.patch
index ba799f73fa7c8c4ae5eeeca859351dc7f9654518..eeed239507936a08434d40ea39b74653d448d32e 100644 (file)
@@ -1,7 +1,7 @@
-diff -Naur linux-3.14.22.org/include/linux/netfilter/xt_layer7.h linux-3.14.22/include/linux/netfilter/xt_layer7.h
---- linux-3.14.22.org/include/linux/netfilter/xt_layer7.h      1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/include/linux/netfilter/xt_layer7.h  2014-10-24 15:33:21.281274380 +0200
-@@ -0,0 +1,14 @@
+diff -Naur linux-4.9.8.org/include/linux/netfilter/xt_layer7.h linux-4.9.8/include/linux/netfilter/xt_layer7.h
+--- linux-4.9.8.org/include/linux/netfilter/xt_layer7.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/include/linux/netfilter/xt_layer7.h    2017-02-10 20:55:36.894611414 +0100
+@@ -0,0 +1,13 @@
 +#ifndef _XT_LAYER7_H
 +#define _XT_LAYER7_H
 +
@@ -12,16 +12,15 @@ diff -Naur linux-3.14.22.org/include/linux/netfilter/xt_layer7.h linux-3.14.22/i
 +    char protocol[MAX_PROTOCOL_LEN];
 +    char pattern[MAX_PATTERN_LEN];
 +    u_int8_t invert;
-+    u_int8_t pkt;
 +};
 +
 +#endif /* _XT_LAYER7_H */
-diff -Naur linux-3.14.22.org/include/net/netfilter/nf_conntrack.h linux-3.14.22/include/net/netfilter/nf_conntrack.h
---- linux-3.14.22.org/include/net/netfilter/nf_conntrack.h     2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/include/net/netfilter/nf_conntrack.h 2014-10-24 15:33:21.281274380 +0200
-@@ -105,6 +105,22 @@
-       struct net *ct_net;
- #endif
+diff -Naur linux-4.9.8.org/include/net/netfilter/nf_conntrack.h linux-4.9.8/include/net/netfilter/nf_conntrack.h
+--- linux-4.9.8.org/include/net/netfilter/nf_conntrack.h       2017-02-04 09:47:29.000000000 +0100
++++ linux-4.9.8/include/net/netfilter/nf_conntrack.h   2017-02-10 16:10:27.000000000 +0100
+@@ -120,6 +120,22 @@
+       /* Extensions */
+       struct nf_ct_ext *ext;
  
 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
 +    defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
@@ -42,21 +41,10 @@ diff -Naur linux-3.14.22.org/include/net/netfilter/nf_conntrack.h linux-3.14.22/
        /* Storage reserved for other modules, must be the last member */
        union nf_conntrack_proto proto;
  };
-diff -Naur linux-3.14.22.org/include/uapi/linux/netfilter/Kbuild linux-3.14.22/include/uapi/linux/netfilter/Kbuild
---- linux-3.14.22.org/include/uapi/linux/netfilter/Kbuild      2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/include/uapi/linux/netfilter/Kbuild  2014-10-24 15:34:39.721663344 +0200
-@@ -59,6 +59,7 @@
- header-y += xt_iprange.h
- header-y += xt_ipvs.h
- header-y += xt_l2tp.h
-+header-y += xt_layer7.h
- header-y += xt_length.h
- header-y += xt_limit.h
- header-y += xt_mac.h
-diff -Naur linux-3.14.22.org/net/netfilter/Kconfig linux-3.14.22/net/netfilter/Kconfig
---- linux-3.14.22.org/net/netfilter/Kconfig    2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/net/netfilter/Kconfig        2014-10-24 15:33:21.281274380 +0200
-@@ -1153,6 +1153,26 @@
+diff -Naur linux-4.9.8.org/net/netfilter/Kconfig linux-4.9.8/net/netfilter/Kconfig
+--- linux-4.9.8.org/net/netfilter/Kconfig      2017-02-04 09:47:29.000000000 +0100
++++ linux-4.9.8/net/netfilter/Kconfig  2017-02-10 16:10:30.000000000 +0100
+@@ -1238,6 +1238,26 @@
  
        To compile it as a module, choose M here. If unsure, say N.
  
@@ -83,23 +71,10 @@ diff -Naur linux-3.14.22.org/net/netfilter/Kconfig linux-3.14.22/net/netfilter/K
  config NETFILTER_XT_MATCH_LENGTH
        tristate '"length" match support'
        depends on NETFILTER_ADVANCED
-@@ -1347,6 +1367,12 @@
-         To compile it as a module, choose M here.  If unsure, say N.
-+config NETFILTER_XT_MATCH_LAYER7_DEBUG
-+      bool 'Layer 7 debugging output'
-+      depends on NETFILTER_XT_MATCH_LAYER7
-+      help
-+        Say Y to get lots of debugging output.
-+
- config NETFILTER_XT_MATCH_STATISTIC
-       tristate '"statistic" match support'
-       depends on NETFILTER_ADVANCED
-diff -Naur linux-3.14.22.org/net/netfilter/Makefile linux-3.14.22/net/netfilter/Makefile
---- linux-3.14.22.org/net/netfilter/Makefile   2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/net/netfilter/Makefile       2014-10-24 15:33:21.281274380 +0200
-@@ -158,6 +158,7 @@
+diff -Naur linux-4.9.8.org/net/netfilter/Makefile linux-4.9.8/net/netfilter/Makefile
+--- linux-4.9.8.org/net/netfilter/Makefile     2017-02-04 09:47:29.000000000 +0100
++++ linux-4.9.8/net/netfilter/Makefile 2017-02-10 16:10:30.000000000 +0100
+@@ -174,6 +174,7 @@
  obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
@@ -107,12 +82,12 @@ diff -Naur linux-3.14.22.org/net/netfilter/Makefile linux-3.14.22/net/netfilter/
  obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
  obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
-diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_core.c linux-3.14.22/net/netfilter/nf_conntrack_core.c
---- linux-3.14.22.org/net/netfilter/nf_conntrack_core.c        2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/net/netfilter/nf_conntrack_core.c    2014-10-24 15:33:21.281274380 +0200
-@@ -220,6 +220,13 @@
-        * too. */
-       nf_ct_remove_expectations(ct);
+diff -Naur linux-4.9.8.org/net/netfilter/nf_conntrack_core.c linux-4.9.8/net/netfilter/nf_conntrack_core.c
+--- linux-4.9.8.org/net/netfilter/nf_conntrack_core.c  2017-02-04 09:47:29.000000000 +0100
++++ linux-4.9.8/net/netfilter/nf_conntrack_core.c      2017-02-10 16:10:30.000000000 +0100
+@@ -341,6 +341,13 @@
+ {
+       struct ct_pcpu *pcpu;
  
 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
 +      if(ct->layer7.app_proto)
@@ -122,27 +97,26 @@ diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_core.c linux-3.14.22/net
 +#endif
 +
        /* We overload first tuple to link into unconfirmed or dying list.*/
-       BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
-       hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
-diff -Naur linux-3.14.22.org/net/netfilter/nf_conntrack_standalone.c linux-3.14.22/net/netfilter/nf_conntrack_standalone.c
---- linux-3.14.22.org/net/netfilter/nf_conntrack_standalone.c  2014-10-15 08:42:04.000000000 +0200
-+++ linux-3.14.22/net/netfilter/nf_conntrack_standalone.c      2014-10-24 15:33:21.285274399 +0200
-@@ -240,6 +240,12 @@
-       if (ct_show_delta_time(s, ct))
-               goto release;
+       pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu);
+diff -Naur linux-4.9.8.org/net/netfilter/nf_conntrack_standalone.c linux-4.9.8/net/netfilter/nf_conntrack_standalone.c
+--- linux-4.9.8.org/net/netfilter/nf_conntrack_standalone.c    2017-02-04 09:47:29.000000000 +0100
++++ linux-4.9.8/net/netfilter/nf_conntrack_standalone.c        2017-02-10 16:10:30.000000000 +0100
+@@ -274,6 +274,11 @@
+       ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
+       ct_show_delta_time(s, ct);
  
 +#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
-+      if(ct->layer7.app_proto &&
-+           seq_printf(s, "l7proto=%s ", ct->layer7.app_proto))
-+              return -ENOSPC;
++      if(ct->layer7.app_proto)
++              seq_printf(s, "l7proto=%s ", ct->layer7.app_proto);
 +#endif
 +
-       if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
-               goto release;
+       seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use));
  
-diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.c linux-3.14.22/net/netfilter/regexp/regexp.c
---- linux-3.14.22.org/net/netfilter/regexp/regexp.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/net/netfilter/regexp/regexp.c        2014-10-24 15:33:21.285274399 +0200
+       if (seq_has_overflowed(s))
+diff -Naur linux-4.9.8.org/net/netfilter/regexp/regexp.c linux-4.9.8/net/netfilter/regexp/regexp.c
+--- linux-4.9.8.org/net/netfilter/regexp/regexp.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/net/netfilter/regexp/regexp.c  2017-02-10 20:55:36.898611415 +0100
 @@ -0,0 +1,1197 @@
 +/*
 + * regcomp and regexec -- regsub and regerror are elsewhere
@@ -1341,9 +1315,9 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.c linux-3.14.22/net/net
 +#endif
 +
 +
-diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.h linux-3.14.22/net/netfilter/regexp/regexp.h
---- linux-3.14.22.org/net/netfilter/regexp/regexp.h    1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/net/netfilter/regexp/regexp.h        2014-10-24 15:33:21.285274399 +0200
+diff -Naur linux-4.9.8.org/net/netfilter/regexp/regexp.h linux-4.9.8/net/netfilter/regexp/regexp.h
+--- linux-4.9.8.org/net/netfilter/regexp/regexp.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/net/netfilter/regexp/regexp.h  2017-02-10 20:55:36.898611415 +0100
 @@ -0,0 +1,41 @@
 +/*
 + * Definitions etc. for regexp(3) routines.
@@ -1386,18 +1360,18 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regexp.h linux-3.14.22/net/net
 +void regerror(char *s);
 +
 +#endif
-diff -Naur linux-3.14.22.org/net/netfilter/regexp/regmagic.h linux-3.14.22/net/netfilter/regexp/regmagic.h
---- linux-3.14.22.org/net/netfilter/regexp/regmagic.h  1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/net/netfilter/regexp/regmagic.h      2014-10-24 15:33:21.285274399 +0200
+diff -Naur linux-4.9.8.org/net/netfilter/regexp/regmagic.h linux-4.9.8/net/netfilter/regexp/regmagic.h
+--- linux-4.9.8.org/net/netfilter/regexp/regmagic.h    1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/net/netfilter/regexp/regmagic.h        2017-02-10 20:55:36.898611415 +0100
 @@ -0,0 +1,5 @@
 +/*
 + * The first byte of the regexp internal "program" is actually this magic
 + * number; the start node begins in the second byte.
 + */
 +#define       MAGIC   0234
-diff -Naur linux-3.14.22.org/net/netfilter/regexp/regsub.c linux-3.14.22/net/netfilter/regexp/regsub.c
---- linux-3.14.22.org/net/netfilter/regexp/regsub.c    1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/net/netfilter/regexp/regsub.c        2014-10-24 15:33:21.285274399 +0200
+diff -Naur linux-4.9.8.org/net/netfilter/regexp/regsub.c linux-4.9.8/net/netfilter/regexp/regsub.c
+--- linux-4.9.8.org/net/netfilter/regexp/regsub.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/net/netfilter/regexp/regsub.c  2017-02-10 20:55:36.898611415 +0100
 @@ -0,0 +1,95 @@
 +/*
 + * regsub
@@ -1494,10 +1468,10 @@ diff -Naur linux-3.14.22.org/net/netfilter/regexp/regsub.c linux-3.14.22/net/net
 +      }
 +      *dst++ = '\0';
 +}
-diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilter/xt_layer7.c
---- linux-3.14.22.org/net/netfilter/xt_layer7.c        1970-01-01 01:00:00.000000000 +0100
-+++ linux-3.14.22/net/netfilter/xt_layer7.c    2014-10-24 15:33:21.285274399 +0200
-@@ -0,0 +1,665 @@
+diff -Naur linux-4.9.8.org/net/netfilter/xt_layer7.c linux-4.9.8/net/netfilter/xt_layer7.c
+--- linux-4.9.8.org/net/netfilter/xt_layer7.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-4.9.8/net/netfilter/xt_layer7.c      2017-02-10 22:42:57.750923134 +0100
+@@ -0,0 +1,658 @@
 +/*
 +  Kernel module to match application layer (OSI layer 7) data in connections.
 +
@@ -1521,13 +1495,14 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +#include <net/ip.h>
 +#include <net/tcp.h>
 +#include <linux/module.h>
-+#include <linux/seq_file.h>
 +#include <linux/skbuff.h>
 +#include <linux/netfilter.h>
 +#include <net/netfilter/nf_conntrack.h>
 +#include <net/netfilter/nf_conntrack_core.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
 +#include <net/netfilter/nf_conntrack_extend.h>
 +#include <net/netfilter/nf_conntrack_acct.h>
++#endif
 +#include <linux/netfilter/x_tables.h>
 +#include <linux/netfilter/xt_layer7.h>
 +#include <linux/ctype.h>
@@ -1539,7 +1514,7 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>");
 +MODULE_DESCRIPTION("iptables application layer match module");
 +MODULE_ALIAS("ipt_layer7");
-+MODULE_VERSION("2.21");
++MODULE_VERSION("2.23");
 +
 +static int maxdatalen = 2048; // this is the default
 +module_param(maxdatalen, int, 0444);
@@ -1564,13 +1539,18 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +
 +static int total_acct_packets(struct nf_conn *ct)
 +{
++#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 26)
++      BUG_ON(ct == NULL);
++      return (ct->counters[IP_CT_DIR_ORIGINAL].packets + ct->counters[IP_CT_DIR_REPLY].packets);
++#else
 +      struct nf_conn_counter *acct;
 +
 +      BUG_ON(ct == NULL);
 +      acct = nf_conn_acct_find(ct);
 +      if (!acct)
 +              return 0;
-+      return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
++        return (atomic64_read(&acct[IP_CT_DIR_ORIGINAL].packets) + atomic64_read(&acct[IP_CT_DIR_REPLY].packets));
++#endif
 +}
 +
 +#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
@@ -1706,67 +1686,40 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +
 +static int can_handle(const struct sk_buff *skb)
 +{
-+      struct iphdr iphdr_tmp;
-+      struct iphdr *iphdr;
-+      int offset;
-+
-+      if (!ip_hdr(skb))
++      if(!ip_hdr(skb)) /* not IP */
 +              return 0;
-+
-+      offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data);
-+
-+      iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp);
-+      if (!iphdr)
++      if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
++         ip_hdr(skb)->protocol != IPPROTO_UDP &&
++         ip_hdr(skb)->protocol != IPPROTO_ICMP)
 +              return 0;
-+
-+      if (iphdr->protocol == IPPROTO_TCP ||
-+          iphdr->protocol == IPPROTO_UDP ||
-+          iphdr->protocol == IPPROTO_ICMP)
-+              return 1;
-+
-+      return 0;
++      return 1;
 +}
 +
++/* Returns offset the into the skb->data that the application data starts */
 +static int app_data_offset(const struct sk_buff *skb)
 +{
-+      int offset;
-+      struct iphdr iphdr_tmp;
-+      struct iphdr *iphdr;
-+      struct tcphdr tcphdr_tmp;
-+      struct tcphdr *tcphdr;
-+
-+      if (!ip_hdr(skb))
-+              return -1;
-+
-+      offset = ((uintptr_t)ip_hdr(skb)) - ((uintptr_t)skb->data);
-+
-+      iphdr = skb_header_pointer(skb, offset, sizeof(*iphdr), &iphdr_tmp);
-+      if (!iphdr)
-+              return -1;
-+
-+      offset += iphdr->ihl * 4;
-+
-+      if (iphdr->protocol == IPPROTO_TCP) {
-+              tcphdr = skb_header_pointer(skb, offset, sizeof(*tcphdr),
-+                                          &tcphdr_tmp);
-+              if (!tcphdr)
-+                      return -1;
-+
-+              offset += tcphdr->doff * 4;
-+
-+              return offset;
++      /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
++      isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
++      int ip_hl = 4*ip_hdr(skb)->ihl;
++
++      if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
++              /* 12 == offset into TCP header for the header length field.
++              Can't get this with skb->h.th->doff because the tcphdr
++              struct doesn't get set when routing (this is confirmed to be
++              true in Netfilter as well as QoS.) */
++              int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
++
++              return ip_hl + tcp_hl;
++      } else if( ip_hdr(skb)->protocol == IPPROTO_UDP  ) {
++              return ip_hl + 8; /* UDP header is always 8 bytes */
++      } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
++              return ip_hl + 8; /* ICMP header is 8 bytes */
++      } else {
++              if (net_ratelimit())
++                      printk(KERN_ERR "layer7: tried to handle unknown "
++                                      "protocol!\n");
++              return ip_hl + 8; /* something reasonable */
 +      }
-+
-+      if (iphdr->protocol == IPPROTO_UDP)
-+              return offset + 8;
-+
-+      if (iphdr->protocol == IPPROTO_ICMP)
-+              return offset + 8;
-+
-+      if (net_ratelimit())
-+              pr_err(KERN_ERR "layer7: tried to handle unknown protocol!\n");
-+
-+      return offset + 8; /* something reasonable */
 +}
 +
 +/* handles whether there's a match when we aren't appending data anymore */
@@ -1835,61 +1788,33 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +}
 +
 +/* add the new app data to the conntrack.  Return number of bytes added. */
-+static int add_datastr(char *target, int offset, char *app_data, int len)
++static int add_data(struct nf_conn * master_conntrack,
++                    char * app_data, int appdatalen)
 +{
 +      int length = 0, i;
-+      if (!target) return 0;
++      int oldlength = master_conntrack->layer7.app_data_len;
++
++      /* This is a fix for a race condition by Deti Fliegl. However, I'm not 
++         clear on whether the race condition exists or whether this really 
++         fixes it.  I might just be being dense... Anyway, if it's not really 
++         a fix, all it does is waste a very small amount of time. */
++      if(!master_conntrack->layer7.app_data) return 0;
 +
 +      /* Strip nulls. Make everything lower case (our regex lib doesn't
 +      do case insensitivity).  Add it to the end of the current data. */
-+      for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
++      for(i = 0; i < maxdatalen-oldlength-1 &&
++                 i < appdatalen; i++) {
 +              if(app_data[i] != '\0') {
 +                      /* the kernel version of tolower mungs 'upper ascii' */
-+                      target[length+offset] =
++                      master_conntrack->layer7.app_data[length+oldlength] =
 +                              isascii(app_data[i])? 
 +                                      tolower(app_data[i]) : app_data[i];
 +                      length++;
 +              }
 +      }
-+      target[length+offset] = '\0';
-+
-+      return length;
-+}
-+
-+/* add the new app data to the buffer.  Return number of bytes added. */
-+static int add_data(char *target, int offset, const struct sk_buff *skb)
-+{
-+      int length, length_sum = 0;
-+      int data_start = app_data_offset(skb);
-+      int remaining = skb->len - data_start;
-+      int to_copy;
-+      uint8_t buf[512];
-+      uint8_t *data;
-+
-+      while ((offset < maxdatalen - 1) && (remaining > 0)) {
-+              to_copy = min_t(int, remaining, sizeof(buf));
-+
-+              data = skb_header_pointer(skb, data_start, to_copy, buf);
-+              length = add_datastr(target, offset, data, to_copy);
-+
-+              remaining -= to_copy;
-+              data_start += to_copy;
-+              offset += length;
-+              length_sum += length;
-+      }
-+
-+      return length_sum;
-+}
-+
-+/* add the new app data to the conntrack.  Return number of bytes added. */
-+static int add_data_conntrack(struct nf_conn *master_conntrack,
-+                            const struct sk_buff *skb)
-+{
-+      int length;
 +
-+      length = add_data(master_conntrack->layer7.app_data,
-+                        master_conntrack->layer7.app_data_len, skb);
-+      master_conntrack->layer7.app_data_len += length;
++      master_conntrack->layer7.app_data[length+oldlength] = '\0';
++      master_conntrack->layer7.app_data_len = length + oldlength;
 +
 +      return length;
 +}
@@ -1941,23 +1866,42 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +      return count;
 +}
 +
-+static bool match(const struct sk_buff *skbin, struct xt_action_param *par)
++static bool
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
++match(const struct sk_buff *skbin, struct xt_action_param *par)
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
++match(const struct sk_buff *skbin, const struct xt_match_param *par)
++#else
++match(const struct sk_buff *skbin,
++      const struct net_device *in,
++      const struct net_device *out,
++      const struct xt_match *match,
++      const void *matchinfo,
++      int offset,
++      unsigned int protoff,
++      bool *hotdrop)
++#endif
 +{
 +      /* sidestep const without getting a compiler warning... */
-+      struct sk_buff *skb = (struct sk_buff *)skbin;
++      struct sk_buff * skb = (struct sk_buff *)skbin; 
 +
-+      const struct xt_layer7_info * info = par->matchinfo;
++      const struct xt_layer7_info * info = 
++      #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
++              par->matchinfo;
++      #else
++              matchinfo;
++      #endif
 +
 +      enum ip_conntrack_info master_ctinfo, ctinfo;
 +      struct nf_conn *master_conntrack, *conntrack;
-+      unsigned char *tmp_data;
-+      unsigned int pattern_result;
++      unsigned char * app_data;
++      unsigned int pattern_result, appdatalen;
 +      regexp * comppattern;
 +
 +      /* Be paranoid/incompetent - lock the entire match function. */
 +      spin_lock_bh(&l7_lock);
 +
-+      if (!can_handle(skbin)) {
++      if(!can_handle(skb)){
 +              DPRINTK("layer7: This is some protocol I can't handle.\n");
 +              spin_unlock_bh(&l7_lock);
 +              return info->invert;
@@ -1966,9 +1910,8 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +      /* Treat parent & all its children together as one connection, except
 +      for the purpose of setting conntrack->layer7.app_proto in the actual
 +      connection. This makes /proc/net/ip_conntrack more satisfying. */
-+      conntrack = nf_ct_get(skbin, &ctinfo);
-+      master_conntrack = nf_ct_get(skbin, &master_ctinfo);
-+      if (!conntrack || !master_conntrack) {
++      if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
++         !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
 +              DPRINTK("layer7: couldn't get conntrack.\n");
 +              spin_unlock_bh(&l7_lock);
 +              return info->invert;
@@ -1979,8 +1922,8 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +              master_conntrack = master_ct(master_conntrack);
 +
 +      /* if we've classified it or seen too many packets */
-+      if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
-+         master_conntrack->layer7.app_proto)) {
++      if(total_acct_packets(master_conntrack) > num_packets ||
++         master_conntrack->layer7.app_proto) {
 +
 +              pattern_result = match_no_append(conntrack, master_conntrack, 
 +                                               ctinfo, master_ctinfo, info);
@@ -1996,27 +1939,22 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +              return (pattern_result ^ info->invert);
 +      }
 +
-+      /* the return value gets checked later, when we're ready to use it */
-+      comppattern = compile_and_cache(info->pattern, info->protocol);
-+
-+      if (info->pkt) {
-+              tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
-+              if(!tmp_data){
++      if(skb_is_nonlinear(skb)){
++              if(skb_linearize(skb) != 0){
 +                      if (net_ratelimit())
-+                              printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
++                              printk(KERN_ERR "layer7: failed to linearize "
++                                              "packet, bailing.\n");
++                      spin_unlock_bh(&l7_lock);
 +                      return info->invert;
 +              }
++      }
 +
-+              tmp_data[0] = '\0';
-+              add_data(tmp_data, 0, skbin);
-+              pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
-+
-+              kfree(tmp_data);
-+              tmp_data = NULL;
-+              spin_unlock_bh(&l7_lock);
++      /* now that the skb is linearized, it's safe to set these. */
++      app_data = skb->data + app_data_offset(skb);
++      appdatalen = skb_tail_pointer(skb) - app_data;
 +
-+              return (pattern_result ^ info->invert);
-+      }
++      /* the return value gets checked later, when we're ready to use it */
++      comppattern = compile_and_cache(info->pattern, info->protocol);
 +
 +      /* On the first packet of a connection, allocate space for app data */
 +      if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] && 
@@ -2043,7 +1981,7 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +
 +      if(!skb->cb[0]){
 +              int newbytes;
-+              newbytes = add_data_conntrack(master_conntrack, skb);
++              newbytes = add_data(master_conntrack, app_data, appdatalen);
 +
 +              if(newbytes == 0) { /* didn't add any data */
 +                      skb->cb[0] = 1;
@@ -2094,26 +2032,54 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +}
 +
 +// load nf_conntrack_ipv4
-+static int check(const struct xt_mtchk_param *par)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
++static int
++#else
++static bool
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
++check(const struct xt_mtchk_param *par)
 +{
 +        if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
 +                printk(KERN_WARNING "can't load conntrack support for "
 +                                    "proto=%d\n", par->match->family);
++#else
++check(const char *tablename, const void *inf,
++               const struct xt_match *match, void *matchinfo,
++               unsigned int hook_mask)
++{
++        if (nf_ct_l3proto_try_module_get(match->family) < 0) {
++                printk(KERN_WARNING "can't load conntrack support for "
++                                    "proto=%d\n", match->family);
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
 +              return -EINVAL;
 +      }
 +      return 0;
++#else
++                return 0;
++        }
++      return 1;
++#endif
 +}
 +
 +
-+static void destroy(const struct xt_mtdtor_param *par)
-+{
-+      nf_ct_l3proto_module_put(par->match->family);
-+}
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
++      static void destroy(const struct xt_mtdtor_param *par)
++      {
++              nf_ct_l3proto_module_put(par->match->family);
++      }
++#else
++      static void destroy(const struct xt_match *match, void *matchinfo)
++      {
++              nf_ct_l3proto_module_put(match->family);
++      }
++#endif
 +
 +static struct xt_match xt_layer7_match[] __read_mostly = {
 +{
 +      .name           = "layer7",
-+      .family         = AF_INET,
++      .family         = NFPROTO_IPV4,
 +      .checkentry     = check,
 +      .match          = match,
 +      .destroy        = destroy,
@@ -2163,3 +2129,4 @@ diff -Naur linux-3.14.22.org/net/netfilter/xt_layer7.c linux-3.14.22/net/netfilt
 +
 +module_init(xt_layer7_init);
 +module_exit(xt_layer7_fini);
++