]> git.pond.sub.org Git - empserver/blobdiff - src/lib/gen/tcp_listen.c
Use IPv4 and v6 only when suitable interfaces are configured
[empserver] / src / lib / gen / tcp_listen.c
index 9b2b167a965806d9b134ec4bf6e94972adc8f728..fa494c40d2c41ddaa9a0caa136d9f9b864d8d3e0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
  *  tcp_listen.c: Create a socket and listen on it
- * 
+ *
  *  Known contributors to this file:
  *     Markus Armbruster, 2005
  */
 #include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
 #include <unistd.h>
+#include "prototypes.h"
 
-static int cant_listen(char *, char *, const char *);
+/* Portability cruft, should become unnecessary eventually */
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0
+#endif
+
+static void cant_listen(char *, char *, const char *);
 
 int
 tcp_listen(char *host, char *serv, size_t *addrlenp)
@@ -61,7 +67,7 @@ tcp_listen(char *host, char *serv, size_t *addrlenp)
     struct addrinfo hints, *res, *ressave;
 
     memset(&hints, 0, sizeof(struct addrinfo));
-    hints.ai_flags = AI_PASSIVE;
+    hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
     hints.ai_family = AF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
 
@@ -74,19 +80,8 @@ tcp_listen(char *host, char *serv, size_t *addrlenp)
        if (fd < 0)
            continue;           /* error, try next one */
 
-#ifndef _WIN32
-       /*
-        * SO_REUSEADDR requests to permit another bind even when the
-        * port is still in state TIME_WAIT.  Windows' SO_REUSEADDR is
-        * broken: it makes bind() succeed no matter what, even if
-        * there's another server running on the same port.  Luckily,
-        * bind() seems to be broken as well: it seems to suceed while
-        * the port in state TIME_WAIT by default; thus we get the
-        * behavior we want by not setting SO_REUSEADDR.
-        */
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
            cant_listen(host, serv, strerror(errno));
-#endif
        if (bind(fd, res->ai_addr, res->ai_addrlen) == 0)
            break;              /* success */
 
@@ -131,11 +126,8 @@ tcp_listen(char *host, char *serv, size_t *addrlenp)
     }
     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        cant_listen(host, serv, strerror(errno));
-#ifndef _WIN32
-    /* see comment on setsockopt() above */
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        cant_listen(host, serv, strerror(errno));
-#endif
     if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
        cant_listen(host, serv, strerror(errno));
     if (listen(fd, SOMAXCONN) < 0)
@@ -149,10 +141,10 @@ tcp_listen(char *host, char *serv, size_t *addrlenp)
     return fd;
 }
 
-
-static int
+static void
 cant_listen(char *host, char *serv, const char *err)
 {
-    fprintf(stderr, "Can't listen on %s:%s: %s", host, serv, err);
+    fprintf(stderr, "Can't listen on %s%s%s: %s\n",
+           host ? host : "", host ? ":" : "", serv, err);
     exit(1);
 }