--- ./linux_os.h.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./linux_os.h	2008-04-15 11:02:35.000000000 +0300
@@ -5,6 +5,9 @@
 *  File:    linux_os.h
 *  Date:    04/25/2001
 *
+*  Updated to work with Linux kernels >=2.6.19 (including 2.6.22) by
+*  Alexander Griesser 29/05/07 <cisco@tuxx-home.at>
+*
 ***************************************************************************
 *
 * Macros for handling differences in the linux kernel api.
@@ -30,6 +33,39 @@
 #define PACKET_TYPE_NEXT(pt) ((pt)->next)
 #endif
 
+/* With linux 2.6.19, CHECKSUM_HW was split into CHECKSUM_COMPLETE
+ * and CHECKSUM_PARTIAL
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
+  #define CHECK_IP_SUMMED(n) \
+    (((n) == CHECKSUM_COMPLETE) || ((n) == CHECKSUM_PARTIAL))
+  #define SKB_CHECKSUM_HELP(a,b)        skb_checksum_help((a))
+#else
+  #define CHECK_IP_SUMMED(n) ((n) == CHECKSUM_HW)
+  #define SKB_CHECKSUM_HELP(a,b)        skb_checksum_help((a),(b))
+#endif
+
+
+/* With linux 2.6.22, the sk_buff struct has changed
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+  #define CISCOVPN_SKB_NH_ID(a)           (ip_hdr(a)->id)
+  #define CISCOVPN_SKB_NH_FRAGOFF(a)      (ip_hdr(a)->frag_off)
+  #define CISCOVPN_SKB_NH_TOTLEN(a)       (ip_hdr(a)->tot_len)
+  #define CISCOVPN_SKB_NH_IHL(a)          (ip_hdr(a)->ihl)
+  #define CISCOVPN_SKB_IPHEADER(a)        (ip_hdr(a))
+  #define CISCOVPN_SKB_MACHEADER(a)       (skb_mac_header(a))
+  #define CISCOVPN_SKB_NETWORKHEADER(a)   (skb_network_header(a))
+#else
+  #define CISCOVPN_SKB_NH_ID(a)           (a->nh.iph->id)
+  #define CISCOVPN_SKB_NH_FRAGOFF(a)      (a->nh.iph->frag_off)
+  #define CISCOVPN_SKB_NH_TOTLEN(a)       (a->nh.iph->tot_len)
+  #define CISCOVPN_SKB_NH_IHL(a)          (a->nh.iph->ihl)
+  #define CISCOVPN_SKB_IPHEADER(a)        (a->nh.iph)
+  #define CISCOVPN_SKB_MACHEADER(a)       (a->mac.raw)
+  #define CISCOVPN_SKB_NETWORKHEADER(a)   (a->nh.raw)
+#endif
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,5)
 #include <asm/uaccess.h>
 #else
--- ./interceptor.c.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./interceptor.c	2008-04-15 11:02:35.000000000 +0300
@@ -5,10 +5,13 @@
 *  File:    interceptor.c
 *  Date:    04/10/2001
 *
+*  Updated to work with Linux kernels >=2.6.19 (including 2.6.22) by
+*  Alexander Griesser 29/05/07 <cisco@tuxx-home.at>
+*
 ***************************************************************************
 * This module implements the linux driver.
 ***************************************************************************/
-#include <linux/config.h>
+#include <linux/autoconf.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -24,6 +27,37 @@
 #include <linux/udp.h>
 #include <net/protocol.h>
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#include <net/net_namespace.h>
+#include <linux/nsproxy.h>
+
+/* Workaround for getting the init namespace without making use
+ * of the GPL-only init_net symbol
+ * 
+ * This function is borrowed from net/core/rtnetlink.c
+ *
+ * by Alexander Griesser <work@tuxx-home.at>, 2008-01-13
+ */
+static struct net *get_net_ns_by_pid(pid_t pid)
+{
+        struct task_struct *tsk;
+        struct net *net;
+
+        /* Lookup the network namespace */
+        net = ERR_PTR(-ESRCH);
+        rcu_read_lock();
+        tsk = find_task_by_vpid(pid);
+        if (tsk) {
+                struct nsproxy *nsproxy;
+                nsproxy = task_nsproxy(tsk);
+                if (nsproxy)
+                        net = get_net(nsproxy->net_ns);
+        }
+        rcu_read_unlock();
+        return net;
+}
+#endif
+
 #include "linux_os.h"
 
 #include "vpn_ioctl_linux.h"
