- /* Create socket for listening. */
- listen_sock = socket(AF_INET, SOCK_STREAM, 0);
- if (listen_sock < 0)
- fatal("socket: %.100s", strerror(errno));
-
- /* Set socket options. We try to make the port reusable
- and have it close as fast as possible without waiting
- in unnecessary wait states on close. */
- setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *) &on,
- sizeof(on));
- linger.l_onoff = 1;
- linger.l_linger = 5;
- setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *) &linger,
- sizeof(linger));
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr = options.listen_addr;
- sin.sin_port = htons(options.port);
-
- if (bind(listen_sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
- error("bind: %.100s", strerror(errno));
- shutdown(listen_sock, SHUT_RDWR);
- close(listen_sock);
- fatal("Bind to port %d failed.", options.port);
+ for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
+ if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
+ continue;
+ if (num_listen_socks >= MAX_LISTEN_SOCKS)
+ fatal("Too many listen sockets. "
+ "Enlarge MAX_LISTEN_SOCKS");
+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ ntop, sizeof(ntop), strport, sizeof(strport),
+ NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+ error("getnameinfo failed");
+ continue;
+ }
+ /* Create socket for listening. */
+ listen_sock = socket(ai->ai_family, SOCK_STREAM, 0);
+ if (listen_sock < 0) {
+ /* kernel may not support ipv6 */
+ verbose("socket: %.100s", strerror(errno));
+ continue;
+ }
+ if (fcntl(listen_sock, F_SETFL, O_NONBLOCK) < 0) {
+ error("listen_sock O_NONBLOCK: %s", strerror(errno));
+ close(listen_sock);
+ continue;
+ }
+ /*
+ * Set socket options. We try to make the port
+ * reusable and have it close as fast as possible
+ * without waiting in unnecessary wait states on
+ * close.
+ */
+ setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *) &on, sizeof(on));
+ linger.l_onoff = 1;
+ linger.l_linger = 5;
+ setsockopt(listen_sock, SOL_SOCKET, SO_LINGER,
+ (void *) &linger, sizeof(linger));
+
+ debug("Bind to port %s on %s.", strport, ntop);
+
+ /* Bind the socket to the desired port. */
+ if (bind(listen_sock, ai->ai_addr, ai->ai_addrlen) < 0) {
+ error("Bind to port %s on %s failed: %.200s.",
+ strport, ntop, strerror(errno));
+ close(listen_sock);
+ continue;
+ }
+ listen_socks[num_listen_socks] = listen_sock;
+ num_listen_socks++;
+
+ /* Start listening on the port. */
+ log("Server listening on %s port %s.", ntop, strport);
+ if (listen(listen_sock, 5) < 0)
+ fatal("listen: %.100s", strerror(errno));
+