On 15 Feb 2021, at 17:25, William Herrin <bill@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 bill@herrin.us https://bill.herrin.us/
-- Mark Andrews, ISC 1 Seymour St., Dundas Valley, NSW 2117, Australia PHONE: +61 2 9871 4742 INTERNET: marka@isc.org