Hello list,

we actively use openvpn between our offices and it work fine,
except for the following situation:
- one of our providers .. a service that requires to mark 
  packets in tos/dscp field, for example BE, CS1,CS3,CS5
- each class of traffic has its guarantied packet loss, speed, 
  jitter etc.
- we marks packet at tun interfaces and use openvpn passtos 
  option to save tos/dscp field
- but when BE class reaches it upper limit providers equipment 
  starts to drop packets. unfortunatelly openvpn ping and tls 
  packets has tos field 0x0 (BE).
  in this situation this packets are also dropped from time to 
  time by providers equipment. this leads to openvpn ping 
  timeout and as a result to connection loss.
it is almost impossible to classify openvpn ping and tls packets by its 
signature as far as they are encrypted.

the proposed patch solves the problem by specifying tos value
for ping & tls packets and works together with passtos feature.

best regards,
Vadim

Only in openvpn-2.0.9.tos: Doxyfile
diff -ur openvpn-2.0.9/forward.c openvpn-2.0.9.tos/forward.c
--- openvpn-2.0.9/forward.c	2005-12-13 20:09:13.000000000 +0300
+++ openvpn-2.0.9.tos/forward.c	2009-08-27 15:59:37.790869347 +0400
@@ -978,7 +978,7 @@
 
 #if PASSTOS_CAPABILITY
 	  /* Set TOS */
-	  link_socket_set_tos (c->c2.link_socket);
+	  link_socket_set_tos (c->c2.link_socket, c->options.tos );
 #endif
 
 	  /* Log packet send */
diff -ur openvpn-2.0.9/openvpn.8 openvpn-2.0.9.tos/openvpn.8
--- openvpn-2.0.9/openvpn.8	2005-11-03 04:16:43.000000000 +0300
+++ openvpn-2.0.9.tos/openvpn.8	2009-08-27 16:20:34.702875534 +0400
@@ -192,6 +192,7 @@
 [\ \fB\-\-nobind\fR\ ]
 [\ \fB\-\-ns\-cert\-type\fR\ \fIclient|server\fR\ ]
 [\ \fB\-\-passtos\fR\ ]
+[\ \fB\-\-tos\fR\ n\fR\ ]
 [\ \fB\-\-pause\-exit\fR\ ]
 [\ \fB\-\-persist\-key\fR\ ]
 [\ \fB\-\-persist\-local\-ip\fR\ ]
@@ -1810,6 +1811,12 @@
 Set the TOS field of the tunnel packet to what the payload's TOS is.
 .\"*********************************************************
 .TP
+.B --tos n
+Set the TOS field of outgoing packets such as openvpn ping and tls to the
+specified value.
+.B n
+must be a hexadecimal value between 0x0 and 0xfc.
+.TP
 .B --inetd [wait|nowait] [progname]
 Use this option when OpenVPN is being run from the inetd or
 .BR xinetd(8)
Only in openvpn-2.0.9: openvpn.kdevelop
Only in openvpn-2.0.9: openvpn.kdevelop.pcs
Only in openvpn-2.0.9: openvpn.kdevses
diff -ur openvpn-2.0.9/options.c openvpn-2.0.9.tos/options.c
--- openvpn-2.0.9/options.c	2005-12-13 02:50:43.000000000 +0300
+++ openvpn-2.0.9.tos/options.c	2009-08-27 16:42:52.567862396 +0400
@@ -179,6 +179,7 @@
   "--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"
+  "--tos n         : default TOS for outgoing packets (must be specified in hex)\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"
@@ -581,6 +582,9 @@
 #if P2MP
   o->scheduled_exit_interval = 5;
 #endif
+#if PASSTOS_CAPABILITY
+  o->tos = 0xa0;
+#endif
 #ifdef USE_CRYPTO
   o->ciphername = "BF-CBC";
   o->ciphername_defined = true;
@@ -612,6 +616,7 @@
 #define SHOW_PARM(name, value, format) msg(D_SHOW_PARMS, "  " #name " = " format, (value))
 #define SHOW_STR(var)       SHOW_PARM(var, (o->var ? o->var : "[UNDEF]"), "'%s'")
 #define SHOW_INT(var)       SHOW_PARM(var, o->var, "%d")
+#define SHOW_INTH(var)      SHOW_PARM(var, o->var, "0x%x")
 #define SHOW_UINT(var)      SHOW_PARM(var, o->var, "%u")
 #define SHOW_UNSIGNED(var)  SHOW_PARM(var, o->var, "0x%08x")
 #define SHOW_BOOL(var)      SHOW_PARM(var, (o->var ? "ENABLED" : "DISABLED"), "%s");
@@ -1007,6 +1012,7 @@
   
 #if PASSTOS_CAPABILITY
   SHOW_BOOL (passtos);
+  SHOW_INTH (tos);
 #endif
 
   SHOW_INT (resolve_retry_seconds);
@@ -4153,6 +4159,19 @@
       VERIFY_PERMISSION (OPT_P_GENERAL);
       options->passtos = true;
     }
+  else if (streq (p[0], "tos") && p[1])
+    {
+      int s;
+      ++i;
+      s = strtol(p[1], (char **)NULL, 16);
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      if (s < 0 || s > 0xfc)
+	  {
+	    msg (msglevel, "--tos parameter must be between 0x00 and 0xfc");
+	    goto err;
+	  }
+      options->tos = s;
+    }
 #endif
 #ifdef USE_LZO
   else if (streq (p[0], "comp-lzo"))
diff -ur openvpn-2.0.9/options.h openvpn-2.0.9.tos/options.h
--- openvpn-2.0.9/options.h	2005-11-01 14:06:11.000000000 +0300
+++ openvpn-2.0.9.tos/options.h	2009-08-27 15:52:00.339864207 +0400
@@ -181,6 +181,7 @@
 
 #if PASSTOS_CAPABILITY
   bool passtos;                  
+  uint8_t tos;
 #endif
 
   int resolve_retry_seconds;    /* If hostname resolve fails, retry for n seconds */
diff -ur openvpn-2.0.9/socket.h openvpn-2.0.9.tos/socket.h
--- openvpn-2.0.9/socket.h	2005-11-01 14:06:11.000000000 +0300
+++ openvpn-2.0.9.tos/socket.h	2009-08-27 15:59:21.419861840 +0400
@@ -746,10 +746,17 @@
  * from tunnel packet.
  */
 static inline void
-link_socket_set_tos (struct link_socket *ls)
+link_socket_set_tos (struct link_socket *ls,const uint8_t tos )
 {
   if (ls && ls->ptos_defined)
-    setsockopt (ls->sd, IPPROTO_IP, IP_TOS, &ls->ptos, sizeof (ls->ptos));
+    {
+      setsockopt (ls->sd, IPPROTO_IP, IP_TOS, &ls->ptos, sizeof (ls->ptos));
+      ls->ptos_defined = false;
+    }
+  else
+   {
+      setsockopt (ls->sd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos));
+   }
 }
 
 #endif

Reply via email to