Beispiel #1
0
int netcat_socket_accept(int s, int timeout)
{
  fd_set in;
  int ret;
  static bool timeout_init = FALSE;
  static struct timeval timest;

  debug_v(("netcat_socket_accept(s=%d, timeout=%d)", s, timeout));

  /* initialize the select() variables */
  FD_ZERO(&in);
  FD_SET(s, &in);
  if (timeout > 0) {
    timest.tv_sec = timeout;
    timest.tv_usec = 0;
    timeout_init = TRUE;
  }
  else if (timeout && !timeout_init) {
    /* means that timeout is < 0 and timest hasn't been initialized */
    timeout = 0;
  }

  /* now call select(2).  use timest only if we won't wait forever */
 call_select:
  ret = select(s + 1, &in, NULL, NULL, (timeout ? &timest : NULL));
  if (ret < 0) {
    /* if the call was interrupted by a signal nothing happens. signal at this
       stage ought to be handled externally. */
    if (errno == EINTR)
      goto call_select;
    perror("select(sock_accept)");
    exit(EXIT_FAILURE);
  }

  /* have we got this connection? */
  if (FD_ISSET(s, &in)) {
    int new_sock;

    new_sock = accept(s, NULL, NULL);
    debug_v(("Connection received (new fd=%d)", new_sock));

    /* NOTE: as accept() could fail, new_sock might also be a negative value.
       It's application's work to handle the right errno. */
    return new_sock;
  }

  /* since we've got a timeout, the timest is now zero and thus it is like
     uninitialized.  Next time assume wait forever. */
  timeout_init = FALSE;

  /* no connections arrived during the given time. nothing happens */
  errno = ETIMEDOUT;
  return -1;
}
Beispiel #2
0
/* ainda entendendo a função... doc será escrito quando eu tiver absorvido ela completamente  */
bool netcat_resolvehost(nc_host_t *dst, const char *name) {
  int i, ret;
  struct hostent *hostent;
  struct in_addr res_addr;

  assert(name && name[0]);
  debug_v(("netcat_resolvehost(dst=%p, name=\"%s\")", (void *)dst, name));

  /* reseta os campos da estrutura dst */
  memset(dst, 0, sizeof(*dst));

  ret = netcat_inet_pton(name, &res_addr);
  if(!ret) { /* não conseguiu traduzir, precisa ser um nome! */
    bool host_auth_taken = FALSE;

  /* se opt_numeric estiver setado não devemos usar DNS */
  if(opt_numeric)
    return FALSE;

  /* falhas no lookup de host são reportadas de volta a função que chamou */
  if(!(hostent = gethostbyname(name))))
    return FALSE;

  /* precisamos controlar o CNAME. se olharmos para o host www.foo.bar, que é um alias para
     www.foo.mux.bar, o hostent vai conter o nome real em h_name, que não é o que queremos
     para o output (o usuário não quer ver que ele não digitou). então assumimos o lookup
     name como oficial e pegamos os ips para o lookup reverso */
  debug(("(lookup) lookup=\"%s\" oficial=\"%s\" (should match)\n", name, hostent->h_name));
  strncpy(dst->name, name, MAXHOSTNAMELEN - 1);

  /* agora salva todos os ips validos (não mais que MAXINETADDRS) */
  for(i=0; hostent->h_addr_list[i] && (i < MAXINETADDRS); i++) {
    memcpy(&dst->iaddrs[i], hostent->h_addr_list[i], sizeof(dst->iaddrs[0]));
    strncpy(dst->addrs[i], netcat_inet_ntop(&dst->iaddrs[i]), sizeof(dst->addrs[0]));
  }
Beispiel #3
0
const char *netcat_inet_ntop(int af, const void *src)
{
#ifdef HAVE_INET_NTOP
  static char my_buf[127];
# ifdef USE_IPV6
  struct in_addr v4mapped;
# endif
#endif
  const char *ret;

  debug_v(("netcat_inet_ntop(src=%p)", src));
  assert((af == AF_INET) || (af == AF_INET6));

#ifdef HAVE_INET_NTOP
# ifdef USE_IPV6
  /* If this is an IPv6-mapped IPv4 address, translate it in the correct way */
  if ((af == AF_INET6) && IN6_IS_ADDR_V4MAPPED(src)) {
    af = AF_INET;
    src = &((struct in6_addr *)src)->s6_addr32[3];
  }
# endif

  ret = inet_ntop(af, src, my_buf, sizeof(my_buf));
#else
# ifdef __GNUC__
#  warning Using broken network address conversion function for ntop
# endif
  ret = inet_ntoa(*(struct in_addr *)src);
#endif

  return ret;
}			/* end of netcat_inet_ntop() */
Beispiel #4
0
static void got_term(int z)
{
  if (!got_sigterm)
    ncprint(NCPRINT_VERB1, _("Terminated."));
  debug_v(("_____ RECEIVED SIGTERM _____ [signal_handler=%s]",
	  BOOL_TO_STR(signal_handler)));
  got_sigterm = TRUE;
  if (signal_handler)			/* default action */
    exit(EXIT_FAILURE);
}
Beispiel #5
0
bool netcat_ports_isset(nc_ports_t portsrange, unsigned short port)
{
  nc_ports_t tmp = portsrange;

  debug_v(("netcat_ports_isset(): p=%p port=%hu", portsrange, port));

  while (tmp && (tmp->start <= port)) {
    if (tmp->end > port)
      return TRUE;
    tmp = tmp->next;
  }
  return FALSE;
}
Beispiel #6
0
static void got_int(int z)
{
  if (!got_sigint)
    ncprint(NCPRINT_VERB1, _("Exiting."));
  debug_v(("_____ RECEIVED SIGINT _____ [signal_handler=%s]",
	  BOOL_TO_STR(signal_handler)));
  got_sigint = TRUE;
  if (signal_handler) {			/* default action */
    if (commandline_need_newline)	/* if we were waiting for input */
      printf("\n");
    netcat_printstats(FALSE);
    exit(EXIT_FAILURE);
  }
}
Beispiel #7
0
int netcat_ports_count(nc_ports_t portsrange)
{
  nc_ports_t tmp = portsrange;
  int count = 0;

  debug_v(("netcat_ports_count(): p=%p", portsrange));

  while (tmp) {
    count += (tmp->end - tmp->start);
    tmp = tmp->next;
  }

  return count;
}
Beispiel #8
0
void netcat_ports_insert(nc_ports_t *portsrange, unsigned short first, unsigned short last)
{
  nc_ports_t prev = NULL, next = *portsrange, ins;
  int start = first, end = last+1;

  debug_v(("netcat_ports_insert(): p=%p  %hu - %hu", *portsrange, first, last));

  /* find tmp_prev and tmp such that prev->start <= start && start < next->start */

  while (next && (start >= next->start)) {
    prev = next;
    next = next->next;
  }

  /* if the range to be inserted overlaps with prev then just modify
     the existing range */

  if (prev && (start <= prev->end)) {
    prev->end = MAX(prev->end, end);
    ins = prev;
  }
  else {	/* we are fully after the previous range. add a new one */
    ins = malloc(sizeof(*ins));

    ins->start = start;
    ins->end = end;
    ins->next = next;
    if (prev) {
      prev->next = ins;
    } else {
      /* we insert the range as the first element of the chained list; modify
         the pointer stored by the caller */
      *portsrange = ins;
    }
  }

  /* now, either we added a new range or recycled the previous one, we might
     have overlapped one or more of the following ranges.  Check this and
     merge when this happens. */

  while (ins->next && (ins->end >= ins->next->start)) {
    nc_ports_t tmp_del = ins->next;

    ins->end = MAX(ins->end, ins->next->end);
    ins->next = ins->next->next;
    free(tmp_del);
  }
}
Beispiel #9
0
int main(int argc, char **argv) 
{
	application app(argv[0], (std::string(getenv("HOME")) + "/.config/" + APP_NAME), getenv("HOME"));	
	
	std::string args("");
	for ( int i = 1 ; i < argc ; i++ ) args += std::string(argv[i]) + " ";
		
	//~ traitement  des arguments
	if (argc >= 2)
	{
		if ( !strcmp(argv[1],"--exec") or !strcmp(argv[1],"-e") )
		{
			args = args.substr(strlen(argv[1]),-1);
			args = haku::string::trim(args);
			debug_v("execcmd from cmdline: " << args);
			app.execcmd(exec_context_shell, args, NULL);			
		}
		else if ( !strcmp(argv[1],"--help") or !strcmp(argv[1],"-h") )
		{
			app.execcmd(exec_context_shell, "help", NULL);			
		}
		else
		{
			if ( argc == 2 && g_file_test(argv[1],G_FILE_TEST_IS_REGULAR) )
				args = "file://" + std::string(argv[1]);
			
			app.loaduri(args);
		}
	}
	//~ pas d'argument
	else
	{
		#if DEFAULT_SESSION_RESTORE
			app.session_restore("default");	
		#else
			app.loaduri("default");
		#endif
	}
	
	//~ boucle evenementielle
	app.mainloop();	

	return EXIT_SUCCESS;
}
Beispiel #10
0
/* faz o parsing de uma estrutura de endereço de rede. essa função é uma reposição do
   standard POSIX inet_ntop() por questoes de compatibilidade  */
const char *netcat_inet_ntop(const void *src) {
#ifdef HAVE_INET_NTOP
  static char my_buf[127];
#endif
  const char *ret;

  debug_v(("netcat_inet_ntop(src=%p)", src));

#ifdef HAVE_INET_NTOP
  ret = inet_ntop(AF_INET, src, my_buf, sizeof(my_buf));
#else
#ifdef __GNUC__
#warning Using broken network address conversion function for ntop
#endif
  ret = inet_ntoa(*(struct inaddr *)src);
#endif

  return ret;
} /* fim do netcat_inet_ntop() */
Beispiel #11
0
const char *netcat_inet_ntop(const void *src)
{
#ifdef HAVE_INET_NTOP
  static char my_buf[127];
#endif
  const char *ret;

  debug_v(("netcat_inet_ntop(src=%p)", src));

#ifdef HAVE_INET_NTOP
  /* FIXME: Since inet_ntop breaks on IPv6-mapped IPv4 addresses i'll need to
   * sort it out by myself. */
  ret = inet_ntop(AF_INET, src, my_buf, sizeof(my_buf));
#else
# ifdef __GNUC__
#  warning Using broken network address conversion function for ntop
# endif
  ret = inet_ntoa(*(struct in_addr *)src);
#endif

  return ret;
}			/* end of netcat_inet_ntop() */
Beispiel #12
0
unsigned short netcat_ports_next(nc_ports_t portsrange, unsigned short port)
{
  nc_ports_t tmp = portsrange;

  debug_v(("netcat_ports_next(): p=%p port=%hu", portsrange, port));

  if (port == 0)
    return tmp ? tmp->start : 0;

  while (tmp && ((tmp->start > port) || (tmp->end <= port)))
    tmp = tmp->next;

  if (!tmp)
    return 0;

  if (port+1 < tmp->end)
    return (port + 1);
  else if (tmp->next)
    return tmp->next->start;

  return 0;
}
Beispiel #13
0
static int core_udp_connect(nc_sock_t *ncsock)
{
  int ret, sock;
  struct sockaddr_in myaddr;
  debug_v(("core_udp_connect(ncsock=%p)", (void *)ncsock));

  sock = netcat_socket_new(PF_INET, SOCK_DGRAM);
  if (sock < 0)
    return -1;

  /* prepare myaddr for the bind() call */
  myaddr.sin_family = AF_INET;
  myaddr.sin_port = ncsock->local_port.netnum;
  memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0],
	 sizeof(myaddr.sin_addr));
  /* only call bind if it is really needed */
  if (myaddr.sin_port || myaddr.sin_addr.s_addr) {
    ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
    if (ret < 0)
      goto err;
  }

  /* now prepare myaddr for the connect() call */
  myaddr.sin_family = AF_INET;
  myaddr.sin_port = ncsock->port.netnum;
  memcpy(&myaddr.sin_addr, &ncsock->host.iaddrs[0], sizeof(myaddr.sin_addr));
  ret = connect(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
  if (ret < 0)
    goto err;

  return sock;

 err:
  close(sock);
  return -1;
}				/* end of core_udp_connect() */
Beispiel #14
0
int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave)
{
  int fd_stdin, fd_stdout, fd_sock, fd_max;
  int read_ret, write_ret;
  #ifdef  __MVS__             /* zosunix01 26.07.2011 */
  unsigned char buf[32768];
  #else
  unsigned char buf[1024]; 
  #endif 
  bool inloop = TRUE;
  fd_set ins, outs;
  struct timeval delayer;
  assert(nc_main && nc_slave);

  debug_v(("core_readwrite(nc_main=%p, nc_slave=%p)", (void *)nc_main,
	  (void *)nc_slave));

  /* set the actual input and output fds and find out the max fd + 1 */
  fd_sock = nc_main->fd;
  assert(fd_sock >= 0);

  /* if the domain is unspecified, it means that this is the standard I/O */
  if (nc_slave->domain == PF_UNSPEC) {
    fd_stdin = STDIN_FILENO;
    fd_stdout = STDOUT_FILENO;
  }
  else {
    fd_stdin = fd_stdout = nc_slave->fd;
    assert(fd_stdin >= 0);
  }
  fd_max = 1 + (fd_stdin > fd_sock ? fd_stdin : fd_sock);
  delayer.tv_sec = 0;
  delayer.tv_usec = 0;

  /* use the internal signal handler */
  signal_handler = FALSE;

  while (inloop) {
    bool call_select = TRUE;
    struct sockaddr_in recv_addr;	/* only used by UDP proto */
    unsigned int recv_len = sizeof(recv_addr);

    /* if we received an interrupt signal break this function */
    if (got_sigint) {
      got_sigint = FALSE;
      break;
    }
    /* if we received a terminating signal we must terminate */
    if (got_sigterm)
      break;

    /* reset the ins and outs events watch because some changes could happen */
    FD_ZERO(&ins);
    FD_ZERO(&outs);

    /* if the receiving queue is not empty it means that something bad is
       happening (for example the target sending queue is delaying the output
       and so requires some more time to free up. */
    if (nc_main->recvq.len == 0) {
      debug_v(("watching main sock for incoming data (recvq is empty)"));
      FD_SET(fd_sock, &ins);
    }
    else
      call_select = FALSE;

    /* same thing for the other socket */
    if (nc_slave->recvq.len == 0) { /* FIXME: call_select = false but could call it
	anyway and one of them could be set.. so what happens? */
      debug_v(("watching slave sock for incoming data (recvq is empty)"));
      if (use_stdin || (netcat_mode == NETCAT_TUNNEL))
        FD_SET(fd_stdin, &ins);
    }
    else
      call_select = FALSE;

    /* now the send queue. There are two cases in which the main sendq is not
       empty.  The first one is when we have a delayed output (-i), in which
       case the delayer is not null, and the socket is writable.  The second
       case is when the socket buffer is full, so the socket is not writable
       and the delayer is either null or set, depending on the opt_interval
       variable. */
    if (nc_main->sendq.len > 0) {
      if ((delayer.tv_sec == 0) && (delayer.tv_usec == 0)) {
	debug_v(("watching main sock for outgoing availability (there is pending data)"));
	FD_SET(fd_sock, &outs);
	call_select = TRUE;
      }
    }

    if (call_select || delayer.tv_sec || delayer.tv_usec) {
      int ret;
#ifndef USE_LINUX_SELECT
      struct timeval dd_saved;

      dd_saved.tv_sec = delayer.tv_sec;
      dd_saved.tv_usec = delayer.tv_usec;
      update_timeval(NULL);
#endif

      debug(("[select] entering with timeout=%d:%d ...", delayer.tv_sec, delayer.tv_usec));
      ret = select(fd_max, &ins, &outs, NULL,
		   (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL));

#ifndef USE_LINUX_SELECT
      delayer.tv_sec = dd_saved.tv_sec;
      delayer.tv_usec = dd_saved.tv_usec;
      update_timeval(&delayer);
#endif

      if (ret < 0) {			/* something went wrong (maybe a legal signal) */
	if (errno == EINTR)
	  goto handle_signal;
	perror("select(core_readwrite)");
	exit(EXIT_FAILURE);
      }
      else if (ret == 0) {		/* timeout expired */
	delayer.tv_sec = 0;
	delayer.tv_usec = 0;
      }

      call_select = TRUE;
      debug(("ret=%d\n", ret));
    }

    /* reading from stdin the incoming data.  The data is currently in the
       kernel's receiving queue, and in this session we move that data to our
       own receiving queue, located in the socket object.  We can be sure that
       this queue is empty now because otherwise this fd wouldn't have been
       watched. */
    if (call_select && FD_ISSET(fd_stdin, &ins)) {
      read_ret = read(fd_stdin, buf, sizeof(buf));
      debug_dv(("read(stdin) = %d", read_ret));

      if (read_ret < 0) {
	perror("read(stdin)");
	exit(EXIT_FAILURE);
      }
      else if (read_ret == 0) {
	/* when we receive EOF and this is a tunnel say goodbye, otherwise
	   it means that stdin has finished its input. */
	if ((netcat_mode == NETCAT_TUNNEL) || opt_eofclose) {
	  debug_v(("EOF Received from stdin! (exiting from loop..)"));
	  inloop = FALSE;
	}
	else {
	  debug_v(("EOF Received from stdin! (removing from lookups..)"));
	  use_stdin = FALSE;
	}
      }
      else {
	/* we can overwrite safely since if the receive queue is busy this fd
	   is not watched at all. */
        nc_slave->recvq.len = read_ret;
        nc_slave->recvq.head = NULL;
        nc_slave->recvq.pos = buf;
      }
    }

    /* for optimization reasons we have a common buffer for both receiving
       queues, because of this, handle the data now so the buffer is available
       for the other socket events. */
    if (nc_slave->recvq.len > 0) {
      nc_buffer_t *my_recvq = &nc_slave->recvq;
      nc_buffer_t *rem_sendq = &nc_main->sendq;
      debug_v(("there are %d data bytes in slave->recvq", my_recvq->len));

      /* if the remote send queue is empty, move there the entire data block */
      if (rem_sendq->len == 0) {
	debug_v(("  moved %d data bytes from slave->recvq to main->sendq", my_recvq->len));
	memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
	memset(my_recvq, 0, sizeof(*my_recvq));
      }
      else if (!my_recvq->head) {
	/* move the data block in a dedicated allocated space */
	debug_v(("  reallocating %d data bytes in slave->recvq", my_recvq->len));
	my_recvq->head = malloc(my_recvq->len);
	memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
	my_recvq->pos = my_recvq->head;
      }
    }

    /* now handle the nc_slave sendq because of the same reason as above. There
       could be a common buffer that moves around the queues, so if this is the case
       handle it so that it can be reused. If we must delay it some more, copy it
       in a dynamically allocated space. */
    if (nc_main->sendq.len > 0) {
      unsigned char *data = nc_main->sendq.pos;
      int data_len = nc_main->sendq.len;
      nc_buffer_t *my_sendq = &nc_main->sendq;

      debug_v(("there are %d data bytes in main->sendq", my_sendq->len));

      /* we have a delayed output, but at this point we might have the
         send queue pointing to a stack buffer.  In this case, allocate a
         new buffer and copy the data there for the buffered output. */
      if (opt_interval) {
	int i = 0;

	if (delayer.tv_sec || delayer.tv_usec)
	  goto skip_sect;		/* the delay is not yet over! */

	/* find the newline character.  We are going to output the first line
	   immediately while we allocate and safe the rest of the data for a
	   later output. */
	while (i < data_len)
	  if (data[i++] == '\n')
	    break;

	data_len = i;
	delayer.tv_sec = opt_interval;
      }

      write_ret = write(fd_sock, data, data_len);
      if (write_ret < 0) {
        #ifdef  __MVS__          /* zosunix01 26.07.2011                   */ 
                                 /* z/OS Unix is Unix V and here the errno */
                                 /* EWOULBBLOCK appears, if the socket is  */
                                 /* blocked.                               */
	if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
        #else
        if (errno == EAGAIN)
        #endif
	  write_ret = 0;	/* write would block, append it to select */
	else {
	  perror("write(net)");
	  exit(EXIT_FAILURE);
	}
      }

      /* FIXME: fix the below unhandled exception, and find a way to delay the
       * tries to call write(2) in case of EAGAIN, i think 100ms would be fine
       * for most systems. A too high value would not use all the bandwidth on
       * bigger installations, while a too small value would eat cpu with
       * kernel overhead. */

      bytes_sent += write_ret;		/* update statistics */
      debug_dv(("write(net) = %d (buf=%p)", write_ret, (void *)data));

      if (write_ret < data_len) {
	debug_v(("Damn! I wanted to send to sock %d bytes but it only sent %d",
		data_len, write_ret));
	data_len = write_ret;
      }

      /* if the option is set, hexdump the sent data */
      if (opt_hexdump) {
#ifndef USE_OLD_HEXDUMP
	fprintf(output_fp, "Sent %u bytes to the socket\n", write_ret);
#endif
	netcat_fhexdump(output_fp, '>', data, data_len);
      }

      /* update the queue */
      my_sendq->len -= data_len;
      my_sendq->pos += data_len;

 skip_sect:
      debug_v(("there are %d data bytes left in the queue", my_sendq->len));
      if (my_sendq->len == 0) {
	free(my_sendq->head);
	memset(my_sendq, 0, sizeof(*my_sendq));
      }
      else if (!my_sendq->head) {
	my_sendq->head = malloc(my_sendq->len);
	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
	my_sendq->pos = my_sendq->head;
      }

    }				/* end of reading from stdin section */

    /* reading from the socket (net). */
    if (call_select && FD_ISSET(fd_sock, &ins)) {
      if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) {
	memset(&recv_addr, 0, sizeof(recv_addr));
	/* this allows us to fetch packets from different addresses */
	read_ret = recvfrom(fd_sock, buf, sizeof(buf), 0,
			    (struct sockaddr *)&recv_addr, &recv_len);
	/* when recvfrom() call fails, recv_addr remains untouched */
	debug_dv(("recvfrom(net) = %d (address=%s:%d)", read_ret,
		netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port)));
      }
      else {
	/* common file read fallback */
	read_ret = read(fd_sock, buf, sizeof(buf));
	debug_dv(("read(net) = %d", read_ret));
      }

      if (read_ret < 0) {
	perror("read(net)");
	exit(EXIT_FAILURE);
      }
      else if (read_ret == 0) {
	debug_v(("EOF Received from the net"));
	inloop = FALSE;
      }
      else {
	nc_main->recvq.len = read_ret;
	nc_main->recvq.head = NULL;
	nc_main->recvq.pos = buf;
      }
    }

    /* handle net receiving queue */
    if (nc_main->recvq.len > 0) {
      nc_buffer_t *my_recvq = &nc_main->recvq;
      nc_buffer_t *rem_sendq = &nc_slave->sendq;

      /* check for telnet codes (if enabled).  Note that the buffered output
         interval does NOT apply to telnet code answers */
      if (opt_telnet)
	netcat_telnet_parse(nc_main);

      /* the telnet parsing could have returned 0 chars! */
      if (my_recvq->len > 0) {
	/* if the remote send queue is empty, move there the entire data block */
	if (rem_sendq->len == 0) {
	  memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
	  memset(my_recvq, 0, sizeof(*my_recvq));
	}
	else if (!my_recvq->head) {
	  /* move the data block in a dedicated allocated space */
	  my_recvq->head = malloc(my_recvq->len);
	  memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
	  my_recvq->pos = my_recvq->head;
	}
      }
    }

    if (nc_slave->sendq.len > 0) {
      unsigned char *data = nc_slave->sendq.pos;
      int data_len = nc_slave->sendq.len;
      nc_buffer_t *my_sendq = &nc_slave->sendq;

      write_ret = write(fd_stdout, data, data_len);
      bytes_recv += write_ret;		/* update statistics */
      debug_dv(("write(stdout) = %d", write_ret));

      if (write_ret < 0) {
	perror("write(stdout)");
	exit(EXIT_FAILURE);
      }

      /* FIXME: unhandled exception */
      assert((write_ret > 0) && (write_ret <= data_len));

      if (write_ret < data_len) {
	debug_v(("Damn! I wanted to send to stdout %d bytes but it only sent %d",
		data_len, write_ret));
	data_len = write_ret;
      }

      /* if option is set, hexdump the received data */
      if (opt_hexdump) {
#ifndef USE_OLD_HEXDUMP
	if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero)
	  fprintf(output_fp, "Received %d bytes from %s:%d\n", write_ret,
		  netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port));
	else
	  fprintf(output_fp, "Received %d bytes from the socket\n", write_ret);
