mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-11-23 17:53:49 +08:00
Implement --mssfix handling for IPv6 packets.
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>
(cherry picked from commit f0e8997a87
)
This commit is contained in:
parent
34bc52d611
commit
729c846402
@ -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))
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user