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

📄 tunnel.c

📁 穿越防火墙技术代码
💻 C
📖 第 1 页 / 共 3 页
字号:
tunnel_write_data (Tunnel *tunnel, void *data, size_t length){  if (write_all (tunnel->out_fd, data, length) == -1)    {      log_error ("tunnel_write_data: write error: %s", strerror (errno));      return -1;    }  tunnel->bytes += length;  return length;}static inttunnel_write_request (Tunnel *tunnel, Request request,		      void *data, Length length){  if (tunnel->bytes + sizeof request +      (data ? sizeof length + length : 0) > tunnel->content_length)    tunnel_padding (tunnel, tunnel->content_length - tunnel->bytes);#if 1 /* FIXME: this is a kludge */  {    time_t t;    time (&t);    if (tunnel_is_client (tunnel) &&	tunnel_is_connected (tunnel) &&	t - tunnel->out_connect_time > tunnel->max_connection_age)      {	char c = TUNNEL_DISCONNECT;	log_debug ("tunnel_write_request: connection > %d seconds old",		   tunnel->max_connection_age);	if (tunnel->strict_content_length)	  {	    int l = tunnel->content_length - tunnel->bytes - 1;	    log_debug ("tunnel_write_request: write padding (%d bytes)",		       tunnel->content_length - tunnel->bytes - 1);	    if (l > 3)	    {		char c;		short s;		int i;		c = TUNNEL_PADDING;  		tunnel_write_data (tunnel, &c, sizeof c);		s = htons(l-2);		tunnel_write_data (tunnel, &s, sizeof s);		l -= 2;		c = 0;	    	for (i=0; i<l; i++)  			tunnel_write_data (tunnel, &c, sizeof c);	    }	    else	    {		char c = TUNNEL_PAD1;		int i;			    	for (i=0; i<l; i++)  			tunnel_write_data (tunnel, &c, sizeof c);	    }	  }	log_debug ("tunnel_write_request: closing old connection");	if (tunnel_write_data (tunnel, &c, sizeof c) <= 0)	  return -1;	tunnel_out_disconnect (tunnel);      }  }#endif  if (tunnel_is_disconnected (tunnel))    {      if (tunnel_is_client (tunnel))	{	  if (tunnel_out_connect (tunnel) == -1)	    return -1;	}      else	{#if 0	  log_error ("tunnel_write_request: output is disconnected");	  errno = EIO;	  return -1;#else	  if (tunnel_accept (tunnel) == -1)	    return -1;#endif	}    }  if (request != TUNNEL_PADDING && request != TUNNEL_PAD1)    tunnel->padding_only = FALSE;  if (tunnel_write_data (tunnel, &request, sizeof request) == -1)    {      if (errno != EPIPE)	return -1;      tunnel_out_disconnect (tunnel);      if (tunnel_is_client (tunnel))	tunnel_out_connect (tunnel);      else	{	  log_error ("tunnel_write_request: couldn't write request: "		     "output is disconnected");	  errno = EIO;	  return -1;	}      /* return tunnel_write_request (tunnel, request, data, length); */      if (tunnel_write_data (tunnel, &request, sizeof request) == -1)	return -1;    }  if (data)    {      Length network_length = htons ((short)length);      if (tunnel_write_data (tunnel,			     &network_length,			     sizeof network_length) == -1)	return -1;#ifdef DEBUG_MODE      if (request == TUNNEL_DATA && debug_level >= 5)	{	  log_annoying ("tunnel_write_request: TUNNEL_DATA:");	  dump_buf (debug_file, data, (size_t)length);	}#endif      if (tunnel_write_data (tunnel, data, (size_t)length) == -1)	return -1;    }  if (data)    {      tunnel->out_total_raw += 3 + length;      if (request == TUNNEL_DATA)	log_verbose ("tunnel_write_request: %s (%d)",		     REQ_TO_STRING (request), length);      else	log_debug ("tunnel_write_request: %s (%d)",		     REQ_TO_STRING (request), length);    }  else    {      tunnel->out_total_raw += 1;      log_debug ("tunnel_write_request: %s", REQ_TO_STRING (request));    }  log_annoying ("tunnel_write_data: out_total_raw = %u",		tunnel->out_total_raw);#ifdef DEBUG_MODE  if (tunnel->bytes > tunnel->content_length)    log_debug ("tunnel_write_request: tunnel->bytes > tunnel->content_length");#endif		      if (tunnel->bytes >= tunnel->content_length)    {      char c = TUNNEL_DISCONNECT;      tunnel_write_data (tunnel, &c, sizeof c);      tunnel_out_disconnect (tunnel);#if 0      if (tunnel_is_server (tunnel))	tunnel_accept (tunnel);#endif    }  return 0;}inttunnel_connect (Tunnel *tunnel){  char auth_data[1] = { 42 }; /* dummy data, not used by server */  log_verbose ("tunnel_connect()");  if (tunnel_is_connected (tunnel))    {      log_error ("tunnel_connect: already connected");      errno = EINVAL;      return -1;    }  if (tunnel_write_request (tunnel, TUNNEL_OPEN,			    auth_data, sizeof auth_data) == -1)    return -1;  if (tunnel_in_connect (tunnel) <= 0)    return -1;  return 0;}static inline inttunnel_write_or_padding (Tunnel *tunnel, Request request, void *data,			 size_t length){  static char padding[65536];  size_t n, remaining;  char *wdata = data;  for (remaining = length; remaining > 0; remaining -= n, wdata += n)    {      if (tunnel->bytes + remaining > tunnel->content_length - sizeof_header &&	  tunnel->content_length - tunnel->bytes > sizeof_header)	n = tunnel->content_length - sizeof_header - tunnel->bytes;      else if (remaining > tunnel->content_length - sizeof_header)	n = tunnel->content_length - sizeof_header;      else	n = remaining;      if (n > 65535)	n = 65535;      if (request == TUNNEL_PADDING)	{	  if (n + sizeof_header > remaining)	    n = remaining - sizeof_header;	  if (tunnel_write_request (tunnel, request, padding, n) == -1)	    break;	  n += sizeof_header;	}      else	{	  if (tunnel_write_request (tunnel, request, wdata, n) == -1)	    break;	}    }  return length - remaining;}ssize_ttunnel_write (Tunnel *tunnel, void *data, size_t length){  ssize_t n;  n = tunnel_write_or_padding (tunnel, TUNNEL_DATA, data, length);  tunnel->out_total_data += length;  log_verbose ("tunnel_write: out_total_data = %u", tunnel->out_total_data);  return n;}ssize_ttunnel_padding (Tunnel *tunnel, size_t length){  if (length < sizeof_header + 1)    {      int i;      for (i = 0; i < length; i++)	tunnel_write_request (tunnel, TUNNEL_PAD1, NULL, 0);      return length;    }  return tunnel_write_or_padding (tunnel, TUNNEL_PADDING, NULL, length);}inttunnel_close (Tunnel *tunnel){  struct pollfd p;  char buf[10240];  ssize_t n;  if (tunnel->strict_content_length)    {      log_debug ("tunnel_close: write padding (%d bytes)",		 tunnel->content_length - tunnel->bytes - 1);      tunnel_padding (tunnel, tunnel->content_length - tunnel->bytes - 1);    }  log_debug ("tunnel_close: write TUNNEL_CLOSE request");  tunnel_write_request (tunnel, TUNNEL_CLOSE, NULL, 0);  tunnel_out_disconnect (tunnel);  log_debug ("tunnel_close: reading trailing data from input ...");  p.fd = tunnel->in_fd;  p.events = POLLIN;  while (poll (&p, 1, READ_TRAIL_TIMEOUT) > 0)    {      if (p.revents & POLLIN)	{	  n = read (tunnel->in_fd, buf, sizeof buf);	  if (n > 0)	    {	      log_annoying ("read (%d, %p, %d) = %d",			    tunnel->in_fd, buf, sizeof buf, n);	      continue;	    }	  else if (n == -1 && errno == EAGAIN)	    continue;	  else if (n == -1)	    log_debug ("tunnel_close: ... error: %s", strerror (errno));	  else	    log_debug ("tunnel_close: ... done (tunnel closed)");	}      if (p.revents & POLLHUP)	log_debug ("POLLHUP");      if (p.revents & POLLERR)	log_debug ("POLLERR");      if (p.revents & POLLNVAL)	log_debug ("POLLNVAL");      break;    }  tunnel_in_disconnect (tunnel);  tunnel->buf_len = 0;  tunnel->in_total_raw = 0;  tunnel->in_total_data = 0;  tunnel->out_total_raw = 0;  tunnel->out_total_data = 0;  return 0;}static inttunnel_read_request (Tunnel *tunnel, enum tunnel_request *request,		     unsigned char *buf, size_t *length){  Request req;  Length len;  ssize_t n;  log_annoying ("read (%d, %p, %d) ...", tunnel->in_fd, &req, 1);  n = read (tunnel->in_fd, &req, 1);  log_annoying ("... = %d", n);  if (n == -1)    {      if (errno != EAGAIN)	log_error ("tunnel_read_request: error reading request: %s",		   strerror (errno));      return n;    }  else if (n == 0)    {      log_debug ("tunnel_read_request: connection closed by peer");      tunnel_in_disconnect (tunnel);      if (tunnel_is_client (tunnel)	  && tunnel_in_connect (tunnel) == -1)	return -1;      errno = EAGAIN;      return -1;    }  *request = req;  tunnel->in_total_raw += n;  log_annoying ("request = 0x%x (%s)", req, REQ_TO_STRING (req));  if (req & TUNNEL_SIMPLE)    {      log_annoying ("tunnel_read_request: in_total_raw = %u",		    tunnel->in_total_raw);      log_debug ("tunnel_read_request:  %s", REQ_TO_STRING (req));      *length = 0;      return 1;    }  n = read_all (tunnel->in_fd, &len, 2);  if (n <= 0)    {      log_error ("tunnel_read_request: error reading request length: %s",		 strerror (errno));      if (n == 0)	errno = EIO;      return -1;    }  len = ntohs (len);  *length = len;  tunnel->in_total_raw += n;  log_annoying ("length = %d", len);  if (len > 0)    {      n = read_all (tunnel->in_fd, buf, (size_t)len);      if (n <= 0)	{	  log_error ("tunnel_read_request: error reading request data: %s",		     strerror (errno));	  if (n == 0)	    errno = EIO;	  return -1;	}      tunnel->in_total_raw += n;      log_annoying ("tunnel_read_request: in_total_raw = %u",		    tunnel->in_total_raw);    }  if (req == TUNNEL_DATA)    log_verbose ("tunnel_read_request:  %s (%d)",		 REQ_TO_STRING (req), len);  else    log_debug ("tunnel_read_request:  %s (%d)",	       REQ_TO_STRING (req), len);  return 1;}ssize_ttunnel_read (Tunnel *tunnel, void *data, size_t length){  enum tunnel_request req;  size_t len;  ssize_t n;  if (tunnel->buf_len > 0)    {      n = min (tunnel->buf_len, length);      memcpy (data, tunnel->buf_ptr, n);      tunnel->buf_ptr += n;      tunnel->buf_len -= n;      return n;    }  if (tunnel->in_fd == -1)    {      if (tunnel_is_client (tunnel))	{	  if (tunnel_in_connect (tunnel) == -1)	    return -1;	}      else	{#if 1	  if (tunnel_accept (tunnel) == -1)	    return -1;#else	  errno = EAGAIN;	  return -1;#endif	}      errno = EAGAIN;      return -1;    }  if (tunnel->out_fd == -1 && tunnel_is_server (tunnel))    {      tunnel_accept (tunnel);      errno = EAGAIN;      return -1;    }  if (tunnel_read_request (tunnel, &req, tunnel->buf, &len) <= 0)    {log_annoying ("tunnel_read_request returned <= 0, returning -1");      return -1;    }  switch (req)    {    case TUNNEL_OPEN:      /* do something with tunnel->buf */      break;    case TUNNEL_DATA:      tunnel->buf_ptr = tunnel->buf;      tunnel->buf_len = len;      tunnel->in_total_data += len;      log_verbose ("tunnel_read: in_total_data = %u", tunnel->in_total_data);      return tunnel_read (tunnel, data, length);    case TUNNEL_PADDING:      /* discard data */      break;    case TUNNEL_PAD1:      /* do nothing */

⌨️ 快捷键说明

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