예제 #1
0
zmq::signaler_t::signaler_t ()
{
    //  Create the socketpair for signaling.
    int rc = make_fdpair (&r, &w);
    errno_assert (rc == 0);

    //  Set both fds to non-blocking mode.
    unblock_socket (w);
    unblock_socket (r);
}
예제 #2
0
zmq::signaler_t::signaler_t ()
{
    //  Create the socketpair for signaling.
    if (make_fdpair (&r, &w) == 0) {
        unblock_socket (w);
        unblock_socket (r);
    }
#ifdef HAVE_FORK
    pid = getpid();
#endif
}
예제 #3
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;
}
예제 #4
0
int zmq::ipc_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    //  Create the socket.
    s = open_socket (AF_UNIX, SOCK_STREAM, 0);
    if (s == -1)
        return -1;

    //  Set the non-blocking flag.
    unblock_socket (s);

    //  Connect to the remote peer.
    int rc = ::connect (
        s, addr->resolved.ipc_addr->addr (),
        addr->resolved.ipc_addr->addrlen ());

    //  Connect was successfull immediately.
    if (rc == 0)
        return 0;
        
    //  Translate other error codes indicating asynchronous connect has been
    //  launched to a uniform EINPROGRESS.
    if (rc == -1 && errno == EINTR) {
        errno = EINPROGRESS;
        return -1;
    }

    //  Forward the error.
    return -1;
}
예제 #5
0
zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
                                       const std::string &endpoint_) :
    s (fd_),
    inpos (NULL),
    insize (0),
    decoder (NULL),
    outpos (NULL),
    outsize (0),
    encoder (NULL),
    handshaking (true),
    greeting_size (v2_greeting_size),
    greeting_bytes_read (0),
    session (NULL),
    options (options_),
    endpoint (endpoint_),
    plugged (false),
    terminating (false),
    read_msg (&stream_engine_t::read_identity),
    write_msg (&stream_engine_t::write_identity),
    io_error (false),
    subscription_required (false),
    mechanism (NULL),
    input_paused (false),
    output_paused (false),
    socket (NULL)
{
    int rc = tx_msg.init ();
    errno_assert (rc == 0);

    //  Put the socket into non-blocking mode.
    unblock_socket (s);
    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf) {
        rc = setsockopt (s, SOL_SOCKET, SO_SNDBUF,
                         (char*) &options.sndbuf, sizeof (int));
#ifdef ZMQ_HAVE_WINDOWS
        wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }
    if (options.rcvbuf) {
        rc = setsockopt (s, SOL_SOCKET, SO_RCVBUF,
                         (char*) &options.rcvbuf, sizeof (int));
#ifdef ZMQ_HAVE_WINDOWS
        wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }

#ifdef SO_NOSIGPIPE
    //  Make sure that SIGPIPE signal is not generated when writing to a
    //  connection that was already closed by the peer.
    int set = 1;
    rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
    errno_assert (rc == 0);
#endif
}
예제 #6
0
파일: signaler.cpp 프로젝트: adeze/libxs
int xs::signaler_init (xs::signaler_t *self_)
{
    //  Create the socketpair for signaling.
    int rc = make_fdpair (&self_->r, &self_->w);
    if (rc != 0)
        return -1;

    //  Set both fds to non-blocking mode.
    unblock_socket (self_->w);
    unblock_socket (self_->r);

#if defined XS_USE_SYNC_SELECT
    FD_ZERO (&self_->fds);
#endif

    return 0;
}
예제 #7
0
파일: ip.c 프로젝트: mahiso/JudoShiai
gint nodescan(guint network) // addr in network byte order
{
    guint i, sd[16], block;
    guint last, addr;
    struct sockaddr_in dst;
    guint found = 0;

    addr = ntohl(network) & 0xffffff00;

    for (block = 0; block < 16 && node_ip_addr == 0; block++) {
        for (i = 0; i < 16; i++) {
            last = (block << 4) | i;
            if (last == 0 || last > 254)
                continue;

            memset(&dst, 0, sizeof(dst));
            dst.sin_family = AF_INET;
            dst.sin_port = htons(SHIAI_PORT);
            dst.sin_addr.s_addr = htonl(addr + last);

            sd[i] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (sd < 0)
                return -1;

            unblock_socket(sd[i]);

            connect(sd[i], (const struct sockaddr *)&dst, sizeof(dst));
        }

        g_usleep(1000000);

        for (i = 0; i < 16; i++) {
            last = (block << 4) | i;
            if (last == 0 || last > 254)
                continue;

            memset(&dst, 0, sizeof(dst));
            dst.sin_family = AF_INET;
            dst.sin_port = htons(SHIAI_PORT);
            dst.sin_addr.s_addr = htonl(addr + last);

            int ret = connect(sd[i], (const struct sockaddr *)&dst, sizeof(dst));

            closesocket(sd[i]);

            if (ret >= 0 && found == 0)
                found = dst.sin_addr.s_addr;
        }

        if (found) {
            dst.sin_addr.s_addr = found;
            g_print("%s: node found\n", inet_ntoa(dst.sin_addr));
            return found;
        }
    }

    return 0;
}
예제 #8
0
xs::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_) :
    s (fd_),
    inpos (NULL),
    insize (0),
    decoder (in_batch_size, options_.maxmsgsize),
    outpos (NULL),
    outsize (0),
    encoder (out_batch_size),
    session (NULL),
    leftover_session (NULL),
    options (options_),
    plugged (false),
    header_pos (in_header),
    header_remaining (sizeof in_header),
    header_received (false),
    header_sent (false)
{
    //  Fill in outgoing SP protocol header and the complementary (desired)
    //  header.
    if (!options.legacy_protocol) {
        sp_get_header (out_header, options.sp_service, options.sp_pattern,
            options.sp_version, options.sp_role);
        sp_get_header (desired_header, options.sp_service, options.sp_pattern,
            options.sp_version, options.sp_complement);
    }

    //  Get the socket into non-blocking mode.
    unblock_socket (s);

    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf) {
        int rc = setsockopt (s, SOL_SOCKET, SO_SNDBUF,
            (char*) &options.sndbuf, sizeof (int));
#ifdef XS_HAVE_WINDOWS
		wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }
    if (options.rcvbuf) {
        int rc = setsockopt (s, SOL_SOCKET, SO_RCVBUF,
            (char*) &options.rcvbuf, sizeof (int));
#ifdef XS_HAVE_WINDOWS
		wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }

#ifdef SO_NOSIGPIPE
    //  Make sure that SIGPIPE signal is not generated when writing to a
    //  connection that was already closed by the peer.
    int set = 1;
    int rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
    errno_assert (rc == 0);
#endif
}
예제 #9
0
/* If we are sending a large amount of data, we might momentarily run out of send
   space and get an EAGAIN when we send. Temporarily convert a socket to
   blocking more, do the send, and unblock it again. Assumes that the socket was
   in nonblocking mode to begin with; it has the side effect of leaving the
   socket nonblocking on return. */
static int blocking_fdinfo_send(struct fdinfo *fdn, const char *buf, size_t size)
{
    int ret;

    block_socket(fdn->fd);
    ret = fdinfo_send(fdn, buf, size);
    unblock_socket(fdn->fd);

    return ret;
}
예제 #10
0
int zmq::tcp_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    //  Create the socket.
    s = open_socket (addr->resolved.tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP);
#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        return -1;
    }
#else
    if (s == -1)
        return -1;
#endif

    //  On some systems, IPv4 mapping in IPv6 sockets is disabled by default.
    //  Switch it on in such cases.
    if (addr->resolved.tcp_addr->family () == AF_INET6)
        enable_ipv4_mapping (s);

    // Set the socket to non-blocking mode so that we get async connect().
    unblock_socket (s);

    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf != 0)
        set_tcp_send_buffer (s, options.sndbuf);
    if (options.rcvbuf != 0)
        set_tcp_receive_buffer (s, options.rcvbuf);

    //  Connect to the remote peer.
    int rc = ::connect (
        s, addr->resolved.tcp_addr->addr (),
        addr->resolved.tcp_addr->addrlen ());

    //  Connect was successfull immediately.
    if (rc == 0)
        return 0;

    //  Translate error codes indicating asynchronous connect has been
    //  launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
    const int error_code = WSAGetLastError ();
    if (error_code == WSAEINPROGRESS || error_code == WSAEWOULDBLOCK)
        errno = EINPROGRESS;
    else
        errno = wsa_error_to_errno (error_code);
