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

📄 openvpn.c

📁 OpenVPN -- A Secure tunneling daemon
💻 C
📖 第 1 页 / 共 4 页
字号:
		  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 FRAGMENT_ENABLE		  if (fragment)		    fragment_outgoing (fragment, &buf, &frame_fragment, 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 outgoing data (for UDP port) pending, wait for ready-to-send       * status from UDP port. Otherwise, wait for incoming data on TUN/TAP device.       */      if (to_udp.len > 0)	{	  /*	   * 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.	   */#ifdef HAVE_GETTIMEOFDAY	  int delay = 0;	  /* set traffic shaping delay in microseconds */	  if (options->shaper)	    delay = max_int (delay, shaper_delay (&shaper));	  if (delay >= 1000)	    {	      shaper_soonest_event (&timeval, delay);	      tv = &timeval;	    }	  else	    {	      FD_SET (udp_socket.sd, &writes);	    }#else /* HAVE_GETTIMEOFDAY */	  FD_SET (udp_socket.sd, &writes);#endif /* HAVE_GETTIMEOFDAY */	}#ifdef FRAGMENT_ENABLE      else if (!fragment || !fragment_outgoing_defined (fragment))#else      else#endif	{	  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 (&thread_parms), &reads);#endif	}      /*       * If outgoing data (for TUN/TAP device) pending, wait for ready-to-send status       * from device.  Otherwise, wait for incoming data on UDP port.       */      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) {	msg (D_SELECT, "SELECT %s|%s|%s|%s %d/%d",	     (tuntap->fd >= 0 && FD_ISSET (tuntap->fd, &reads)) ? "TR" : "tr", 	     (tuntap->fd >= 0 && FD_ISSET (tuntap->fd, &writes)) ? "TW" : "tw", 	     FD_ISSET (udp_socket.sd, &reads) ?  "UR" : "ur",	     FD_ISSET (udp_socket.sd, &writes) ? "UW" : "uw",	     tv ? (int)tv->tv_sec : -1,	     tv ? (int)tv->tv_usec : -1	     );	stat = select (fm, &reads, &writes, NULL, tv);	check_status (stat, "select", NULL);      }      /* current should always be a reasonably up-to-date timestamp */      current = time (NULL);#ifdef HAVE_SIGNAL_H      /*       * 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;	}#endif /* HAVE_SIGNAL_H */      if (!stat) /* timeout? */	continue;      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", &udp_socket);	      /* take action to corrupt packet if we are in gremlin test mode */	      if (options->gremlin) {		if (!ask_gremlin())		  buf.len = 0;		corrupt_gremlin(&buf);	      }	      /* log incoming packet */#ifdef LOG_RW	      if (check_debug_level (D_LOG_RW) && !check_debug_level (D_LOG_RW + 1))		fprintf (stderr, "R");#endif	      msg (D_UDP_RW, "UDP READ [%d] from %s: %s",		   BLEN (&buf), 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.		       *		       * If 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 (&thread_parms) == -1)			    {			      msg (M_WARN, "TLS thread is not responding, exiting (1)");			      signal_received = 0;			      mutex_unlock (L_TLS);			      break;			    }#else			  interval_action (&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 /* USE_SSL */#endif /* USE_CRYPTO */#ifdef FRAGMENT_ENABLE		  if (fragment)		    fragment_incoming (fragment, &buf, &frame_fragment, current);#endif#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.		   *		   * Also, update the persisted version of our packet-id.		   */		  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 (&thread_parms), &reads))	    {	      int s;	      ASSERT (!to_udp.len);	      s = tls_thread_rec_buf (&thread_parms, &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)		tun_read_bytes += buf.len;	      /* Check the status return from read() */	      check_status (buf.len, "read from TUN/TAP", NULL);	      /* show packet content */	      msg (D_TUN_RW, "TUN READ [%d]: %s md5=%s",		   BLEN (&buf),		   format_hex (BPTR (&buf), BLEN (&buf), 80),		   MD5SUM (BPTR (&buf), BLEN (&buf)));#ifdef FRAGMENT_ENABLE	      /* if packet is too big, we might want to bounce back a "fragmentation		 needed but DF set ICMP message */	      if (fragment)		fragment_check_fragmentability (fragment, &frame_fragment, &buf);#endif	      if (buf.len > 0)		{#if PASSTOS_CAPABILITY		  if (options->passtos)		    {		      /* Get the TOS before compression/encryption. */		      iph = (struct iphdr*) BPTR (&buf);		      /* Check that it's an IPv4 packet. */		      if (iph->version == 0x04)			{			  ptos = iph->tos;			  ptos_defined = true;			}		    }#endif#ifdef USE_LZO		  /* Compress the packet. */		  if (options->comp_lzo)		    lzo_compress (&buf, lzo_compress_buf, &lzo_compwork, &frame, current);#endif#ifdef FRAGMENT_ENABLE		  if (fragment)		    fragment_outgoing (fragment, &buf, &frame_fragment, current);#endif#ifdef USE_CRYPTO#ifdef USE_SSL		  /*		   * If TLS mode, get the key we will use to encrypt		   * the packet.		   */		  mutex_lock (L_TLS);		  if (tls_multi)		    tls_pre_encrypt (tls_multi, &buf, &crypto_options);#endif		  /*		   * Encrypt the packet and write an optional		   * HMAC authentication record.		   */		  openvpn_encrypt (&buf, encrypt_buf, &crypto_options, &frame, current);#endif		  /*		   * Get the address we will be sending the packet to.		   */		  udp_socket_get_outgoing_addr (&buf, &udp_socket,						&to_udp_addr);#ifdef USE_CRYPTO#ifdef USE_SSL		  /*		   * In TLS mode, prepend the appropriate one-byte opcode		   * to the packet which identifies it as a data channel		   * packet and gives the low-permutation version of		   * the key-id to the recipient so it knows which		   * decrypt key to use.		   */		  if (tls_multi)		    tls_post_encrypt (tls_multi, &buf);		  mutex_unlock (L_TLS);#endif#endif		  to_udp = buf;		}	      else		{		  to_udp = nullbuf;		}	      free_to_udp = false;	    }	  /* TUN device ready to accept write */	  else if (tuntap->fd >= 0 && FD_ISSET (tuntap->fd, &writes))	    {	      /*	       * Set up for write() call to TUN/TAP	       * device.	       */	      ASSERT (to_tun.len > 0);	      if (to_tun.len <= MAX_RW_SIZE_TUN(&frame))		{		  /*		   * Write to TUN/TAP device.		   */		  int size;		  msg (D_TUN_RW, "TUN WRITE [%d]: %s md5=%s",		       BLEN (&to_tun),		       format_hex (BPTR (&to_tun), BLEN (&to_tun), 80),		       MD5SUM (BPTR (&to_tun), BLEN (&to_tun)));		  size = write_tun (tuntap, BPTR (&to_tun), BLEN (&to_tun));		  if (size > 0)		    tun_write_bytes += size;		  check_status (size, "write to TUN/TAP", NULL);		  /* check written packet size */		  if (size > 0)		    {		      /* Did we write a different size packet than we intended? */		      if (size != BLEN (&to_tun))			msg (D_LINK_ERRORS,			     "TUN/TAP packet was fragmented on write to %s (tried=%d,actual=%d)",			     tuntap->actual,			     BLEN (&to_tun),			     size);		    }		}	      else		{		  /*		   * This should never happen, probably indicates some kind		   * of MTU mismatch.		   */		  msg (D_LINK_ERRORS, "tun packet too large on write (tried=%d,max=%d)",		       to_tun.len,		       MAX_RW_SIZE_TUN (&frame));		}	      /*	       * Putting the --inactive timeout reset here, ensures that we will timeout	       * if the remote goes away, even if we are trying to send data to the	       * remote and failing.	       */	      if (options->inactivity_timeout)		event_timeout_reset (&inactivity_interval, current);	      to_tun = nullbuf;	    }	  /* UDP port ready to accept write */	  else if (FD_ISSET (udp_socket.sd, &writes))	    {	      if (to_udp.len > 0 && to_udp.len <= max_rw_size_udp)		{		  /*

⌨️ 快捷键说明

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