- {
- assert(addr->family == AF_INET);
- a.sin_family = AF_INET;
- a.sin_addr.s_addr = htonl(INADDR_ANY);
- a.sin_port = htons(localport);
- retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
+
+ /* We don't try to bind to a local address for UNIX domain sockets. (Why
+ * do we bother doing the bind when localport == 0 anyway?) */
+ if(addr->family != AF_UNIX) {
+ /* Loop round trying to bind */
+ while (1) {
+ int retcode;
+
+#ifndef NO_IPV6
+ if (addr->family == AF_INET6) {
+ /* XXX use getaddrinfo to get a local address? */
+ a6.sin6_family = AF_INET6;
+ a6.sin6_addr = in6addr_any;
+ a6.sin6_port = htons(localport);
+ retcode = bind(s, (struct sockaddr *) &a6, sizeof(a6));
+ } else
+#endif
+ {
+ assert(addr->family == AF_INET);
+ a.sin_family = AF_INET;
+ a.sin_addr.s_addr = htonl(INADDR_ANY);
+ a.sin_port = htons(localport);
+ retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
+ }
+ if (retcode >= 0) {
+ err = 0;
+ break; /* done */
+ } else {
+ err = errno;
+ if (err != EADDRINUSE) /* failed, for a bad reason */
+ break;
+ }
+
+ if (localport == 0)
+ break; /* we're only looping once */
+ localport--;
+ if (localport == 0)
+ break; /* we might have got to the end */