X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Fnetwork%2Flookup_name.c;h=c93263a9d5542918f9462d41448b9756d92adc39;hb=167cbf1316246616c2cc200ab54a07e402c67a72;hp=86f90ac1b74b9b11183d8a495667da2d9989b7f4;hpb=6d70c08a2c37745df637b231711f6dec79dbc6e1;p=musl diff --git a/src/network/lookup_name.c b/src/network/lookup_name.c index 86f90ac1..c93263a9 100644 --- a/src/network/lookup_name.c +++ b/src/network/lookup_name.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "lookup.h" #include "stdio_impl.h" #include "syscall.h" @@ -98,11 +99,6 @@ struct dpc_ctx { int cnt; }; -int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); -int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); -int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); -int __res_msend_rc(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int, const struct resolvconf *); - #define RR_A 1 #define RR_CNAME 5 #define RR_AAAA 28 @@ -111,6 +107,7 @@ static int dns_parse_callback(void *c, int rr, const void *data, int len, const { char tmp[256]; struct dpc_ctx *ctx = c; + if (ctx->cnt >= MAXADDRS) return -1; switch (rr) { case RR_A: if (len != 4) return -1; @@ -141,16 +138,19 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static int qlens[2], alens[2]; int i, nq = 0; struct dpc_ctx ctx = { .addrs = buf, .canon = canon }; - - if (family != AF_INET6) { - qlens[nq] = __res_mkquery(0, name, 1, RR_A, 0, 0, 0, - qbuf[nq], sizeof *qbuf); - nq++; - } - if (family != AF_INET) { - qlens[nq] = __res_mkquery(0, name, 1, RR_AAAA, 0, 0, 0, - qbuf[nq], sizeof *qbuf); - nq++; + static const struct { int af; int rr; } afrr[2] = { + { .af = AF_INET6, .rr = RR_A }, + { .af = AF_INET, .rr = RR_AAAA }, + }; + + for (i=0; i<2; i++) { + if (family != afrr[i].af) { + qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr, + 0, 0, 0, qbuf[nq], sizeof *qbuf); + if (qlens[nq] == -1) + return EAI_NONAME; + nq++; + } } if (__res_msend_rc(nq, qp, qlens, ap, alens, sizeof *abuf, conf) < 0) @@ -180,6 +180,10 @@ static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[ for (dots=l=0; name[l]; l++) if (name[l]=='.') dots++; if (dots >= conf.ndots || name[l-1]=='.') *search = 0; + /* Strip final dot for canon, fail if multiple trailing dots. */ + if (name[l-1]=='.') l--; + if (!l || name[l-1]=='.') return EAI_NONAME; + /* This can never happen; the caller already checked length. */ if (l >= 256) return EAI_NONAME; @@ -335,8 +339,8 @@ int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], c /* No further processing is needed if there are fewer than 2 * results or if there are only IPv4 results. */ if (cnt<2 || family==AF_INET) return cnt; - for (i=0; buf[i].family == AF_INET; i++) - if (i==cnt) return cnt; + for (i=0; ilabel; int dprec = dpolicy->prec; int prefixlen = 0; - int fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); + int fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); if (fd >= 0) { - if (!connect(fd, (void *)&da, sizeof da)) { + if (!connect(fd, da, dalen)) { key |= DAS_USABLE; - if (!getsockname(fd, (void *)&sa, - &(socklen_t){sizeof sa})) { - if (dscope == scopeof(&sa.sin6_addr)) + if (!getsockname(fd, sa, &salen)) { + if (family == AF_INET) memcpy( + sa6.sin6_addr.s6_addr+12, + &sa4.sin_addr, 4); + if (dscope == scopeof(&sa6.sin6_addr)) key |= DAS_MATCHINGSCOPE; - if (dlabel == labelof(&sa.sin6_addr)) + if (dlabel == labelof(&sa6.sin6_addr)) key |= DAS_MATCHINGLABEL; - prefixlen = prefixmatch(&sa.sin6_addr, - &da.sin6_addr); + prefixlen = prefixmatch(&sa6.sin6_addr, + &da6.sin6_addr); } } close(fd);