From owner-skip-info@rt.com  Wed Mar 11 04:38:56 1998
Return-Path: <owner-skip-info@rt.com>
Received: from linas.org (firewall.linas.org [10.50.1.1])
	by shadygrove.linas.org (8.8.4/8.8.7) with ESMTP id EAA18694
	for <linas@shadygrove.linas.org>; Wed, 11 Mar 1998 04:38:55 -0600
Received: from freeside.fc.net (freeside.fc.net [207.170.70.2]) by linas.org (8.8.4/8.7.3) with ESMTP id DAA31191 for <linas@linas.org>; Wed, 11 Mar 1998 03:29:16 -0600
Received: from xkey.com (xkey.com [207.126.116.160])
	by freeside.fc.net (8.8.8/8.8.8) with SMTP id DAA14074
	for <linas@fc.net>; Wed, 11 Mar 1998 03:26:24 -0600 (CST)
Received: (from majordomo@localhost) by xkey.com
	id WAA14722 for skip-info-outgoing; Tue, 10 Mar 1998 22:34:57 -0800
Received: (from smtp@localhost) by xkey.com
	id WAA14714 for <skip-info@skip.org>; Tue, 10 Mar 1998 22:34:56 -0800
Received: from sigge.signum.se(193.180.23.4) by xkey.com via smtp (V1.3)
	id sma014712; Tue Mar 10 22:34:47 1998
Received: from semlan (kina@semlan.signum.se [193.180.23.62])
	by sigge.signum.se (8.8.5/8.8.5) with ESMTP id HAA02690;
	Wed, 11 Mar 1998 07:34:30 +0100 (MET)
Date: Wed, 11 Mar 1998 07:35:34 +0100 (MET)
From: Kristina Holmqvist <kina@signum.se>
Reply-To: Kristina Holmqvist <kina@signum.se>
Subject: Re: Enskip for linux 2.0.33
To: Radovan Semancik <semancik@pubnet.sk>
cc: skip-info@skip.org
In-Reply-To: <34E6C147.C120395E@pubnet.sk>
Message-ID: <ML-3.3.889598134.249.kina@semlan>
MIME-Version: 1.0
Content-Type: MULTIPART/MIXED; BOUNDARY="-1262404073-1497742220-889598136=:25053"
Sender: owner-skip-info@rt.com
Precedence: bulk
Status: RO

---1262404073-1497742220-889598136=:25053
Content-Type: TEXT/PLAIN; CHARSET=US-ASCII

> 
> Is there an enskip linux kernel patch for kernel version 2.0.33 ?

You can find both a 2.0.32- and a 2.0.33-patch attached. But I guess that
you've already got one...

Regards, 

/Kristina Holmqvist


---1262404073-1497742220-889598136=:25053
Content-Type: TEXT/plain; CHARSET=US-ASCII
Content-Description: ENskip-linux-2.0.32.diff

--- linux/include/linux/firewall.h.orig	Thu Nov 21 10:36:10 1996
+++ linux/include/linux/firewall.h	Sun Nov 24 15:08:49 1996
@@ -5,22 +5,23 @@
  *	Definitions for loadable firewall modules
  */
 
-#define FW_BLOCK	0
-#define FW_ACCEPT	1
+#define FW_QUEUE	0
+#define FW_BLOCK	1
+#define FW_ACCEPT	2
 #define FW_REJECT	(-1)
