src/openvpn/multi.h
6fbf66fa
 /*
  *  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.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
6fbf66fa
  *
  *  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.
  *
caa54ac3
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6fbf66fa
  */
 
98619012
 /**
  * @file Header file for server-mode related structures and functions.
  */
 
6fbf66fa
 #ifndef MULTI_H
 #define MULTI_H
 
 #if P2MP_SERVER
 
 #include "init.h"
 #include "forward.h"
 #include "mroute.h"
 #include "mbuf.h"
 #include "list.h"
 #include "schedule.h"
 #include "pool.h"
 #include "mudp.h"
 #include "mtcp.h"
 #include "perf.h"
 
09cf2ec5
 #define MULTI_PREFIX_MAX_LENGTH 256
 
6fbf66fa
 /*
  * Walk (don't run) through the routing table,
  * deleting old entries, and possibly multi_instance
  * structs as well which have been marked for deletion.
  */
 struct multi_reap
 {
81d882d5
     int bucket_base;
     int buckets_per_pass;
     time_t last_call;
6fbf66fa
 };
 
98619012
 
8dd9ff8c
 struct deferred_signal_schedule_entry
 {
81d882d5
     struct schedule_entry se;
     int signal_received;
     struct timeval wakeup;
8dd9ff8c
 };
 
98619012
 /**
  * Server-mode state structure for one single VPN tunnel.
  *
  * This structure is used by OpenVPN processes running in server-mode to
  * store state information related to one single VPN tunnel.
  *
  * The @ref tunnel_state "Structure of VPN tunnel state storage" related
  * page describes the role the structure plays when OpenVPN is running in
  * server-mode.
6fbf66fa
  */
 struct multi_instance {
81d882d5
     struct schedule_entry se;  /* this must be the first element of the structure */
     struct gc_arena gc;
     bool defined;
     bool halt;
     int refcount;
     int route_count;           /* number of routes (including cached routes) owned by this instance */
     time_t created;             /**< Time at which a VPN tunnel instance
98619012
                                  *   was created.  This parameter is set
                                  *   by the \c multi_create_instance()
                                  *   function. */
81d882d5
     struct timeval wakeup;     /* absolute time */
     struct mroute_addr real;    /**< External network address of the
98619012
                                  *   remote peer. */
81d882d5
     ifconfig_pool_handle vaddr_handle;
     char msg_prefix[MULTI_PREFIX_MAX_LENGTH];
6fbf66fa
 
81d882d5
     /* queued outgoing data in Server/TCP mode */
     unsigned int tcp_rwflags;
     struct mbuf_set *tcp_link_out_deferred;
     bool socket_set_called;
6fbf66fa
 
81d882d5
     in_addr_t reporting_addr;     /* IP address shown in status listing */
     struct in6_addr reporting_addr_ipv6; /* IPv6 address in status listing */
6fbf66fa
 
81d882d5
     bool did_open_context;
     bool did_real_hash;
     bool did_iter;
90efcacb
 #ifdef MANAGEMENT_DEF_AUTH
81d882d5
     bool did_cid_hash;
     struct buffer_list *cc_config;
90efcacb
 #endif
81d882d5
     bool connection_established_flag;
     bool did_iroutes;
     int n_clients_delta; /* added to multi_context.n_clients when instance is closed */
6fbf66fa
 
81d882d5
     struct context context;     /**< The context structure storing state
98619012
                                  *   for this VPN tunnel. */
0d1a75bf
 
 #ifdef ENABLE_ASYNC_PUSH
81d882d5
     int inotify_watch; /* watch descriptor for acf */
0d1a75bf
 #endif
6fbf66fa
 };
 
