summaryrefslogtreecommitdiff
path: root/src/openvpn
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2013-01-10 17:54:05 +0100
committerAlberto Gonzalez Iniesta <agi@inittab.org>2013-01-10 17:54:05 +0100
commit0159f6a3459c511c94b009afd0bfe5dc8e8991d1 (patch)
tree3c12297fd9b61426d6873c3c821360ef71e01448 /src/openvpn
parentc0bce9e49cf1fbeda1269e93d9818e4861725e71 (diff)
parent9e3cceecfca10ef806f193ec41e0e0a44706c328 (diff)
Merge tag 'upstream/2.3.0'
Upstream version 2.3.0
Diffstat (limited to 'src/openvpn')
-rw-r--r--src/openvpn/forward.c26
-rw-r--r--src/openvpn/forward.h4
-rw-r--r--src/openvpn/manage.c15
-rw-r--r--src/openvpn/mss.c57
-rw-r--r--src/openvpn/mss.h3
-rw-r--r--src/openvpn/multi.c6
-rw-r--r--src/openvpn/openvpn.h1
-rw-r--r--src/openvpn/options.c24
-rw-r--r--src/openvpn/pf.c1
-rw-r--r--src/openvpn/pkcs11.c2
-rw-r--r--src/openvpn/proto.c19
-rw-r--r--src/openvpn/proto.h3
-rw-r--r--src/openvpn/push.c7
-rw-r--r--src/openvpn/route.c4
-rw-r--r--src/openvpn/socket.c24
-rw-r--r--src/openvpn/socket.h9
16 files changed, 159 insertions, 46 deletions
diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c
index 57c7846..024cd58 100644
--- a/src/openvpn/forward.c
+++ b/src/openvpn/forward.c
@@ -985,9 +985,9 @@ process_incoming_tun (struct context *c)
{
/*
* The --passtos and --mssfix options require
- * us to examine the IPv4 header.
+ * us to examine the IP header (IPv4 or IPv6).
*/
- process_ipv4_header (c, PIPV4_PASSTOS|PIPV4_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
+ process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);
#ifdef PACKET_TRUNCATION_CHECK
/* if (c->c2.buf.len > 1) --c->c2.buf.len; */
@@ -1009,10 +1009,10 @@ process_incoming_tun (struct context *c)
}
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.ce.mssfix)
- flags &= ~PIPV4_MSSFIX;
+ flags &= ~PIP_MSSFIX;
#if PASSTOS_CAPABILITY
if (!c->options.passtos)
flags &= ~PIPV4_PASSTOS;
@@ -1027,9 +1027,9 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
* us to examine the IPv4 header.
*/
#if PASSTOS_CAPABILITY
- if (flags & (PIPV4_PASSTOS|PIPV4_MSSFIX))
+ if (flags & (PIPV4_PASSTOS|PIP_MSSFIX))
#else
- if (flags & PIPV4_MSSFIX)
+ if (flags & PIP_MSSFIX)
#endif
{
struct buffer ipbuf = *buf;
@@ -1042,8 +1042,8 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
#endif
/* possibly alter the TCP MSS */
- if (flags & PIPV4_MSSFIX)
- mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+ if (flags & PIP_MSSFIX)
+ mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
#ifdef ENABLE_CLIENT_NAT
/* possibly do NAT on packet */
@@ -1061,6 +1061,12 @@ process_ipv4_header (struct context *c, unsigned int flags, struct buffer *buf)
route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router);
}
}
+ else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf))
+ {
+ /* possibly alter the TCP MSS */
+ if (flags & PIP_MSSFIX)
+ mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame)));
+ }
}
}
}
@@ -1217,9 +1223,9 @@ process_outgoing_tun (struct context *c)
/*
* The --mssfix option requires
- * us to examine the IPv4 header.
+ * us to examine the IP header (IPv4 or IPv6).
*/
- process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
+ process_ip_header (c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun);
if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame))
{
diff --git a/src/openvpn/forward.h b/src/openvpn/forward.h
index 0f829bd..1830a00 100644
--- a/src/openvpn/forward.h
+++ b/src/openvpn/forward.h
@@ -228,12 +228,12 @@ void process_outgoing_tun (struct context *c);
bool send_control_channel_string (struct context *c, const char *str, int msglevel);
#define PIPV4_PASSTOS (1<<0)
-#define PIPV4_MSSFIX (1<<1)
+#define PIP_MSSFIX (1<<1) /* v4 and v6 */
#define PIPV4_OUTGOING (1<<2)
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
#define PIPV4_CLIENT_NAT (1<<4)
-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, const int signal);
diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c
index d0bb416..0a4542a 100644
--- a/src/openvpn/manage.c
+++ b/src/openvpn/manage.c
@@ -287,13 +287,13 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
# define AF_DID_PUSH (1<<0)
# define AF_DID_RESET (1<<1)
- unsigned int action_flags = 0;
if (!recursive_level) /* don't allow recursion */
{
struct gc_arena gc = gc_new ();
struct log_entry e;
const char *out = NULL;
+ unsigned int action_flags = 0;
++recursive_level;
@@ -334,14 +334,15 @@ virtual_output_callback_func (void *arg, const unsigned int flags, const char *s
}
}
- --recursive_level;
gc_free (&gc);
- }
- if (action_flags & AF_DID_PUSH)
- man_output_list_push_finalize (man);
- if (action_flags & AF_DID_RESET)
- man_reset_client_socket (man, true);
+ if (action_flags & AF_DID_PUSH)
+ man_output_list_push_finalize (man);
+ if (action_flags & AF_DID_RESET)
+ man_reset_client_socket (man, true);
+
+ --recursive_level;
+ }
}
/*
diff --git a/src/openvpn/mss.c b/src/openvpn/mss.c
index 8981bad..64fd722 100644
--- a/src/openvpn/mss.c
+++ b/src/openvpn/mss.c
@@ -38,8 +38,13 @@
* problems which arise from protocol
* encapsulation.
*/
+
+/*
+ * IPv4 packet: find TCP header, check flags for "SYN"
+ * if yes, hand to mss_fixup_dowork()
+ */
void
-mss_fixup (struct buffer *buf, int maxmss)
+mss_fixup_ipv4 (struct buffer *buf, int maxmss)
{
const struct openvpn_iphdr *pip;
int hlen;
@@ -69,6 +74,56 @@ mss_fixup (struct buffer *buf, int maxmss)
}
}
+/*
+ * IPv6 packet: find TCP header, check flags for "SYN"
+ * if yes, hand to mss_fixup_dowork()
+ * (IPv6 header structure is sufficiently different from IPv4...)
+ */
+void
+mss_fixup_ipv6 (struct buffer *buf, int maxmss)
+{
+ const struct openvpn_ipv6hdr *pip6;
+ struct buffer newbuf;
+
+ if (BLEN (buf) < (int) sizeof (struct openvpn_ipv6hdr))
+ return;
+
+ verify_align_4 (buf);
+ pip6 = (struct openvpn_ipv6hdr *) BPTR (buf);
+
+ /* do we have the full IPv6 packet?
+ * "payload_len" does not include IPv6 header (+40 bytes)
+ */
+ if (BLEN (buf) != (int) ntohs(pip6->payload_len)+40 )
+ return;
+
+ /* follow header chain until we reach final header, then check for TCP
+ *
+ * An IPv6 packet could, theoretically, have a chain of multiple headers
+ * before the final header (TCP, UDP, ...), so we'd need to walk that
+ * chain (see RFC 2460 and RFC 6564 for details).
+ *
+ * In practice, "most typically used" extention headers (AH, routing,
+ * fragment, mobility) are very unlikely to be seen inside an OpenVPN
+ * tun, so for now, we only handle the case of "single next header = TCP"
+ */
+ if ( pip6->nexthdr != OPENVPN_IPPROTO_TCP )
+ return;
+
+ newbuf = *buf;
+ if ( buf_advance( &newbuf, 40 ) )
+ {
+ struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
+ if (tc->flags & OPENVPN_TCPH_SYN_MASK)
+ mss_fixup_dowork (&newbuf, (uint16_t) maxmss-20);
+ }
+}
+
+/*
+ * change TCP MSS option in SYN/SYN-ACK packets, if present
+ * this is generic for IPv4 and IPv6, as the TCP header is the same
+ */
+
void
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
{
diff --git a/src/openvpn/mss.h b/src/openvpn/mss.h
index 0b290c3..0d32943 100644
--- a/src/openvpn/mss.h
+++ b/src/openvpn/mss.h
@@ -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 --git a/src/openvpn/multi.c b/src/openvpn/multi.c
index 9876b80..ab3f10c 100644
--- a/src/openvpn/multi.c
+++ b/src/openvpn/multi.c
@@ -2411,13 +2411,13 @@ multi_get_queue (struct mbuf_set *ms)
if (mbuf_extract_item (ms, &item)) /* cleartext IP packet */
{
- unsigned int pipv4_flags = PIPV4_PASSTOS;
+ unsigned int pip_flags = PIPV4_PASSTOS;
set_prefix (item.instance);
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);
+ pip_flags |= PIP_MSSFIX;
+ process_ip_header (&item.instance->context, pip_flags, &item.instance->context.c2.buf);
encrypt_sign (&item.instance->context, true);
mbuf_free_buf (item.buffer);
diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h
index 7abfb08..bdfa685 100644
--- a/src/openvpn/openvpn.h
+++ b/src/openvpn/openvpn.h
@@ -474,6 +474,7 @@ struct context_2
bool did_pre_pull_restore;
/* hash of pulled options, so we can compare when options change */
+ bool pulled_options_md5_init_done;
struct md5_state pulled_options_state;
struct md5_digest pulled_options_digest;
diff --git a/src/openvpn/options.c b/src/openvpn/options.c
index 9baa4ff..8ca41a3 100644
--- a/src/openvpn/options.c
+++ b/src/openvpn/options.c
@@ -2274,7 +2274,7 @@ options_postprocess_verify_ce (const struct options *options, const struct conne
{
notnull (options->cert_file, "certificate file (--cert) or PKCS#12 file (--pkcs12)");
#ifdef MANAGMENT_EXTERNAL_KEY
- if (!options->management_flags & MF_EXTERNAL_KEY)
+ if (!(options->management_flags & MF_EXTERNAL_KEY))
#endif
notnull (options->priv_key_file, "private key file (--key) or PKCS#12 file (--pkcs12)");
}
@@ -2666,7 +2666,7 @@ options_postprocess_filechecks (struct options *options)
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->extra_certs_file, R_OK,
"--extra-certs");
#ifdef MANAGMENT_EXTERNAL_KEY
- if(!options->management_flags & MF_EXTERNAL_KEY)
+ if(!(options->management_flags & MF_EXTERNAL_KEY))
#endif
errs |= check_file_access (CHKACC_FILE|CHKACC_INLINE, options->priv_key_file, R_OK,
"--key");
@@ -2917,7 +2917,11 @@ options_string (const struct options *o,
buf_printf (&out, ",link-mtu %d", EXPANDED_SIZE (frame));
buf_printf (&out, ",tun-mtu %d", PAYLOAD_SIZE (frame));
buf_printf (&out, ",proto %s", proto2ascii (proto_remote (o->ce.proto, remote), true));
- if (o->tun_ipv6)
+
+ /* send tun_ipv6 only in peer2peer mode - in client/server mode, it
+ * is usually pushed by the server, triggering a non-helpful warning
+ */
+ if (o->tun_ipv6 && o->mode == MODE_POINT_TO_POINT && !PULL_DEFINED(o))
buf_printf (&out, ",tun-ipv6");
/*
@@ -3097,6 +3101,15 @@ options_warning_safe_scan2 (const int msglevel,
const char *b1_name,
const char *b2_name)
{
+ /* we will stop sending 'proto xxx' in OCC in a future version
+ * (because it's not useful), and to reduce questions when
+ * interoperating, we start not-printing a warning about it today
+ */
+ if (strncmp(p1, "proto ", 6) == 0 )
+ {
+ return;
+ }
+
if (strlen (p1) > 0)
{
struct gc_arena gc = gc_new ();
@@ -5141,6 +5154,11 @@ add_option (struct options *options,
msg (msglevel, "--max-routes parameter is out of range");
goto err;
}
+ if (options->routes || options->routes_ipv6)
+ {
+ msg (msglevel, "--max-routes must to be specifed before any route/route-ipv6/redirect-gateway option");
+ goto err;
+ }
options->max_routes = max_routes;
}
else if (streq (p[0], "route-gateway") && p[1])
diff --git a/src/openvpn/pf.c b/src/openvpn/pf.c
index 3c46801..aafe9ff 100644
--- a/src/openvpn/pf.c
+++ b/src/openvpn/pf.c
@@ -606,7 +606,6 @@ pf_destroy_context (struct pf_context *pfc)
if (pfc->filename)
{
platform_unlink (pfc->filename);
- free (pfc->filename);
}
#endif
if (pfc->pfs)
diff --git a/src/openvpn/pkcs11.c b/src/openvpn/pkcs11.c
index 645f1f4..3a15ef6 100644
--- a/src/openvpn/pkcs11.c
+++ b/src/openvpn/pkcs11.c
@@ -887,7 +887,7 @@ show_pkcs11_ids (
(dn = pkcs11_certificate_dn (
certificate,
&gc
- ))
+ )) == NULL
) {
goto cleanup1;
}
diff --git a/src/openvpn/proto.c b/src/openvpn/proto.c
index 2cf8314..b437f1a 100644
--- a/src/openvpn/proto.c
+++ b/src/openvpn/proto.c
@@ -36,11 +36,12 @@
#include "memdbg.h"
/*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv<X>, return true and increment
* buffer offset to start of IP header.
*/
+static
bool
-is_ipv4 (int tunnel_type, struct buffer *buf)
+is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver )
{
int offset;
const struct openvpn_iphdr *ih;
@@ -68,12 +69,24 @@ is_ipv4 (int tunnel_type, struct buffer *buf)
ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset);
- if (OPENVPN_IPH_GET_VER (ih->version_len) == 4)
+ /* IP version is stored in the same bits for IPv4 or IPv6 header */
+ if (OPENVPN_IPH_GET_VER (ih->version_len) == ip_ver)
return buf_advance (buf, offset);
else
return false;
}
+bool
+is_ipv4 (int tunnel_type, struct buffer *buf)
+{
+ return is_ipv_X( tunnel_type, buf, 4 );
+}
+bool
+is_ipv6 (int tunnel_type, struct buffer *buf)
+{
+ return is_ipv_X( tunnel_type, buf, 6 );
+}
+
#ifdef PACKET_TRUNCATION_CHECK
void
diff --git a/src/openvpn/proto.h b/src/openvpn/proto.h
index 8cd4ede..f91e787 100644
--- a/src/openvpn/proto.h
+++ b/src/openvpn/proto.h
@@ -219,10 +219,11 @@ struct ip_tcp_udp_hdr {
- sizeof(struct openvpn_tcphdr))
/*
- * If raw tunnel packet is IPv4, return true and increment
+ * If raw tunnel packet is IPv4 or IPv6, return true and increment
* buffer offset to start of IP header.
*/
bool is_ipv4 (int tunnel_type, struct buffer *buf);
+bool is_ipv6 (int tunnel_type, struct buffer *buf);
#ifdef PACKET_TRUNCATION_CHECK
void ipv4_packet_size_verify (const uint8_t *data,
diff --git a/src/openvpn/push.c b/src/openvpn/push.c
index 05a38e0..be50bef 100644
--- a/src/openvpn/push.c
+++ b/src/openvpn/push.c
@@ -446,10 +446,14 @@ process_incoming_push_msg (struct context *c,
if (ch == ',')
{
struct buffer buf_orig = buf;
+ if (!c->c2.pulled_options_md5_init_done)
+ {
+ md5_state_init (&c->c2.pulled_options_state);
+ c->c2.pulled_options_md5_init_done = true;
+ }
if (!c->c2.did_pre_pull_restore)
{
pre_pull_restore (&c->options);
- md5_state_init (&c->c2.pulled_options_state);
c->c2.did_pre_pull_restore = true;
}
if (apply_push_options (&c->options,
@@ -463,6 +467,7 @@ process_incoming_push_msg (struct context *c,
case 1:
md5_state_update (&c->c2.pulled_options_state, BPTR(&buf_orig), BLEN(&buf_orig));
md5_state_final (&c->c2.pulled_options_state, &c->c2.pulled_options_digest);
+ c->c2.pulled_options_md5_init_done = false;
ret = PUSH_MSG_REPLY;
break;
case 2:
diff --git a/src/openvpn/route.c b/src/openvpn/route.c
index 8c3d0dc..dd69d8e 100644
--- a/src/openvpn/route.c
+++ b/src/openvpn/route.c
@@ -2701,7 +2701,7 @@ get_default_gateway (struct route_gateway_info *rgi)
if (write(s, (char *)&m_rtmsg, l) < 0)
{
- warn("writing to routing socket");
+ msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
gc_free (&gc);
close(s);
return;
@@ -3067,7 +3067,7 @@ get_default_gateway (struct route_gateway_info *rgi)
if (write(s, (char *)&m_rtmsg, l) < 0)
{
- warn("writing to routing socket");
+ msg(M_WARN|M_ERRNO, "Could not retrieve default gateway from route socket:");
gc_free (&gc);
close(s);
return;
diff --git a/src/openvpn/socket.c b/src/openvpn/socket.c
index 505cf3b..8eb112b 100644
--- a/src/openvpn/socket.c
+++ b/src/openvpn/socket.c
@@ -158,7 +158,7 @@ openvpn_getaddrinfo (unsigned int flags,
CLEAR(hints);
hints.ai_family = ai_family;
hints.ai_flags = AI_NUMERICHOST;
- hints.ai_socktype = dnsflags_to_socktype(flags);
+ hints.ai_socktype = SOCK_STREAM;
status = getaddrinfo(hostname, NULL, &hints, res);
@@ -2560,6 +2560,10 @@ addr_family_name (int af)
*
* This is used for options compatibility
* checking.
+ *
+ * IPv6 and IPv4 protocols are comptabile but OpenVPN
+ * has always sent UDPv4, TCPv4 over the wire. Keep these
+ * strings for backward compatbility
*/
int
proto_remote (int proto, bool remote)
@@ -2569,10 +2573,20 @@ proto_remote (int proto, bool remote)
{
switch (proto)
{
- case PROTO_TCPv4_SERVER: return PROTO_TCPv4_CLIENT;
- case PROTO_TCPv4_CLIENT: return PROTO_TCPv4_SERVER;
- case PROTO_TCPv6_SERVER: return PROTO_TCPv6_CLIENT;
- case PROTO_TCPv6_CLIENT: return PROTO_TCPv6_SERVER;
+ case PROTO_TCPv4_SERVER: return PROTO_TCPv4_CLIENT;
+ case PROTO_TCPv4_CLIENT: return PROTO_TCPv4_SERVER;
+ case PROTO_TCPv6_SERVER: return PROTO_TCPv4_CLIENT;
+ case PROTO_TCPv6_CLIENT: return PROTO_TCPv4_SERVER;
+ case PROTO_UDPv6: return PROTO_UDPv4;
+ }
+ }
+ else
+ {
+ switch (proto)
+ {
+ case PROTO_TCPv6_SERVER: return PROTO_TCPv4_SERVER;
+ case PROTO_TCPv6_CLIENT: return PROTO_TCPv4_CLIENT;
+ case PROTO_UDPv6: return PROTO_UDPv4;
}
}
return proto;
diff --git a/src/openvpn/socket.h b/src/openvpn/socket.h
index 44f1098..4e7e7f8 100644
--- a/src/openvpn/socket.h
+++ b/src/openvpn/socket.h
@@ -237,7 +237,11 @@ struct link_socket
#if PASSTOS_CAPABILITY
/* used to get/set TOS. */
+#if defined(TARGET_LINUX)
uint8_t ptos;
+#else /* all the BSDs, Solaris, MacOS use plain "int" -> see "man ip" there */
+ int ptos;
+#endif
bool ptos_defined;
#endif
@@ -478,11 +482,6 @@ bool unix_socket_get_peer_uid_gid (const socket_descriptor_t sd, int *uid, int *
#define GETADDR_UPDATE_MANAGEMENT_STATE (1<<8)
#define GETADDR_RANDOMIZE (1<<9)
-/* [ab]use flags bits to get socktype info downstream */
-/* TODO(jjo): resolve tradeoff between hackiness|args-overhead */
-#define GETADDR_DGRAM (1<<10)
-#define dnsflags_to_socktype(flags) ((flags & GETADDR_DGRAM) ? SOCK_DGRAM : SOCK_STREAM)
-
in_addr_t getaddr (unsigned int flags,
const char *hostname,
int resolve_retry_seconds,