-#define FW_REDIRECT	2
-#define FW_MASQUERADE	3
-#define FW_SKIP		4
+#define FW_REDIRECT	3
+#define FW_MASQUERADE	4
+#define FW_SKIP		5
 
 struct firewall_ops
 {
 	struct firewall_ops *next;
 	int (*fw_forward)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_input)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_output)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	/* Data falling in the second 486 cache line isn't used directly
 	   during a firewall call and scan, only by insert/delete and other
 	   unusual cases
@@ -32,9 +33,9 @@
 #ifdef __KERNEL__
 extern int register_firewall(int pf, struct firewall_ops *fw);
 extern int unregister_firewall(int pf, struct firewall_ops *fw);
-extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg);
-extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg);
-extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg);
+extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 extern void fwchain_init(void);
 #endif
 
--- linux/include/linux/ipsec.h.orig	Tue Nov 26 18:46:57 1996
+++ linux/include/linux/ipsec.h	Tue Nov 26 18:06:33 1996
@@ -0,0 +1,54 @@
+/*
+ *	Definitions for the SECurity layer
+ *
+ *	Author:
+ *		Robert Muchsel <muchsel@acm.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+ 
+#ifndef _LINUX_IPSEC_H
+#define _LINUX_IPSEC_H
+
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+
+/* Values for the set/getsockopt calls */
+
+/* These defines are compatible with NRL IPv6, however their semantics
+   is different */
+
+#define IPSEC_LEVEL_NONE	-1	/* send plaintext, accept any */
+#define IPSEC_LEVEL_DEFAULT	0	/* encrypt/authenticate if possible */
+					/* the default MUST be 0, because a */
+					/* socket is initialized with 0's */
+#define IPSEC_LEVEL_USE		1	/* use outbound, don't require inbound */
+#define IPSEC_LEVEL_REQUIRE	2	/* require both directions */
+#define IPSEC_LEVEL_UNIQUE	2	/* for compatibility only */
+
+#ifdef __KERNEL__
+
+/* skb bit flags set on packet input processing */
+
+#define RCV_SEC			0x01	/* options on receive */
+#define RCV_AUTH		0x02	/* was authenticated */
+#define RCV_CRYPT		0x04	/* was encrypted */
+#define RCV_TUNNEL		0x08	/* was tunneled */
+#define SND_SEC			0x10	/* options on send, these are */
+#define SND_AUTH		0x20	/* currently unused */
+#define SND_CRYPT		0x40
+#define SND_TUNNEL		0x80
+
+static __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb)
+{
+  return ((sk->authentication < IPSEC_LEVEL_REQUIRE) ||
+          (skb->proto_priv[15] & RCV_AUTH)) &&
+         ((sk->encryption < IPSEC_LEVEL_REQUIRE) ||
+	  (skb->proto_priv[15] & RCV_CRYPT));
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* _LINUX_IPSEC_H */
--- linux/include/net/sock.h.orig	Tue Nov 26 15:25:23 1996
+++ linux/include/net/sock.h	Tue Nov 26 17:08:36 1996
@@ -340,6 +340,13 @@
 	void			(*data_ready)(struct sock *sk,int bytes);
 	void			(*write_space)(struct sock *sk);
 	void			(*error_report)(struct sock *sk);
+
+   /*
+    *	Security
+    */
+
+	short			authentication;
+	short			encryption;
   
 };
 
--- linux/net/core/firewall.c.orig	Thu Nov 21 10:37:41 1996
+++ linux/net/core/firewall.c	Sun Nov 24 15:08:50 1996
@@ -99,13 +99,13 @@
 	return -ENOENT;
 }
 
-int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_forward(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_forward(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
@@ -117,13 +117,13 @@
  *	Actual invocation of the chains
  */
  
-int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_input(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_input(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
@@ -131,13 +131,13 @@
 	return firewall_policy[pf];
 }
 
-int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_output(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_output(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
--- linux/net/core/sock.c.orig	Wed Dec 17 07:35:16 1997
+++ linux/net/core/sock.c	Wed Dec 17 07:36:05 1997
@@ -235,6 +235,14 @@
 			sk->bsdism = valbool;
 			return 0;
 
+                case SO_SECURITY_AUTHENTICATION:
+                        sk->authentication = val;
+                        return 0;
+
+                case SO_SECURITY_ENCRYPTION_TRANSPORT:
+                        sk->encryption = val;
+                        return 0;
+
 #ifdef CONFIG_NET	
  	        case SO_BINDTODEVICE:
  			/* Bind this socket to a particular device like "eth0",
@@ -345,6 +353,14 @@
 		
 		case SO_BSDCOMPAT:
 			val = sk->bsdism;
+                        break;
+
+                case SO_SECURITY_AUTHENTICATION:
+                        val = sk->authentication;
+                        break;
+ 
+                case SO_SECURITY_ENCRYPTION_TRANSPORT:
+                        val = sk->encryption;
 			break;
 
 #ifdef CONFIG_NET
--- linux/net/ipv4/ip_output.c.orig	Tue Nov 26 16:19:29 1996
+++ linux/net/ipv4/ip_output.c	Tue Nov 26 16:02:00 1996
@@ -66,6 +66,7 @@
 #include <linux/firewall.h>
 #include <linux/mroute.h>
 #include <net/netlink.h>
+#include <linux/ipsec.h>
 
 /*
  *	Allows dynamic re-writing of packet's addresses.
@@ -488,9 +489,20 @@
 		goto no_device;
 
 #ifdef CONFIG_FIREWALL
-	if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+	if (call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
 		goto out;
 #endif	
+	/*
+	 *	Add an IP checksum (must do this before SECurity because
+	 *	of possible tunneling)
+	 */
+
+	ip_send_check(iph);
+
+	if (call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 4, &skb)<FW_ACCEPT)
+		goto out;
+	iph = skb->ip_hdr;
+	/* don't update tot_len, as the dev->mtu is already decreased */	
 
 	/*
 	 *	Do we need to fragment. Again this is inefficient.
@@ -501,11 +513,13 @@
 	if (tot_len > dev->mtu)
 		goto fragment;
 
+#if 0
 	/*
 	 *	Add an IP checksum
 	 */
 
 	ip_send_check(iph);
+#endif
 
 	/*
 	 *	More debugging. You cannot queue a packet already on a list
@@ -641,6 +655,9 @@
 	struct hh_cache * hh=NULL;
 	int nfrags=0;
 	__u32 true_daddr = daddr;
+#ifdef CONFIG_FIREWALL
+	int fw_res;
+#endif
 
 	if (opt && opt->srr && !sk->ip_hdrincl)
 	  daddr = opt->faddr;
@@ -766,12 +783,20 @@
 			getfrag(frag,saddr,(void *)iph,0,length);
 		dev_unlock_list();
 #ifdef CONFIG_FIREWALL
-		if(call_out_firewall(PF_INET, skb->dev, iph, NULL)< FW_ACCEPT)
+		if(call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb)<FW_ACCEPT)
 		{
 			kfree_skb(skb, FREE_WRITE);
 			return -EPERM;
 		}
 #endif
+		if ((fw_res=call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 5, &skb))<FW_ACCEPT)
+		{
+			kfree_skb(skb, FREE_WRITE);
+			if (fw_res != FW_QUEUE)
+				return -EPERM;
+			else
+				return 0;
+		}
 #ifdef CONFIG_IP_ACCT
 		ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
 #endif		
@@ -975,13 +1000,27 @@
 		 */
 		 
 #ifdef CONFIG_FIREWALL
-		if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+		if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
 		{
 			kfree_skb(skb, FREE_WRITE);
 			dev_unlock_list();
 			return -EPERM;
 		}
 #endif		
+		if ((fw_res=call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 6, &skb))<FW_ACCEPT)
+		{
+			kfree_skb(skb, FREE_WRITE);
+			if (fw_res != FW_QUEUE) {
+				dev_unlock_list();
+				return -EPERM;
+			}
+			else {
+				nfrags++;
+				offset -= (maxfraglen-fragheaderlen);
+				fraglen = maxfraglen;
+				continue;
+			}
+		}
 #ifdef CONFIG_IP_ACCT
 		ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
 #endif	
--- linux/net/ipv4/tcp_output.c.orig	Tue Nov 26 16:19:40 1996
+++ linux/net/ipv4/tcp_output.c	Tue Nov 26 16:10:26 1996
@@ -577,7 +577,7 @@
 			skb->dev=dev;
 			skb->arp=1;
 #ifdef CONFIG_FIREWALL
-        		if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT) {
+        		if (call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT) {
 				/* The firewall wants us to dump the packet.
 			 	* We have to check this here, because
 			 	* the drop in ip_queue_xmit only catches the
@@ -587,6 +587,18 @@
 				break;
         		}
 #endif 
+			/* We must add these fields before the call to SECurity layer
+			   because the TCP header might be gone afterwards... */
+			th->ack_seq = htonl(sk->acked_seq);
+			clear_delayed_acks(sk);
+			th->window = ntohs(tcp_select_window(sk));
+			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
+
+	        	if (call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 3, &skb)<FW_ACCEPT)
+				break;
+			iph = (struct iphdr *)skb->data;
+			size = ntohs(iph->tot_len) - (iph->ihl<<2);
+
 			if (rt->rt_hh)
 			{
 				memcpy(skb_push(skb,dev->hard_header_len),rt->rt_hh->hh_data,dev->hard_header_len);
@@ -604,6 +616,7 @@
 					skb->arp=0;
 			}
 		
+#if 0	
 			/*
 			 *	This is not the right way to handle this. We have to
 			 *	issue an up to date window and ack report with this 
@@ -619,6 +632,7 @@
 			clear_delayed_acks(sk);
 			th->window = ntohs(tcp_select_window(sk));
 			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
+#endif
 		
 			/*
 			 *	If the interface is (still) up and running, kick it.
--- linux/net/ipv4/tcp_input.c.orig	Tue Nov 26 16:42:14 1996
+++ linux/net/ipv4/tcp_input.c	Tue Nov 26 16:44:15 1996
@@ -42,6 +42,7 @@
 #include <linux/types.h>
 #include <linux/random.h>
 #include <net/tcp.h>
+#include <linux/ipsec.h>
 
 /*
  *	Policy code extracted so it's now separate
@@ -2313,6 +2314,8 @@
		sk = __tcp_v4_lookup(th, saddr, th->source, daddr, th->dest, dev);
 		if (!sk)
 			goto no_tcp_socket;
+		if (!ipsec_sk_policy(sk, skb))
+			goto discard_it; /* don't send RST (think!) */
 		skb->sk = sk;
 		skb->seq = ntohl(th->seq);
 		skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4;
--- linux/net/ipv4/udp.c.orig	Tue Nov 26 16:44:24 1996
+++ linux/net/ipv4/udp.c	Tue Nov 26 16:50:24 1996
@@ -114,6 +114,7 @@
 #include <net/icmp.h>
 #include <net/route.h>
 #include <net/checksum.h>
+#include <linux/ipsec.h>
 
 /*
  *	Snmp MIB for the UDP layer
@@ -1102,6 +1103,12 @@
 		kfree_skb(skb, FREE_WRITE);
 		return(0);
   	}
+	if (!ipsec_sk_policy(sk, skb)) /* discard the frame */
+	{
+		skb->sk = NULL;
+		kfree_skb(skb, FREE_WRITE);
+		return(0);
+	}
 	udp_deliver(sk, skb);
 	return 0;
 }
--- linux/include/linux/socket.h.orig	Sun May 25 17:17:45 1997
+++ linux/include/linux/socket.h	Sun May 25 17:27:39 1997
@@ -63,6 +63,7 @@
 #ifdef LINUX_2_1_X
 #define AF_INET6	10	/* IP version 6			*/
 #endif
+#define pseudo_AF_IPSEC	11	/* used for IPSEC callbacks	*/
 #define AF_MAX		12	/* For now.. */
 
 /* Protocol families, same as address families. */
@@ -76,6 +77,7 @@
 #define PF_BRIDGE	AF_BRIDGE
 #define PF_AAL5		AF_AAL5
 #define PF_X25		AF_X25
+#define PF_IPSEC	pseudo_AF_IPSEC
 #ifdef LINUX_2_1_X
 #define PF_INET6	AF_INET6
 #endif
@@ -132,6 +134,11 @@
 #define SOPRI_INTERACTIVE	0
 #define SOPRI_NORMAL		1
 #define SOPRI_BACKGROUND	2
+
+/* Socket options for the security layer (these are compatible with NRL IPv6) */
+#define SO_SECURITY_AUTHENTICATION		0x1009	/* set AH */
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	0x1010	/* set ESP */
+/* #define SO_SECURITY_ENCRYPTION_NETWORK	0x1011 -- unsupported */
 
 #ifdef __KERNEL__
 extern void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
--- linux/net/ipv4/ip_forward.c.orig	Sun May 25 17:18:01 1997
+++ linux/net/ipv4/ip_forward.c	Sun May 25 17:30:22 1997
@@ -40,6 +40,8 @@
 #include <linux/route.h>
 #include <net/route.h>
 
+#define CONFIG_IP_NO_ICMP_REDIRECT
+
 #ifdef CONFIG_IP_FORWARD /* set the default */
 int sysctl_ip_forward = 1; 
 #else
@@ -125,6 +127,7 @@
 	struct sk_buff *skb_in = skb;	/* So we can remember if the masquerader did some swaps */
 #endif /* CONFIG_IP_MASQUERADE */
 #endif /* CONFIG_FIREWALL */
+	unsigned short mtu;
 	
 	/*
 	 *	According to the RFC, we must first decrease the TTL field. If
@@ -292,7 +295,7 @@
 #endif				
 		}
 #endif
-		fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL);
+		fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
 		switch (fw_res) {
 		case FW_ACCEPT:
 		case FW_MASQUERADE:
@@ -310,6 +313,9 @@
 	}
 #endif
 
+	if (call_out_firewall(PF_IPSEC, dev2, NULL, (void *) 2, &skb)<FW_ACCEPT)
+		return -1;
+
 	/*
 	 * We now may allocate a new buffer, and copy the datagram into it.
 	 * If the indicated interface is up and running, kick it.
@@ -335,10 +341,13 @@
 #endif
 		IS_SKB(skb);
 
-		if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF))) 
+		mtu = dev2->mtu;
+		call_fw_firewall(PF_IPSEC, dev2, NULL, &mtu, NULL);
+
+		if (skb->len+encap > mtu && (iph->frag_off & htons(IP_DF))) 
 		{
 			ip_statistics.IpFragFails++;
-			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu), dev);
 			if(rt)
 				ip_rt_put(rt);
 			return -1;
@@ -446,7 +455,7 @@
 #endif			
 		}
 #ifdef CONFIG_FIREWALL
-		if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL)) < FW_ACCEPT)
+		if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL, &skb2)) < FW_ACCEPT)
 		{
 			/* FW_ACCEPT and FW_MASQUERADE are treated equal:
 			   masquerading is only supported via forward rules */
@@ -517,7 +526,7 @@
 		 *	the fragmenter does the right thing.
 		 */
 
-		if(skb2->len > dev2->mtu + dev2->hard_header_len)
+		if(skb2->len > mtu + dev2->hard_header_len)
 		{
 			ip_fragment(NULL,skb2,dev2, is_frag);
 			kfree_skb(skb2,FREE_WRITE);
--- linux/net/ipv4/ip_input.c.orig	Sun May 25 17:18:01 1997
+++ linux/net/ipv4/ip_input.c	Sun May 25 17:37:26 1997
@@ -159,6 +159,7 @@
 #ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
 #endif
+#include <linux/ipsec.h>
 
 extern int last_retran;
 extern void sort_send(struct sock *sk);
@@ -384,7 +385,7 @@
 	
 #ifdef	CONFIG_FIREWALL
 
-	if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))<FW_ACCEPT)
+	if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport, &skb))<FW_ACCEPT)
 	{
 		if(fwres==FW_REJECT)
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
@@ -602,7 +603,10 @@
 					else
 						break;	/* One pending raw socket left */
 					if(skb1)
-						raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr);
+ 						if(ipsec_sk_policy(raw_sk, skb1))
+ 							raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr);
+ 						else
+ 							kfree_skb(skb1, FREE_WRITE);
 					raw_sk = sknext;
 				} while(raw_sk!=NULL);
 				
@@ -692,7 +696,10 @@
 #endif		
 
 		if(raw_sk!=NULL)	/* Shift to last raw user */
-			raw_rcv(raw_sk, skb, dev, iph->saddr, daddr);
+			if(ipsec_sk_policy(raw_sk, skb))
+				raw_rcv(raw_sk, skb, dev, iph->saddr, daddr);
+			else
+				kfree_skb(skb, FREE_WRITE);
 		else if (!flag)		/* Free and report errors */
 		{
 			if (brd != IS_BROADCAST && brd!=IS_MULTICAST)

---1262404073-1497742220-889598136=:25053
Content-Type: TEXT/plain; CHARSET=US-ASCII
Content-Description: ENskip-linux-2.0.33.diff

--- linux/include/linux/firewall.h.orig	Thu Nov 21 10:36:10 1996
+++ linux/include/linux/firewall.h	Sun Nov 24 15:08:49 1996
@@ -5,22 +5,23 @@
  *	Definitions for loadable firewall modules
  */
 
-#define FW_BLOCK	0
-#define FW_ACCEPT	1
+#define FW_QUEUE	0
+#define FW_BLOCK	1
+#define FW_ACCEPT	2
 #define FW_REJECT	(-1)
-#define FW_REDIRECT	2
-#define FW_MASQUERADE	3
-#define FW_SKIP		4
+#define FW_REDIRECT	3
+#define FW_MASQUERADE	4
+#define FW_SKIP		5
 
 struct firewall_ops
 {
 	struct firewall_ops *next;
 	int (*fw_forward)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_input)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	int (*fw_output)(struct firewall_ops *this, int pf, 
-			struct device *dev, void *phdr, void *arg);
+			struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 	/* Data falling in the second 486 cache line isn't used directly
 	   during a firewall call and scan, only by insert/delete and other
 	   unusual cases
@@ -32,9 +33,9 @@
 #ifdef __KERNEL__
 extern int register_firewall(int pf, struct firewall_ops *fw);
 extern int unregister_firewall(int pf, struct firewall_ops *fw);
-extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg);
-extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg);
-extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg);
+extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
+extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb);
 extern void fwchain_init(void);
 #endif
 
--- linux/include/linux/ipsec.h.orig	Tue Nov 26 18:46:57 1996
+++ linux/include/linux/ipsec.h	Tue Nov 26 18:06:33 1996
@@ -0,0 +1,54 @@
+/*
+ *	Definitions for the SECurity layer
+ *
+ *	Author:
+ *		Robert Muchsel <muchsel@acm.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+ 
+#ifndef _LINUX_IPSEC_H
+#define _LINUX_IPSEC_H
+
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+
+/* Values for the set/getsockopt calls */
+
+/* These defines are compatible with NRL IPv6, however their semantics
+   is different */
+
+#define IPSEC_LEVEL_NONE	-1	/* send plaintext, accept any */
+#define IPSEC_LEVEL_DEFAULT	0	/* encrypt/authenticate if possible */
+					/* the default MUST be 0, because a */
+					/* socket is initialized with 0's */
+#define IPSEC_LEVEL_USE		1	/* use outbound, don't require inbound */
+#define IPSEC_LEVEL_REQUIRE	2	/* require both directions */
+#define IPSEC_LEVEL_UNIQUE	2	/* for compatibility only */
+
+#ifdef __KERNEL__
+
+/* skb bit flags set on packet input processing */
+
+#define RCV_SEC			0x01	/* options on receive */
+#define RCV_AUTH		0x02	/* was authenticated */
+#define RCV_CRYPT		0x04	/* was encrypted */
+#define RCV_TUNNEL		0x08	/* was tunneled */
+#define SND_SEC			0x10	/* options on send, these are */
+#define SND_AUTH		0x20	/* currently unused */
+#define SND_CRYPT		0x40
+#define SND_TUNNEL		0x80
+
+static __inline__ int ipsec_sk_policy(struct sock *sk, struct sk_buff *skb)
+{
+  return ((sk->authentication < IPSEC_LEVEL_REQUIRE) ||
+          (skb->proto_priv[15] & RCV_AUTH)) &&
+         ((sk->encryption < IPSEC_LEVEL_REQUIRE) ||
+	  (skb->proto_priv[15] & RCV_CRYPT));
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* _LINUX_IPSEC_H */
--- linux/include/net/sock.h.orig	Tue Nov 26 15:25:23 1996
+++ linux/include/net/sock.h	Tue Nov 26 17:08:36 1996
@@ -340,6 +340,13 @@
 	void			(*data_ready)(struct sock *sk,int bytes);
 	void			(*write_space)(struct sock *sk);
 	void			(*error_report)(struct sock *sk);
+
+   /*
+    *	Security
+    */
+
+	short			authentication;
+	short			encryption;
   
 };
 
--- linux/net/core/firewall.c.orig	Thu Nov 21 10:37:41 1996
+++ linux/net/core/firewall.c	Sun Nov 24 15:08:50 1996
@@ -99,13 +99,13 @@
 	return -ENOENT;
 }
 
-int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_forward(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_forward(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
@@ -117,13 +117,13 @@
  *	Actual invocation of the chains
  */
  
-int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_input(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_input(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
@@ -131,13 +131,13 @@
 	return firewall_policy[pf];
 }
 
-int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg)
+int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg, struct sk_buff **pskb)
 {
 	struct firewall_ops *fw=firewall_chain[pf];
 	
 	while(fw!=NULL)
 	{
-		int rc=fw->fw_output(fw,pf,dev,phdr,arg);
+		int rc=fw->fw_output(fw,pf,dev,phdr,arg,pskb);
 		if(rc!=FW_SKIP)
 			return rc;
 		fw=fw->next;
--- linux/net/core/sock.c.orig	Wed Dec 17 07:35:16 1997
+++ linux/net/core/sock.c	Wed Dec 17 07:36:05 1997
@@ -235,6 +235,14 @@
 			sk->bsdism = valbool;
 			return 0;
 
+                case SO_SECURITY_AUTHENTICATION:
+                        sk->authentication = val;
+                        return 0;
+
+                case SO_SECURITY_ENCRYPTION_TRANSPORT:
+                        sk->encryption = val;
+                        return 0;
+
 #ifdef CONFIG_NET	
  	        case SO_BINDTODEVICE:
  			/* Bind this socket to a particular device like "eth0",
@@ -345,6 +353,14 @@
 		
 		case SO_BSDCOMPAT:
 			val = sk->bsdism;
+                        break;
+
+                case SO_SECURITY_AUTHENTICATION:
+                        val = sk->authentication;
+                        break;
+ 
+                case SO_SECURITY_ENCRYPTION_TRANSPORT:
+                        val = sk->encryption;
 			break;
 
 #ifdef CONFIG_NET
--- linux/net/ipv4/ip_output.c.orig	Tue Nov 26 16:19:29 1996
+++ linux/net/ipv4/ip_output.c	Tue Nov 26 16:02:00 1996
@@ -66,6 +66,7 @@
 #include <linux/firewall.h>
 #include <linux/mroute.h>
 #include <net/netlink.h>
+#include <linux/ipsec.h>
 
 /*
  *	Allows dynamic re-writing of packet's addresses.
@@ -488,9 +489,20 @@
 		goto no_device;
 
 #ifdef CONFIG_FIREWALL
-	if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+	if (call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
 		goto out;
 #endif	
+	/*
+	 *	Add an IP checksum (must do this before SECurity because
+	 *	of possible tunneling)
+	 */
+
+	ip_send_check(iph);
+
+	if (call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 4, &skb)<FW_ACCEPT)
+		goto out;
+	iph = skb->ip_hdr;
+	/* don't update tot_len, as the dev->mtu is already decreased */	
 
 	/*
 	 *	Do we need to fragment. Again this is inefficient.
@@ -501,11 +513,13 @@
 	if (tot_len > dev->mtu)
 		goto fragment;
 
+#if 0
 	/*
 	 *	Add an IP checksum
 	 */
 
 	ip_send_check(iph);
+#endif
 
 	/*
 	 *	More debugging. You cannot queue a packet already on a list
@@ -641,6 +655,9 @@
 	struct hh_cache * hh=NULL;
 	int nfrags=0;
 	__u32 true_daddr = daddr;
+#ifdef CONFIG_FIREWALL
+	int fw_res;
+#endif
 
 	if (opt && opt->srr && !sk->ip_hdrincl)
 	  daddr = opt->faddr;
@@ -766,12 +783,20 @@
 			getfrag(frag,saddr,(void *)iph,0,length);
 		dev_unlock_list();
 #ifdef CONFIG_FIREWALL
-		if(call_out_firewall(PF_INET, skb->dev, iph, NULL)< FW_ACCEPT)
+		if(call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb)<FW_ACCEPT)
 		{
 			kfree_skb(skb, FREE_WRITE);
 			return -EPERM;
 		}
 #endif
+		if ((fw_res=call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 5, &skb))<FW_ACCEPT)
+		{
+			kfree_skb(skb, FREE_WRITE);
+			if (fw_res != FW_QUEUE)
+				return -EPERM;
+			else
+				return 0;
+		}
 #ifdef CONFIG_IP_ACCT
 		ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
 #endif		
@@ -975,13 +1000,27 @@
 		 */
 		 
 #ifdef CONFIG_FIREWALL
-		if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+		if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT)
 		{
 			kfree_skb(skb, FREE_WRITE);
 			dev_unlock_list();
 			return -EPERM;
 		}
 #endif		
+		if ((fw_res=call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 6, &skb))<FW_ACCEPT)
+		{
+			kfree_skb(skb, FREE_WRITE);
+			if (fw_res != FW_QUEUE) {
+				dev_unlock_list();
+				return -EPERM;
+			}
+			else {
+				nfrags++;
+				offset -= (maxfraglen-fragheaderlen);
+				fraglen = maxfraglen;
+				continue;
+			}
+		}
 #ifdef CONFIG_IP_ACCT
 		ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
 #endif	