#endif
	netcat_fhexdump(output_fp, '<', data, write_ret);
      }

      /* update the queue */
      my_sendq->len -= data_len;
      my_sendq->pos += data_len;

      debug_v(("there are %d data bytes left in the queue", my_sendq->len));
      if (my_sendq->len == 0) {
	free(my_sendq->head);
	memset(my_sendq, 0, sizeof(*my_sendq));
      }
      else if (!my_sendq->head) {
	my_sendq->head = malloc(my_sendq->len);
	memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
	my_sendq->pos = my_sendq->head;
      }
      
    }				/* end of reading from the socket section */

 handle_signal:			/* FIXME: i'm not sure this is the right place */
    if (got_sigusr1) {
      debug_v(("LOCAL printstats!"));
      netcat_printstats(TRUE);
      got_sigusr1 = FALSE;
    }
    continue;
  }				/* end of while (inloop) */

  /* we've got an EOF from the net, close the sockets */
  shutdown(fd_sock, SHUT_RDWR);  
  close(fd_sock);
  nc_main->fd = -1;

  /* close the slave socket only if it wasn't a simulation */
  if (nc_slave->domain != PF_UNSPEC) {
    shutdown(fd_stdin, SHUT_RDWR);
    close(fd_stdin);
    nc_slave->fd = -1;
  }

  /* restore the extarnal signal handler */
  signal_handler = TRUE;

  return 0;
}				/* end of core_readwrite() */
Beispiel #15
0
static int core_tcp_listen(nc_sock_t *ncsock)
{
  int sock_listen, sock_accept, timeout = ncsock->timeout;
  debug_v(("core_tcp_listen(ncsock=%p)", (void *)ncsock));

  sock_listen = netcat_socket_new_listen(PF_INET, &ncsock->local_host.iaddrs[0],
			ncsock->local_port.netnum);
  if (sock_listen < 0)
    ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
	    _("Couldn't setup listening socket (err=%d)"), sock_listen);

  /* if the port was set to 0 this means that it is assigned randomly by the
     OS.  Find out which port they assigned to us. */
  if (ncsock->local_port.num == 0) {
    int ret;
    struct sockaddr_in myaddr;
    unsigned int myaddr_len = sizeof(myaddr);

    ret = getsockname(sock_listen, (struct sockaddr *)&myaddr, &myaddr_len);
    if (ret < 0) {
      close(sock_listen);
      return -1;
    }
    netcat_getport(&ncsock->local_port, NULL, ntohs(myaddr.sin_port));
  }

  ncprint(NCPRINT_VERB2, _("Listening on %s"),
	netcat_strid(&ncsock->local_host, &ncsock->local_port));
  while (TRUE) {
    struct sockaddr_in my_addr;
    unsigned int my_len = sizeof(my_addr);	/* this *IS* socklen_t */

    sock_accept = netcat_socket_accept(sock_listen, timeout);
    /* reset the timeout to the "use remaining time" value (see network.c file)
       if it exited with timeout we also return this function, so losing the
       original value is not a bad thing. */
    timeout = -1;

    /* failures in netcat_socket_accept() cause this function to return */
    if (sock_accept < 0)
      return -1;

    /* FIXME: i want a library function like netcat_peername() that fetches it
       and resolves with netcat_resolvehost(). */
    getpeername(sock_accept, (struct sockaddr *)&my_addr, &my_len);

    /* if a remote address (and optionally some ports) have been specified we
       assume it as the only ip and port that it is allowed to connect to
       this socket */

    if ((ncsock->host.iaddrs[0].s_addr && memcmp(&ncsock->host.iaddrs[0],
	 &my_addr.sin_addr, sizeof(ncsock->host.iaddrs[0]))) ||
	(netcat_flag_count() && !netcat_flag_get(ntohs(my_addr.sin_port)))) {
      ncprint(NCPRINT_VERB2, _("Unwanted connection from %s:%hu (refused)"),
	      netcat_inet_ntop(&my_addr.sin_addr), ntohs(my_addr.sin_port));
      goto refuse;
    }
    ncprint(NCPRINT_VERB1, _("Connection from %s:%hu"),
	    netcat_inet_ntop(&my_addr.sin_addr), ntohs(my_addr.sin_port));

    /* with zero I/O mode we don't really accept any connection */
    if (opt_zero)
      goto refuse;

    /* we have got our socket, now exit the loop */
    break;

 refuse:
    shutdown(sock_accept, 2);
    close(sock_accept);
    continue;
  }			/* end of infinite accepting loop */

  /* we don't need a listening socket anymore */
  close(sock_listen);
  return sock_accept;
}				/* end of core_tcp_listen() */
Beispiel #16
0
static int core_tcp_connect(nc_sock_t *ncsock)
{
  int ret, sock, timeout = ncsock->timeout;
  struct timeval timest;
  fd_set outs;
  debug_v(("core_tcp_connect(ncsock=%p)", (void *)ncsock));

  /* since we are nonblocking now, we could start as many connections as we
     want but it's not a great idea connecting more than one host at time.
     Also don't specify the local address if it's not really needed, so we can
     avoid one bind(2) call. */
  sock = netcat_socket_new_connect(PF_INET, SOCK_STREAM,
	&ncsock->host.iaddrs[0], ncsock->port.netnum,
	(ncsock->local_host.iaddrs[0].s_addr ? &ncsock->local_host.iaddrs[0] :
	NULL), ncsock->local_port.netnum);

  #ifdef __MVS__   /* 01.08.2011 zosunix01                                */
                   /* The new retcode shows, that the destination host has*/
                   /* rejected the connect. The function doesn't finish   */
                   /* the main program, but ends with the retcode -1 to   */ 
                   /* indicate a failure.                                 */
  if (sock == -6) {
   return -1;
  }
  #endif

  if (sock < 0)
    ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Couldn't create connection (err=%d): %s",
	    sock, strerror(errno)); 

  /* initialize select()'s variables */
  FD_ZERO(&outs);
  FD_SET(sock, &outs);
  timest.tv_sec = timeout;
  timest.tv_usec = 0;

  ret = select(sock + 1, NULL, &outs, NULL, (timeout > 0 ? &timest : NULL));
  if (ret > 0) {
    int ret, get_ret;
    unsigned int get_len = sizeof(get_ret);	/* socklen_t */

    /* ok, select([single]), so sock must have triggered this */
    assert(FD_ISSET(sock, &outs));

    /* fetch the errors of the socket and handle system request errors */
    ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &get_ret, &get_len);
    if (ret < 0)
      ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Critical system request failed: %s",
	      strerror(errno));

    /* POSIX says that SO_ERROR expects an int, so my_len must be untouched */
    assert(get_len == sizeof(get_ret));

    /* FIXME: the error Broken Pipe should probably not stop here */
    debug_v(("Connection returned errcode=%d (%s)", get_ret, strerror(get_ret)));
    if (get_ret > 0) {
      char tmp;

      /* Ok, select() returned a write event for this socket AND getsockopt()
         said that some error happened.  This mean that EOF is expected. */
      ret = read(sock, &tmp, 1);
      #ifdef __MVS__  /* zosunix01 27.07.2011                          */
                      /* In z/OS Unix the socket is closed in the case */
                      /* of a connection error                         */
      if(!((ret == -1) && ((errno == EAGAIN) || (errno == ENOTCONN)))) {
       assert(ret == 0);
      }
      #else
      assert(ret == 0); /* for systems other than z/OS Unix */
      #endif
      /* FIXME: see the TODO entry about false error detection */

      shutdown(sock, 2);
      close(sock);
      ncsock->fd = -1;
      errno = get_ret;		/* value returned by getsockopt(SO_ERROR) */
      return -1;
    }

    /* everything went fine, we have the socket */
    ncprint(NCPRINT_VERB1, _("%s open"), netcat_strid(&ncsock->host,
						      &ncsock->port));
    return sock;
  }
  else if (ret) {
    /* Terminated by a signal. Silently exit */
    if (errno == EINTR)
      exit(EXIT_FAILURE);
    /* The error seems to be a little worse */
    ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Critical system request failed: %s",
	    strerror(errno));
  }

  /* select returned 0, this means connection timed out for our timing
     directives (in fact the socket has a longer timeout usually, so we need
     to abort the connection try, set the proper errno and return */
  shutdown(sock, 2);
  close(sock);
  errno = ETIMEDOUT;
  return -1;
}				/* end of core_tcp_connect() */
Beispiel #17
0
static int core_udp_listen(nc_sock_t *ncsock)
{
  int ret, *sockbuf, sock, sock_max, timeout = ncsock->timeout;
  bool need_udphelper = TRUE;
#ifdef USE_PKTINFO
  int sockopt = 1;
#endif
  struct sockaddr_in myaddr;
  struct timeval tt;		/* needed by the select() call */
  debug_v(("core_udp_listen(ncsock=%p)", (void *)ncsock));

#ifdef USE_PKTINFO
  need_udphelper = FALSE;
#else
  /* if we need a specified source address then go straight to it */
  if (ncsock->local_host.iaddrs[0].s_addr)
    need_udphelper = FALSE;
#endif

  if (!need_udphelper) {
    /* simulates a udphelper_sockets_open() call */
    sockbuf = calloc(2, sizeof(int));
    sockbuf[0] = 1;
    sockbuf[1] = sock = netcat_socket_new(PF_INET, SOCK_DGRAM);
  }
#ifndef USE_PKTINFO
  else
    sock = udphelper_sockets_open(&sockbuf, ncsock->local_port.netnum);
#endif
  if (sock < 0)
    goto err;

  /* we know that udphelper_sockets_open() returns the highest socket, and
     if we didn't call it we have just one socket */
  sock_max = sock + 1;

  if (!need_udphelper) {
    /* prepare myaddr for the bind() call */
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = ncsock->local_port.netnum;
    memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0],
	   sizeof(myaddr.sin_addr));
    /* bind() MUST be called in this function, since it's the final call for
       this type of socket. FIXME: I heard that UDP port 0 is illegal. true? */
    ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
    if (ret < 0)
      goto err;
  }

