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

📄 multi.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 4 页
字号:
							  &dest,							  &c->c2.to_tun,							  DEV_TYPE_TAP);	  if (mroute_flags & MROUTE_EXTRACT_SUCCEEDED)	    {	      /* check for broadcast */	      if (m->enable_c2c)		{		  if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))		    {		      multi_bcast (m, &c->c2.to_tun, mt->pending);		    }		  else /* try client-to-client routing */		    {		      mi = multi_get_instance_by_virtual_addr (m, &dest, false);		      /* 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;			}		    }		}		  	      /* learn source address */	      multi_learn_addr (m, mt->pending, &src, 0);	    }	  else	    {	      c->c2.to_tun.len = 0;	    }	}            /* postprocess and set wakeup */      multi_process_post (mt, mt->pending);      clear_prefix ();    }  gc_free (&gc);}/* * Process packets in the TUN/TAP interface -> TCP/UDP socket direction, * i.e. server -> client direction. */static voidmulti_process_incoming_tun (struct multi_thread *mt){  struct gc_arena gc = gc_new ();  struct multi_context *m = mt->multi;  if (BLEN (&mt->top.c2.buf) > 0)    {      unsigned int mroute_flags;      struct mroute_addr src, dest;      const int dev_type = TUNNEL_TYPE (mt->top.c1.tuntap);#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("TUN -> UDP [%d]\n", BLEN (&mt->top.c2.buf));#endif      ASSERT (!mt->pending);      /*        * Route an incoming tun/tap packet to       * the appropriate multi_instance object.       */      mroute_flags = mroute_extract_addr_from_packet (&src,						      &dest,						      &mt->top.c2.buf,						      dev_type);      if (mroute_flags & MROUTE_EXTRACT_SUCCEEDED)	{	  struct context *c;	  /* broadcast or multicast dest addr? */	  if (mroute_flags & (MROUTE_EXTRACT_BCAST|MROUTE_EXTRACT_MCAST))	    {	      /* for now, treat multicast as broadcast */	      multi_bcast (m, &mt->top.c2.buf, NULL);	    }	  else	    {	      mt->pending = multi_get_instance_by_virtual_addr (m, &dest, dev_type == DEV_TYPE_TUN);	      if (mt->pending)		{		  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;     		  /* encrypt in instance context */		  process_incoming_tun (c);	      		  /* postprocess and set wakeup */		  multi_process_post (mt, mt->pending);		  clear_prefix ();		}	    }	}    }  gc_free (&gc);}/* * Process a possible client-to-client/bcast/mcast message in the * queue. */struct multi_instance *multi_bcast_instance (struct multi_context *m){  struct mbuf_item item;  if (mbuf_extract_item_lock (m->mbuf, &item, true))    {      set_prefix (item.instance);      item.instance->context.c2.buf = item.buffer->buf;      encrypt_sign (&item.instance->context, true);      mbuf_free_buf (item.buffer);      mbuf_extract_item_unlock (m->mbuf);#ifdef MULTI_DEBUG      msg (D_MULTI_DEBUG, "MULTI: C2C/MCAST/BCAST");#endif      clear_prefix ();      return item.instance;    }  else    {      return NULL;    }}/* * Send a packet to TCP/UDP socket. */static inline voidmulti_process_outgoing_link (struct multi_thread *mt){  struct multi_instance *mi;  if (mt->pending)    {      mi = mt->pending;#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("%s -> UDP [U] l=%d f=%d\n",	      id(mi),	      mi->context.c2.to_link.len,	      mi->context.c2.fragment ? mi->context.c2.fragment->outgoing.len : -1);#endif    }  else    {      mi = multi_bcast_instance (mt->multi);#ifdef MULTI_DEBUG_EVENT_LOOP      printf ("%s -> UDP [B] len=%d frag=%d\n",	      id(mi),	      mi ? mi->context.c2.to_link.len : -1,	      (mi && mi->context.c2.fragment) ? mi->context.c2.fragment->outgoing.len : -1);#endif    }    if (mi)    {      set_prefix (mi);      process_outgoing_link (&mi->context);      multi_process_post (mt, mi);      clear_prefix ();    }}/* * Send a packet to TUN/TAP interface. */static inline voidmulti_process_outgoing_tun (struct multi_thread *mt){  struct multi_instance *mi = mt->pending;  ASSERT (mi);#ifdef MULTI_DEBUG_EVENT_LOOP  printf ("%s -> TUN len=%d\n",	  id(mi),	  mi->context.c2.to_tun.len);#endif  set_prefix (mi);  process_outgoing_tun (&mi->context);  multi_process_post (mt, mi);  clear_prefix ();}/* * Process an I/O event. */voidmulti_process_io (struct multi_thread *mt){  const unsigned int status = mt->top.c2.event_set_status;#ifdef MULTI_DEBUG_EVENT_LOOP  char buf[16];  buf[0] = 0;  if (status & SOCKET_READ)    strcat (buf, "SR/");  else if (status & SOCKET_WRITE)    strcat (buf, "SW/");  else if (status & TUN_READ)    strcat (buf, "TR/");  else if (status & TUN_WRITE)    strcat (buf, "TW/");  printf ("IO %s\n", buf);#endif  /* TCP/UDP port ready to accept write */  if (status & SOCKET_WRITE)    {      multi_process_outgoing_link (mt);    }  /* TUN device ready to accept write */  else if (status & TUN_WRITE)    {      multi_process_outgoing_tun (mt);    }  /* Incoming data on TCP/UDP port */  else if (status & SOCKET_READ)    {      read_incoming_link (&mt->top);      if (!IS_SIG (&mt->top))	multi_process_incoming_link (mt);    }  /* Incoming data on TUN device */  else if (status & TUN_READ)    {      read_incoming_tun (&mt->top);      if (!IS_SIG (&mt->top))	multi_process_incoming_tun (mt);    }}/* * Called when an I/O wait times out.  Usually means that a particular * client instance object needs timer-based service. */static inline voidmulti_process_timeout (struct multi_thread *mt){#ifdef MULTI_DEBUG_EVENT_LOOP  printf ("%s -> TIMEOUT\n", id(mt->earliest_wakeup));#endif  /* instance marked for wakeup? */  if (mt->earliest_wakeup)    {      set_prefix (mt->earliest_wakeup);      multi_process_post (mt, mt->earliest_wakeup);      mt->earliest_wakeup = NULL;      clear_prefix ();    }}/* * Check for signals. */#define TNUS_SIG() \  if (IS_SIG (&thread->top)) \  { \    if (thread->top.sig->signal_received == SIGUSR2) \      { \        struct status_output *so = status_open (NULL, 0, M_INFO); \        multi_print_status (thread->multi, so); \        status_close (so); \        thread->top.sig->signal_received = 0; \        continue; \      } \    break; \  }/* * The idea of struct multi_thread is that multiple threads could handle * the event loop simultaneously. */static struct multi_thread *multi_thread_init (struct multi_context *multi, const struct context *top){  struct multi_thread *thread;  ALLOC_OBJ_CLEAR (thread, struct multi_thread);  thread->multi = multi;  inherit_context_thread (&thread->top, top);  thread->context_buffers = thread->top.c2.buffers = init_context_buffers (&top->c2.frame);  return thread;}static voidmulti_thread_free (struct multi_thread *thread){  close_context (&thread->top, -1);  free_context_buffers (thread->context_buffers);  free (thread);}/* * Return the io_wait() flags appropriate for * a point-to-multipoint tunnel. */static inline unsigned intp2mp_iow_flags (const struct multi_thread *mt){  unsigned int flags = 0;  if (mt->pending)    {      if (TUN_OUT (&mt->pending->context))	flags |= IOW_TO_TUN;      if (LINK_OUT (&mt->pending->context))	flags |= IOW_TO_LINK;    }  else if (mbuf_defined (mt->multi->mbuf))    flags |= IOW_MBUF;  else    flags |= IOW_READ;  return flags;}static inline voidprocess_per_second_timers (struct multi_thread *thread){  if (thread->per_second_trigger != now)    {      /* possibly reap instances/routes in vhash */      multi_reap_process (thread->multi);      /* possibly print to status log */      if (thread->top.c1.status_output) {	if (status_trigger (thread->top.c1.status_output))	  multi_print_status (thread->multi, thread->top.c1.status_output);      }      thread->per_second_trigger = now;    }}/* * Top level event loop for single-threaded operation. * UDP mode. */static voidtunnel_server_single_threaded_udp (struct context *top){  struct multi_context multi;  struct multi_thread *thread;  top->mode = CM_TOP;  context_clear_2 (top);  /* initialize top-tunnel instance */  init_instance (top);  if (IS_SIG (top))    return;    /* initialize global multi_context object */  multi_init (&multi, top);  /* initialize a single multi_thread object */  thread = multi_thread_init (&multi, top);  /* per-packet event loop */  while (true)    {      /* set up and do the io_wait() */      multi_get_timeout (thread, &thread->top.c2.timeval);      io_wait (&thread->top, p2mp_iow_flags (thread));      TNUS_SIG ();      /* check on status of coarse timers */      process_per_second_timers (thread);      /* timeout? */      if (thread->top.c2.event_set_status == ES_TIMEOUT)	{	  multi_process_timeout (thread);	}      else	{	  /* process the I/O which triggered select */	  multi_process_io (thread);	  TNUS_SIG ();	}    }  /* tear down tunnel instance (unless --persist-tun) */  multi_thread_free (thread);  close_instance (top);  multi_uninit (&multi);  top->first_time = false;}/* * Top level event loop for single-threaded operation. * TCP mode. */static voidtunnel_server_single_threaded_tcp (struct context *top){  //struct multi_context multi;  //struct multi_thread *thread;  msg (M_FATAL, "Sorry, TCP support in server mode is not finished yet");}/* * Top level event loop for single-threaded operation. */voidtunnel_server_single_threaded (struct context *top){  ASSERT (top->options.mode == MODE_SERVER);  switch (top->options.proto) {  case PROTO_UDPv4:    tunnel_server_single_threaded_udp (top);    break;  case PROTO_TCPv4_SERVER:    tunnel_server_single_threaded_tcp (top);    break;  default:    ASSERT (0);  }}#ifdef USE_PTHREAD/* * NOTE: multi-threaded mode is not finished yet. */voidtunnel_server_multi_threaded (struct context *top){  ASSERT (top->options.n_threads >= 2);  openvpn_thread_init ();  tunnel_server_single_threaded (top);  openvpn_thread_cleanup ();}#endif#elsestatic void dummy(void) {}#endif /* P2MP */

⌨️ 快捷键说明

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