📄 socket.c
字号:
case LS_MODE_TCP_ACCEPT_FROM: sock->sd = socket_do_accept (sock->sd, &sock->info.lsa->actual, false); if (sock->sd == -1) { *signal_received = SIGTERM; goto done; } tcp_connection_established (&sock->info.lsa->actual); break; default: ASSERT (0); } } else if (sock->info.proto == PROTO_TCPv4_CLIENT) { socket_connect (&sock->sd, &sock->info.lsa->actual, sock->remote_list, remote_dynamic, &remote_changed, sock->connect_retry_seconds, signal_received); if (*signal_received) goto done; if (sock->http_proxy) { establish_http_proxy_passthru (sock->http_proxy, sock->sd, sock->proxy_dest_host, sock->proxy_dest_port, &sock->stream_buf.residual, signal_received); } else if (sock->socks_proxy) { establish_socks_proxy_passthru (sock->socks_proxy, sock->sd, sock->proxy_dest_host, sock->proxy_dest_port, signal_received); } } else if (sock->info.proto == PROTO_UDPv4 && sock->socks_proxy) { socket_connect (&sock->ctrl_sd, &sock->info.lsa->actual, NULL, remote_dynamic, &remote_changed, sock->connect_retry_seconds, signal_received); if (*signal_received) goto done; establish_socks_proxy_udpassoc (sock->socks_proxy, sock->ctrl_sd, sock->sd, &sock->socks_relay, signal_received); if (*signal_received) goto done; sock->remote_host = sock->proxy_dest_host; sock->remote_port = sock->proxy_dest_port; sock->did_resolve_remote = false; sock->info.lsa->actual.sin_addr.s_addr = 0; sock->info.lsa->remote.sin_addr.s_addr = 0; resolve_remote (sock, 1, NULL, signal_received); if (*signal_received) goto done; } if (*signal_received) goto done; if (remote_changed) { msg (M_INFO, "TCP/UDP: Dynamic remote address changed during TCP connection establishment"); sock->info.lsa->remote.sin_addr.s_addr = sock->info.lsa->actual.sin_addr.s_addr; } } /* set socket buffers based on --sndbuf and --rcvbuf options */ socket_set_buffers (sock->sd, &sock->socket_buffer_sizes); /* set socket to non-blocking mode */ set_nonblock (sock->sd); /* set socket file descriptor to not pass across execs, so that scripts don't have access to it */ set_cloexec (sock->sd); if (sock->ctrl_sd != -1) set_cloexec (sock->ctrl_sd); /* set Path MTU discovery options on the socket */ set_mtu_discover_type (sock->sd, sock->mtu_discover_type);#if EXTENDED_SOCKET_ERROR_CAPABILITY /* if the OS supports it, enable extended error passing on the socket */ set_sock_extended_error_passing (sock->sd);#endif /* print local address */ if (sock->inetd) msg (M_INFO, "%s link local: [inetd]", proto2ascii (sock->info.proto, true)); else msg (M_INFO, "%s link local%s: %s", proto2ascii (sock->info.proto, true), (sock->bind_local ? " (bound)" : ""), print_sockaddr_ex (&sock->info.lsa->local, sock->bind_local, ":", &gc)); /* print active remote address */ msg (M_INFO, "%s link remote: %s", proto2ascii (sock->info.proto, true), print_sockaddr_ex (&sock->info.lsa->actual, addr_defined (&sock->info.lsa->actual), ":", &gc)); done: gc_free (&gc);}voidlink_socket_close (struct link_socket *sock){ if (sock) { if (sock->sd != -1) {#ifdef WIN32 overlapped_io_close (&sock->reads); overlapped_io_close (&sock->writes);#endif msg (D_CLOSE, "TCP/UDP: Closing socket"); if (openvpn_close_socket (sock->sd)) msg (M_WARN | M_ERRNO_SOCK, "TCP/UDP: Close Socket failed"); sock->sd = -1; } if (sock->ctrl_sd != -1) { if (openvpn_close_socket (sock->ctrl_sd)) msg (M_WARN | M_ERRNO_SOCK, "TCP/UDP: Close Socket failed"); sock->ctrl_sd = -1; } stream_buf_close (&sock->stream_buf); free_buf (&sock->stream_buf_data); free (sock); }}/* for stream protocols, allow for packet length prefix */voidsocket_adjust_frame_parameters (struct frame *frame, int proto){ if (link_socket_proto_connection_oriented (proto)) frame_add_to_extra_frame (frame, sizeof (packet_size_type));}voidsetenv_trusted (const struct link_socket_info *info){ setenv_sockaddr ("trusted", &info->lsa->actual);}voidlink_socket_connection_initiated (const struct buffer *buf, struct link_socket_info *info, const struct sockaddr_in *addr, const char *common_name){ struct gc_arena gc = gc_new (); /* acquire script mutex */ mutex_lock_static (L_SCRIPT); info->lsa->actual = *addr; /* Note: skip this line for --force-dest */ setenv_trusted (info); info->connection_established = true; /* Print connection initiated message, with common name if available */ { struct buffer out = alloc_buf_gc (256, &gc); if (common_name) buf_printf (&out, "[%s] ", common_name); buf_printf (&out, "Peer Connection Initiated with %s", print_sockaddr (&info->lsa->actual, &gc)); msg (M_INFO, "%s", BSTR (&out)); } /* Process --ipchange option */ if (info->ipchange_command) { struct buffer out = alloc_buf_gc (512, &gc); setenv_str ("script_type", "ipchange"); buf_printf (&out, "%s %s", info->ipchange_command, print_sockaddr_ex (&info->lsa->actual, true, " ", &gc)); msg (D_TLS_DEBUG, "executing ip-change command: %s", BSTR (&out)); system_check (BSTR (&out), "ip-change command failed", false); } mutex_unlock_static (L_SCRIPT); gc_free (&gc);}voidlink_socket_bad_incoming_addr (struct buffer *buf, const struct link_socket_info *info, const struct sockaddr_in *from_addr){ struct gc_arena gc = gc_new (); msg (D_LINK_ERRORS, "TCP/UDP: Incoming packet rejected from %s[%d], expected peer address: %s (allow this incoming source address/port by removing --remote or adding --float)", print_sockaddr (from_addr, &gc), (int)from_addr->sin_family, print_sockaddr (&info->lsa->remote, &gc)); buf->len = 0; gc_free (&gc);}voidlink_socket_bad_outgoing_addr (void){ msg (D_READ_WRITE, "TCP/UDP: No outgoing address to send packet");}in_addr_tlink_socket_current_remote (const struct link_socket_info *info){ const struct link_socket_addr *lsa = info->lsa; if (addr_defined (&lsa->actual)) return ntohl (lsa->actual.sin_addr.s_addr); else if (addr_defined (&lsa->remote)) return ntohl (lsa->remote.sin_addr.s_addr); else return 0;}/* * Return a status string describing socket state. */const char *socket_stat (const struct link_socket *s, unsigned int rwflags, struct gc_arena *gc){ struct buffer out = alloc_buf_gc (64, gc); if (s) { if (rwflags & EVENT_READ) { buf_printf (&out, "S%s", (s->rwflags & EVENT_READ) ? "R" : "r");#ifdef WIN32 buf_printf (&out, "%s", overlapped_io_state_ascii (&s->reads));#endif } if (rwflags & EVENT_WRITE) { buf_printf (&out, "S%s", (s->rwflags & EVENT_WRITE) ? "W" : "w");#ifdef WIN32 buf_printf (&out, "%s", overlapped_io_state_ascii (&s->writes));#endif } } else { buf_printf (&out, "S?"); } return BSTR (&out);}/* * Stream buffer functions, used to packetize a TCP * stream connection. */static inline voidstream_buf_reset (struct stream_buf *sb){ msg (D_STREAM_DEBUG, "STREAM: RESET"); sb->residual_fully_formed = false; sb->buf = sb->buf_init; buf_reset (&sb->next); sb->len = -1;}voidstream_buf_init (struct stream_buf *sb, struct buffer *buf){ sb->buf_init = *buf; sb->maxlen = sb->buf_init.len; sb->buf_init.len = 0; sb->residual = alloc_buf (sb->maxlen); sb->error = false; stream_buf_reset (sb); msg (D_STREAM_DEBUG, "STREAM: INIT maxlen=%d", sb->maxlen);}static inline voidstream_buf_set_next (struct stream_buf *sb){ /* set up 'next' for next i/o read */ sb->next = sb->buf; sb->next.offset = sb->buf.offset + sb->buf.len; sb->next.len = (sb->len >= 0 ? sb->len : sb->maxlen) - sb->buf.len; msg (D_STREAM_DEBUG, "STREAM: SET NEXT, buf=[%d,%d] next=[%d,%d] len=%d maxlen=%d", sb->buf.offset, sb->buf.len, sb->next.offset, sb->next.len, sb->len, sb->maxlen); ASSERT (sb->next.len > 0); ASSERT (buf_safe (&sb->buf, sb->next.len));}static inline voidstream_buf_get_final (struct stream_buf *sb, struct buffer *buf){ msg (D_STREAM_DEBUG, "STREAM: GET FINAL len=%d", buf_defined (&sb->buf) ? sb->buf.len : -1); ASSERT (buf_defined (&sb->buf)); *buf = sb->buf;}static inline voidstream_buf_get_next (struct stream_buf *sb, struct buffer *buf){ msg (D_STREAM_DEBUG, "STREAM: GET NEXT len=%d", buf_defined (&sb->next) ? sb->next.len : -1); ASSERT (buf_defined (&sb->next)); *buf = sb->next;}boolstream_buf_read_setup_dowork (struct link_socket* sock){ if (sock->stream_buf.residual.len && !sock->stream_buf.residual_fully_formed) { ASSERT (buf_copy (&sock->stream_buf.buf, &sock->stream_buf.residual)); ASSERT (buf_init (&sock->stream_buf.residual, 0)); sock->stream_buf.residual_fully_formed = stream_buf_added (&sock->stream_buf, 0); msg (D_STREAM_DEBUG, "STREAM: RESIDUAL FULLY FORMED [%s], len=%d", sock->stream_buf.residual_fully_formed ? "YES" : "NO", sock->stream_buf.residual.len); } if (!sock->stream_buf.residual_fully_formed) stream_buf_set_next (&sock->stream_buf); return !sock->stream_buf.residual_fully_formed;}boolstream_buf_added (struct stream_buf *sb, int length_added){ msg (D_STREAM_DEBUG, "STREAM: ADD length_added=%d", length_added); if (length_added > 0) sb->buf.len += length_added; /* if length unknown, see if we can get the length prefix from the head of the buffer */ if (sb->len < 0 && sb->buf.len >= (int) sizeof (packet_size_type)) { packet_size_type net_size; ASSERT (buf_read (&sb->buf, &net_size, sizeof (net_size))); sb->len = ntohps (net_size); if (sb->len < 1 || sb->len > sb->maxlen) { msg (M_WARN, "WARNING: Bad encapsulated packet length from peer (%d), which must be > 0 and <= %d -- please ensure that --tun-mtu or --link-mtu is equal on both peers -- this condition could also indicate a possible active attack on the TCP link -- [Attemping restart...]", sb->len, sb->maxlen); stream_buf_reset (sb); sb->error = true; return false; } } /* is our incoming packet fully read? */ if (sb->len > 0 && sb->buf.len >= sb->len) { /* save any residual data that's part of the next packet */ ASSERT (buf_init (&sb->residual, 0)); if (sb->buf.len > sb->len) ASSERT (buf_copy_excess (&sb->residual, &sb->buf, sb->len)); msg (D_STREAM_DEBUG, "STREAM: ADD returned TRUE, buf_len=%d, residual_len=%d", BLEN (&sb->buf), BLEN (&sb->residual)); return true; } else { msg (D_STREAM_DEBUG, "STREAM: ADD returned FALSE (have=%d need=%d)", sb->buf.len, sb->len); stream_buf_set_next (sb); return false; }}voidstream_buf_close (struct stream_buf* sb){ free_buf (&sb->residual);}/* * Format IP addresses in ascii */const char *print_sockaddr (const struct sockaddr_in *addr, struct gc_arena *gc){ return print_sockaddr_ex(addr, true, ":", gc);}const char *print_sockaddr_ex (const struct sockaddr_in *addr, bool do_port, const char* separator, struct gc_arena *gc){ struct buffer out = alloc_buf_gc (64, gc); const int port = ntohs (addr->sin_port); mutex_lock_static (L_INET_NTOA); buf_printf (&out, "%s", (addr_defined (addr) ? inet_ntoa (addr->sin_addr) : "[undef]")); mutex_unlock_static (L_INET_NTOA); if (do_port && port) { if (separator) buf_printf (&out, "%s", separator); buf_printf (&out, "%d", port); } return BSTR (&out);}/* * Convert an in_addr_t in host byte order * to an ascii dotted quad. */const char *print_in_addr_t (in_addr_t addr, bool empty_if_undef, struct gc_arena *gc){ struct in_addr ia; struct buffer out = alloc_buf_gc (64, gc); if (addr || !empty_if_undef) { CLEAR (ia); ia.s_addr = htonl (addr); mutex_lock_static (L_INET_NTOA); buf_printf (&out, "%s", inet_ntoa (ia)); mutex_unlock_static (L_INET_NTOA); } return BSTR (&out);}/* set environmental variables for ip/port in *addr */voidsetenv_sockaddr (const char *name_prefix, const struct sockaddr_in *addr){ char name_buf[256]; openvpn_snprintf (name_buf, sizeof (name_buf), "%s_ip", name_prefix); mutex_lock_static (L_INET_NTOA); setenv_str (name_buf, inet_ntoa (addr->sin_addr)); mutex_unlock_static (L_INET_NTOA); openvpn_snprintf (name_buf, sizeof (name_buf), "%s_port", name_prefix); setenv_int (name_buf, ntohs (addr->sin_port));}voidsetenv_in_addr_t (const char *name_prefix, in_addr_t addr){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -