Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 07 Oct 2006 20:11:48 +0300
From:      Alexander Motin <mav@alkar.net>
To:        freebsd-net@freebsd.org
Subject:   Does PPTP over IPv6 exists?
Message-ID:  <4527DFD4.6010406@alkar.net>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------070105060504030305010709
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Hi.

Last week I have made many changes in mpd4 CVS to enable IPv6 support. 
As result, IPV6CP and IPv6 console is now supported, TCP and UDP link 
types perfectly work over IPv6.

But when I have touched PPTP, I have found two problems:
1. There seems like no special support for inet6/raw/gre in kernel, so 
at the beginning, when GRE packets pass through ipfw, ipfw can't 
recognize header 47(GRE), and then, if using sysctl I allow them to 
pass, ng_pptpgre is getting them without IP header.
2. There is no support for IPv6 in ng_pptpgre, so it tries to cut 
unexisting IPv4 header from packet.

I have not found in Internet any documents about specific suport of PPTP 
over IPv6, but I also have not found that it must not work. And I have a 
stupid question: "Should PPTP at all work over IPv6?".

Does anybody know something about PPTP and IPv6? What side is right: it 
should work, but nobody try to do it yet, or it should work in different 
way, or it should not work at all?

When I have tried to fix ng_pptpgre with patch in attachment and allowed 
ipfw to pass unknown packets, mpd4 was able to successfully make PPTP 
connection over IPv6 and transmit both IPv4 and IPv6 packets. So, it 
should do it or not?

-- 
Alexander Motin

--------------070105060504030305010709
Content-Type: text/plain;
 name="ng_pptpgre.c.patch2"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="ng_pptpgre.c.patch2"

--- ng_pptpgre.c.orig	Tue Sep 20 16:40:55 2005
+++ ng_pptpgre.c	Sat Oct  7 18:53:04 2006
@@ -67,6 +67,7 @@
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 
 #include <netgraph/ng_message.h>
 #include <netgraph/netgraph.h>
@@ -588,6 +589,7 @@
 	int iphlen, grelen, extralen;
 	const struct greheader *gre;
 	const struct ip *ip;
+	const u_int8_t *ipv;
 	int error = 0;
 	struct mbuf *m;
 
@@ -598,40 +600,89 @@
 	priv->stats.recvPackets++;
 	priv->stats.recvOctets += m->m_pkthdr.len;
 
+	/* Get the first byte to identify protocol */
 	/* Sanity check packet length */
-	if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
+	if (m->m_pkthdr.len < 1) {
 		priv->stats.recvRunts++;
 		ERROUT(EINVAL);
 	}
 
-	/* Safely pull up the complete IP+GRE headers */
-	if (m->m_len < sizeof(*ip) + sizeof(*gre)
-	    && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
+	/* Safely pull up the first byte of headers */
+	if (m->m_len < 1
+	    && (m = m_pullup(m, 1)) == NULL) {
 		priv->stats.memoryFailures++;
 		ERROUT(ENOBUFS);
 	}
-	ip = mtod(m, const struct ip *);
-	iphlen = ip->ip_hl << 2;
-	if (m->m_len < iphlen + sizeof(*gre)) {
-		if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
+	ipv = mtod(m, const u_int8_t *);
+	
+	if ((((*ipv)&IPV6_VERSION_MASK)==0x40) && (((*ipv)&(~IPV6_VERSION_MASK))>=5)) { 
+	    /* There is IPv4 header, remove it */
+
+		/* Sanity check packet length */
+		if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
+			priv->stats.recvRunts++;
+			ERROUT(EINVAL);
+		}
+
+		/* Safely pull up the complete IP+GRE headers */
+		if (m->m_len < sizeof(*ip) + sizeof(*gre)
+		    && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
 			priv->stats.memoryFailures++;
 			ERROUT(ENOBUFS);
 		}
 		ip = mtod(m, const struct ip *);
-	}
-	gre = (const struct greheader *)((const u_char *)ip + iphlen);
-	grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
-	if (m->m_pkthdr.len < iphlen + grelen) {
-		priv->stats.recvRunts++;
-		ERROUT(EINVAL);
-	}
-	if (m->m_len < iphlen + grelen) {
-		if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
+		iphlen = ip->ip_hl << 2;
+		if (m->m_len < iphlen + sizeof(*gre)) {
+			if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
+				priv->stats.memoryFailures++;
+				ERROUT(ENOBUFS);
+			}
+			ip = mtod(m, const struct ip *);
+		}
+		gre = (const struct greheader *)((const u_char *)ip + iphlen);
+		grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
+		if (m->m_pkthdr.len < iphlen + grelen) {
+			priv->stats.recvRunts++;
+			ERROUT(EINVAL);
+		}
+		if (m->m_len < iphlen + grelen) {
+			if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
+				priv->stats.memoryFailures++;
+				ERROUT(ENOBUFS);
+			}
+			ip = mtod(m, const struct ip *);
+			gre = (const struct greheader *)((const u_char *)ip + iphlen);
+		}
+	} else {
+	    /* There is no IPv4 header */
+
+		/* Sanity check packet length */
+		if (m->m_pkthdr.len < sizeof(*gre)) {
+			priv->stats.recvRunts++;
+			ERROUT(EINVAL);
+		}
+
+		/* Safely pull up the complete GRE headers */
+		if (m->m_len < sizeof(*gre)
+		    && (m = m_pullup(m, sizeof(*gre))) == NULL) {
 			priv->stats.memoryFailures++;
 			ERROUT(ENOBUFS);
 		}
-		ip = mtod(m, const struct ip *);
-		gre = (const struct greheader *)((const u_char *)ip + iphlen);
+		iphlen = 0;
+		gre = mtod(m, const struct greheader *);
+		grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
+		if (m->m_pkthdr.len < grelen) {
+			priv->stats.recvRunts++;
+			ERROUT(EINVAL);
+		}
+		if (m->m_len < grelen) {
+			if ((m = m_pullup(m, grelen)) == NULL) {
+				priv->stats.memoryFailures++;
+				ERROUT(ENOBUFS);
+			}
+			gre = mtod(m, const struct greheader *);
+		}
+		
 	}
 
 	/* Sanity check packet length and GRE header bits */

--------------070105060504030305010709--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4527DFD4.6010406>