📄 tunnel.c
字号:
/* * Tunnel server TCP and pipe detection routine. It is greedy. Thus it cannot * share the port configuration with other TCP or pipe servers. */inttnl_detect_proto (svz_server_t *server, svz_socket_t *sock){ svz_log (LOG_NOTICE, "tunnel: %s connection accepted\n", sock->flags & SOCK_FLAG_PIPE ? "pipe" : "tcp"); return -1;}/* * If any TCP or pipe connection has been accepted this routine is called * to setup the tunnel server specific callbacks. */inttnl_connect_socket (svz_server_t *server, svz_socket_t *sock){ svz_socket_t *xsock = NULL; tnl_connect_t *source; sock->flags |= SOCK_FLAG_NOFLOOD; sock->check_request = sock->flags & SOCK_FLAG_PIPE ? tnl_check_request_pipe_source : tnl_check_request_tcp_source; sock->disconnected_socket = tnl_disconnect_source; svz_sock_resize_buffers (sock, UDP_BUF_SIZE, UDP_BUF_SIZE); /* try connecting to target */ xsock = tnl_create_socket (sock, sock->flags & SOCK_FLAG_PIPE ? TNL_FLAG_SRC_PIPE : TNL_FLAG_SRC_TCP); if (xsock == NULL) return -1; /* put the source connection into data field */ source = tnl_create_connect (); source->source_sock = sock; source->target_sock = xsock; source->ip = sock->remote_addr; source->port = sock->remote_port; xsock->data = source; sock->data = source; return 0;}/* * The tunnel servers TCP check_request routine for target connections. * Each TCP target connection gets assigned this function in order to * send data back to its source connection. */inttnl_check_request_tcp_target (svz_socket_t *sock){ svz_socket_t *xsock = NULL; tnl_connect_t *source = sock->data;#if ENABLE_DEBUG if (source == NULL || source->source_sock == NULL) { svz_log (LOG_FATAL, "tunnel: tcp target has no source connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* obtain source connection */ xsock = source->source_sock; xsock->remote_addr = source->ip; xsock->remote_port = source->port; /* forward data to source connection */ if (tnl_send_request_target (xsock, sock->recv_buffer, sock->recv_buffer_fill, sock->userflags) == -1) { svz_sock_schedule_for_shutdown (xsock); return -1; } /* empty the receive buffer of this target connection */ sock->recv_buffer_fill = 0; return 0;}/* * The tunnel servers TCP check_request() routine for the source connections. * It simply copies the received data to the send buffer of the target * connection. */inttnl_check_request_tcp_source (svz_socket_t *sock){ tnl_connect_t *target = sock->data; svz_socket_t *xsock;#if ENABLE_DEBUG if (target == NULL || target->target_sock == NULL) { svz_log (LOG_FATAL, "tunnel: tcp source has no target connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* obtain target connection */ xsock = target->target_sock; /* forward data to target connection */ if (tnl_send_request_source (xsock, sock->recv_buffer, sock->recv_buffer_fill, sock->userflags) == -1) { return -1; } sock->recv_buffer_fill = 0; return 0;}/* * This function is the handle_request() routine for target UDP sockets. */inttnl_handle_request_udp_target (svz_socket_t *sock, char *packet, int len){ tnl_connect_t *source = sock->data; svz_socket_t *xsock = NULL;#if ENABLE_DEBUG if (source == NULL || source->source_sock == NULL) { svz_log (LOG_FATAL, "tunnel: udp target has no source connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* get source connection from data field */ xsock = source->source_sock; xsock->remote_addr = source->ip; xsock->remote_port = source->port; /* forward packet data to source connection */ if (tnl_send_request_target (xsock, packet, len, sock->userflags) == -1) { /* shutdown the source connection if it is TCP or pipe */ if (sock->userflags & (TNL_FLAG_SRC_TCP | TNL_FLAG_SRC_PIPE)) svz_sock_schedule_for_shutdown (xsock); return -1; } /* returning zero means that the packet has been processed */ return 0;}/* * This function is the handle_request() routine for source UDP sockets. * It accepts UDP connections (listening connection) or forwards data * to existing target sockets. */inttnl_handle_request_udp_source (svz_socket_t *sock, char *packet, int len){ tnl_config_t *cfg = sock->cfg; tnl_connect_t *source; svz_socket_t *xsock = NULL; /* check if there is such a connection in the source hash already */ source = svz_hash_get (cfg->client, tnl_addr (sock)); if (source) { /* get existing target socket */ xsock = source->target_sock; } else { /* start connecting to a new target */ if ((xsock = tnl_create_socket (sock, TNL_FLAG_SRC_UDP)) == NULL) return 0; /* foreign address not in hash, create new target connection */ source = tnl_create_connect (); source->source_sock = sock; source->ip = sock->remote_addr; source->port = sock->remote_port; svz_hash_put (cfg->client, tnl_addr (sock), source); /* put the source connection into data field of target */ xsock->data = source; source->target_sock = xsock; } /* forward packet data to target connection */ if (tnl_send_request_source (xsock, packet, len, sock->userflags) == -1) { svz_sock_schedule_for_shutdown (xsock); return 0; } return 0;}/* * This function is the handle_request routine for target ICMP sockets. */inttnl_handle_request_icmp_target (svz_socket_t *sock, char *packet, int len){ tnl_connect_t *source = sock->data; svz_socket_t *xsock = NULL;#if ENABLE_DEBUG if (source == NULL || source->source_sock == NULL) { svz_log (LOG_FATAL, "tunnel: icmp target has no source connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* get source connection from data field */ xsock = source->source_sock; xsock->remote_addr = source->ip; xsock->remote_port = source->port; /* forward packet data to source connection */ if (tnl_send_request_target (xsock, packet, len, sock->userflags) == -1) { /* shutdown source connection if it is TCP or pipe */ if (sock->userflags & (TNL_FLAG_SRC_TCP | TNL_FLAG_SRC_PIPE)) svz_sock_schedule_for_shutdown (xsock); return -1; } /* packet successfully processed */ return 0;}/* * This function is the handle_request() routine for source ICMP sockets. * It accepts ICMP connections (listening connection) or forwards data * to existing target sockets. */inttnl_handle_request_icmp_source (svz_socket_t *sock, char *packet, int len){ tnl_config_t *cfg = sock->cfg; tnl_connect_t *source; svz_socket_t *xsock = NULL; /* check if there is such a connection in the source hash already */ source = svz_hash_get (cfg->client, tnl_addr (sock)); if (source) { /* get existing target socket */ xsock = source->target_sock; } else { /* start connecting */ if ((xsock = tnl_create_socket (sock, TNL_FLAG_SRC_ICMP)) == NULL) return 0; /* foreign address not in hash, create new target connection */ source = tnl_create_connect (); source->source_sock = sock; source->ip = sock->remote_addr; source->port = sock->remote_port; svz_hash_put (cfg->client, tnl_addr (sock), source); /* put the source connection into data field */ xsock->data = source; source->target_sock = xsock; } /* forward packet data to target connection */ if (tnl_send_request_source (xsock, packet, len, sock->userflags) == -1) { svz_sock_schedule_for_shutdown (xsock); return 0; } return 0;}/* * The targets's disconnection routine for types of targets (TCP, PIPE, * ICMP and UDP). */inttnl_disconnect_target (svz_socket_t *sock){ tnl_config_t *cfg = sock->cfg; tnl_connect_t *source = sock->data; svz_socket_t *xsock; char *key; /* do not do anything if we are shutting down */ if (svz_nuke_happened) { /* if source is TCP or PIPE then shutdown referring connection */ if (sock->userflags & (TNL_FLAG_SRC_TCP | TNL_FLAG_SRC_PIPE)) { xsock = source ? source->source_sock : NULL; if (xsock) xsock->data = NULL; tnl_free_connect (sock); } return 0; }#if ENABLE_DEBUG if (source == NULL || source->source_sock == NULL) { svz_log (LOG_FATAL, "tunnel: target has no source connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* obtain source connection */ xsock = source->source_sock; /* if the source connection is ICMP send a disconnection message */ if (sock->userflags & TNL_FLAG_SRC_ICMP) {#if ENABLE_DEBUG svz_log (LOG_DEBUG, "tunnel: sending icmp disconnect on socket id %d\n", xsock->id);#endif /* ENABLE_DEBUG */ svz_icmp_send_control (xsock, ICMP_SERVEEZ_CLOSE); } /* if source is TCP or PIPE then shutdown referring connection */ if (sock->userflags & (TNL_FLAG_SRC_TCP | TNL_FLAG_SRC_PIPE)) {#if ENABLE_DEBUG svz_log (LOG_DEBUG, "tunnel: shutdown referrer id %d\n", xsock->id);#endif /* ENABLE_DEBUG */ svz_sock_schedule_for_shutdown (xsock); xsock->data = NULL; tnl_free_connect (sock); } /* else delete target connection from its hash */ else if ((key = svz_hash_contains (cfg->client, source)) != NULL) { svz_hash_delete (cfg->client, key); tnl_free_connect (sock); } return 0;}/* * What happens if a source connection gets lost. */inttnl_disconnect_source (svz_socket_t *sock){ tnl_connect_t *target = sock->data; svz_socket_t *xsock; /* if target is TCP or PIPE shutdown referring connection */ if (sock->userflags & (TNL_FLAG_TGT_TCP | TNL_FLAG_TGT_PIPE)) {#if ENABLE_DEBUG if (target == NULL || target->target_sock == NULL) { svz_log (LOG_DEBUG, "tunnel: tcp/pipe source has no " "target connection\n"); return -1; }#endif /* ENABLE_DEBUG */ /* get target connection */ xsock = target->target_sock;#if ENABLE_DEBUG svz_log (LOG_DEBUG, "tunnel: shutdown referrer id %d\n", xsock->id);#endif /* ENABLE_DEBUG */ svz_sock_schedule_for_shutdown (xsock); xsock->data = NULL; tnl_free_connect (sock); } return 0;}/* * Because UDP and ICMP sockets cannot not be detected as being closed * we need to shutdown target sockets ourselves. */inttnl_idle (svz_socket_t *sock){ time_t t = time (NULL); if (t - sock->last_recv < TNL_TIMEOUT || t - sock->last_send < TNL_TIMEOUT) { sock->idle_counter = TNL_TIMEOUT; return 0; } return -1;}#else /* not ENABLE_TUNNEL */int tunnel_dummy; /* Shut compiler warnings up. */#endif /* not ENABLE_TUNNEL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -