[Openswan dev] [patch] RHEL3 (26sec) + Openswan-2.2.0 + NAT-T + KLIPS

Matthew Callaway matt-openswan-dev at kindjal.net
Thu Oct 14 16:06:10 CEST 2004


The RHEL3 kernel (2.4.21-9.0.1.EL) has a 26sec backport of ipsec that
supports NAT-Traversal in a way that differs from that of Openswan.  If
you build Openswan (2.2.0) and try to apply the Openswan NAT-T patch, it
conflicts with RHEL3's.

I've produced a patch that I think will allow both implementations to
co-exist.  That is, you build RHEL3's ipsec support as modules, and you
build openswan (KLIPS) as a module.  Pick one, and either should work
with this patch.

I add this to RHEL3's kernel src.rpm as patch 9002 and add it in the
appropriate place in the patch sequence.  Then I make sure the kernel
config files build all ESP related material as modules.  The kernel
runs, the openswan 2.2.0 modules load, klips appears to work (I get
ipsec0 devices), and I get SAs to establish.

My testing has not been thorough yet, I was just excited to see that it
builds and appears to load properly.

Hopefully this will allow RHEL3 users to use Openswan-2.2.0 with KLIPS
and NAT-T.


MC
-------------- next part --------------
diff -ruN kernel-2.4.21.orig/linux-2.4.21/include/net/sock.h kernel-2.4.21/linux-2.4.21/include/net/sock.h
--- kernel-2.4.21.orig/linux-2.4.21/include/net/sock.h	2004-10-14 16:05:56.000000000 -0500
+++ kernel-2.4.21/linux-2.4.21/include/net/sock.h	2004-10-14 16:27:33.000000000 -0500
@@ -481,6 +481,7 @@
 	__u16		sport;		/* source port */
 	__u16		dport;		/* destination port */
 	__u16		len;		/* total length of pending frames */
+	__u32	esp_in_udp;
 };
  	
 /*
diff -ruN kernel-2.4.21.orig/linux-2.4.21/net/ipv4/udp.c kernel-2.4.21/linux-2.4.21/net/ipv4/udp.c
--- kernel-2.4.21.orig/linux-2.4.21/net/ipv4/udp.c	2004-10-14 16:06:02.000000000 -0500
+++ kernel-2.4.21/linux-2.4.21/net/ipv4/udp.c	2004-10-14 16:36:32.000000000 -0500
@@ -1100,6 +1100,7 @@
 static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 {
 	struct udp_opt *up = udp_sk(sk);
+	struct udp_opt *tp = &(sk->tp_pinfo.af_udp);
 
 	/*
 	 *	Charge it to the socket, dropping if the queue is full.
@@ -1149,6 +1150,41 @@
 	}
 #endif
 
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+	if (tp->esp_in_udp) {
+		/*
+		 * Set skb->sk and xmit packet to ipsec_rcv.
+		 *
+		 * If ret != 0, ipsec_rcv refused the packet (not ESPinUDP),
+		 * restore skb->sk and fall back to sock_queue_rcv_skb
+	 */
+		struct inet_protocol *esp = NULL;
+
+#if defined(CONFIG_IPSEC) && !defined(CONFIG_IPSEC_MODULE)
+		/* optomize only when we know it is statically linked */
+		extern struct inet_protocol esp_protocol;
+		esp = &esp_protocol;
+#else
+		for (esp = (struct inet_protocol *)inet_protos[IPPROTO_ESP & (MAX_INET_PROTOS - 1)];
+				(esp) && (esp->protocol != IPPROTO_ESP);
+				esp = esp->next);
+#endif
+
+		if (esp && esp->handler) {
+			struct sock *sav_sk = skb->sk;
+			skb->sk = sk;
+			if (esp->handler(skb) == 0) {
+				skb->sk = sav_sk;
+				/*not sure we might count ESPinUDP as UDP...*/
+				UDP_INC_STATS_BH(UdpInDatagrams);
+				return 0;
+			}
+			skb->sk = sav_sk;
+		}
+	}
+#endif
+
+
 	if (sock_queue_rcv_skb(sk,skb)<0) {
 		UDP_INC_STATS_BH(UdpInErrors);
 		IP_INC_STATS_BH(IpInDiscards);
@@ -1402,6 +1438,7 @@
 			  char *optval, int optlen)
 {
 	struct udp_opt *up = udp_sk(sk);
+	struct udp_opt *tp = &(sk->tp_pinfo.af_udp);
 	int val;
 	int err = 0;
 
@@ -1414,27 +1451,39 @@
 	if (get_user(val, (int *)optval))
 		return -EFAULT;
 
+	lock_sock(sk);
+
 	switch(optname) {
-	case UDP_CORK:
-		if (val != 0) {
-			up->corkflag = 1;
-		} else {
-			up->corkflag = 0;
-			lock_sock(sk);
-			udp_push_pending_frames(sk, up);
-			release_sock(sk);
-		}
-		break;
-		
-	case UDP_ENCAP:
-		up->encap_type = val;
-		break;
+		case UDP_CORK:
+			if (val != 0) {
+				up->corkflag = 1;
+			} else {
+				up->corkflag = 0;
+				lock_sock(sk);
+				udp_push_pending_frames(sk, up);
+				release_sock(sk);
+			}
+			break;
 
-	default:
-		err = -ENOPROTOOPT;
-		break;
+		case UDP_ENCAP:
+			up->encap_type = val;
+			break;
+
+#ifdef CONFIG_IPSEC_NAT_TRAVERSAL
+#ifndef UDP_ESPINUDP
+#define UDP_ESPINUDP 100
+#endif
+		case UDP_ESPINUDP:
+			tp->esp_in_udp = val;
+			break;
+#endif
+
+		default:
+			err = -ENOPROTOOPT;
+			break;
 	};
 
+	release_sock(sk);
 	return err;
 }
 


More information about the Dev mailing list