-int create_listen_socket6(const char *ip, int port, int listen_backlog)
-{
- int sock = -1;
- int sockopt = 1;
-
- 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. Disabling IPv6.");
- return -1;
- }
-
- /* avoid "address already in use" */
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt));
-
- struct sockaddr_in6 name;
- memset(&name, 0, sizeof(struct sockaddr_in6));
- name.sin6_family = AF_INET6;
- name.sin6_port = htons ((uint16_t) port);
-
- 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);
- return -1;
- }
- // info("Listening on IP '%s' (IPv6)", ip);
- }
-
- name.sin6_scope_id = 0;
-
- if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
- close(sock);
- error("IPv6 bind() failed. Disabling IPv6.");
- return -1;
- }
-
- 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;
+int create_listen_socket4(const char *ip, int port, int listen_backlog) {
+ int sock;
+ int sockopt = 1;
+
+ debug(D_LISTENER, "IPv4 creating new listening socket on ip '%s' port %d", ip, port);
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if(sock < 0) {
+ error("IPv4 socket() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ /* avoid "address already in use" */
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) != 0)
+ error("Cannot set SO_REUSEADDR on ip '%s' port's %d.", ip, port);
+
+ struct sockaddr_in name;
+ memset(&name, 0, sizeof(struct sockaddr_in));
+ name.sin_family = AF_INET;
+ name.sin_port = htons (port);
+
+ 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);
+ shown_server_socket_error = 1;
+ close(sock);
+ return -1;
+ }
+
+ if(bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
+ close(sock);
+ error("IPv4 bind() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ if(listen(sock, listen_backlog) < 0) {
+ close(sock);
+ error("IPv4 listen() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ debug(D_LISTENER, "Listening on IPv4 ip '%s' port %d", ip, port);
+ return sock;
+}
+
+int create_listen_socket6(const char *ip, int port, int listen_backlog) {
+ int sock = -1;
+ int sockopt = 1;
+ int ipv6only = 1;
+
+ debug(D_LISTENER, "IPv6 creating new listening socket on ip '%s' port %d", ip, port);
+
+ sock = socket(AF_INET6, SOCK_STREAM, 0);
+ if (sock < 0) {
+ error("IPv6 socket() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ /* avoid "address already in use" */
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt)) != 0)
+ error("Cannot set SO_REUSEADDR on ip '%s' port's %d.", ip, port);
+
+ /* IPv6 only */
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&ipv6only, sizeof(ipv6only)) != 0)
+ error("Cannot set IPV6_V6ONLY on ip '%s' port's %d.", ip, port);
+
+ struct sockaddr_in6 name;
+ memset(&name, 0, sizeof(struct sockaddr_in6));
+ name.sin6_family = AF_INET6;
+ name.sin6_port = htons ((uint16_t) port);
+
+ 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.", ip);
+ shown_server_socket_error = 1;
+ close(sock);
+ return -1;
+ }
+
+ name.sin6_scope_id = 0;
+
+ if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) {
+ close(sock);
+ error("IPv6 bind() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ if (listen(sock, listen_backlog) < 0) {
+ close(sock);
+ error("IPv6 listen() on ip '%s' port %d failed.", ip, port);
+ shown_server_socket_error = 1;
+ return -1;
+ }
+
+ debug(D_LISTENER, "Listening on IPv6 ip '%s' port %d", ip, port);
+ return sock;
+}
+
+static inline int add_listen_socket(int fd, const char *ip, int port) {
+ if(listen_fds_count >= MAX_LISTEN_FDS) {
+ error("Too many listening sockets. Failed to add listening socket at ip '%s' port %d", ip, port);
+ shown_server_socket_error = 1;
+ close(fd);
+ return -1;
+ }
+
+ listen_fds[listen_fds_count] = fd;
+
+ char buffer[100 + 1];
+ snprintfz(buffer, 100, "[%s]:%d", ip, port);
+ listen_fds_names[listen_fds_count] = strdupz(buffer);
+
+ listen_fds_count++;
+ return 0;
+}
+
+int is_listen_socket(int fd) {
+ size_t 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) {
+ size_t i;
+ for(i = 0; i < listen_fds_count ;i++) {
+ close(listen_fds[i]);
+ listen_fds[i] = -1;
+
+ freez(listen_fds_names[i]);
+ listen_fds_names[i] = NULL;
+ }
+
+ listen_fds_count = 0;