--- linux/net/ipv4/tcp_output.c.orig	Tue Nov 26 16:19:40 1996
+++ linux/net/ipv4/tcp_output.c	Tue Nov 26 16:10:26 1996
@@ -577,7 +577,7 @@
 			skb->dev=dev;
 			skb->arp=1;
 #ifdef CONFIG_FIREWALL
-        		if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT) {
+        		if (call_out_firewall(PF_INET, skb->dev, iph, NULL, &skb) < FW_ACCEPT) {
 				/* The firewall wants us to dump the packet.
 			 	* We have to check this here, because
 			 	* the drop in ip_queue_xmit only catches the
@@ -587,6 +587,18 @@
 				break;
         		}
 #endif 
+			/* We must add these fields before the call to SECurity layer
+			   because the TCP header might be gone afterwards... */
+			th->ack_seq = htonl(sk->acked_seq);
+			clear_delayed_acks(sk);
+			th->window = ntohs(tcp_select_window(sk));
+			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
+
+	        	if (call_out_firewall(PF_IPSEC, skb->dev, NULL, (void *) 3, &skb)<FW_ACCEPT)
+				break;
+			iph = (struct iphdr *)skb->data;
+			size = ntohs(iph->tot_len) - (iph->ihl<<2);
+
 			if (rt->rt_hh)
 			{
 				memcpy(skb_push(skb,dev->hard_header_len),rt->rt_hh->hh_data,dev->hard_header_len);
@@ -604,6 +616,7 @@
 					skb->arp=0;
 			}
 		
+#if 0	
 			/*
 			 *	This is not the right way to handle this. We have to
 			 *	issue an up to date window and ack report with this 
@@ -619,6 +632,7 @@
 			clear_delayed_acks(sk);
 			th->window = ntohs(tcp_select_window(sk));
 			tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
+#endif
 		
 			/*
 			 *	If the interface is (still) up and running, kick it.
--- linux/net/ipv4/tcp_input.c.orig	Tue Nov 26 16:42:14 1996
+++ linux/net/ipv4/tcp_input.c	Tue Nov 26 16:44:15 1996
@@ -42,6 +42,7 @@
 #include <linux/types.h>
 #include <linux/random.h>
 #include <net/tcp.h>
+#include <linux/ipsec.h>
 
 /*
  *	Policy code extracted so it's now separate
@@ -2313,6 +2314,8 @@
		sk = __tcp_v4_lookup(th, saddr, th->source, daddr, th->dest, dev);
 		if (!sk)
 			goto no_tcp_socket;
+		if (!ipsec_sk_policy(sk, skb))
+			goto discard_it; /* don't send RST (think!) */
 		skb->sk = sk;
 		skb->seq = ntohl(th->seq);
 		skb->end_seq = skb->seq + th->syn + th->fin + len - th->doff*4;
--- linux/net/ipv4/udp.c.orig	Tue Nov 26 16:44:24 1996
+++ linux/net/ipv4/udp.c	Tue Nov 26 16:50:24 1996
@@ -115,6 +115,7 @@
 #include <net/icmp.h>
 #include <net/route.h>
 #include <net/checksum.h>
+#include <linux/ipsec.h>
 
 /*
  *	Snmp MIB for the UDP layer
@@ -1105,6 +1105,12 @@
 		kfree_skb(skb, FREE_WRITE);
 		return(0);
   	}
+	if (!ipsec_sk_policy(sk, skb)) /* discard the frame */
+	{
+		skb->sk = NULL;
+		kfree_skb(skb, FREE_WRITE);
+		return(0);
+	}
 	udp_deliver(sk, skb);
 	return 0;
 }
--- linux/include/linux/socket.h.orig	Sun May 25 17:17:45 1997
+++ linux/include/linux/socket.h	Sun May 25 17:27:39 1997
@@ -63,6 +63,7 @@
 #ifdef LINUX_2_1_X
 #define AF_INET6	10	/* IP version 6			*/
 #endif
+#define pseudo_AF_IPSEC	11	/* used for IPSEC callbacks	*/
 #define AF_MAX		12	/* For now.. */
 
 /* Protocol families, same as address families. */
@@ -76,6 +77,7 @@
 #define PF_BRIDGE	AF_BRIDGE
 #define PF_AAL5		AF_AAL5
 #define PF_X25		AF_X25
+#define PF_IPSEC	pseudo_AF_IPSEC
 #ifdef LINUX_2_1_X
 #define PF_INET6	AF_INET6
 #endif
@@ -132,6 +134,11 @@
 #define SOPRI_INTERACTIVE	0
 #define SOPRI_NORMAL		1
 #define SOPRI_BACKGROUND	2
+
+/* Socket options for the security layer (these are compatible with NRL IPv6) */
+#define SO_SECURITY_AUTHENTICATION		0x1009	/* set AH */
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	0x1010	/* set ESP */
+/* #define SO_SECURITY_ENCRYPTION_NETWORK	0x1011 -- unsupported */
 
 #ifdef __KERNEL__
 extern void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
--- linux/net/ipv4/ip_forward.c	Thu Dec 11 03:13:49 1997
+++ linux/net/ipv4/ip_forward.c	Thu Jan 22 09:34:39 1998
@@ -41,6 +41,8 @@
 #include <linux/route.h>
 #include <net/route.h>
 
+#define CONFIG_IP_NO_ICMP_REDIRECT
+
 #ifdef CONFIG_IP_FORWARD /* set the default */
 int sysctl_ip_forward = 1; 
 #else
@@ -126,6 +128,7 @@
 	struct sk_buff *skb_in = skb;	/* So we can remember if the masquerader did some swaps */
 #endif /* CONFIG_IP_MASQUERADE */
 #endif /* CONFIG_FIREWALL */
+	unsigned short mtu;
 	
 	/*
 	 *	According to the RFC, we must first decrease the TTL field. If
@@ -293,7 +296,7 @@
 #endif				
 		}
 #endif
-		fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL);
+		fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL, &skb);
 		switch (fw_res) {
 		case FW_ACCEPT:
 		case FW_MASQUERADE:
@@ -313,6 +316,9 @@
 	}
 #endif
 
+	if (call_out_firewall(PF_IPSEC, dev2, NULL, (void *) 2, &skb)<FW_ACCEPT)
+		return -1;
+
 	/*
 	 * We now may allocate a new buffer, and copy the datagram into it.
 	 * If the indicated interface is up and running, kick it.
@@ -349,7 +355,10 @@
 #endif
 		IS_SKB(skb);
 
-		if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF))) 
+		mtu = dev2->mtu;
+		call_fw_firewall(PF_IPSEC, dev2, NULL, &mtu, NULL);
+
+		if (skb->len+encap > mtu && (iph->frag_off & htons(IP_DF))) 
 		{
 			ip_statistics.IpFragFails++;
 #ifdef CONFIG_IP_MASQUERADE
@@ -371,10 +380,10 @@
 
 			if (premasq_len_diff < 0)
 				icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
-					  htonl(dev2->mtu+premasq_len_diff), dev);
+					  htonl(mtu+premasq_len_diff), dev);
 			else
 #endif
-			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
+			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu), dev);
 			if(rt)
 				ip_rt_put(rt);
 			return -1;
@@ -482,7 +491,7 @@
 #endif			
 		}
 #ifdef CONFIG_FIREWALL
-		if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL)) < FW_ACCEPT)
+		if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL, &skb2)) < FW_ACCEPT)
 		{
 			/* FW_ACCEPT and FW_MASQUERADE are treated equal:
 			   masquerading is only supported via forward rules */
@@ -555,7 +564,7 @@
 		 *	the fragmenter does the right thing.
 		 */
 
-		if(skb2->len > dev2->mtu + dev2->hard_header_len)
+		if(skb2->len > mtu + dev2->hard_header_len)
 		{
 			ip_fragment(NULL,skb2,dev2, is_frag);
 			kfree_skb(skb2,FREE_WRITE);
--- linux/net/ipv4/ip_input.c.orig	Sun May 25 17:18:01 1997
+++ linux/net/ipv4/ip_input.c	Sun May 25 17:37:26 1997
@@ -159,6 +159,7 @@
 #ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
 #endif
+#include <linux/ipsec.h>
 
 extern int last_retran;
 extern void sort_send(struct sock *sk);
@@ -384,7 +385,7 @@
 	
 #ifdef	CONFIG_FIREWALL
 
-	if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))<FW_ACCEPT)
+	if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport, &skb))<FW_ACCEPT)
 	{
 		if(fwres==FW_REJECT)
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
@@ -602,7 +603,10 @@
 					else
 						break;	/* One pending raw socket left */
 					if(skb1)
-						raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr);
+ 						if(ipsec_sk_policy(raw_sk, skb1))
+ 							raw_rcv(raw_sk, skb1, dev, iph->saddr,daddr);
+ 						else
+ 							kfree_skb(skb1, FREE_WRITE);
 					raw_sk = sknext;
 				} while(raw_sk!=NULL);
 				
@@ -692,7 +696,10 @@
 #endif		
 
 		if(raw_sk!=NULL)	/* Shift to last raw user */
-			raw_rcv(raw_sk, skb, dev, iph->saddr, daddr);
+			if(ipsec_sk_policy(raw_sk, skb))
+				raw_rcv(raw_sk, skb, dev, iph->saddr, daddr);
+			else
+				kfree_skb(skb, FREE_WRITE);
 		else if (!flag)		/* Free and report errors */
 		{
 			if (brd != IS_BROADCAST && brd!=IS_MULTICAST)

---1262404073-1497742220-889598136=:25053--

