Hello,
i had a problem with tcp on ipv6 through openvpn. The problem is that
the ipv6 mssfix is not implemented. So i added these to the
openvpn-2.0.2 software.
I attach the patch to this email.
I tried hard to adapted to the codeing style but there could be some
faults.
I only tested it on macos x and freebsd so there are some other
platforms to go.
One major change is that I renamed the openvpn_iphdr structure to
openvpn_ip4hdr
and added the openvpn_ip6hdr which are now both needed.
Have fun
meno
diff -ur openvpn-2.0.2.orig/forward.c
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/forward.c
--- openvpn-2.0.2.orig/forward.c Thu Aug 4 05:22:16 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/forward.c
Sun Oct 23 04:29:09 2005
@@ -878,7 +878,7 @@
* The --passtos and --mssfix options require
* us to examine the IPv4 header.
*/
- process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX, &c->c2.buf);
+ process_ip_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX, &c->c2.buf);
encrypt_sign (c, true);
}
else
@@ -890,7 +890,7 @@
}
void
-process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
+process_ip_header (struct context *c, unsigned int flags, struct buffer *buf)
{
if (!c->options.mssfix)
flags &= ~PIPV4_MSSFIX;
@@ -912,17 +912,22 @@
#endif
{
struct buffer ipbuf = *buf;
- if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
+ switch (get_ipversion(TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
{
+ case OPENVPN_PROTO_IPV4:
#if PASSTOS_CAPABILITY
- /* extract TOS from IP header */
- if (flags & PIPV4_PASSTOS)
- link_socket_extract_tos (c->c2.link_socket, &ipbuf);
-#endif
-
- /* possibly alter the TCP MSS */
- if (flags & PIPV4_MSSFIX)
- mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC
(&c->c2.frame)));
+ /* extract TOS from IP header */
+ if (flags & PIPV4_PASSTOS)
+ link_socket_extract_tos (c->c2.link_socket, &ipbuf);
+#endif
+ /* possibly alter the TCP MSS */
+ if (flags & PIPV4_MSSFIX)
+ mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC
(&c->c2.frame)));
+ break;
+ case OPENVPN_PROTO_IPV6:
+ if (flags & PIPV4_MSSFIX)
+ mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC
(&c->c2.frame)));
+
}
}
}
@@ -1061,7 +1066,7 @@
* The --mssfix option requires
* us to examine the IPv4 header.
*/
- process_ipv4_header (c, PIPV4_MSSFIX, &c->c2.to_tun);
+ process_ip_header (c, PIPV4_MSSFIX, &c->c2.to_tun);
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
{
diff -ur openvpn-2.0.2.orig/forward.h
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/forward.h
--- openvpn-2.0.2.orig/forward.h Mon Apr 11 05:43:58 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/forward.h
Sun Oct 23 04:25:30 2005
@@ -75,7 +75,7 @@
#define PIPV4_PASSTOS (1<<0)
#define PIPV4_MSSFIX (1<<1)
-void process_ipv4_header (struct context *c, unsigned int flags, struct buffer
*buf);
+void process_ip_header (struct context *c, unsigned int flags, struct buffer
*buf);
#if P2MP
void schedule_exit (struct context *c, const int n_seconds);
diff -ur openvpn-2.0.2.orig/mroute.c
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mroute.c
--- openvpn-2.0.2.orig/mroute.c Thu Aug 4 01:58:52 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mroute.c
Sun Oct 23 04:40:00 2005
@@ -101,9 +101,9 @@
switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
{
case 4:
- if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
+ if (BLEN (buf) >= (int) sizeof (struct openvpn_ip4hdr))
{
- const struct openvpn_iphdr *ip = (const struct openvpn_iphdr
*) BPTR (buf);
+ const struct openvpn_ip4hdr *ip = (const struct
openvpn_ip4hdr *) BPTR (buf);
if (src)
{
src->type = MR_ADDR_IPV4;
diff -ur openvpn-2.0.2.orig/mss.c
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mss.c
--- openvpn-2.0.2.orig/mss.c Mon Apr 11 05:43:55 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mss.c
Sun Oct 23 05:27:23 2005
@@ -39,16 +39,16 @@
* encapsulation.
*/
void
-mss_fixup (struct buffer *buf, int maxmss)
+mss_fixup_ipv4 (struct buffer *buf, int maxmss)
{
- const struct openvpn_iphdr *pip;
+ const struct openvpn_ip4hdr *pip;
int hlen;
- if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr))
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ip4hdr))
return;
verify_align_4 (buf);
- pip = (struct openvpn_iphdr *) BPTR (buf);
+ pip = (struct openvpn_ip4hdr *) BPTR (buf);
hlen = OPENVPN_IPH_GET_LEN (pip->version_len);
@@ -70,6 +70,31 @@
}
void
+mss_fixup_ipv6 (struct buffer *buf, int maxmss)
+{
+ const struct openvpn_ip6hdr *pip;
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ip6hdr))
+ return;
+
+ verify_align_4 (buf);
+ pip = (struct openvpn_ip6hdr *) BPTR (buf);
+ if (pip->ip6_ctlun.ip6_un1.ip6_un1_nxt == OPENVPN_IPPROTO_TCP
+ && ntohs (pip->ip6_ctlun.ip6_un1.ip6_un1_plen)
+ == BLEN (buf) - sizeof(struct openvpn_ip6hdr)
+ && BLEN(buf) - sizeof(struct openvpn_ip6hdr)
+ >= (int) sizeof (struct openvpn_tcphdr))
+ {
+ struct buffer newbuf = *buf;
+ if (buf_advance (&newbuf, sizeof(struct openvpn_ip6hdr)))
+ {
+ struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
+ if (tc->flags & OPENVPN_TCPH_SYN_MASK)
+ mss_fixup_dowork (&newbuf, (uint16_t) maxmss);
+ }
+ }
+}
+
+void
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
{
int hlen, olen, optlen;
@@ -118,3 +143,4 @@
}
}
}
+
diff -ur openvpn-2.0.2.orig/mss.h
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mss.h
--- openvpn-2.0.2.orig/mss.h Mon Apr 11 05:43:55 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/mss.h
Sun Oct 23 04:29:29 2005
@@ -28,7 +28,8 @@
#include "proto.h"
#include "error.h"
-void mss_fixup (struct buffer *buf, int maxmss);
+void mss_fixup_ipv4 (struct buffer *buf, int maxmss);
+void mss_fixup_ipv6 (struct buffer *buf, int maxmss);
void mss_fixup_dowork (struct buffer *buf, uint16_t maxmss);
#endif
diff -ur openvpn-2.0.2.orig/multi.c
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/multi.c
--- openvpn-2.0.2.orig/multi.c Thu Aug 4 01:59:32 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/multi.c
Sun Oct 23 04:25:53 2005
@@ -1809,7 +1809,7 @@
item.instance->context.c2.buf = item.buffer->buf;
if (item.buffer->flags & MF_UNICAST) /* --mssfix doesn't make sense for
broadcast or multicast */
pipv4_flags |= PIPV4_MSSFIX;
- process_ipv4_header (&item.instance->context, pipv4_flags,
&item.instance->context.c2.buf);
+ process_ip_header (&item.instance->context, pipv4_flags,
&item.instance->context.c2.buf);
encrypt_sign (&item.instance->context, true);
mbuf_free_buf (item.buffer);
diff -ur openvpn-2.0.2.orig/proto.c
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/proto.c
--- openvpn-2.0.2.orig/proto.c Mon Apr 11 05:43:58 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/proto.c
Sun Oct 23 05:23:02 2005
@@ -31,6 +31,7 @@
#include "syshead.h"
#include "proto.h"
+#include "errlevel.h"
#include "memdbg.h"
@@ -38,37 +39,41 @@
* If raw tunnel packet is IPv4, return true and increment
* buffer offset to start of IP header.
*/
-bool
-is_ipv4 (int tunnel_type, struct buffer *buf)
+int
+get_ipversion (int tunnel_type, struct buffer *buf)
{
int offset;
- const struct openvpn_iphdr *ih;
+ uint8_t version;
verify_align_4 (buf);
if (tunnel_type == DEV_TYPE_TUN)
{
- if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr))
- return false;
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ip4hdr))
+ return OPENVPN_PROTO_UNK;
offset = 0;
}
else if (tunnel_type == DEV_TYPE_TAP)
{
const struct openvpn_ethhdr *eh;
if (BLEN (buf) < (int)(sizeof (struct openvpn_ethhdr)
- + sizeof (struct openvpn_iphdr)))
+ + sizeof (struct openvpn_ip4hdr)))
return false;
eh = (const struct openvpn_ethhdr *) BPTR (buf);
- if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4)
- return false;
+ if (!(ntohs (eh->proto) == OPENVPN_ETH_P_IPV4 ||
+ ntohs (eh->proto) == OPENVPN_ETH_P_IPV6 ))
+ return OPENVPN_PROTO_UNK;
offset = sizeof (struct openvpn_ethhdr);
}
else
- return false;
-
- ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset);
+ return OPENVPN_PROTO_UNK;
- if (OPENVPN_IPH_GET_VER (ih->version_len) == 4)
- return buf_advance (buf, offset);
+ version = (*((uint8_t *)(BPTR (buf) + offset)) >> 4) & 0xf;
+ if (version == OPENVPN_PROTO_IPV4 || version == OPENVPN_PROTO_IPV6)
+ {
+ if (!buf_advance (buf, offset))
+ return OPENVPN_PROTO_UNK;
+ return version;
+ }
else
- return false;
+ return OPENVPN_PROTO_UNK;
}
diff -ur openvpn-2.0.2.orig/proto.h
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/proto.h
--- openvpn-2.0.2.orig/proto.h Mon Apr 11 05:43:58 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/proto.h
Sun Oct 23 04:39:34 2005
@@ -54,7 +54,7 @@
uint16_t proto; /* packet type ID field */
};
-struct openvpn_iphdr {
+struct openvpn_ip4hdr {
# define OPENVPN_IPH_GET_VER(v) (((v) >> 4) & 0x0F)
# define OPENVPN_IPH_GET_LEN(v) (((v) & 0x0F) << 2)
uint8_t version_len;
@@ -79,6 +79,27 @@
/*The options start here. */
};
+struct openvpn_in6_addr {
+ union {
+ uint8_t __u6_addr8[16];
+ uint16_t __u6_addr16[8];
+ uint32_t __u6_addr32[4];
+ } __u6_addr; /* 128-bit IP6 address */
+};
+struct openvpn_ip6hdr {
+ union {
+ struct ip6_hdrctl {
+ uint32_t ip6_un1_flow; /* 20 bits of flow-ID */
+ uint16_t ip6_un1_plen; /* payload length */
+ uint8_t ip6_un1_nxt; /* next header */
+ uint8_t ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */
+ } ip6_ctlun;
+ struct openvpn_in6_addr ip6_src; /* source address */
+ struct openvpn_in6_addr ip6_dst; /* destination address */
+};
+
/*
* UDP header
*/
@@ -151,13 +172,18 @@
*
* (RFC 879, section 7).
*/
-#define MTU_TO_MSS(mtu) (mtu - sizeof(struct openvpn_iphdr) \
+#define MTU_TO_MSS(mtu) (mtu - sizeof(struct openvpn_ip4hdr) \
- sizeof(struct openvpn_tcphdr))
/*
- * If raw tunnel packet is IPv4, return true and increment
+ * Check if raw tunnel packet is IPv4 or IPv6,
+ * return the version and increment
* buffer offset to start of IP header.
*/
-bool is_ipv4 (int tunnel_type, struct buffer *buf);
+
+#define OPENVPN_PROTO_IPV6 6
+#define OPENVPN_PROTO_IPV4 4
+#define OPENVPN_PROTO_UNK 0
+int get_ipversion(int tunnel_type, struct buffer *buf);
#endif
diff -ur openvpn-2.0.2.orig/socket.h
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/socket.h
--- openvpn-2.0.2.orig/socket.h Sat Apr 30 10:49:21 2005
+++
/jails/jails/neo/obj/ports/usr/ports/security/openvpn/work/openvpn-2.0.2/socket.h
Sun Oct 23 04:40:37 2005
@@ -735,7 +735,7 @@
{
if (ls && ipbuf)
{
- struct openvpn_iphdr *iph = (struct openvpn_iphdr *) BPTR (ipbuf);
+ struct openvpn_ip4hdr *iph = (struct openvpn_ip4hdr *) BPTR (ipbuf);
ls->ptos = iph->tos;
ls->ptos_defined = true;
}