📄 socket.c
字号:
new_sd = -1; } return new_sd;}static voidtcp_connection_established (const struct sockaddr_in *remote){ struct gc_arena gc = gc_new (); msg (M_INFO, "TCP connection established with %s", print_sockaddr (remote, &gc)); gc_free (&gc);}static intsocket_listen_accept (socket_descriptor_t sd, struct sockaddr_in *remote, const char *remote_dynamic, bool *remote_changed, const struct sockaddr_in *local, bool do_listen, bool nowait, volatile int *signal_received){ struct gc_arena gc = gc_new (); struct sockaddr_in remote_verify = *remote; int new_sd = -1; socket_do_listen (sd, local, do_listen, true); while (true) { int status; fd_set reads; struct timeval tv; FD_ZERO (&reads); FD_SET (sd, &reads); tv.tv_sec = 5; tv.tv_usec = 0; status = select (sd + 1, &reads, NULL, NULL, &tv); get_signal (signal_received); if (*signal_received) { gc_free (&gc); return sd; } if (status < 0) msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: select() failed"); if (status <= 0) continue; new_sd = socket_do_accept (sd, remote, nowait); if (new_sd >= 0) { update_remote (remote_dynamic, &remote_verify, remote_changed); if (addr_defined (&remote_verify) && !addr_match (&remote_verify, remote)) { msg (M_WARN, "TCP NOTE: Rejected connection attempt from %s due to --remote setting", print_sockaddr (remote, &gc)); if (openvpn_close_socket (new_sd)) msg (M_SOCKERR, "TCP: close socket failed (new_sd)"); } else break; } sleep (1); } if (!nowait && openvpn_close_socket (sd)) msg (M_SOCKERR, "TCP: close socket failed (sd)"); tcp_connection_established (remote); gc_free (&gc); return new_sd;}static voidsocket_connect (socket_descriptor_t *sd, struct sockaddr_in *remote, struct remote_list *remote_list, const char *remote_dynamic, bool *remote_changed, const int connect_retry_seconds, volatile int *signal_received){ struct gc_arena gc = gc_new (); msg (M_INFO, "Attempting to establish TCP connection with %s", print_sockaddr (remote, &gc)); while (true) { const int status = connect (*sd, (struct sockaddr *) remote, sizeof (*remote)); get_signal (signal_received); if (*signal_received) goto done; if (!status) break; msg (D_LINK_ERRORS | M_ERRNO_SOCK, "TCP: connect to %s failed, will try again in %d seconds", print_sockaddr (remote, &gc), connect_retry_seconds); openvpn_close_socket (*sd); sleep (connect_retry_seconds); if (remote_list) { remote_list_next (remote_list); remote_dynamic = remote_list_host (remote_list); remote->sin_port = htons (remote_list_port (remote_list)); *remote_changed = true; } *sd = create_socket_tcp (); update_remote (remote_dynamic, remote, remote_changed); } msg (M_INFO, "TCP connection established with %s", print_sockaddr (remote, &gc)); done: gc_free (&gc);}/* For stream protocols, allocate a buffer to build up packet. Called after frame has been finalized. */static voidsocket_frame_init (const struct frame *frame, struct link_socket *sock){#ifdef WIN32 overlapped_io_init (&sock->reads, frame, FALSE, false); overlapped_io_init (&sock->writes, frame, TRUE, false); sock->rw_handle.read = sock->reads.overlapped.hEvent; sock->rw_handle.write = sock->writes.overlapped.hEvent;#endif if (link_socket_connection_oriented (sock)) {#ifdef WIN32 stream_buf_init (&sock->stream_buf, &sock->reads.buf_init);#else alloc_buf_sock_tun (&sock->stream_buf_data, frame, false); stream_buf_init (&sock->stream_buf, &sock->stream_buf_data);#endif }}/* * Adjust frame structure based on a Path MTU value given * to us by the OS. */voidframe_adjust_path_mtu (struct frame *frame, int pmtu, int proto){ frame_set_mtu_dynamic (frame, pmtu - datagram_overhead (proto), SET_MTU_UPPER_BOUND);}static voidresolve_bind_local (struct link_socket *sock){ struct gc_arena gc = gc_new (); /* resolve local address if undefined */ if (!addr_defined (&sock->info.lsa->local)) { sock->info.lsa->local.sin_family = AF_INET; sock->info.lsa->local.sin_addr.s_addr = (sock->local_host ? getaddr ( GETADDR_RESOLVE | GETADDR_FATAL | GETADDR_FATAL_ON_SIGNAL, sock->local_host, 0, NULL, NULL) : htonl (INADDR_ANY)); sock->info.lsa->local.sin_port = htons (sock->local_port); } /* bind to local address/port */ if (sock->bind_local) { if (bind (sock->sd, (struct sockaddr *) &sock->info.lsa->local, sizeof (sock->info.lsa->local))) { const int errnum = openvpn_errno_socket (); msg (M_FATAL, "TCP/UDP: Socket bind failed on local address %s: %s", print_sockaddr (&sock->info.lsa->local, &gc), strerror_ts (errnum, &gc)); } } gc_free (&gc);}static voidresolve_remote (struct link_socket *sock, int phase, const char **remote_dynamic, volatile int *signal_received){ struct gc_arena gc = gc_new (); if (!sock->did_resolve_remote) { /* resolve remote address if undefined */ if (!addr_defined (&sock->info.lsa->remote)) { sock->info.lsa->remote.sin_family = AF_INET; sock->info.lsa->remote.sin_addr.s_addr = 0; if (sock->remote_host) { unsigned int flags = 0; int retry = 0; bool status = false; if (phase == 1) { if (sock->resolve_retry_seconds) { flags = GETADDR_RESOLVE; retry = 0; } else { flags = GETADDR_RESOLVE | GETADDR_FATAL | GETADDR_MENTION_RESOLVE_RETRY; retry = 0; } } else if (phase == 2) { if (sock->resolve_retry_seconds) { flags = GETADDR_RESOLVE | GETADDR_FATAL; retry = sock->resolve_retry_seconds; } else { ASSERT (0); } } else { ASSERT (0); } sock->info.lsa->remote.sin_addr.s_addr = getaddr ( flags, sock->remote_host, retry, &status, signal_received); if (!status || (signal_received && *signal_received)) goto done; } sock->info.lsa->remote.sin_port = htons (sock->remote_port); } /* should we re-use previous active remote address? */ if (addr_defined (&sock->info.lsa->actual)) { msg (M_INFO, "TCP/UDP: Preserving recently used remote address: %s", print_sockaddr (&sock->info.lsa->actual, &gc)); if (remote_dynamic) *remote_dynamic = NULL; } else sock->info.lsa->actual = sock->info.lsa->remote; /* remember that we finished */ sock->did_resolve_remote = true; } done: gc_free (&gc);}struct link_socket *link_socket_new (void){ struct link_socket *sock; ALLOC_OBJ_CLEAR (sock, struct link_socket); sock->sd = -1; sock->ctrl_sd = -1; return sock;}/* bind socket if necessary */voidlink_socket_init_phase1 (struct link_socket *sock, const char *local_host, struct remote_list *remote_list, int local_port, int proto, int mode, const struct link_socket *accept_from, struct http_proxy_info *http_proxy, struct socks_proxy_info *socks_proxy, bool bind_local, bool remote_float, int inetd, struct link_socket_addr *lsa, const char *ipchange_command, int resolve_retry_seconds, int connect_retry_seconds, int mtu_discover_type, int rcvbuf, int sndbuf){ const char *remote_host; int remote_port; ASSERT (sock); sock->remote_list = remote_list; remote_list_next (remote_list); remote_host = remote_list_host (remote_list); remote_port = remote_list_port (remote_list); sock->mode = mode; if (mode == LS_MODE_TCP_ACCEPT_FROM) { ASSERT (accept_from); sock->sd = accept_from->sd; } sock->local_host = local_host; sock->local_port = local_port; sock->http_proxy = http_proxy; sock->socks_proxy = socks_proxy; sock->bind_local = bind_local; sock->inetd = inetd; sock->resolve_retry_seconds = resolve_retry_seconds; sock->connect_retry_seconds = connect_retry_seconds; sock->mtu_discover_type = mtu_discover_type; sock->socket_buffer_sizes.rcvbuf = rcvbuf; sock->socket_buffer_sizes.sndbuf = sndbuf; sock->info.proto = proto; sock->info.remote_float = remote_float; sock->info.lsa = lsa; sock->info.ipchange_command = ipchange_command; /* are we running in HTTP proxy mode? */ if (sock->http_proxy) { ASSERT (sock->info.proto == PROTO_TCPv4_CLIENT); ASSERT (!sock->inetd); /* the proxy server */ sock->remote_host = http_proxy->server; sock->remote_port = http_proxy->port; /* the OpenVPN server we will use the proxy to connect to */ sock->proxy_dest_host = remote_host; sock->proxy_dest_port = remote_port; } /* or in Socks proxy mode? */ else if (sock->socks_proxy) { ASSERT (!sock->inetd); /* the proxy server */ sock->remote_host = socks_proxy->server; sock->remote_port = socks_proxy->port; /* the OpenVPN server we will use the proxy to connect to */ sock->proxy_dest_host = remote_host; sock->proxy_dest_port = remote_port; } else { sock->remote_host = remote_host; sock->remote_port = remote_port; } /* bind behavior for TCP server vs. client */ if (sock->info.proto == PROTO_TCPv4_SERVER) sock->bind_local = true; else if (sock->info.proto == PROTO_TCPv4_CLIENT) sock->bind_local = false; /* were we started by inetd or xinetd? */ if (sock->inetd) { ASSERT (sock->info.proto != PROTO_TCPv4_CLIENT); ASSERT (inetd_socket_descriptor >= 0); sock->sd = inetd_socket_descriptor; } else { create_socket (sock); resolve_bind_local (sock); resolve_remote (sock, 1, NULL, NULL); }}/* finalize socket initialization */voidlink_socket_init_phase2 (struct link_socket *sock, const struct frame *frame, volatile int *signal_received){ struct gc_arena gc = gc_new (); const char *remote_dynamic = NULL; bool remote_changed = false; ASSERT (sock); /* initialize buffers */ socket_frame_init (frame, sock); /* * Pass a remote name to connect/accept so that * they can test for dynamic IP address changes * and throw a SIGUSR1 if appropriate. */ if (sock->resolve_retry_seconds) remote_dynamic = sock->remote_host; /* were we started by inetd or xinetd? */ if (sock->inetd) { if (sock->info.proto == PROTO_TCPv4_SERVER) sock->sd = socket_listen_accept (sock->sd, &sock->info.lsa->actual, remote_dynamic, &remote_changed, &sock->info.lsa->local, false, sock->inetd == INETD_NOWAIT, signal_received); ASSERT (!remote_changed); if (*signal_received) goto done; } else { resolve_remote (sock, 2, &remote_dynamic, signal_received); if (*signal_received) goto done; /* TCP client/server */ if (sock->info.proto == PROTO_TCPv4_SERVER) { switch (sock->mode) { case LS_MODE_DEFAULT: sock->sd = socket_listen_accept (sock->sd, &sock->info.lsa->actual, remote_dynamic, &remote_changed, &sock->info.lsa->local, true, false, signal_received); break; case LS_MODE_TCP_LISTEN: socket_do_listen (sock->sd, &sock->info.lsa->local, true, false); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -