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); }
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 }
/* 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; }
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; }
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 }
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; }
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; }
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 }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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 }
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 }
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; }
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; }
/* 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; }
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; }
/* // 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; }
/* 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); }
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; }
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 }
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; }
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; } }
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; }
/* * 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; }
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; }