98619012
 
 /**
  * Main OpenVPN server state structure.
  *
  * This structure is used by OpenVPN processes running in server-mode to
  * store all the VPN tunnel and process-wide state.
  *
  * The @ref tunnel_state "Structure of VPN tunnel state storage" related
  * page describes the role the structure plays when OpenVPN is running in
  * server-mode.
6fbf66fa
  */
 struct multi_context {
81d882d5
 #define MC_UNDEF                      0
 #define MC_SINGLE_THREADED            (1<<0)
 #define MC_MULTI_THREADED_MASTER      (1<<1)
 #define MC_MULTI_THREADED_WORKER      (1<<2)
 #define MC_MULTI_THREADED_SCHEDULER   (1<<3)
 #define MC_WORK_THREAD                (MC_MULTI_THREADED_WORKER|MC_MULTI_THREADED_SCHEDULER)
     int thread_mode;
 
     struct multi_instance **instances;  /**< Array of multi_instances. An instance can be
65eedc35
                                          * accessed using peer-id as an index. */
 
81d882d5
     struct hash *hash;          /**< VPN tunnel instances indexed by real
98619012
                                  *   address of the remote peer. */
81d882d5
     struct hash *vhash;         /**< VPN tunnel instances indexed by
98619012
                                  *   virtual address of remote hosts. */
81d882d5
     struct hash *iter;          /**< VPN tunnel instances indexed by real
98619012
                                  *   address of the remote peer, optimized
                                  *   for iteration. */
81d882d5
     struct schedule *schedule;
     struct mbuf_set *mbuf;      /**< Set of buffers for passing data
98619012
                                  *   channel packets between VPN tunnel
                                  *   instances. */
81d882d5
     struct multi_tcp *mtcp;     /**< State specific to OpenVPN using TCP
98619012
                                  *   as external transport. */
81d882d5
     struct ifconfig_pool *ifconfig_pool;
     struct frequency_limit *new_connection_limiter;
     struct mroute_helper *route_helper;
     struct multi_reap *reaper;
     struct mroute_addr local;
     bool enable_c2c;
     int max_clients;
     int tcp_queue_limit;
     int status_file_version;
     int n_clients; /* current number of authenticated clients */
6fbf66fa
 
90efcacb
 #ifdef MANAGEMENT_DEF_AUTH
81d882d5
     struct hash *cid_hash;
     unsigned long cid_counter;
90efcacb
 #endif
 
81d882d5
     struct multi_instance *pending;
     struct multi_instance *earliest_wakeup;
     struct multi_instance **mpp_touched;
     struct context_buffers *context_buffers;
     time_t per_second_trigger;
6fbf66fa
 
81d882d5
     struct context top;         /**< Storage structure for process-wide
98619012
                                  *   configuration. */
3a957aae
 
81d882d5
     /*
      * Timer object for stale route check
      */
     struct event_timeout stale_routes_check_et;
0d1a75bf
 
 #ifdef ENABLE_ASYNC_PUSH
81d882d5
     /* mapping between inotify watch descriptors and multi_instances */
     struct hash *inotify_watchers;
0d1a75bf
 #endif
8dd9ff8c
 
81d882d5
     struct deferred_signal_schedule_entry deferred_shutdown_signal;
6fbf66fa
 };
 
 /*
  * Host route
  */
 struct multi_route
 {
81d882d5
     struct mroute_addr addr;
     struct multi_instance *instance;
6fbf66fa
 
81d882d5
 #define MULTI_ROUTE_CACHE   (1<<0)
 #define MULTI_ROUTE_AGEABLE (1<<1)
     unsigned int flags;
6fbf66fa
 
81d882d5
     unsigned int cache_generation;
     time_t last_reference;
6fbf66fa
 };
 
98619012
 
 /**************************************************************************/
 /**
  * Main event loop for OpenVPN in server mode.
  * @ingroup eventloop
  *
  * This function calls the appropriate main event loop function depending
  * on the transport protocol used:
  *  - \c tunnel_server_udp()
  *  - \c tunnel_server_tcp()
  *
  * @param top          - Top-level context structure.
6fbf66fa
  */
81d882d5
 void tunnel_server(struct context *top);
6fbf66fa
 
98619012
 
81d882d5
 const char *multi_instance_string(const struct multi_instance *mi, bool null, struct gc_arena *gc);
6fbf66fa
 
 /*
  * Called by mtcp.c, mudp.c, or other (to be written) protocol drivers
  */
 
81d882d5
 void multi_init(struct multi_context *m, struct context *t, bool tcp_mode, int thread_mode);
6fbf66fa
 
81d882d5
 void multi_uninit(struct multi_context *m);
6fbf66fa
 
81d882d5
 void multi_top_init(struct multi_context *m, const struct context *top);
6fbf66fa
 
81d882d5
 void multi_top_free(struct multi_context *m);
 
 struct multi_instance *multi_create_instance(struct multi_context *m, const struct mroute_addr *real);
 
 void multi_close_instance(struct multi_context *m, struct multi_instance *mi, bool shutdown);
 
 bool multi_process_timeout(struct multi_context *m, const unsigned int mpp_flags);
6fbf66fa
 
65eedc35
 /**
  * Handles peer floating.
  *
  * If peer is floated to a taken address, either drops packet
  * (if peer that owns address has different CN) or disconnects
  * existing peer. Updates multi_instance with new address,
  * updates hashtables in multi_context.
  */
81d882d5
 void multi_process_float(struct multi_context *m, struct multi_instance *mi);
65eedc35
 
