+static inline int add_listen_socket(int fd) {
+ if(listen_fds_count >= MAX_LISTEN_FDS)
+ return -1;
+
+ listen_fds[listen_fds_count++] = fd;
+
+ return 0;
+}
+
+int is_listen_socket(int fd) {
+ int i;
+ for(i = 0; i < listen_fds_count ;i++)
+ if(listen_fds[i] == fd) return 1;
+
+ return 0;
+}
+
+static inline void close_listen_sockets(void) {
+ int i;
+ for(i = 0; i < listen_fds_count ;i++)
+ close(listen_fds[i]);
+ 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, *rp;
+
+ 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";
+ 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);
+ fd = create_listen_socket4(rip, ntohs(sin->sin_port), 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);
+ fd = create_listen_socket6(rip, ntohs(sin6->sin6_port), listen_backlog);
+ break;
+ }
+ }
+
+ if (fd == -1)
+ error("Cannot bind to ip '%s', port %d", rip, default_port);
+ else {
+ add_listen_socket(fd);
+ added++;
+ }
+ }
+
+ return added;
+}