Esempio n. 1
0
int do_connect(int type)
{
    int sock = 0;

    if (type != SOCK_STREAM && type != SOCK_DGRAM)
        return -1;

    /* We need a socket that can be inherited by child processes in
       ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
       nbase. */
    sock = inheritable_socket(targetss.storage.ss_family, type, 0);

    if (srcaddr.storage.ss_family != AF_UNSPEC) {
        size_t sa_len;

#ifdef HAVE_SOCKADDR_SA_LEN
        sa_len = srcaddr.sockaddr.sa_len;
#else
        sa_len = sizeof(srcaddr);
#endif
        if (bind(sock, &srcaddr.sockaddr, sa_len) < 0) {
            bye("bind to %s:%hu: %s.", inet_socktop(&srcaddr),
                inet_port(&srcaddr), socket_strerror(socket_errno()));
        }
    }

    if (sock != -1) {
        if (connect(sock, &targetss.sockaddr, (int) targetsslen) != -1)
            return sock;
        else if (socket_errno() == EINPROGRESS || socket_errno() == EAGAIN)
            return sock;
    }
    return -1;
}
Esempio n. 2
0
void setup_environment(struct fdinfo *info)
{
    union sockaddr_u su;
    char ip[INET6_ADDRSTRLEN];
    char port[16];
    socklen_t alen = sizeof(su);

    if (getpeername(info->fd, &su.sockaddr, &alen) != 0) {
        bye("getpeername failed: %s", socket_strerror(socket_errno()));
    }
#ifdef HAVE_SYS_UN_H
    if (su.sockaddr.sa_family == AF_UNIX) {
        /* say localhost to keep it backwards compatible */
        setenv_portable("NCAT_REMOTE_ADDR", "localhost");
        setenv_portable("NCAT_REMOTE_PORT", "");
    } else
#endif
    if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
            port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
        setenv_portable("NCAT_REMOTE_ADDR", ip);
        setenv_portable("NCAT_REMOTE_PORT", port);
    } else {
        bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
    }

    if (getsockname(info->fd, (struct sockaddr *)&su, &alen) < 0) {
        bye("getsockname failed: %s", socket_strerror(socket_errno()));
    }
#ifdef HAVE_SYS_UN_H
    if (su.sockaddr.sa_family == AF_UNIX) {
        /* say localhost to keep it backwards compatible, else su.un.sun_path */
        setenv_portable("NCAT_LOCAL_ADDR", "localhost");
        setenv_portable("NCAT_LOCAL_PORT", "");
    } else
#endif
    if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
            port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
        setenv_portable("NCAT_LOCAL_ADDR", ip);
        setenv_portable("NCAT_LOCAL_PORT", port);
    } else {
        bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
    }

    switch(o.proto) {
        case IPPROTO_TCP:
            setenv_portable("NCAT_PROTO", "TCP");
            break;
        case IPPROTO_SCTP:
            setenv_portable("NCAT_PROTO", "SCTP");
            break;
        case IPPROTO_UDP:
            setenv_portable("NCAT_PROTO", "UDP");
            break;
    }
}
Esempio n. 3
0
static int
xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) {

    int 	total_sent = 0;

    if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) {
        while (total_sent < outlen) {
            int nsent = send(ctxt->fd, xmt_ptr + total_sent,
                                      outlen - total_sent, 0);
            if (nsent>0)
                total_sent += nsent;
	    else if ( ( nsent == -1 ) && 
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
	    	      ( socket_errno( ) != EAGAIN ) &&
#endif
		        ( socket_errno( ) != EWOULDBLOCK ) ) {
		__xmlIOErr(XML_FROM_HTTP, 0, "send failed\n");
		if ( total_sent == 0 )
		    total_sent = -1;
		break;
	    }
	    else {
	        /*
		**  No data sent
		**  Since non-blocking sockets are used, wait for 
		**  socket to be writable or default timeout prior
		**  to retrying.
		*/

		struct timeval	tv;
		fd_set		wfd;

		tv.tv_sec = timeout;
		tv.tv_usec = 0;
		FD_ZERO( &wfd );
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4018)
#endif
		FD_SET( ctxt->fd, &wfd );
#ifdef _MSC_VER
#pragma warning(pop)
#endif
		(void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv );
	    }
	}
    }

    return total_sent;
}
Esempio n. 4
0
int get_authenticated_socket( const char * host, int port)
{
    int remote = 0 ;
    int ret;

    dest_host = strdup(host);
    dest_port = port;
    
    if (0 < connect_timeout)
        set_timeout (connect_timeout);
    //if (check_direct(dest_host))
    //   relay_method = METHOD_DIRECT;
  
    if ( relay_method == METHOD_DIRECT ) {
        remote = open_connection (dest_host, dest_port);
        if ( remote == SOCKET_ERROR )
            g_error( "Unable to connect to destination host, errno=%d\n",
                     socket_errno());
    } else {
        remote = open_connection (relay_host, relay_port);
        if ( remote == SOCKET_ERROR )
            g_error( "Unable to connect to relay host, errno=%d\n",
                     socket_errno());
    }

    if (socks_ns.sin_addr.s_addr != 0)
        switch_ns (&socks_ns);

    switch ( relay_method ) {
        case METHOD_HTTP:
            ret = begin_http_relay(remote);
            switch (ret) {
                case START_ERROR:
                    close (remote);
                    g_error("failed to begin relaying via HTTP.\n");
                case START_OK:
                    break;
                case START_RETRY:
                    
                    close (remote);
            }
            break;
        case METHOD_DIRECT:
            g_debug("Did not using proxy bypass ...(%s,%d)",__FILE__, __LINE__);
            break;
    }
    return remote;
}
Esempio n. 5
0
/* Create the actual socket (nse->iod->sd) underlying the iod. This unblocks the
 * socket, binds to the localaddr address, sets IP options, and sets the
 * broadcast flag. Trying to change these functions after making this call will
 * not have an effect. This function needs to be called before you try to read
 * or write on the iod. */
static int nsock_make_socket(struct npool *ms, struct niod *iod, int family, int type, int proto) {

  /* inheritable_socket is from nbase */
  iod->sd = (int)inheritable_socket(family, type, proto);
  if (iod->sd == -1) {
    nsock_log_error("Socket trouble: %s", socket_strerror(socket_errno()));
    return -1;
  }

  unblock_socket(iod->sd);

  iod->lastproto = proto;

  if (iod->locallen)
    mksock_bind_addr(ms, iod);

  if (iod->ipoptslen && family == AF_INET)
    mksock_set_ipopts(ms, iod);

  if (ms->device)
    mksock_bind_device(ms, iod);

  if (ms->broadcast && type != SOCK_STREAM)
    mksock_set_broadcast(ms, iod);

  /* mksock_* functions can raise warnings/errors
   * but we don't let them stop us for now. */
  return iod->sd;
}
/* Broadcast a message to all the descriptors in fds. Returns -1 if any of the
   sends failed. */
int ncat_broadcast(fd_set *fds, const fd_list_t *fdlist, const char *msg, size_t size)
{
    struct fdinfo *fdn;
    int i, ret;

    if (o.recvonly)
        return size;

    ret = 0;
    for (i = 0; i <= fdlist->fdmax; i++) {
        if (!FD_ISSET(i, fds))
            continue;

        fdn = get_fdinfo(fdlist, i);
        ncat_assert(fdn != NULL);
        if (blocking_fdinfo_send(fdn, msg, size) <= 0) {
            if (o.debug > 1)
                logdebug("Error sending to fd %d: %s.\n", i, socket_strerror(socket_errno()));
            ret = -1;
        }
    }

    ncat_log_send(msg, size);

    return ret;
}
Esempio n. 7
0
ssize_t R_SockRead(int sockp, void *buf, size_t len, int blocking, int timeout)
{
    ssize_t res;

    if(blocking && R_SocketWait(sockp, 0, timeout) != 0) return 0;
    res = recv(sockp, buf, len, 0);
    return (res >= 0) ? res : -socket_errno();
}
Esempio n. 8
0
ssize_t R_SockRead(int sockp, void *buf, size_t len, int blocking, int timeout)
{
    ssize_t res;

    if(blocking && (res = R_SocketWait(sockp, 0, timeout)) != 0)
        return res < 0 ? res : 0; /* socket error or timeout */
    res = recv(sockp, buf, len, 0);
    return (res >= 0) ? res : -socket_errno();
}
Esempio n. 9
0
obj_t bigloo_socket_read_returns_data(int fd) {
  char buf;

  if ((0 == recv(fd, &buf, 1, MSG_PEEK)) && 
      (socket_errno() != EAGAIN)) {
    return BFALSE;
  } else {
    return BTRUE;
  }
}
Esempio n. 10
0
void setup_environment(struct fdinfo *info)
{
    union sockaddr_u su;
    char ip[INET6_ADDRSTRLEN];
    char port[16];
    socklen_t alen = sizeof(su);

    if (getpeername(info->fd, &su.sockaddr, &alen) != 0) {
        bye("getpeername failed: %s", socket_strerror(socket_errno()));
    }
    if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
            port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
        setenv_portable("NCAT_REMOTE_ADDR", ip);
        setenv_portable("NCAT_REMOTE_PORT", port);
    } else {
        bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
    }

    if (getsockname(info->fd, (struct sockaddr *)&su, &alen) < 0) {
        bye("getsockname failed: %s", socket_strerror(socket_errno()));
    }
    if (getnameinfo((struct sockaddr *)&su, alen, ip, sizeof(ip),
            port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
        setenv_portable("NCAT_LOCAL_ADDR", ip);
        setenv_portable("NCAT_LOCAL_PORT", port);
    } else {
        bye("getnameinfo failed: %s", socket_strerror(socket_errno()));
    }

    switch(o.proto) {
        case IPPROTO_TCP:
            setenv_portable("NCAT_PROTO", "TCP");
            break;
        case IPPROTO_SCTP:
            setenv_portable("NCAT_PROTO", "SCTP");
            break;
        case IPPROTO_UDP:
            setenv_portable("NCAT_PROTO", "UDP");
            break;
    }
}
Esempio n. 11
0
int
htsp_tcp_read(socket_t fd, void *buf, size_t len)
{
  int x = recv(fd, buf, len, MSG_WAITALL);

  if(x == -1)
    return socket_errno();
  if(x != len)
    return ECONNRESET;
  return 0;

}
Esempio n. 12
0
static int mksock_bind_addr(struct npool *ms, struct niod *iod) {
  int rc;
  int one = 1;

  rc = setsockopt(iod->sd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one));
  if (rc == -1) {
    int err = socket_errno();

    nsock_log_error("Setting of SO_REUSEADDR failed (#%li): %s (%d)", iod->id,
                    socket_strerror(err), err);
  }

  nsock_log_info("Binding to %s (IOD #%li)", get_localaddr_string(iod), iod->id);
  rc = bind(iod->sd, (struct sockaddr *)&iod->local, (int) iod->locallen);
  if (rc == -1) {
    int err = socket_errno();

    nsock_log_error("Bind to %s failed (IOD #%li): %s (%d)",
                    get_localaddr_string(iod), iod->id,
                    socket_strerror(err), err);
  }
  return 0;
}
Esempio n. 13
0
static int mksock_set_broadcast(struct npool *ms, struct niod *iod) {
  int rc;
  int one = 1;

  rc = setsockopt(iod->sd, SOL_SOCKET, SO_BROADCAST,
                  (const char *)&one, sizeof(one));
  if (rc == -1) {
    int err = socket_errno();

    nsock_log_error("Setting of SO_BROADCAST failed (IOD #%li): %s (%d)",
                    iod->id, socket_strerror(err), err);
  }
  return 0;
}
Esempio n. 14
0
ssize_t R_SockWrite(int sockp, const void *buf, size_t len, int timeout)
{
    ssize_t res, out = 0;

    /* Rprintf("socket %d writing |%s|\n", sockp, buf); */
    /* This function is not passed a `blocking' argument so the code
       here is equivalent to blocking == TRUE; it's not clear
       non-blocking writes make much sense with the current connection
       interface since there is no way to tell how much, if anything,
       has been written.  LT */
    do {
	if(R_SocketWait(sockp, 1, timeout) != 0) return out;
	res = send(sockp, buf, len, 0);
	if (res < 0 && socket_errno() != EWOULDBLOCK)
	    return -socket_errno();
	else {
	    { const char *cbuf = buf; cbuf += res; buf = cbuf; }
	    len -= res;
	    out += res;
	}
    } while (/* ! blocking && */len > 0);
    return out;
}
Esempio n. 15
0
static int mksock_set_ipopts(struct npool *ms, struct niod *iod) {
  int rc;

  errno = 0;
  rc = setsockopt(iod->sd, IPPROTO_IP, IP_OPTIONS, (const char *)iod->ipopts,
                  iod->ipoptslen);
  if (rc == -1) {
    int err = socket_errno();

    nsock_log_error("Setting of IP options failed (IOD #%li): %s (%d)",
                    iod->id, socket_strerror(err), err);
  }
  return 0;
}
Esempio n. 16
0
int sendf(SOCKET s, const char *fmt,...)
{
    static char buf[10240];                   
    
    va_list args;
    va_start( args, fmt );
    vsnprintf( buf, sizeof(buf), fmt, args );
    va_end( args );

    //report_text(">>>", buf);
    if ( send(s, buf, strlen(buf), 0) == SOCKET_ERROR ) {
        g_debug("failed to send http request. errno=%d\n", socket_errno());
        return -1;
    }
    return 0;
}
Esempio n. 17
0
static int mksock_bind_device(struct npool *ms, struct niod *iod) {
  int rc;

  rc = socket_bindtodevice(iod->sd, ms->device);
  if (!rc) {
    int err = socket_errno();

    if (err != EPERM)
      nsock_log_error("Setting of SO_BINDTODEVICE failed (IOD #%li): %s (%d)",
                      iod->id, socket_strerror(err), err);
    else
      nsock_log_debug_all("Setting of SO_BINDTODEVICE failed (IOD #%li): %s (%d)",
                          iod->id, socket_strerror(err), err);
  }
  return 0;
}
Esempio n. 18
0
/*
 * socktoa - return a numeric host name from a sockaddr_storage structure
 */
const char *
socktoa(
	const sockaddr_u *sock
	)
{
	int		saved_errno;
	char *		res;
	char *		addr;
	u_long		scope;

	saved_errno = socket_errno();
	LIB_GETBUF(res);

	if (NULL == sock) {
		strlcpy(res, "(null)", LIB_BUFLENGTH);
	} else {
		switch(AF(sock)) {

		case AF_INET:
		case AF_UNSPEC:
			inet_ntop(AF_INET, PSOCK_ADDR4(sock), res,
				  LIB_BUFLENGTH);
			break;

		case AF_INET6:
			inet_ntop(AF_INET6, PSOCK_ADDR6(sock), res,
				  LIB_BUFLENGTH);
			scope = SCOPE_VAR(sock);
			if (0 != scope && !strchr(res, '%')) {
				addr = res;
				LIB_GETBUF(res);
				snprintf(res, LIB_BUFLENGTH, "%s%%%lu",
					 addr, scope);
				res[LIB_BUFLENGTH - 1] = '\0';
			}
			break;

		default:
			snprintf(res, LIB_BUFLENGTH, 
				 "(socktoa unknown family %d)", 
				 AF(sock));
		}
	}
	errno = saved_errno;

	return res;
}
Esempio n. 19
0
int atomic_out( SOCKET s, char *buf, int size )
{
    int ret, len;

    assert( buf != NULL );
    assert( 0<=size );
  
    ret = 0;
    while ( 0 < size ) {
        len = send( s, buf+ret, size, 0 );
        if ( len == -1 )
            g_error("atomic_out() failed to send(), %d\n", socket_errno());
        ret += len;
        size -= len;
    }
    g_debug("atomic_out()  [%d bytes]\n", ret);
    return ret;
}
Esempio n. 20
0
int
htsp_tcp_read_timeout(socket_t fd, char *buf, size_t len, int timeout)
{
  int x, tot = 0, val, err;
  fd_set fd_read;
  struct timeval tv;

  assert(timeout > 0);

  while(tot != len) {

    tv.tv_sec  =         timeout / 1000;
    tv.tv_usec = 1000 * (timeout % 1000);

    FD_ZERO(&fd_read);
    FD_SET(fd, &fd_read);

    x = select((int)fd+1, &fd_read, NULL, NULL, &tv);

    if(x == 0)
      return ETIMEDOUT;

    val = 1;
    ioctlsocket(fd, FIONBIO, &val);

    x   = recv(fd, buf + tot, len - tot, 0);
    err = socket_errno();

    val = 0;
    ioctlsocket(fd, FIONBIO, &val);

    if(x == 0)
      return ECONNRESET;
    else if(x == -1)
    {
      if(err == EAGAIN)
        continue;
      return err;
    }

    tot += x;
  }
  return 0;
}
Esempio n. 21
0
int async_connect(int socket, const struct sockaddr* address, socklen_t length) {
    int result = connect(socket, address, length);

    if (result == 0) {
        return 0;
    }

    if (sched_errno != EINPROGRESS) {
        return -1;
    }

    sched_event_wait(socket, WAITOUT);

    int error = socket_errno(socket);
    if (error != 0) {
        sched_errno = error;
        return -1;
    }
    return 0;
}
Esempio n. 22
0
/* Converts an IP address given in a sockaddr_u to an IPv4 or
   IPv6 IP address string.  Since a static buffer is returned, this is
   not thread-safe and can only be used once in calls like printf()
*/
const char *inet_socktop(const union sockaddr_u *su)
{
    static char buf[INET6_ADDRSTRLEN + 1];
    void *addr;

    if (su->storage.ss_family == AF_INET)
        addr = (void *) &su->in.sin_addr;
#if HAVE_IPV6
    else if (su->storage.ss_family == AF_INET6)
        addr = (void *) &su->in6.sin6_addr;
#endif
    else
        addr = NULL;

    if (inet_ntop(su->storage.ss_family, addr, buf, sizeof(buf)) == NULL) {
        bye("Failed to convert address to presentation format!  Error: %s.",
            strerror(socket_errno()));
    }

    return buf;
}
Esempio n. 23
0
const char *
sockporttoa(
	const sockaddr_u *sock
	)
{
	int		saved_errno;
	const char *	atext;
	char *		buf;

	saved_errno = socket_errno();
	atext = socktoa(sock);
	LIB_GETBUF(buf);
	snprintf(buf, LIB_BUFLENGTH,
		 (IS_IPV6(sock))
		     ? "[%s]:%u"
		     : "%s:%u",
		 atext, SRCPORT(sock));
	errno = saved_errno;

	return buf;
}
Esempio n. 24
0
int atomic_in( SOCKET s, char *buf, int size )
{
    int ret, len;

    assert( buf != NULL );
    assert( 0<=size );

 
    ret = 0;
    while ( 0 < size ) {
        len = recv( s, buf+ret, size, 0 );
        if ( len == -1 ) {
            g_error("atomic_in() failed to recv(), %d\n", socket_errno());
        } else if ( len == 0 ) {
            g_error( "Connection closed by peer.\n");
        }
        ret += len;
        size -= len;
    }
    g_debug("atomic_in()  [some bytes]\n");
    return ret;
}
Esempio n. 25
0
/* Return a listening socket after setting various characteristics on it.
   Returns -1 on error. */
