+
+ if (portstr) {
+ struct servent *s;
+ if (!portstr[strspn(portstr, "0123456789")]) {
+ port = atoi(portstr);
+ } else if ((s = getservbyname(portstr, NULL)) != NULL) {
+ port = ntohs(s->s_port);
+ } else {
+ fprintf(stderr, "getservbyname: port '%s' not understood\n",
+ portstr);
+ return -1;
+ }
+ }
+
+#endif
+
+#ifndef NO_IPV6
+#ifndef NO_IPV4
+ retry:
+#endif
+ if (got_v6) {
+ fds->v6 = socket(PF_INET6, SOCK_STREAM, 0);
+ if (fds->v6 < 0) {
+ fprintf(stderr, "socket(PF_INET6): %s\n", strerror(errno));
+ goto done_v6;
+ }
+#ifdef IPV6_V6ONLY
+ {
+ int i = 1;
+ if (setsockopt(fds->v6, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&i, sizeof(i)) < 0) {
+ fprintf(stderr, "setsockopt(IPV6_V6ONLY): %s\n",
+ strerror(errno));
+ close(fds->v6);
+ fds->v6 = -1;
+ goto done_v6;
+ }
+ }
+#endif /* IPV6_V6ONLY */
+ addr6.sin6_port = htons(port);
+ addrlen = sizeof(addr6);
+ if (bind(fds->v6, (const struct sockaddr *)&addr6, addrlen) < 0) {
+ fprintf(stderr, "bind: %s\n", strerror(errno));
+ close(fds->v6);
+ fds->v6 = -1;
+ goto done_v6;
+ }
+ if (listen(fds->v6, 5) < 0) {
+ fprintf(stderr, "listen: %s\n", strerror(errno));
+ close(fds->v6);
+ fds->v6 = -1;
+ goto done_v6;
+ }
+ if (port == 0) {
+ addrlen = sizeof(addr6);
+ if (getsockname(fds->v6, (struct sockaddr *)&addr6,
+ &addrlen) < 0) {
+ fprintf(stderr, "getsockname: %s\n", strerror(errno));
+ close(fds->v6);
+ fds->v6 = -1;
+ goto done_v6;
+ }
+ port = ntohs(addr6.sin6_port);
+ }
+ }
+ done_v6:
+#endif
+
+#ifndef NO_IPV4
+ if (got_v4) {
+ fds->v4 = socket(PF_INET, SOCK_STREAM, 0);
+ if (fds->v4 < 0) {
+ fprintf(stderr, "socket(PF_INET): %s\n", strerror(errno));
+ goto done_v4;
+ }
+ addr4.sin_port = htons(port);
+ addrlen = sizeof(addr4);
+ if (bind(fds->v4, (const struct sockaddr *)&addr4, addrlen) < 0) {
+#ifndef NO_IPV6
+ if (fds->v6 >= 0) {
+ /*
+ * If we support both v6 and v4, it's a failure
+ * condition if we didn't manage to bind to both. If
+ * the port number was arbitrary, we go round and try
+ * again. Otherwise, give up.
+ */
+ close(fds->v6);
+ close(fds->v4);
+ fds->v6 = fds->v4 = -1;
+ port = 0;
+ if (!portstr)
+ goto retry;
+ }
+#endif
+ fprintf(stderr, "bind: %s\n", strerror(errno));
+ close(fds->v4);
+ fds->v4 = -1;
+ goto done_v4;
+ }
+ if (listen(fds->v4, 5) < 0) {
+ fprintf(stderr, "listen: %s\n", strerror(errno));
+ close(fds->v4);
+ fds->v4 = -1;
+ goto done_v4;
+ }
+ if (port == 0) {
+ addrlen = sizeof(addr4);
+ if (getsockname(fds->v4, (struct sockaddr *)&addr4,
+ &addrlen) < 0) {
+ fprintf(stderr, "getsockname: %s\n", strerror(errno));
+ close(fds->v4);
+ fds->v4 = -1;
+ goto done_v4;
+ }
+ port = ntohs(addr4.sin_port);
+ }