⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multi.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  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-2004 James Yonan <jim@yonan.net> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  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 */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#if P2MP#include "multi.h"#include "init.h"#include "forward.h"#include "push.h"#include "misc.h"#include "otime.h"#include "memdbg.h"#include "forward-inline.h"#define MULTI_DEBUG // JYFIXME//#define MULTI_DEBUG_EVENT_LOOP // JYFIXME/* * 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 60static bool multi_process_post (struct multi_thread *mt, struct multi_instance *mi);#ifdef MULTI_DEBUG_EVENT_LOOPstatic const char *id (struct multi_instance *mi){  if (mi)    return tls_common_name (mi->context.c2.tls_multi, false);  else    return "NULL";}#endifstatic voidlearn_address_script (const struct multi_context *m,		      const struct multi_instance *mi,		      const char *op,		      const struct mroute_addr *addr){  if (m->learn_address_script)    {      struct gc_arena gc = gc_new ();      struct buffer cmd = alloc_buf_gc (256, &gc);      mutex_lock_static (L_SCRIPT);      setenv_str ("script_type", "learn-address");      buf_printf (&cmd, "%s \"%s\" \"%s\"",		  m->learn_address_script,		  op,		  mroute_addr_print (addr, &gc));      if (mi)	buf_printf (&cmd, " \"%s\"", tls_common_name (mi->context.c2.tls_multi, true));      system_check (BSTR (&cmd), "learn-address command failed", false);      mutex_unlock_static (L_SCRIPT);      gc_free (&gc);    }}static voidmulti_reap_range (const struct multi_context *m,		  int start_bucket,		  int end_bucket){  struct gc_arena gc = gc_new ();  struct hash_iterator hi;  struct hash_element *he;  if (start_bucket < 0)    {      start_bucket = 0;      end_bucket = hash_n_buckets (m->vhash);    }  msg (D_MULTI_DEBUG, "MULTI: REAP range %d -> %d", start_bucket, end_bucket);  hash_iterator_init_range (m->vhash, &hi, true, start_bucket, end_bucket);  while ((he = hash_iterator_next (&hi)) != NULL)    {      struct multi_route *r = (struct multi_route *) he->value;      if (!multi_route_defined (m, r))	{	  msg (D_MULTI_DEBUG, "MULTI: REAP DEL %s",	       mroute_addr_print (&r->addr, &gc));	  learn_address_script (m, NULL, "delete", &r->addr);	  multi_route_del (r);	  hash_iterator_delete_element (&hi);	}    }  hash_iterator_free (&hi);  gc_free (&gc);}static voidmulti_reap_all (const struct multi_context *m){  multi_reap_range (m, -1, 0);}static struct multi_reap *multi_reap_new (int buckets_per_pass){  struct multi_reap *mr;  ALLOC_OBJ (mr, struct multi_reap);  mr->bucket_base = 0;  mr->buckets_per_pass = buckets_per_pass;  mr->last_call = now;  return mr;}static voidmulti_reap_process_dowork (const struct multi_context *m){  struct multi_reap *mr = m->reaper;  if (mr->bucket_base >= hash_n_buckets (m->vhash))    mr->bucket_base = 0;  multi_reap_range (m, mr->bucket_base, mr->bucket_base + mr->buckets_per_pass);   mr->bucket_base += mr->buckets_per_pass;  mr->last_call = now;}static inline voidmulti_reap_process (const struct multi_context *m){  if (m->reaper->last_call != now)    multi_reap_process_dowork (m);}static voidmulti_reap_free (struct multi_reap *mr){  free (mr);}/* * How many buckets in vhash to reap per pass. */static intreap_buckets_per_pass (int n_buckets){  return constrain_int (n_buckets / REAP_DIVISOR, REAP_MIN, REAP_MAX);}/* * Main initialization function, init multi_context object. */static voidmulti_init (struct multi_context *m, struct context *t){  int dev = DEV_TYPE_UNDEF;  msg (D_MULTI_LOW, "MULTI: multi_init called, r=%d v=%d",       t->options.real_hash_size,       t->options.virtual_hash_size);  /*   * Get tun/tap/null device type   */  dev = dev_type_enum (t->options.dev, t->options.dev_type);  /*   * Init our multi_context object.   */  CLEAR (*m);  /*   * Real address hash table (source port number is   * considered to be part of the address).  Used   * to determine which client sent an incoming packet   * which is seen on the TCP/UDP socket.   */  m->hash = hash_init (t->options.real_hash_size,		       mroute_addr_hash_function,		       mroute_addr_compare_function);  /*   * Virtual address hash table.  Used to determine   * which client to route a packet to.    */  m->vhash = hash_init (t->options.virtual_hash_size,			mroute_addr_hash_function,			mroute_addr_compare_function);  /*   * This hash table is a clone of m->hash but with a   * bucket size of one so that it can be used   * for fast iteration through the list.   */  m->iter = hash_init (1,		       mroute_addr_hash_function,		       mroute_addr_compare_function);  /*   * This is our scheduler, for time-based wakeup   * events.   */  m->schedule = schedule_init ();  /*   * Limit frequency of incoming connections to control   * DoS.   */  m->new_connection_limiter = frequency_limit_init (t->options.cf_max,						    t->options.cf_per);  /*   * Allocate broadcast/multicast buffer list   */  m->mbuf = mbuf_init (t->options.n_bcast_buf);  /*   * Possibly allocate an ifconfig pool, do it   * differently based on whether a tun or tap style   * tunnel.   */  if (t->options.ifconfig_pool_defined)    {      if (dev == DEV_TYPE_TUN)	{	  m->ifconfig_pool = ifconfig_pool_init (IFCONFIG_POOL_30NET,						 t->options.ifconfig_pool_start,						 t->options.ifconfig_pool_end);	}      else if (dev == DEV_TYPE_TAP)	{	  m->ifconfig_pool = ifconfig_pool_init (IFCONFIG_POOL_INDIV,						 t->options.ifconfig_pool_start,						 t->options.ifconfig_pool_end);	}    }  /*   * Help us keep track of routing table.   */  m->route_helper = mroute_helper_init (MULTI_CACHE_ROUTE_TTL);  /*   * Initialize route and instance reaper.   */  m->reaper = multi_reap_new (reap_buckets_per_pass (t->options.virtual_hash_size));  /*   * Get local ifconfig address   */  CLEAR (m->local);  ASSERT (t->c1.tuntap);  mroute_extract_in_addr_t (&m->local, t->c1.tuntap->local);  /*   * Remember possible learn_address_script   */  m->learn_address_script = t->options.learn_address_script;  /*   * Allow client <-> client communication, without going through   * tun/tap interface and network stack?   */  m->enable_c2c = t->options.enable_c2c;}const char *multi_instance_string (struct multi_instance *mi, bool null, struct gc_arena *gc){  if (mi)    {      struct buffer out = alloc_buf_gc (256, gc);      const char *cn = tls_common_name (mi->context.c2.tls_multi, true);      if (cn)	buf_printf (&out, "%s/", cn);      buf_printf (&out, "%s", mroute_addr_print (&mi->real, gc));      return BSTR (&out);    }  else if (null)    return NULL;  else    return "UNDEF";}/* * Set a msg() function prefix with our current client instance ID. */static inline voidset_prefix (struct multi_instance *mi){#ifdef MULTI_DEBUG_EVENT_LOOP  if (mi->msg_prefix)    printf ("[%s]\n", mi->msg_prefix);#endif  msg_set_prefix (mi->msg_prefix);}static inline voidclear_prefix (void){#ifdef MULTI_DEBUG_EVENT_LOOP  printf ("[NULL]\n");#endif  msg_set_prefix (NULL);}voidgenerate_prefix (struct multi_instance *mi){  mi->msg_prefix = multi_instance_string (mi, true, &mi->gc);  set_prefix (mi);}voidungenerate_prefix (struct multi_instance *mi){  mi->msg_prefix = NULL;  set_prefix (mi);}/* * Tell the route helper about deleted iroutes so * that it can update its mask of currently used * CIDR netlengths. */static voidmulti_del_iroutes (struct multi_context *m,		   struct multi_instance *mi){  const struct iroute *ir;  for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)    mroute_helper_del_iroute (m->route_helper, ir);}static voidmulti_close_instance (struct multi_context *m,		      struct multi_instance *mi,		      bool shutdown){  ASSERT (!mi->halt);  mi->halt = true;  msg (D_MULTI_LOW, "MULTI: multi_close_instance called");  if (!shutdown)    {      if (mi->did_real_hash)	{	  ASSERT (hash_remove (m->hash, &mi->real));	}      if (mi->did_iter)	{	  ASSERT (hash_remove (m->iter, &mi->real));	}      schedule_remove_entry (m->schedule, (struct schedule_entry *) mi);      ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle);      multi_del_iroutes (m, mi);      mbuf_dereference_instance (m->mbuf, mi);    }  if (mi->context.options.client_disconnect_script)    {      struct gc_arena gc = gc_new ();      struct buffer cmd = alloc_buf_gc (256, &gc);      mutex_lock_static (L_SCRIPT);      setenv_str ("script_type", "client-disconnect");      /* setenv incoming cert common name for script */      setenv_str ("common_name", tls_common_name (mi->context.c2.tls_multi, false));      /* setenv client real IP address */      setenv_trusted (get_link_socket_info (&mi->context));      buf_printf (&cmd, "%s", mi->context.options.client_disconnect_script);      system_check (BSTR (&cmd), "client-disconnect command failed", false);      mutex_unlock_static (L_SCRIPT);      gc_free (&gc);    }  if (mi->did_open_context)    {      close_context (&mi->context, SIGTERM);    }  ungenerate_prefix (mi);  /*   * Don't actually delete the instance memory allocation yet,   * because virtual routes may still point to it.  Let the   * vhash reaper deal with it.   */  multi_instance_dec_refcount (mi);}/* * Called on shutdown or restart. */static voidmulti_uninit (struct multi_context *m){  if (m->hash)    {      struct hash_iterator hi;      struct hash_element *he;      hash_iterator_init (m->iter, &hi, true);      while ((he = hash_iterator_next (&hi)))	{	  struct multi_instance *mi = (struct multi_instance *) he->value;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -