Exemplo n.º 1
0
int netcat_socket_new_connect(nc_domain_t domain, nc_proto_t proto,
			      const nc_host_t *addr, const nc_port_t *port,
			      const nc_host_t *local_addr, const nc_port_t *local_port,
			      const nc_sockopts_t *opts)
{
  int sock, ret;
  assert(addr);

  debug_dv(("netcat_socket_new_connect(domain=%d, addr=%p, port=%hu, "
	    "local_addr=%p, local_port=%hu)", domain, (void *)addr, port->num,
	    (void *)local_addr, local_port->num));

  /* create the socket and fix the options */
  sock = netcat_socket_new(domain, proto, opts);
  if (sock < 0)
    return sock;		/* just forward the error code */

  /* only if needed, bind it to a local address */
  if (local_addr || local_port->num) {
    ret = netcat_bind(sock, domain, local_addr, local_port);
    if (ret < 0) {
      ret = -3;
      goto err;
    }
  }

  /* add the non-blocking flag to this socket */
  if ((ret = fcntl(sock, F_GETFL, 0)) >= 0)
    ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK);
  if (ret < 0) {
    ret = -4;
    goto err;
  }

  /* now launch the real connection.  Since we are in non-blocking mode, this
     call will return -1 in MOST cases (on some systems, a connect() to a local
     address may immediately return successfully) */
  ret = netcat_connect(sock, domain, addr, port);
  if ((ret < 0) && (errno != EINPROGRESS)) {
    ret = -5;
    goto err;
  }

  /* everything went fine, return the (connected or connecting) socket */
  return sock;

 err:
  /* the if () statement is unuseful, but I need to for declaring vars */
  if (ret < 0) {
    int tmpret, saved_errno = errno;

    /* the close() calls MUST NOT fail */
    tmpret = close(sock);
    assert(tmpret >= 0);

    /* restore the original errno */
    errno = saved_errno;
  }
  return ret;
}
Exemplo n.º 2
0
int netcat_socket_new_listen(int domain, const struct in_addr *addr,
			     in_port_t port)
{
  int sock, ret, my_family;
  struct sockaddr_in my_addr;

  debug_dv(("netcat_socket_new_listen(addr=%p, port=%hu)", (void *)addr, port));

  /* selects the currently supported domains */
  if (domain == PF_INET)
    my_family = AF_INET;
  else
    return -1;		/* assumes as the socket(2) call failed */

  /* Reset the sockaddr structure */
  memset(&my_addr, 0, sizeof(my_addr));
  my_addr.sin_family = my_family;
  my_addr.sin_port = port;

  /* this parameter is not mandatory.  if it's not present, it's assumed as
     INADDR_ANY, and the behaviour is the same */
  if (addr)
    memcpy(&my_addr.sin_addr, addr, sizeof(my_addr.sin_addr));

  /* create the socket and fix the options */
  sock = netcat_socket_new(domain, SOCK_STREAM);
  if (sock < 0)
    return sock;		/* forward the error code */

  /* bind it to the specified address (can be INADDY_ANY) */
  ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
  if (ret < 0) {
    ret = -3;
    goto err;
  }

  /* now make it listening, with a reasonable backlog value */
  ret = listen(sock, 4);
  if (ret < 0) {
    ret = -4;
    goto err;
  }

  return sock;

 err:
  /* the if () statement is unuseful, but I need to for declaring vars */
  if (ret < 0) {
    int tmpret, saved_errno = errno;

    /* the close() calls MUST NOT fail */
    tmpret = close(sock);
    assert(tmpret >= 0);

    /* restore the original errno */
    errno = saved_errno;
  }
  return ret;
}
Exemplo n.º 3
0
int netcat_socket_new_listen(nc_domain_t domain, const nc_host_t *addr,
			     const nc_port_t *port, const nc_sockopts_t *opts)
{
  int sock, ret;

  debug_dv(("netcat_socket_new_listen(addr=%p, port=(%hu))", (void *)addr, port->num));

  /* create the socket and fix the options */
  sock = netcat_socket_new(domain, NETCAT_PROTO_TCP, opts);
  if (sock < 0)
    return sock;		/* forward the error code */

  /* bind it to the specified address (can be INADDY_ANY) */
  ret = netcat_bind(sock, domain, addr, port);
  if (ret < 0) {
    ret = -3;
    goto err;
  }

  /* now make it listening, with a reasonable backlog value */
  ret = listen(sock, 4);
  if (ret < 0) {
    ret = -4;
    goto err;
  }

  return sock;

 err:
  /* the `if' statement is unuseful, but I need it to declare vars */
  if (ret < 0) {
    int tmpret, saved_errno = errno;

    /* the close() calls MUST NOT fail */
    tmpret = close(sock);
    assert(tmpret >= 0);

    /* restore the original errno */
    errno = saved_errno;
  }
  return ret;
}
Exemplo n.º 4
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() */
Exemplo n.º 5
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() */
Exemplo n.º 6
0
int netcat_socket_new_connect(int domain, int type, const struct in_addr *addr,
		in_port_t port, const struct in_addr *local_addr,
		in_port_t local_port)
{
  int sock, ret, my_family = AF_UNSPEC;
  struct sockaddr_in rem_addr;
  assert(addr);

  debug_dv(("netcat_socket_new_connect(addr=%p, port=%hu, local_addr=%p, local_"
	   "port=%hu)", (void *)addr, ntohs(port), (void *)local_addr,
	   ntohs(local_port)));

  /* selects the currently supported domains */
  if (domain == PF_INET)
    my_family = AF_INET;
  else
    return -1;		/* assumes as the socket(2) call failed */

  memset(&rem_addr, 0, sizeof(rem_addr));
  rem_addr.sin_family = my_family;
  rem_addr.sin_port = port;
  memcpy(&rem_addr.sin_addr, addr, sizeof(rem_addr.sin_addr));

  /* create the socket and fix the options */
  sock = netcat_socket_new(domain, type);
  if (sock < 0)
    return sock;		/* just forward the error code */

  /* only if needed, bind it to a local address */
  if (local_addr || local_port) {
    struct sockaddr_in my_addr;

    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = my_family;
    my_addr.sin_port = local_port;

    /* local_addr may not be specified because the user may want to only
       enforce the local source port */
    if (local_addr)
      memcpy(&my_addr.sin_addr, local_addr, sizeof(my_addr.sin_addr));

    ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
    if (ret < 0) {
      ret = -3;
      goto err;
    }
  }

  /* add the non-blocking flag to this socket */
  if ((ret = fcntl(sock, F_GETFL, 0)) >= 0)
    ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK);
  if (ret < 0) {
    ret = -4;
    goto err;
  }

  /* now launch the real connection.  Since we are in non-blocking mode, this
     call will return -1 in MOST cases (on some systems, a connect() to a local
     address may immediately return successfully) */
  ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr));
  if ((ret < 0) && (errno != EINPROGRESS)) {
    ret = -5;
    goto err;
  }

  /* everything went fine, return the (connected or connecting) socket */
  return sock;

 err:
  /* the if () statement is unuseful, but I need to for declaring vars */
  if (ret < 0) {
    int tmpret, saved_errno = errno;

    /* the close() calls MUST NOT fail */
    tmpret = close(sock);
    assert(tmpret >= 0);

    /* restore the original errno */
    errno = saved_errno;
  }
  return ret;
}