From owner-freebsd-net@FreeBSD.ORG Sat Oct 7 17:12:02 2006 Return-Path: X-Original-To: freebsd-net@freebsd.org Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9364216A40F for ; Sat, 7 Oct 2006 17:12:02 +0000 (UTC) (envelope-from mav@alkar.net) Received: from cmail.optima.ua (cmail.optima.ua [195.248.191.121]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9DCDE43D60 for ; Sat, 7 Oct 2006 17:11:52 +0000 (GMT) (envelope-from mav@alkar.net) Received: from [195.248.178.122] (account mav@alkar.net HELO [192.168.3.5]) by cmail.optima.ua (CommuniGate Pro SMTP 5.0.11) with ESMTPA id 17103211; Sat, 07 Oct 2006 20:11:51 +0300 Message-ID: <4527DFD4.6010406@alkar.net> Date: Sat, 07 Oct 2006 20:11:48 +0300 From: Alexander Motin User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.13) Gecko/20060414 X-Accept-Language: en-us, en MIME-Version: 1.0 To: freebsd-net@freebsd.org Content-Type: multipart/mixed; boundary="------------070105060504030305010709" Subject: Does PPTP over IPv6 exists? X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Oct 2006 17:12:02 -0000 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 #include #include +#include #include #include @@ -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--