#ifdef USE_PKTINFO
  /* set the right flag in order to obtain the ancillary data */
  ret = setsockopt(sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof(sockopt));
  if (ret < 0)
    goto err;
#endif

  /* if the port was set to 0 this means that it is assigned randomly by the
     OS.  Find out which port they assigned to us. */
  if (ncsock->local_port.num == 0) {
    struct sockaddr_in get_myaddr;
    unsigned int get_myaddr_len = sizeof(get_myaddr);

    ret = getsockname(sock, (struct sockaddr *)&get_myaddr, &get_myaddr_len);
    if (ret < 0)
      goto err;
    netcat_getport(&ncsock->local_port, NULL, ntohs(get_myaddr.sin_port));
    assert(ncsock->local_port.num != 0);
  }

  if (!need_udphelper)
    ncprint(NCPRINT_VERB2, _("Listening on %s"),
	    netcat_strid(&ncsock->local_host, &ncsock->local_port));
  else
    ncprint(NCPRINT_VERB2, _("Listening on %s (using %d sockets)"),
	    netcat_strid(&ncsock->local_host, &ncsock->local_port), sockbuf[0]);

  /* since this protocol is connectionless, we need a special handling here.
     We want to simulate a two-ends connection but in order to do this we need
     a remote address and a local address (in case we bound to INADDR_ANY).
     Wait here until a packet is received, and use its source and destination
     addresses as default endpoints.  If we have the zero-I/O option set, we
     just eat the packet and return when timeout is elapsed (maybe never). */
  tt.tv_sec = timeout;
  tt.tv_usec = 0;

  while (TRUE) {
    int socks_loop;
    fd_set ins;

    FD_ZERO(&ins);
    for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) {
      debug_v(("Setting sock %d on ins", sockbuf[socks_loop]));
      FD_SET(sockbuf[socks_loop], &ins);
    }

    /* automatically use remaining timeout time if in zero-I/O mode */
    ret = select(sock_max, &ins, NULL, NULL, (timeout > 0 ? &tt : NULL));
    if (ret == 0)
      break;

    /* loop all the open sockets to find the active one */
    for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) {
      int recv_ret, write_ret;
      struct msghdr my_hdr;
      #ifdef  __MVS__             /* zosunix01 26.07.2011 */
      unsigned char buf[32768];
      #else
      unsigned char buf[1024]; 
      #endif 
      struct iovec my_hdr_vec;
      struct sockaddr_in rem_addr;
      struct sockaddr_in local_addr;
#ifdef USE_PKTINFO
      unsigned char anc_buf[512];
#endif

      sock = sockbuf[socks_loop];

      if (!FD_ISSET(sock, &ins))
	continue;

      /* I've looked for this code for a lot of hours, and finally found the
         RFC 2292 which provides a socket API for fetching the destination
         interface of the incoming packet. */
      memset(&my_hdr, 0, sizeof(my_hdr));
      memset(&rem_addr, 0, sizeof(rem_addr));
      memset(&local_addr, 0, sizeof(local_addr));
      my_hdr.msg_name = (void *)&rem_addr;
      my_hdr.msg_namelen = sizeof(rem_addr);
      /* initialize the vector struct and then the vectory member of the header */
      my_hdr_vec.iov_base = buf;
      my_hdr_vec.iov_len = sizeof(buf);
      my_hdr.msg_iov = &my_hdr_vec;
      my_hdr.msg_iovlen = 1;
#ifdef USE_PKTINFO
      /* now the core part for the IP_PKTINFO support: the ancillary data */
      my_hdr.msg_control = anc_buf;
      my_hdr.msg_controllen = sizeof(anc_buf);
#endif

      /* now check the remote address.  If we are simulating a routing then
         use the MSG_PEEK flag, which leaves the received packet untouched */
      recv_ret = recvmsg(sock, &my_hdr, (opt_zero ? 0 : MSG_PEEK));

      debug_v(("received packet from %s:%d%s", netcat_inet_ntop(&rem_addr.sin_addr),
		ntohs(rem_addr.sin_port), (opt_zero ? "" : ", using as default dest")));

#ifdef USE_PKTINFO
      ret = udphelper_ancillary_read(&my_hdr, &local_addr);
      local_addr.sin_port = myaddr.sin_port;
      local_addr.sin_family = myaddr.sin_family;
#else
      ret = sizeof(local_addr);
      ret = getsockname(sock, (struct sockaddr *)&local_addr, &ret);
#endif

      if (ret == 0) {
	char tmpbuf[127];

	strncpy(tmpbuf, netcat_inet_ntop(&rem_addr.sin_addr), sizeof(tmpbuf));
	ncprint(NCPRINT_VERB1, _("Received packet from %s:%d -> %s:%d (local)"),
		tmpbuf, ntohs(rem_addr.sin_port),
		netcat_inet_ntop(&local_addr.sin_addr),
		ntohs(local_addr.sin_port));
      }
      else
	ncprint(NCPRINT_VERB1, _("Received packet from %s:%d"),
		netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port));

      if (opt_zero) {		/* output the packet right here right now */
	write_ret = write(STDOUT_FILENO, buf, recv_ret);
	bytes_recv += write_ret;
	debug_dv(("write_u(stdout) = %d", write_ret));

	if (write_ret < 0) {
	  perror("write_u(stdout)");
	  exit(EXIT_FAILURE);
	}

	/* FIXME: unhandled exception */
	assert(write_ret == recv_ret);

	/* if the hexdump option is set, hexdump the received data */
	if (opt_hexdump) {
#ifndef USE_OLD_HEXDUMP
	  fprintf(output_fp, "Received %d bytes from %s:%d\n", recv_ret,
		netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port));
#endif
	  netcat_fhexdump(output_fp, '<', buf, write_ret);
	}
      }
      else {
#ifdef USE_PKTINFO
	nc_sock_t dup_socket;

	memset(&dup_socket, 0, sizeof(dup_socket));
	dup_socket.domain = ncsock->domain;
	dup_socket.proto = ncsock->proto;
	memcpy(&dup_socket.local_host.iaddrs[0], &local_addr.sin_addr,
	       sizeof(local_addr));
	memcpy(&dup_socket.host.iaddrs[0], &rem_addr.sin_addr,
	       sizeof(local_addr));
	dup_socket.local_port.netnum = local_addr.sin_port;
	dup_socket.local_port.num = ntohs(local_addr.sin_port);
	dup_socket.port.netnum = rem_addr.sin_port;
	dup_socket.port.num = ntohs(rem_addr.sin_port);
	/* copy the received data in the socket's queue */
	ncsock->recvq.len = recv_ret;
	ncsock->recvq.head = ncsock->recvq.pos = malloc(recv_ret);
	memcpy(ncsock->recvq.head, my_hdr_vec.iov_base, recv_ret);
	/* FIXME: this ONLY saves the first 1024 bytes! and the others? */
#else
	ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr));
	if (ret < 0)
	  goto err;

	/* remove this socket from the array in order not to get it closed */
	sockbuf[socks_loop] = -1;
