X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrdd.c;h=042b33114a8b94fba548ac331a86f742810d57d3;hb=93399a0e4410b955507eca8ff47273cf9bec3ba7;hp=c2f79365859139643612123a43cfb377318b5e3f;hpb=5b7997e7e5e35b9fcf08969527994307ccec3d19;p=rrdd.git diff --git a/src/rrdd.c b/src/rrdd.c index c2f7936..042b331 100644 --- a/src/rrdd.c +++ b/src/rrdd.c @@ -78,6 +78,9 @@ static pthread_cond_t cache_cond = PTHREAD_COND_INITIALIZER; static int config_write_interval = 300; static int config_flush_interval = 3600; +static char **config_listen_address_list = NULL; +static int config_listen_address_list_len = 0; + /* * Functions */ @@ -163,7 +166,7 @@ static void *queue_thread_main (void *args) /* {{{ */ RRDD_LOG (LOG_DEBUG, "queue_thread_main: rrd_update (%s, %i, %p)", file, values_num, (void *) values); - status = rrd_update_r (file, NULL, values_num, values); + status = rrd_update_r (file, NULL, values_num, (void *) values); if (status != 0) { RRDD_LOG (LOG_ERR, "queue_thread_main: " @@ -454,7 +457,7 @@ static void *connection_thread_main (void *args) /* {{{ */ return (NULL); } /* }}} void *connection_thread_main */ -static int open_listen_socket (const char *path) /* {{{ */ +static int open_listen_socket_unix (const char *path) /* {{{ */ { int fd; struct sockaddr_un sa; @@ -465,7 +468,7 @@ static int open_listen_socket (const char *path) /* {{{ */ sizeof (listen_fds[0]) * (listen_fds_num + 1)); if (temp == NULL) { - RRDD_LOG (LOG_ERR, "open_listen_socket: realloc failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: realloc failed."); return (-1); } listen_fds = temp; @@ -474,7 +477,7 @@ static int open_listen_socket (const char *path) /* {{{ */ fd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0); if (fd < 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: socket(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: socket(2) failed."); return (-1); } @@ -485,7 +488,7 @@ static int open_listen_socket (const char *path) /* {{{ */ status = bind (fd, (struct sockaddr *) &sa, sizeof (sa)); if (status != 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: bind(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: bind(2) failed."); close (fd); unlink (path); return (-1); @@ -494,18 +497,98 @@ static int open_listen_socket (const char *path) /* {{{ */ status = listen (fd, /* backlog = */ 10); if (status != 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: listen(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: listen(2) failed."); close (fd); unlink (path); return (-1); } listen_fds[listen_fds_num].fd = fd; - strncpy (listen_fds[listen_fds_num].path, path, - sizeof (listen_fds[listen_fds_num].path) - 1); + snprintf (listen_fds[listen_fds_num].path, + sizeof (listen_fds[listen_fds_num].path) - 1, + "unix:%s", path); listen_fds_num++; return (0); +} /* }}} int open_listen_socket_unix */ + +static int open_listen_socket (const char *addr) /* {{{ */ +{ + struct addrinfo ai_hints; + struct addrinfo *ai_res; + struct addrinfo *ai_ptr; + int status; + + assert (addr != NULL); + + if (strncmp ("unix:", addr, strlen ("unix:")) == 0) + return (open_listen_socket_unix (addr + strlen ("unix:"))); + else if (addr[0] == '/') + return (open_listen_socket_unix (addr)); + + memset (&ai_hints, 0, sizeof (ai_hints)); + ai_hints.ai_flags = 0; +#ifdef AI_ADDRCONFIG + ai_hints.ai_flags |= AI_ADDRCONFIG; +#endif + ai_hints.ai_family = AF_UNSPEC; + ai_hints.ai_socktype = SOCK_STREAM; + + ai_res = NULL; + status = getaddrinfo (addr, DEFAULT_PORT, &ai_hints, &ai_res); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: getaddrinfo(%s) failed: " + "%s", addr, gai_strerror (status)); + return (-1); + } + + for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + { + int fd; + struct sockaddr_storage sa; + listen_socket_t *temp; + + temp = (listen_socket_t *) realloc (listen_fds, + sizeof (listen_fds[0]) * (listen_fds_num + 1)); + if (temp == NULL) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: realloc failed."); + continue; + } + listen_fds = temp; + memset (listen_fds + listen_fds_num, 0, sizeof (listen_fds[0])); + + fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); + if (fd < 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: socket(2) failed."); + continue; + } + + status = bind (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: bind(2) failed."); + close (fd); + continue; + } + + status = listen (fd, /* backlog = */ 10); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: listen(2) failed."); + close (fd); + return (-1); + } + + listen_fds[listen_fds_num].fd = fd; + strncpy (listen_fds[listen_fds_num].path, addr, + sizeof (listen_fds[listen_fds_num].path) - 1); + listen_fds_num++; + } /* for (ai_ptr) */ + + return (0); } /* }}} int open_listen_socket */ static int close_listen_sockets (void) /* {{{ */ @@ -515,7 +598,8 @@ static int close_listen_sockets (void) /* {{{ */ for (i = 0; i < listen_fds_num; i++) { close (listen_fds[i].fd); - unlink (listen_fds[i].path); + if (strncmp ("unix:", listen_fds[i].path, strlen ("unix:")) == 0) + unlink (listen_fds[i].path + strlen ("unix:")); } free (listen_fds); @@ -528,57 +612,106 @@ static int close_listen_sockets (void) /* {{{ */ static void *listen_thread_main (void *args) /* {{{ */ { char buffer[4096]; + struct pollfd *pollfds; + int pollfds_num; int status; int i; - status = open_listen_socket (RRDD_SOCK_PATH); - if (status != 0) + for (i = 0; i < config_listen_address_list_len; i++) { - RRDD_LOG (LOG_ERR, "listen_thread_main: open_listen_socket failed."); + RRDD_LOG (LOG_DEBUG, "listen_thread_main: config_listen_address_list[%i] " + "= %s", i, config_listen_address_list[i]); + open_listen_socket (config_listen_address_list[i]); + } + + if (listen_fds_num < 1) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: No listen sockets " + "could be opened. Sorry."); return (NULL); } - while (do_shutdown == 0) + pollfds_num = listen_fds_num; + pollfds = (struct pollfd *) malloc (sizeof (*pollfds) * pollfds_num); + if (pollfds == NULL) { - int *client_sd; - struct sockaddr_un client_sa; - socklen_t client_sa_size; - pthread_t tid; + RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed."); + return (NULL); + } + memset (pollfds, 0, sizeof (*pollfds) * pollfds_num); - client_sd = (int *) malloc (sizeof (int)); - if (client_sd == NULL) + while (do_shutdown == 0) + { + assert (pollfds_num == listen_fds_num); + for (i = 0; i < pollfds_num; i++) { - RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed."); - sleep (120); - continue; + pollfds[i].fd = listen_fds[i].fd; + pollfds[i].events = POLLIN | POLLPRI; + pollfds[i].revents = 0; } - client_sa_size = sizeof (client_sa); - /* FIXME: Don't implement listen_fds as a list or use poll(2) here! */ - *client_sd = accept (listen_fds[0].fd, - (struct sockaddr *) &client_sa, &client_sa_size); - if (*client_sd < 0) + status = poll (pollfds, pollfds_num, /* timeout = */ -1); + if (status < 1) { - RRDD_LOG (LOG_ERR, "listen_thread_main: accept(2) failed."); + status = errno; + if (status != EINTR) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: poll(2) failed."); + } continue; } - RRDD_LOG (LOG_DEBUG, "listen_thread_main: accept(2) returned fd #%i.", - *client_sd); - - status = pthread_create (&tid, /* attr = */ NULL, connection_thread_main, - /* args = */ (void *) client_sd); - if (status != 0) + for (i = 0; i < pollfds_num; i++) { - RRDD_LOG (LOG_ERR, "listen_thread_main: pthread_create failed."); - close (*client_sd); - free (client_sd); - continue; - } + int *client_sd; + struct sockaddr_storage client_sa; + socklen_t client_sa_size; + pthread_t tid; + + if (pollfds[i].revents == 0) + continue; + + if ((pollfds[i].revents & (POLLIN | POLLPRI)) == 0) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: " + "poll(2) returned something unexpected for listen FD #%i.", + pollfds[i].fd); + continue; + } + + client_sd = (int *) malloc (sizeof (int)); + if (client_sd == NULL) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: malloc failed."); + continue; + } + + client_sa_size = sizeof (client_sa); + *client_sd = accept (pollfds[i].fd, + (struct sockaddr *) &client_sa, &client_sa_size); + if (*client_sd < 0) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: accept(2) failed."); + continue; + } + + RRDD_LOG (LOG_DEBUG, "listen_thread_main: accept(2) returned fd #%i.", + *client_sd); - RRDD_LOG (LOG_DEBUG, "listen_thread_main: pthread_create succeeded: " - "tid = %lu", - *((unsigned long *) &tid)); + status = pthread_create (&tid, /* attr = */ NULL, connection_thread_main, + /* args = */ (void *) client_sd); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "listen_thread_main: pthread_create failed."); + close (*client_sd); + free (client_sd); + continue; + } + + RRDD_LOG (LOG_DEBUG, "listen_thread_main: pthread_create succeeded: " + "tid = %lu", + *((unsigned long *) &tid)); + } /* for (pollfds_num) */ } /* while (do_shutdown == 0) */ close_listen_sockets (); @@ -698,7 +831,24 @@ static int read_options (int argc, char **argv) /* {{{ */ { case 'l': { - printf ("Listening to: %s\n", optarg); + char **temp; + + temp = (char **) realloc (config_listen_address_list, + sizeof (char *) * (config_listen_address_list_len + 1)); + if (temp == NULL) + { + fprintf (stderr, "read_options: realloc failed.\n"); + return (2); + } + config_listen_address_list = temp; + + temp[config_listen_address_list_len] = strdup (optarg); + if (temp[config_listen_address_list_len] == NULL) + { + fprintf (stderr, "read_options: strdup failed.\n"); + return (2); + } + config_listen_address_list_len++; } break;