/* Pure Load Balancer - (C)opyleft 2003 Jedi/Sector One */ #include #include "plb.h" #include "plb_globals.h" #ifdef WITH_DMALLOC # include #endif #define EVENT_FD_(e) ((e)->ev_fd) void client_disconnect(Client * const client) { current_nb_clients--; if (client->header != NULL) { free(client->header); client->header = NULL; client->header_len = (size_t) 0U; client->header_written = (size_t) 0U; } if (client->replybuf != NULL) { free(client->replybuf); client->replybuf = NULL; client->replybuf_len = (size_t) 0U; client->replybuf_written = (size_t) 0U; } if (client->postbuf != NULL) { free(client->postbuf); client->postbuf = NULL; client->postbuf_len = (size_t) 0U; client->postbuf_written = (size_t) 0U; } if (EVENT_FD((&client->server_read_ev)) != -1) { event_del(&client->server_read_ev); EVENT_FD_((&client->server_read_ev)) = -1; } if (EVENT_FD((&client->server_write_ev)) != -1) { event_del(&client->server_write_ev); EVENT_FD_((&client->server_write_ev)) = -1; } if (EVENT_FD((&client->client_read_ev)) != -1) { event_del(&client->client_read_ev); EVENT_FD_((&client->client_read_ev)) = -1; } if (EVENT_FD((&client->client_write_ev)) != -1) { event_del(&client->client_write_ev); EVENT_FD_((&client->client_write_ev)) = -1; } if (client->server_fd != -1) { while (close(client->server_fd) != 0 && errno == EINTR); client->server_fd = -1; } if (client->client_fd != -1) { while (close(client->client_fd) != 0 && errno == EINTR); client->client_fd = -1; } client->state = STATE_OFFLINE; } int handle_timeout(const short event, Client * const client) { if ((event & EV_TIMEOUT) != 0) { plb_log(LL_DEBUG, "Timeout"); client_disconnect(client); return 1; } return 0; } static void smtp_banner(const int fd) { char banner[300]; char nodename[256]; ssize_t written; size_t towrite; if (gethostname(nodename, sizeof nodename - (size_t) 1U) != 0) { nodename[0] = 'x'; nodename[1] = 0; } nodename[sizeof nodename - (size_t) 1U] = 0; snprintf(banner, sizeof banner, "220 %s ESMTP - Pure Load Balancer ready\r\n", nodename); towrite = strlen(banner); while ((written = write(fd, banner, towrite)) < (ssize_t) 0 && errno == EINTR); /* to be rewritten */ if (written < (ssize_t) 0 || (size_t) written != towrite) { plb_log(LL_NOTIFY, "Error while sending a banner to a client (nmap scan?): [%s]", strerror(errno)); } } void new_client(const int listenfd, short event, void *ev) { static int last_was_full; Client *client; struct sockaddr_storage client_sa; socklen_t client_sa_len; int client_fd; (void) ev; (void) event; if ((client_fd = accept(listenfd, (struct sockaddr *) &client_sa, &client_sa_len)) < 0) { plb_log(LL_ERROR, "Unable to accept a new client connection : [%s]", strerror(errno)); return; } setsockopt_aggressive(client_fd); socket_nonblock(client_fd); if (client_fd >= (int) max_clients) { (void) write(client_fd, SERVER_FULL_MSG, sizeof SERVER_FULL_MSG - (size_t) 1U); if (last_was_full == 0) { plb_log(LL_WARNING, "Server full - too many clients"); last_was_full = 1; } while (close(client_fd) != 0 && errno == EINTR); return; } else { last_was_full = 0; } if (protocol == PROTOCOL_SMTP) { smtp_banner(client_fd); } current_nb_clients++; client = &clients[client_fd]; client->client_fd = client_fd; client->server_fd = -1; client->state = STATE_HEADER; client->header = NULL; client->postbuf = NULL; client->replybuf = NULL; client->header_len = (size_t) 0U; client->header_written = (size_t) 0U; client->postbuf_len = (size_t) 0U; client->postbuf_written = (size_t) 0U; client->replybuf_len = (size_t) 0U; client->replybuf_written = (size_t) 0U; EVENT_FD_((&client->client_read_ev)) = -1; EVENT_FD_((&client->client_write_ev)) = -1; EVENT_FD_((&client->server_read_ev)) = -1; EVENT_FD_((&client->server_write_ev)) = -1; event_set(&client->client_read_ev, client_fd, EV_READ, client_read, &clients[client_fd]); event_add(&client->client_read_ev, &timeout_header_client_read); }