#else
    if (errno == EINTR)
        errno = EINPROGRESS;
#endif
    return -1;
}
예제 #11
0
파일: ip.c 프로젝트: mahiso/JudoShiai
gint nodescan(guint network) // addr in network byte order
{
    SOCKET sd;
    guint last, addr;
    struct sockaddr_in dst;
    gint r;
    fd_set xxx;
    gint ret;
    struct timeval timeout;

    addr = ntohl(network) & 0xffffff00;

    for (last = 1; last <= 254 && node_ip_addr == 0; last++) {
        sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (sd < 0)
            return -1;

        unblock_socket(sd);

        struct linger l;
        l.l_onoff = 1;
        l.l_linger = 0;
        setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(struct linger));

        memset(&dst, 0, sizeof(dst));
        dst.sin_family = AF_INET;
        dst.sin_port = htons(SHIAI_PORT);
        dst.sin_addr.s_addr = htonl(addr + last);

        r = connect(sd, (const struct sockaddr *)&dst, sizeof(dst));

        g_usleep(500000);

        FD_ZERO(&xxx);
        FD_SET(sd, &xxx);
        timeout.tv_sec = 0;
        timeout.tv_usec = 0;

        ret = select(0, NULL, &xxx, NULL, &timeout);
        closesocket(sd);

        if (ret > 0) {
            dst.sin_addr.s_addr = htonl(addr + last);
            g_print("%s: node found\n", inet_ntoa(dst.sin_addr));
            return dst.sin_addr.s_addr;
        }

        g_usleep(1000000);
    }

    return 0;
}
예제 #12
0
int zmq::tcp_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    //  Create the socket.
    s = open_socket (addr->resolved.tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP);
#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        wsa_error_to_errno ();
        return -1;
    }
#else
    if (s == -1)
        return -1;
#endif

    //  On some systems, IPv4 mapping in IPv6 sockets is disabled by default.
    //  Switch it on in such cases.
    if (addr->resolved.tcp_addr->family () == AF_INET6)
        enable_ipv4_mapping (s);

    // Set the socket to non-blocking mode so that we get async connect().
    unblock_socket (s);

    //  Connect to the remote peer.
    int rc = ::connect (
        s, addr->resolved.tcp_addr->addr (),
        addr->resolved.tcp_addr->addrlen ());

    //  Connect was successfull immediately.
    if (rc == 0)
        return 0;

    //  Asynchronous connect was launched.
#ifdef ZMQ_HAVE_WINDOWS
    if (rc == SOCKET_ERROR && (WSAGetLastError () == WSAEINPROGRESS ||
          WSAGetLastError () == WSAEWOULDBLOCK)) {
        errno = EAGAIN;
        return -1;
    }    
    wsa_error_to_errno ();
#else
    if (rc == -1 && errno == EINPROGRESS) {
        errno = EAGAIN;
        return -1;
    }
#endif
    return -1;
}
예제 #13
0
int zmq::vmci_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    int family = this->get_ctx ()->get_vmci_socket_family ();
    if (family == -1)
        return -1;

    //  Create the socket.
    s = open_socket (family, SOCK_STREAM, 0);
#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        errno = wsa_error_to_errno(WSAGetLastError());
        return -1;
    }
#else
    if (s == -1)
        return -1;
#endif

    //  Set the non-blocking flag.
    unblock_socket (s);

    //  Connect to the remote peer.
    int rc = ::connect (
        s, addr->resolved.vmci_addr->addr (),
        addr->resolved.vmci_addr->addrlen ());

    //  Connect was successful immediately.
    if (rc == 0)
        return 0;

    //  Translate error codes indicating asynchronous connect has been
    //  launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
    const int error_code = WSAGetLastError();
    if (error_code == WSAEINPROGRESS || error_code == WSAEWOULDBLOCK)
        errno = EINPROGRESS;
    else
        errno = wsa_error_to_errno(error_code);
#else
    if (errno == EINTR)
        errno = EINPROGRESS;
#endif

    //  Forward the error.
    return -1;
}
예제 #14
0
파일: udp_engine.cpp 프로젝트: 5igm4/libzmq
int zmq::udp_engine_t::init (address_t *address_, bool send_, bool recv_)
{
    zmq_assert (address_);
    zmq_assert (send_ || recv_);
    send_enabled = send_;
    recv_enabled = recv_;
    address = address_;

    fd = open_socket (address->resolved.udp_addr->family (), SOCK_DGRAM, IPPROTO_UDP);
    if (fd == retired_fd)
        return -1;

    unblock_socket (fd);

    return 0;
}
예제 #15
0
zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_) :
    s (fd_),
    inpos (NULL),
    insize (0),
    decoder (in_batch_size, options_.maxmsgsize),
    input_error (false),
    outpos (NULL),
    outsize (0),
    encoder (out_batch_size),
    session (NULL),
    options (options_),
    plugged (false)
{
    //  Put the socket into non-blocking mode.
    unblock_socket (s);

    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf) {
        int rc = setsockopt (s, SOL_SOCKET, SO_SNDBUF,
            (char*) &options.sndbuf, sizeof (int));
#ifdef ZMQ_HAVE_WINDOWS
		wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }
    if (options.rcvbuf) {
        int rc = setsockopt (s, SOL_SOCKET, SO_RCVBUF,
            (char*) &options.rcvbuf, sizeof (int));
#ifdef ZMQ_HAVE_WINDOWS
		wsa_assert (rc != SOCKET_ERROR);
#else
        errno_assert (rc == 0);
#endif
    }

#if defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_FREEBSD
    //  Make sure that SIGPIPE signal is not generated when writing to a
    //  connection that was already closed by the peer.
    int set = 1;
    int rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
    errno_assert (rc == 0);
#endif
}
예제 #16
0
zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_, 
                                       const std::string &endpoint_) :
    s (fd_),
    inpos (NULL),
    insize (0),
    decoder (NULL),
    outpos (NULL),
    outsize (0),
    encoder (NULL),
    handshaking (true),
    greeting_size (v2_greeting_size),
    greeting_bytes_read (0),
    session (NULL),
    options (options_),
    endpoint (endpoint_),
    plugged (false),
    terminating (false),
    read_msg (&stream_engine_t::read_identity),
    write_msg (&stream_engine_t::write_identity),
    io_error (false),
    subscription_required (false),
    mechanism (NULL),
    input_paused (false),
    output_paused (false),
    socket (NULL)
{
    int rc = tx_msg.init ();
    errno_assert (rc == 0);
    
    //  Put the socket into non-blocking mode.
    unblock_socket (s);

    if (!get_peer_ip_address (s, peer_address))
        peer_address = "";

#ifdef SO_NOSIGPIPE
    //  Make sure that SIGPIPE signal is not generated when writing to a
    //  connection that was already closed by the peer.
    int set = 1;
    rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
    errno_assert (rc == 0);
#endif
}
예제 #17
0
int zmq::udp_receiver_t::init (const char *address_)
{
    int rc;

    rc = address.resolve (address_, false, !options.ipv6);
    if (rc != 0)
        return rc;

    //  Create a unconnected UDP socket, bind it to the requested address
    //  and make it non-blocking.
    socket = open_socket (address.family(), SOCK_DGRAM, IPPROTO_UDP);
    if (socket == -1)
        return -1;
    rc = ::bind (socket, address.addr(), address.addrlen());
    if (rc != 0)
        return -1;
    unblock_socket (socket);

    return 0;
}
예제 #18
0
int zmq::tcp_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    //  Resolve the address
    if (addr->resolved.tcp_addr != NULL) {
        delete addr->resolved.tcp_addr;
        addr->resolved.tcp_addr = NULL;
    }

    addr->resolved.tcp_addr = new (std::nothrow) tcp_address_t ();
    alloc_assert (addr->resolved.tcp_addr);
    int rc = addr->resolved.tcp_addr->resolve (
        addr->address.c_str (), false, options.ipv6);
    if (rc != 0) {
        delete addr->resolved.tcp_addr;
        addr->resolved.tcp_addr = NULL;
        return -1;
    }
    zmq_assert (addr->resolved.tcp_addr != NULL);
    tcp_address_t * const tcp_addr = addr->resolved.tcp_addr;

    //  Create the socket.
    s = open_socket (tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP);
