Hi, this is simple patch implementing internal openvpn ping over OCC channel. Important difference of OCC ping (OCC_PING) to existing one is that this one is replied on the other side of the channel (with OCC_PING_REPLY), thus making it possible to configure clients and server ping and ping-restart timeout differently. This might be usefull if someone is trying to combine mobile and non-mobile clients on one openvpn server. Non-mobile clients might want to have reliable link and ping more frequently compared to mobile clients that might not want this (ie. to save battery on android ;-).
OCC ping replaces 'normal' ping if activated via occ-ping directive, and thus fully integrates with all ping/ping-restart/... directives. Additionaly I've implemented occ-ping-compat mode, that will send OCC_REQUEST instread of OCC_PING. All OCC clients will then reply to this request with OCC_REPLY message - it might be usefull to enable this on server, to stay backward compatible with older non occ-ping clients. Please review it ;) Thanks. Sam diff -ur openvpn-2.2.2/occ.c openvpn-2.2.2-dev/occ.c --- openvpn-2.2.2/occ.c 2011-12-13 17:58:56.000000000 +0100 +++ openvpn-2.2.2-dev/occ.c 2012-05-27 19:23:15.000000000 +0200 @@ -302,6 +302,29 @@ dmsg (D_PACKET_CONTENT, "SENT OCC_EXIT"); doit = true; break; + + case OCC_PING: + if (c->options.occ_ping_compat) + { + if (!buf_write_u8 (&c->c2.buf, OCC_REQUEST)) + break; + dmsg (D_PACKET_CONTENT, "SENT OCC_REQUEST (compat OCC_PING)"); + } + else + { + if (!buf_write_u8 (&c->c2.buf, OCC_PING)) + break; + dmsg (D_PACKET_CONTENT, "SENT OCC_PING"); + } + doit = true; + break; + + case OCC_PING_REPLY: + if (!buf_write_u8 (&c->c2.buf, OCC_PING_REPLY)) + break; + dmsg (D_PACKET_CONTENT, "SENT OCC_PING_REPLY"); + doit = true; + break; } if (doit) @@ -384,6 +407,14 @@ c->sig->signal_received = SIGTERM; c->sig->signal_text = "remote-exit"; break; + + case OCC_PING: + dmsg (D_PACKET_CONTENT, "RECEIVED OCC_PING"); + c->c2.occ_op = OCC_PING_REPLY; + break; + case OCC_PING_REPLY: + dmsg (D_PACKET_CONTENT, "RECEIVED OCC_PING_REPLY"); + break; } c->c2.buf.len = 0; /* don't pass packet on */ } diff -ur openvpn-2.2.2/occ.h openvpn-2.2.2-dev/occ.h --- openvpn-2.2.2/occ.h 2011-04-26 10:33:04.000000000 +0200 +++ openvpn-2.2.2-dev/occ.h 2012-05-25 23:07:18.000000000 +0200 @@ -70,6 +70,13 @@ #define OCC_EXIT 6 /* + * OCC based ping + */ +#define OCC_PING 7 +#define OCC_PING_REPLY 8 + + +/* * Used to conduct a load test command sequence * of UDP connection for empirical MTU measurement. */ diff -ur openvpn-2.2.2/options.c openvpn-2.2.2-dev/options.c --- openvpn-2.2.2/options.c 2011-12-13 17:58:56.000000000 +0100 +++ openvpn-2.2.2-dev/options.c 2012-05-25 23:20:55.000000000 +0200 @@ -229,6 +229,11 @@ "--ping-timer-rem: Run the --ping-exit/--ping-restart timer only if we have a\n" " remote address.\n" "--ping n : Ping remote once every n seconds over TCP/UDP port.\n" +#ifdef ENABLE_OCC + "--occ-ping : Ping using internal OCC protocol.\n" + "--occ-ping-compat : Use backward compatible OCC ping.\n" + " Use for clients without occ-ping support.\n" +#endif #if ENABLE_IP_PKTINFO "--multihome : Configure a multi-homed UDP server.\n" #endif @@ -1235,8 +1240,11 @@ SHOW_BOOL (ping_timer_remote); SHOW_INT (remap_sigusr1); #ifdef ENABLE_OCC + SHOW_BOOL (occ_ping); + SHOW_BOOL (occ_ping_compat); SHOW_INT (explicit_exit_notification); #endif + SHOW_BOOL (persist_tun); SHOW_BOOL (persist_local_ip); SHOW_BOOL (persist_remote_ip); @@ -4529,6 +4537,16 @@ options->ping_timer_remote = true; } #ifdef ENABLE_OCC + else if (streq (p[0], "occ-ping")) + { + VERIFY_PERMISSION (OPT_P_TIMER); + options->occ_ping = true; + } + else if (streq (p[0], "occ-ping-compat")) + { + VERIFY_PERMISSION (OPT_P_TIMER); + options->occ_ping_compat = true; + } else if (streq (p[0], "explicit-exit-notify")) { VERIFY_PERMISSION (OPT_P_EXPLICIT_NOTIFY); diff -ur openvpn-2.2.2/options.h openvpn-2.2.2-dev/options.h --- openvpn-2.2.2/options.h 2011-12-13 17:58:56.000000000 +0100 +++ openvpn-2.2.2-dev/options.h 2012-05-25 23:04:14.000000000 +0200 @@ -239,6 +239,11 @@ int ping_send_timeout; /* Send a TCP/UDP ping to remote every n seconds */ int ping_rec_timeout; /* Expect a TCP/UDP ping from remote at least once every n seconds */ bool ping_timer_remote; /* Run ping timer only if we have a remote address */ +#ifdef ENABLE_OCC + bool occ_ping; /* Enable OCC ping */ + bool occ_ping_compat; /* Enable OCC ping compatibility mode */ +#endif + bool tun_ipv6; /* Build tun dev that supports IPv6 */ # define PING_UNDEF 0 diff -ur openvpn-2.2.2/ping-inline.h openvpn-2.2.2-dev/ping-inline.h --- openvpn-2.2.2/ping-inline.h 2011-04-26 10:33:04.000000000 +0200 +++ openvpn-2.2.2-dev/ping-inline.h 2012-05-27 18:50:40.000000000 +0200 @@ -53,7 +53,14 @@ && event_timeout_trigger (&c->c2.ping_send_interval, &c->c2.timeval, !TO_LINK_DEF(c) ? ETT_DEFAULT : 1)) - check_ping_send_dowork (c); + { +#ifdef ENABLE_OCC + if(c->options.occ_ping) + c->c2.occ_op = OCC_PING; + else +#endif + check_ping_send_dowork (c); + } } #endif