Patch for pass-TOS -- retry

Ralph Schmieder ralph.schmieder at gmail.com
Tue Mar 8 07:14:50 PST 2016


Trying one more time with this patch for the pass-TOS patch. This patch is against (current as of this mail) head of origin/master.

Again, this is not something that tries to influence QoS over the Internet (SPs will usually zeroize TOS anyway) BUT to influence the local queueing in the local network. In my case, I want to make sure that my video / voice streams (inside of a VPN tunnel) are properly prioritized on my home gateway which apparently has limited upstream bandwidth.

Thanks,
-ralph





Signed-off-by: Ralph Schmieder <ralph.schmieder at gmail.com>
---
 dtls.c                 | 29 +++++++++++++++++++++++++++++
 libopenconnect.map.in  |  5 +++++
 library.c              |  9 +++++++++
 main.c                 |  6 ++++++
 openconnect-internal.h |  4 ++++
 openconnect.h          |  3 +++
 ssl.c                  |  9 +++++++++
 7 files changed, 65 insertions(+)

diff --git a/dtls.c b/dtls.c
index a1a5a72..a2054bf 100644
--- a/dtls.c
+++ b/dtls.c
@@ -1005,6 +1005,35 @@ int dtls_mainloop(struct openconnect_info *vpninfo, int *timeout)
 		struct pkt *send_pkt = this;
 		int ret;
 
+		/* if TOS optname is set, we want to copy the TOS/TCLASS header */
+		/* to the outer UDP packet */
+		if (vpninfo->dtls_tos_optname) {
+			int valid=1;
+			int tos;
+
+                        switch(this->data[0] >> 4) {
+				case 4:
+					tos = this->data[1];
+					break;
+				case 6:
+					tos = (load_be16(this->data) >> 4) & 0xff;
+					break;
+				default:
+					vpn_progress(vpninfo, PRG_ERR, 
+					_("Unknown packet (len %d) received: %02x %02x %02x %02x...\n"), 
+					this->len, this->data[0], this->data[1], this->data[2], this->data[3]);
+					valid = 0;
+			}
+
+			/* set the actual value */
+			if (valid && tos != vpninfo->dtls_tos_current) {
+				vpn_progress(vpninfo, PRG_DEBUG, _("TOS this: %d, TOS last: %d\n"), tos, vpninfo->dtls_tos_current);
+				if (setsockopt(vpninfo->dtls_fd, vpninfo->dtls_tos_proto, vpninfo->dtls_tos_optname, &tos, sizeof(tos)))
+					vpn_perror(vpninfo, _("UDP setsockopt"));
+				vpninfo->dtls_tos_current = tos;
+			}
+		}
+
 		/* One byte of header */
 		this->cstp.hdr[7] = AC_PKT_DATA;
 
diff --git a/libopenconnect.map.in b/libopenconnect.map.in
index 7c99c86..f660ab4 100644
--- a/libopenconnect.map.in
+++ b/libopenconnect.map.in
@@ -83,6 +83,11 @@ OPENCONNECT_5_3 {
 	openconnect_set_localname;
 } OPENCONNECT_5_2;
 