6fbf66fa
 #define MPP_PRE_SELECT             (1<<0)
 #define MPP_CONDITIONAL_PRE_SELECT (1<<1)
 #define MPP_CLOSE_ON_SIGNAL        (1<<2)
 #define MPP_RECORD_TOUCH           (1<<3)
98619012
 
 
 /**************************************************************************/
 /**
  * Perform postprocessing of a VPN tunnel instance.
  *
  * After some VPN tunnel activity has taken place, the VPN tunnel's state
  * may need updating and some follow-up action may be required.  This
  * function controls the necessary postprocessing.  It is called by many
  * other functions that handle VPN tunnel related activity, such as \c
  * multi_process_incoming_link(), \c multi_process_outgoing_link(), \c
  * multi_process_incoming_tun(), \c multi_process_outgoing_tun(), and \c
  * multi_process_timeout(), among others.
  *
  * @param m            - The single \c multi_context structure.
  * @param mi           - The \c multi_instance of the VPN tunnel to be
  *                       postprocessed.
  * @param flags        - Fast I/O optimization flags.
  *
  * @return
  *  - True, if the VPN tunnel instance \a mi was not closed due to a
  *    signal during processing.
  *  - False, if the VPN tunnel instance \a mi was closed.
  */
81d882d5
 bool multi_process_post(struct multi_context *m, struct multi_instance *mi, const unsigned int flags);
6fbf66fa
 
98619012
 
 /**************************************************************************/
 /**
  * Demultiplex and process a packet received over the external network
  * interface.
  * @ingroup external_multiplexer
  *
  * This function determines which VPN tunnel instance the incoming packet
  * is associated with, and then calls \c process_incoming_link() to handle
  * it.  Afterwards, if the packet is destined for a broadcast/multicast
  * address or a remote host reachable through a different VPN tunnel, this
  * function takes care of sending it they are.
  *
  * @note This function is only used by OpenVPN processes which are running
  *     in server mode, and can therefore sustain multiple active VPN
  *     tunnels.
  *
  * @param m            - The single \c multi_context structure.
  * @param instance     - The VPN tunnel state structure associated with
  *                       the incoming packet, if known, as is the case
  *                       when using TCP transport. Otherwise NULL, as is
  *                       the case when using UDP transport.
  * @param mpp_flags    - Fast I/O optimization flags.
  */
81d882d5
 bool multi_process_incoming_link(struct multi_context *m, struct multi_instance *instance, const unsigned int mpp_flags);
98619012
 
 
 /**
  * Determine the destination VPN tunnel of a packet received over the
  * virtual tun/tap network interface and then process it accordingly.
  * @ingroup internal_multiplexer
  *
  * This function determines which VPN tunnel instance the packet is
  * destined for, and then calls \c process_outgoing_tun() to handle it.
  *
  * @note This function is only used by OpenVPN processes which are running
  *     in server mode, and can therefore sustain multiple active VPN
  *     tunnels.
  *
  * @param m            - The single \c multi_context structure.
  * @param mpp_flags    - Fast I/O optimization flags.
  */
81d882d5
 bool multi_process_incoming_tun(struct multi_context *m, const unsigned int mpp_flags);
 
6fbf66fa
 
81d882d5
 void multi_process_drop_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags);
98619012
 
81d882d5
 void multi_print_status(struct multi_context *m, struct status_output *so, const int version);
6fbf66fa
 
81d882d5
 struct multi_instance *multi_get_queue(struct mbuf_set *ms);
6fbf66fa
 
81d882d5
 void multi_add_mbuf(struct multi_context *m,
                     struct multi_instance *mi,
                     struct mbuf_buffer *mb);
6fbf66fa
 
81d882d5
 void multi_ifconfig_pool_persist(struct multi_context *m, bool force);
6fbf66fa
 
81d882d5
 bool multi_process_signal(struct multi_context *m);
6fbf66fa
 
81d882d5
 void multi_close_instance_on_signal(struct multi_context *m, struct multi_instance *mi);
6fbf66fa
 
81d882d5
 void init_management_callback_multi(struct multi_context *m);
6fbf66fa
 
81d882d5
 void uninit_management_callback_multi(struct multi_context *m);
6fbf66fa
 
0d1a75bf
 
 #ifdef ENABLE_ASYNC_PUSH
 /**
  * Called when inotify event is fired, which happens when acf file is closed or deleted.
  * Continues authentication and sends push_repl
  *
  * @param m multi_context
  * @param mpp_flags
  */
81d882d5
 void multi_process_file_closed(struct multi_context *m, const unsigned int mpp_flags);
 
0d1a75bf
 #endif
 
6fbf66fa
 /*
  * Return true if our output queue is not full
  */
 static inline bool