#endif
	udphelper_sockets_close(sockbuf);

#ifdef USE_PKTINFO
	/* this is all we want from this function */
	debug_dv(("calling the udp_connect() function..."));
	return core_udp_connect(&dup_socket);
#else
	return sock;
#endif
      }
    }				/* end of foreach (sock, sockbuf) */
  }				/* end of packet receiving loop */

  /* no packets until timeout, set errno and proceed to general error handling */
  errno = ETIMEDOUT;

 err:
  udphelper_sockets_close(sockbuf);
  return -1;
}				/* end of core_udp_listen() */
Beispiel #18
0
bool netcat_resolvehost(nc_host_t *dst, const char *name)
{
  int i;
  struct hostent *hostent;
  struct in_addr res_addr;
#ifdef USE_IPV6
  struct in6_addr res6_addr;
#endif

  assert(name && name[0]);
  debug_v(("netcat_resolvehost(dst=%p, name=\"%s\")", (void *)dst, name));

  /* reset all fields of the dst struct */
  memset(dst, 0, sizeof(*dst));

  /* try to see if `name' is a numeric address, in case try reverse lookup */
  if (netcat_inet_pton(AF_INET, name, &res_addr)) {
    memcpy(&dst->host.iaddrs[0], &res_addr, sizeof(dst->host.iaddrs[0]));
    strncpy(dst->host.addrs[0], netcat_inet_ntop(AF_INET, &res_addr), sizeof(dst->host.addrs[0]));

    /* if opt_numeric is set or we don't require verbosity, we are done */
    if (opt_numeric)
      return TRUE;

    /* failures to look up a PTR record are *not* considered fatal */
    hostent = gethostbyaddr((char *)&res_addr, sizeof(res_addr), AF_INET);
    if (!hostent)
      ncprint(NCPRINT_VERB2 | NCPRINT_WARNING,
	      _("Inverse name lookup failed for `%s'"), name);
    else {
      strncpy(dst->host.name, hostent->h_name, MAXHOSTNAMELEN - 2);
      /* now do the direct lookup to see if the PTR was authoritative */
      hostent = gethostbyname(dst->host.name);

      /* Any kind of failure in this section results in a host not auth
         warning, and the dst->host.name field cleaned (I don't care if there is a
         PTR, if it's unauthoritative). */
      if (!hostent || !hostent->h_addr_list[0]) {
	ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
		_("Host %s isn't authoritative! (direct lookup failed)"),
		dst->host.addrs[0]);
	goto check_failed;
      }
      for (i = 0; hostent->h_addr_list[i] && (i < MAXINETADDRS); i++)
	if (!memcmp(&dst->host.iaddrs[0], hostent->h_addr_list[i],
		    sizeof(dst->host.iaddrs[0])))
	  return TRUE;		/* resolving verified, it's AUTH */

      ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
	      _("Host %s isn't authoritative! (direct lookup mismatch)"),
	      dst->host.addrs[0]);
      ncprint(NCPRINT_VERB1, _("  %s -> %s  BUT  %s -> %s"),
	      dst->host.addrs[0], dst->host.name, dst->host.name,
	      netcat_inet_ntop(AF_INET, hostent->h_addr_list[0]));

 check_failed:
      memset(dst->host.name, 0, sizeof(dst->host.name));
    }				/* if hostent */
  }
#ifdef USE_IPV6
  /* same as above, but check for an IPv6 address notation */
  else if (netcat_inet_pton(AF_INET6, name, &res6_addr)) {
    memcpy(&dst->host6.iaddrs[0], &res6_addr, sizeof(dst->host6.iaddrs[0]));
    strncpy(dst->host6.addrs[0], netcat_inet_ntop(AF_INET6, &res_addr), sizeof(dst->host6.addrs[0]));

    /* if opt_numeric is set or we don't require verbosity, we are done */
    if (opt_numeric)
      return TRUE;
  }
#endif
  else {			/* couldn't translate: it must be a name! */
    bool host_auth_taken = FALSE;

    /* if the opt_numeric option is set, we must not use DNS in any way */
    if (opt_numeric)
      return FALSE;

    /* failures to look up a name are reported to the calling function */
    if (!(hostent = gethostbyname(name)))
      return FALSE;

    /* now I need to handle the host aliases (CNAME).  If we lookup host
       www.bighost.foo, which is an alias for www.bighost.mux.foo, the hostent
       struct will contain the real name in h_name, which is not what we want
       for the output purpose (the user doesn't want to see something he didn't
       type.  So assume the lookup name as the "official" name and fetch the
       ips for the reverse lookup. */
    debug(("(lookup) lookup=\"%s\" official=\"%s\" (should match)\n", name,
	  hostent->h_name));
    strncpy(dst->host.name, name, MAXHOSTNAMELEN - 1);

    /* now save all the available ip addresses (no more than MAXINETADDRS) */
    for (i = 0; hostent->h_addr_list[i] && (i < MAXINETADDRS); i++) {
      memcpy(&dst->host.iaddrs[i], hostent->h_addr_list[i], sizeof(dst->host.iaddrs[0]));
      strncpy(dst->host.addrs[i], netcat_inet_ntop(AF_INET, &dst->host.iaddrs[i]),
	      sizeof(dst->host.addrs[0]));
    }				/* end of foreach addr, part A */

    /* for speed purposes, skip the authoritative checking if we haven't got
       any verbosity level set.  note that this will cause invalid results
       in the dst struct, but we don't care at this point. (FIXME: ?) */
    if (!is_logging_enabled())
      return TRUE;

    /* do inverse lookups in a separated loop for each collected addresses */
    for (i = 0; dst->host.iaddrs[i].s_addr && (i < MAXINETADDRS); i++) {
      hostent = gethostbyaddr((char *)&dst->host.iaddrs[i], sizeof(dst->host.iaddrs[0]),
			      AF_INET);

      if (!hostent || !hostent->h_name) {
	ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
		_("Inverse name lookup failed for `%s'"), dst->host.addrs[i]);
	continue;
      }

      /* now the case.  hostnames aren't case sensitive because of this we may
         find a different case for the authoritative hostname.  For the same
         previous reason we may want to keep the user typed case, but this time
         we are going to override it because this tool is a "network exploration
         tool", thus it's good to see the case they chose for this host. */
      if (strcasecmp(dst->host.name, hostent->h_name)) {
	int xcmp;
	char savedhost[MAXHOSTNAMELEN];

	/* refering to the flowchart (see the drafts directory contained in
	   this package), try to guess the real hostname */
	strncpy(savedhost, hostent->h_name, sizeof(savedhost));
	savedhost[sizeof(savedhost) - 1] = 0;

	/* ok actually the given host and the reverse-resolved address doesn't
	   match, so try to see if we can find the real machine name.  In order to
	   this to happen the originally found address must match with the newly
	   found hostname directly resolved.  If this doesn't, or if this resolve
	   fails, then fall back to the original warning message: they have a DNS
	   misconfigured! */
	hostent = gethostbyname(savedhost);
	if (!hostent)
	  continue;		/* FIXME: missing information analysis */

	for (xcmp = 0; hostent->h_addr_list[xcmp] &&
		(xcmp < MAXINETADDRS); xcmp++) {
	  if (!memcmp(&dst->host.iaddrs[i], hostent->h_addr_list[xcmp],
		     sizeof(dst->host.iaddrs[0])))
	    goto found_real_host;
	}

	ncprint(NCPRINT_WARNING | NCPRINT_VERB1,
		_("This host's reverse DNS doesn't match! %s -- %s"),
		hostent->h_name, dst->host.name);
	continue;

 found_real_host:
	ncprint(NCPRINT_NOTICE | NCPRINT_VERB2,
		_("Real hostname for %s [%s] is %s"),
		dst->host.name, dst->host.addrs[i], savedhost);
	continue;
      }
      else if (!host_auth_taken) {	/* case: take only the first one as auth */
	strncpy(dst->host.name, hostent->h_name, sizeof(dst->host.name));
	host_auth_taken = TRUE;
      }
    }				/* end of foreach addr, part B */
  }

  return TRUE;
}
Beispiel #19
0
int main(int argc, char *argv[])
{
  int c, glob_ret = EXIT_FAILURE;
  int total_ports, left_ports, accept_ret = -1, connect_ret = -1;
  struct sigaction sv;
  nc_port_t local_port;		/* local port specified with -p option */
  nc_host_t local_host;		/* local host for bind()ing operations */
  nc_host_t remote_host;
  nc_sock_t listen_sock;
  nc_sock_t connect_sock;
  nc_sock_t stdio_sock;
  nc_ports_t old_flag = NULL;

  memset(&local_port, 0, sizeof(local_port));
  memset(&local_host, 0, sizeof(local_host));
  memset(&remote_host, 0, sizeof(remote_host));
  memset(&listen_sock, 0, sizeof(listen_sock));
  memset(&connect_sock, 0, sizeof(connect_sock));
  memset(&stdio_sock, 0, sizeof(stdio_sock));
  listen_sock.domain = NETCAT_DOMAIN_IPV4;
  connect_sock.domain = NETCAT_DOMAIN_IPV4;

#ifdef ENABLE_NLS
  setlocale(LC_MESSAGES, "");
  bindtextdomain(PACKAGE, LOCALEDIR);
  textdomain(PACKAGE);
#endif

  /* set up the signal handling system */
  sigemptyset(&sv.sa_mask);
  sv.sa_flags = 0;
  sv.sa_handler = got_int;
  sigaction(SIGINT, &sv, NULL);
  sv.sa_handler = got_term;
  sigaction(SIGTERM, &sv, NULL);
  sv.sa_handler = got_usr1;
  sigaction(SIGUSR1, &sv, NULL);
  /* ignore some boring signals */
  sv.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &sv, NULL);
  sigaction(SIGURG, &sv, NULL);

  /* if no args given at all, take them from stdin and generate argv */
  if (argc == 1)
    netcat_commandline_read(&argc, &argv);

  /* check for command line switches */
  while (TRUE) {
    int option_index = 0;
    static const struct option long_options[] = {
	{ "close",	no_argument,		NULL, 'c' },
	{ "debug",	no_argument,		NULL, 'd' },
	{ "exec",	required_argument,	NULL, 'e' },
	{ "gateway",	required_argument,	NULL, 'g' },
	{ "pointer",	required_argument,	NULL, 'G' },
	{ "help",	no_argument,		NULL, 'h' },
	{ "interval",	required_argument,	NULL, 'i' },
	{ "ipv4",	no_argument,		NULL, '4' },
	{ "ipv6",	no_argument,		NULL, '6' },
	{ "listen",	no_argument,		NULL, 'l' },
	{ "tunnel",	required_argument,	NULL, 'L' },
	{ "dont-resolve", no_argument,		NULL, 'n' },
	{ "convert",	required_argument,	NULL, 'N' }, /* FIXME: proposal: A Ascii? */
	{ "output",	required_argument,	NULL, 'o' },
	{ "local-port",	required_argument,	NULL, 'p' },
	{ "tunnel-port", required_argument,	NULL, 'P' },
	{ "randomize",	no_argument,		NULL, 'r' },
	{ "source",	required_argument,	NULL, 's' },
	{ "tunnel-source", required_argument,	NULL, 'S' },
#ifndef USE_OLD_COMPAT
	{ "tcp",	no_argument,		NULL, 't' },
	{ "telnet",	no_argument,		NULL, 'T' },
#else
	{ "tcp",	no_argument,		NULL, 1 },
	{ "telnet",	no_argument,		NULL, 't' },
#endif
	{ "udp",	no_argument,		NULL, 'u' },
	{ "verbose",	no_argument,		NULL, 'v' },
	{ "version",	no_argument,		NULL, 'V' },
	{ "hexdump",	no_argument,		NULL, 'x' },
	{ "wait",	required_argument,	NULL, 'w' },
	{ "zero",	no_argument,		NULL, 'z' },
	{ 0, 0, 0, 0 }
    };

    c = getopt_long(argc, argv, "46cde:g:G:hi:lL:no:p:P:rs:S:tTuvVxw:z",
		    long_options, &option_index);
    if (c == -1)
      break;

    switch (c) {
    case '4':			/* don't use IPv6 protocol */
      opt_domain = NETCAT_DOMAIN_IPV4;
      break;
    case '6':			/* use IPv6 protocol */
      opt_domain = NETCAT_DOMAIN_IPV6;
      break;
    case 'c':			/* close connection on EOF from stdin */
      opt_eofclose = TRUE;
      break;
    case 'd':			/* enable debugging */
      opt_debug = TRUE;
      break;
    case 'e':			/* prog to exec */
      if (opt_exec)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Cannot specify `-e' option double"));
      opt_exec = strdup(optarg);
      break;
    case 'G':			/* srcrt gateways pointer val */
      break;
    case 'g':			/* srcroute hops */
      break;
    case 'h':			/* display help and exit */
      netcat_printhelp(argv[0]);
      exit(EXIT_SUCCESS);
    case 'i':			/* line/ports interval time (seconds) */
      opt_interval = atoi(optarg);
      if (opt_interval < 0)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Invalid interval time \"%s\""), optarg);
      break;
    case 'l':			/* mode flag: listen mode */
      if (netcat_mode != NETCAT_UNSPEC)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("You can specify mode flags (`-l' and `-L') only once"));
      netcat_mode = NETCAT_LISTEN;
      break;
    case 'L':			/* mode flag: tunnel mode */
      if (netcat_mode != NETCAT_UNSPEC)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("You can specify mode flags (`-l' and `-L') only once"));
      if (opt_zero)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("`-L' and `-z' options are incompatible"));
      do {
	char *div, *p, *pbuf = strdup(optarg);

	div = p = pbuf;
	/* if the address has '[' unbalanced, threat is as plain address */
	if (div[0] == '[') {
	  div = strchr(div, ']');
	  if (div != NULL) {
	    *div++ = '\0';
	    p++;				/* skip the '[' */
	  }
	}
	div = strchr(div, ':');

	if (div && *(div + 1))
	  *div++ = '\0';
	else {
	  ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		  _("Invalid target string for `-L' option"));
	}

	/* lookup the remote address and the remote port for tunneling */
	if (!netcat_resolvehost(&connect_sock.remote, optarg))
	  ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		  _("Couldn't resolve tunnel target host: %s"), optarg);
	if (!netcat_getport(&connect_sock.port, div, 0))
	  ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		  _("Invalid tunnel target port: %s"), div);

	/* takes the options configured so far as they may change */
	connect_sock.domain = opt_domain;
	connect_sock.proto = opt_proto;
	connect_sock.timeout = opt_wait;
	netcat_mode = NETCAT_TUNNEL;
      } while (FALSE);
      break;
    case 'N':			/* ascii line ends conversion, use with care */
      if (!strcasecmp(optarg, "none"))
	opt_ascii_conversion = NETCAT_CONVERT_NONE;
      else if (!strcasecmp(optarg, "crlf"))
	opt_ascii_conversion = NETCAT_CONVERT_CRLF;
      else if (!strcasecmp(optarg, "cr"))
	opt_ascii_conversion = NETCAT_CONVERT_CR;
      else if (!strcasecmp(optarg, "lf"))
	opt_ascii_conversion = NETCAT_CONVERT_LF;
      else {
	ncprint(NCPRINT_NORMAL, _("Conversion must be one of: none crlf cr lf"));
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Invalid conversion specified: %s"), optarg);
      }
      break;
    case 'n':			/* numeric-only, no DNS lookups */
      opt_numeric = TRUE;
      break;
    case 'o':			/* output hexdump log to file */
      opt_outputfile = strdup(optarg);
      opt_hexdump = TRUE;	/* implied */
      break;
    case 'p':			/* local source port */
      if (!netcat_getport(&local_port, optarg, 0))
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid local port: %s"),
		optarg);
      break;
    case 'P':			/* used only in tunnel mode (source port) */
      if (!netcat_getport(&connect_sock.local_port, optarg, 0))
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Invalid tunnel connect port: %s"), optarg);
      break;
    case 'r':			/* randomize various things */
      opt_random = TRUE;
      break;
    case 's':			/* local source address */
      /* lookup the source address and assign it to the connection address */
      if (!netcat_resolvehost(&local_host, optarg))
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Couldn't resolve local host: %s"), optarg);
      break;
    case 'S':			/* used only in tunnel mode (source ip) */
      if (!netcat_resolvehost(&connect_sock.local, optarg))
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("Couldn't resolve tunnel local host: %s"), optarg);
      break;
    case 1:			/* use TCP protocol (default) */