+OPENCONNECT_5_3 {
+ global:
+	openconnect_set_pass_tos;
+} OPENCONNECT_5_2;
+
 OPENCONNECT_PRIVATE {
  global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ @SYMVER_WIN32_STRERROR@
 	openconnect_fopen_utf8;
diff --git a/library.c b/library.c
index 5c4028b..8c04a73 100644
--- a/library.c
+++ b/library.c
@@ -68,6 +68,8 @@ struct openconnect_info *openconnect_vpninfo_new(const char *useragent,
 	init_pkt_queue(&vpninfo->incoming_queue);
 	init_pkt_queue(&vpninfo->outgoing_queue);
 	init_pkt_queue(&vpninfo->oncp_control_queue);
+	vpninfo->dtls_tos_current = 255;
+	vpninfo->dtls_pass_tos = 0;
 	vpninfo->ssl_fd = vpninfo->dtls_fd = -1;
 	vpninfo->cmd_fd = vpninfo->cmd_fd_write = -1;
 	vpninfo->tncc_fd = -1;
@@ -143,6 +145,12 @@ int openconnect_set_protocol(struct openconnect_info *vpninfo, const char *proto
 	return 0;
 }
 
+void openconnect_set_pass_tos(struct openconnect_info *vpninfo, 
+			      int is_enabled)
+{
+	vpninfo->dtls_pass_tos = is_enabled;
+}
+
 void openconnect_set_loglevel(struct openconnect_info *vpninfo,
 			      int level)
 {
@@ -538,6 +546,7 @@ void openconnect_reset_ssl(struct openconnect_info *vpninfo)
 	vpninfo->peer_addr = NULL;
 	free(vpninfo->ip_info.gateway_addr);
 	vpninfo->ip_info.gateway_addr = NULL;
+	vpninfo->dtls_tos_optname = 0;
 
 	openconnect_clear_cookies(vpninfo);
 }
diff --git a/main.c b/main.c
index 847241b..9f862c2 100644
--- a/main.c
+++ b/main.c
@@ -187,6 +187,7 @@ enum {
 	OPT_PROXY_AUTH,
 	OPT_HTTP_AUTH,
 	OPT_LOCAL_HOSTNAME,
+	OPT_PASSTOS,
 };
 
 #ifdef __sun__
@@ -226,6 +227,7 @@ static const struct option long_options[] = {
 	OPTION("base-mtu", 1, OPT_BASEMTU),
 	OPTION("script", 1, 's'),
 	OPTION("timestamp", 0, OPT_TIMESTAMP),
+	OPTION("passtos", 0, OPT_PASSTOS),
 	OPTION("key-password", 1, 'p'),
 	OPTION("proxy", 1, 'P'),
 	OPTION("proxy-auth", 1, OPT_PROXY_AUTH),
@@ -759,6 +761,7 @@ static void usage(void)
 	printf("  -l, --syslog                    %s\n", _("Use syslog for progress messages"));
 #endif
 	printf("      --timestamp                 %s\n", _("Prepend timestamp to progress messages"));
+	printf("      --passtos                   %s\n", _("copy TOS / TCLASS when using DTLS"));
 #ifndef _WIN32
 	printf("  -U, --setuid=USER               %s\n", _("Drop privileges after connecting"));
 	printf("      --csd-user=USER             %s\n", _("Drop privileges during CSD execution"));
@@ -1366,6 +1369,9 @@ int main(int argc, char **argv)
 					xstrdup("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
 			}
 			break;
+		case OPT_PASSTOS:
+			openconnect_set_pass_tos(vpninfo, 1);
+			break;
 		case OPT_TIMESTAMP:
 			timestamp = 1;
 			break;
diff --git a/openconnect-internal.h b/openconnect-internal.h
index fa729d2..897acdc 100644
--- a/openconnect-internal.h
+++ b/openconnect-internal.h
@@ -575,6 +575,10 @@ struct openconnect_info {
 	int ssl_fd;
 	int dtls_fd;
 
+	int dtls_tos_current;
+	int dtls_pass_tos;
+	int dtls_tos_proto, dtls_tos_optname;
+
 	int cmd_fd;
 	int cmd_fd_write;
 	int got_cancel_cmd;
diff --git a/openconnect.h b/openconnect.h
index 23a8fb3..fed7517 100644
--- a/openconnect.h
+++ b/openconnect.h
@@ -582,6 +582,9 @@ void openconnect_set_protect_socket_handler(struct openconnect_info *vpninfo,
 void openconnect_set_loglevel(struct openconnect_info *vpninfo,
 			      int level);
 
+void openconnect_set_pass_tos(struct openconnect_info *vpninfo, 
+                              int is_enabled);
+
 /* Callback for obtaining traffic stats via OC_CMD_STATS.
  */
 typedef void (*openconnect_stats_vfn) (void *privdata, const struct oc_stats *stats);
diff --git a/ssl.c b/ssl.c
index 55a1ecd..28fd592 100644
--- a/ssl.c
+++ b/ssl.c
@@ -910,9 +910,13 @@ int udp_sockaddr(struct openconnect_info *vpninfo, int port)
 	if (vpninfo->peer_addr->sa_family == AF_INET) {
 		struct sockaddr_in *sin = (void *)vpninfo->dtls_addr;
 		sin->sin_port = htons(port);
+		vpninfo->dtls_tos_proto = IPPROTO_IP;
+		vpninfo->dtls_tos_optname = IP_TOS;
 	} else if (vpninfo->peer_addr->sa_family == AF_INET6) {
 		struct sockaddr_in6 *sin = (void *)vpninfo->dtls_addr;
 		sin->sin6_port = htons(port);
+		vpninfo->dtls_tos_proto = IPPROTO_IPV6;
+		vpninfo->dtls_tos_optname = IPV6_TCLASS;
 	} else {
 		vpn_progress(vpninfo, PRG_ERR,
 			     _("Unknown protocol family %d. Cannot create UDP server address\n"),
@@ -920,6 +924,11 @@ int udp_sockaddr(struct openconnect_info *vpninfo, int port)
 		return -EINVAL;
 	}
 
+	/* in case DTLS TOS copy is disabled, reset the optname value */
+	/* so that the copy won't be applied in dtls.c / dtls_mainloop() */
+	if (!vpninfo->dtls_pass_tos)
+		vpninfo->dtls_tos_optname = 0;
+
 	return 0;
 }
 
-- 
2.2.1




More information about the openconnect-devel mailing list