From 3a2bbdb05ca6a6996e424c9fb225cb0d53804125 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Iniesta Date: Tue, 27 Dec 2016 18:25:47 +0100 Subject: New upstream version 2.4.0 --- src/openvpn/forward.c | 2245 ++++++++++++++++++++++++++----------------------- 1 file changed, 1206 insertions(+), 1039 deletions(-) (limited to 'src/openvpn/forward.c') diff --git a/src/openvpn/forward.c b/src/openvpn/forward.c index b50a2e0..8102e94 100644 --- a/src/openvpn/forward.c +++ b/src/openvpn/forward.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -56,27 +56,27 @@ counter_type link_write_bytes_global; /* GLOBAL */ #ifdef ENABLE_DEBUG const char * -wait_status_string (struct context *c, struct gc_arena *gc) +wait_status_string(struct context *c, struct gc_arena *gc) { - struct buffer out = alloc_buf_gc (64, gc); - buf_printf (&out, "I/O WAIT %s|%s|%s|%s %s", - tun_stat (c->c1.tuntap, EVENT_READ, gc), - tun_stat (c->c1.tuntap, EVENT_WRITE, gc), - socket_stat (c->c2.link_socket, EVENT_READ, gc), - socket_stat (c->c2.link_socket, EVENT_WRITE, gc), - tv_string (&c->c2.timeval, gc)); - return BSTR (&out); + struct buffer out = alloc_buf_gc(64, gc); + buf_printf(&out, "I/O WAIT %s|%s|%s|%s %s", + tun_stat(c->c1.tuntap, EVENT_READ, gc), + tun_stat(c->c1.tuntap, EVENT_WRITE, gc), + socket_stat(c->c2.link_socket, EVENT_READ, gc), + socket_stat(c->c2.link_socket, EVENT_WRITE, gc), + tv_string(&c->c2.timeval, gc)); + return BSTR(&out); } void -show_wait_status (struct context *c) +show_wait_status(struct context *c) { - struct gc_arena gc = gc_new (); - dmsg (D_EVENT_WAIT, "%s", wait_status_string (c, &gc)); - gc_free (&gc); + struct gc_arena gc = gc_new(); + dmsg(D_EVENT_WAIT, "%s", wait_status_string(c, &gc)); + gc_free(&gc); } -#endif +#endif /* ifdef ENABLE_DEBUG */ /* * In TLS mode, let TLS level respond to any control-channel @@ -90,45 +90,47 @@ show_wait_status (struct context *c) */ #ifdef ENABLE_CRYPTO void -check_tls_dowork (struct context *c) +check_tls_dowork(struct context *c) { - interval_t wakeup = BIG_TIMEOUT; + interval_t wakeup = BIG_TIMEOUT; - if (interval_test (&c->c2.tmp_int)) + if (interval_test(&c->c2.tmp_int)) { - const int tmp_status = tls_multi_process - (c->c2.tls_multi, &c->c2.to_link, &c->c2.to_link_addr, - get_link_socket_info (c), &wakeup); - if (tmp_status == TLSMP_ACTIVE) - { - update_time (); - interval_action (&c->c2.tmp_int); - } - else if (tmp_status == TLSMP_KILL) - { - register_signal (c, SIGTERM, "auth-control-exit"); - } - - interval_future_trigger (&c->c2.tmp_int, wakeup); + const int tmp_status = tls_multi_process + (c->c2.tls_multi, &c->c2.to_link, &c->c2.to_link_addr, + get_link_socket_info(c), &wakeup); + if (tmp_status == TLSMP_ACTIVE) + { + update_time(); + interval_action(&c->c2.tmp_int); + } + else if (tmp_status == TLSMP_KILL) + { + register_signal(c, SIGTERM, "auth-control-exit"); + } + + interval_future_trigger(&c->c2.tmp_int, wakeup); } - interval_schedule_wakeup (&c->c2.tmp_int, &wakeup); + interval_schedule_wakeup(&c->c2.tmp_int, &wakeup); - if (wakeup) - context_reschedule_sec (c, wakeup); + if (wakeup) + { + context_reschedule_sec(c, wakeup); + } } void -check_tls_errors_co (struct context *c) +check_tls_errors_co(struct context *c) { - msg (D_STREAM_ERRORS, "Fatal TLS error (check_tls_errors_co), restarting"); - register_signal (c, c->c2.tls_exit_signal, "tls-error"); /* SOFT-SIGUSR1 -- TLS error */ + msg(D_STREAM_ERRORS, "Fatal TLS error (check_tls_errors_co), restarting"); + register_signal(c, c->c2.tls_exit_signal, "tls-error"); /* SOFT-SIGUSR1 -- TLS error */ } void -check_tls_errors_nco (struct context *c) +check_tls_errors_nco(struct context *c) { - register_signal (c, c->c2.tls_exit_signal, "tls-error"); /* SOFT-SIGUSR1 -- TLS error */ + register_signal(c, c->c2.tls_exit_signal, "tls-error"); /* SOFT-SIGUSR1 -- TLS error */ } #endif /* ENABLE_CRYPTO */ @@ -139,38 +141,48 @@ check_tls_errors_nco (struct context *c) * messages on the control channel. */ void -check_incoming_control_channel_dowork (struct context *c) +check_incoming_control_channel_dowork(struct context *c) { - const int len = tls_test_payload_len (c->c2.tls_multi); - if (len) - { - struct gc_arena gc = gc_new (); - struct buffer buf = alloc_buf_gc (len, &gc); - if (tls_rec_payload (c->c2.tls_multi, &buf)) - { - /* force null termination of message */ - buf_null_terminate (&buf); - - /* enforce character class restrictions */ - string_mod (BSTR (&buf), CC_PRINT, CC_CRLF, 0); - - if (buf_string_match_head_str (&buf, "AUTH_FAILED")) - receive_auth_failed (c, &buf); - else if (buf_string_match_head_str (&buf, "PUSH_")) - incoming_push_message (c, &buf); - else if (buf_string_match_head_str (&buf, "RESTART")) - server_pushed_signal (c, &buf, true, 7); - else if (buf_string_match_head_str (&buf, "HALT")) - server_pushed_signal (c, &buf, false, 4); - else - msg (D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR (&buf)); - } - else - { - msg (D_PUSH_ERRORS, "WARNING: Receive control message failed"); - } - - gc_free (&gc); + const int len = tls_test_payload_len(c->c2.tls_multi); + if (len) + { + struct gc_arena gc = gc_new(); + struct buffer buf = alloc_buf_gc(len, &gc); + if (tls_rec_payload(c->c2.tls_multi, &buf)) + { + /* force null termination of message */ + buf_null_terminate(&buf); + + /* enforce character class restrictions */ + string_mod(BSTR(&buf), CC_PRINT, CC_CRLF, 0); + + if (buf_string_match_head_str(&buf, "AUTH_FAILED")) + { + receive_auth_failed(c, &buf); + } + else if (buf_string_match_head_str(&buf, "PUSH_")) + { + incoming_push_message(c, &buf); + } + else if (buf_string_match_head_str(&buf, "RESTART")) + { + server_pushed_signal(c, &buf, true, 7); + } + else if (buf_string_match_head_str(&buf, "HALT")) + { + server_pushed_signal(c, &buf, false, 4); + } + else + { + msg(D_PUSH_ERRORS, "WARNING: Received unknown control message: %s", BSTR(&buf)); + } + } + else + { + msg(D_PUSH_ERRORS, "WARNING: Receive control message failed"); + } + + gc_free(&gc); } } @@ -178,12 +190,12 @@ check_incoming_control_channel_dowork (struct context *c) * Periodically resend PUSH_REQUEST until PUSH message received */ void -check_push_request_dowork (struct context *c) +check_push_request_dowork(struct context *c) { - send_push_request (c); + send_push_request(c); - /* if no response to first push_request, retry at PUSH_REQUEST_INTERVAL second intervals */ - event_timeout_modify_wakeup (&c->c2.push_request_interval, PUSH_REQUEST_INTERVAL); + /* if no response to first push_request, retry at PUSH_REQUEST_INTERVAL second intervals */ + event_timeout_modify_wakeup(&c->c2.push_request_interval, PUSH_REQUEST_INTERVAL); } #endif /* P2MP */ @@ -192,40 +204,40 @@ check_push_request_dowork (struct context *c) * Things that need to happen immediately after connection initiation should go here. */ void -check_connection_established_dowork (struct context *c) +check_connection_established_dowork(struct context *c) { - if (event_timeout_trigger (&c->c2.wait_for_connect, &c->c2.timeval, ETT_DEFAULT)) + if (event_timeout_trigger(&c->c2.wait_for_connect, &c->c2.timeval, ETT_DEFAULT)) { - if (CONNECTION_ESTABLISHED (c)) - { + if (CONNECTION_ESTABLISHED(c)) + { #if P2MP - /* if --pull was specified, send a push request to server */ - if (c->c2.tls_multi && c->options.pull) - { + /* if --pull was specified, send a push request to server */ + if (c->c2.tls_multi && c->options.pull) + { #ifdef ENABLE_MANAGEMENT - if (management) - { - management_set_state (management, - OPENVPN_STATE_GET_CONFIG, - NULL, - NULL, - NULL, - NULL, - NULL); - } + if (management) + { + management_set_state(management, + OPENVPN_STATE_GET_CONFIG, + NULL, + NULL, + NULL, + NULL, + NULL); + } #endif - /* fire up push request right away (already 1s delayed) */ - event_timeout_init (&c->c2.push_request_interval, 0, now); - reset_coarse_timers (c); - } - else -#endif - { - do_up (c, false, 0); - } - - event_timeout_clear (&c->c2.wait_for_connect); - } + /* fire up push request right away (already 1s delayed) */ + event_timeout_init(&c->c2.push_request_interval, 0, now); + reset_coarse_timers(c); + } + else +#endif /* if P2MP */ + { + do_up(c, false, 0); + } + + event_timeout_clear(&c->c2.wait_for_connect); + } } } @@ -235,35 +247,36 @@ check_connection_established_dowork (struct context *c) * etc. */ bool -send_control_channel_string (struct context *c, const char *str, int msglevel) +send_control_channel_string(struct context *c, const char *str, int msglevel) { #ifdef ENABLE_CRYPTO - if (c->c2.tls_multi) { - struct gc_arena gc = gc_new (); - bool stat; - - /* buffered cleartext write onto TLS control channel */ - stat = tls_send_payload (c->c2.tls_multi, (uint8_t*) str, strlen (str) + 1); - - /* - * Reschedule tls_multi_process. - * NOTE: in multi-client mode, usually the below two statements are - * insufficient to reschedule the client instance object unless - * multi_schedule_context_wakeup(m, mi) is also called. - */ - interval_action (&c->c2.tmp_int); - context_immediate_reschedule (c); /* ZERO-TIMEOUT */ - - msg (msglevel, "SENT CONTROL [%s]: '%s' (status=%d)", - tls_common_name (c->c2.tls_multi, false), - sanitize_control_message (str, &gc), - (int) stat); - - gc_free (&gc); - return stat; - } + if (c->c2.tls_multi) + { + struct gc_arena gc = gc_new(); + bool stat; + + /* buffered cleartext write onto TLS control channel */ + stat = tls_send_payload(c->c2.tls_multi, (uint8_t *) str, strlen(str) + 1); + + /* + * Reschedule tls_multi_process. + * NOTE: in multi-client mode, usually the below two statements are + * insufficient to reschedule the client instance object unless + * multi_schedule_context_wakeup(m, mi) is also called. + */ + interval_action(&c->c2.tmp_int); + context_immediate_reschedule(c); /* ZERO-TIMEOUT */ + + msg(msglevel, "SENT CONTROL [%s]: '%s' (status=%d)", + tls_common_name(c->c2.tls_multi, false), + sanitize_control_message(str, &gc), + (int) stat); + + gc_free(&gc); + return stat; + } #endif /* ENABLE_CRYPTO */ - return true; + return true; } /* @@ -271,46 +284,48 @@ send_control_channel_string (struct context *c, const char *str, int msglevel) */ static void -check_add_routes_action (struct context *c, const bool errors) +check_add_routes_action(struct context *c, const bool errors) { - do_route (&c->options, c->c1.route_list, c->c1.route_ipv6_list, - c->c1.tuntap, c->plugins, c->c2.es); - update_time (); - event_timeout_clear (&c->c2.route_wakeup); - event_timeout_clear (&c->c2.route_wakeup_expire); - initialization_sequence_completed (c, errors ? ISC_ERRORS : 0); /* client/p2p --route-delay was defined */ + do_route(&c->options, c->c1.route_list, c->c1.route_ipv6_list, + c->c1.tuntap, c->plugins, c->c2.es); + update_time(); + event_timeout_clear(&c->c2.route_wakeup); + event_timeout_clear(&c->c2.route_wakeup_expire); + initialization_sequence_completed(c, errors ? ISC_ERRORS : 0); /* client/p2p --route-delay was defined */ } void -check_add_routes_dowork (struct context *c) +check_add_routes_dowork(struct context *c) { - if (test_routes (c->c1.route_list, c->c1.tuntap)) + if (test_routes(c->c1.route_list, c->c1.tuntap)) { - check_add_routes_action (c, false); + check_add_routes_action(c, false); } - else if (event_timeout_trigger (&c->c2.route_wakeup_expire, &c->c2.timeval, ETT_DEFAULT)) + else if (event_timeout_trigger(&c->c2.route_wakeup_expire, &c->c2.timeval, ETT_DEFAULT)) { - check_add_routes_action (c, true); + check_add_routes_action(c, true); } - else + else { - msg (D_ROUTE, "Route: Waiting for TUN/TAP interface to come up..."); - if (c->c1.tuntap) - { - if (!tun_standby (c->c1.tuntap)) - { - register_signal (c, SIGHUP, "ip-fail"); - c->persist.restart_sleep_seconds = 10; + msg(D_ROUTE, "Route: Waiting for TUN/TAP interface to come up..."); + if (c->c1.tuntap) + { + if (!tun_standby(c->c1.tuntap)) + { + register_signal(c, SIGHUP, "ip-fail"); + c->persist.restart_sleep_seconds = 10; #ifdef _WIN32 - show_routes (M_INFO|M_NOPREFIX); - show_adapters (M_INFO|M_NOPREFIX); + show_routes(M_INFO|M_NOPREFIX); + show_adapters(M_INFO|M_NOPREFIX); #endif - } - } - update_time (); - if (c->c2.route_wakeup.n != 1) - event_timeout_init (&c->c2.route_wakeup, 1, now); - event_timeout_reset (&c->c2.ping_rec_interval); + } + } + update_time(); + if (c->c2.route_wakeup.n != 1) + { + event_timeout_init(&c->c2.route_wakeup, 1, now); + } + event_timeout_reset(&c->c2.ping_rec_interval); } } @@ -318,31 +333,31 @@ check_add_routes_dowork (struct context *c) * Should we exit due to inactivity timeout? */ void -check_inactivity_timeout_dowork (struct context *c) +check_inactivity_timeout_dowork(struct context *c) { - msg (M_INFO, "Inactivity timeout (--inactive), exiting"); - register_signal (c, SIGTERM, "inactive"); + msg(M_INFO, "Inactivity timeout (--inactive), exiting"); + register_signal(c, SIGTERM, "inactive"); } int -get_server_poll_remaining_time (struct event_timeout* server_poll_timeout) +get_server_poll_remaining_time(struct event_timeout *server_poll_timeout) { update_time(); int remaining = event_timeout_remaining(server_poll_timeout); - return max_int (0, remaining); + return max_int(0, remaining); } #if P2MP void -check_server_poll_timeout_dowork (struct context *c) +check_server_poll_timeout_dowork(struct context *c) { - event_timeout_reset (&c->c2.server_poll_interval); - ASSERT(c->c2.tls_multi); - if (!tls_initial_packet_received (c->c2.tls_multi)) + event_timeout_reset(&c->c2.server_poll_interval); + ASSERT(c->c2.tls_multi); + if (!tls_initial_packet_received(c->c2.tls_multi)) { - msg (M_INFO, "Server poll timeout, restarting"); - register_signal (c, SIGUSR1, "server_poll"); - c->persist.restart_sleep_seconds = -1; + msg(M_INFO, "Server poll timeout, restarting"); + register_signal(c, SIGUSR1, "server_poll"); + c->persist.restart_sleep_seconds = -1; } } @@ -350,35 +365,37 @@ check_server_poll_timeout_dowork (struct context *c) * Schedule a signal n_seconds from now. */ void -schedule_exit (struct context *c, const int n_seconds, const int signal) +schedule_exit(struct context *c, const int n_seconds, const int signal) { - tls_set_single_session (c->c2.tls_multi); - update_time (); - reset_coarse_timers (c); - event_timeout_init (&c->c2.scheduled_exit, n_seconds, now); - c->c2.scheduled_exit_signal = signal; - msg (D_SCHED_EXIT, "Delayed exit in %d seconds", n_seconds); + tls_set_single_session(c->c2.tls_multi); + update_time(); + reset_coarse_timers(c); + event_timeout_init(&c->c2.scheduled_exit, n_seconds, now); + c->c2.scheduled_exit_signal = signal; + msg(D_SCHED_EXIT, "Delayed exit in %d seconds", n_seconds); } /* * Scheduled exit? */ void -check_scheduled_exit_dowork (struct context *c) +check_scheduled_exit_dowork(struct context *c) { - register_signal (c, c->c2.scheduled_exit_signal, "delayed-exit"); + register_signal(c, c->c2.scheduled_exit_signal, "delayed-exit"); } -#endif +#endif /* if P2MP */ /* * Should we write timer-triggered status file. */ void -check_status_file_dowork (struct context *c) +check_status_file_dowork(struct context *c) { - if (c->c1.status_output) - print_status (c, c->c1.status_output); + if (c->c1.status_output) + { + print_status(c, c->c1.status_output); + } } #ifdef ENABLE_FRAGMENT @@ -386,46 +403,46 @@ check_status_file_dowork (struct context *c) * Should we deliver a datagram fragment to remote? */ void -check_fragment_dowork (struct context *c) +check_fragment_dowork(struct context *c) { - struct link_socket_info *lsi = get_link_socket_info (c); + struct link_socket_info *lsi = get_link_socket_info(c); - /* OS MTU Hint? */ - if (lsi->mtu_changed) + /* OS MTU Hint? */ + if (lsi->mtu_changed) { - frame_adjust_path_mtu (&c->c2.frame_fragment, c->c2.link_socket->mtu, - c->options.ce.proto); - lsi->mtu_changed = false; + frame_adjust_path_mtu(&c->c2.frame_fragment, c->c2.link_socket->mtu, + c->options.ce.proto); + lsi->mtu_changed = false; } - if (fragment_outgoing_defined (c->c2.fragment)) + if (fragment_outgoing_defined(c->c2.fragment)) { - if (!c->c2.to_link.len) - { - /* encrypt a fragment for output to TCP/UDP port */ - ASSERT (fragment_ready_to_send (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment)); - encrypt_sign (c, false); - } + if (!c->c2.to_link.len) + { + /* encrypt a fragment for output to TCP/UDP port */ + ASSERT(fragment_ready_to_send(c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment)); + encrypt_sign(c, false); + } } - fragment_housekeeping (c->c2.fragment, &c->c2.frame_fragment, &c->c2.timeval); + fragment_housekeeping(c->c2.fragment, &c->c2.frame_fragment, &c->c2.timeval); } -#endif +#endif /* ifdef ENABLE_FRAGMENT */ /* * Buffer reallocation, for use with null encryption. */ static inline void -buffer_turnover (const uint8_t *orig_buf, struct buffer *dest_stub, struct buffer *src_stub, struct buffer *storage) +buffer_turnover(const uint8_t *orig_buf, struct buffer *dest_stub, struct buffer *src_stub, struct buffer *storage) { - if (orig_buf == src_stub->data && src_stub->data != storage->data) + if (orig_buf == src_stub->data && src_stub->data != storage->data) { - buf_assign (storage, src_stub); - *dest_stub = *storage; + buf_assign(storage, src_stub); + *dest_stub = *storage; } - else + else { - *dest_stub = *src_stub; + *dest_stub = *src_stub; } } @@ -435,188 +452,218 @@ buffer_turnover (const uint8_t *orig_buf, struct buffer *dest_stub, struct buffe * Output: c->c2.to_link */ void -encrypt_sign (struct context *c, bool comp_frag) +encrypt_sign(struct context *c, bool comp_frag) { - struct context_buffers *b = c->c2.buffers; - const uint8_t *orig_buf = c->c2.buf.data; - struct crypto_options *co = NULL; + struct context_buffers *b = c->c2.buffers; + const uint8_t *orig_buf = c->c2.buf.data; + struct crypto_options *co = NULL; #if P2MP_SERVER - /* - * Drop non-TLS outgoing packet if client-connect script/plugin - * has not yet succeeded. - */ - if (c->c2.context_auth != CAS_SUCCEEDED) - c->c2.buf.len = 0; + /* + * Drop non-TLS outgoing packet if client-connect script/plugin + * has not yet succeeded. + */ + if (c->c2.context_auth != CAS_SUCCEEDED) + { + c->c2.buf.len = 0; + } #endif - if (comp_frag) + if (comp_frag) { #ifdef USE_COMP - /* Compress the packet. */ - if (c->c2.comp_context) - (*c->c2.comp_context->alg.compress)(&c->c2.buf, b->compress_buf, c->c2.comp_context, &c->c2.frame); + /* Compress the packet. */ + if (c->c2.comp_context) + { + (*c->c2.comp_context->alg.compress)(&c->c2.buf, b->compress_buf, c->c2.comp_context, &c->c2.frame); + } #endif #ifdef ENABLE_FRAGMENT - if (c->c2.fragment) - fragment_outgoing (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); + if (c->c2.fragment) + { + fragment_outgoing(c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); + } #endif } #ifdef ENABLE_CRYPTO - /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */ - ASSERT (buf_init (&b->encrypt_buf, FRAME_HEADROOM (&c->c2.frame))); + /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */ + ASSERT(buf_init(&b->encrypt_buf, FRAME_HEADROOM(&c->c2.frame))); - if (c->c2.tls_multi) + if (c->c2.tls_multi) { - /* Get the key we will use to encrypt the packet. */ - tls_pre_encrypt (c->c2.tls_multi, &c->c2.buf, &co); - /* If using P_DATA_V2, prepend the 1-byte opcode and 3-byte peer-id to the - * packet before openvpn_encrypt(), so we can authenticate the opcode too. - */ - if (c->c2.buf.len > 0 && !c->c2.tls_multi->opt.server && c->c2.tls_multi->use_peer_id) - tls_prepend_opcode_v2 (c->c2.tls_multi, &b->encrypt_buf); + /* Get the key we will use to encrypt the packet. */ + tls_pre_encrypt(c->c2.tls_multi, &c->c2.buf, &co); + /* If using P_DATA_V2, prepend the 1-byte opcode and 3-byte peer-id to the + * packet before openvpn_encrypt(), so we can authenticate the opcode too. + */ + if (c->c2.buf.len > 0 && !c->c2.tls_multi->opt.server && c->c2.tls_multi->use_peer_id) + { + tls_prepend_opcode_v2(c->c2.tls_multi, &b->encrypt_buf); + } } - else + else { - co = &c->c2.crypto_options; + co = &c->c2.crypto_options; } - /* Encrypt and authenticate the packet */ - openvpn_encrypt (&c->c2.buf, b->encrypt_buf, co); + /* Encrypt and authenticate the packet */ + openvpn_encrypt(&c->c2.buf, b->encrypt_buf, co); - /* Do packet administration */ - if (c->c2.tls_multi) + /* Do packet administration */ + if (c->c2.tls_multi) { - if (c->c2.buf.len > 0 && (c->c2.tls_multi->opt.server || !c->c2.tls_multi->use_peer_id)) - tls_prepend_opcode_v1(c->c2.tls_multi, &c->c2.buf); - tls_post_encrypt (c->c2.tls_multi, &c->c2.buf); + if (c->c2.buf.len > 0 && (c->c2.tls_multi->opt.server || !c->c2.tls_multi->use_peer_id)) + { + tls_prepend_opcode_v1(c->c2.tls_multi, &c->c2.buf); + } + tls_post_encrypt(c->c2.tls_multi, &c->c2.buf); } -#endif +#endif /* ifdef ENABLE_CRYPTO */ - /* - * Get the address we will be sending the packet to. - */ - link_socket_get_outgoing_addr (&c->c2.buf, get_link_socket_info (c), - &c->c2.to_link_addr); + /* + * Get the address we will be sending the packet to. + */ + link_socket_get_outgoing_addr(&c->c2.buf, get_link_socket_info(c), + &c->c2.to_link_addr); - /* if null encryption, copy result to read_tun_buf */ - buffer_turnover (orig_buf, &c->c2.to_link, &c->c2.buf, &b->read_tun_buf); + /* if null encryption, copy result to read_tun_buf */ + buffer_turnover(orig_buf, &c->c2.to_link, &c->c2.buf, &b->read_tun_buf); } /* * Coarse timers work to 1 second resolution. */ static void -process_coarse_timers (struct context *c) +process_coarse_timers(struct context *c) { #ifdef ENABLE_CRYPTO - /* flush current packet-id to file once per 60 - seconds if --replay-persist was specified */ - check_packet_id_persist_flush (c); + /* flush current packet-id to file once per 60 + * seconds if --replay-persist was specified */ + check_packet_id_persist_flush(c); #endif - /* should we update status file? */ - check_status_file (c); + /* should we update status file? */ + check_status_file(c); - /* process connection establishment items */ - check_connection_established (c); + /* process connection establishment items */ + check_connection_established(c); #if P2MP - /* see if we should send a push_request in response to --pull */ - check_push_request (c); + /* see if we should send a push_request in response to --pull */ + check_push_request(c); #endif #ifdef PLUGIN_PF - pf_check_reload (c); + pf_check_reload(c); #endif - /* process --route options */ - check_add_routes (c); + /* process --route options */ + check_add_routes(c); - /* possibly exit due to --inactive */ - check_inactivity_timeout (c); - if (c->sig->signal_received) - return; + /* possibly exit due to --inactive */ + check_inactivity_timeout(c); + if (c->sig->signal_received) + { + return; + } - /* restart if ping not received */ - check_ping_restart (c); - if (c->sig->signal_received) - return; + /* restart if ping not received */ + check_ping_restart(c); + if (c->sig->signal_received) + { + return; + } #if P2MP - if (c->c2.tls_multi) + if (c->c2.tls_multi) { - check_server_poll_timeout (c); - if (c->sig->signal_received) - return; - - check_scheduled_exit (c); - if (c->sig->signal_received) - return; + check_server_poll_timeout(c); + if (c->sig->signal_received) + { + return; + } + + check_scheduled_exit(c); + if (c->sig->signal_received) + { + return; + } } #endif #ifdef ENABLE_OCC - /* Should we send an OCC_REQUEST message? */ - check_send_occ_req (c); + /* Should we send an OCC_REQUEST message? */ + check_send_occ_req(c); - /* Should we send an MTU load test? */ - check_send_occ_load_test (c); + /* Should we send an MTU load test? */ + check_send_occ_load_test(c); - /* Should we send an OCC_EXIT message to remote? */ - if (c->c2.explicit_exit_notification_time_wait) - process_explicit_exit_notification_timer_wakeup (c); + /* Should we send an OCC_EXIT message to remote? */ + if (c->c2.explicit_exit_notification_time_wait) + { + process_explicit_exit_notification_timer_wakeup(c); + } #endif - /* Should we ping the remote? */ - check_ping_send (c); + /* Should we ping the remote? */ + check_ping_send(c); } static void -check_coarse_timers_dowork (struct context *c) +check_coarse_timers_dowork(struct context *c) { - const struct timeval save = c->c2.timeval; - c->c2.timeval.tv_sec = BIG_TIMEOUT; - c->c2.timeval.tv_usec = 0; - process_coarse_timers (c); - c->c2.coarse_timer_wakeup = now + c->c2.timeval.tv_sec; + const struct timeval save = c->c2.timeval; + c->c2.timeval.tv_sec = BIG_TIMEOUT; + c->c2.timeval.tv_usec = 0; + process_coarse_timers(c); + c->c2.coarse_timer_wakeup = now + c->c2.timeval.tv_sec; - dmsg (D_INTERVAL, "TIMER: coarse timer wakeup %d seconds", (int) c->c2.timeval.tv_sec); + dmsg(D_INTERVAL, "TIMER: coarse timer wakeup %d seconds", (int) c->c2.timeval.tv_sec); - /* Is the coarse timeout NOT the earliest one? */ - if (c->c2.timeval.tv_sec > save.tv_sec) - c->c2.timeval = save; + /* Is the coarse timeout NOT the earliest one? */ + if (c->c2.timeval.tv_sec > save.tv_sec) + { + c->c2.timeval = save; + } } static inline void -check_coarse_timers (struct context *c) +check_coarse_timers(struct context *c) { - const time_t local_now = now; - if (local_now >= c->c2.coarse_timer_wakeup) - check_coarse_timers_dowork (c); - else - context_reschedule_sec (c, c->c2.coarse_timer_wakeup - local_now); + const time_t local_now = now; + if (local_now >= c->c2.coarse_timer_wakeup) + { + check_coarse_timers_dowork(c); + } + else + { + context_reschedule_sec(c, c->c2.coarse_timer_wakeup - local_now); + } } static void -check_timeout_random_component_dowork (struct context *c) +check_timeout_random_component_dowork(struct context *c) { - const int update_interval = 10; /* seconds */ - c->c2.update_timeout_random_component = now + update_interval; - c->c2.timeout_random_component.tv_usec = (time_t) get_random () & 0x0003FFFF; - c->c2.timeout_random_component.tv_sec = 0; + const int update_interval = 10; /* seconds */ + c->c2.update_timeout_random_component = now + update_interval; + c->c2.timeout_random_component.tv_usec = (time_t) get_random() & 0x0003FFFF; + c->c2.timeout_random_component.tv_sec = 0; - dmsg (D_INTERVAL, "RANDOM USEC=%d", (int) c->c2.timeout_random_component.tv_usec); + dmsg(D_INTERVAL, "RANDOM USEC=%d", (int) c->c2.timeout_random_component.tv_usec); } static inline void -check_timeout_random_component (struct context *c) +check_timeout_random_component(struct context *c) { - if (now >= c->c2.update_timeout_random_component) - check_timeout_random_component_dowork (c); - if (c->c2.timeval.tv_sec >= 1) - tv_add (&c->c2.timeval, &c->c2.timeout_random_component); + if (now >= c->c2.update_timeout_random_component) + { + check_timeout_random_component_dowork(c); + } + if (c->c2.timeval.tv_sec >= 1) + { + tv_add(&c->c2.timeval, &c->c2.timeout_random_component); + } } /* @@ -625,35 +672,39 @@ check_timeout_random_component (struct context *c) */ static inline void -socks_postprocess_incoming_link (struct context *c) +socks_postprocess_incoming_link(struct context *c) { - if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) - socks_process_incoming_udp (&c->c2.buf, &c->c2.from); + if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) + { + socks_process_incoming_udp(&c->c2.buf, &c->c2.from); + } } static inline void -socks_preprocess_outgoing_link (struct context *c, - struct link_socket_actual **to_addr, - int *size_delta) +socks_preprocess_outgoing_link(struct context *c, + struct link_socket_actual **to_addr, + int *size_delta) { - if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) + if (c->c2.link_socket->socks_proxy && c->c2.link_socket->info.proto == PROTO_UDP) { - *size_delta += socks_process_outgoing_udp (&c->c2.to_link, c->c2.to_link_addr); - *to_addr = &c->c2.link_socket->socks_relay; + *size_delta += socks_process_outgoing_udp(&c->c2.to_link, c->c2.to_link_addr); + *to_addr = &c->c2.link_socket->socks_relay; } } /* undo effect of socks_preprocess_outgoing_link */ static inline void -link_socket_write_post_size_adjust (int *size, - int size_delta, - struct buffer *buf) +link_socket_write_post_size_adjust(int *size, + int size_delta, + struct buffer *buf) { - if (size_delta > 0 && *size > size_delta) + if (size_delta > 0 && *size > size_delta) { - *size -= size_delta; - if (!buf_advance (buf, size_delta)) - *size = 0; + *size -= size_delta; + if (!buf_advance(buf, size_delta)) + { + *size = 0; + } } } @@ -662,279 +713,306 @@ link_socket_write_post_size_adjust (int *size, */ void -read_incoming_link (struct context *c) +read_incoming_link(struct context *c) { - /* - * Set up for recvfrom call to read datagram - * sent to our TCP/UDP port. - */ - int status; + /* + * Set up for recvfrom call to read datagram + * sent to our TCP/UDP port. + */ + int status; - /*ASSERT (!c->c2.to_tun.len);*/ + /*ASSERT (!c->c2.to_tun.len);*/ - perf_push (PERF_READ_IN_LINK); + perf_push(PERF_READ_IN_LINK); - c->c2.buf = c->c2.buffers->read_link_buf; - ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM_ADJ (&c->c2.frame, FRAME_HEADROOM_MARKER_READ_LINK))); + c->c2.buf = c->c2.buffers->read_link_buf; + ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM_ADJ(&c->c2.frame, FRAME_HEADROOM_MARKER_READ_LINK))); - status = link_socket_read (c->c2.link_socket, - &c->c2.buf, - &c->c2.from); + status = link_socket_read(c->c2.link_socket, + &c->c2.buf, + &c->c2.from); - if (socket_connection_reset (c->c2.link_socket, status)) + if (socket_connection_reset(c->c2.link_socket, status)) { #if PORT_SHARE - if (port_share && socket_foreign_protocol_detected (c->c2.link_socket)) - { - const struct buffer *fbuf = socket_foreign_protocol_head (c->c2.link_socket); - const int sd = socket_foreign_protocol_sd (c->c2.link_socket); - port_share_redirect (port_share, fbuf, sd); - register_signal (c, SIGTERM, "port-share-redirect"); - } - else + if (port_share && socket_foreign_protocol_detected(c->c2.link_socket)) + { + const struct buffer *fbuf = socket_foreign_protocol_head(c->c2.link_socket); + const int sd = socket_foreign_protocol_sd(c->c2.link_socket); + port_share_redirect(port_share, fbuf, sd); + register_signal(c, SIGTERM, "port-share-redirect"); + } + else #endif - { - /* received a disconnect from a connection-oriented protocol */ - if (c->options.inetd) - { - register_signal (c, SIGTERM, "connection-reset-inetd"); - msg (D_STREAM_ERRORS, "Connection reset, inetd/xinetd exit [%d]", status); - } - else - { + { + /* received a disconnect from a connection-oriented protocol */ + if (c->options.inetd) + { + register_signal(c, SIGTERM, "connection-reset-inetd"); + msg(D_STREAM_ERRORS, "Connection reset, inetd/xinetd exit [%d]", status); + } + else + { #ifdef ENABLE_OCC - if (event_timeout_defined(&c->c2.explicit_exit_notification_interval)) - { - msg (D_STREAM_ERRORS, "Connection reset during exit notification period, ignoring [%d]", status); - openvpn_sleep(1); - } - else + if (event_timeout_defined(&c->c2.explicit_exit_notification_interval)) + { + msg(D_STREAM_ERRORS, "Connection reset during exit notification period, ignoring [%d]", status); + openvpn_sleep(1); + } + else #endif - { - register_signal (c, SIGUSR1, "connection-reset"); /* SOFT-SIGUSR1 -- TCP connection reset */ - msg (D_STREAM_ERRORS, "Connection reset, restarting [%d]", status); - } - } - } - perf_pop (); - return; + { + register_signal(c, SIGUSR1, "connection-reset"); /* SOFT-SIGUSR1 -- TCP connection reset */ + msg(D_STREAM_ERRORS, "Connection reset, restarting [%d]", status); + } + } + } + perf_pop(); + return; } - /* check recvfrom status */ - check_status (status, "read", c->c2.link_socket, NULL); + /* check recvfrom status */ + check_status(status, "read", c->c2.link_socket, NULL); - /* Remove socks header if applicable */ - socks_postprocess_incoming_link (c); + /* Remove socks header if applicable */ + socks_postprocess_incoming_link(c); - perf_pop (); + perf_pop(); } bool -process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated) +process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, bool floated) { - struct gc_arena gc = gc_new (); - bool decrypt_status = false; + struct gc_arena gc = gc_new(); + bool decrypt_status = false; - if (c->c2.buf.len > 0) + if (c->c2.buf.len > 0) { - c->c2.link_read_bytes += c->c2.buf.len; - link_read_bytes_global += c->c2.buf.len; + c->c2.link_read_bytes += c->c2.buf.len; + link_read_bytes_global += c->c2.buf.len; #ifdef ENABLE_MEMSTATS - if (mmap_stats) - mmap_stats->link_read_bytes = link_read_bytes_global; + if (mmap_stats) + { + mmap_stats->link_read_bytes = link_read_bytes_global; + } #endif - c->c2.original_recv_size = c->c2.buf.len; + c->c2.original_recv_size = c->c2.buf.len; #ifdef ENABLE_MANAGEMENT - if (management) - { - management_bytes_in (management, c->c2.buf.len); + if (management) + { + management_bytes_in(management, c->c2.buf.len); #ifdef MANAGEMENT_DEF_AUTH - management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); + management_bytes_server(management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); #endif - } + } #endif } - else - c->c2.original_recv_size = 0; - + else + { + c->c2.original_recv_size = 0; + } + #ifdef ENABLE_DEBUG - /* take action to corrupt packet if we are in gremlin test mode */ - if (c->options.gremlin) { - if (!ask_gremlin (c->options.gremlin)) - c->c2.buf.len = 0; - corrupt_gremlin (&c->c2.buf, c->options.gremlin); - } + /* take action to corrupt packet if we are in gremlin test mode */ + if (c->options.gremlin) + { + if (!ask_gremlin(c->options.gremlin)) + { + c->c2.buf.len = 0; + } + corrupt_gremlin(&c->c2.buf, c->options.gremlin); + } #endif - /* log incoming packet */ + /* log incoming packet */ #ifdef LOG_RW - if (c->c2.log_rw && c->c2.buf.len > 0) - fprintf (stderr, "R"); + if (c->c2.log_rw && c->c2.buf.len > 0) + { + fprintf(stderr, "R"); + } #endif - msg (D_LINK_RW, "%s READ [%d] from %s: %s", - proto2ascii (lsi->proto, lsi->af, true), - BLEN (&c->c2.buf), - print_link_socket_actual (&c->c2.from, &gc), - PROTO_DUMP (&c->c2.buf, &gc)); - - /* - * 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 or -1, - * telling downstream stages to ignore the packet. - */ - if (c->c2.buf.len > 0) - { - struct crypto_options *co = NULL; - const uint8_t *ad_start = NULL; - if (!link_socket_verify_incoming_addr (&c->c2.buf, lsi, &c->c2.from)) - link_socket_bad_incoming_addr (&c->c2.buf, lsi, &c->c2.from); + msg(D_LINK_RW, "%s READ [%d] from %s: %s", + proto2ascii(lsi->proto, lsi->af, true), + BLEN(&c->c2.buf), + print_link_socket_actual(&c->c2.from, &gc), + PROTO_DUMP(&c->c2.buf, &gc)); + + /* + * 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 or -1, + * telling downstream stages to ignore the packet. + */ + if (c->c2.buf.len > 0) + { + struct crypto_options *co = NULL; + const uint8_t *ad_start = NULL; + if (!link_socket_verify_incoming_addr(&c->c2.buf, lsi, &c->c2.from)) + { + link_socket_bad_incoming_addr(&c->c2.buf, lsi, &c->c2.from); + } #ifdef ENABLE_CRYPTO - if (c->c2.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 (c->c2.tls_multi, &c->c2.from, &c->c2.buf, &co, - floated, &ad_start)) - { - interval_action (&c->c2.tmp_int); - - /* reset packet received timer if TLS packet */ - if (c->options.ping_rec_timeout) - event_timeout_reset (&c->c2.ping_rec_interval); - } - } - else - { - co = &c->c2.crypto_options; - } + if (c->c2.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(c->c2.tls_multi, &c->c2.from, &c->c2.buf, &co, + floated, &ad_start)) + { + interval_action(&c->c2.tmp_int); + + /* reset packet received timer if TLS packet */ + if (c->options.ping_rec_timeout) + { + event_timeout_reset(&c->c2.ping_rec_interval); + } + } + } + else + { + co = &c->c2.crypto_options; + } #if P2MP_SERVER - /* - * Drop non-TLS packet if client-connect script/plugin has not - * yet succeeded. - */ - if (c->c2.context_auth != CAS_SUCCEEDED) - c->c2.buf.len = 0; + /* + * Drop non-TLS packet if client-connect script/plugin has not + * yet succeeded. + */ + if (c->c2.context_auth != CAS_SUCCEEDED) + { + c->c2.buf.len = 0; + } #endif - /* authenticate and decrypt the incoming packet */ - decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, - co, &c->c2.frame, ad_start); + /* authenticate and decrypt the incoming packet */ + decrypt_status = openvpn_decrypt(&c->c2.buf, c->c2.buffers->decrypt_buf, + co, &c->c2.frame, ad_start); - if (!decrypt_status && link_socket_connection_oriented (c->c2.link_socket)) - { - /* decryption errors are fatal in TCP mode */ - register_signal (c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ - msg (D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting"); - } + if (!decrypt_status && link_socket_connection_oriented(c->c2.link_socket)) + { + /* decryption errors are fatal in TCP mode */ + register_signal(c, SIGUSR1, "decryption-error"); /* SOFT-SIGUSR1 -- decryption error in TCP mode */ + msg(D_STREAM_ERRORS, "Fatal decryption error (process_incoming_link), restarting"); + } #else /* ENABLE_CRYPTO */ - decrypt_status = true; + decrypt_status = true; #endif /* ENABLE_CRYPTO */ } - else + else { - buf_reset (&c->c2.to_tun); + buf_reset(&c->c2.to_tun); } - gc_free (&gc); + gc_free(&gc); - return decrypt_status; + return decrypt_status; } void -process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf) +process_incoming_link_part2(struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf) { - if (c->c2.buf.len > 0) + if (c->c2.buf.len > 0) { #ifdef ENABLE_FRAGMENT - if (c->c2.fragment) - fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); + if (c->c2.fragment) + { + fragment_incoming(c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment); + } #endif #ifdef USE_COMP - /* decompress the incoming packet */ - if (c->c2.comp_context) - (*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf, c->c2.comp_context, &c->c2.frame); + /* decompress the incoming packet */ + if (c->c2.comp_context) + { + (*c->c2.comp_context->alg.decompress)(&c->c2.buf, c->c2.buffers->decompress_buf, c->c2.comp_context, &c->c2.frame); + } #endif #ifdef PACKET_TRUNCATION_CHECK - /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ - ipv4_packet_size_verify (BPTR (&c->c2.buf), - BLEN (&c->c2.buf), - TUNNEL_TYPE (c->c1.tuntap), - "POST_DECRYPT", - &c->c2.n_trunc_post_decrypt); + /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ + ipv4_packet_size_verify(BPTR(&c->c2.buf), + BLEN(&c->c2.buf), + TUNNEL_TYPE(c->c1.tuntap), + "POST_DECRYPT", + &c->c2.n_trunc_post_decrypt); #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 (c)) - link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL, c->c2.es); - - /* reset packet received timer */ - if (c->options.ping_rec_timeout && c->c2.buf.len > 0) - event_timeout_reset (&c->c2.ping_rec_interval); - - /* increment authenticated receive byte count */ - if (c->c2.buf.len > 0) - { - c->c2.link_read_bytes_auth += c->c2.buf.len; - c->c2.max_recv_size_local = max_int (c->c2.original_recv_size, c->c2.max_recv_size_local); - } - - /* Did we just receive an openvpn ping packet? */ - if (is_ping_msg (&c->c2.buf)) - { - dmsg (D_PING, "RECEIVED PING PACKET"); - c->c2.buf.len = 0; /* drop packet */ - } + /* + * 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(c)) + { + link_socket_set_outgoing_addr(&c->c2.buf, lsi, &c->c2.from, NULL, c->c2.es); + } + + /* reset packet received timer */ + if (c->options.ping_rec_timeout && c->c2.buf.len > 0) + { + event_timeout_reset(&c->c2.ping_rec_interval); + } + + /* increment authenticated receive byte count */ + if (c->c2.buf.len > 0) + { + c->c2.link_read_bytes_auth += c->c2.buf.len; + c->c2.max_recv_size_local = max_int(c->c2.original_recv_size, c->c2.max_recv_size_local); + } + + /* Did we just receive an openvpn ping packet? */ + if (is_ping_msg(&c->c2.buf)) + { + dmsg(D_PING, "RECEIVED PING PACKET"); + c->c2.buf.len = 0; /* drop packet */ + } #ifdef ENABLE_OCC - /* Did we just receive an OCC packet? */ - if (is_occ_msg (&c->c2.buf)) - process_received_occ_msg (c); + /* Did we just receive an OCC packet? */ + if (is_occ_msg(&c->c2.buf)) + { + process_received_occ_msg(c); + } #endif - buffer_turnover (orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf); + buffer_turnover(orig_buf, &c->c2.to_tun, &c->c2.buf, &c->c2.buffers->read_link_buf); - /* to_tun defined + unopened tuntap can cause deadlock */ - if (!tuntap_defined (c->c1.tuntap)) - c->c2.to_tun.len = 0; + /* to_tun defined + unopened tuntap can cause deadlock */ + if (!tuntap_defined(c->c1.tuntap)) + { + c->c2.to_tun.len = 0; + } } - else + else { - buf_reset (&c->c2.to_tun); + buf_reset(&c->c2.to_tun); } } void -process_incoming_link (struct context *c) +process_incoming_link(struct context *c) { - perf_push (PERF_PROC_IN_LINK); + perf_push(PERF_PROC_IN_LINK); - struct link_socket_info *lsi = get_link_socket_info (c); - const uint8_t *orig_buf = c->c2.buf.data; + struct link_socket_info *lsi = get_link_socket_info(c); + const uint8_t *orig_buf = c->c2.buf.data; - process_incoming_link_part1(c, lsi, false); - process_incoming_link_part2(c, lsi, orig_buf); + process_incoming_link_part1(c, lsi, false); + process_incoming_link_part2(c, lsi, orig_buf); - perf_pop (); + perf_pop(); } /* @@ -942,55 +1020,55 @@ process_incoming_link (struct context *c) */ void -read_incoming_tun (struct context *c) +read_incoming_tun(struct context *c) { - /* - * Setup for read() call on TUN/TAP device. - */ - /*ASSERT (!c->c2.to_link.len);*/ + /* + * Setup for read() call on TUN/TAP device. + */ + /*ASSERT (!c->c2.to_link.len);*/ - perf_push (PERF_READ_IN_TUN); + perf_push(PERF_READ_IN_TUN); - c->c2.buf = c->c2.buffers->read_tun_buf; + c->c2.buf = c->c2.buffers->read_tun_buf; #ifdef TUN_PASS_BUFFER - read_tun_buffered (c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame)); + read_tun_buffered(c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN(&c->c2.frame)); #else - ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); - ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); - c->c2.buf.len = read_tun (c->c1.tuntap, BPTR (&c->c2.buf), MAX_RW_SIZE_TUN (&c->c2.frame)); + ASSERT(buf_init(&c->c2.buf, FRAME_HEADROOM(&c->c2.frame))); + ASSERT(buf_safe(&c->c2.buf, MAX_RW_SIZE_TUN(&c->c2.frame))); + c->c2.buf.len = read_tun(c->c1.tuntap, BPTR(&c->c2.buf), MAX_RW_SIZE_TUN(&c->c2.frame)); #endif #ifdef PACKET_TRUNCATION_CHECK - ipv4_packet_size_verify (BPTR (&c->c2.buf), - BLEN (&c->c2.buf), - TUNNEL_TYPE (c->c1.tuntap), - "READ_TUN", - &c->c2.n_trunc_tun_read); + ipv4_packet_size_verify(BPTR(&c->c2.buf), + BLEN(&c->c2.buf), + TUNNEL_TYPE(c->c1.tuntap), + "READ_TUN", + &c->c2.n_trunc_tun_read); #endif - /* Was TUN/TAP interface stopped? */ - if (tuntap_stop (c->c2.buf.len)) + /* Was TUN/TAP interface stopped? */ + if (tuntap_stop(c->c2.buf.len)) { - register_signal (c, SIGTERM, "tun-stop"); - msg (M_INFO, "TUN/TAP interface has been stopped, exiting"); - perf_pop (); - return; + register_signal(c, SIGTERM, "tun-stop"); + msg(M_INFO, "TUN/TAP interface has been stopped, exiting"); + perf_pop(); + return; } - /* Was TUN/TAP I/O operation aborted? */ - if (tuntap_abort(c->c2.buf.len)) - { - register_signal(c, SIGHUP, "tun-abort"); - c->persist.restart_sleep_seconds = 10; - msg(M_INFO, "TUN/TAP I/O operation aborted, restarting"); - perf_pop(); - return; - } + /* Was TUN/TAP I/O operation aborted? */ + if (tuntap_abort(c->c2.buf.len)) + { + register_signal(c, SIGHUP, "tun-abort"); + c->persist.restart_sleep_seconds = 10; + msg(M_INFO, "TUN/TAP I/O operation aborted, restarting"); + perf_pop(); + return; + } - /* Check the status return from read() */ - check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); + /* Check the status return from read() */ + check_status(c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); - perf_pop (); + perf_pop(); } /** @@ -1002,64 +1080,78 @@ read_incoming_tun (struct context *c) * and sent to routing table, which sends it again to tun. */ static void -drop_if_recursive_routing (struct context *c, struct buffer *buf) +drop_if_recursive_routing(struct context *c, struct buffer *buf) { - bool drop = false; - struct openvpn_sockaddr tun_sa; - int ip_hdr_offset = 0; - - if (c->c2.to_link_addr == NULL) /* no remote addr known */ - return; - - tun_sa = c->c2.to_link_addr->dest; + bool drop = false; + struct openvpn_sockaddr tun_sa; + int ip_hdr_offset = 0; - int proto_ver = get_tun_ip_ver (TUNNEL_TYPE (c->c1.tuntap), &c->c2.buf, &ip_hdr_offset); - - if (proto_ver == 4) + if (c->c2.to_link_addr == NULL) /* no remote addr known */ { - const struct openvpn_iphdr *pip; - - /* make sure we got whole IP header */ - if (BLEN (buf) < ((int) sizeof (struct openvpn_iphdr) + ip_hdr_offset)) - return; + return; + } - /* skip ipv4 packets for ipv6 tun */ - if (tun_sa.addr.sa.sa_family != AF_INET) - return; + tun_sa = c->c2.to_link_addr->dest; - pip = (struct openvpn_iphdr *) (BPTR (buf) + ip_hdr_offset); + int proto_ver = get_tun_ip_ver(TUNNEL_TYPE(c->c1.tuntap), &c->c2.buf, &ip_hdr_offset); - /* drop packets with same dest addr as gateway */ - if (tun_sa.addr.in4.sin_addr.s_addr == pip->daddr) - drop = true; + if (proto_ver == 4) + { + const struct openvpn_iphdr *pip; + + /* make sure we got whole IP header */ + if (BLEN(buf) < ((int) sizeof(struct openvpn_iphdr) + ip_hdr_offset)) + { + return; + } + + /* skip ipv4 packets for ipv6 tun */ + if (tun_sa.addr.sa.sa_family != AF_INET) + { + return; + } + + pip = (struct openvpn_iphdr *) (BPTR(buf) + ip_hdr_offset); + + /* drop packets with same dest addr as gateway */ + if (tun_sa.addr.in4.sin_addr.s_addr == pip->daddr) + { + drop = true; + } } - else if (proto_ver == 6) + else if (proto_ver == 6) { - const struct openvpn_ipv6hdr *pip6; - - /* make sure we got whole IPv6 header */ - if (BLEN (buf) < ((int) sizeof (struct openvpn_ipv6hdr) + ip_hdr_offset)) - return; - - /* skip ipv6 packets for ipv4 tun */ - if (tun_sa.addr.sa.sa_family != AF_INET6) - return; - - /* drop packets with same dest addr as gateway */ - pip6 = (struct openvpn_ipv6hdr *) (BPTR (buf) + ip_hdr_offset); - if (IN6_ARE_ADDR_EQUAL(&tun_sa.addr.in6.sin6_addr, &pip6->daddr)) - drop = true; + const struct openvpn_ipv6hdr *pip6; + + /* make sure we got whole IPv6 header */ + if (BLEN(buf) < ((int) sizeof(struct openvpn_ipv6hdr) + ip_hdr_offset)) + { + return; + } + + /* skip ipv6 packets for ipv4 tun */ + if (tun_sa.addr.sa.sa_family != AF_INET6) + { + return; + } + + /* drop packets with same dest addr as gateway */ + pip6 = (struct openvpn_ipv6hdr *) (BPTR(buf) + ip_hdr_offset); + if (IN6_ARE_ADDR_EQUAL(&tun_sa.addr.in6.sin6_addr, &pip6->daddr)) + { + drop = true; + } } - if (drop) + if (drop) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new(); - c->c2.buf.len = 0; + c->c2.buf.len = 0; - msg(D_LOW, "Recursive routing detected, drop tun packet to %s", - print_link_socket_actual(c->c2.to_link_addr, &gc)); - gc_free (&gc); + msg(D_LOW, "Recursive routing detected, drop tun packet to %s", + print_link_socket_actual(c->c2.to_link_addr, &gc)); + gc_free(&gc); } } @@ -1069,114 +1161,136 @@ drop_if_recursive_routing (struct context *c, struct buffer *buf) */ void -process_incoming_tun (struct context *c) +process_incoming_tun(struct context *c) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new(); - perf_push (PERF_PROC_IN_TUN); + perf_push(PERF_PROC_IN_TUN); - if (c->c2.buf.len > 0) - c->c2.tun_read_bytes += c->c2.buf.len; + if (c->c2.buf.len > 0) + { + c->c2.tun_read_bytes += c->c2.buf.len; + } #ifdef LOG_RW - if (c->c2.log_rw && c->c2.buf.len > 0) - fprintf (stderr, "r"); + if (c->c2.log_rw && c->c2.buf.len > 0) + { + fprintf(stderr, "r"); + } #endif - /* Show packet content */ - dmsg (D_TUN_RW, "TUN READ [%d]", BLEN (&c->c2.buf)); + /* Show packet content */ + dmsg(D_TUN_RW, "TUN READ [%d]", BLEN(&c->c2.buf)); - if (c->c2.buf.len > 0) + if (c->c2.buf.len > 0) { - if ((c->options.mode == MODE_POINT_TO_POINT) && (!c->options.allow_recursive_routing)) - drop_if_recursive_routing (c, &c->c2.buf); - /* - * The --passtos and --mssfix options require - * us to examine the IP header (IPv4 or IPv6). - */ - process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf); + if ((c->options.mode == MODE_POINT_TO_POINT) && (!c->options.allow_recursive_routing)) + { + drop_if_recursive_routing(c, &c->c2.buf); + } + /* + * The --passtos and --mssfix options require + * us to examine the IP header (IPv4 or IPv6). + */ + process_ip_header(c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf); #ifdef PACKET_TRUNCATION_CHECK - /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ - ipv4_packet_size_verify (BPTR (&c->c2.buf), - BLEN (&c->c2.buf), - TUNNEL_TYPE (c->c1.tuntap), - "PRE_ENCRYPT", - &c->c2.n_trunc_pre_encrypt); + /* if (c->c2.buf.len > 1) --c->c2.buf.len; */ + ipv4_packet_size_verify(BPTR(&c->c2.buf), + BLEN(&c->c2.buf), + TUNNEL_TYPE(c->c1.tuntap), + "PRE_ENCRYPT", + &c->c2.n_trunc_pre_encrypt); #endif - encrypt_sign (c, true); + encrypt_sign(c, true); } - else + else { - buf_reset (&c->c2.to_link); + buf_reset(&c->c2.to_link); } - perf_pop (); - gc_free (&gc); + perf_pop(); + gc_free(&gc); } void -process_ip_header (struct context *c, unsigned int flags, struct buffer *buf) +process_ip_header(struct context *c, unsigned int flags, struct buffer *buf) { - if (!c->options.ce.mssfix) - flags &= ~PIP_MSSFIX; + if (!c->options.ce.mssfix) + { + flags &= ~PIP_MSSFIX; + } #if PASSTOS_CAPABILITY - if (!c->options.passtos) - flags &= ~PIPV4_PASSTOS; + if (!c->options.passtos) + { + flags &= ~PIPV4_PASSTOS; + } #endif - if (!c->options.client_nat) - flags &= ~PIPV4_CLIENT_NAT; - if (!c->options.route_gateway_via_dhcp) - flags &= ~PIPV4_EXTRACT_DHCP_ROUTER; + if (!c->options.client_nat) + { + flags &= ~PIPV4_CLIENT_NAT; + } + if (!c->options.route_gateway_via_dhcp) + { + flags &= ~PIPV4_EXTRACT_DHCP_ROUTER; + } - if (buf->len > 0) + if (buf->len > 0) { - /* - * The --passtos and --mssfix options require - * us to examine the IPv4 header. - */ + /* + * The --passtos and --mssfix options require + * us to examine the IPv4 header. + */ - if (flags & (PIP_MSSFIX + if (flags & (PIP_MSSFIX #if PASSTOS_CAPABILITY - | PIPV4_PASSTOS + | PIPV4_PASSTOS #endif - | PIPV4_CLIENT_NAT - )) - { - struct buffer ipbuf = *buf; - if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) - { + | PIPV4_CLIENT_NAT + )) + { + struct buffer ipbuf = *buf; + if (is_ipv4(TUNNEL_TYPE(c->c1.tuntap), &ipbuf)) + { #if PASSTOS_CAPABILITY - /* extract TOS from IP header */ - if (flags & PIPV4_PASSTOS) - link_socket_extract_tos (c->c2.link_socket, &ipbuf); + /* extract TOS from IP header */ + if (flags & PIPV4_PASSTOS) + { + link_socket_extract_tos(c->c2.link_socket, &ipbuf); + } #endif - - /* possibly alter the TCP MSS */ - if (flags & PIP_MSSFIX) - mss_fixup_ipv4 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); - - /* possibly do NAT on packet */ - if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat) - { - const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : CN_OUTGOING; - client_nat_transform (c->options.client_nat, &ipbuf, direction); - } - /* possibly extract a DHCP router message */ - if (flags & PIPV4_EXTRACT_DHCP_ROUTER) - { - const in_addr_t dhcp_router = dhcp_extract_router_msg (&ipbuf); - if (dhcp_router) - route_list_add_vpn_gateway (c->c1.route_list, c->c2.es, dhcp_router); - } - } - else if (is_ipv6 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) - { - /* possibly alter the TCP MSS */ - if (flags & PIP_MSSFIX) - mss_fixup_ipv6 (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); - } - } + + /* possibly alter the TCP MSS */ + if (flags & PIP_MSSFIX) + { + mss_fixup_ipv4(&ipbuf, MTU_TO_MSS(TUN_MTU_SIZE_DYNAMIC(&c->c2.frame))); + } + + /* possibly do NAT on packet */ + if ((flags & PIPV4_CLIENT_NAT) && c->options.client_nat) + { + const int direction = (flags & PIPV4_OUTGOING) ? CN_INCOMING : CN_OUTGOING; + client_nat_transform(c->options.client_nat, &ipbuf, direction); + } + /* possibly extract a DHCP router message */ + if (flags & PIPV4_EXTRACT_DHCP_ROUTER) + { + const in_addr_t dhcp_router = dhcp_extract_router_msg(&ipbuf); + if (dhcp_router) + { + route_list_add_vpn_gateway(c->c1.route_list, c->c2.es, dhcp_router); + } + } + } + else if (is_ipv6(TUNNEL_TYPE(c->c1.tuntap), &ipbuf)) + { + /* possibly alter the TCP MSS */ + if (flags & PIP_MSSFIX) + { + mss_fixup_ipv6(&ipbuf, MTU_TO_MSS(TUN_MTU_SIZE_DYNAMIC(&c->c2.frame))); + } + } + } } } @@ -1185,139 +1299,153 @@ process_ip_header (struct context *c, unsigned int flags, struct buffer *buf) */ void -process_outgoing_link (struct context *c) +process_outgoing_link(struct context *c) { - struct gc_arena gc = gc_new (); - int error_code = 0; + struct gc_arena gc = gc_new(); + int error_code = 0; - perf_push (PERF_PROC_OUT_LINK); + perf_push(PERF_PROC_OUT_LINK); - if (c->c2.to_link.len > 0 && c->c2.to_link.len <= EXPANDED_SIZE (&c->c2.frame)) + if (c->c2.to_link.len > 0 && c->c2.to_link.len <= EXPANDED_SIZE(&c->c2.frame)) { - /* - * Setup for call to send/sendto which will send - * packet to remote over the TCP/UDP port. - */ - int size = 0; - ASSERT (link_socket_actual_defined (c->c2.to_link_addr)); + /* + * Setup for call to send/sendto which will send + * packet to remote over the TCP/UDP port. + */ + int size = 0; + ASSERT(link_socket_actual_defined(c->c2.to_link_addr)); #ifdef ENABLE_DEBUG - /* In gremlin-test mode, we may choose to drop this packet */ - if (!c->options.gremlin || ask_gremlin (c->options.gremlin)) + /* In gremlin-test mode, we may choose to drop this packet */ + if (!c->options.gremlin || ask_gremlin(c->options.gremlin)) #endif - { - /* - * Let the traffic shaper know how many bytes - * we wrote. - */ + { + /* + * Let the traffic shaper know how many bytes + * we wrote. + */ #ifdef ENABLE_FEATURE_SHAPER - if (c->options.shaper) - shaper_wrote_bytes (&c->c2.shaper, BLEN (&c->c2.to_link) - + datagram_overhead (c->options.ce.proto)); + if (c->options.shaper) + { + shaper_wrote_bytes(&c->c2.shaper, BLEN(&c->c2.to_link) + + datagram_overhead(c->options.ce.proto)); + } #endif - /* - * Let the pinger know that we sent a packet. - */ - if (c->options.ping_send_timeout) - event_timeout_reset (&c->c2.ping_send_interval); + /* + * Let the pinger know that we sent a packet. + */ + if (c->options.ping_send_timeout) + { + event_timeout_reset(&c->c2.ping_send_interval); + } #if PASSTOS_CAPABILITY - /* Set TOS */ - link_socket_set_tos (c->c2.link_socket); + /* Set TOS */ + link_socket_set_tos(c->c2.link_socket); #endif - /* Log packet send */ + /* Log packet send */ #ifdef LOG_RW - if (c->c2.log_rw) - fprintf (stderr, "W"); + if (c->c2.log_rw) + { + fprintf(stderr, "W"); + } #endif - msg (D_LINK_RW, "%s WRITE [%d] to %s: %s", - proto2ascii (c->c2.link_socket->info.proto, c->c2.link_socket->info.af, true), - BLEN (&c->c2.to_link), - print_link_socket_actual (c->c2.to_link_addr, &gc), - PROTO_DUMP (&c->c2.to_link, &gc)); - - /* Packet send complexified by possible Socks5 usage */ - { - struct link_socket_actual *to_addr = c->c2.to_link_addr; - int size_delta = 0; - - /* If Socks5 over UDP, prepend header */ - socks_preprocess_outgoing_link (c, &to_addr, &size_delta); - - /* Send packet */ - size = link_socket_write (c->c2.link_socket, - &c->c2.to_link, - to_addr); - - /* Undo effect of prepend */ - link_socket_write_post_size_adjust (&size, size_delta, &c->c2.to_link); - } - - if (size > 0) - { - c->c2.max_send_size_local = max_int (size, c->c2.max_send_size_local); - c->c2.link_write_bytes += size; - link_write_bytes_global += size; + msg(D_LINK_RW, "%s WRITE [%d] to %s: %s", + proto2ascii(c->c2.link_socket->info.proto, c->c2.link_socket->info.af, true), + BLEN(&c->c2.to_link), + print_link_socket_actual(c->c2.to_link_addr, &gc), + PROTO_DUMP(&c->c2.to_link, &gc)); + + /* Packet send complexified by possible Socks5 usage */ + { + struct link_socket_actual *to_addr = c->c2.to_link_addr; + int size_delta = 0; + + /* If Socks5 over UDP, prepend header */ + socks_preprocess_outgoing_link(c, &to_addr, &size_delta); + + /* Send packet */ + size = link_socket_write(c->c2.link_socket, + &c->c2.to_link, + to_addr); + + /* Undo effect of prepend */ + link_socket_write_post_size_adjust(&size, size_delta, &c->c2.to_link); + } + + if (size > 0) + { + c->c2.max_send_size_local = max_int(size, c->c2.max_send_size_local); + c->c2.link_write_bytes += size; + link_write_bytes_global += size; #ifdef ENABLE_MEMSTATS - if (mmap_stats) - mmap_stats->link_write_bytes = link_write_bytes_global; + if (mmap_stats) + { + mmap_stats->link_write_bytes = link_write_bytes_global; + } #endif #ifdef ENABLE_MANAGEMENT - if (management) - { - management_bytes_out (management, size); + if (management) + { + management_bytes_out(management, size); #ifdef MANAGEMENT_DEF_AUTH - management_bytes_server (management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); + management_bytes_server(management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context); #endif - } + } #endif - } - } - - /* Check return status */ - error_code = openvpn_errno(); - check_status (size, "write", c->c2.link_socket, NULL); - - if (size > 0) - { - /* Did we write a different size packet than we intended? */ - if (size != BLEN (&c->c2.to_link)) - msg (D_LINK_ERRORS, - "TCP/UDP packet was truncated/expanded on write to %s (tried=%d,actual=%d)", - print_link_socket_actual (c->c2.to_link_addr, &gc), - BLEN (&c->c2.to_link), - size); - } - - /* if not a ping/control message, indicate activity regarding --inactive parameter */ - if (c->c2.buf.len > 0 ) - register_activity (c, size); + } + } + + /* Check return status */ + error_code = openvpn_errno(); + check_status(size, "write", c->c2.link_socket, NULL); + + if (size > 0) + { + /* Did we write a different size packet than we intended? */ + if (size != BLEN(&c->c2.to_link)) + { + msg(D_LINK_ERRORS, + "TCP/UDP packet was truncated/expanded on write to %s (tried=%d,actual=%d)", + print_link_socket_actual(c->c2.to_link_addr, &gc), + BLEN(&c->c2.to_link), + size); + } + } + + /* if not a ping/control message, indicate activity regarding --inactive parameter */ + if (c->c2.buf.len > 0) + { + register_activity(c, size); + } #ifdef ENABLE_CRYPTO - /* for unreachable network and "connecting" state switch to the next host */ - if (size < 0 && ENETUNREACH == error_code && c->c2.tls_multi && - !tls_initial_packet_received (c->c2.tls_multi) && c->options.mode == MODE_POINT_TO_POINT) - { - msg (M_INFO, "Network unreachable, restarting"); - register_signal (c, SIGUSR1, "network-unreachable"); - } + /* for unreachable network and "connecting" state switch to the next host */ + if (size < 0 && ENETUNREACH == error_code && c->c2.tls_multi + && !tls_initial_packet_received(c->c2.tls_multi) && c->options.mode == MODE_POINT_TO_POINT) + { + msg(M_INFO, "Network unreachable, restarting"); + register_signal(c, SIGUSR1, "network-unreachable"); + } #endif } - else + else { - if (c->c2.to_link.len > 0) - msg (D_LINK_ERRORS, "TCP/UDP packet too large on write to %s (tried=%d,max=%d)", - print_link_socket_actual (c->c2.to_link_addr, &gc), - c->c2.to_link.len, - EXPANDED_SIZE (&c->c2.frame)); + if (c->c2.to_link.len > 0) + { + msg(D_LINK_ERRORS, "TCP/UDP packet too large on write to %s (tried=%d,max=%d)", + print_link_socket_actual(c->c2.to_link_addr, &gc), + c->c2.to_link.len, + EXPANDED_SIZE(&c->c2.frame)); + } } - buf_reset (&c->c2.to_link); + buf_reset(&c->c2.to_link); - perf_pop (); - gc_free (&gc); + perf_pop(); + gc_free(&gc); } /* @@ -1325,138 +1453,152 @@ process_outgoing_link (struct context *c) */ void -process_outgoing_tun (struct context *c) +process_outgoing_tun(struct context *c) { - struct gc_arena gc = gc_new (); + struct gc_arena gc = gc_new(); - /* - * Set up for write() call to TUN/TAP - * device. - */ - if (c->c2.to_tun.len <= 0) - return; + /* + * Set up for write() call to TUN/TAP + * device. + */ + if (c->c2.to_tun.len <= 0) + { + return; + } - perf_push (PERF_PROC_OUT_TUN); + perf_push(PERF_PROC_OUT_TUN); - /* - * The --mssfix option requires - * us to examine the IP header (IPv4 or IPv6). - */ - process_ip_header (c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); + /* + * The --mssfix option requires + * us to examine the IP header (IPv4 or IPv6). + */ + process_ip_header(c, PIP_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); - if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame)) + if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN(&c->c2.frame)) { - /* - * Write to TUN/TAP device. - */ - int size; + /* + * Write to TUN/TAP device. + */ + int size; #ifdef LOG_RW - if (c->c2.log_rw) - fprintf (stderr, "w"); + if (c->c2.log_rw) + { + fprintf(stderr, "w"); + } #endif - dmsg (D_TUN_RW, "TUN WRITE [%d]", BLEN (&c->c2.to_tun)); + dmsg(D_TUN_RW, "TUN WRITE [%d]", BLEN(&c->c2.to_tun)); #ifdef PACKET_TRUNCATION_CHECK - ipv4_packet_size_verify (BPTR (&c->c2.to_tun), - BLEN (&c->c2.to_tun), - TUNNEL_TYPE (c->c1.tuntap), - "WRITE_TUN", - &c->c2.n_trunc_tun_write); + ipv4_packet_size_verify(BPTR(&c->c2.to_tun), + BLEN(&c->c2.to_tun), + TUNNEL_TYPE(c->c1.tuntap), + "WRITE_TUN", + &c->c2.n_trunc_tun_write); #endif #ifdef TUN_PASS_BUFFER - size = write_tun_buffered (c->c1.tuntap, &c->c2.to_tun); + size = write_tun_buffered(c->c1.tuntap, &c->c2.to_tun); #else - size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun)); + size = write_tun(c->c1.tuntap, BPTR(&c->c2.to_tun), BLEN(&c->c2.to_tun)); #endif - if (size > 0) - c->c2.tun_write_bytes += size; - check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap); - - /* check written packet size */ - if (size > 0) - { - /* Did we write a different size packet than we intended? */ - if (size != BLEN (&c->c2.to_tun)) - msg (D_LINK_ERRORS, - "TUN/TAP packet was destructively fragmented on write to %s (tried=%d,actual=%d)", - c->c1.tuntap->actual_name, - BLEN (&c->c2.to_tun), - size); - - /* indicate activity regarding --inactive parameter */ - register_activity (c, size); - } + if (size > 0) + { + c->c2.tun_write_bytes += size; + } + check_status(size, "write to TUN/TAP", NULL, c->c1.tuntap); + + /* check written packet size */ + if (size > 0) + { + /* Did we write a different size packet than we intended? */ + if (size != BLEN(&c->c2.to_tun)) + { + msg(D_LINK_ERRORS, + "TUN/TAP packet was destructively fragmented on write to %s (tried=%d,actual=%d)", + c->c1.tuntap->actual_name, + BLEN(&c->c2.to_tun), + size); + } + + /* indicate activity regarding --inactive parameter */ + register_activity(c, size); + } } - else + 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)", - c->c2.to_tun.len, - MAX_RW_SIZE_TUN (&c->c2.frame)); + /* + * 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)", + c->c2.to_tun.len, + MAX_RW_SIZE_TUN(&c->c2.frame)); } - buf_reset (&c->c2.to_tun); + buf_reset(&c->c2.to_tun); - perf_pop (); - gc_free (&gc); + perf_pop(); + gc_free(&gc); } void -pre_select (struct context *c) +pre_select(struct context *c) { - /* make sure current time (now) is updated on function entry */ + /* make sure current time (now) is updated on function entry */ - /* - * Start with an effectively infinite timeout, then let it - * reduce to a timeout that reflects the component which - * needs the earliest service. - */ - c->c2.timeval.tv_sec = BIG_TIMEOUT; - c->c2.timeval.tv_usec = 0; + /* + * Start with an effectively infinite timeout, then let it + * reduce to a timeout that reflects the component which + * needs the earliest service. + */ + c->c2.timeval.tv_sec = BIG_TIMEOUT; + c->c2.timeval.tv_usec = 0; #if defined(_WIN32) - if (check_debug_level (D_TAP_WIN_DEBUG)) + if (check_debug_level(D_TAP_WIN_DEBUG)) { - c->c2.timeval.tv_sec = 1; - if (tuntap_defined (c->c1.tuntap)) - tun_show_debug (c->c1.tuntap); + c->c2.timeval.tv_sec = 1; + if (tuntap_defined(c->c1.tuntap)) + { + tun_show_debug(c->c1.tuntap); + } } #endif - /* check coarse timers? */ - check_coarse_timers (c); - if (c->sig->signal_received) - return; + /* check coarse timers? */ + check_coarse_timers(c); + if (c->sig->signal_received) + { + return; + } - /* Does TLS need service? */ - check_tls (c); + /* Does TLS need service? */ + check_tls(c); - /* In certain cases, TLS errors will require a restart */ - check_tls_errors (c); - if (c->sig->signal_received) - return; + /* In certain cases, TLS errors will require a restart */ + check_tls_errors(c); + if (c->sig->signal_received) + { + return; + } - /* check for incoming configuration info on the control channel */ - check_incoming_control_channel (c); + /* check for incoming configuration info on the control channel */ + check_incoming_control_channel(c); #ifdef ENABLE_OCC - /* Should we send an OCC message? */ - check_send_occ_msg (c); + /* Should we send an OCC message? */ + check_send_occ_msg(c); #endif #ifdef ENABLE_FRAGMENT - /* Should we deliver a datagram fragment to remote? */ - check_fragment (c); + /* Should we deliver a datagram fragment to remote? */ + check_fragment(c); #endif - /* Update random component of timeout */ - check_timeout_random_component (c); + /* Update random component of timeout */ + check_timeout_random_component(c); } /* @@ -1466,217 +1608,242 @@ pre_select (struct context *c) */ void -io_wait_dowork (struct context *c, const unsigned int flags) +io_wait_dowork(struct context *c, const unsigned int flags) { - unsigned int socket = 0; - unsigned int tuntap = 0; - struct event_set_return esr[4]; - - /* These shifts all depend on EVENT_READ and EVENT_WRITE */ - static int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ - static int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ - static int err_shift = 4; /* depends on ES_ERROR */ + unsigned int socket = 0; + unsigned int tuntap = 0; + struct event_set_return esr[4]; + + /* These shifts all depend on EVENT_READ and EVENT_WRITE */ + static int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ + static int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ + static int err_shift = 4; /* depends on ES_ERROR */ #ifdef ENABLE_MANAGEMENT - static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ + static int management_shift = 6; /* depends on MANAGEMENT_READ and MANAGEMENT_WRITE */ #endif #ifdef ENABLE_ASYNC_PUSH - static int file_shift = 8; /* listening inotify events */ + static int file_shift = 8; /* listening inotify events */ #endif - /* - * Decide what kind of events we want to wait for. - */ - event_reset (c->c2.event_set); - - /* - * On win32 we use the keyboard or an event object as a source - * of asynchronous signals. - */ - if (flags & IOW_WAIT_SIGNAL) - wait_signal (c->c2.event_set, (void*)&err_shift); - - /* - * If outgoing data (for TCP/UDP port) pending, wait for ready-to-send - * status from TCP/UDP port. Otherwise, wait for incoming data on - * TUN/TAP device. - */ - if (flags & IOW_TO_LINK) - { - if (flags & IOW_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. - */ + /* + * Decide what kind of events we want to wait for. + */ + event_reset(c->c2.event_set); + + /* + * On win32 we use the keyboard or an event object as a source + * of asynchronous signals. + */ + if (flags & IOW_WAIT_SIGNAL) + { + wait_signal(c->c2.event_set, (void *)&err_shift); + } + + /* + * If outgoing data (for TCP/UDP port) pending, wait for ready-to-send + * status from TCP/UDP port. Otherwise, wait for incoming data on + * TUN/TAP device. + */ + if (flags & IOW_TO_LINK) + { + if (flags & IOW_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. + */ #ifdef ENABLE_FEATURE_SHAPER - int delay = 0; - - /* set traffic shaping delay in microseconds */ - if (c->options.shaper) - delay = max_int (delay, shaper_delay (&c->c2.shaper)); - - if (delay < 1000) - { - socket |= EVENT_WRITE; - } - else - { - shaper_soonest_event (&c->c2.timeval, delay); - } + int delay = 0; + + /* set traffic shaping delay in microseconds */ + if (c->options.shaper) + { + delay = max_int(delay, shaper_delay(&c->c2.shaper)); + } + + if (delay < 1000) + { + socket |= EVENT_WRITE; + } + else + { + shaper_soonest_event(&c->c2.timeval, delay); + } #else /* ENABLE_FEATURE_SHAPER */ - socket |= EVENT_WRITE; + socket |= EVENT_WRITE; #endif /* ENABLE_FEATURE_SHAPER */ - } - else - { - socket |= EVENT_WRITE; - } + } + else + { + socket |= EVENT_WRITE; + } } - else if (!((flags & IOW_FRAG) && TO_LINK_FRAG (c))) + else if (!((flags & IOW_FRAG) && TO_LINK_FRAG(c))) { - if (flags & IOW_READ_TUN) - tuntap |= EVENT_READ; + if (flags & IOW_READ_TUN) + { + tuntap |= EVENT_READ; + } } - /* - * If outgoing data (for TUN/TAP device) pending, wait for ready-to-send status - * from device. Otherwise, wait for incoming data on TCP/UDP port. - */ - if (flags & IOW_TO_TUN) + /* + * If outgoing data (for TUN/TAP device) pending, wait for ready-to-send status + * from device. Otherwise, wait for incoming data on TCP/UDP port. + */ + if (flags & IOW_TO_TUN) { - tuntap |= EVENT_WRITE; + tuntap |= EVENT_WRITE; } - else + else { - if (flags & IOW_READ_LINK) - socket |= EVENT_READ; + if (flags & IOW_READ_LINK) + { + socket |= EVENT_READ; + } } - /* - * outgoing bcast buffer waiting to be sent? - */ - if (flags & IOW_MBUF) - socket |= EVENT_WRITE; + /* + * outgoing bcast buffer waiting to be sent? + */ + if (flags & IOW_MBUF) + { + socket |= EVENT_WRITE; + } - /* - * Force wait on TUN input, even if also waiting on TCP/UDP output - */ - if (flags & IOW_READ_TUN_FORCE) - tuntap |= EVENT_READ; + /* + * Force wait on TUN input, even if also waiting on TCP/UDP output + */ + if (flags & IOW_READ_TUN_FORCE) + { + tuntap |= EVENT_READ; + } - /* - * Configure event wait based on socket, tuntap flags. - */ - socket_set (c->c2.link_socket, c->c2.event_set, socket, (void*)&socket_shift, NULL); - tun_set (c->c1.tuntap, c->c2.event_set, tuntap, (void*)&tun_shift, NULL); + /* + * Configure event wait based on socket, tuntap flags. + */ + socket_set(c->c2.link_socket, c->c2.event_set, socket, (void *)&socket_shift, NULL); + tun_set(c->c1.tuntap, c->c2.event_set, tuntap, (void *)&tun_shift, NULL); #ifdef ENABLE_MANAGEMENT - if (management) - management_socket_set (management, c->c2.event_set, (void*)&management_shift, NULL); + if (management) + { + management_socket_set(management, c->c2.event_set, (void *)&management_shift, NULL); + } #endif #ifdef ENABLE_ASYNC_PUSH - /* arm inotify watcher */ - event_ctl (c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void*)&file_shift); + /* arm inotify watcher */ + if (c->options.mode == MODE_SERVER) + { + event_ctl(c->c2.event_set, c->c2.inotify_fd, EVENT_READ, (void *)&file_shift); + } #endif - /* - * Possible scenarios: - * (1) tcp/udp port has data available to read - * (2) tcp/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) we received a signal (handler sets signal_received) - * (6) timeout (tv) expired - */ + /* + * Possible scenarios: + * (1) tcp/udp port has data available to read + * (2) tcp/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) we received a signal (handler sets signal_received) + * (6) timeout (tv) expired + */ - c->c2.event_set_status = ES_ERROR; + c->c2.event_set_status = ES_ERROR; - if (!c->sig->signal_received) + if (!c->sig->signal_received) { - if (!(flags & IOW_CHECK_RESIDUAL) || !socket_read_residual (c->c2.link_socket)) - { - int status; + if (!(flags & IOW_CHECK_RESIDUAL) || !socket_read_residual(c->c2.link_socket)) + { + int status; #ifdef ENABLE_DEBUG - if (check_debug_level (D_EVENT_WAIT)) - show_wait_status (c); + if (check_debug_level(D_EVENT_WAIT)) + { + show_wait_status(c); + } #endif - /* - * Wait for something to happen. - */ - status = event_wait (c->c2.event_set, &c->c2.timeval, esr, SIZE(esr)); - - check_status (status, "event_wait", NULL, NULL); - - if (status > 0) - { - int i; - c->c2.event_set_status = 0; - for (i = 0; i < status; ++i) - { - const struct event_set_return *e = &esr[i]; - c->c2.event_set_status |= ((e->rwflags & 3) << *((int*)e->arg)); - } - } - else if (status == 0) - { - c->c2.event_set_status = ES_TIMEOUT; - } - } - else - { - c->c2.event_set_status = SOCKET_READ; - } - } - - /* 'now' should always be a reasonably up-to-date timestamp */ - update_time (); - - /* set signal_received if a signal was received */ - if (c->c2.event_set_status & ES_ERROR) - get_signal (&c->sig->signal_received); - - dmsg (D_EVENT_WAIT, "I/O WAIT status=0x%04x", c->c2.event_set_status); + /* + * Wait for something to happen. + */ + status = event_wait(c->c2.event_set, &c->c2.timeval, esr, SIZE(esr)); + + check_status(status, "event_wait", NULL, NULL); + + if (status > 0) + { + int i; + c->c2.event_set_status = 0; + for (i = 0; i < status; ++i) + { + const struct event_set_return *e = &esr[i]; + c->c2.event_set_status |= ((e->rwflags & 3) << *((int *)e->arg)); + } + } + else if (status == 0) + { + c->c2.event_set_status = ES_TIMEOUT; + } + } + else + { + c->c2.event_set_status = SOCKET_READ; + } + } + + /* 'now' should always be a reasonably up-to-date timestamp */ + update_time(); + + /* set signal_received if a signal was received */ + if (c->c2.event_set_status & ES_ERROR) + { + get_signal(&c->sig->signal_received); + } + + dmsg(D_EVENT_WAIT, "I/O WAIT status=0x%04x", c->c2.event_set_status); } void -process_io (struct context *c) +process_io(struct context *c) { - const unsigned int status = c->c2.event_set_status; + const unsigned int status = c->c2.event_set_status; #ifdef ENABLE_MANAGEMENT - if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE)) + if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE)) { - ASSERT (management); - management_io (management); + ASSERT(management); + management_io(management); } #endif - /* TCP/UDP port ready to accept write */ - if (status & SOCKET_WRITE) + /* TCP/UDP port ready to accept write */ + if (status & SOCKET_WRITE) { - process_outgoing_link (c); + process_outgoing_link(c); } - /* TUN device ready to accept write */ - else if (status & TUN_WRITE) + /* TUN device ready to accept write */ + else if (status & TUN_WRITE) { - process_outgoing_tun (c); + process_outgoing_tun(c); } - /* Incoming data on TCP/UDP port */ - else if (status & SOCKET_READ) + /* Incoming data on TCP/UDP port */ + else if (status & SOCKET_READ) { - read_incoming_link (c); - if (!IS_SIG (c)) - process_incoming_link (c); + read_incoming_link(c); + if (!IS_SIG(c)) + { + process_incoming_link(c); + } } - /* Incoming data on TUN device */ - else if (status & TUN_READ) + /* Incoming data on TUN device */ + else if (status & TUN_READ) { - read_incoming_tun (c); - if (!IS_SIG (c)) - process_incoming_tun (c); + read_incoming_tun(c); + if (!IS_SIG(c)) + { + process_incoming_tun(c); + } } } -- cgit v1.2.3