summaryrefslogtreecommitdiff
path: root/src/openvpn/mtu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/mtu.c')
-rw-r--r--src/openvpn/mtu.c411
1 files changed, 220 insertions, 191 deletions
diff --git a/src/openvpn/mtu.c b/src/openvpn/mtu.c
index 8cbaa86..73eab21 100644
--- a/src/openvpn/mtu.c
+++ b/src/openvpn/mtu.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -41,76 +41,78 @@
/* allocate a buffer for socket or tun layer */
void
-alloc_buf_sock_tun (struct buffer *buf,
- const struct frame *frame,
- const bool tuntap_buffer,
- const unsigned int align_mask)
+alloc_buf_sock_tun(struct buffer *buf,
+ const struct frame *frame,
+ const bool tuntap_buffer,
+ const unsigned int align_mask)
{
- /* allocate buffer for overlapped I/O */
- *buf = alloc_buf (BUF_SIZE (frame));
- ASSERT (buf_init (buf, FRAME_HEADROOM_ADJ (frame, align_mask)));
- buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN (frame) : MAX_RW_SIZE_LINK (frame);
- ASSERT (buf_safe (buf, 0));
+ /* allocate buffer for overlapped I/O */
+ *buf = alloc_buf(BUF_SIZE(frame));
+ ASSERT(buf_init(buf, FRAME_HEADROOM_ADJ(frame, align_mask)));
+ buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN(frame) : MAX_RW_SIZE_LINK(frame);
+ ASSERT(buf_safe(buf, 0));
}
void
-frame_finalize (struct frame *frame,
- bool link_mtu_defined,
- int link_mtu,
- bool tun_mtu_defined,
- int tun_mtu)
+frame_finalize(struct frame *frame,
+ bool link_mtu_defined,
+ int link_mtu,
+ bool tun_mtu_defined,
+ int tun_mtu)
{
- /* Set link_mtu based on command line options */
- if (tun_mtu_defined)
+ /* Set link_mtu based on command line options */
+ if (tun_mtu_defined)
{
- ASSERT (!link_mtu_defined);
- frame->link_mtu = tun_mtu + TUN_LINK_DELTA (frame);
+ ASSERT(!link_mtu_defined);
+ frame->link_mtu = tun_mtu + TUN_LINK_DELTA(frame);
}
- else
+ else
{
- ASSERT (link_mtu_defined);
- frame->link_mtu = link_mtu;
+ ASSERT(link_mtu_defined);
+ frame->link_mtu = link_mtu;
}
- if (TUN_MTU_SIZE (frame) < TUN_MTU_MIN)
+ if (TUN_MTU_SIZE(frame) < TUN_MTU_MIN)
{
- msg (M_WARN, "TUN MTU value (%d) must be at least %d", TUN_MTU_SIZE (frame), TUN_MTU_MIN);
- frame_print (frame, M_FATAL, "MTU is too small");
+ msg(M_WARN, "TUN MTU value (%d) must be at least %d", TUN_MTU_SIZE(frame), TUN_MTU_MIN);
+ frame_print(frame, M_FATAL, "MTU is too small");
}
- frame->link_mtu_dynamic = frame->link_mtu;
+ frame->link_mtu_dynamic = frame->link_mtu;
}
/*
* Set the tun MTU dynamically.
*/
void
-frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags)
+frame_set_mtu_dynamic(struct frame *frame, int mtu, unsigned int flags)
{
#ifdef ENABLE_DEBUG
- const int orig_mtu = mtu;
- const int orig_link_mtu_dynamic = frame->link_mtu_dynamic;
+ const int orig_mtu = mtu;
+ const int orig_link_mtu_dynamic = frame->link_mtu_dynamic;
#endif
- ASSERT (mtu >= 0);
+ ASSERT(mtu >= 0);
- if (flags & SET_MTU_TUN)
- mtu += TUN_LINK_DELTA (frame);
+ if (flags & SET_MTU_TUN)
+ {
+ mtu += TUN_LINK_DELTA(frame);
+ }
- if (!(flags & SET_MTU_UPPER_BOUND) || mtu < frame->link_mtu_dynamic)
+ if (!(flags & SET_MTU_UPPER_BOUND) || mtu < frame->link_mtu_dynamic)
{
- frame->link_mtu_dynamic = constrain_int (
- mtu,
- EXPANDED_SIZE_MIN (frame),
- EXPANDED_SIZE (frame));
+ frame->link_mtu_dynamic = constrain_int(
+ mtu,
+ EXPANDED_SIZE_MIN(frame),
+ EXPANDED_SIZE(frame));
}
- dmsg (D_MTU_DEBUG, "MTU DYNAMIC mtu=%d, flags=%u, %d -> %d",
- orig_mtu,
- flags,
- orig_link_mtu_dynamic,
- frame->link_mtu_dynamic);
+ dmsg(D_MTU_DEBUG, "MTU DYNAMIC mtu=%d, flags=%u, %d -> %d",
+ orig_mtu,
+ flags,
+ orig_link_mtu_dynamic,
+ frame->link_mtu_dynamic);
}
/*
@@ -119,200 +121,227 @@ frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags)
* queue.
*/
void
-frame_subtract_extra (struct frame *frame, const struct frame *src)
+frame_subtract_extra(struct frame *frame, const struct frame *src)
{
- frame->extra_frame -= src->extra_frame;
- frame->extra_tun += src->extra_frame;
+ frame->extra_frame -= src->extra_frame;
+ frame->extra_tun += src->extra_frame;
}
void
-frame_init_mssfix (struct frame *frame, const struct options *options)
+frame_init_mssfix(struct frame *frame, const struct options *options)
{
- if (options->ce.mssfix)
+ if (options->ce.mssfix)
{
- frame_set_mtu_dynamic (frame, options->ce.mssfix, SET_MTU_UPPER_BOUND);
+ frame_set_mtu_dynamic(frame, options->ce.mssfix, SET_MTU_UPPER_BOUND);
}
}
void
-frame_print (const struct frame *frame,
- int level,
- const char *prefix)
+frame_print(const struct frame *frame,
+ int level,
+ const char *prefix)
{
- struct gc_arena gc = gc_new ();
- struct buffer out = alloc_buf_gc (256, &gc);
- if (prefix)
- buf_printf (&out, "%s ", prefix);
- buf_printf (&out, "[");
- buf_printf (&out, " L:%d", frame->link_mtu);
- buf_printf (&out, " D:%d", frame->link_mtu_dynamic);
- buf_printf (&out, " EF:%d", frame->extra_frame);
- buf_printf (&out, " EB:%d", frame->extra_buffer);
- buf_printf (&out, " ET:%d", frame->extra_tun);
- buf_printf (&out, " EL:%d", frame->extra_link);
- if (frame->align_flags && frame->align_adjust)
- buf_printf (&out, " AF:%u/%d", frame->align_flags, frame->align_adjust);
- buf_printf (&out, " ]");
-
- msg (level, "%s", out.data);
- gc_free (&gc);
+ struct gc_arena gc = gc_new();
+ struct buffer out = alloc_buf_gc(256, &gc);
+ if (prefix)
+ {
+ buf_printf(&out, "%s ", prefix);
+ }
+ buf_printf(&out, "[");
+ buf_printf(&out, " L:%d", frame->link_mtu);
+ buf_printf(&out, " D:%d", frame->link_mtu_dynamic);
+ buf_printf(&out, " EF:%d", frame->extra_frame);
+ buf_printf(&out, " EB:%d", frame->extra_buffer);
+ buf_printf(&out, " ET:%d", frame->extra_tun);
+ buf_printf(&out, " EL:%d", frame->extra_link);
+ if (frame->align_flags && frame->align_adjust)
+ {
+ buf_printf(&out, " AF:%u/%d", frame->align_flags, frame->align_adjust);
+ }
+ buf_printf(&out, " ]");
+
+ msg(level, "%s", out.data);
+ gc_free(&gc);
}
#define MTUDISC_NOT_SUPPORTED_MSG "--mtu-disc is not supported on this OS"
void
-set_mtu_discover_type (int sd, int mtu_type, sa_family_t proto_af)
+set_mtu_discover_type(int sd, int mtu_type, sa_family_t proto_af)
{
- if (mtu_type >= 0)
+ if (mtu_type >= 0)
{
- switch (proto_af)
- {
+ switch (proto_af)
+ {
#if defined(HAVE_SETSOCKOPT) && defined(IP_MTU_DISCOVER)
- case AF_INET:
- if (setsockopt
- (sd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
- msg (M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
- mtu_type);
- break;
+ case AF_INET:
+ if (setsockopt
+ (sd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu_type, sizeof(mtu_type)))
+ {
+ msg(M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
+ mtu_type);
+ }
+ break;
+
#endif
#if defined(HAVE_SETSOCKOPT) && defined(IPV6_MTU_DISCOVER)
- case AF_INET6:
- if (setsockopt
- (sd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
- msg (M_ERR, "Error setting IPV6_MTU_DISCOVER type=%d on TCP6/UDP6 socket",
- mtu_type);
- break;
+ case AF_INET6:
+ if (setsockopt
+ (sd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &mtu_type, sizeof(mtu_type)))
+ {
+ msg(M_ERR, "Error setting IPV6_MTU_DISCOVER type=%d on TCP6/UDP6 socket",
+ mtu_type);
+ }
+ break;
+
#endif
- default:
- msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
- break;
- }
+ default:
+ msg(M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
+ break;
+ }
}
}
int
-translate_mtu_discover_type_name (const char *name)
+translate_mtu_discover_type_name(const char *name)
{
#if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO)
- if (!strcmp (name, "yes"))
- return IP_PMTUDISC_DO;
- if (!strcmp (name, "maybe"))
- return IP_PMTUDISC_WANT;
- if (!strcmp (name, "no"))
- return IP_PMTUDISC_DONT;
- msg (M_FATAL,
- "invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
- name);
-#else
- msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
+ if (!strcmp(name, "yes"))
+ {
+ return IP_PMTUDISC_DO;
+ }
+ if (!strcmp(name, "maybe"))
+ {
+ return IP_PMTUDISC_WANT;
+ }
+ if (!strcmp(name, "no"))
+ {
+ return IP_PMTUDISC_DONT;
+ }
+ msg(M_FATAL,
+ "invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
+ name);
+#else /* if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO) */
+ msg(M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
#endif
- return -1; /* NOTREACHED */
+ return -1; /* NOTREACHED */
}
#if EXTENDED_SOCKET_ERROR_CAPABILITY
struct probehdr
{
- uint32_t ttl;
- struct timeval tv;
+ uint32_t ttl;
+ struct timeval tv;
};
const char *
-format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc)
+format_extended_socket_error(int fd, int *mtu, struct gc_arena *gc)
{
- int res;
- struct probehdr rcvbuf;
- struct iovec iov;
- struct msghdr msg;
- struct cmsghdr *cmsg;
- struct sock_extended_err *e;
- struct sockaddr_in addr;
- struct buffer out = alloc_buf_gc (256, gc);
- char *cbuf = (char *) gc_malloc (256, false, gc);
-
- *mtu = 0;
-
- while (true)
+ int res;
+ struct probehdr rcvbuf;
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ struct sock_extended_err *e;
+ struct sockaddr_in addr;
+ struct buffer out = alloc_buf_gc(256, gc);
+ char *cbuf = (char *) gc_malloc(256, false, gc);
+
+ *mtu = 0;
+
+ while (true)
{
- memset (&rcvbuf, -1, sizeof (rcvbuf));
- iov.iov_base = &rcvbuf;
- iov.iov_len = sizeof (rcvbuf);
- msg.msg_name = (uint8_t *) &addr;
- msg.msg_namelen = sizeof (addr);
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- msg.msg_control = cbuf;
- msg.msg_controllen = 256; /* size of cbuf */
-
- res = recvmsg (fd, &msg, MSG_ERRQUEUE);
- if (res < 0)
- goto exit;
-
- e = NULL;
-
- for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
- {
- if (cmsg->cmsg_level == SOL_IP)
- {
- if (cmsg->cmsg_type == IP_RECVERR)
- {
- e = (struct sock_extended_err *) CMSG_DATA (cmsg);
- }
- else
- {
- buf_printf (&out ,"CMSG=%d|", cmsg->cmsg_type);
- }
- }
- }
- if (e == NULL)
- {
- buf_printf (&out, "NO-INFO|");
- goto exit;
- }
-
- switch (e->ee_errno)
- {
- case ETIMEDOUT:
- buf_printf (&out, "ETIMEDOUT|");
- break;
- case EMSGSIZE:
- buf_printf (&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
- *mtu = e->ee_info;
- break;
- case ECONNREFUSED:
- buf_printf (&out, "ECONNREFUSED|");
- break;
- case EPROTO:
- buf_printf (&out, "EPROTO|");
- break;
- case EHOSTUNREACH:
- buf_printf (&out, "EHOSTUNREACH|");
- break;
- case ENETUNREACH:
- buf_printf (&out, "ENETUNREACH|");
- break;
- case EACCES:
- buf_printf (&out, "EACCES|");
- break;
- default:
- buf_printf (&out, "UNKNOWN|");
- break;
- }
+ memset(&rcvbuf, -1, sizeof(rcvbuf));
+ iov.iov_base = &rcvbuf;
+ iov.iov_len = sizeof(rcvbuf);
+ msg.msg_name = (uint8_t *) &addr;
+ msg.msg_namelen = sizeof(addr);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = cbuf;
+ msg.msg_controllen = 256; /* size of cbuf */
+
+ res = recvmsg(fd, &msg, MSG_ERRQUEUE);
+ if (res < 0)
+ {
+ goto exit;
+ }
+
+ e = NULL;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
+ {
+ if (cmsg->cmsg_level == SOL_IP)
+ {
+ if (cmsg->cmsg_type == IP_RECVERR)
+ {
+ e = (struct sock_extended_err *) CMSG_DATA(cmsg);
+ }
+ else
+ {
+ buf_printf(&out,"CMSG=%d|", cmsg->cmsg_type);
+ }
+ }
+ }
+ if (e == NULL)
+ {
+ buf_printf(&out, "NO-INFO|");
+ goto exit;
+ }
+
+ switch (e->ee_errno)
+ {
+ case ETIMEDOUT:
+ buf_printf(&out, "ETIMEDOUT|");
+ break;
+
+ case EMSGSIZE:
+ buf_printf(&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
+ *mtu = e->ee_info;
+ break;
+
+ case ECONNREFUSED:
+ buf_printf(&out, "ECONNREFUSED|");
+ break;
+
+ case EPROTO:
+ buf_printf(&out, "EPROTO|");
+ break;
+
+ case EHOSTUNREACH:
+ buf_printf(&out, "EHOSTUNREACH|");
+ break;
+
+ case ENETUNREACH:
+ buf_printf(&out, "ENETUNREACH|");
+ break;
+
+ case EACCES:
+ buf_printf(&out, "EACCES|");
+ break;
+
+ default:
+ buf_printf(&out, "UNKNOWN|");
+ break;
+ }
}
- exit:
- buf_rmtail (&out, '|');
- return BSTR (&out);
+exit:
+ buf_rmtail(&out, '|');
+ return BSTR(&out);
}
void
-set_sock_extended_error_passing (int sd)
+set_sock_extended_error_passing(int sd)
{
- int on = 1;
- if (setsockopt (sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof (on)))
- msg (M_WARN | M_ERRNO,
- "Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
+ int on = 1;
+ if (setsockopt(sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof(on)))
+ {
+ msg(M_WARN | M_ERRNO,
+ "Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
+ }
}
-#endif
+#endif /* if EXTENDED_SOCKET_ERROR_CAPABILITY */