81d882d5
 multi_output_queue_ready(const struct multi_context *m,
                          const struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     if (mi->tcp_link_out_deferred)
     {
         return mbuf_len(mi->tcp_link_out_deferred) <= m->tcp_queue_limit;
     }
     else
     {
         return true;
     }
6fbf66fa
 }
 
 /*
  * Determine which instance has pending output
  * and prepare the output for sending in
  * the to_link buffer.
  */
 static inline struct multi_instance *
81d882d5
 multi_process_outgoing_link_pre(struct multi_context *m)
6fbf66fa
 {
81d882d5
     struct multi_instance *mi = NULL;
6fbf66fa
 
81d882d5
     if (m->pending)
     {
         mi = m->pending;
     }
     else if (mbuf_defined(m->mbuf))
     {
         mi = multi_get_queue(m->mbuf);
     }
     return mi;
6fbf66fa
 }
 
 /*
  * Per-client route quota management
  */
 
81d882d5
 void route_quota_exceeded(const struct multi_context *m, const struct multi_instance *mi);
6fbf66fa
 
 static inline void
81d882d5
 route_quota_inc(struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     ++mi->route_count;
6fbf66fa
 }
 
 static inline void
81d882d5
 route_quota_dec(struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     --mi->route_count;
6fbf66fa
 }
 
 /* can we add a new route? */
 static inline bool
81d882d5
 route_quota_test(const struct multi_context *m, const struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     if (mi->route_count >= mi->context.options.max_routes_per_client)
     {
         route_quota_exceeded(m, mi);
         return false;
     }
     else
6fbf66fa
     {
81d882d5
         return true;
6fbf66fa
     }
 }
 
 /*
  * Instance reference counting
  */
 
 static inline void
81d882d5
 multi_instance_inc_refcount(struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     ++mi->refcount;
6fbf66fa
 }
 
 static inline void
81d882d5
 multi_instance_dec_refcount(struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     if (--mi->refcount <= 0)
6fbf66fa
     {
81d882d5
         gc_free(&mi->gc);
         free(mi);
6fbf66fa
     }
 }
 
 static inline void
81d882d5
 multi_route_del(struct multi_route *route)
6fbf66fa
 {
81d882d5
     struct multi_instance *mi = route->instance;
     route_quota_dec(mi);
     multi_instance_dec_refcount(mi);
     free(route);
6fbf66fa
 }
 
 static inline bool
81d882d5
 multi_route_defined(const struct multi_context *m,
                     const struct multi_route *r)
6fbf66fa
 {
81d882d5
     if (r->instance->halt)
     {
         return false;
     }
     else if ((r->flags & MULTI_ROUTE_CACHE)
              && r->cache_generation != m->route_helper->cache_generation)
     {
         return false;
     }
     else if ((r->flags & MULTI_ROUTE_AGEABLE)
              && r->last_reference + m->route_helper->ageable_ttl_secs < now)
     {
         return false;
     }
     else
     {
         return true;
     }
6fbf66fa
 }
 
 /*
65eedc35
  * Takes prefix away from multi_instance.
  */
 void
81d882d5
 ungenerate_prefix(struct multi_instance *mi);
65eedc35
 
 /*
6fbf66fa
  * Set a msg() function prefix with our current client instance ID.
  */
 
 static inline void
81d882d5
 set_prefix(struct multi_instance *mi)
6fbf66fa
 {
 #ifdef MULTI_DEBUG_EVENT_LOOP
81d882d5
     if (mi->msg_prefix[0])
     {
         printf("[%s]\n", mi->msg_prefix);
     }
6fbf66fa
 #endif
81d882d5
     msg_set_prefix(mi->msg_prefix[0] ? mi->msg_prefix : NULL);
6fbf66fa
 }
 
 static inline void
81d882d5
 clear_prefix(void)
6fbf66fa
 {
 #ifdef MULTI_DEBUG_EVENT_LOOP
81d882d5
     printf("[NULL]\n");
6fbf66fa
 #endif
81d882d5
     msg_set_prefix(NULL);
6fbf66fa
 }
 
 /*
  * Instance Reaper
  *
  * Reaper constants.  The reaper is the process where the virtual address
  * and virtual route hash table is scanned for dead entries which are
  * then removed.  The hash table could potentially be quite large, so we
  * don't want to reap in a single pass.
  */
 
 #define REAP_MAX_WAKEUP   10  /* Do reap pass at least once per n seconds */
 #define REAP_DIVISOR     256  /* How many passes to cover whole hash table */
 #define REAP_MIN          16  /* Minimum number of buckets per pass */
 #define REAP_MAX        1024  /* Maximum number of buckets per pass */
 
 /*
  * Mark a cached host route for deletion after this
  * many seconds without any references.
  */
 #define MULTI_CACHE_ROUTE_TTL 60
 
 static inline void