@@ -44,7 +78,7 @@
 unsigned long rx_bytes;
 
 /*methods of the cipsec network device*/
-static int interceptor_init(struct net_device *);
+static void interceptor_init(struct net_device *);
 static struct net_device_stats *interceptor_stats(struct net_device *dev);
 static int interceptor_ioctl(struct net_device *dev, struct ifreq *ifr,
                              int cmd);
@@ -88,15 +122,22 @@
 
 BINDING Bindings[MAX_INTERFACES];
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+static struct net_device interceptor_dev_s = {
+#else
 static struct net_device interceptor_dev = {
+#endif
     .name = interceptor_name,
     .init = interceptor_init
 };
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+static struct net_device *interceptor_dev = &interceptor_dev_s;
+#endif
 static struct notifier_block interceptor_notifier = {
     .notifier_call = handle_netdev_event,
 };
 
-static int __init
+static void __init
 interceptor_init(struct net_device *dev)
 {
     ether_setup(dev);
@@ -110,8 +151,6 @@
     dev->flags |= IFF_NOARP;
     dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
     kernel_memset(dev->broadcast, 0xFF, ETH_ALEN);
-
-    return 0;
 }
 
 static struct net_device_stats *
@@ -283,6 +322,17 @@
     static struct packet_type dummy_pt;
 
     struct net_device *dp = NULL;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    /* Get the network namespace for process id 1 (usually init)
+     * and therefore should be the namespace for all local interfaces used
+     * to connect to your VPN gateway
+     *
+     * by Alexander Griesser <work@tuxx-home.at>, 2008-01-13
+     */
+    struct net *initnet = get_net_ns_by_pid((pid_t)1);
+#endif
+
     struct packet_type *default_pt = NULL;
     int error = VPNIFUP_SUCCESS, num_target_devices;
 
@@ -339,13 +389,22 @@
 
     dp = NULL;
     num_target_devices = 0;
-    for (dp = dev_base; dp != NULL; dp = dp->next)
-    {
+
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+       for_each_netdev(
+       #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+                     &init_net,
+       #endif
+                     dp)
+    #else
+      for (dp = dev_base; dp != NULL; dp = dp->next)
+    #endif
+      {
         if (add_netdev(dp) == 0)
         {
             num_target_devices++;
         }
-    }
+      }
 
     if (num_target_devices == 0)
     {
@@ -550,13 +609,13 @@
         goto exit_gracefully;
     }
 
-    if (skb->ip_summed == CHECKSUM_HW)
+    if (CHECK_IP_SUMMED(skb->ip_summed))
     {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
-       if (skb_checksum_help(skb,1))
+       if (SKB_CHECKSUM_HELP(skb,1))
 #else
-       if (skb_checksum_help(&skb,1))
+       if (SKB_CHECKSUM_HELP(&skb,1))
 #endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
        {
            dev_kfree_skb(skb);
@@ -569,9 +628,10 @@
     }
 
     reset_inject_status(&pBinding->recv_stat);
-    if (skb->mac.raw)
+
+    if (CISCOVPN_SKB_MACHEADER(skb))
     {
-        hard_header_len = skb->data - skb->mac.raw;
+        hard_header_len = skb->data - CISCOVPN_SKB_MACHEADER(skb);
         if ((hard_header_len < 0) || (hard_header_len > skb_headroom(skb)))
         {
             printk(KERN_DEBUG "bad hh len %d\n", hard_header_len);
@@ -588,7 +648,7 @@
     switch (hard_header_len)
     {
     case ETH_HLEN:
-        CniNewFragment(ETH_HLEN, skb->mac.raw, &MacHdr, CNI_USE_BUFFER);
+        CniNewFragment(ETH_HLEN, CISCOVPN_SKB_MACHEADER(skb), &MacHdr, CNI_USE_BUFFER);
         break;
     case IPPP_MAX_HEADER:
     case 0:
@@ -677,14 +737,14 @@
     tmp_InjectSend = NULL;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-    if (skb->ip_summed == CHECKSUM_HW)
+    if (CHECK_IP_SUMMED(skb->ip_summed))
     {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
-       if (skb_checksum_help(skb,0))
+       if (SKB_CHECKSUM_HELP(skb,0))
 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
-       if (skb_checksum_help(&skb,0))
+       if (SKB_CHECKSUM_HELP(&skb,0))
 #else
-       if ((skb = skb_checksum_help(skb)) == NULL)
+       if ((skb = SKB_CHECKSUM_HELP(skb)) == NULL)
 #endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7)
        {
            goto exit_gracefully;
@@ -692,7 +752,8 @@
     }
 #endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     reset_inject_status(&pBinding->send_stat);
-    hard_header_len = skb->nh.raw - skb->data;
+
+    hard_header_len = CISCOVPN_SKB_NETWORKHEADER(skb) - skb->data;
     pBinding->send_real_hh_len = hard_header_len;
     switch (hard_header_len)
     {
@@ -833,15 +894,30 @@
 
     rc = CniPluginLoad(&pcDeviceName, &PCNICallbackTable);
 
+/* 2.6.24 needs to allocate each netdevice before registering it, otherwise
+ * the kernel BUG()s.
+ *
+ * by Alexander Griesser <work@tuxx-home.at>, 2008-01-11
+ */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    if(! (interceptor_dev = alloc_netdev(sizeof(struct net_device), interceptor_name, interceptor_init)))
+      return 0;
+#endif
+
     if (CNI_IS_SUCCESS(rc))
     {
 
         CNICallbackTable = *PCNICallbackTable;
         CniPluginDeviceCreated();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+	if ((status = register_netdev(interceptor_dev)) != 0)
+#else
         if ((status = register_netdev(&interceptor_dev)) != 0)
+#endif
         {
             printk(KERN_INFO "%s: error %d registering device \"%s\".\n",
-                   LINUX_VPN_IFNAME, status, interceptor_dev.name);
+                   LINUX_VPN_IFNAME, status, interceptor_name);
             CniPluginUnload();
 
         }
@@ -861,7 +937,11 @@
     cleanup_frag_queue();
     CniPluginUnload();
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+    unregister_netdev(interceptor_dev);
+#else
     unregister_netdev(&interceptor_dev);
+#endif
     unregister_netdevice_notifier(&interceptor_notifier);
 
     return;
--- ./GenDefs.h.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./GenDefs.h	2008-04-15 11:02:35.000000000 +0300
@@ -105,6 +105,12 @@
 #define _INTPTR_T_DEFINED
 #endif
 
+/* uintptr_t has been defined in include/linux/types.h in 2.6.24.
+ * No need to define it here again (will only lead to compile errors)
+ *
+ * by Alexander Griesser <work@tuxx-home.at>, 2008-01-11
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
 #ifndef _UINTPTR_T_DEFINED
 #if defined(_LP64)
 #warning 64 bit
@@ -114,6 +120,7 @@
 #endif
 #define _UINTPTR_T_DEFINED
 #endif
+#endif
 
 
 typedef int 	BOOL;
--- ./IPSecDrvOS_linux.c.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./IPSecDrvOS_linux.c	2008-04-15 11:02:35.000000000 +0300
@@ -11,7 +11,7 @@
 *   
 *
 ***************************************************************************/
-#include <linux/config.h>
+#include <linux/autoconf.h>
 #include <linux/version.h>
 #include <linux/vmalloc.h>
 #include <linux/sched.h>
--- ./linuxcniapi.c.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./linuxcniapi.c	2008-04-15 11:02:35.000000000 +0300
@@ -5,11 +5,14 @@
  *  File:    linuxcniapi.c
  *  Date:    22/03/01
  *
+ *  Updated to work with Linux kernels >=2.6.19 (including 2.6.22) by
+ *  Alexander Griesser 29/05/07 <cisco@tuxx-home.at>
+ *
  ***************************************************************************
  * This module implements a translation layer between the CNI API and the
  * Linux Interceptor driver.
  ***************************************************************************/
-#include <linux/config.h>
+#include <linux/autoconf.h>
 #include <linux/version.h>
 #include <linux/netdevice.h>
 #include <linux/if.h>
@@ -292,9 +295,19 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
     {
         struct timeval timestamp;
-
         do_gettimeofday(&timestamp);
-        skb_set_timestamp(skb,&timestamp);
+	/* With Linux 2.6.22 skb_set_timestamp has been dropped.
+	 * Additionally, the attribute tstamp now is in ktime_t
+	 * where it prior to 2.6.22 was in skb_timeval.
+	 *
+	 * As a proprietary module, we may not use ktime_get_real,
+	 * so we need to do it this way
+	 */
+	#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+          skb->tstamp = timeval_to_ktime(timestamp);
+	#else
+          skb_set_timestamp(skb,&timestamp);
+	#endif
     }
 #else
     do_gettimeofday(&skb->stamp);
@@ -328,8 +341,13 @@
 
     skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-    skb->nh.iph = (struct iphdr *) skb->data;
-    skb->mac.raw = pMac;
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+      skb_reset_network_header(skb);
+      skb_reset_mac_header(skb);
+    #else
+      skb->nh.iph = (struct iphdr *) skb->data;
+      skb->mac.raw = pMac;
+    #endif
 
     pBinding->recv_stat.called = TRUE;
 
@@ -441,9 +459,19 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
     {
         struct timeval timestamp;
-
         do_gettimeofday(&timestamp);
-        skb_set_timestamp(skb,&timestamp);
+        /* With Linux 2.6.22 skb_set_timestamp has been dropped.
+         * Additionally, the attribute tstamp now is in ktime_t
+         * where it prior to 2.6.22 was in skb_timeval.
+         *
+         * As a proprietary module, we may not use ktime_get_real,
+         * so we need to do it this way
+         */
+        #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+          skb->tstamp = timeval_to_ktime(timestamp);
+        #else
+          skb_set_timestamp(skb,&timestamp);
+        #endif
     }
 #else
     do_gettimeofday(&skb->stamp);
@@ -451,11 +479,21 @@
 
     skb->dev = pBinding->pDevice;
 
-    skb->mac.raw = pMac;
-    skb->nh.raw = pIP;
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+      skb_reset_mac_header(skb);
+      skb_reset_network_header(skb);
+    #else
+      skb->mac.raw = pMac;
+      skb->nh.raw = pIP;
+    #endif
 
     /*ip header length is in 32bit words */
-    skb->h.raw = pIP + (skb->nh.iph->ihl * 4);
+    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+      skb->transport_header = skb->network_header + (ip_hdr(skb)->ihl * 4);
+    #else
+      skb->h.raw = pIP + (skb->nh.iph->ihl * 4);
+    #endif
+
     skb->protocol = htons(ETH_P_IP);
 
     /* send this packet up the NIC driver */
--- ./frag.c.orig	2005-11-22 11:43:57.000000000 +0200
+++ ./frag.c	2008-04-15 11:02:35.000000000 +0300
@@ -1,4 +1,18 @@
-#include <linux/config.h>
+/**************************************************************************
+ *           Copyright (c) 2001, Cisco Systems, All Rights Reserved
+ ***************************************************************************
+ *
+ *  File:    frag.c
+ *  Date:    22/03/01
+ *
+ *  Updated to work with Linux kernels >=2.6.19 (including 2.6.22) by
+ *  Alexander Griesser 29/05/07 <cisco@tuxx-home.at>
+ *
+ ***************************************************************************
+ * This module does some really cool stuff only Cisco knows about
+ ***************************************************************************/
+
+#include <linux/autoconf.h>
 #include <linux/version.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -37,9 +51,10 @@
     int ret=FALSE;
     struct frag_queue_entry *cur=NULL,*n=NULL,*prev=NULL;
 
-    id = ntohs(skb->nh.iph->id);
+    id = ntohs(CISCOVPN_SKB_NH_ID(skb));
+
     /* look for an entry with the same id as this packet*/
-    if (frag_queue_head && id != ntohs(frag_queue_head->skb->nh.iph->id))
+    if (frag_queue_head && id != ntohs(CISCOVPN_SKB_NH_ID(frag_queue_head->skb)))
     {
         printk(KERN_INFO "%s: incomplete fragment set destroyed",__FUNCTION__);
         cleanup_frag_queue();
@@ -57,10 +72,13 @@
     cur = frag_queue_head;
 
     prev = NULL;
-    skb_offset = ntohs(skb->nh.iph->frag_off) & IP_OFFSET;
+
+    skb_offset = ntohs(CISCOVPN_SKB_NH_FRAGOFF(skb)) & IP_OFFSET;
+
     while (cur)
     {
-        cur_offset = ntohs(cur->skb->nh.iph->frag_off) & IP_OFFSET;
+        cur_offset = ntohs(CISCOVPN_SKB_NH_FRAGOFF(cur->skb)) & IP_OFFSET;
+
         /*sanity check*/
         if (cur_offset < prev_offset)
         {
@@ -112,8 +130,9 @@
         goto done_with_tests;
     }
     cur = frag_queue_head;
+
     /*first in queue must be first frag.*/
-    if ((ntohs(cur->skb->nh.iph->frag_off) & IP_OFFSET) != 0)
+    if ((ntohs(CISCOVPN_SKB_NH_FRAGOFF(cur->skb)) & IP_OFFSET) != 0)
     {
         goto done_with_tests;
     }
@@ -121,19 +140,22 @@
        by comparing adjacent offset values and packet lengths*/
     while (cur)
     {
-        cur_offset = (ntohs(cur->skb->nh.iph->frag_off) & IP_OFFSET)*8;
-        if (cur_offset != prev_end_offset)
+	cur_offset = (ntohs(CISCOVPN_SKB_NH_FRAGOFF(cur->skb)) & IP_OFFSET)*8;
+
+	if (cur_offset != prev_end_offset)
         { 
             goto done_with_tests;
         }
         prev = cur;
         prev_offset = cur_offset;
-        prev_end_offset = prev_offset + ntohs(prev->skb->nh.iph->tot_len)
-                          - (prev->skb->nh.iph->ihl*4);
+
+        prev_end_offset = prev_offset + ntohs(CISCOVPN_SKB_NH_TOTLEN(prev->skb))
+	                  - (CISCOVPN_SKB_NH_IHL(prev->skb)*4);
         cur = cur->next;
     } 
     /*last in queue must not have more frags set*/
-    if (ntohs(prev->skb->nh.iph->frag_off) & IP_MF)
+
+    if (ntohs(CISCOVPN_SKB_NH_FRAGOFF(prev->skb)) & IP_MF)
     {
         goto done_with_tests;
     }
@@ -185,10 +207,12 @@
         /*not an IP packet*/
         goto done_with_tests;
     }
-    iph = skb->nh.iph;
+
+    iph = CISCOVPN_SKB_IPHEADER(skb);
+
     if (!iph)
     {
-        printk(KERN_DEBUG "%s: skb->nh is NULL.", __FUNCTION__);
+        printk(KERN_DEBUG "%s: iph (IP Header) is NULL.", __FUNCTION__);
         goto done_with_tests;
     }
     offset = ntohs(iph->frag_off);
