From: Mark Wooding Date: Thu, 28 Sep 2017 00:52:03 +0000 (+0100) Subject: pkstream/pkstream.c: Be more careful about handling address families. X-Git-Tag: 1.5.0~41^2~46 X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/commitdiff_plain/d66e33f00fd3c8f4ca06fe089234b93e601b1356 pkstream/pkstream.c: Be more careful about handling address families. * Introduce a concept of `known' address families. Currently, only `AF_INET' is known. * Filter `struct addrinfo' chains for known address families. If we come up short, complain. * Tweak `aihints' to arrange that addresses which are supposed to match up actually will do: so server peer and bind addresses should match; client bind and connect addresses should match; and UDP local and remote addresses should match. * Initialize address structures using the `ai_family' slot from the appropriate `struct addrinfo' structure. --- diff --git a/pkstream/pkstream.c b/pkstream/pkstream.c index dd4658e4..cf66b3e4 100644 --- a/pkstream/pkstream.c +++ b/pkstream/pkstream.c @@ -111,6 +111,14 @@ static socklen_t addrsz(const addr *a) } } +static int knownafp(int af) +{ + switch (af) { + case AF_INET: return (1); + default: return (0); + } +} + static int initsock(int fd, int af) { switch (af) { @@ -141,11 +149,17 @@ static int addreq(const addr *a, const addr *b) } } -static void initaddr(addr *a) +static void initaddr(addr *a, int af) { - a->sin.sin_family = AF_INET; - a->sin.sin_addr.s_addr = INADDR_ANY; - a->sin.sin_port = 0; + a->sa.sa_family = af; + switch (af) { + case AF_INET: + a->sin.sin_addr.s_addr = INADDR_ANY; + a->sin.sin_port = 0; + break; + default: + abort(); + } } #define caf_addr 1u @@ -343,10 +357,12 @@ static void pushaddrs(addr_v *av, const struct addrinfo *ailist) const struct addrinfo *ai; size_t i, n; - for (ai = ailist, n = 0; ai; ai = ai->ai_next) n++; + for (ai = ailist, n = 0; ai; ai = ai->ai_next) + if (knownafp(ai->ai_family)) n++; DA_ENSURE(av, n); for (i = DA_LEN(av), ai = ailist; ai; ai = ai->ai_next) { - initaddr(&DA(av)[i]); + if (!knownafp(ai->ai_family)) continue; + initaddr(&DA(av)[i], ai->ai_family); copyaddr(&DA(av)[i++], ai->ai_addr, caf_addr | caf_port); } DA_EXTEND(av, n); @@ -481,9 +497,13 @@ int main(int argc, char *argv[]) freeaddrinfo(ailist); } else if (!bindsvc) { if (n != 1) die(1, "can only bind to one address as client"); - parseaddr(&aihint, DA(&bindhosts)[0], 0, 0, &ailist); ai = ailist; - initaddr(&bindaddr); + parseaddr(&aihint, DA(&bindhosts)[0], 0, 0, &ailist); + for (ai = ailist; ai && !knownafp(ai->ai_family); ai = ai->ai_next); + if (!ai) + die(1, "no usable addresses returned for `%s'", DA(&bindhosts)[0]); + initaddr(&bindaddr, ai->ai_family); copyaddr(&bindaddr, ai->ai_addr, caf_addr); + aihint.ai_family = ai->ai_family; freeaddrinfo(ailist); } else for (i = 0; i < n; i++) { parseaddr(&aihint, DA(&bindhosts)[i], bindsvc, 0, &ailist); @@ -507,6 +527,7 @@ int main(int argc, char *argv[]) pushaddrs(&cw.peer, ailist); freeaddrinfo(ailist); } + if (!DA_LEN(&cw.peer)) die(1, "no usable peer addresses"); } if (connhost) { @@ -530,10 +551,13 @@ int main(int argc, char *argv[]) die(1, "couldn't connect to TCP server: %s", strerror(errno)); } + aihint.ai_family = AF_INET; aihint.ai_socktype = SOCK_DGRAM; aihint.ai_protocol = IPPROTO_UDP; aihint.ai_flags = AI_ADDRCONFIG | AI_PASSIVE; - parseaddr(&aihint, argv[optind], 0, paf_parse, &ailist); ai = ailist; + parseaddr(&aihint, argv[optind], 0, paf_parse, &ailist); + for (ai = ailist; ai && !knownafp(ai->ai_family); ai = ai->ai_next); + if (!ai) die(1, "no usable addresses returned for `%s'", argv[optind]); if ((fd_udp = socket(ai->ai_family, SOCK_DGRAM, IPPROTO_UDP)) < 0 || initsock(fd_udp, ai->ai_family) || nonblockify(fd_udp) || cloexec(fd_udp) || @@ -542,6 +566,7 @@ int main(int argc, char *argv[]) bind(fd_udp, ai->ai_addr, ai->ai_addrlen)) die(1, "couldn't set up UDP socket: %s", strerror(errno)); freeaddrinfo(ailist); + aihint.ai_family = ai->ai_family; aihint.ai_flags = AI_ADDRCONFIG; parseaddr(&aihint, argv[optind + 1], 0, paf_parse, &ailist); for (ai = ailist; ai; ai = ai->ai_next)