81d882d5
 multi_reap_process(const struct multi_context *m)
6fbf66fa
 {
81d882d5
     void multi_reap_process_dowork(const struct multi_context *m);
 
     if (m->reaper->last_call != now)
     {
         multi_reap_process_dowork(m);
     }
6fbf66fa
 }
 
 static inline void
81d882d5
 multi_process_per_second_timers(struct multi_context *m)
6fbf66fa
 {
81d882d5
     if (m->per_second_trigger != now)
6fbf66fa
     {
81d882d5
         void multi_process_per_second_timers_dowork(struct multi_context *m);
 
         multi_process_per_second_timers_dowork(m);
         m->per_second_trigger = now;
6fbf66fa
     }
 }
 
 /*
  * Compute earliest timeout expiry from the set of
  * all instances.  Output:
  *
  * m->earliest_wakeup : instance needing the earliest service.
  * dest               : earliest timeout as a delta in relation
  *                      to current time.
  */
 static inline void
81d882d5
 multi_get_timeout(struct multi_context *m, struct timeval *dest)
6fbf66fa
 {
81d882d5
     struct timeval tv, current;
6fbf66fa
 
81d882d5
     CLEAR(tv);
     m->earliest_wakeup = (struct multi_instance *) schedule_get_earliest_wakeup(m->schedule, &tv);
     if (m->earliest_wakeup)
6fbf66fa
     {
81d882d5
         ASSERT(!openvpn_gettimeofday(&current, NULL));
         tv_delta(dest, &current, &tv);
         if (dest->tv_sec >= REAP_MAX_WAKEUP)
         {
             m->earliest_wakeup = NULL;
             dest->tv_sec = REAP_MAX_WAKEUP;
             dest->tv_usec = 0;
         }
6fbf66fa
     }
81d882d5
     else
6fbf66fa
     {
81d882d5
         dest->tv_sec = REAP_MAX_WAKEUP;
         dest->tv_usec = 0;
6fbf66fa
     }
 }
 
98619012
 
 /**
  * Send a packet over the virtual tun/tap network interface to its locally
  * reachable destination.
  * @ingroup internal_multiplexer
  *
  * This function calls \c process_outgoing_tun() to perform the actual
  * sending of the packet.  Afterwards, it calls \c multi_process_post() to
  * perform server-mode postprocessing.
  *
  * @param m            - The single \c multi_context structure.
  * @param mpp_flags    - Fast I/O optimization flags.
  *
  * @return
  *  - True, if the \c multi_instance associated with the packet sent was
  *    not closed due to a signal during processing.
  *  - Falls, if the \c multi_instance was closed.
6fbf66fa
  */
 static inline bool
81d882d5
 multi_process_outgoing_tun(struct multi_context *m, const unsigned int mpp_flags)
6fbf66fa
 {
81d882d5
     struct multi_instance *mi = m->pending;
     bool ret = true;
6fbf66fa
 
81d882d5
     ASSERT(mi);
6fbf66fa
 #ifdef MULTI_DEBUG_EVENT_LOOP
81d882d5
     printf("%s -> TUN len=%d\n",
            id(mi),
            mi->context.c2.to_tun.len);
6fbf66fa
 #endif
81d882d5
     set_prefix(mi);
     process_outgoing_tun(&mi->context);
     ret = multi_process_post(m, mi, mpp_flags);
     clear_prefix();
     return ret;
6fbf66fa
 }
 
98619012
 
 
6fbf66fa
 static inline bool
81d882d5
 multi_process_outgoing_link_dowork(struct multi_context *m, struct multi_instance *mi, const unsigned int mpp_flags)
6fbf66fa
 {
81d882d5
     bool ret = true;
     set_prefix(mi);
     process_outgoing_link(&mi->context);
     ret = multi_process_post(m, mi, mpp_flags);
     clear_prefix();
     return ret;
6fbf66fa
 }
 
 /*
  * Check for signals.
  */
81d882d5
 #define MULTI_CHECK_SIG(m) EVENT_LOOP_CHECK_SIGNAL(&(m)->top, multi_process_signal, (m))
6fbf66fa
 
 static inline void
81d882d5
 multi_set_pending(struct multi_context *m, struct multi_instance *mi)
6fbf66fa
 {
81d882d5
     m->pending = mi;
6fbf66fa
 }
 
 #endif /* P2MP_SERVER */
 #endif /* MULTI_H */