Rename process_ipv4_header() to process_ip_header() and PIPV4_MSSFIX
flag to PIP_MSSFIX, to make visible that it's no longer IPv4-only.
Inside process_ip_header(), call out to mss_fixup_ipv6() if --mssfix
is active and IPv6 packet seen.
Rename mss_fixup() to mss_fixup_ipv4(), implement mss_fixup_ipv6().
Signed-off-by: Gert Doering <gert@greenie.muc.de>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: 1354482672-16136-2-git-send-email-gert@greenie.muc.de
URL: http://article.gmane.org/gmane.network.openvpn.devel/7173
Signed-off-by: David Sommerseth <davids@redhat.com>
... | ... |
@@ -985,9 +985,9 @@ process_incoming_tun (struct context *c) |
985 | 985 |
{ |
986 | 986 |
/* |
987 | 987 |
* The --passtos and --mssfix options require |
988 |
- * us to examine the IPv4 header. |
|
988 |
+ * us to examine the IP header (IPv4 or IPv6). |
|
989 | 989 |
*/ |
990 |
- process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf); |
|
990 |
+ process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf); |
|
991 | 991 |
|
992 | 992 |
#ifdef PACKET_TRUNCATION_CHECK |
993 | 993 |
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */ |
... | ... |
@@ -1009,10 +1009,10 @@ process_incoming_tun (struct context *c) |
1009 | 1009 |
} |
1010 | 1010 |
|
1011 | 1011 |
void |
1012 |
-process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf) |
|
1012 |
+process_ip_header (struct context *c, unsigned int flags, struct buffer *buf) |
|
1013 | 1013 |
{ |
1014 | 1014 |
if (!c->options.ce.mssfix) |
1015 |
- flags &= ~PIPV4_MSSFIX; |
|
1015 |
+ flags &= ~PIP_MSSFIX; |
|
1016 | 1016 |
#if PASSTOS_CAPABILITY |
1017 | 1017 |
if (!c->options.passtos) |
1018 | 1018 |
flags &= ~PIPV4_PASSTOS; |
... | ... |
@@ -1027,9 +1027,9 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf) |
1027 | 1027 |
* us to examine the IPv4 header. |
1028 | 1028 |
*/ |
1029 | 1029 |
#if PASSTOS_CAPABILITY |
1030 |
- if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX)) |
|
1030 |
+ if (flags & (PIPV4_PASSTOS|PIP_MSSFIX)) |
|
1031 | 1031 |
#else |
1032 |
- if (flags & PIPV4_MSSFIX) |
|
1032 |
+ if (flags & PIP_MSSFIX) |
|
1033 | 1033 |
#endif |
1034 | 1034 |
{ |
1035 | 1035 |
struct buffer ipbuf = *buf; |
... | ... |
@@ -1042,8 +1042,8 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf) |
1042 | 1042 |
#endif |
1043 | 1043 |
|
1044 | 1044 |
/* possibly alter the TCP MSS */ |
1045 |
- if (flags & PIPV4_MSSFIX) |
|
1046 |
- mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); |
|
1045 |
+ if (flags & PIP_MSSFIX) |
|
1046 |
+ mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); |
|
1047 | 1047 |
|
1048 | 1048 |
#ifdef ENABLE_CLIENT_NAT |
1049 | 1049 |
/* possibly do NAT on packet */ |
... | ... |
@@ -1061,6 +1061,12 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf) |
1061 | 1061 |
route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router); |
1062 | 1062 |
} |
1063 | 1063 |
} |
1064 |
+ else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) |
|
1065 |
+ { |
|
1066 |
+ /* possibly alter the TCP MSS */ |
|
1067 |
+ if (flags & PIP_MSSFIX) |
|
1068 |
+ mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); |
|
1069 |
+ } |
|
1064 | 1070 |
} |
1065 | 1071 |
} |
1066 | 1072 |
} |
... | ... |
@@ -1217,9 +1223,9 @@ process_outgoing_tun (struct context *c) |
1217 | 1217 |
|
1218 | 1218 |
/* |
1219 | 1219 |
* The --mssfix option requires |
1220 |
- * us to examine the IPv4 header. |
|
1220 |
+ * us to examine the IP header (IPv4 or IPv6). |
|
1221 | 1221 |
*/ |
1222 |
- process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); |
|
1222 |
+ process_ip_header (c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); |
|
1223 | 1223 |
|
1224 | 1224 |
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame)) |
1225 | 1225 |
{ |
... | ... |
@@ -228,12 +228,12 @@ void process_outgoing_tun (struct context *c); |
228 | 228 |
bool send_control_channel_string (struct context *c, const char *str, int msglevel); |
229 | 229 |
|
230 | 230 |
#define PIPV4_PASSTOS (1<<0) |
231 |
-#define PIPV4_MSSFIX (1<<1) |
|
231 |
+#define PIP_MSSFIX (1<<1) /* v4 and v6 */ |
|
232 | 232 |
#define PIPV4_OUTGOING (1<<2) |
233 | 233 |
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3) |
234 | 234 |
#define PIPV4_CLIENT_NAT (1<<4) |
235 | 235 |
|
236 |
-void process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf); |
|
236 |
+void process_ip_header (struct context *c, unsigned int flags, struct buffer *buf); |
|
237 | 237 |
|
238 | 238 |
#if P2MP |
239 | 239 |
void schedule_exit (struct context *c, const int n_seconds, const int signal); |
... | ... |
@@ -38,8 +38,13 @@ |
38 | 38 |
* problems which arise from protocol |
39 | 39 |
* encapsulation. |
40 | 40 |
*/ |
41 |
+ |
|
42 |
+/* |
|
43 |
+ * IPv4 packet: find TCP header, check flags for "SYN" |
|
44 |
+ * if yes, hand to mss_fixup_dowork() |
|
45 |
+ */ |
|
41 | 46 |
void |
42 |
-mss_fixup (struct buffer *buf, int maxmss) |
|
47 |
+mss_fixup_ipv4 (struct buffer *buf, int maxmss) |
|
43 | 48 |
{ |
44 | 49 |
const struct openvpn_iphdr *pip; |
45 | 50 |
int hlen; |
... | ... |
@@ -69,6 +74,56 @@ mss_fixup (struct buffer *buf, int maxmss) |
69 | 69 |
} |
70 | 70 |
} |
71 | 71 |
|
72 |
+/* |
|
73 |
+ * IPv6 packet: find TCP header, check flags for "SYN" |
|
74 |
+ * if yes, hand to mss_fixup_dowork() |
|
75 |
+ * (IPv6 header structure is sufficiently different from IPv4...) |
|
76 |
+ */ |
|
77 |
+void |
|
78 |
+mss_fixup_ipv6 (struct buffer *buf, int maxmss) |
|
79 |
+{ |
|
80 |
+ const struct openvpn_ipv6hdr *pip6; |
|
81 |
+ struct buffer newbuf; |
|
82 |
+ |
|
83 |
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ipv6hdr)) |
|
84 |
+ return; |
|
85 |
+ |
|
86 |
+ verify_align_4 (buf); |
|
87 |
+ pip6 = (struct openvpn_ipv6hdr *) BPTR (buf); |
|
88 |
+ |
|
89 |
+ /* do we have the full IPv6 packet? |
|
90 |
+ * "payload_len" does not include IPv6 header (+40 bytes) |
|
91 |
+ */ |
|
92 |
+ if (BLEN (buf) != (int) ntohs(pip6->payload_len)+40 ) |
|
93 |
+ return; |
|
94 |
+ |
|
95 |
+ /* follow header chain until we reach final header, then check for TCP |
|
96 |
+ * |
|
97 |
+ * An IPv6 packet could, theoretically, have a chain of multiple headers |
|
98 |
+ * before the final header (TCP, UDP, ...), so we'd need to walk that |
|
99 |
+ * chain (see RFC 2460 and RFC 6564 for details). |
|
100 |
+ * |
|
101 |
+ * In practice, "most typically used" extention headers (AH, routing, |
|
102 |
+ * fragment, mobility) are very unlikely to be seen inside an OpenVPN |
|
103 |
+ * tun, so for now, we only handle the case of "single next header = TCP" |
|
104 |
+ */ |
|
105 |
+ if ( pip6->nexthdr != OPENVPN_IPPROTO_TCP ) |
|
106 |
+ return; |
|
107 |
+ |
|
108 |
+ newbuf = *buf; |
|
109 |
+ if ( buf_advance( &newbuf, 40 ) ) |
|
110 |
+ { |
|
111 |
+ struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf); |
|
112 |
+ if (tc->flags & OPENVPN_TCPH_SYN_MASK) |
|
113 |
+ mss_fixup_dowork (&newbuf, (uint16_t) maxmss-20); |
|
114 |
+ } |
|
115 |
+} |
|
116 |
+ |
|
117 |
+/* |
|
118 |
+ * change TCP MSS option in SYN/SYN-ACK packets, if present |
|
119 |
+ * this is generic for IPv4 and IPv6, as the TCP header is the same |
|
120 |
+ */ |
|
121 |
+ |
|
72 | 122 |
void |
73 | 123 |
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss) |
74 | 124 |
{ |
... | ... |
@@ -28,7 +28,8 @@ |
28 | 28 |
#include "proto.h" |
29 | 29 |
#include "error.h" |
30 | 30 |
|
31 |
-void mss_fixup (struct buffer *buf, int maxmss); |
|
31 |
+void mss_fixup_ipv4 (struct buffer *buf, int maxmss); |
|
32 |
+void mss_fixup_ipv6 (struct buffer *buf, int maxmss); |
|
32 | 33 |
void mss_fixup_dowork (struct buffer *buf, uint16_t maxmss); |
33 | 34 |
|
34 | 35 |
#endif |
... | ... |
@@ -2411,13 +2411,13 @@ multi_get_queue (struct mbuf_set *ms) |
2411 | 2411 |
|
2412 | 2412 |
if (mbuf_extract_item (ms, &item)) /* cleartext IP packet */ |
2413 | 2413 |
{ |
2414 |
- unsigned int pipv4_flags = PIPV4_PASSTOS; |
|
2414 |
+ unsigned int pip_flags = PIPV4_PASSTOS; |
|
2415 | 2415 |
|
2416 | 2416 |
set_prefix (item.instance); |
2417 | 2417 |
item.instance->context.c2.buf = item.buffer->buf; |
2418 | 2418 |
if (item.buffer->flags & MF_UNICAST) /* --mssfix doesn't make sense for broadcast or multicast */ |
2419 |
- pipv4_flags |= PIPV4_MSSFIX; |
|
2420 |
- process_ipv4_header (&item.instance->context, pipv4_flags, &item.instance->context.c2.buf); |
|
2419 |
+ pip_flags |= PIP_MSSFIX; |
|
2420 |
+ process_ip_header (&item.instance->context, pip_flags, &item.instance->context.c2.buf); |
|
2421 | 2421 |
encrypt_sign (&item.instance->context, true); |
2422 | 2422 |
mbuf_free_buf (item.buffer); |
2423 | 2423 |
|
... | ... |
@@ -36,11 +36,12 @@ |
36 | 36 |
#include "memdbg.h" |
37 | 37 |
|
38 | 38 |
/* |
39 |
- * If raw tunnel packet is IPv4, return true and increment |
|
39 |
+ * If raw tunnel packet is IPv<X>, return true and increment |
|
40 | 40 |
* buffer offset to start of IP header. |
41 | 41 |
*/ |
42 |
+static |
|
42 | 43 |
bool |
43 |
-is_ipv4 (int tunnel_type, struct buffer *buf) |
|
44 |
+is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver ) |
|
44 | 45 |
{ |
45 | 46 |
int offset; |
46 | 47 |
const struct openvpn_iphdr *ih; |
... | ... |
@@ -68,12 +69,24 @@ is_ipv4 (int tunnel_type, struct buffer *buf) |
68 | 68 |
|
69 | 69 |
ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset); |
70 | 70 |
|
71 |
- if (OPENVPN_IPH_GET_VER (ih->version_len) == 4) |
|
71 |
+ /* IP version is stored in the same bits for IPv4 or IPv6 header */ |
|
72 |
+ if (OPENVPN_IPH_GET_VER (ih->version_len) == ip_ver) |
|
72 | 73 |
return buf_advance (buf, offset); |
73 | 74 |
else |
74 | 75 |
return false; |
75 | 76 |
} |
76 | 77 |
|
78 |
+bool |
|
79 |
+is_ipv4 (int tunnel_type, struct buffer *buf) |
|
80 |
+{ |
|
81 |
+ return is_ipv_X( tunnel_type, buf, 4 ); |
|
82 |
+} |
|
83 |
+bool |
|
84 |
+is_ipv6 (int tunnel_type, struct buffer *buf) |
|
85 |
+{ |
|
86 |
+ return is_ipv_X( tunnel_type, buf, 6 ); |
|
87 |
+} |
|
88 |
+ |
|
77 | 89 |
#ifdef PACKET_TRUNCATION_CHECK |
78 | 90 |
|
79 | 91 |
void |
... | ... |
@@ -219,10 +219,11 @@ struct ip_tcp_udp_hdr { |
219 | 219 |
- sizeof(struct openvpn_tcphdr)) |
220 | 220 |
|
221 | 221 |
/* |
222 |
- * If raw tunnel packet is IPv4, return true and increment |
|
222 |
+ * If raw tunnel packet is IPv4 or IPv6, return true and increment |
|
223 | 223 |
* buffer offset to start of IP header. |
224 | 224 |
*/ |
225 | 225 |
bool is_ipv4 (int tunnel_type, struct buffer *buf); |
226 |
+bool is_ipv6 (int tunnel_type, struct buffer *buf); |
|
226 | 227 |
|
227 | 228 |
#ifdef PACKET_TRUNCATION_CHECK |
228 | 229 |
void ipv4_packet_size_verify (const uint8_t *data, |