#ifndef USE_OLD_COMPAT
    case 't':
#endif
      opt_proto = NETCAT_PROTO_TCP;
      break;
#ifdef USE_OLD_COMPAT
    case 't':
#endif
    case 'T':			/* answer telnet codes */
      opt_telnet = TRUE;
      break;
    case 'u':			/* use UDP protocol */
      opt_proto = NETCAT_PROTO_UDP;
      break;
    case 'v':			/* be verbose (twice=more verbose) */
      opt_verbose++;
      break;
    case 'V':			/* display version and exit */
      netcat_printversion();
      exit(EXIT_SUCCESS);
    case 'w':			/* wait time (in seconds), 0 means no timeout */
      opt_wait = atoi(optarg);
      if (opt_wait < 0)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid wait-time: %s"),
		optarg);
      break;
    case 'x':			/* hexdump traffic */
      opt_hexdump = TRUE;
      break;
    case 'z':			/* little or no data xfer */
      if (netcat_mode == NETCAT_TUNNEL)
	ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("`-L' and `-z' options are incompatible"));
      opt_zero = TRUE;
      break;
    default:
      ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
    }
  }

  if (opt_zero && opt_exec)
    ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
		_("`-e' and `-z' options are incompatible"));

  /* initialize the flag buffer to keep track of the specified ports */
  //netcat_flag_init(65535);
  old_flag = netcat_ports_init();

