+ listen_fds_count = 0;
+}
+
+static inline int bind_to_one(const char *definition, int default_port, int listen_backlog) {
+ int added = 0;
+ struct addrinfo hints;
+ struct addrinfo *result = NULL, *rp = NULL;
+
+ char buffer[strlen(definition) + 1];
+ strcpy(buffer, definition);
+
+ char buffer2[10 + 1];
+ snprintfz(buffer2, 10, "%d", default_port);
+
+ char *ip = buffer, *port = buffer2;
+
+ char *e = ip;
+ if(*e == '[') {
+ e = ++ip;
+ while(*e && *e != ']') e++;
+ if(*e == ']') {
+ *e = '\0';
+ e++;
+ }
+ }
+ else {
+ while(*e && *e != ':') e++;
+ }
+
+ if(*e == ':') {
+ port = e + 1;
+ *e = '\0';
+ }
+
+ if(!*ip || *ip == '*' || !strcmp(ip, "any") || !strcmp(ip, "all"))
+ ip = NULL;
+ if(!*port)
+ port = buffer2;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+ hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */
+ hints.ai_protocol = 0; /* Any protocol */
+ hints.ai_canonname = NULL;
+ hints.ai_addr = NULL;
+ hints.ai_next = NULL;
+
+ int r = getaddrinfo(ip, port, &hints, &result);
+ if (r != 0) {
+ error("getaddrinfo('%s', '%s'): %s\n", ip, port, gai_strerror(r));
+ return -1;
+ }
+
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ int fd = -1;
+
+ char rip[INET_ADDRSTRLEN + INET6_ADDRSTRLEN] = "INVALID";
+ int rport = default_port;
+
+ switch (rp->ai_addr->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in *) rp->ai_addr;
+ inet_ntop(AF_INET, &sin->sin_addr, rip, INET_ADDRSTRLEN);
+ rport = ntohs(sin->sin_port);
+ fd = create_listen_socket4(rip, rport, listen_backlog);
+ break;
+ }
+
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) rp->ai_addr;
+ inet_ntop(AF_INET6, &sin6->sin6_addr, rip, INET6_ADDRSTRLEN);
+ rport = ntohs(sin6->sin6_port);
+ fd = create_listen_socket6(rip, rport, listen_backlog);
+ break;
+ }
+ }
+
+ if (fd == -1)
+ error("Cannot bind to ip '%s', port %d", rip, rport);
+ else {
+ add_listen_socket(fd, rip, rport);
+ added++;
+ }
+ }
+
+ freeaddrinfo(result);
+
+ return added;
+}
+
+int create_listen_sockets(void) {
+ shown_server_socket_error = 0;
+
+ listen_backlog = (int) config_get_number(CONFIG_SECTION_WEB, "listen backlog", LISTEN_BACKLOG);
+
+ listen_port = (int) config_get_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT);
+ if(listen_port < 1 || listen_port > 65535) {
+ error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
+ listen_port = (int) config_set_number(CONFIG_SECTION_WEB, "default port", LISTEN_PORT);
+ }
+ debug(D_OPTIONS, "Default listen port set to %d.", listen_port);
+
+ char *s = config_get(CONFIG_SECTION_WEB, "bind to", "*");
+ while(*s) {
+ char *e = s;
+
+ // skip separators, moving both s(tart) and e(nd)
+ while(isspace(*e) || *e == ',') s = ++e;
+
+ // move e(nd) to the first separator
+ while(*e && !isspace(*e) && *e != ',') e++;
+
+ // is there anything?
+ if(!*s || s == e) break;
+
+ char buf[e - s + 1];
+ strncpyz(buf, s, e - s);
+ bind_to_one(buf, listen_port, listen_backlog);
+
+ s = e;
+ }
+
+ if(!listen_fds_count)
+ fatal("Cannot listen on any socket. Exiting...");
+ else if(shown_server_socket_error) {
+ size_t i;
+ for(i = 0; i < listen_fds_count ;i++)
+ info("Listen socket %s opened.", listen_fds_names[i]);
+ }
+
+ return (int)listen_fds_count;