int do_listen(int type, int proto, const union sockaddr_u *srcaddr_u)
{
    int sock = 0, option_on = 1;
    size_t sa_len;

    if (type != SOCK_STREAM && type != SOCK_DGRAM)
        return -1;

    /* We need a socket that can be inherited by child processes in
       ncat_exec_win.c, for --exec and --sh-exec. inheritable_socket is from
       nbase. */
    sock = inheritable_socket(srcaddr_u->storage.ss_family, type, proto);
    if (sock < 0)
        return -1;

    Setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &option_on, sizeof(int));

/* IPPROTO_IPV6 is defined in Visual C++ only when _WIN32_WINNT >= 0x501.
   Nbase's nbase_winunix.h defines _WIN32_WINNT to a lower value for
   compatibility with older versions of Windows. This code disables IPv6 sockets
   that also receive IPv4 connections. This is the default on Windows anyway so
   it doesn't make a difference.
   http://support.microsoft.com/kb/950688
   http://msdn.microsoft.com/en-us/library/bb513665
*/
#ifdef IPPROTO_IPV6
#ifdef IPV6_V6ONLY
    if (srcaddr_u->storage.ss_family == AF_INET6) {
        int set = 1;
        /* Tell it to not try and bind to IPV4 */
        if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &set, sizeof(set)) == -1)
            die("Unable to set IPV6 socket to bind only to IPV6");
    }
#endif
#endif

#ifdef HAVE_SYS_UN_H
    if (srcaddr_u->storage.ss_family == AF_UNIX)
        sa_len = SUN_LEN(&srcaddr_u->un);
    else
#endif
#ifdef HAVE_SOCKADDR_SA_LEN
        sa_len = srcaddr_u->sockaddr.sa_len;
#else
        sa_len = sizeof(*srcaddr_u);
#endif

    if (bind(sock, &srcaddr_u->sockaddr, sa_len) < 0) {
#ifdef HAVE_SYS_UN_H
        if (srcaddr_u->storage.ss_family == AF_UNIX)
            bye("bind to %s: %s.", srcaddr_u->un.sun_path,
                socket_strerror(socket_errno()));
        else
#endif
            bye("bind to %s:%hu: %s.", inet_socktop(srcaddr_u),
                inet_port(srcaddr_u), socket_strerror(socket_errno()));
    }

    if (type == SOCK_STREAM)
        Listen(sock, BACKLOG);

    if (o.verbose) {
#ifdef HAVE_SYS_UN_H
        if (srcaddr_u->storage.ss_family == AF_UNIX)
            loguser("Listening on %s\n", srcaddr_u->un.sun_path);
        else
#endif
            loguser("Listening on %s:%hu\n", inet_socktop(srcaddr_u), inet_port(srcaddr_u));
    }
    if (o.test)
        logtest("LISTEN\n");

    return sock;
}
Esempio n. 26
0
static SOCKET
xmlNanoHTTPConnectAttempt(struct sockaddr *addr)
{
#ifndef HAVE_POLL_H
    fd_set wfd;
#ifdef _WINSOCKAPI_
    fd_set xfd;
#endif
    struct timeval tv;
#else /* !HAVE_POLL_H */
    struct pollfd p;
#endif /* !HAVE_POLL_H */
    int status;

    int addrlen;

    SOCKET s;

#ifdef SUPPORT_IP6
    if (addr->sa_family == AF_INET6) {
        s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
        addrlen = sizeof(struct sockaddr_in6);
    } else
#endif
    {
        s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        addrlen = sizeof(struct sockaddr_in);
    }
    if (s == INVALID_SOCKET) {
#ifdef DEBUG_HTTP
        perror("socket");
#endif
        __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n");
        return INVALID_SOCKET;
    }
#ifdef _WINSOCKAPI_
    {
        u_long one = 1;

        status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0;
    }
#else /* _WINSOCKAPI_ */
#if defined(VMS)
    {
        int enable = 1;

        status = ioctl(s, FIONBIO, &enable);
    }
#else /* VMS */
#if defined(__BEOS__) && !defined(__HAIKU__)
    {
        bool noblock = true;

        status =
            setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock,
                       sizeof(noblock));
    }
#else /* __BEOS__ */
    if ((status = fcntl(s, F_GETFL, 0)) != -1) {
#ifdef O_NONBLOCK
        status |= O_NONBLOCK;
#else /* O_NONBLOCK */
#ifdef F_NDELAY
        status |= F_NDELAY;
#endif /* F_NDELAY */
#endif /* !O_NONBLOCK */
        status = fcntl(s, F_SETFL, status);
    }
    if (status < 0) {
#ifdef DEBUG_HTTP
        perror("nonblocking");
#endif
        __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n");
        closesocket(s);
        return INVALID_SOCKET;
    }
#endif /* !__BEOS__ */
#endif /* !VMS */
#endif /* !_WINSOCKAPI_ */

    if (connect(s, addr, addrlen) == -1) {
        switch (socket_errno()) {
            case EINPROGRESS:
            case EWOULDBLOCK:
                break;
            default:
                __xmlIOErr(XML_FROM_HTTP, 0,
                           "error connecting to HTTP server");
                closesocket(s);
                return INVALID_SOCKET;
        }
    }
#ifndef HAVE_POLL_H
    tv.tv_sec = timeout;
    tv.tv_usec = 0;

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4018)
#endif
#ifndef _WINSOCKAPI_
    if (s > FD_SETSIZE)
        return INVALID_SOCKET;
#endif
    FD_ZERO(&wfd);
    FD_SET(s, &wfd);

#ifdef _WINSOCKAPI_
    FD_ZERO(&xfd);
    FD_SET(s, &xfd);

    switch (select(s + 1, NULL, &wfd, &xfd, &tv))
#else
    switch (select(s + 1, NULL, &wfd, NULL, &tv))
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif

#else /* !HAVE_POLL_H */
    p.fd = s;
    p.events = POLLOUT;
    switch (poll(&p, 1, timeout * 1000))
#endif /* !HAVE_POLL_H */

    {
        case 0:
            /* Time out */
            __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out");
            closesocket(s);
            return INVALID_SOCKET;
        case -1:
            /* Ermm.. ?? */
            __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed");
            closesocket(s);
            return INVALID_SOCKET;
    }

#ifndef HAVE_POLL_H
    if (FD_ISSET(s, &wfd)
#ifdef _WINSOCKAPI_
        || FD_ISSET(s, &xfd)
#endif
        )
#else /* !HAVE_POLL_H */
    if (p.revents == POLLOUT)
#endif /* !HAVE_POLL_H */
    {
        XML_SOCKLEN_T len;

        len = sizeof(status);
#ifdef SO_ERROR
        if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) <
            0) {
            /* Solaris error code */
            __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n");
            return INVALID_SOCKET;
        }
#endif
        if (status) {
            __xmlIOErr(XML_FROM_HTTP, 0,
                       "Error connecting to remote host");
            closesocket(s);
            errno = status;
            return INVALID_SOCKET;
        }
    } else {
        /* pbm */
        __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n");
        closesocket(s);
        return INVALID_SOCKET;
    }

    return (s);
}
Esempio n. 27
0
static int
xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt)
{
#ifdef HAVE_POLL_H
    struct pollfd p;
#else
    fd_set rfd;
    struct timeval tv;
#endif


    while (ctxt->state & XML_NANO_HTTP_READ) {
        if (ctxt->in == NULL) {
            ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char));
            if (ctxt->in == NULL) {
                xmlHTTPErrMemory("allocating input");
                ctxt->last = -1;
                return (-1);
            }
            ctxt->inlen = 65000;
            ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in;
        }
        if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) {
            int delta = ctxt->inrptr - ctxt->in;
            int len = ctxt->inptr - ctxt->inrptr;

            memmove(ctxt->in, ctxt->inrptr, len);
            ctxt->inrptr -= delta;
            ctxt->content -= delta;
            ctxt->inptr -= delta;
        }
        if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) {
            int d_inptr = ctxt->inptr - ctxt->in;
            int d_content = ctxt->content - ctxt->in;
            int d_inrptr = ctxt->inrptr - ctxt->in;
            char *tmp_ptr = ctxt->in;

            ctxt->inlen *= 2;
            ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen);
            if (ctxt->in == NULL) {
                xmlHTTPErrMemory("allocating input buffer");
                xmlFree(tmp_ptr);
                ctxt->last = -1;
                return (-1);
            }
            ctxt->inptr = ctxt->in + d_inptr;
            ctxt->content = ctxt->in + d_content;
            ctxt->inrptr = ctxt->in + d_inrptr;
        }
        ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0);
        if (ctxt->last > 0) {
            ctxt->inptr += ctxt->last;
            return (ctxt->last);
        }
        if (ctxt->last == 0) {
            return (0);
        }
        if (ctxt->last == -1) {
            switch (socket_errno()) {
                case EINPROGRESS:
                case EWOULDBLOCK:
#if defined(EAGAIN) && EAGAIN != EWOULDBLOCK
                case EAGAIN:
#endif
                    break;

                case ECONNRESET:
                case ESHUTDOWN:
                    return (0);

                default:
                    __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n");
                    return (-1);
            }
        }
#ifdef HAVE_POLL_H
        p.fd = ctxt->fd;
        p.events = POLLIN;
        if ((poll(&p, 1, timeout * 1000) < 1)
#if defined(EINTR)
            && (errno != EINTR)
#endif
            )
            return (0);
#else /* !HAVE_POLL_H */
#ifndef _WINSOCKAPI_
        if (ctxt->fd > FD_SETSIZE)
            return 0;
#endif

        tv.tv_sec = timeout;
        tv.tv_usec = 0;
        FD_ZERO(&rfd);

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4018)
#endif

        FD_SET(ctxt->fd, &rfd);

#ifdef _MSC_VER
#pragma warning(pop)
#endif

        if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1)
#if defined(EINTR)
            && (errno != EINTR)
#endif
            )
            return (0);
#endif /* !HAVE_POLL_H */
    }
    return (0);
}
Esempio n. 28
0
/**
 * New inbound connection for httpd.
 *
 * @param[in] fd	socket file descriptor
 * @param[in] id	I/O ID
 */
void
hio_connection(iosrc_t fd, ioid_t id)
{
    socket_t t;
    union {
	struct sockaddr sa;
	struct sockaddr_in sin;
#if defined(X3270_IPV6) /*[*/
	struct sockaddr_in6 sin6;
#endif /*]*/
    } sa;
    socklen_t len;
    char hostbuf[128];
    session_t *session;

    len = sizeof(sa);
    t = accept(listen_s, &sa.sa, &len);
    if (t == INVALID_SOCKET) {
	vtrace("httpd accept error: %s%s\n", socket_errtext(),
		(socket_errno() == SE_EWOULDBLOCK)? " (harmless)": "");
	return;
    }
    if (n_sessions >= N_SESSIONS) {
	vtrace("Too many connections.\n");
	SOCK_CLOSE(t);
	return;
    }

    session = Malloc(sizeof(session_t));
    memset(session, 0, sizeof(session_t));
    vb_init(&session->pending.result);
    session->s = t;
#if defined(_WIN32) /*[*/
    session->event = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (session->event == NULL) {
	vtrace("httpd: can't create socket handle\n");
	SOCK_CLOSE(t);
	Free(session);
	return;
    }
    if (WSAEventSelect(session->s, session->event, FD_READ | FD_CLOSE) != 0) {
	vtrace("httpd: Can't set socket handle events\n");
	CloseHandle(session->event);
	SOCK_CLOSE(t);
	Free(session);
	return;
    }
#endif /*]*/
    if (sa.sa.sa_family == AF_INET) {
	session->dhandle = httpd_new(session,
		lazyaf("%s:%u",
		    inet_ntop(AF_INET, &sa.sin.sin_addr, hostbuf,
			sizeof(hostbuf)),
		    ntohs(sa.sin.sin_port)));
    }
#if defined(X3270_IPV6) /*[*/
    else if (sa.sa.sa_family == AF_INET6) {
	session->dhandle = httpd_new(session,
		lazyaf("%s:%u",
		    inet_ntop(AF_INET6, &sa.sin6.sin6_addr, hostbuf,
			sizeof(hostbuf)),
		    ntohs(sa.sin6.sin6_port)));
    }
#endif /*]*/
    else {
	session->dhandle = httpd_new(session, "???");
    }
#if !defined(_WIN32) /*[*/
    session->ioid = AddInput(t, hio_socket_input);
#else /*][*/
    session->ioid = AddInput(session->event, hio_socket_input);
#endif /*]*/

    /* Set the timeout for the first line of input. */
    session->toid = AddTimeOut(IDLE_MAX * 1000, hio_timeout);

    llist_insert_before(&session->link, sessions.next);
    n_sessions++;
}
Esempio n. 29
0
/**
 * New inbound data for an httpd connection.
 *
 * @param[in] fd	socket file descriptor
 * @param[in] id	I/O ID
 */
void
hio_socket_input(iosrc_t fd, ioid_t id)
{
    session_t *session;
    char buf[1024];
    ssize_t nr;

    session = NULL;
    FOREACH_LLIST(&sessions, session, session_t *) {
	if (session->ioid == id) {
	    break;
	}
    } FOREACH_LLIST_END(&sessions, session, session_t *);
    if (session == NULL) {
	vtrace("httpd mystery input\n");
	return;
    }

    /* Move this session to the front of the list. */
    llist_unlink(&session->link);
    llist_insert_before(&session->link, sessions.next);

    session->idle = 0;

    if (session->toid != NULL_IOID) {
	RemoveTimeOut(session->toid);
	session->toid = NULL_IOID;
    }

    nr = recv(session->s, buf, sizeof(buf), 0);
    if (nr <= 0) {
	const char *ebuf;
	bool harmless = false;

	if (nr < 0) {
	    if (socket_errno() == SE_EWOULDBLOCK) {
		harmless = true;
	    }
	    ebuf = lazyaf("recv error: %s", socket_errtext());
	    vtrace("httpd %s%s\n", ebuf, harmless? " (harmless)": "");
	} else {
	    ebuf = "session EOF";
	}
	if (!harmless) {
	    httpd_close(session->dhandle, ebuf);
	    hio_socket_close(session);
	}
    } else {
	httpd_status_t rv;

	rv = httpd_input(session->dhandle, buf, nr);
	if (rv < 0) {
	    httpd_close(session->dhandle, "protocol error");
	    hio_socket_close(session);
	} else if (rv == HS_PENDING) {
	    /* Stop input on this socket. */
	    RemoveInput(session->ioid);
	    session->ioid = NULL_IOID;
	} else if (session->toid == NULL_IOID) {
	    /* Leave input enabled and start the timeout. */
	    session->toid = AddTimeOut(IDLE_MAX * 1000, hio_timeout);
	}
    }
}
Esempio n. 30
0
/* Returns -1 if an error, otherwise the number of newly written bytes */
static int do_actual_read(struct npool *ms, struct nevent *nse) {
  char buf[8192];
  int buflen = 0;
  struct niod *iod = nse->iod;
  int err = 0;
  int max_chunk = NSOCK_READ_CHUNK_SIZE;
  int startlen = fs_length(&nse->iobuf);

  if (nse->readinfo.read_type == NSOCK_READBYTES)
    max_chunk = nse->readinfo.num;

  if (!iod->ssl) {
    do {
      struct sockaddr_storage peer;
      socklen_t peerlen;

      peerlen = sizeof(peer);
      buflen = recvfrom(iod->sd, buf, sizeof(buf), 0, (struct sockaddr *)&peer, &peerlen);

      /* Using recv() was failing, at least on UNIX, for non-network sockets
       * (i.e. stdin) in this case, a read() is done - as on ENOTSOCK we may
       * have a non-network socket */
      if (buflen == -1) {
        if (socket_errno() == ENOTSOCK) {
          peer.ss_family = AF_UNSPEC;
          peerlen = 0;
          buflen = read(iod->sd, buf, sizeof(buf));
        }
      }
      if (buflen == -1) {
        err = socket_errno();
        break;
      }
      if (peerlen > 0) {
        assert(peerlen <= sizeof(iod->peer));
        memcpy(&iod->peer, &peer, peerlen);
        iod->peerlen = peerlen;
      }
      if (buflen > 0) {
        if (fs_cat(&nse->iobuf, buf, buflen) == -1) {
          nse->event_done = 1;
          nse->status = NSE_STATUS_ERROR;
          nse->errnum = ENOMEM;
          return -1;
        }

        /* Sometimes a service just spews and spews data.  So we return after a
         * somewhat large amount to avoid monopolizing resources and avoid DOS
         * attacks. */
        if (fs_length(&nse->iobuf) > max_chunk)
          return fs_length(&nse->iobuf) - startlen;

        /* No good reason to read again if we we were successful in the read but
         * didn't fill up the buffer.  Especially for UDP, where we want to
         * return only one datagram at a time. The consistency of the above
         * assignment of iod->peer depends on not consolidating more than one
         * UDP read buffer. */
        if (buflen > 0 && buflen < sizeof(buf))
          return fs_length(&nse->iobuf) - startlen;
      }
    } while (buflen > 0 || (buflen == -1 && err == EINTR));

    if (buflen == -1) {
      if (err != EINTR && err != EAGAIN) {
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = err;
        return -1;
      }
    }
  } else {
#if HAVE_OPENSSL
    /* OpenSSL read */
    while ((buflen = SSL_read(iod->ssl, buf, sizeof(buf))) > 0) {

      if (fs_cat(&nse->iobuf, buf, buflen) == -1) {
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = ENOMEM;
        return -1;
      }

      /* Sometimes a service just spews and spews data.  So we return
       * after a somewhat large amount to avoid monopolizing resources
       * and avoid DOS attacks. */
      if (fs_length(&nse->iobuf) > max_chunk)
        return fs_length(&nse->iobuf) - startlen;
    }

    if (buflen == -1) {
      err = SSL_get_error(iod->ssl, buflen);
      if (err == SSL_ERROR_WANT_READ) {
        int evclr;

        evclr = socket_count_dec_ssl_desire(nse);
        socket_count_read_inc(iod);
        update_events(iod, ms, EV_READ, evclr);
        nse->sslinfo.ssl_desire = err;
      } else if (err == SSL_ERROR_WANT_WRITE) {
        int evclr;

        evclr = socket_count_dec_ssl_desire(nse);
        socket_count_write_inc(iod);
        update_events(iod, ms, EV_WRITE, evclr);
        nse->sslinfo.ssl_desire = err;
      } else {
        /* Unexpected error */
        nse->event_done = 1;
        nse->status = NSE_STATUS_ERROR;
        nse->errnum = EIO;
        nsock_log_info("SSL_read() failed for reason %s on NSI %li",
                       ERR_error_string(err, NULL), iod->id);
        return -1;
      }
    }
#endif /* HAVE_OPENSSL */
  }

  if (buflen == 0) {
    nse->event_done = 1;
    nse->eof = 1;
    if (fs_length(&nse->iobuf) > 0) {
      nse->status = NSE_STATUS_SUCCESS;
      return fs_length(&nse->iobuf) - startlen;
    } else {
      nse->status = NSE_STATUS_EOF;
      return 0;
    }
  }

  return fs_length(&nse->iobuf) - startlen;
}