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

📄 openvpn.c

📁 一个开源的VPN原码
💻 C
📖 第 1 页 / 共 3 页
字号:
		tun_read_bytes += buf.len;	      /* Check the status return from read() */	      check_status (buf.len, "read from tun");	      if (buf.len > 0)		{#if 0		  /* special BSD <-> Linux mode, remove leading AF_INET		     from tun driver IP encoding */		  if (options->tun_af_inet)		    tun_rm_head (&buf, AF_INET);#endif#ifdef USE_LZO		  /* Compress the packet. */		  if (options->comp_lzo)		    lzo_compress (&buf, lzo_compress_buf, &lzo_compwork, &frame, 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 0	      if (options->tun_af_inet)		tun_add_head (&to_tun, AF_INET);#endif	      if (to_tun.len <= MAX_RW_SIZE_TUN(&frame))		{		  /*		   * Write to tun/tap device.		   */		  const int size = write_tun (tuntap, BPTR (&to_tun), BLEN (&to_tun));		  if (size > 0)		    tun_write_bytes += size;		  check_status (size, "write to tun");		  /* 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)		{		  /*		   * Setup for call to sendto() which will send		   * packet to remote over the UDP port.		   */		  int size;		  ASSERT (addr_defined (&to_udp_addr));		  /* In gremlin-test mode, we may choose to drop this packet */		  if (!options->gremlin || ask_gremlin())		    {		      /*		       * Let the traffic shaper know how many bytes		       * we wrote.		       */		      if (options->shaper)			shaper_wrote_bytes (&shaper, BLEN (&to_udp));		      /*		       * Let the pinger know that we sent a packet.		       */		      if (options->ping_send_timeout)			event_timeout_reset (&ping_send_interval, current);		      /* Send packet */		      size = sendto (udp_socket.sd, BPTR (&to_udp), BLEN (&to_udp), 0,				     (struct sockaddr *) &to_udp_addr,				     (socklen_t) sizeof (to_udp_addr));		      if (size > 0)			udp_write_bytes += size;		    }		  else		    size = 0;		  /* Check sendto() return status */		  check_status (size, "write to UDP");		  if (size > 0)		    {		      /* Did we write a different size packet than we intended? */		      if (size != BLEN (&to_udp))			msg (D_LINK_ERRORS,			     "UDP packet was fragmented on write to %s (tried=%d,actual=%d)",			     print_sockaddr (&to_udp_addr),			     BLEN (&to_udp),			     size);		    }		  /* Log packet send */		  msg (D_PACKET_CONTENT, "UDP WRITE to %s: %s",		       print_sockaddr (&to_udp_addr), PROTO_DUMP (&to_udp));		}	      else		{		  msg (D_LINK_ERRORS, "UDP packet too large on write to %s (tried=%d,max=%d)",		       print_sockaddr (&to_udp_addr),		       to_udp.len,		       max_rw_size_udp);		}	      /*	       * The free_to_udp flag means that we should free the packet buffer	       * after send.  This flag is usually set when the TLS background	       * thread generated the packet buffer.	       */	      if (free_to_udp)		{		  free_to_udp = false;		  free_buf (&to_udp);		}	      to_udp = nullbuf;	    }	}    }  /*   *  Do Cleanup   */  if (free_to_udp)    free_buf (&to_udp);    #if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD)  if (tls_multi)    tls_thread_close (tls_thread_socket);#endif  free_buf (&read_udp_buf);  free_buf (&read_tun_buf);#ifdef USE_LZO  if (options->comp_lzo)    {      lzo_compress_uninit (&lzo_compwork);      free_buf (&lzo_compress_buf);      free_buf (&lzo_decompress_buf);    }#endif#ifdef USE_CRYPTO  free_buf (&encrypt_buf);  free_buf (&decrypt_buf);#ifdef USE_SSL  if (tls_multi)    tls_multi_free (tls_multi, true);  if (data_channel_options)    free (data_channel_options);#endif#endif /* USE_CRYPTO */  /*   * Free key schedules   */  if ( !(signal_received == SIGUSR1 && options->persist_key) )    key_schedule_free (ks);  /*   * Close UDP connection   */  udp_socket_close (&udp_socket);  if ( !(signal_received == SIGUSR1 && options->persist_remote_ip) )    {      CLEAR (udp_socket_addr->remote);      CLEAR (udp_socket_addr->actual);    }  if ( !(signal_received == SIGUSR1 && options->persist_local_ip) )    CLEAR (udp_socket_addr->local);  /*   * Close tun/tap device   */  if ( !(signal_received == SIGUSR1 && options->persist_tun) )    {      char* tuntap_actual = (char *) gc_malloc (sizeof (tuntap->actual));      strcpy (tuntap_actual, tuntap->actual);      msg (M_INFO, "Closing tun/tap device");      close_tun (tuntap);      /* Run the down script -- note that it will run at reduced	 privilege if, for example, "--user nobody" was used. */      run_script (options->down_script, tuntap_actual, MAX_RW_SIZE_TUN (&frame),		  max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote);    } done:  /* pop our garbage collection level */  gc_free_level (gc_level);  /* return the signal that brought us here */  {    int s = signal_received;    signal_received = 0;    return s;  }}intmain (int argc, char *argv[]){  const int gc_level = gc_new_level ();  bool first_time = true;  int sig;#ifdef PID_TEST  packet_id_interactive_test();  /* test the sequence number code */  goto exit;#endif  error_reset ();                /* initialize error.c */  do {    struct options options;    init_options (&options);    /*     * Parse command line options,     * and read configuration file.     */    parse_argv (&options, argc, argv);    /*     * OpenSSL info print mode?     */#ifdef USE_CRYPTO    if (options.show_ciphers || options.show_digests#ifdef USE_SSL	|| options.show_tls_ciphers#endif	)      {	if (first_time)	  init_ssl_lib ();	if (options.show_ciphers)	  show_available_ciphers ();	if (options.show_digests)	  show_available_digests ();#ifdef USE_SSL	if (options.show_tls_ciphers)	  show_available_tls_ciphers ();#endif	free_ssl_lib ();	goto exit;      }    /*     * Possibly set --dev based on --dev-node.     * For example, if --dev-node /tmp/foo/tun, and --dev undefined,     * set --dev to tun.     */    if (!options.dev)      options.dev = dev_component_in_dev_node (options.dev_node);    /*     * Static pre-shared key generation mode?     */    if (options.genkey)      {	struct key key;	notnull (options.shared_secret_file,		 "shared secret output file (--secret)");	if (options.mlock)    /* should we disable paging? */	  do_mlockall(true);	generate_key_random (&key, NULL);	write_key_file (&key, options.shared_secret_file);	CLEAR (key);	goto exit;      }#endif /* USE_CRYPTO */    /*     * Persistent tun/tap device management mode?     */#ifdef TUNSETPERSIST    if (options.persist_config)      {	/* sanity check on options for --mktun or --rmtun */	notnull (options.dev, "tun/tap device (--dev)");	if (options.remote || options.ifconfig_local || options.ifconfig_remote#ifdef USE_CRYPTO	    || options.shared_secret_file#ifdef USE_SSL	    || options.tls_server || options.tls_client#endif#endif	    )	  msg (M_FATAL, "Options error: options --mktun or --rmtun should only be used together with --dev");	tuncfg (options.dev, options.dev_type, options.dev_node,		options.tun_ipv6, options.persist_mode);	goto exit;      }#endif    /*     * Main OpenVPN block -- tunnel generation mode     */    {#ifdef USE_CRYPTO      if (options.test_crypto)	{	  notnull (options.shared_secret_file, "key file (--secret)");	}      else#endif	notnull (options.dev, "tun/tap device (--dev)");      /*       * Sanity check on daemon/inetd modes       */      if (options.daemon && options.inetd)	{	  msg (M_WARN, "Options error: only one of --daemon or --inetd may be specified");	  usage_small ();	}      if (options.inetd && (options.local || options.remote))	{	  msg (M_WARN, "Options error: --local or --remote cannot be used with --inetd");	  usage_small ();	}      /*       * Sanity check on MTU parameters       */      if (options.tun_mtu_defined && options.udp_mtu_defined)	{	  msg (M_WARN, "Options error: only one of --tun-mtu or --udp-mtu may be defined (note that --ifconfig implies --udp-mtu %d)", DEFAULT_UDP_MTU);	  usage_small ();	}      if (!options.tun_mtu_defined && !options.udp_mtu_defined)	options.tun_mtu_defined = true;      /*       * Sanity check on --local, --remote, and ifconfig       */      if (string_defined_equal (options.local, options.remote)	  && options.local_port == options.remote_port)	{	  msg (M_WARN, "Options error: --remote and --local addresses are the same");	  usage_small ();	}	      if (string_defined_equal (options.local, options.ifconfig_local)	  || string_defined_equal (options.local, options.ifconfig_remote)	  || string_defined_equal (options.remote, options.ifconfig_local)	  || string_defined_equal (options.remote, options.ifconfig_remote))	{	  msg (M_WARN, "Options error: --local and --remote addresses must be distinct from --ifconfig addresses");	  usage_small ();	}      if (string_defined_equal (options.ifconfig_local, options.ifconfig_remote))	{	  msg (M_WARN, "Options error: local and remote --ifconfig addresses must be different");	  usage_small ();	}#ifdef USE_CRYPTO      if (first_time)	init_ssl_lib ();#ifdef USE_SSL      if (options.tls_server + options.tls_client +	  (options.shared_secret_file != NULL) > 1)	{	  msg (M_WARN, "specify only one of --tls-server, --tls-client, or --secret");	  usage_small ();	}      if (options.tls_server)	{	  notnull (options.dh_file, "DH file (--dh)");	}      if (options.tls_server || options.tls_client)	{	  notnull (options.ca_file, "CA file (--ca)");	  notnull (options.cert_file, "certificate file (--cert)");	  notnull (options.priv_key_file, "private key file (--key)");	  if (first_time && options.askpass)	    pem_password_callback (NULL, 0, 0, NULL);	}      else	{	  /*	   * Make sure user doesn't specify any TLS options	   * when in non-TLS mode.	   */#define MUST_BE_UNDEF(parm) if (options.parm != def.parm) msg (M_FATAL, err, #parm);	  const char err[] = "Parameter %s can only be specified in TLS-mode, i.e. where --tls-server or --tls-client is also specified.";	  struct options def;	  init_options (&def);	  MUST_BE_UNDEF (ca_file);	  MUST_BE_UNDEF (dh_file);	  MUST_BE_UNDEF (cert_file);	  MUST_BE_UNDEF (priv_key_file);	  MUST_BE_UNDEF (cipher_list);	  MUST_BE_UNDEF (tls_verify);	  MUST_BE_UNDEF (tls_timeout);	  MUST_BE_UNDEF (renegotiate_bytes);	  MUST_BE_UNDEF (renegotiate_packets);	  MUST_BE_UNDEF (renegotiate_seconds);	  MUST_BE_UNDEF (handshake_window);	  MUST_BE_UNDEF (transition_window);	  MUST_BE_UNDEF (tls_auth_file);	  MUST_BE_UNDEF (single_session);	  MUST_BE_UNDEF (disable_occ);	}#undef MUST_BE_UNDEF#endif /* USE_CRYPTO */#endif /* USE_SSL */      set_check_status (D_LINK_ERRORS, D_READ_WRITE);      set_debug_level (options.verbosity);      set_mute_cutoff (options.mute);      /* Become a daemon if requested */      if (first_time)	{	  if (options.daemon)	    {	      ASSERT (!options.inetd);	      become_daemon (options.cd_dir);	    }	}      /* show all option settings */      show_settings (&options);      /* Do Work */      {	struct udp_socket_addr usa;	struct key_schedule ks;	struct tuntap tuntap;	CLEAR (usa);	CLEAR (ks);	clear_tuntap (&tuntap);	do {	  sig = openvpn (&options, &usa, &tuntap, &ks, first_time);	  first_time = false;	} while (sig == SIGUSR1);      }    }    gc_collect (gc_level);  } while (sig == SIGHUP);  thread_cleanup();#ifdef USE_CRYPTO  free_ssl_lib ();#endif exit:  /* pop our garbage collection level */  gc_free_level (gc_level);  return 0;}/* * Basic threading test. */#if defined(USE_PTHREAD) && defined(USE_CRYPTO)static void*test_crypto_thread (void *arg){  struct udp_socket_addr usa;  struct tuntap tuntap;  struct key_schedule ks;  const struct options *opt = (struct options*) arg;  set_nice (opt->nice_work);  CLEAR (usa);  CLEAR (ks);  clear_tuntap (&tuntap);  openvpn (opt, &usa, &tuntap, &ks, false);  return NULL;}#endif

⌨️ 快捷键说明

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