From 3a33734a8402d2c1ace1b0a28012f40936eb7c46 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 29 Dec 2021 14:11:12 -0600 Subject: [PATCH] Teach host to look up nameserver in /etc/resolv.conf and use same codepath for specified nameservers and system nameservers. This means bionic not having res_send() isn't a problem. --- toys/pending/host.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/toys/pending/host.c b/toys/pending/host.c index c99eabef..a8562498 100644 --- a/toys/pending/host.c +++ b/toys/pending/host.c @@ -28,6 +28,9 @@ config HOST GLOBALS( char *t; + + char **nsname; + unsigned nslen; ) static const struct rrt { @@ -49,13 +52,31 @@ int xdn_expand(char *packet, char *endpkt, char *comp, char *expand, int elen) return i; } +// Fetch "nameserve" lines from /etc/resolv.conf. Ignores 'options' lines +static void get_nsname(char **pline, long len) +{ + char *line, *p; + + if (!len) return; + line = *pline; + if (strstart(&line, "nameserver") && isspace(*line)) { + while (isspace(*line)) line++; + for (p = line; *p && !isspace(*p) && *p!='#'; p++); + if (p == line) return; + *p = 0; + if (!(TT.nslen&8)) + TT.nsname = xrealloc(TT.nsname, (TT.nslen+8)*sizeof(void *)); + TT.nsname[TT.nslen++] = xstrdup(line); + } +} + void host_main(void) { int verbose = FLAG(a)||FLAG(v), type, abuf_len = 65536, //Largest TCP response - i, j, sec, rcode, qlen, alen, pllen = 0, t2len = 2048; + i, j, sec, rcode, qlen, alen QUIET, pllen = 0, t2len = 2048; unsigned count, ttl; char *abuf = xmalloc(abuf_len), *name = *toys.optargs, *p, *ss, - *nsname = toys.optargs[1], *t2 = toybuf+t2len; + *t2 = toybuf+t2len; struct addrinfo *ai; // What kind of query are we doing? @@ -87,18 +108,24 @@ void host_main(void) qlen = res_mkquery(0, name, 1, type, 0, 0, 0, t2, 280); //t2len); if (qlen<0) error_exit("bad NAME: %s", name); - // Send query packet to server, receive response - if (nsname) { - ai = xgetaddrinfo(nsname, "53", 0, SOCK_DGRAM, 0, 0); + // Grab nameservers + if (toys.optargs[1]) TT.nsname = toys.optargs+1; + else do_lines(xopen("/etc/resolv.conf", O_RDONLY), '\n', get_nsname); + if (!TT.nsname) error_exit("No nameservers"); + + // Send one query packet to each server until we receive response + while (*TT.nsname) { + if (verbose) printf("Using domain server %s:\n", *TT.nsname); + ai = xgetaddrinfo(*TT.nsname, "53", 0, SOCK_DGRAM, 0, 0); i = xsocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); xconnect(i, ai->ai_addr, ai->ai_addrlen); setsockopt(i, SOL_SOCKET, SO_RCVTIMEO, &(struct timeval){ .tv_sec = 5 }, sizeof(struct timeval)); - if (verbose) printf("Using domain server %s:\n", nsname); send(i, t2, qlen, 0); - alen = recv(i, abuf, abuf_len, 0); - } else alen = res_send(t2, qlen, abuf, abuf_len); - if (alen < 16) error_exit("Host not found."); + if (16 < (alen = recv(i, abuf, abuf_len, 0))) break; + if (!*++TT.nsname) error_exit("Host not found."); + close(i); + } // Did it error? rcode = abuf[3]&7; -- 2.39.2