#ifndef DEBUG
  /* check for debugging support */
  if (opt_debug)
    ncprint(NCPRINT_WARNING,
	    _("Debugging support not compiled, option `-d' discarded. Using maximum verbosity."));
#endif

  /* randomize only if needed */
  if (opt_random)
#ifdef USE_RANDOM
    SRAND(time(0));
#else
    ncprint(NCPRINT_WARNING,
	    _("Randomization support not compiled, option `-r' discarded."));
#endif

  /* handle the -o option. exit on failure */
  if (opt_outputfile) {
    output_fp = fopen(opt_outputfile, "w");
    if (!output_fp)
      ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Failed to open output file: %s (%s)"),
	      opt_outputfile, strerror(errno));
  }
  else
    output_fp = stderr;

  /* FIXME: now we can resolve special hostnames */

  debug_v(("Trying to parse non-args parameters (argc=%d, optind=%d)", argc,
	  optind));

  /* try to get an hostname parameter */
  if (optind < argc) {
    const char *get_host = argv[optind++];
    if (!netcat_resolvehost(&remote_host, get_host))
      ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't resolve host \"%s\""),
	      get_host);
  }

  /* now loop all the other (maybe optional) parameters for port-ranges */
  while (optind < argc) {
    const char *get_argv = argv[optind++];
    char *q, *parse = strdup(get_argv);
    int port_lo = 0, port_hi = 65535;
    nc_port_t port_tmp;

    if (!(q = strchr(parse, '-')))	/* simple number? */
      q = strchr(parse, ':');		/* try with the other separator */

    if (!q) {
      if (netcat_getport(&port_tmp, parse, 0))
	netcat_ports_insert(old_flag, port_tmp.num, port_tmp.num);
      else
	goto got_err;
    }
    else {		/* could be in the forms: N1-N2, -N2, N1- */
      *q++ = 0;
      if (*parse) {
	if (netcat_getport(&port_tmp, parse, 0))
	  port_lo = port_tmp.num;
	else
	  goto got_err;
      }
      if (*q) {
	if (netcat_getport(&port_tmp, q, 0))
	  port_hi = port_tmp.num;
	else
	  goto got_err;
      }
      if (!*parse && !*q)		/* don't accept the form '-' */
	goto got_err;

      netcat_ports_insert(old_flag, port_lo, port_hi);
    }

    free(parse);
    continue;

 got_err:
    free(parse);
    ncprint(NCPRINT_ERROR, _("Invalid port specification: %s"), get_argv);
    exit(EXIT_FAILURE);
  }

  debug_dv(("Arguments parsing complete! Total ports=%d", netcat_ports_count(old_flag)));