#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        return -1;
    }
#else
    if (s == -1)
        return -1;
#endif

    //  On some systems, IPv4 mapping in IPv6 sockets is disabled by default.
    //  Switch it on in such cases.
    if (tcp_addr->family () == AF_INET6)
        enable_ipv4_mapping (s);

    // Set the IP Type-Of-Service priority for this socket
    if (options.tos != 0)
        set_ip_type_of_service (s, options.tos);

    // Set the socket to non-blocking mode so that we get async connect().
    unblock_socket (s);

    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf >= 0)
        set_tcp_send_buffer (s, options.sndbuf);
    if (options.rcvbuf >= 0)
        set_tcp_receive_buffer (s, options.rcvbuf);

    // Set the IP Type-Of-Service for the underlying socket
    if (options.tos != 0)
        set_ip_type_of_service (s, options.tos);

    // Set a source address for conversations
    if (tcp_addr->has_src_addr ()) {
        rc = ::bind (s, tcp_addr->src_addr (), tcp_addr->src_addrlen ());
        if (rc == -1)
            return -1;
    }

    //  Connect to the remote peer.
    rc = ::connect (s, tcp_addr->addr (), tcp_addr->addrlen ());

    //  Connect was successfull immediately.
    if (rc == 0)
        return 0;

    //  Translate error codes indicating asynchronous connect has been
    //  launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
    const int last_error = WSAGetLastError();
    if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK)
        errno = EINPROGRESS;
    else
        errno = wsa_error_to_errno (last_error);
#else
    if (errno == EINTR)
        errno = EINPROGRESS;
#endif
    return -1;
}
예제 #19
0
/* This version allows you to associate an existing sd with the msi so that you
 * can read/write it using the nsock infrastructure.  For example, you may want
 * to watch for data from STDIN_FILENO at the same time as you read/write
 * various sockets.  STDIN_FILENO is a special case, however. Any other sd is
 * dup()ed, so you may close or otherwise manipulate your copy.  The duped copy
 * will be destroyed when the nsi is destroyed. */
