/* This function handles the post connection specific actions that are needed * after a socket has been initialized(normal socket or ssl socket). */ static void post_handle_connection(struct fdinfo sinfo) { /* * Are we executing a command? If so then don't add this guy * to our descriptor list or set. */ if (o.cmdexec) { if (o.keepopen) netrun(&sinfo, o.cmdexec); else netexec(&sinfo, o.cmdexec); } else { /* Now that a client is connected, pay attention to stdin. */ if (!stdin_eof) FD_SET(STDIN_FILENO, &master_readfds); if (!o.sendonly) { /* add to our lists */ FD_SET(sinfo.fd, &master_readfds); /* add it to our list of fds for maintaining maxfd */ #ifdef HAVE_OPENSSL /* Don't add it twice (see handle_connection above) */ if (!o.ssl) #endif if (add_fdinfo(&client_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); } FD_SET(sinfo.fd, &master_broadcastfds); if (add_fdinfo(&broadcast_fdlist, &sinfo) < 0) bye("add_fdinfo() failed."); if (o.chat) chat_announce_connect(sinfo.fd, &sinfo.remoteaddr); } }
/* Add a descriptor to the list. Use this when you are only adding to the list * for the side effect of increasing fdmax, and don't care about fdinfo * members. */ int add_fd(fd_list_t *fdl, int fd) { struct fdinfo info = { 0 }; info.fd = fd; return add_fdinfo(fdl, &info); }
/* 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); }