@@ -1346,7 +1346,7 @@ process_incoming_tun(struct context *c)
* The --passtos and --mssfix options require
* us to examine the IP header (IPv4 or IPv6).
*/
- unsigned int flags = PIPV4_PASSTOS | PIP_MSSFIX | PIPV4_CLIENT_NAT
+ unsigned int flags = PIP_PASSTOS | PIP_MSSFIX | PIPV4_CLIENT_NAT
| PIPV6_IMCP_NOHOST_CLIENT;
process_ip_header(c, flags, &c->c2.buf);
@@ -1518,7 +1518,7 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf)
#if PASSTOS_CAPABILITY
if (!c->options.passtos)
{
- flags &= ~PIPV4_PASSTOS;
+ flags &= ~PIP_PASSTOS;
}
#endif
if (!c->options.client_nat)
@@ -1543,7 +1543,7 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf)
if (flags & (PIP_MSSFIX
#if PASSTOS_CAPABILITY
- | PIPV4_PASSTOS
+ | PIP_PASSTOS
#endif
| PIPV4_CLIENT_NAT
))
@@ -1553,9 +1553,9 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf)
{
#if PASSTOS_CAPABILITY
/* extract TOS from IP header */
- if (flags & PIPV4_PASSTOS)
+ if (flags & PIP_PASSTOS)
{
- link_socket_extract_tos(c->c2.link_socket, &ipbuf);
+ link_socket_extract_tos_v4(c->c2.link_socket, &ipbuf);
}
#endif
@@ -1583,6 +1583,14 @@ process_ip_header(struct context *c, unsigned int flags, struct buffer *buf)
}
else if (is_ipv6(TUNNEL_TYPE(c->c1.tuntap), &ipbuf))
{
+#if PASSTOS_CAPABILITY
+ /* extract TOS from IPiv6 header */
+ if (flags & PIP_PASSTOS)
+ {
+ link_socket_extract_tos_v6(c->c2.link_socket, &ipbuf);
+ }
+#endif
+
/* possibly alter the TCP MSS */
if (flags & PIP_MSSFIX)
{
@@ -291,7 +291,7 @@ send_control_channel_string_dowork(struct tls_multi *multi,
*/
void reschedule_multi_process(struct context *c);
-#define PIPV4_PASSTOS (1<<0)
+#define PIP_PASSTOS (1<<0)
#define PIP_MSSFIX (1<<1) /* v4 and v6 */
#define PIP_OUTGOING (1<<2)
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
@@ -3573,7 +3573,7 @@ multi_get_queue(struct mbuf_set *ms)
if (mbuf_extract_item(ms, &item)) /* cleartext IP packet */
{
- unsigned int pip_flags = PIPV4_PASSTOS | PIPV6_IMCP_NOHOST_SERVER;
+ unsigned int pip_flags = PIP_PASSTOS | PIPV6_IMCP_NOHOST_SERVER;
set_prefix(item.instance);
item.instance->context.c2.buf = item.buffer->buf;
@@ -276,7 +276,7 @@ static const char usage_message[] =
"--persist-local-ip : Keep local IP address across SIGUSR1 or --ping-restart.\n"
"--persist-key : Don't re-read key files across SIGUSR1 or --ping-restart.\n"
#if PASSTOS_CAPABILITY
- "--passtos : TOS passthrough (applies to IPv4 only).\n"
+ "--passtos : TOS passthrough.\n"
#endif
"--tun-mtu n : Take the tun/tap device MTU to be n and derive the\n"
" TCP/UDP MTU from it (default=%d).\n"
@@ -1209,17 +1209,35 @@ link_socket_write(struct link_socket *sock,
#if PASSTOS_CAPABILITY
/*
- * Extract TOS bits. Assumes that ipbuf is a valid IPv4 packet.
+ * Extract TOS bits. Assumes that ipbuf is a valid IPv4 packet.
*/
static inline void
-link_socket_extract_tos(struct link_socket *ls, const struct buffer *ipbuf)
+link_socket_extract_tos_v4(struct link_socket *ls, const struct buffer *ipbuf)
{
- if (ls && ipbuf)
+ if (!ls || !ipbuf)
{
- struct openvpn_iphdr *iph = (struct openvpn_iphdr *) BPTR(ipbuf);
- ls->ptos = iph->tos;
- ls->ptos_defined = true;
+ return;
}
+
+ struct openvpn_iphdr *iph = (struct openvpn_iphdr *) BPTR(ipbuf);
+ ls->ptos = iph->tos;
+ ls->ptos_defined = true;
+}
+
+/*
+ * Extract TOS bits. Assumes that ipbuf is a valid IPv6 packet.
+ */
+static inline void
+link_socket_extract_tos_v6(struct link_socket *ls, const struct buffer *ipbuf)
+{
+ if (!ls || !ipbuf)
+ {
+ return;
+ }
+
+ struct openvpn_ipv6hdr *ip6h = (struct openvpn_ipv6hdr *)BPTR(ipbuf);
+ ls->ptos = ((ip6h->version_prio & 0x0F) << 4) | (ip6h->flow_lbl[0] >> 4);
+ ls->ptos_defined = true;
}
/*
@@ -1229,9 +1247,20 @@ link_socket_extract_tos(struct link_socket *ls, const struct buffer *ipbuf)
static inline void
link_socket_set_tos(struct link_socket *ls)
{
- if (ls && ls->ptos_defined)
+ if (!ls || !ls->ptos_defined)
+ {
+ return;
+ }
+
+ if (ls->info.af == AF_INET6)
+ {
+ setsockopt(ls->sd, IPPROTO_IPV6, IPV6_TCLASS, (const void *)&ls->ptos,
+ sizeof(ls->ptos));
+ }
+ else
{
- setsockopt(ls->sd, IPPROTO_IP, IP_TOS, (const void *)&ls->ptos, sizeof(ls->ptos));
+ setsockopt(ls->sd, IPPROTO_IP, IP_TOS, (const void *)&ls->ptos,
+ sizeof(ls->ptos));
}
}
@@ -362,7 +362,7 @@ typedef int MIB_TCP_STATE;
/*
* Do we have the capability to support the --passtos option?
*/
-#if defined(IPPROTO_IP) && defined(IP_TOS)
+#if defined(IPPROTO_IP) && defined(IP_TOS) && defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
#define PASSTOS_CAPABILITY 1
#else
#define PASSTOS_CAPABILITY 0