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

📄 multi.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 4 页
字号:
 */static voidmulti_connection_established (struct multi_context *m, struct multi_instance *mi){  struct gc_arena gc = gc_new ();  in_addr_t local=0, remote=0;  const char *dynamic_config_file = NULL;  bool dynamic_config_file_mark_for_delete = false;  /* acquire script mutex */  mutex_lock_static (L_SCRIPT);  /* generate a msg() prefix for this client instance */  generate_prefix (mi);  /* delete instances of previous clients with same common-name */  if (!mi->context.options.duplicate_cn)    multi_delete_dup (m, mi);  /*   * Get a pool address, which may be released before the end   * of this function if it's not needed.   */  if (m->ifconfig_pool)    {      mi->vaddr_handle = ifconfig_pool_acquire (m->ifconfig_pool, &local, &remote, tls_common_name (mi->context.c2.tls_multi, true));      if (mi->vaddr_handle >= 0)	{	  if (local)	    setenv_in_addr_t ("ifconfig_pool_local", local);	  if (remote)	    setenv_in_addr_t ("ifconfig_pool_remote", remote);	}      else	{	  msg (D_MULTI_ERRORS, "MULTI: no free --ifconfig-pool addresses are available");	}    }  /* 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));  /*   * instance-specific directives to be processed:   *   *   iroute start-ip end-ip   *   ifconfig-push local remote-netmask   *   push   */  /*   * Run --client-connect script.   */  if (mi->context.options.client_connect_script)    {      struct buffer cmd = alloc_buf_gc (256, &gc);      setenv_str ("script_type", "client-connect");      dynamic_config_file = create_temp_filename (mi->context.options.tmp_dir, &gc);      delete_file (dynamic_config_file);      buf_printf (&cmd, "%s %s",		  mi->context.options.client_connect_script,		  dynamic_config_file);      system_check (BSTR (&cmd), "client-connect command failed", false);      if (test_file (dynamic_config_file))	{	  dynamic_config_file_mark_for_delete = true;	}      else	{	  dynamic_config_file = NULL;	}    }  /*   * If client connect script was not run, or if it   * was run but did not create a dynamic config file,   * try to get a dynamic config file from the   * --client-config-dir directory.   */  if (!dynamic_config_file)    {      dynamic_config_file = gen_path	(mi->context.options.client_config_dir,	 tls_common_name (mi->context.c2.tls_multi, false),	 &gc);      if (!test_file (dynamic_config_file))	dynamic_config_file = NULL;    }  /*   * Load the dynamic options.   */  if (dynamic_config_file)    {      unsigned int option_types_found = 0;      options_server_import (&mi->context.options,			     dynamic_config_file,			     D_IMPORT_ERRORS,			     OPT_P_PUSH|OPT_P_INSTANCE|OPT_P_TIMER|OPT_P_CONFIG,			     &option_types_found);      do_deferred_options (&mi->context, option_types_found);    }  /*   * Delete script-generated dynamic config file.   */  if (dynamic_config_file && dynamic_config_file_mark_for_delete)    {      if (!delete_file (dynamic_config_file))	msg (D_MULTI_ERRORS, "MULTI: problem deleting temporary file: %s",	     dynamic_config_file);    }  /*   * If ifconfig addresses were set by dynamic config file,   * release pool addresses, otherwise keep them.   */  if (mi->context.options.push_ifconfig_defined)    {      /* ifconfig addresses were set statically,	 release dynamic allocation */      ifconfig_pool_release (m->ifconfig_pool, mi->vaddr_handle);      mi->vaddr_handle = -1;      mi->context.c2.push_ifconfig_defined = true;      mi->context.c2.push_ifconfig_local = mi->context.options.push_ifconfig_local;      mi->context.c2.push_ifconfig_remote_netmask = mi->context.options.push_ifconfig_remote_netmask;    }  else    {      if (mi->vaddr_handle >= 0)	{	  /* use pool ifconfig address(es) */	  mi->context.c2.push_ifconfig_local = remote;	  if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)	    {	      mi->context.c2.push_ifconfig_remote_netmask = local;	      mi->context.c2.push_ifconfig_defined = true;	    }	  else if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TAP)	    {	      mi->context.c2.push_ifconfig_remote_netmask = mi->context.c1.tuntap->remote_netmask;	      mi->context.c2.push_ifconfig_defined = true;	    }	}    }  /*   * make sure we got ifconfig settings from somewhere   */  if (!mi->context.c2.push_ifconfig_defined)    {      msg (D_MULTI_ERRORS, "MULTI: no dynamic or static remote --ifconfig address is available for %s",	   multi_instance_string (mi, false, &gc));    }  /*   * For routed tunnels, set up internal route to endpoint   * plus add all iroute routes.   */  if (TUNNEL_TYPE (mi->context.c1.tuntap) == DEV_TYPE_TUN)    {      if (mi->context.c2.push_ifconfig_defined)	{	  multi_learn_in_addr_t (m, mi, mi->context.c2.push_ifconfig_local, -1);	  msg (D_MULTI_LOW, "MULTI: primary virtual IP for %s: %s",	       multi_instance_string (mi, false, &gc),	       print_in_addr_t (mi->context.c2.push_ifconfig_local, false, &gc));	}      /* add routes locally, pointing to new client, if	 --iroute options have been specified */      multi_add_iroutes (m, mi);    }  else if (mi->context.options.iroutes)    {      msg (D_MULTI_ERRORS, "MULTI: --iroute options rejected for %s -- iroute only works with tun-style tunnels",	   multi_instance_string (mi, false, &gc));    }  /*   * Reply now to client's PUSH_REQUEST query   */  mi->context.c2.push_reply_deferred = false;  mutex_unlock_static (L_SCRIPT);  gc_free (&gc);}/* * 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 voidmulti_get_timeout (struct multi_thread *mt, struct timeval *dest){  struct timeval tv, current;  mt->earliest_wakeup = (struct multi_instance *) schedule_get_earliest_wakeup (mt->multi->schedule, &tv);  if (mt->earliest_wakeup)    {      ASSERT (!gettimeofday (&current, NULL));      tv_delta (dest, &current, &tv);      if (dest->tv_sec >= REAP_MAX_WAKEUP)	{	  mt->earliest_wakeup = NULL;	  dest->tv_sec = REAP_MAX_WAKEUP;	  dest->tv_usec = 0;	}    }  else    {      dest->tv_sec = REAP_MAX_WAKEUP;      dest->tv_usec = 0;    }}/* * Add a packet to a client instance output queue. */static inline voidmulti_unicast (struct multi_context *m,	       const struct buffer *buf,	       struct multi_instance *mi){  struct mbuf_buffer *mb;  if (BLEN (buf) > 0)    {      mb = mbuf_alloc_buf (buf);      multi_add_mbuf (m, mi, mb);      mbuf_free_buf (mb);    }}/* * Broadcast a packet to all clients. */voidmulti_bcast (struct multi_context *m,	     const struct buffer *buf,	     struct multi_instance *omit){  struct hash_iterator hi;  struct hash_element *he;  struct multi_instance *mi;  struct mbuf_buffer *mb;  if (BLEN (buf) > 0)    {#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("BCAST len=%d\n", BLEN (buf));#endif      mb = mbuf_alloc_buf (buf);      hash_iterator_init (m->iter, &hi, true);      while ((he = hash_iterator_next (&hi)))	{	  mi = (struct multi_instance *) he->value;	  if (mi != omit)	    multi_add_mbuf (m, mi, mb);	}      hash_iterator_free (&hi);      mbuf_free_buf (mb);    }}/* * Given a time delta, indicating that we wish to be * awoken by the scheduler at time now + delta, figure * a sigma parameter (in microseconds) that represents * a sort of fuzz factor around delta, so that we're * really telling the scheduler to wake us up any time * between now + delta - sigma and now + delta + sigma. * * The sigma parameter helps the scheduler to run more efficiently. * Sigma should be no larger than TV_WITHIN_SIGMA_MAX_USEC */static inline unsigned intcompute_wakeup_sigma (const struct timeval *delta){  if (delta->tv_sec < 1)    {      /* if < 1 sec, fuzz = # of microseconds / 8 */      return delta->tv_usec >> 3;    }  else    {      /* if < 10 minutes, fuzz = 13.1% of timeout */      if (delta->tv_sec < 600)	return delta->tv_sec << 17;      else	return 120000000; /* if >= 10 minutes, fuzz = 2 minutes */    }}/* * Figure instance-specific timers, convert * earliest to absolute time in mi->wakeup, * call scheduler with our future wakeup time. * * Also close context on signal. */static boolmulti_process_post (struct multi_thread *mt, struct multi_instance *mi){  if (!IS_SIG (&mi->context))    {      /* figure timeouts and fetch possible outgoing	 to_link packets (such as ping or TLS control) */      pre_select (&mi->context);      if (!IS_SIG (&mi->context))	{	  /* calculate an absolute wakeup time */	  ASSERT (!gettimeofday (&mi->wakeup, NULL));	  tv_add (&mi->wakeup, &mi->context.c2.timeval);	  /* tell scheduler to wake us up at some point in the future */	  schedule_add_entry (mt->multi->schedule,			      (struct schedule_entry *) mi,			      &mi->wakeup,			      compute_wakeup_sigma (&mi->context.c2.timeval));	  /* connection is "established" when SSL/TLS key negotiation succeeds */	  if (!mi->connection_established_flag && CONNECTION_ESTABLISHED (&mi->context))	    {	      multi_connection_established (mt->multi, mi);	      mi->connection_established_flag = true;	    }	}    }  if (IS_SIG (&mi->context))    {      /* make sure that pending is nullified if	 it points to our soon-to-be-deleted instance */      if (mt->pending == mi)	mt->pending = NULL;      if (mt->earliest_wakeup == mi)	mt->earliest_wakeup = NULL;      multi_close_instance (mt->multi, mi, false);      return false;    }  else    {      /* continue to pend on output? */      mt->pending = ANY_OUT (&mi->context) ? mi : NULL;#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("POST %s[%d] to=%d lo=%d/%d w=%d/%d\n",	      id(mi),	      (int) (mi == mt->pending),	      mi ? mi->context.c2.to_tun.len : -1,	      mi ? mi->context.c2.to_link.len : -1,	      (mi && mi->context.c2.fragment) ? mi->context.c2.fragment->outgoing.len : -1,	      (int)mi->context.c2.timeval.tv_sec,	      (int)mi->context.c2.timeval.tv_usec);#endif      return true;    }}/* * Process packets in the TCP/UDP socket -> TUN/TAP interface direction, * i.e. client -> server direction. */static voidmulti_process_incoming_link (struct multi_thread *mt){  struct gc_arena gc = gc_new ();  if (BLEN (&mt->top.c2.buf) > 0)    {      struct context *c;      struct mroute_addr src, dest;      unsigned int mroute_flags;      struct multi_instance *mi;      struct multi_context *m = mt->multi;#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("UDP -> TUN [%d]\n", BLEN (&mt->top.c2.buf));#endif      ASSERT (!mt->pending);      mt->pending = multi_get_create_instance (mt);      if (!mt->pending)	return;      set_prefix (mt->pending);      /* get instance context */      c = &mt->pending->context;      /* transfer packet pointer from top-level context buffer to instance */      c->c2.buf = mt->top.c2.buf;      /* transfer from-addr from top-level context buffer to instance */      c->c2.from = mt->top.c2.from;      /* decrypt in instance context */      process_incoming_link (c);      if (TUNNEL_TYPE (mt->top.c1.tuntap) == DEV_TYPE_TUN)	{	  /* extract packet source and dest addresses */	  mroute_flags = mroute_extract_addr_from_packet (&src,							  &dest,							  &c->c2.to_tun,							  DEV_TYPE_TUN);	  /* drop packet if extract failed */	  if (!(mroute_flags & MROUTE_EXTRACT_SUCCEEDED))	    {	      c->c2.to_tun.len = 0;	    }	  /* make sure that source address is associated with this client */	  else if (multi_get_instance_by_virtual_addr (m, &src, true) != mt->pending)	    {	      msg (D_MULTI_DEBUG, "MULTI: bad source address from client [%s], packet dropped",		   mroute_addr_print (&src, &gc));	      c->c2.to_tun.len = 0;	    }	  /* client-to-client communication enabled? */	  else if (m->enable_c2c)	    {	      /* multicast? */	      if (mroute_flags & MROUTE_EXTRACT_MCAST)		{		  /* for now, treat multicast as broadcast */		  multi_bcast (m, &c->c2.to_tun, mt->pending);		}	      else /* possible client to client routing */		{		  ASSERT (!(mroute_flags & MROUTE_EXTRACT_BCAST));		  mi = multi_get_instance_by_virtual_addr (m, &dest, true);		  		  /* if dest addr is a known client, route to it */		  if (mi)		    {		      multi_unicast (m, &c->c2.to_tun, mi);		      register_activity (c);		      c->c2.to_tun.len = 0;		    }		}	    }	}      else if (TUNNEL_TYPE (mt->top.c1.tuntap) == DEV_TYPE_TAP)	{	  /* extract packet source and dest addresses */	  mroute_flags = mroute_extract_addr_from_packet (&src,

⌨️ 快捷键说明

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