openvpn/ping.c

93 lines
2.8 KiB
C
Raw Normal View History

/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "syshead.h"
#include "ping.h"
#include "memdbg.h"
#include "ping-inline.h"
/*
* This random string identifies an OpenVPN ping packet.
* It should be of sufficient length and randomness
* so as not to collide with other tunnel data.
*
* PING_STRING_SIZE must be sizeof (ping_string)
*/
const uint8_t ping_string[] = {
0x2a, 0x18, 0x7b, 0xf3, 0x64, 0x1e, 0xb4, 0xcb,
0x07, 0xed, 0x2d, 0x0a, 0x98, 0x1f, 0xc7, 0x48
};
/*
* Should we exit or restart due to ping (or other authenticated packet)
* not received in n seconds?
*/
void
check_ping_restart_dowork (struct context *c)
{
struct gc_arena gc = gc_new ();
switch (c->options.ping_rec_timeout_action)
{
case PING_EXIT:
msg (M_INFO, "%sInactivity timeout (--ping-exit), exiting",
format_common_name (c, &gc));
c->sig->signal_received = SIGTERM;
c->sig->signal_text = "ping-exit";
break;
case PING_RESTART:
msg (M_INFO, "%sInactivity timeout (--ping-restart), restarting",
format_common_name (c, &gc));
c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Ping Restart */
c->sig->signal_text = "ping-restart";
break;
default:
ASSERT (0);
}
gc_free (&gc);
}
/*
* Should we ping the remote?
*/
void
check_ping_send_dowork (struct context *c)
{
c->c2.buf = c->c2.buffers->aux_buf;
ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame)));
ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame)));
ASSERT (buf_write (&c->c2.buf, ping_string, sizeof (ping_string)));
/*
* We will treat the ping like any other outgoing packet,
* encrypt, sign, etc.
*/
encrypt_sign (c, true);
Exclude ping and control packets from activity Problem: using --ping and --inactive together partially defeats the point of using --inactive as periodic ping packets are counted as activity. Here is the original discussion: http://article.gmane.org/gmane.network.openvpn.devel/3676 It turns out that "activity" is detected and recorded in two places in the code, both in forward.c: in process_outgoing_tun() for received packets, after they've been decrypted and sent to the TUN device; and in process_outgoing_link(), after they've been encrypted and written to the network socket. In the first case we can be sure that packets that get so far are really due to user activity, whereas in the second case there can be non-user packets (like OpenVPN's internal ping packets, and TLS control packets), and those should not be counted as activity as they are not coming from the user. So a need arises to detect those control packets and not count them as activity for the purposes of --inactive. Unfortunately, at that stage packets are already compressed and encrypted, so it's not possible to look into them to see what they are. However, there seems to be a convention in the code that packets whose buffer length in the context_2 structure is 0 should be ignored for certain purposes. TLS control packets follow that convention already, so this patch makes a small change in the code that generates the ping packets to set their buffer length to 0 as well. Finally, the call to register_activity() in process_outgoing_link() is made conditional to the buffer length being > 0. According to my tests, now --inactive behaves correctly according to the configured parameters (time or time+bytes) even when --ping is being used. forward.c: Call register_activity() in process_outgoing_link() only if the packet is not a ping or TLS control packet. openvpn.8: Updated the description of --inactive to describe the new semantics. ping.c: Set c->c2.buf.len = 0 after the ping packet has been generated and encrypted. Test routine is described here: <https://community.openvpn.net/openvpn/wiki/PingInactivePatch?version=6> Signed-off-by: Davide Brini <dave_br@gmx.com> Acked-by: David Sommerseth <dazo@users.sourceforge.net> Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
2010-05-02 17:07:38 +08:00
/* Set length to 0, so it won't be counted as activity */
c->c2.buf.len = 0;
dmsg (D_PING, "SENT PING");
}