?? openvpn.c
字號:
* 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. */#ifdef HAVE_GETTIMEOFDAY if (options->shaper) shaper_wrote_bytes (&shaper, BLEN (&to_udp) + datagram_overhead (ipv6_udp_transport));#endif#ifdef FRAGMENT_ENABLE if (fragment) fragment_post_send (fragment, BLEN (&to_udp) + datagram_overhead (ipv6_udp_transport));#endif /* * Let the pinger know that we sent a packet. */ if (options->ping_send_timeout) event_timeout_reset (&ping_send_interval, current);#if PASSTOS_CAPABILITY /* Set TOS */ if (ptos_defined) setsockopt(udp_socket.sd, IPPROTO_IP, IP_TOS, &ptos, sizeof(ptos));#endif /* 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", &udp_socket); 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 truncated/expanded on write to %s (tried=%d,actual=%d)", print_sockaddr (&to_udp_addr), BLEN (&to_udp), size); } /* Log packet send */#ifdef LOG_RW if (check_debug_level (D_LOG_RW) && !check_debug_level (D_LOG_RW + 1)) fprintf (stderr, "W");#endif msg (D_UDP_RW, "UDP WRITE [%d] to %s: %s", BLEN (&to_udp), 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 (&thread_parms);#endif free_buf (&read_udp_buf); free_buf (&read_tun_buf); free_buf (&ping_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, TUN_MTU_SIZE (&frame), max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote); }#ifdef USE_CRYPTO /* * Close packet-id persistance file */ packet_id_persist_save (pid_persist); if ( !(signal_received == SIGUSR1) ) packet_id_persist_close (pid_persist);#endif /* * Close fragmentation handler. */#ifdef FRAGMENT_ENABLE if (fragment) fragment_free (fragment);#endif 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 WIN32 init_win32 ();#endif init_random_seed(); /* init random() function, only used as source for weak random numbers */ error_reset (); /* initialize error.c */ reset_check_status (); /* initialize status check code in socket.c */#ifdef OPENVPN_DEBUG_COMMAND_LINE { int i; for (i = 0; i < argc; ++i) msg (M_INFO, "argv[%d] = '%s'", i, argv[i]); }#endif#ifdef PID_TEST packet_id_interactive_test(); /* test the sequence number code */ goto exit;#endif 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)", UDP_MTU_DEFAULT); usage_small (); } /* * If neither --tun-mtu or --udp-mtu specified, * use default --udp-mtu if --ifconfig specified, otherwise * use default --tun-mtu. */ if (!options.tun_mtu_defined && !options.udp_mtu_defined) { if (options.ifconfig_local || options.ifconfig_remote) options.udp_mtu_defined = true; else 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 */ possibly_become_daemon (0, &options, first_time); /* show all option settings */ show_settings (&options); /* Do Work */ { /* these objects are potentially persistent across SIGUSR1 resets */ struct udp_socket_addr usa; struct key_schedule ks; struct tuntap tuntap; struct packet_id_persist pid_persist; CLEAR (usa); CLEAR (ks); clear_tuntap (&tuntap); packet_id_persist_init (&pid_persist); do { sig = openvpn (&options, &usa, &tuntap, &ks, &pid_persist, first_time); first_time = false; } while (sig == SIGUSR1); } } gc_collect (gc_level); close_syslog (); } while (sig == SIGHUP); thread_cleanup();#ifdef USE_CRYPTO free_ssl_lib ();#endif#ifdef WIN32 uninit_win32 ();#endif exit:#if defined(MEASURE_TLS_HANDSHAKE_STATS) && defined(USE_CRYPTO) && defined(USE_SSL) show_tls_performance_stats();#endif /* pop our garbage collection level */ gc_free_level (gc_level); return OPENVPN_EXIT_STATUS_GOOD; /* exit point */}/* * 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; struct packet_id_persist pid_persist; const struct options *opt = (struct options*) arg; set_nice (opt->nice_work); CLEAR (usa); CLEAR (ks); clear_tuntap (&tuntap); packet_id_persist_init (&pid_persist); openvpn (opt, &usa, &tuntap, &ks, &pid_persist, false); return NULL;}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -