⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.c

📁 Serveez是一个服务器框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * tunnel.c - port forward implementations * * Copyright (C) 2000, 2001 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. *  * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA.   * * $Id: tunnel.c,v 1.26 2001/07/03 10:43:31 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#if ENABLE_TUNNEL#define _GNU_SOURCE#include <assert.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <time.h>#ifdef __MINGW32__# include <winsock2.h>#endif#ifndef __MINGW32__# include <sys/socket.h># include <netinet/in.h># include <arpa/inet.h>#endif#include "libserveez.h"#include "tunnel.h"/* * The default tunnel server configuration. */tnl_config_t tnl_config = {  NULL, /* the source port to forward from */  NULL, /* target port to forward to */  NULL  /* the source client socket hash */};/* * Defining configuration file associations with key-value-pairs. */svz_key_value_pair_t tnl_config_prototype [] = {  SVZ_REGISTER_PORTCFG ("source", tnl_config.source, SVZ_ITEM_NOTDEFAULTABLE),  SVZ_REGISTER_PORTCFG ("target", tnl_config.target, SVZ_ITEM_NOTDEFAULTABLE),  SVZ_REGISTER_END ()};/* * Definition of this server. */svz_servertype_t tnl_server_definition ={  "tunnel server",  "tunnel",  tnl_global_init,  tnl_init,  tnl_detect_proto,  tnl_connect_socket,  tnl_finalize,  tnl_global_finalize,  NULL,  NULL,  NULL,  tnl_handle_request_udp_source,  &tnl_config,  sizeof (tnl_config),  tnl_config_prototype};/* * The tunnel server's global initializer. */inttnl_global_init (svz_servertype_t *server){  return 0;}/* * The tunnel server's global finalizer. */inttnl_global_finalize (svz_servertype_t *server){  return 0;}/* * Tunnel server instance initializer. Check the configuration. */inttnl_init (svz_server_t *server){  tnl_config_t *cfg = server->cfg;  struct sockaddr_in *addr;  /* protocol supported ? */  if (!(cfg->source->proto & (PROTO_TCP|PROTO_ICMP|PROTO_UDP|PROTO_PIPE)) ||      !(cfg->target->proto & (PROTO_TCP|PROTO_ICMP|PROTO_UDP|PROTO_PIPE)))    {      svz_log (LOG_ERROR, "tunnel: protocol not supported\n");      return -1;    }  /* check identity of source and target port configurations */  if (svz_portcfg_equal (cfg->source, cfg->target))    {      svz_log (LOG_ERROR, "tunnel: source and target identical\n");      return -1;    }  if (!(cfg->target->proto & PROTO_PIPE))    {      /* broadcast target ip address not allowed */      addr = svz_portcfg_addr (cfg->target);      if (addr->sin_addr.s_addr == INADDR_ANY)	{	  svz_log (LOG_ERROR, "tunnel: broadcast target ip not allowed\n");	  return -1;	}    }  /* create source client hash (for UDP and ICMP only) */  cfg->client = svz_hash_create (4);    /* assign the appropriate handle request routine of the server */  if (cfg->source->proto & PROTO_UDP)    server->handle_request = tnl_handle_request_udp_source;  if (cfg->source->proto & PROTO_ICMP)    server->handle_request = tnl_handle_request_icmp_source;  return 0;}/* * The tunnel server instance finalizer. */inttnl_finalize (svz_server_t *server){  tnl_config_t *cfg = server->cfg;  tnl_connect_t **source;  int n;  /* release source connection hash if necessary */  if ((source = (tnl_connect_t **) svz_hash_values (cfg->client)) != NULL)    {      for (n = 0; n < svz_hash_size (cfg->client); n++)	{	  svz_free (source[n]);	}      svz_hash_xfree (source);    }  svz_hash_destroy (cfg->client);  return 0;}/* * Create a hash string (key) for the source client hash. Identifiers * are the remote ip address and port. */static char *tnl_addr (svz_socket_t *sock){  static char addr[24];  sprintf (addr, "%s:%u", svz_inet_ntoa (sock->remote_addr), 	   ntohs (sock->remote_port));  return addr;}/* * Release referring tunnel structure. */static voidtnl_free_connect (svz_socket_t *sock){  if (sock->data)    {      svz_free (sock->data);      sock->data = NULL;    }}/* * Create a referring tunnel connection structure. */static tnl_connect_t *tnl_create_connect (void){  tnl_connect_t *source;  source = svz_malloc (sizeof (tnl_connect_t));  memset (source, 0, sizeof (tnl_connect_t));  return source;}/* * Depending on the given socket structure target flag this routine * tries to connect to the servers target configuration and delivers a * new socket structure or NULL if it failed. */ static svz_socket_t *tnl_create_socket (svz_socket_t *sock, int source){  tnl_config_t *cfg = sock->cfg;  unsigned long ip = 0;  unsigned short port = 0;  svz_socket_t *xsock = NULL;  struct sockaddr_in *addr;  /* get host and target ip if necessary */  if (!(cfg->target->proto & PROTO_PIPE))    {      addr = svz_portcfg_addr (cfg->target);      ip = addr->sin_addr.s_addr;      port = addr->sin_port;    }  /*   * Depending on the target configuration we assign different   * callbacks, set other flags and use various connection routines.   */  switch (cfg->target->proto)    {    case PROTO_TCP:      sock->userflags |= TNL_FLAG_TGT_TCP;      break;    case PROTO_UDP:      sock->userflags |= TNL_FLAG_TGT_UDP;      break;    case PROTO_ICMP:      sock->userflags |= TNL_FLAG_TGT_ICMP;      break;    case PROTO_PIPE:      sock->userflags |= TNL_FLAG_TGT_PIPE;      break;    default:      svz_log (LOG_ERROR, "tunnel: invalid target configuration\n");      return NULL;    }  /* target is a TCP connection */  if (sock->userflags & TNL_FLAG_TGT_TCP)    {      if ((xsock = svz_tcp_connect (ip, port)) == NULL)	{	  svz_log (LOG_ERROR, "tunnel: tcp: cannot connect to %s:%u\n",		   svz_inet_ntoa (ip), ntohs (port));	  return NULL;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "tunnel: tcp: connecting to %s:%u\n",	       svz_inet_ntoa (ip), ntohs (port));#endif /* ENABLE_DEBUG */      xsock->check_request = tnl_check_request_tcp_target;      svz_sock_resize_buffers (xsock, UDP_BUF_SIZE, UDP_BUF_SIZE);    }  /* target is an UDP connection */  else if (sock->userflags & TNL_FLAG_TGT_UDP)    {      if ((xsock = svz_udp_connect (ip, port)) == NULL)	{	  svz_log (LOG_ERROR, "tunnel: udp: cannot connect to %s:%u\n",		   svz_inet_ntoa (ip), ntohs (port));	  return NULL;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "tunnel: udp: connecting to %s:%u\n",	       svz_inet_ntoa (ip), ntohs (port));#endif /* ENABLE_DEBUG */      xsock->handle_request = tnl_handle_request_udp_target;      xsock->idle_func = tnl_idle;      xsock->idle_counter = TNL_TIMEOUT;    }  /* target is an ICMP connection */  else if (sock->userflags & TNL_FLAG_TGT_ICMP)    {      if ((xsock = svz_icmp_connect (ip, port, cfg->target->icmp_type)) 	  == NULL)	{	  svz_log (LOG_ERROR, "tunnel: icmp: cannot connect to %s\n",		   svz_inet_ntoa (ip));	  return NULL;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "tunnel: icmp: connecting to %s\n",	       svz_inet_ntoa (ip));#endif /* ENABLE_DEBUG */      xsock->handle_request = tnl_handle_request_icmp_target;      xsock->idle_func = tnl_idle;      xsock->idle_counter = TNL_TIMEOUT;    }  /* target is a pipe connection */  else if (sock->userflags & TNL_FLAG_TGT_PIPE)    {      if ((xsock = svz_pipe_connect (&cfg->target->pipe_recv, 				     &cfg->target->pipe_send)) == NULL)	{	  svz_log (LOG_ERROR, "tunnel: pipe: cannot connect to %s\n",		   cfg->target->pipe_send.name);	  return NULL;	}#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "tunnel: pipe: connecting to %s\n",	       cfg->target->pipe_send.name);#endif /* ENABLE_DEBUG */      xsock->check_request = tnl_check_request_pipe_target;      svz_sock_resize_buffers (xsock, UDP_BUF_SIZE, UDP_BUF_SIZE);    }  xsock->cfg = cfg;  xsock->flags |= SOCK_FLAG_NOFLOOD;  xsock->userflags = (sock->userflags | source) & ~(TNL_FLAG_TGT);  xsock->disconnected_socket = tnl_disconnect_target;  return xsock;}/* * Forward a given packet with a certain length to a target connection. * This routine can be used by all source connection handler passing * the targets socket and its own userflags. */static inttnl_send_request_source (svz_socket_t *sock, char *packet, int len, int flag){  /* target is TCP or PIPE */  if (flag & (TNL_FLAG_TGT_TCP | TNL_FLAG_TGT_PIPE))    {      if (svz_sock_write (sock, packet, len) == -1)	return -1;    }  /* target is UDP */  else if (flag & TNL_FLAG_TGT_UDP)    {      if (svz_udp_write (sock, packet, len) == -1)	return -1;    }  /* target is ICMP */  else if (flag & TNL_FLAG_TGT_ICMP)    {      if (svz_icmp_write (sock, packet, len) == -1)	return -1;    }  return 0;}/* * Forward a given packet with a certain length to a source connection. * This routine can be used by all target connection handler passing * the sources socket and its own userflags. */static inttnl_send_request_target (svz_socket_t *sock, char *packet, int len, int flag){  /* source is TCP or PIPE */  if (flag & (TNL_FLAG_SRC_TCP | TNL_FLAG_SRC_PIPE))    {      if (svz_sock_write (sock, packet, len) == -1)	return -1;    }  /* source is UDP */  else if (flag & TNL_FLAG_SRC_UDP)    {      if (svz_udp_write (sock, packet, len) == -1)	return -1;    }  /* source is ICMP */  else if (flag & TNL_FLAG_SRC_ICMP)    {      if (svz_icmp_write (sock, packet, len) == -1)	return -1;    }  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -