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

📄 openvpn.c

📁 一个开源的VPN原码
💻 C
📖 第 1 页 / 共 3 页
字号:
   * Make space for a uint32 to be removed from incoming TUN packets   * and added to outgoing TUN packets.   */  if (options->tun_af_inet)    tun_adjust_frame_parameters (&frame, sizeof (uint32_t));#endif  /*   * Fill in the blanks in the frame parameters structure,   * make sure values are rational, etc.   */  frame_finalize (&frame, options);  max_rw_size_udp = MAX_RW_SIZE_UDP (&frame);  print_frame_parms (D_SHOW_PARMS, &frame, "Data Channel MTU parms");#if defined(USE_CRYPTO) && defined(USE_SSL)  if (tls_multi)    {      int size;      tls_multi_init_finalize (tls_multi, &frame);      size = MAX_RW_SIZE_UDP (&tls_multi->opt.frame);      if (size > max_rw_size_udp)	max_rw_size_udp = size;      print_frame_parms (D_SHOW_PARMS, &tls_multi->opt.frame, "Control Channel MTU parms");    }#endif  /*   * Now that we know all frame parameters, initialize   * our buffers.   */  read_udp_buf = alloc_buf (BUF_SIZE (&frame));  read_tun_buf = alloc_buf (BUF_SIZE (&frame));#ifdef USE_CRYPTO  encrypt_buf = alloc_buf (BUF_SIZE (&frame));  decrypt_buf = alloc_buf (BUF_SIZE (&frame));#endif#ifdef USE_LZO  if (options->comp_lzo)    {      lzo_compress_buf = alloc_buf (BUF_SIZE (&frame));      lzo_decompress_buf = alloc_buf (BUF_SIZE (&frame));    }#endif  if (!tuntap_defined (tuntap))    {      /* do ifconfig */      if (ifconfig_order() == IFCONFIG_BEFORE_TUN_OPEN)	do_ifconfig (options->dev, options->dev_type,		     options->ifconfig_local, options->ifconfig_remote,		     MAX_RW_SIZE_TUN (&frame));      /* open the tun device */      open_tun (options->dev, options->dev_type, options->dev_node, options->tun_ipv6, tuntap);      /* do ifconfig */        if (ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN)	do_ifconfig (tuntap->actual, options->dev_type,		     options->ifconfig_local, options->ifconfig_remote,		     MAX_RW_SIZE_TUN (&frame));      /* run the up script */      run_script (options->up_script, tuntap->actual, MAX_RW_SIZE_TUN (&frame),		  max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote);    }  else    {      msg (M_INFO, "Preserving previous tun/tap instance: %s", tuntap->actual);    }  /* initialize traffic shaper */  if (options->shaper)    shaper_init (&shaper, options->shaper);  /* drop privileges if requested */  if (first_time)    {      set_group (options->groupname);      set_user (options->username);    }  /* catch signals */  signal (SIGINT, signal_handler);  signal (SIGTERM, signal_handler);  signal (SIGHUP, signal_handler);  signal (SIGUSR1, signal_handler);  signal (SIGUSR2, signal_handler);  /* start the TLS thread */#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD)  if (tls_multi)    tls_thread_socket = tls_thread_create (tls_multi, &udp_socket,					   options->nice_work, options->mlock);#endif  /* change scheduling priority if requested */  if (first_time)    set_nice (options->nice);  /*   * MAIN EVENT LOOP   *   * Pipe UDP -> tun and tun -> UDP using nonblocked i/o.   *   * If tls_multi is defined, multiplex a TLS   * control channel over the UDP connection which   * will be used for secure key exchange with our peer.   *   */  /* calculate max file handle + 1 for select */  fm = udp_socket.sd;  if (tuntap->fd > fm)    fm = tuntap->fd;  current = time (NULL);  /* initialize inactivity timeout */  if (options->inactivity_timeout)    event_timeout_init (&inactivity_interval, current, options->inactivity_timeout);  /* initialize pings */  if (options->ping_send_timeout)    event_timeout_init (&ping_send_interval, 0, options->ping_send_timeout);  if (options->ping_rec_timeout)    event_timeout_init (&ping_rec_interval, current, options->ping_rec_timeout);#if defined(USE_CRYPTO) && defined(USE_SSL)#ifdef USE_PTHREAD  if (tls_multi && tls_thread_socket > fm)    fm = tls_thread_socket;#else  /* initialize tmp_int optimization that limits the number of times we call     tls_multi_process in the main event loop */  CLEAR (tmp_int);  interval_trigger (&tmp_int, current);#endif#endif  /* select() needs this */  ++fm;  /* this flag is true for buffers coming from the TLS background thread */  free_to_udp = false;  while (true)    {      int stat = 0;      struct timeval *tv = NULL;      struct timeval timeval;      /* initialize select() timeout */      timeval.tv_sec = 0;      timeval.tv_usec = 0;#if defined(USE_CRYPTO) && defined(USE_SSL) && !defined(USE_PTHREAD)      /*       * In TLS mode, let TLS level respond to any control-channel packets which were       * received, or prepare any packets for transmission.       *       * tmp_int is purely an optimization that allows us to call tls_multi_process       * less frequently when there's not much traffic on the control-channel.       *       */      if (tls_multi)	{	  time_t t = 0;	  if (interval_test (&tmp_int, current))	    {	      if (tls_multi_process (tls_multi, &to_udp, &to_udp_addr, &udp_socket, &t, current))		interval_trigger(&tmp_int, current);	    }	  interval_set_timeout (&tmp_int, current, &t);	  tv = &timeval;	  timeval.tv_sec = t;	  timeval.tv_usec = 0;	  free_to_udp = false;	}#endif      current = time (NULL);      /*       * Should we exit due to inactivity timeout?       */      if (options->inactivity_timeout)	{	  if (event_timeout_trigger (&inactivity_interval, current)) 	    {	      msg (M_INFO, "Inactivity timeout (--inactive), exiting");	      signal_received = 0;	      break;	    }	  event_timeout_wakeup (&inactivity_interval, current, &timeval);	  tv = &timeval;	}      /*       * Should we exit or restart due to ping (or other authenticated packet)       * not received in n seconds?       */      if (options->ping_rec_timeout &&	  (!options->ping_timer_remote || addr_defined (&udp_socket_addr->actual)))	{	  if (event_timeout_trigger (&ping_rec_interval, current)) 	    {	      switch (options->ping_rec_timeout_action)		{		case PING_EXIT:		  msg (M_INFO, "Inactivity timeout (--ping-exit), exiting");		  signal_received = 0;		  break;		case PING_RESTART:		  msg (M_INFO, "Inactivity timeout (--ping-restart), restarting");		  signal_received = SIGUSR1;		  break;		default:		  ASSERT (0);		}	      break;	    }	  event_timeout_wakeup (&ping_rec_interval, current, &timeval);	  tv = &timeval;	}      /*       * Should we ping the remote?       */      if (options->ping_send_timeout)	{	  if (!to_udp.len)	    {	      if (event_timeout_trigger (&ping_send_interval, current))		{		  buf = read_tun_buf;		  ASSERT (buf_init (&buf, EXTRA_FRAME (&frame)));		  ASSERT (buf_safe (&buf, MAX_RW_SIZE_TUN (&frame)));		  ASSERT (buf_write (&buf, ping_string, sizeof (ping_string)));		  /*		   * We will treat the ping like any other outgoing packet,		   * encrypt, authenticate, etc.		   */#ifdef USE_LZO		  if (options->comp_lzo)		    lzo_compress (&buf, lzo_compress_buf, &lzo_compwork, &frame, current);#endif#ifdef USE_CRYPTO#ifdef USE_SSL		  mutex_lock (L_TLS);		  if (tls_multi)		    tls_pre_encrypt (tls_multi, &buf, &crypto_options);#endif		  openvpn_encrypt (&buf, encrypt_buf, &crypto_options, &frame, current);#endif		  udp_socket_get_outgoing_addr (&buf, &udp_socket,						&to_udp_addr);#ifdef USE_CRYPTO#ifdef USE_SSL		  if (tls_multi)		    tls_post_encrypt (tls_multi, &buf);		  mutex_unlock (L_TLS);#endif#endif		  to_udp = buf;		  free_to_udp = false;		  msg (D_PACKET_CONTENT, "SENT PING");		}	      event_timeout_wakeup (&ping_send_interval, current, &timeval);	      tv = &timeval;	    }	}      /* do a quick garbage collect */      gc_collect (gc_level);      /*       * Set up for select call.       *       * Decide what kind of events we want to wait for.       */      FD_ZERO (&reads);      FD_ZERO (&writes);      if (to_udp.len > 0)	{	  if (options->shaper)	    {	      /*	       * If sending this packet would put us over our traffic shaping	       * quota, don't send -- instead compute the delay we must wait	       * until it will be OK to send the packet.	       */	      const int delay = shaper_delay (&shaper); /* traffic shaping delay in microseconds */	      if (delay)		{		  shaper_soonest_event (&timeval, delay);		  tv = &timeval;		}	      else		{		  FD_SET (udp_socket.sd, &writes);		}	    }	  else	    {	      FD_SET (udp_socket.sd, &writes);	    }	}      else	{	  if (tuntap->fd >= 0)	    FD_SET (tuntap->fd, &reads);#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD)	  if (tls_multi)	    FD_SET (tls_thread_socket, &reads);#endif	}      if (to_tun.len > 0)	{	  if (tuntap->fd >= 0)	    FD_SET (tuntap->fd, &writes);	}      else	{	  FD_SET (udp_socket.sd, &reads);	}      /*       * Possible scenarios:       *  (1) udp port has data available to read       *  (2) udp port is ready to accept more data to write       *  (3) tun dev has data available to read       *  (4) tun dev is ready to accept more data to write       *  (5) tls background thread has data available to forward to udp port       *  (6) we received a signal (handler sets signal_received)       *  (7) timeout (tv) expired (from TLS, shaper, inactivity timeout, or ping timeout)       */      /*       * Wait for something to happen.       */      if (!signal_received)	stat = select (fm, &reads, &writes, NULL, tv);      /* current should always be a reasonably up-to-date timestamp */      current = time (NULL);      /*       * Did we get a signal before or while we were waiting       * in select() ?       */      if (signal_received)	{	  if (signal_received == SIGUSR2)	    {	      msg (M_INFO, "Current OpenVPN Statistics:");	      msg (M_INFO, " tun/tap read bytes:   " counter_format, tun_read_bytes);	      msg (M_INFO, " tun/tap write bytes:  " counter_format, tun_write_bytes);	      msg (M_INFO, " UDP read bytes:       " counter_format, udp_read_bytes);	      msg (M_INFO, " UDP write bytes:      " counter_format, udp_write_bytes);#ifdef USE_LZO	      if (options->comp_lzo)		  lzo_print_stats (&lzo_compwork);		  #endif	      signal_received = 0;	      continue;	    }	  /* for all other signals (INT, TERM, HUP, USR1) we break */	  switch (signal_received)	    {	    case SIGINT:	      msg (M_INFO, "SIGINT received, exiting");	      break;	    case SIGTERM:	      msg (M_INFO, "SIGTERM received, exiting");	      break;	    case SIGHUP:	      msg (M_INFO, "SIGHUP received, restarting");	      break;	    case SIGUSR1:	      msg (M_INFO, "SIGUSR1 received, restarting");	      break;	    default:	      msg (M_INFO, "Unknown signal %d received", signal_received);	      break;	    }	  break;	}#if defined(USE_CRYPTO) && defined(USE_SSL)      if (!stat) /* timeout? */	continue;#endif      check_status (stat, "select");      if (stat > 0)	{	  /* Incoming data on UDP port */	  if (FD_ISSET (udp_socket.sd, &reads))	    {	      /*	       * Set up for recvfrom call to read datagram	       * sent to our UDP port from any source address.	       */	      struct sockaddr_in from;	      socklen_t fromlen = sizeof (from);	      ASSERT (!to_tun.len);	      buf = read_udp_buf;	      ASSERT (buf_init (&buf, EXTRA_FRAME (&frame)));	      ASSERT (buf_safe (&buf, max_rw_size_udp));	      fromlen = sizeof (from);	      buf.len = recvfrom (udp_socket.sd, BPTR (&buf), max_rw_size_udp, 0,				  (struct sockaddr *) &from, &fromlen);	      ASSERT (fromlen == sizeof (from));	      if (buf.len > 0)		udp_read_bytes += buf.len;	      /* check recvfrom status */	      check_status (buf.len, "read from UDP");	      /* possibly corrupt packet if we are in gremlin test mode */	      if (options->gremlin) {		if (!ask_gremlin())		  buf.len = 0;		corrupt_gremlin(&buf);	      }	      /* log incoming packet */	      msg (D_PACKET_CONTENT, "UDP READ from %s: %s",		   print_sockaddr (&from), PROTO_DUMP (&buf));	      /*	       * Good, non-zero length packet received.	       * Commence multi-stage processing of packet,	       * such as authenticate, decrypt, decompress.	       * If any stage fails, it sets buf.len to 0,	       * telling downstream stages to ignore the packet.	       */	      if (buf.len > 0)		{		  udp_socket_incoming_addr (&buf, &udp_socket, &from);#ifdef USE_CRYPTO#ifdef USE_SSL		  mutex_lock (L_TLS);		  if (tls_multi)		    {		      /*		       * If tls_pre_decrypt returns true, it means the incoming		       * packet was a good TLS control channel packet.  If so, TLS code		       * will deal with the packet and set buf.len to 0 so downstream		       * stages ignore it.		       *		       * It the packet is a data channel packet, tls_pre_decrypt		       * will load crypto_options with the correct encryption key		       * and return false.		       */		      if (tls_pre_decrypt (tls_multi, &from, &buf, &crypto_options, current))			{#ifdef USE_PTHREAD			  /* tell TLS thread a packet is waiting */			  if (tls_thread_process (tls_thread_socket) == -1)			    {			      msg (M_WARN, "TLS thread is not responding, exiting (1)");			      signal_received = 0;			      mutex_unlock (L_TLS);			      break;			    }#else			  interval_trigger(&tmp_int, current);#endif /* USE_PTHREAD */			  /* reset packet received timer if TLS packet */			  if (options->ping_rec_timeout)			    event_timeout_reset (&ping_rec_interval, current);			}		    }#endif /* USE_SSL */		  /* authenticate and decrypt the incoming packet */		  openvpn_decrypt (&buf, decrypt_buf, &crypto_options, &frame, current);#ifdef USE_SSL		  mutex_unlock (L_TLS);#endif#endif /* USE_CRYPTO */#ifdef USE_LZO		  /* decompress the incoming packet */		  if (options->comp_lzo)		    lzo_decompress (&buf, lzo_decompress_buf, &lzo_compwork, &frame);#endif		  /*		   * Set our "official" outgoing address, since		   * if buf.len is non-zero, we know the packet		   * authenticated.  In TLS mode we do nothing		   * because TLS mode takes care of source address		   * authentication.		   */		  if (!TLS_MODE)		    udp_socket_set_outgoing_addr (&buf, &udp_socket, &from);		  /* reset packet received timer */		  if (options->ping_rec_timeout && buf.len > 0)		    event_timeout_reset (&ping_rec_interval, current);		  /* Did we just receive an openvpn ping packet? */		  if (buf_string_match (&buf, ping_string, sizeof (ping_string)))		    {		      msg (D_PACKET_CONTENT, "RECEIVED PING");		      buf.len = 0; /* drop it */		    }		  to_tun = buf;		}	      else		{		  to_tun = nullbuf;		}	    }#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD)	  /* Incoming data from TLS background thread */	  else if (tls_multi && FD_ISSET (tls_thread_socket, &reads))	    {	      int s;	      ASSERT (!to_udp.len);	      s = tls_thread_rec_buf (tls_thread_socket, &tt_ret, true);	      if (s == 1)		{		  /*		   * TLS background thread has a control channel		   * packet to send to remote.		   */		  to_udp = tt_ret.to_udp;		  to_udp_addr = tt_ret.to_udp_addr;				  /* tell UDP packet writer to free buffer after write */		  free_to_udp = true;		}	      /* remote died? */	      else if (s == -1)		{		  msg (M_WARN, "TLS thread is not responding, exiting (2)");		  signal_received = 0;		  break;		}	    }#endif	  /* Incoming data on TUN device */	  else if (tuntap->fd >= 0 && FD_ISSET (tuntap->fd, &reads))	    {	      /*	       * Setup for read() call on tun/tap device.	       */	      ASSERT (!to_udp.len);	      buf = read_tun_buf;	      ASSERT (buf_init (&buf, EXTRA_FRAME (&frame)));	      ASSERT (buf_safe (&buf, MAX_RW_SIZE_TUN (&frame)));	      buf.len = read_tun (tuntap, BPTR (&buf), MAX_RW_SIZE_TUN (&frame));	      if (buf.len > 0)

⌨️ 快捷键说明

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