> On 15 Feb 2021, at 17:25, William Herrin <b...@herrin.us> wrote:
> 
> On Sun, Feb 14, 2021 at 8:27 PM Mark Tinka <mark@tinka.africa> wrote:
>> Dropping a few feet from cloud nine, there, really, is no other thing
>> that will facilitate or hold back the adoption of IPv6, like money.
> 
> Well actually, that's not entirely true. One thing holding back IPv6
> is the unfortunately routine need to turn it off in order to get one
> or another IPv4 thing back working again. Like the disney thing
> earlier in this thread. Or like my experience yesterday where I had to
> disable IPv6 to fetch files on a particular server because SLAAC was
> serving up invalid addresses but the app insisted on trying all 8 IPv6
> addresses before it would attempt any of the IPv4 addresses. And of
> course I can't call my ISP and say: you're causing my Linux box to
> pick up bad IPv6 addresses. Front line support can barely handle IPv4
> and Windows.
> 
> I stuck with it for a couple hours and figured out how to disable
> SLAAC without disabling DHCP-PD so that I could turn IPv6 back on with
> addresses which worked. But really, how many people are going to do
> that? Most tick the IPv6 checkbox to off and are done with it.
> 
> This particular problem could be quickly resolved if the OSes still
> getting updates were updated to default name resolution to prioritize
> the IPv4 addresses instead. That would allow broken IPv6
> configurations to exist without breaking the user's entire Internet
> experience. Which would allow them to leave it turned on so that it
> resumes working when the error is eventually found and fixed.
> 
> Prioritizing IPv6 over IPv4 for newly initiated connections is one of
> the trifecta of critical design errors that have been killing IPv6 for
> two decades. One of the two that if key folks weren't being so
> bull-headed about it, it would be trivial to fix.

Complain to your vendors about not implementing RFC 8305, RFC 6724, and
RFC 7078.  RFC 8305 or RFC6724 + RFC 7078 would fix your issue.

Thats Happy Eyeballs and tuneable address selection rules.

You don’t have to perform the naive connection from getaddrinfo() man page.

           struct addrinfo hints, *res, *res0;
           int error;
           int s;
           const char *cause = NULL;

           memset(&hints, 0, sizeof(hints));
           hints.ai_family = PF_UNSPEC;
           hints.ai_socktype = SOCK_STREAM;
           error = getaddrinfo("www.kame.net", "http", &hints, &res0);
           if (error) {
                   errx(1, "%s", gai_strerror(error));
                   /*NOTREACHED*/
           }
           s = -1;
           for (res = res0; res; res = res->ai_next) {
                   s = socket(res->ai_family, res->ai_socktype,
                       res->ai_protocol);
                   if (s < 0) {
                           cause = "socket";
                           continue;
                   }

                   if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
                           cause = "connect";
                           close(s);
                           s = -1;
                           continue;
                   }

                   break;  /* okay we got one */
           }
           if (s < 0) {
                   err(1, "%s", cause);
                   /*NOTREACHED*/
           }
           freeaddrinfo(res0);

You could actually use something a little more sophisticated like

int
connect_to_host(struct addrinfo *res0) {
        struct addrinfo *res;
        int fd = -1, n, i, j, flags, count;
        struct pollfd *fds;
        int timeout = TIMEOUT;

        /*
         * Work out how many possible descriptors we could use.
         */
        for (res = res0, count = 0; res; res = res->ai_next)
                count++;
        fds = calloc(count, sizeof(*fds));
        if (fds == NULL) {
                perror("calloc");
                goto cleanup;
        }

        for (res = res0, i = 0, count = 0; res; res = res->ai_next) {
                fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
                if (fd == -1) {
                        /*
                         * If AI_ADDRCONFIG is not supported we will get
                         * EAFNOSUPPORT returned.  Behave as if the address
                         * was not there.
                         */
                        if (errno != EAFNOSUPPORT)
                                perror("socket");
                        else if (res->ai_next != NULL)
                                continue;
                } else if ((flags = fcntl(fd, F_GETFL)) == -1) {
                        perror("fcntl");
                        close(fd);
                } else if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
                        perror("fcntl");
                        close(fd);
                } else if (connect(fd, res->ai_addr, res->ai_addrlen) == -1) {
                        if (errno != EINPROGRESS) {
                                perror("connect");
                                close(fd);
                        } else {
                                /*
                                 * Record the information for this descriptor.
                                 */
                                fds[i].fd = fd;
                                fds[i].events = POLLERR | POLLHUP |
                                                POLLIN | POLLOUT;
                                count++;
                                i++;
                        }
                } else  {
                        /*
                         * We connected without blocking.
                         */
                        goto done;
                }

                if (count == 0)
                        continue;

                do {
                        if (res->ai_next == NULL)
                                timeout = -1;

                        n = poll(fds, i, timeout);
                        if (n == 0) {
                                timeout >>= 1;
                                break;
                        }
                        if (n < 0) {
                                if (errno == EAGAIN || errno == EINTR)
                                        continue;
                                perror("poll");
                                fd = -1;
                                goto done;
                        }
                        for (j = 0; j < i; j++) {
                                if (fds[j].fd == -1 || fds[j].events == 0 ||
                                    fds[j].revents == 0)
                                        continue;
                                fd = fds[j].fd;
                                if (fds[j].revents & POLLHUP) {
                                        close(fd);
                                        fds[j].fd = -1;
                                        fds[j].events = 0;
                                        count--;
                                        continue;
                                }
                                /* Connect succeeded. */
                                goto done;
                        }
                } while (timeout == -1 && count != 0);
        }

        /* We failed to connect. */
        fd = -1;

 done:
        /* Close all other descriptors we have created. */
        for (j = 0; j < i; j++)
                if (fds[j].fd != fd && fds[j].fd != -1) {
                        close(fds[j].fd);
                }

        if (fd != -1) {
                /* Restore default blocking behaviour.  */
                if ((flags = fcntl(fd, F_GETFL)) != -1) {
                        flags &= ~O_NONBLOCK;
                        if (fcntl(fd, F_SETFL, flags) == -1)
                                perror("fcntl");
                } else
                        perror("fcntl");
        }

 cleanup:
        /* Free everything. */
        if (fds != NULL) free(fds);

        return (fd);
}

See https://users.isc.org/~marka/

Mark

> Regards,
> Bill Herrin
> 
> --
> William Herrin
> b...@herrin.us
> https://bill.herrin.us/

-- 
Mark Andrews, ISC
1 Seymour St., Dundas Valley, NSW 2117, Australia
PHONE: +61 2 9871 4742              INTERNET: ma...@isc.org

Reply via email to