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

📄 multi.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 4 页
字号:
	  mi->did_iter = false;	  multi_close_instance (m, mi, true);	}      hash_iterator_free (&hi);      multi_reap_all (m);      hash_free (m->hash);      hash_free (m->vhash);      hash_free (m->iter);      m->hash = NULL;      schedule_free (m->schedule);      mbuf_free (m->mbuf);      ifconfig_pool_free (m->ifconfig_pool);      frequency_limit_free (m->new_connection_limiter);      multi_reap_free (m->reaper);      mroute_helper_free (m->route_helper);    }}/* * Create a client instance object for a newly connected client. */static struct multi_instance *multi_create_instance (struct multi_thread *mt, const struct mroute_addr *real){  struct gc_arena gc = gc_new ();  struct multi_instance *mi;  ALLOC_OBJ_CLEAR (mi, struct multi_instance);  msg (D_MULTI_LOW, "MULTI: multi_create_instance called");  mi->gc = gc_new ();  multi_instance_inc_refcount (mi);  mroute_addr_init (&mi->real);  mi->vaddr_handle = -1;  mi->created = now;  mi->real = *real;  generate_prefix (mi);  if (!hash_add (mt->multi->iter, &mi->real, mi, false))    {      msg (D_MULTI_LOW, "MULTI: unable to add real address [%s] to iterator hash table",	   mroute_addr_print (&mi->real, &gc));      goto err;    }  mi->did_iter = true;  inherit_context_child (&mi->context, &mt->top);  mi->did_open_context = true;  mi->context.c2.push_reply_deferred = true;  if (!multi_process_post (mt, mi))    {      msg (D_MULTI_ERRORS, "MULTI: signal occurred during client instance initialization");      goto err;    }  gc_free (&gc);  return mi; err:  multi_close_instance (mt->multi, mi, false);  gc_free (&gc);  return NULL;}/* * Get a client instance based on real address.  If * the instance doesn't exist, create it while * maintaining real address hash table atomicity. */static struct multi_instance *multi_get_create_instance (struct multi_thread *mt){  struct gc_arena gc = gc_new ();  struct mroute_addr real;  struct multi_instance *mi = NULL;  struct hash *hash = mt->multi->hash;  if (mroute_extract_sockaddr_in (&real, &mt->top.c2.from, true))    {      struct hash_element *he;      const uint32_t hv = hash_value (hash, &real);      struct hash_bucket *bucket = hash_bucket (hash, hv);        hash_bucket_lock (bucket);      he = hash_lookup_fast (hash, bucket, &real, hv);      if (he)	{	  mi = (struct multi_instance *) he->value;	}      else	{	  if (!mt->top.c2.tls_auth_standalone	      || tls_pre_decrypt_lite (mt->top.c2.tls_auth_standalone, &mt->top.c2.from, &mt->top.c2.buf))	    {	      if (frequency_limit_event_allowed (mt->multi->new_connection_limiter))		{		  mi = multi_create_instance (mt, &real);		  if (mi)		    {		      hash_add_fast (hash, bucket, &mi->real, hv, mi);		      mi->did_real_hash = true;		    }		}	      else		{		  msg (D_MULTI_ERRORS,		       "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",		       mroute_addr_print (&real, &gc));		}	    }	}      hash_bucket_unlock (bucket);#ifdef MULTI_DEBUG      if (check_debug_level (D_MULTI_DEBUG))	{	  const char *status;	  if (he && mi)	    status = "[succeeded]";	  else if (!he && mi)	    status = "[created]";	  else	    status = "[failed]";		  msg (D_MULTI_DEBUG, "GET INST BY REAL: %s %s",	       mroute_addr_print (&real, &gc),	       status);	}#endif    }  gc_free (&gc);  ASSERT (!(mi && mi->halt));  return mi;}/* * Dump tables -- triggered by SIGUSR2. * If status file is defined, write to file. * If status file is NULL, write to syslog. */static voidmulti_print_status (struct multi_context *m, struct status_output *so){  if (m->hash)    {      struct gc_arena gc_top = gc_new ();      struct hash_iterator hi;      const struct hash_element *he;      status_reset (so);      status_printf (so, PACKAGE_NAME " CLIENT LIST");      status_printf (so, "Updated,%s", time_string (0, 0, false, &gc_top));      status_printf (so, "Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since");      hash_iterator_init (m->hash, &hi, true);      while ((he = hash_iterator_next (&hi)))	{	  struct gc_arena gc = gc_new ();	  const struct multi_instance *mi = (struct multi_instance *) he->value;	  if (!mi->halt)	    {	      status_printf (so, "%s,%s," counter_format "," counter_format ",%s",			     tls_common_name (mi->context.c2.tls_multi, false),			     mroute_addr_print (&mi->real, &gc),			     mi->context.c2.link_read_bytes,			     mi->context.c2.link_write_bytes,			     time_string (mi->created, 0, false, &gc));	    }	  gc_free (&gc);	}      hash_iterator_free (&hi);      status_printf (so, "ROUTING TABLE");      status_printf (so, "Virtual Address,Common Name,Real Address,Last Ref");      hash_iterator_init (m->vhash, &hi, true);      while ((he = hash_iterator_next (&hi)))	{	  struct gc_arena gc = gc_new ();	  const struct multi_route *route = (struct multi_route *) he->value;	  if (multi_route_defined (m, route))	    {	      const struct multi_instance *mi = route->instance;	      const struct mroute_addr *ma = &route->addr;	      char flags[2] = {0, 0};	      if (route->flags & MULTI_ROUTE_CACHE)		flags[0] = 'C';	      status_printf (so, "%s%s,%s,%s,%s",			     mroute_addr_print (ma, &gc),			     flags,			     tls_common_name (mi->context.c2.tls_multi, false),			     mroute_addr_print (&mi->real, &gc),			     time_string (route->last_reference, 0, false, &gc));	    }	  gc_free (&gc);	}      hash_iterator_free (&hi);      status_printf (so, "GLOBAL STATS");      status_printf (so, "Max bcast/mcast queue length,%d",	   mbuf_maximum_queued (m->mbuf));      status_printf (so, "END");      status_flush (so);      gc_free (&gc_top);    }}/* * Learn a virtual address or route. */static voidmulti_learn_addr (struct multi_context *m,		  struct multi_instance *mi,		  const struct mroute_addr *addr,		  const unsigned int flags){  struct hash_element *he;  const uint32_t hv = hash_value (m->vhash, addr);  struct hash_bucket *bucket = hash_bucket (m->vhash, hv);  struct multi_route *oldroute = NULL;    hash_bucket_lock (bucket);  he = hash_lookup_fast (m->vhash, bucket, addr, hv);  if (he)    oldroute = (struct multi_route *) he->value;  /* do we need to add address to hash table? */  if ((!oldroute       || oldroute->instance != mi       || !multi_route_defined (m, oldroute))      && mroute_learnable_address (addr)      && !mroute_addr_equal (addr, &m->local))    {      struct gc_arena gc = gc_new ();      struct multi_route *newroute;      ALLOC_OBJ (newroute, struct multi_route);      newroute->addr = *addr;      newroute->instance = mi;      newroute->flags = flags;      newroute->last_reference = now;      newroute->cache_generation = 0;      /* The cache is invalidated when cache_generation is incremented */      if (flags & MULTI_ROUTE_CACHE)	newroute->cache_generation = m->route_helper->cache_generation;      multi_instance_inc_refcount (mi);      if (oldroute) /* route already exists? */	{	  /* delete old route */	  multi_route_del (oldroute);	  /* modify hash table entry, replacing old route */	  he->key = &newroute->addr;	  he->value = newroute;	  learn_address_script (m, mi, "update", &newroute->addr);	}      else	{	  /* add new route */	  hash_add_fast (m->vhash, bucket, &newroute->addr, hv, newroute);	  learn_address_script (m, mi, "add", &newroute->addr);	}      msg (D_MULTI_LOW, "MULTI: Learn: %s -> %s",	   mroute_addr_print (&newroute->addr, &gc),	   multi_instance_string (mi, false, &gc));      gc_free (&gc);    }  hash_bucket_unlock (bucket);}/* * Get client instance based on virtual address. */static struct multi_instance *multi_get_instance_by_virtual_addr (struct multi_context *m,				    const struct mroute_addr *addr,				    bool cidr_routing){  struct multi_route *route;  struct multi_instance *ret = NULL;  /* check for local address */  if (mroute_addr_equal (addr, &m->local))    return NULL;  route = (struct multi_route *) hash_lookup (m->vhash, addr);  /* does host route (possible cached) exist? */  if (route && multi_route_defined (m, route))    {      struct multi_instance *mi = route->instance;      route->last_reference = now;      ret = mi;    }  else if (cidr_routing) /* do we need to regenerate a host route cache entry? */    {      struct mroute_helper *rh = m->route_helper;      struct mroute_addr tryaddr;      int i;      mroute_helper_lock (rh);      /* cycle through each CIDR length */      for (i = 0; i < rh->n_net_len; ++i)	{	  tryaddr = *addr;	  tryaddr.type |= MR_WITH_NETBITS;	  tryaddr.netbits = rh->net_len[i];	  mroute_addr_mask_host_bits (&tryaddr);	  /* look up a possible route with netbits netmask */	  route = (struct multi_route *) hash_lookup (m->vhash, &tryaddr);	  if (route && multi_route_defined (m, route))	    {	      /* found an applicable route, cache host route */	      struct multi_instance *mi = route->instance;	      multi_learn_addr (m, mi, addr, MULTI_ROUTE_CACHE|MULTI_ROUTE_AGEABLE);	      ret = mi;	      break;	    }	}            mroute_helper_unlock (rh);    }  #ifdef MULTI_DEBUG  if (check_debug_level (D_MULTI_DEBUG))    {      struct gc_arena gc = gc_new ();      const char *addr_text = mroute_addr_print (addr, &gc);      if (ret)	{	  msg (D_MULTI_DEBUG, "GET INST BY VIRT: %s -> %s via %s",	       addr_text,	       multi_instance_string (ret, false, &gc),	       mroute_addr_print (&route->addr, &gc));	}      else	{	  msg (D_MULTI_DEBUG, "GET INST BY VIRT: %s [failed]",	       addr_text);	}      gc_free (&gc);    }#endif  ASSERT (!(ret && ret->halt));  return ret;}/* * Helper function to multi_learn_addr(). */static voidmulti_learn_in_addr_t (struct multi_context *m,		       struct multi_instance *mi,		       in_addr_t a,		       int netbits) /* -1 if host route, otherwise # of network bits in address */{  struct sockaddr_in remote_si;  struct mroute_addr addr;  CLEAR (remote_si);  remote_si.sin_family = AF_INET;  remote_si.sin_addr.s_addr = htonl (a);  ASSERT (mroute_extract_sockaddr_in (&addr, &remote_si, false));  if (netbits >= 0)    {      addr.type |= MR_WITH_NETBITS;      addr.netbits = (uint8_t) netbits;    }  multi_learn_addr (m, mi, &addr, 0);}/* * A new client has connected, add routes (server -> client) * to internal routing table. */static voidmulti_add_iroutes (struct multi_context *m,		   struct multi_instance *mi){  struct gc_arena gc = gc_new ();  const struct iroute *ir;  for (ir = mi->context.options.iroutes; ir != NULL; ir = ir->next)    {      if (ir->netbits >= 0)	msg (D_MULTI_LOW, "MULTI: internal route %s/%d -> %s",	     print_in_addr_t (ir->network, false, &gc),	     ir->netbits,	     multi_instance_string (mi, false, &gc));      else	msg (D_MULTI_LOW, "MULTI: internal route %s -> %s",	     print_in_addr_t (ir->network, false, &gc),	     multi_instance_string (mi, false, &gc));      mroute_helper_add_iroute (m->route_helper, ir);      multi_learn_in_addr_t (m, mi, ir->network, ir->netbits);    }  gc_free (&gc);}/* * Given an instance (new_mi), delete all other instances which use the * same common name. */static voidmulti_delete_dup (struct multi_context *m, struct multi_instance *new_mi){  if (new_mi)    {      const char *new_cn = tls_common_name (new_mi->context.c2.tls_multi, true);      if (new_cn)	{	  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;	      if (mi != new_mi)		{		  const char *cn = tls_common_name (mi->context.c2.tls_multi, true);		  if (cn && !strcmp (cn, new_cn))		    {		      mi->did_iter = false;		      multi_close_instance (m, mi, false);		      hash_iterator_delete_element (&hi);		    }		}	    }	  hash_iterator_free (&hi);	}    }}/* * Called as soon as the SSL/TLS connection authenticates.

⌨️ 快捷键说明

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