nsock_iod nsock_iod_new2(nsock_pool nsockp, int sd, void *userdata) {
  struct npool *nsp = (struct npool *)nsockp;
  gh_lnode_t *lnode;
  struct niod *nsi;

  lnode = gh_list_pop(&nsp->free_iods);
  if (!lnode) {
    nsi = (struct niod *)safe_malloc(sizeof(*nsi));
    memset(nsi, 0, sizeof(*nsi));
  } else {
    nsi = container_of(lnode, struct niod, nodeq);
  }

  if (sd == -1) {
    nsi->sd = -1;
    nsi->state = NSIOD_STATE_INITIAL;
  } else if (sd == STDIN_FILENO) {
    nsi->sd = STDIN_FILENO;
    nsi->state = NSIOD_STATE_UNKNOWN;
  } else {
    nsi->sd = dup_socket(sd);
    if (nsi->sd == -1) {
      free(nsi);
      return NULL;
    }
    unblock_socket(nsi->sd);
    nsi->state = NSIOD_STATE_UNKNOWN;
  }

  nsi->first_connect = NULL;
  nsi->first_read = NULL;
  nsi->first_write = NULL;
#if HAVE_PCAP
  nsi->first_pcap_read = NULL;
  nsi->readpcapsd_count = 0;
#endif
  nsi->readsd_count = 0;
  nsi->write_count = 0;

  nsi->userdata = userdata;
  nsi->nsp = (struct npool *)nsockp;

  nsi->_flags = 0;

  nsi->read_count = 0;
  nsi->write_count = 0;

  nsi->hostname = NULL;

  nsi->ipopts = NULL;
  nsi->ipoptslen = 0;

#if HAVE_OPENSSL
  nsi->ssl_session = NULL;
#endif

  if (nsp->px_chain) {
    nsi->px_ctx = proxy_chain_context_new(nsp);
  } else {
    nsi->px_ctx = NULL;
  }

  nsi->id = nsp->next_iod_serial++;
  if (nsi->id == 0)
    nsi->id = nsp->next_iod_serial++;

  /* The nsp keeps track of active iods so it can delete them if it is deleted */
  gh_list_append(&nsp->active_iods, &nsi->nodeq);

  nsock_log_info("nsock_iod_new (IOD #%lu)", nsi->id);

  return (nsock_iod)nsi;
}
예제 #20
0
static tree_cell * nasl_open_privileged_socket(lex_ctxt * lexic, int proto)
{
 struct arglist * script_infos = lexic->script_infos;
 int sport, current_sport = -1;
 int dport;
 int sock;
 int e, err;
 struct sockaddr_in addr, daddr;
 struct in_addr * p;
 int to = get_int_local_var_by_name(lexic, "timeout", lexic->recv_timeout);
 tree_cell * retc;
 struct timeval tv;
 fd_set rd;
 int opt, opt_sz;
 
 
 
 sport = get_int_local_var_by_name(lexic, "sport", -1);
 dport = get_int_local_var_by_name(lexic, "dport", -1);
 if(dport <= 0)
   {
     nasl_perror(lexic, "open_private_socket: missing or undefined parameter dport!\n");
     return NULL;
   }
 
 if(sport < 0) current_sport = 1023;


restart: 
 bzero(&addr, sizeof(addr));
 if(proto == IPPROTO_TCP)
  sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 else
  sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  
  
 /*
  * We will bind to a privileged port. Let's declare
  * our socket ready for reuse
  */
 
 if(sock < 0)
	 return NULL;
 add_socket(script_infos, sock);

tryagain :
 if ( current_sport < 128 ) return NULL;
 e =  set_socket_source_addr(sock, sport > 0 ? sport : current_sport--);
 
 /*
  * bind() failed - try again on a lower port
  */
 if(e < 0)
 {
  closesocket ( sock );
  if(sport > 0) 
    return NULL;
   else 
     goto tryagain;
 }
 
 /*
  * Connect to the other end
  */
 p = plug_get_host_ip(script_infos);
 bzero(&daddr, sizeof(daddr));
 daddr.sin_addr = *p;
 daddr.sin_port = htons(dport);
 daddr.sin_family = AF_INET;
 
 unblock_socket(sock);
 e = connect(sock, (struct sockaddr*)&daddr, sizeof(daddr));
 if ( e < 0 )
 {
   err = WSAGetLastError();
   if ( err == WSAEADDRINUSE || err == WSAEADDRNOTAVAIL )
   {
     closesocket(sock);
     if ( sport < 0 ) 
          goto restart;
     else  
          return NULL;
   }
 }

  do {
  tv.tv_sec = to;
  tv.tv_usec = 0;
  FD_ZERO(&rd);
  FD_SET(sock, &rd);
  e = select(sock + 1, NULL, &rd, NULL, to > 0 ? &tv:NULL);
  err = WSAGetLastError();
  } while ( e < 0 && err == WSAEINTR );

 block_socket(sock);
 opt_sz = sizeof(opt);

 if ( getsockopt(sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0 )
 {
  fprintf(stderr, "[%d] open_priv_sock()->getsockopt() failed : %s\n", getpid(), strerror(errno));
  closesocket(sock);
  return NULL;
 }
 

 switch ( opt )
 {
   case WSAEADDRINUSE:
   case WSAEADDRNOTAVAIL:
     closesocket ( sock );
     if ( sport < 0 )
 	 goto restart;
      else 
         return FAKE_CELL;

   case 0:
	break;
   default:
       closesocket ( sock );
       return FAKE_CELL;
       break;
 }
 
 if(proto == IPPROTO_TCP)
   sock = nessus_register_connection(sock, NULL);

  retc = alloc_tree_cell(0, NULL);
  retc->type = CONST_INT;
  retc->x.i_val = sock < 0 ? 0 : sock;
  return retc;
}
예제 #21
0
/*
// Name: main
// In: argv, the arguments sent to the program.
//	   argc, the number of arguments sent to the program.
*/
int main (int argc, char **argv) {
	char port[6];
	char ssl_port[6];
	if(!arguments(argv, argc, port, ssl_port)) {
		printf("Usage: chat_server [port] [ssl port]\n");
		return 0;
	}
	char topic[MAXTOKENSIZE];
	memset(topic, '\0', MAXTOKENSIZE);
	// Set the signal handler.
	signal(SIGINT, signal_handler);
	server_socket = -1;
	ssl_socket = -1;
	server_socket_fd;
	int epoll_fd;
	struct epoll_event event, ssl_event;
	BIO *sbio;
	SSL *ssl;
	// Initialize ssl context.
	ctx=init_ctx();
	memset(&event, 0, sizeof event);
	memset(&ssl_event, 0, sizeof event);
	printf("Trying to create socket.\n");
	server_socket_fd = create_socket("telnet", port);
	ssl_socket_fd = create_socket("telnet", ssl_port);
	printf("Created socket.\n");
	// Check if sockets couldn't be created.
	if(server_socket_fd<0 || ssl_socket_fd<0) {
		fprintf(stderr, "Socket could not be created!\n");
		return -1;
	}
	// Set the socket to be non-blocking.
	server_socket = unblock_socket(server_socket_fd);
	ssl_socket = unblock_socket(ssl_socket_fd);
	if(server_socket<0 || ssl_socket<0) {
		fprintf(stderr, "Could not make socket non blocking.\n");
		return -1;
	}
	printf("Listening...\n");
	// Listen for incoming connections.
	server_socket = listen(server_socket_fd, NUMBER_PENDING_CONNECTIONS);
	ssl_socket = listen(ssl_socket_fd, NUMBER_PENDING_CONNECTIONS);
	if(server_socket < 0 || ssl_socket<0) {
		fprintf(stderr, "Could not listen to incoming connections.\n");
		return -1;
	}
	epoll_fd = epoll_create1(0);
	event.data.fd = server_socket_fd;
	// Run as edge-triggered, meaning that epoll_wait will return only on
	// new events.
	event.events = EPOLLIN | EPOLLET;
	// Create epoll control interface for the unsecure socket.
	server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 
								server_socket_fd, &event);
	ssl_event.data.fd=ssl_socket_fd;
	ssl_event.events = EPOLLIN | EPOLLET;
	// Create epoll control interface for the secure socket.
	ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ssl_socket_fd, &ssl_event);
	if(server_socket<0 || ssl_socket<0) {
		fprintf(stderr, "Could not create control interface for polling.\n");
		return -1;
	}
	events = calloc(MAXEVENTS, sizeof event);
	// Create hash map for storing connected clients.
	clients = hash_empty(MAXCLIENTS);
	struct sockaddr client_addr;
	socklen_t client_len;
	int insocket_fd;
	int client_socket;
	char host[MAXHOST_LEN], serv[MAXSERV_LEN];
	client_len = sizeof client_addr;
	// Main loop listening from events generated by epoll.
	while(1) {
		int n,i;
		// Wait for new events.
		n = epoll_wait(epoll_fd, events, MAXEVENTS, -1);
		for(i=0;i<n;i++) {
			if((events[i].events & EPOLLERR) || 
				events[i].events & EPOLLHUP || 
				(!(events[i].events & EPOLLIN))) {
				fprintf(stderr, "An error occured at an event.\n");
				clientconn_t *c;
				// If the an error-event occured at a connected client.
				if((c = hash_get(events[i].data.fd, clients))!=NULL) {
					client_close(c);
					hash_remove(c, clients);
				}
				close(events[i].data.fd);
				continue;
			}
			// If an a connection is made on the unsecure socket.
			else if(server_socket_fd == events[i].data.fd) {
				while(1) {
					// Accept connection.
					insocket_fd = accept(server_socket_fd, 
									&client_addr, &client_len);
					if(insocket_fd<0) {
						if(!(errno == EAGAIN || errno == EWOULDBLOCK)) {
							fprintf(stderr, "Could not accept "
											"input connection");
							break;
						} else {
							// If the whole handshake could not be made, 
							// keep trying to accept.
							break;
						}
					}
					// The address information.
					server_socket = getnameinfo(&client_addr, client_len, host,
							sizeof host, serv, sizeof serv, 
							NI_NUMERICHOST|NI_NUMERICSERV);
					if(server_socket==0) {
						printf("Connection accepted!\n");
					}
					// Make client socket non-blocking.
					server_socket = unblock_socket(insocket_fd);
					if(server_socket <0) {
						fprintf(stderr, "Could not make client socket "
								"non-blocking\n");
						return -1;
					}
					// Create an epoll interface for the client socket.
					event.data.fd = insocket_fd;
					event.events = EPOLLIN|EPOLLET;
					server_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, 
									insocket_fd, &event);
					if(server_socket<0) {
						fprintf(stderr, "Could not create epoll "
										"interface for client\n");
						return -1;
					}
					printf("Added client(%d)!\n", insocket_fd);
					// Store client in the hash map.
					c = create_client(insocket_fd, &client_addr);
					hash_insert(c, clients);
				}
				continue;
			}
			// If a connection is made on the secure socket.
			else if(ssl_socket_fd == events[i].data.fd) {
				printf("Someone connected through ssl!\n");
				while(1) {
					// Accept in the same way as the unsecure socket.
					insocket_fd = accept(ssl_socket_fd, 
										&client_addr, &client_len);
					if(insocket_fd<0) {
						if(!(errno == EAGAIN || errno == EWOULDBLOCK)) {
							fprintf(stderr, "Could not accept input "
											"connection\n");
							break;
						} else {
							break;
						}
					}
					ssl_socket = getnameinfo(&client_addr, client_len, host, 
							sizeof host, serv, sizeof serv, 
							NI_NUMERICHOST|NI_NUMERICSERV);
					if(ssl_socket==0) {
						printf("Connection accepted!\n");
					}
					// Make socket non-blocking
					ssl_socket = unblock_socket(insocket_fd);
					if(ssl_socket<0){
						fprintf(stderr, "Could not make secure client "
										"socket non-blocking.\n");
						return -1;
					}
					// Create epoll interface for the secure client connection
					ssl_event.data.fd = insocket_fd;
					ssl_event.events = EPOLLIN;
					ssl_socket = epoll_ctl(epoll_fd, EPOLL_CTL_ADD,
											insocket_fd, &ssl_event);
					if(ssl_socket<0) {
						fprintf(stderr, "Could not create "
										"epoll interface for client.\n");
						return -1;
					}
					printf("Added client!(%d)\n", insocket_fd);
					c = create_client(insocket_fd, &client_addr);
					// Set up ssl.
					c->ssl_status=STATUS_HANDSHAKE;
					c->ssl = SSL_new(ctx);
					SSL_set_fd(c->ssl, insocket_fd);
					SSL_set_mode(c->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
					hash_insert(c, clients);
				}
				continue;
			}
			// If an incoming message has caused an event.
			else {
				int done = 0;
				while (1) {
					ssize_t count;
					char buf[MAXBUFSIZE];
					memset(buf, '\0', MAXBUFSIZE);
					clientconn_t *c = hash_get(events[i].data.fd, clients);
					// If the client is trying to make an ssl handshake.
					if(c->ssl_status==STATUS_HANDSHAKE) {
						int r=1;
						r=SSL_accept(c->ssl);
						if (r<0) {
							if(SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_READ &&
							  SSL_get_error(c->ssl, r)!=SSL_ERROR_WANT_WRITE ){
									done=1;
									printf("Could not accept ssl "
											"connection\n");
								break;
							}
						} else {
							// Handshake is done.
							c->ssl_status=STATUS_ACCEPTED;
						}
					}
					else {
						// Read data from client.
						int count = client_read(c, buf, sizeof buf);
						if(count<0) {
							if(errno!=EAGAIN) {
								fprintf(stderr, "Could not read"
											" from socket!\n");
								done=1;
							}
							break;
						}
						if(buf[MAXBUFSIZE-1] != '\0') {
							write(events[i].data.fd, "* BAD Buffer will "
													"overflow\r\n", 28);
							break;
						}
						else if (count==0) {
							done=1;
							break;
						}
						if (handle_input(events[i].data.fd, 
								buf, count, clients, topic)==CLIENTCLOSED) {
							done=1;
							break;
						}
						if(server_socket<0) {
							fprintf(stderr, "Could get input.\n");
							return -1;
						}
					}
				}
				// Client connection is done, wants to disconnect.
				if(done) {
					printf("Closed connection!\n");
					clientconn_t *closeclient = hash_get(events[i].data.fd, 
															clients);
					if(closeclient != NULL) {
						hash_remove(closeclient, clients);
						client_close(closeclient);
					}
					close(events[i].data.fd);
				}
			}
		}
	}
	free(events);
	close(server_socket_fd);
	return 0;
}
예제 #22
0
파일: ncat_listen.c 프로젝트: Araleii/nmap
/* Accept a connection on a listening socket. Allow or deny the connection.
   Fork a command if o.cmdexec is set. Otherwise, add the new socket to the
   watch set. */
static void handle_connection(int socket_accept)
{
    union sockaddr_u remoteaddr;
    socklen_t ss_len;
    struct fdinfo s = { 0 };
    int conn_count;

    zmem(&s, sizeof(s));
    zmem(&remoteaddr, sizeof(remoteaddr.storage));

    ss_len = sizeof(remoteaddr.storage);

    errno = 0;
    s.fd = accept(socket_accept, &remoteaddr.sockaddr, &ss_len);

    if (s.fd < 0) {
        if (o.debug)
            logdebug("Error in accept: %s\n", strerror(errno));

        close(s.fd);
        return;
    }

    if (o.verbose) {
#if HAVE_SYS_UN_H
        if (remoteaddr.sockaddr.sa_family == AF_UNIX)
            loguser("Connection from a client on Unix domain socket.\n");
        else
#endif
        if (o.chat)
            loguser("Connection from %s on file descriptor %d.\n", inet_socktop(&remoteaddr), s.fd);
        else
            loguser("Connection from %s.\n", inet_socktop(&remoteaddr));
    }

    if (!o.keepopen && !o.broker) {
        int i;
        for (i = 0; i < num_listenaddrs; i++) {
            Close(listen_socket[i]);
            FD_CLR(listen_socket[i], &master_readfds);
            rm_fd(&client_fdlist, listen_socket[i]);
        }
    }

    if (o.verbose) {
#if HAVE_SYS_UN_H
        if (remoteaddr.sockaddr.sa_family == AF_UNIX)
            loguser("Connection from %s.\n", remoteaddr.un.sun_path);
        else
#endif
            loguser("Connection from %s:%hu.\n", inet_socktop(&remoteaddr), inet_port(&remoteaddr));
    }

    /* Check conditions that might cause us to deny the connection. */
    conn_count = get_conn_count();
    if (conn_count >= o.conn_limit) {
        if (o.verbose)
            loguser("New connection denied: connection limit reached (%d)\n", conn_count);
        Close(s.fd);
        return;
    }
    if (!allow_access(&remoteaddr)) {
        if (o.verbose)
            loguser("New connection denied: not allowed\n");
        Close(s.fd);
        return;
    }

    s.remoteaddr = remoteaddr;

    conn_inc++;

    unblock_socket(s.fd);

#ifdef HAVE_OPENSSL
    if (o.ssl) {
        /* Add the socket to the necessary descriptor lists. */
        FD_SET(s.fd, &sslpending_fds);
        FD_SET(s.fd, &master_readfds);
        FD_SET(s.fd, &master_writefds);
        /* Add it to our list of fds too for maintaining maxfd. */
        if (add_fdinfo(&client_fdlist, &s) < 0)
            bye("add_fdinfo() failed.");
    } else
#endif
        post_handle_connection(s);
}
예제 #23
0
파일: ncat_listen.c 프로젝트: Araleii/nmap
static int ncat_listen_stream(int proto)
{
    int rc, i, fds_ready;
    fd_set listen_fds;
    struct timeval tv;
    struct timeval *tvp = NULL;
    unsigned int num_sockets;

    /* clear out structs */
    FD_ZERO(&master_readfds);
    FD_ZERO(&master_writefds);
    FD_ZERO(&master_broadcastfds);
    FD_ZERO(&listen_fds);
#ifdef HAVE_OPENSSL
    FD_ZERO(&sslpending_fds);
#endif
    zmem(&client_fdlist, sizeof(client_fdlist));
    zmem(&broadcast_fdlist, sizeof(broadcast_fdlist));

#ifdef WIN32
    set_pseudo_sigchld_handler(decrease_conn_count);
#else
    /* Reap on SIGCHLD */
    Signal(SIGCHLD, sigchld_handler);
    /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
       send data to it before noticing. */
    Signal(SIGPIPE, SIG_IGN);
#endif

#ifdef HAVE_OPENSSL
    if (o.ssl)
        setup_ssl_listen();
#endif

/* Not sure if this problem exists on Windows, but fcntl and /dev/null don't */
#ifndef WIN32
    /* Check whether stdin is closed. Because we treat this fd specially, we
     * can't risk it being reopened for an incoming connection, so we'll hold
     * it open instead. */
    if (fcntl(STDIN_FILENO, F_GETFD) == -1 && errno == EBADF) {
      logdebug("stdin is closed, attempting to reserve STDIN_FILENO\n");
      rc = open("/dev/null", O_RDONLY);
      if (rc >= 0 && rc != STDIN_FILENO) {
        /* Oh well, we tried */
        logdebug("Couldn't reserve STDIN_FILENO\n");
        close(rc);
      }
    }
#endif

    /* We need a list of fds to keep current fdmax. The second parameter is a
       number added to the supplied connection limit, that will compensate
       maxfds for the added by default listen and stdin sockets. */
    init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1));

    for (i = 0; i < NUM_LISTEN_ADDRS; i++)
        listen_socket[i] = -1;

    num_sockets = 0;
    for (i = 0; i < num_listenaddrs; i++) {
        /* setup the main listening socket */
        listen_socket[num_sockets] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]);
        if (listen_socket[num_sockets] == -1) {
            if (o.debug > 0)
                logdebug("do_listen(\"%s\"): %s\n", inet_ntop_ez(&listenaddrs[i].storage, sizeof(listenaddrs[i].storage)), socket_strerror(socket_errno()));
            continue;
        }

        /* Make our listening socket non-blocking because there are timing issues
         * which could cause us to block on accept() even though select() says it's
         * readable.  See UNPv1 2nd ed, p422 for more.
         */
        unblock_socket(listen_socket[num_sockets]);

        /* setup select sets and max fd */
        FD_SET(listen_socket[num_sockets], &master_readfds);
        add_fd(&client_fdlist, listen_socket[num_sockets]);

        FD_SET(listen_socket[num_sockets], &listen_fds);

        num_sockets++;
    }
    if (num_sockets == 0) {
        if (num_listenaddrs == 1)
            bye("Unable to open listening socket on %s: %s", inet_ntop_ez(&listenaddrs[0].storage, sizeof(listenaddrs[0].storage)), socket_strerror(socket_errno()));
        else
            bye("Unable to open any listening sockets.");
    }

    add_fd(&client_fdlist, STDIN_FILENO);

    init_fdlist(&broadcast_fdlist, o.conn_limit);

    if (o.idletimeout > 0)
        tvp = &tv;

    while (1) {
        /* We pass these temporary descriptor sets to fselect, since fselect
           modifies the sets it receives. */
        fd_set readfds = master_readfds, writefds = master_writefds;
        struct fdinfo *fdi = NULL;

        if (o.debug > 1)
            logdebug("selecting, fdmax %d\n", client_fdlist.fdmax);

        if (o.debug > 1 && o.broker)
            logdebug("Broker connection count is %d\n", get_conn_count());

        if (o.idletimeout > 0)
            ms_to_timeval(tvp, o.idletimeout);

        fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, tvp);

        if (o.debug > 1)
            logdebug("select returned %d fds ready\n", fds_ready);

        if (fds_ready == 0)
            bye("Idle timeout expired (%d ms).", o.idletimeout);

        /*
         * FIXME: optimize this loop to look only at the fds in the fd list,
         * doing it this way means that if you have one descriptor that is very
         * large, say 500, and none close to it, that you'll loop many times for
         * nothing.
         */
        for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) {
            /* Loop through descriptors until there's something to read */
            if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds))
                continue;

            if (o.debug > 1)
                logdebug("fd %d is ready\n", i);

#ifdef HAVE_OPENSSL
            /* Is this an ssl socket pending a handshake? If so handle it. */
            if (o.ssl && FD_ISSET(i, &sslpending_fds)) {
                FD_CLR(i, &master_readfds);
                FD_CLR(i, &master_writefds);
                fdi = get_fdinfo(&client_fdlist, i);
                ncat_assert(fdi != NULL);
                switch (ssl_handshake(fdi)) {
                case NCAT_SSL_HANDSHAKE_COMPLETED:
                    /* Clear from sslpending_fds once ssl is established */
                    FD_CLR(i, &sslpending_fds);
                    post_handle_connection(*fdi);
                    break;
                case NCAT_SSL_HANDSHAKE_PENDING_WRITE:
                    FD_SET(i, &master_writefds);
                    break;
                case NCAT_SSL_HANDSHAKE_PENDING_READ:
                    FD_SET(i, &master_readfds);
                    break;
                case NCAT_SSL_HANDSHAKE_FAILED:
                default:
                    SSL_free(fdi->ssl);
                    Close(fdi->fd);
                    FD_CLR(i, &sslpending_fds);
                    FD_CLR(i, &master_readfds);
                    rm_fd(&client_fdlist, i);
                    /* Are we in single listening mode(without -k)? If so
                       then we should quit also. */
                    if (!o.keepopen && !o.broker)
                        return 1;
                    --conn_inc;
                    break;
                }
            } else
#endif
            if (FD_ISSET(i, &listen_fds)) {
                /* we have a new connection request */
                handle_connection(i);
            } else if (i == STDIN_FILENO) {
                if (o.broker) {
                    read_and_broadcast(i);
                } else {
                    /* Read from stdin and write to all clients. */
                    rc = read_stdin();
                    if (rc == 0) {
                        if (o.proto != IPPROTO_TCP || (o.proto == IPPROTO_TCP && o.sendonly)) {
                            /* There will be nothing more to send. If we're not
                               receiving anything, we can quit here. */
                            return 0;
                        }
                        if (!o.noshutdown) shutdown_sockets(SHUT_WR);
                    }
                    if (rc < 0)
                        return 1;
                }
            } else if (!o.sendonly) {
                if (o.broker) {
                    read_and_broadcast(i);
                } else {
                    /* Read from a client and write to stdout. */
                    rc = read_socket(i);
                    if (rc <= 0 && !o.keepopen)
                        return rc == 0 ? 0 : 1;
                }
            }

            fds_ready--;
        }
    }

    return 0;
}
예제 #24
0
zmq::stream_engine_t::stream_engine_t (fd_t fd_, const options_t &options_,
                                       const std::string &endpoint_) :
    s (fd_),
    inpos (NULL),
    insize (0),
    decoder (NULL),
    outpos (NULL),
    outsize (0),
    encoder (NULL),
    metadata (NULL),
    handshaking (true),
    greeting_size (v2_greeting_size),
    greeting_bytes_read (0),
    session (NULL),
    options (options_),
    endpoint (endpoint_),
    plugged (false),
    next_msg (&stream_engine_t::identity_msg),
    process_msg (&stream_engine_t::process_identity_msg),
    io_error (false),
    subscription_required (false),
    mechanism (NULL),
    input_stopped (false),
    output_stopped (false),
    has_handshake_timer (false),
    socket (NULL)
{
    int rc = tx_msg.init ();
    errno_assert (rc == 0);

    //  Put the socket into non-blocking mode.
    unblock_socket (s);

    int family = get_peer_ip_address (s, peer_address);
    if (family == 0)
        peer_address.clear();
#if defined ZMQ_HAVE_SO_PEERCRED
    else
    if (family == PF_UNIX) {
        struct ucred cred;
        socklen_t size = sizeof (cred);
        if (!getsockopt (s, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
            std::ostringstream buf;
            buf << ":" << cred.uid << ":" << cred.gid << ":" << cred.pid;
            peer_address += buf.str ();
        }
    }
#elif defined ZMQ_HAVE_LOCAL_PEERCRED
    else
    if (family == PF_UNIX) {
        struct xucred cred;
        socklen_t size = sizeof (cred);
        if (!getsockopt (s, 0, LOCAL_PEERCRED, &cred, &size)
                && cred.cr_version == XUCRED_VERSION) {
            std::ostringstream buf;
            buf << ":" << cred.cr_uid << ":";
            if (cred.cr_ngroups > 0)
                buf << cred.cr_groups[0];
            buf << ":";
            peer_address += buf.str ();
        }
    }
#endif

#ifdef SO_NOSIGPIPE
    //  Make sure that SIGPIPE signal is not generated when writing to a
    //  connection that was already closed by the peer.
    int set = 1;
    rc = setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof (int));
    errno_assert (rc == 0);
#endif
}
예제 #25
0
static int ncat_listen_stream(int proto)
{
    int rc, i, fds_ready;
    fd_set listen_fds;

    /* clear out structs */
    FD_ZERO(&master_readfds);
    FD_ZERO(&master_writefds);
    FD_ZERO(&master_broadcastfds);
    FD_ZERO(&listen_fds);
#ifdef HAVE_OPENSSL
    FD_ZERO(&sslpending_fds);
#endif
    zmem(&client_fdlist, sizeof(client_fdlist));
    zmem(&broadcast_fdlist, sizeof(broadcast_fdlist));

#ifdef WIN32
    set_pseudo_sigchld_handler(decrease_conn_count);
#else
    /* Reap on SIGCHLD */
    Signal(SIGCHLD, sigchld_handler);
    /* Ignore the SIGPIPE that occurs when a client disconnects suddenly and we
       send data to it before noticing. */
    Signal(SIGPIPE, SIG_IGN);
#endif

#ifdef HAVE_OPENSSL
    if (o.ssl)
        setup_ssl_listen();
#endif

    /* We need a list of fds to keep current fdmax. The second parameter is a
       number added to the supplied connection limit, that will compensate
       maxfds for the added by default listen and stdin sockets. */
    init_fdlist(&client_fdlist, sadd(o.conn_limit, num_listenaddrs + 1));

    for (i = 0; i < NUM_LISTEN_ADDRS; i++)
        listen_socket[i] = -1;

    for (i = 0; i < num_listenaddrs; i++) {
        /* setup the main listening socket */
        listen_socket[i] = do_listen(SOCK_STREAM, proto, &listenaddrs[i]);

        /* Make our listening socket non-blocking because there are timing issues
         * which could cause us to block on accept() even though select() says it's
         * readable.  See UNPv1 2nd ed, p422 for more.
         */
        unblock_socket(listen_socket[i]);

        /* setup select sets and max fd */
        FD_SET(listen_socket[i], &master_readfds);
        add_fd(&client_fdlist, listen_socket[i]);

        FD_SET(listen_socket[i], &listen_fds);
    }
    add_fd(&client_fdlist, STDIN_FILENO);

    init_fdlist(&broadcast_fdlist, o.conn_limit);

    while (1) {
        /* We pass these temporary descriptor sets to fselect, since fselect
           modifies the sets it receives. */
        fd_set readfds = master_readfds, writefds = master_writefds;
        struct fdinfo *fdi = NULL;

        if (o.debug > 1)
            logdebug("selecting, fdmax %d\n", client_fdlist.fdmax);

        if (o.debug > 1 && o.broker)
            logdebug("Broker connection count is %d\n", get_conn_count());

        fds_ready = fselect(client_fdlist.fdmax + 1, &readfds, &writefds, NULL, NULL);

        if (o.debug > 1)
            logdebug("select returned %d fds ready\n", fds_ready);

        /*
         * FIXME: optimize this loop to look only at the fds in the fd list,
         * doing it this way means that if you have one descriptor that is very
         * large, say 500, and none close to it, that you'll loop many times for
         * nothing.
         */
        for (i = 0; i <= client_fdlist.fdmax && fds_ready > 0; i++) {
            /* Loop through descriptors until there's something to read */
            if (!FD_ISSET(i, &readfds) && !FD_ISSET(i, &writefds))
                continue;

            if (o.debug > 1)
                logdebug("fd %d is ready\n", i);

#ifdef HAVE_OPENSSL
            /* Is this an ssl socket pending a handshake? If so handle it. */
            if (o.ssl && FD_ISSET(i, &sslpending_fds)) {
                FD_CLR(i, &master_readfds);
                FD_CLR(i, &master_writefds);
                fdi = get_fdinfo(&client_fdlist, i);
                switch(ssl_handshake(fdi)){
                case NCAT_SSL_HANDSHAKE_COMPLETED:
                    /* Clear from sslpending_fds once ssl is established */
                    FD_CLR(i, &sslpending_fds);
                    rm_fd(&client_fdlist, i);
                    post_handle_connection(*fdi);
                    break;
                case NCAT_SSL_HANDSHAKE_PENDING_WRITE:
                    FD_SET(i, &master_writefds);
                    break;
                case NCAT_SSL_HANDSHAKE_PENDING_READ:
                    FD_SET(i, &master_readfds);
                    break;
                case NCAT_SSL_HANDSHAKE_FAILED:
                default:
                    SSL_free(fdi->ssl);
                    Close(fdi->fd);
                    FD_CLR(i, &sslpending_fds);
                    FD_CLR(i, &master_readfds);
                    rm_fd(&client_fdlist, i);
                    /* Are we in single listening mode(without -k)? If so
                       then we should quit also. */
                    if (!o.keepopen && !o.broker)
                        return 1;
                    --conn_inc;
                    break;
                }
            } else
#endif
            if (FD_ISSET(i, &listen_fds)) {
                /* we have a new connection request */
                handle_connection(i);
            } else if (i == STDIN_FILENO) {
                if(o.broker) {
                    read_and_broadcast(i);
                }else {
                    /* Read from stdin and write to all clients. */
                    rc = read_stdin();
                    if (rc == 0 && o.sendonly)
                        /* There will be nothing more to send. If we're not
                           receiving anything, we can quit here. */
                        return 0;
                    if (rc < 0)
                        return 1;
                }
            } else if (!o.sendonly) {
                if(o.broker) {
                    read_and_broadcast(i);
                }else {
                    /* Read from a client and write to stdout. */
                    rc = read_socket(i);
                    if (rc <= 0 && !o.keepopen)
                        return rc == 0 ? 0 : 1;
                }
            }

            fds_ready--;
        }
    }

    return 0;
}
예제 #26
0
zmq::stream_engine_t::stream_engine_t (fd_t fd_,
                                       const options_t &options_,
                                       const std::string &endpoint_) :
    _s (fd_),
    _as_server (false),
    _handle (static_cast<handle_t> (NULL)),
    _inpos (NULL),
    _insize (0),
    _decoder (NULL),
    _outpos (NULL),
    _outsize (0),
    _encoder (NULL),
    _metadata (NULL),
    _handshaking (true),
    _greeting_size (v2_greeting_size),
    _greeting_bytes_read (0),
    _session (NULL),
    _options (options_),
    _endpoint (endpoint_),
    _plugged (false),
    _next_msg (&stream_engine_t::routing_id_msg),
    _process_msg (&stream_engine_t::process_routing_id_msg),
    _io_error (false),
    _subscription_required (false),
    _mechanism (NULL),
    _input_stopped (false),
    _output_stopped (false),
    _has_handshake_timer (false),
    _has_ttl_timer (false),
    _has_timeout_timer (false),
    _has_heartbeat_timer (false),
    _heartbeat_timeout (0),
    _socket (NULL)
{
    int rc = _tx_msg.init ();
    errno_assert (rc == 0);
    rc = _pong_msg.init ();
    errno_assert (rc == 0);

    //  Put the socket into non-blocking mode.
    unblock_socket (_s);

    int family = get_peer_ip_address (_s, _peer_address);
    if (family == 0)
        _peer_address.clear ();
#if defined ZMQ_HAVE_SO_PEERCRED
    else if (family == PF_UNIX) {
        struct ucred cred;
        socklen_t size = sizeof (cred);
        if (!getsockopt (_s, SOL_SOCKET, SO_PEERCRED, &cred, &size)) {
            std::ostringstream buf;
            buf << ":" << cred.uid << ":" << cred.gid << ":" << cred.pid;
            _peer_address += buf.str ();
        }
    }
#elif defined ZMQ_HAVE_LOCAL_PEERCRED
    else if (family == PF_UNIX) {
        struct xucred cred;
        socklen_t size = sizeof (cred);
        if (!getsockopt (_s, 0, LOCAL_PEERCRED, &cred, &size)
            && cred.cr_version == XUCRED_VERSION) {
            std::ostringstream buf;
            buf << ":" << cred.cr_uid << ":";
            if (cred.cr_ngroups > 0)
                buf << cred.cr_groups[0];
            buf << ":";
            _peer_address += buf.str ();
        }
    }
#endif

    if (_options.heartbeat_interval > 0) {
        _heartbeat_timeout = _options.heartbeat_timeout;
        if (_heartbeat_timeout == -1)
            _heartbeat_timeout = _options.heartbeat_interval;
    }
}
예제 #27
0
static tree_cell *
nasl_open_privileged_socket (lex_ctxt * lexic, int proto)
{
  struct arglist *script_infos = lexic->script_infos;
  int sport, current_sport = -1;
  int dport;
  int sock;
  int e;
  struct sockaddr_in addr, daddr;
  struct sockaddr_in6 addr6, daddr6;
  struct in6_addr *p;
  int to = get_int_local_var_by_name (lexic, "timeout", lexic->recv_timeout);
  tree_cell *retc;
  struct timeval tv;
  fd_set rd;
  int opt;
  unsigned int opt_sz;
  int family;



  sport = get_int_local_var_by_name (lexic, "sport", -1);
  dport = get_int_local_var_by_name (lexic, "dport", -1);
  if (dport <= 0)
    {
      nasl_perror (lexic,
                   "open_private_socket: missing or undefined parameter dport!\n");
      return NULL;
    }

  if (sport < 0)
    current_sport = 1023;


restart:
  p = plug_get_host_ip (script_infos);
  if (IN6_IS_ADDR_V4MAPPED (p))
    {
      family = AF_INET;
      bzero (&addr, sizeof (addr));
      if (proto == IPPROTO_TCP)
        sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      else
        sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    }
  else
    {
      family = AF_INET6;
      bzero (&addr6, sizeof (addr6));
      if (proto == IPPROTO_TCP)
        sock = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
      else
        sock = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
    }


  /*
   * We will bind to a privileged port. Let's declare
   * our socket ready for reuse
   */

  if (sock < 0)
    return NULL;

tryagain:
  if (current_sport < 128 && sport < 0)
    return NULL;
  e =
    openvas_source_set_socket (sock, sport > 0 ? sport : current_sport--, family);

  /*
   * bind() failed - try again on a lower port
   */
  if (e < 0)
    {
      close (sock);
      if (sport > 0)
        return NULL;
      else
        goto tryagain;
    }


  /*
   * Connect to the other end
   */
  p = plug_get_host_ip (script_infos);

  if (IN6_IS_ADDR_V4MAPPED (p))
    {
      bzero (&daddr, sizeof (daddr));
      daddr.sin_addr.s_addr = p->s6_addr32[3];
      daddr.sin_family = AF_INET;
      daddr.sin_port = htons (dport);
      unblock_socket (sock);
      e = connect (sock, (struct sockaddr *) &daddr, sizeof (daddr));
    }
  else
    {
      bzero (&daddr6, sizeof (daddr6));
      memcpy (&daddr6.sin6_addr, p, sizeof (struct in6_addr));
      daddr6.sin6_family = AF_INET6;
      daddr6.sin6_port = htons (dport);
      unblock_socket (sock);
      e = connect (sock, (struct sockaddr *) &daddr6, sizeof (daddr6));
    }


  if (e < 0)
    {
      if (errno == EADDRINUSE || errno == EADDRNOTAVAIL)
        {
          close (sock);
          if (sport < 0)
            goto restart;
          else
            return NULL;
        }
      else if (errno != EINPROGRESS)
        {
          close (sock);
          return NULL;
        }
    }

  do
    {
      tv.tv_sec = to;
      tv.tv_usec = 0;
      FD_ZERO (&rd);
      FD_SET (sock, &rd);
      e = select (sock + 1, NULL, &rd, NULL, to > 0 ? &tv : NULL);
    }
  while (e < 0 && errno == EINTR);

  if (e <= 0)
    {
      close (sock);
      return FAKE_CELL;
    }

  block_socket (sock);
  opt_sz = sizeof (opt);

  if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &opt, &opt_sz) < 0)
    {
      log_legacy_write ("[%d] open_priv_sock()->getsockopt() failed : %s\n",
                        getpid (), strerror (errno));
      close (sock);
      return NULL;
    }


  switch (opt)
    {
    case EADDRINUSE:
    case EADDRNOTAVAIL:
      close (sock);
      if (sport < 0)
        goto restart;
      else
        return FAKE_CELL;

    case 0:
      break;
    default:
      close (sock);
      return FAKE_CELL;
      break;
    }

  if (proto == IPPROTO_TCP)
    sock = openvas_register_connection (sock, NULL, NULL,
                                        OPENVAS_ENCAPS_TLScustom);

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_INT;
  retc->x.i_val = sock < 0 ? 0 : sock;
  return retc;
}
예제 #28
0
/*
 * Simple forking HTTP proxy. It is an HTTP/1.0 proxy with knowledge of
 * HTTP/1.1. (The things lacking for HTTP/1.1 are the chunked transfer encoding
 * and the expect mechanism.) The proxy supports the CONNECT, GET, HEAD, and
 * POST methods. It supports Basic and Digest authentication of clients (use the
 * --proxy-auth option).
 *
 * HTTP/1.1 is defined in RFC 2616. Many comments refer to that document.
 * http://tools.ietf.org/html/rfc2616
 *
 * HTTP authentication is discussed in RFC 2617.
 * http://tools.ietf.org/html/rfc2617
 *
 * The CONNECT method is documented in an Internet draft and is specified as the
 * way to proxy HTTPS in RFC 2817, section 5.
 * http://tools.ietf.org/html/draft-luotonen-web-proxy-tunneling-01
 * http://tools.ietf.org/html/rfc2817#section-5
 *
 * The CONNECT method is not limited to HTTP, but is potentially capable of
 * connecting to any TCP port on any host. The proxy connection is requested
 * with an HTTP request, but after that, the proxy does no interpretation of the
 * data passing through it. See section 6 of the above mentioned draft for the
 * security implications.
 */
