static void check_add_routes_action (struct context *c, const bool errors) { do_route (&c->options, c->c1.route_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 */ }
/* * Things that need to happen immediately after connection initiation should go here. */ void check_connection_established_dowork (struct context *c) { if (event_timeout_trigger (&c->c2.wait_for_connect, &c->c2.timeval, ETT_DEFAULT)) { if (CONNECTION_ESTABLISHED (c)) { #if P2MP /* 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, 0, 0); } #endif /* send push request in 1 sec */ event_timeout_init (&c->c2.push_request_interval, 1, now); reset_coarse_timers (c); } else #endif { do_up (c, false, 0); } event_timeout_clear (&c->c2.wait_for_connect); } } }
void incoming_push_message (struct context *c, const struct buffer *buffer) { struct gc_arena gc = gc_new (); unsigned int option_types_found = 0; int status; msg (D_PUSH, "PUSH: Received control message: '%s'", sanitize_control_message(BSTR(buffer), &gc)); status = process_incoming_push_msg (c, buffer, c->options.pull, pull_permission_mask (c), &option_types_found); if (status == PUSH_MSG_ERROR) msg (D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc)); else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION) { c->options.push_option_types_found |= option_types_found; if (status == PUSH_MSG_REPLY) do_up (c, true, c->options.push_option_types_found ); /* delay bringing tun/tap up until --push parms received from remote */ event_timeout_clear (&c->c2.push_request_interval); } gc_free (&gc); }
void check_send_occ_load_test_dowork (struct context *c) { if (CONNECTION_ESTABLISHED (c)) { const struct mtu_load_test *entry; if (!c->c2.occ_mtu_load_n_tries) msg (M_INFO, "NOTE: Beginning empirical MTU test -- results should be available in 3 to 4 minutes."); entry = &mtu_load_test_sequence[c->c2.occ_mtu_load_n_tries++]; if (entry->op >= 0) { c->c2.occ_op = entry->op; c->c2.occ_mtu_load_size = EXPANDED_SIZE (&c->c2.frame) + entry->delta; } else { msg (M_INFO, "NOTE: failed to empirically measure MTU (requires " PACKAGE_NAME " 1.5 or higher at other end of connection)."); event_timeout_clear (&c->c2.occ_mtu_load_test_interval); c->c2.occ_mtu_load_n_tries = 0; } } }
void check_send_occ_req_dowork (struct context *c) { if (++c->c2.occ_n_tries >= OCC_N_TRIES) { if (c->options.remote_list) /* * No OCC_REPLY from peer after repeated attempts. * Give up. */ msg (D_SHOW_OCC, "NOTE: failed to obtain options consistency info from peer -- " "this could occur if the remote peer is running a version of " PACKAGE_NAME " before 1.5-beta8 or if there is a network connectivity problem, and will not necessarily prevent " PACKAGE_NAME " from running (" counter_format " bytes received from peer, " counter_format " bytes authenticated data channel traffic) -- you can disable the options consistency " "check with --disable-occ.", c->c2.link_read_bytes, c->c2.link_read_bytes_auth); event_timeout_clear (&c->c2.occ_interval); } else { c->c2.occ_op = OCC_REQUEST; /* * If we don't hear back from peer, send another * OCC_REQUEST in OCC_INTERVAL_SECONDS. */ event_timeout_reset (&c->c2.occ_interval); } }
void incoming_push_message(struct context *c, const struct buffer *buffer) { struct gc_arena gc = gc_new(); unsigned int option_types_found = 0; int status; msg(D_PUSH, "PUSH: Received control message: '%s'", sanitize_control_message(BSTR(buffer), &gc)); status = process_incoming_push_msg(c, buffer, c->options.pull, pull_permission_mask(c), &option_types_found); if (status == PUSH_MSG_ERROR) { msg(D_PUSH_ERRORS, "WARNING: Received bad push/pull message: %s", sanitize_control_message(BSTR(buffer), &gc)); } else if (status == PUSH_MSG_REPLY || status == PUSH_MSG_CONTINUATION) { c->options.push_option_types_found |= option_types_found; /* delay bringing tun/tap up until --push parms received from remote */ if (status == PUSH_MSG_REPLY) { if (!do_up(c, true, c->options.push_option_types_found)) { msg(D_PUSH_ERRORS, "Failed to open tun/tap interface"); goto error; } } event_timeout_clear(&c->c2.push_request_interval); } else if (status == PUSH_MSG_REQUEST) { if (c->options.mode == MODE_SERVER) { struct tls_session *session = &c->c2.tls_multi->session[TM_ACTIVE]; /* Do not regenerate keys if client send a second push request */ if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized && !tls_session_update_crypto_params(session, &c->options, &c->c2.frame)) { msg(D_TLS_ERRORS, "TLS Error: initializing data channel failed"); goto error; } } } goto cleanup; error: register_signal(c, SIGUSR1, "process-push-msg-failed"); cleanup: gc_free(&gc); }
void process_explicit_exit_notification_timer_wakeup(struct context *c) { if (event_timeout_trigger(&c->c2.explicit_exit_notification_interval, &c->c2.timeval, ETT_DEFAULT)) { ASSERT(c->c2.explicit_exit_notification_time_wait && c->options.ce.explicit_exit_notification); if (now >= c->c2.explicit_exit_notification_time_wait + c->options.ce.explicit_exit_notification) { event_timeout_clear(&c->c2.explicit_exit_notification_interval); c->sig->signal_received = SIGTERM; c->sig->signal_text = "exit-with-notification"; } else { c->c2.occ_op = OCC_EXIT; } } }
void process_received_occ_msg (struct context *c) { ASSERT (buf_advance (&c->c2.buf, OCC_STRING_SIZE)); switch (buf_read_u8 (&c->c2.buf)) { case OCC_REQUEST: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REQUEST"); c->c2.occ_op = OCC_REPLY; break; case OCC_MTU_REQUEST: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REQUEST"); c->c2.occ_op = OCC_MTU_REPLY; break; case OCC_MTU_LOAD_REQUEST: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_LOAD_REQUEST"); c->c2.occ_mtu_load_size = buf_read_u16 (&c->c2.buf); if (c->c2.occ_mtu_load_size >= 0) c->c2.occ_op = OCC_MTU_LOAD; break; case OCC_REPLY: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REPLY"); if (c->options.occ && !TLS_MODE (c) && c->c2.options_string_remote) { if (!options_cmp_equal_safe ((char *) BPTR (&c->c2.buf), c->c2.options_string_remote, c->c2.buf.len)) { options_warning_safe ((char *) BPTR (&c->c2.buf), c->c2.options_string_remote, c->c2.buf.len); } } event_timeout_clear (&c->c2.occ_interval); break; case OCC_MTU_REPLY: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REPLY"); c->c2.max_recv_size_remote = buf_read_u16 (&c->c2.buf); c->c2.max_send_size_remote = buf_read_u16 (&c->c2.buf); if (c->options.mtu_test && c->c2.max_recv_size_remote > 0 && c->c2.max_send_size_remote > 0) { msg (M_INFO, "NOTE: Empirical MTU test completed [Tried,Actual] local->remote=[%d,%d] remote->local=[%d,%d]", c->c2.max_send_size_local, c->c2.max_recv_size_remote, c->c2.max_send_size_remote, c->c2.max_recv_size_local); if (!c->options.fragment && c->options.proto == PROTO_UDPv4 && c->c2.max_send_size_local > TUN_MTU_MIN && (c->c2.max_recv_size_remote < c->c2.max_send_size_local || c->c2.max_recv_size_local < c->c2.max_send_size_remote)) msg (M_INFO, "NOTE: This connection is unable to accomodate a UDP packet size of %d. Consider using --fragment or --mssfix options as a workaround.", c->c2.max_send_size_local); } event_timeout_clear (&c->c2.occ_mtu_load_test_interval); break; case OCC_EXIT: dmsg (D_PACKET_CONTENT, "RECEIVED OCC_EXIT"); c->sig->signal_received = SIGTERM; c->sig->signal_text = "remote-exit"; break; } c->c2.buf.len = 0; /* don't pass packet on */ }
struct status_output * status_open(const char *filename, const int refresh_freq, const int msglevel, const struct virtual_output *vout, const unsigned int flags) { struct status_output *so = NULL; if (filename || msglevel >= 0 || vout) { ALLOC_OBJ_CLEAR(so, struct status_output); so->flags = flags; so->msglevel = msglevel; so->vout = vout; so->fd = -1; buf_reset(&so->read_buf); event_timeout_clear(&so->et); if (filename) { switch (so->flags) { case STATUS_OUTPUT_WRITE: so->fd = platform_open(filename, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); break; case STATUS_OUTPUT_READ: so->fd = platform_open(filename, O_RDONLY, S_IRUSR | S_IWUSR); break; case STATUS_OUTPUT_READ|STATUS_OUTPUT_WRITE: so->fd = platform_open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); break; default: ASSERT(0); } if (so->fd >= 0) { so->filename = string_alloc(filename, NULL); set_cloexec(so->fd); /* allocate read buffer */ if (so->flags & STATUS_OUTPUT_READ) { so->read_buf = alloc_buf(512); } } else { msg(M_WARN, "Note: cannot open %s for %s", filename, print_status_mode(so->flags)); so->errors = true; } } else { so->flags = STATUS_OUTPUT_WRITE; } if ((so->flags & STATUS_OUTPUT_WRITE) && refresh_freq > 0) { event_timeout_init(&so->et, refresh_freq, 0); } } return so; }