#if 0
  /* pure debugging code */
  c = 0;
  while ((c = netcat_ports_next(old_flag, c))) {
    printf("Got port=%d\n", c);
  }
  exit(0);
#endif

  /* Handle listen mode and tunnel mode (whose index number is higher) */
  if (netcat_mode > NETCAT_CONNECT) {
    /* in tunnel mode the opt_zero flag is illegal, while on listen mode it
       means that no connections should be accepted.  For UDP it means that
       no remote addresses should be used as default endpoint, which means
       that we can't send anything.  In both situations, stdin is no longer
       useful, so close it. */
    if (opt_zero) {
      close(STDIN_FILENO);
      use_stdin = FALSE;
    }

    /* prepare the socket var and start listening */
    listen_sock.proto = opt_proto;
    listen_sock.timeout = opt_wait;
    memcpy(&listen_sock.local, &local_host, sizeof(listen_sock.local));
    memcpy(&listen_sock.local_port, &local_port, sizeof(listen_sock.local_port));
    memcpy(&listen_sock.remote, &remote_host, sizeof(listen_sock.remote));
    accept_ret = core_listen(&listen_sock);

    /* in zero I/O mode the core_tcp_listen() call will always return -1
       (ETIMEDOUT) since no connections are accepted, because of this our job
       is completed now. */
    if (accept_ret < 0) {
      /* since i'm planning to make `-z' compatible with `-L' I need to check
         the exact error that caused this failure. */
      if (opt_zero && (errno == ETIMEDOUT))
	exit(0);

      ncprint(NCPRINT_VERB1 | NCPRINT_EXIT, _("Listen mode failed: %s"),
	      strerror(errno));
    }

    /* if we are in listen mode, run the core loop and exit when it returns.
       otherwise now it's the time to connect to the target host and tunnel
       them together (which means passing to the next section. */
    if (netcat_mode == NETCAT_LISTEN) {
      if (opt_exec) {
	ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
	ncexec(&listen_sock);		/* this won't return */
      }
      core_readwrite(&listen_sock, &stdio_sock);
      debug_dv(("Listen: EXIT"));
    }
    else {
      /* otherwise we are in tunnel mode.  The connect_sock var was already
         initialized by the command line arguments. */
      assert(netcat_mode == NETCAT_TUNNEL);
      connect_ret = core_connect(&connect_sock);

      /* connection failure? (we cannot get this in UDP mode) */
      if (connect_ret < 0) {
	assert(connect_sock.proto != NETCAT_PROTO_UDP);
	ncprint(NCPRINT_VERB1, "%s: %s",
		netcat_strid(connect_sock.domain, &connect_sock.remote, &connect_sock.port),
		strerror(errno));
      }
      else {
	glob_ret = EXIT_SUCCESS;
	core_readwrite(&listen_sock, &connect_sock);
	debug_dv(("Tunnel: EXIT (ret=%d)", glob_ret));
      }
    }

    /* all jobs should be ok, go to the cleanup */
    goto main_exit;
  }				/* end of listen and tunnel mode handling */

  /* we need to connect outside, this is the connect mode */
  netcat_mode = NETCAT_CONNECT;

  /* first check that a host parameter was given */
  if (!remote_host.host.iaddrs[0].s_addr) {
    /* FIXME: The Networking specifications state that host address "0" is a
       valid host to connect to but this broken check will assume as not
       specified. */
    ncprint(NCPRINT_NORMAL, _("%s: missing hostname argument"), argv[0]);
    ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
  }

  /* since ports are the second argument, checking ports might be enough */
  total_ports = netcat_ports_count(old_flag);
  if (total_ports == 0)
    ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
	    _("No ports specified for connection"));

  c = 0;			/* must be set to 0 for netcat_flag_next() */
  left_ports = total_ports;
  while (left_ports > 0) {
    /* `c' is the port number independently of the sorting method (linear
       or random).  While in linear mode it is also used to fetch the next
       port number */
    if (opt_random)
      c = netcat_ports_rand(old_flag);
    else
      c = netcat_ports_next(old_flag, c);
    left_ports--;		/* decrease the total ports number to try */

    /* since we are nonblocking now, we can start as many connections as we want
       but it's not a great idea connecting more than one host at time */
    connect_sock.proto = opt_proto;
    connect_sock.timeout = opt_wait;
    memcpy(&connect_sock.local, &local_host, sizeof(connect_sock.local));
    memcpy(&connect_sock.local_port, &local_port,
	   sizeof(connect_sock.local_port));
    memcpy(&connect_sock.remote, &remote_host, sizeof(connect_sock.remote));
    netcat_getport(&connect_sock.port, NULL, c);

    /* FIXME: in udp mode and NETCAT_CONNECT, opt_zero is senseless */
    connect_ret = core_connect(&connect_sock);

    /* connection failure? (we cannot get this in UDP mode) */
    if (connect_ret < 0) {
      int ncprint_flags = NCPRINT_VERB1;
      assert(connect_sock.proto != NETCAT_PROTO_UDP);

      /* if we are portscanning or multiple connecting show only open
         ports with verbosity level 1. */
      if (total_ports > 1)
	ncprint_flags = NCPRINT_VERB2;

      ncprint(ncprint_flags, "%s: %s",
	      netcat_strid(connect_sock.domain, &connect_sock.remote, &connect_sock.port),
	      strerror(errno));
      continue;			/* go with next port */
    }

    /* when portscanning (or checking a single port) we are happy if AT LEAST
       ONE port is available. */
    glob_ret = EXIT_SUCCESS;

    if (opt_zero) {
      shutdown(connect_ret, 2);
      close(connect_ret);
    }
    else {
      if (opt_exec) {
	ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
	ncexec(&connect_sock);		/* this won't return */
      }
      core_readwrite(&connect_sock, &stdio_sock);
      /* FIXME: add a small delay */
      debug_v(("Connect: EXIT"));

      /* both signals are handled inside core_readwrite(), but while the
         SIGINT signal is fully handled, the SIGTERM requires some action
         from outside that function, because of this that flag is not
         cleared. */
      if (got_sigterm)
	break;
    }
  }			/* end of while (left_ports > 0) */

  /* all basic modes should return here for the final cleanup */
 main_exit:
  debug_v(("Main: EXIT (cleaning up)"));

  netcat_printstats(FALSE);
  return glob_ret;
}				/* end of main() */
Beispiel #20
0
bool netcat_getport(nc_port_t *dst, const char *port_name,
		    unsigned short port_num)
{
  const char *get_proto = (opt_proto == NETCAT_PROTO_UDP ? "udp" : "tcp");
  struct servent *servent;

  debug_v(("netcat_getport(dst=%p, port_name=\"%s\", port_num=%hu)",
	  (void *)dst, NULL_STR(port_name), port_num));

/* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
   Despite this, we still have to treat it as a short when copying it around.
   Not only that, but we have to convert it *back* into net order for
   getservbyport to work.  Manpages generally aren't clear on all this, but
   there are plenty of examples in which it is just quietly done. -hobbit */

  /* reset all fields of the dst struct */
  memset(dst, 0, sizeof(*dst));

  if (!port_name) {
    if (port_num == 0)
      return FALSE;
    dst->num = port_num;
    dst->netnum = htons(port_num);
    servent = getservbyport((int)dst->netnum, get_proto);
    if (servent) {
      assert(dst->netnum == servent->s_port);
      strncpy(dst->name, servent->s_name, sizeof(dst->name));
    }
    goto end;
  }
  else {
    long port;
    char *endptr;

    /* empty string? refuse it */
    if (!port_name[0])
      return FALSE;

    /* try to convert the string into a valid port number.  If an error occurs
       but it doesn't occur at the first char, throw an error */
    port = strtol(port_name, &endptr, 10);
    if (!endptr[0]) {
      /* pure numeric value, check it out */
      if ((port > 0) && (port < 65536))
        return netcat_getport(dst, NULL, (in_port_t)port);
      else
        return FALSE;
    }
    else if (endptr != port_name)	/* mixed numeric and string value */
      return FALSE;

    /* this is a port name, try to lookup it */
    servent = getservbyname(port_name, get_proto);
    if (servent) {
      strncpy(dst->name, servent->s_name, sizeof(dst->name));
      dst->netnum = servent->s_port;
      dst->num = ntohs(dst->netnum);
      goto end;
    }
    return FALSE;
  }

 end:
  snprintf(dst->ascnum, sizeof(dst->ascnum), "%hu", dst->num);
  return TRUE;
}			/* end of netcat_getport() */