int ncat_http_server(void)
{
    int c, i, j;
    int listen_socket[NUM_LISTEN_ADDRS];
    socklen_t sslen;
    union sockaddr_u conn;
    struct timeval tv;
    struct timeval *tvp = NULL;

#ifndef WIN32
    Signal(SIGCHLD, proxyreaper);
#endif

#if HAVE_HTTP_DIGEST
    http_digest_init_secret();
#endif

#ifdef HAVE_OPENSSL
    if (o.ssl)
        setup_ssl_listen();
#endif
    /* Clear the socket list */
    for (i = 0; i < NUM_LISTEN_ADDRS; i++)
        listen_socket[i] = -1;

    /* set for selecting listening sockets */
    fd_set listen_fds;
    fd_list_t listen_fdlist;
    FD_ZERO(&listen_fds);
    init_fdlist(&listen_fdlist, num_listenaddrs);

    /* Listen on each address, set up lists for select */
    for (i = 0; i < num_listenaddrs; i++) {
        listen_socket[i] = do_listen(SOCK_STREAM, IPPROTO_TCP, &listenaddrs[i]);

        /* make us not block on accepts in wierd cases. See ncat_listen.c:209 */
        unblock_socket(listen_socket[i]);

        /* setup select sets and max fd */
        FD_SET(listen_socket[i], &listen_fds);
        add_fd(&listen_fdlist, listen_socket[i]);

    }

    if (o.idletimeout > 0)
        tvp = &tv;

    for (;;) {
        fd_set read_fds;

        sslen = sizeof(conn.storage);
        /*
         * We just select to get a list of sockets which we can talk to
         */
        if (o.debug > 1)
            logdebug("selecting, fdmax %d\n", listen_fdlist.fdmax);
        read_fds = listen_fds;

        if (o.idletimeout > 0)
            ms_to_timeval(tvp, o.idletimeout);

        int fds_ready = fselect(listen_fdlist.fdmax + 1, &read_fds, NULL, NULL, tvp);

        if (o.debug > 1)
            logdebug("select returned %d fds ready\n", fds_ready);

        if (fds_ready == 0)
            bye("Idle timeout expired (%d ms).", o.idletimeout);

        for (i = 0; i <= listen_fdlist.fdmax && fds_ready > 0; i++) {
            /* Loop through descriptors until there is something ready */
            if (!FD_ISSET(i, &read_fds))
                continue;

            /* Check each listening socket */
            for (j = 0; j < num_listenaddrs; j++) {
                if (i == listen_socket[j]) {
                    fds_ready--;
                    c = accept(i, &conn.sockaddr, &sslen);

                    if (c == -1) {
                        if (errno == EINTR)
                            continue;
                        die("accept");
                    }

                    if (!allow_access(&conn)) {
                        Close(c);
                        continue;
                    }
                    if (o.debug > 1)
                        logdebug("forking handler for %d\n", i);
                    fork_handler(i, c);
                }
            }
        }
    }
    return 0;
}
예제 #29
0
int zmq::tcp_connecter_t::open ()
{
    zmq_assert (s == retired_fd);

    //  Resolve the address
    if (addr->resolved.tcp_addr != NULL) {
        LIBZMQ_DELETE (addr->resolved.tcp_addr);
    }

    addr->resolved.tcp_addr = new (std::nothrow) tcp_address_t ();
    alloc_assert (addr->resolved.tcp_addr);
    int rc = addr->resolved.tcp_addr->resolve (addr->address.c_str (), false,
                                               options.ipv6);
    if (rc != 0) {
        LIBZMQ_DELETE (addr->resolved.tcp_addr);
        return -1;
    }
    zmq_assert (addr->resolved.tcp_addr != NULL);
    tcp_address_t *const tcp_addr = addr->resolved.tcp_addr;

    //  Create the socket.
    s = open_socket (tcp_addr->family (), SOCK_STREAM, IPPROTO_TCP);

    //  IPv6 address family not supported, try automatic downgrade to IPv4.
    if (s == zmq::retired_fd && tcp_addr->family () == AF_INET6
        && errno == EAFNOSUPPORT && options.ipv6) {
        rc = addr->resolved.tcp_addr->resolve (addr->address.c_str (), false,
                                               false);
        if (rc != 0) {
            LIBZMQ_DELETE (addr->resolved.tcp_addr);
            return -1;
        }
        s = open_socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    }

#ifdef ZMQ_HAVE_WINDOWS
    if (s == INVALID_SOCKET) {
        errno = wsa_error_to_errno (WSAGetLastError ());
        return -1;
    }
#else
    if (s == -1)
        return -1;
#endif

    //  On some systems, IPv4 mapping in IPv6 sockets is disabled by default.
    //  Switch it on in such cases.
    if (tcp_addr->family () == AF_INET6)
        enable_ipv4_mapping (s);

    // Set the IP Type-Of-Service priority for this socket
    if (options.tos != 0)
        set_ip_type_of_service (s, options.tos);

    // Bind the socket to a device if applicable
    if (!options.bound_device.empty ())
        bind_to_device (s, options.bound_device);

    // Set the socket to non-blocking mode so that we get async connect().
    unblock_socket (s);

    // Set the socket to loopback fastpath if configured.
    if (options.loopback_fastpath)
        tcp_tune_loopback_fast_path (s);

    //  Set the socket buffer limits for the underlying socket.
    if (options.sndbuf >= 0)
        set_tcp_send_buffer (s, options.sndbuf);
    if (options.rcvbuf >= 0)
        set_tcp_receive_buffer (s, options.rcvbuf);

    // Set the IP Type-Of-Service for the underlying socket
    if (options.tos != 0)
        set_ip_type_of_service (s, options.tos);

    // Set a source address for conversations
    if (tcp_addr->has_src_addr ()) {
        //  Allow reusing of the address, to connect to different servers
        //  using the same source port on the client.
        int flag = 1;
#ifdef ZMQ_HAVE_WINDOWS
        rc = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (const char *) &flag,
                         sizeof (int));
        wsa_assert (rc != SOCKET_ERROR);
#else
        rc = setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof (int));
        errno_assert (rc == 0);
#endif

        rc = ::bind (s, tcp_addr->src_addr (), tcp_addr->src_addrlen ());
        if (rc == -1)
            return -1;
    }

    //  Connect to the remote peer.
    rc = ::connect (s, tcp_addr->addr (), tcp_addr->addrlen ());

    //  Connect was successful immediately.
    if (rc == 0) {
        return 0;
    }

    //  Translate error codes indicating asynchronous connect has been
    //  launched to a uniform EINPROGRESS.
#ifdef ZMQ_HAVE_WINDOWS
    const int last_error = WSAGetLastError ();
    if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK)
        errno = EINPROGRESS;
    else
        errno = wsa_error_to_errno (last_error);
#else
    if (errno == EINTR)
        errno = EINPROGRESS;
#endif
    return -1;
}