diff options
Diffstat (limited to 'src/web_server.c')
-rw-r--r--[-rwxr-xr-x] | src/web_server.c | 147 |
1 files changed, 96 insertions, 51 deletions
diff --git a/src/web_server.c b/src/web_server.c index cae94aca..10bf39a7 100755..100644 --- a/src/web_server.c +++ b/src/web_server.c @@ -24,12 +24,14 @@ #include "global_statistics.h" #include "rrd.h" #include "rrd2json.h" +#include "../config.h" int listen_backlog = LISTEN_BACKLOG; int listen_fd = -1; int listen_port = LISTEN_PORT; +#ifdef NETDATA_INTERNAL_CHECKS static void log_allocations(void) { static int mem = 0; @@ -46,82 +48,123 @@ static void log_allocations(void) mem = mi.uordblks; } } +#endif -int create_listen_socket4(int port, int listen_backlog) +static int is_ip_anything(const char *ip) { - int sock; - int sockopt = 1; - struct sockaddr_in name; + if(!ip || !*ip + || !strcmp(ip, "any") + || !strcmp(ip, "all") + || !strcmp(ip, "*") + || !strcmp(ip, "::") + || !strcmp(ip, "0.0.0.0") + ) return 1; + + return 0; +} - debug(D_LISTENER, "IPv4 creating new listening socket on port %d", port); +int create_listen_socket4(const char *ip, int port, int listen_backlog) +{ + int sock; + int sockopt = 1; + struct sockaddr_in name; - sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 0) { - error("IPv4 socket() failed."); - return -1; - } + debug(D_LISTENER, "IPv4 creating new listening socket on port %d", port); - /* avoid "address already in use" */ - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)); + sock = socket(AF_INET, SOCK_STREAM, 0); + if(sock < 0) { + error("IPv4 socket() failed."); + return -1; + } - memset(&name, 0, sizeof(struct sockaddr_in)); - name.sin_family = AF_INET; - name.sin_port = htons (port); - name.sin_addr.s_addr = htonl (INADDR_ANY); + /* avoid "address already in use" */ + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)); - if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { - close(sock); - error("IPv4 bind() failed."); - return -1; - } + memset(&name, 0, sizeof(struct sockaddr_in)); + name.sin_family = AF_INET; + name.sin_port = htons (port); - if(listen(sock, listen_backlog) < 0) { + if(is_ip_anything(ip)) { + name.sin_addr.s_addr = htonl(INADDR_ANY); + info("Listening on any IPs (IPv4)."); + } + else { + int ret = inet_pton(AF_INET, ip, (void *)&name.sin_addr.s_addr); + if(ret != 1) { + error("Failed to convert IP '%s' to a valid IPv4 address.", ip); close(sock); - fatal("IPv4 listen() failed."); return -1; } + info("Listening on IP '%s' (IPv4).", ip); + } + + if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { + close(sock); + error("IPv4 bind() failed."); + return -1; + } + + if(listen(sock, listen_backlog) < 0) { + close(sock); + fatal("IPv4 listen() failed."); + return -1; + } - debug(D_LISTENER, "IPv4 listening port %d created", port); - return sock; + debug(D_LISTENER, "IPv4 listening port %d created", port); + return sock; } -int create_listen_socket6(int port, int listen_backlog) +int create_listen_socket6(const char *ip, int port, int listen_backlog) { - int sock = -1; - int sockopt = 1; - struct sockaddr_in6 name; + int sock = -1; + int sockopt = 1; + struct sockaddr_in6 name; - debug(D_LISTENER, "IPv6 creating new listening socket on port %d", port); + debug(D_LISTENER, "IPv6 creating new listening socket on port %d", port); - sock = socket(AF_INET6, SOCK_STREAM, 0); - if (sock < 0) { - error("IPv6 socket() failed."); - return -1; - } + sock = socket(AF_INET6, SOCK_STREAM, 0); + if (sock < 0) { + error("IPv6 socket() failed. Disabling IPv6."); + return -1; + } - /* avoid "address already in use" */ - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)); + /* avoid "address already in use" */ + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)); - memset(&name, 0, sizeof(struct sockaddr_in6)); - name.sin6_family = AF_INET6; - name.sin6_port = htons ((uint16_t) port); - name.sin6_addr = in6addr_any; - name.sin6_scope_id = 0; + memset(&name, 0, sizeof(struct sockaddr_in6)); + name.sin6_family = AF_INET6; + name.sin6_port = htons ((uint16_t) port); - if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { + if(is_ip_anything(ip)) { + name.sin6_addr = in6addr_any; + info("Listening on all IPs (IPv6 and IPv4)"); + } + else { + int ret = inet_pton(AF_INET6, ip, (void *)&name.sin6_addr.s6_addr); + if(ret != 1) { + error("Failed to convert IP '%s' to a valid IPv6 address. Disabling IPv6.", ip); close(sock); - error("IPv6 bind() failed."); return -1; } + info("Listening on IP '%s' (IPv6)", ip); + } - if (listen(sock, listen_backlog) < 0) { - close(sock); - fatal("IPv6 listen() failed."); - return -1; - } + name.sin6_scope_id = 0; + + if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) { + close(sock); + error("IPv6 bind() failed. Disabling IPv6."); + return -1; + } - debug(D_LISTENER, "IPv6 listening port %d created", port); - return sock; + if (listen(sock, listen_backlog) < 0) { + close(sock); + error("IPv6 listen() failed. Disabling IPv6."); + return -1; + } + + debug(D_LISTENER, "IPv6 listening port %d created", port); + return sock; } @@ -210,7 +253,9 @@ void *socket_listen_main(void *ptr) debug(D_WEB_CLIENT, "%llu: Removing client.", w->id); // pthread_join(w->thread, NULL); w = web_client_free(w); +#ifdef NETDATA_INTERNAL_CHECKS log_allocations(); +#endif } } } |