X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/813d2de98ea1bc45a68c3262c1df87f0834bd0ab..89640f3f83c29967e524d754bf130bc452bdefe2:/server/admin.c diff --git a/server/admin.c b/server/admin.c index e39658ef..44222eb8 100644 --- a/server/admin.c +++ b/server/admin.c @@ -272,14 +272,19 @@ void a_vformat(dstr *d, const char *fmt, va_list *ap) } else if (*fmt == '?') { if (strcmp(fmt, "?ADDR") == 0) { const addr *a = va_arg(*ap, const addr *); - switch (a->sa.sa_family) { - case AF_INET: - u_quotify(d, "INET"); - u_quotify(d, inet_ntoa(a->sin.sin_addr)); - dstr_putf(d, " %u", (unsigned)ntohs(a->sin.sin_port)); - break; - default: - abort(); + char name[NI_MAXHOST], serv[NI_MAXSERV]; + int ix, err; + if ((err = getnameinfo(&a->sa, addrsz(a), + name, sizeof(name), serv, sizeof(serv), + (NI_NUMERICHOST | NI_NUMERICSERV | + NI_DGRAM)))) { + dstr_putf(d, " E%d", err); + u_quotify(d, gai_strerror(err)); + } else { + ix = afix(a->sa.sa_family); assert(ix >= 0); + u_quotify(d, aftab[ix].name); + u_quotify(d, name); + u_quotify(d, serv); } } else if (strcmp(fmt, "?B64") == 0) { const octet *p = va_arg(*ap, const octet *); @@ -1028,7 +1033,9 @@ static void a_resolved(struct hostent *h, void *v) r->func(r, ARES_FAIL); } else { T( trace(T_ADMIN, "admin: resop %s ok", BGTAG(r)); ) + r->sa.sin.sin_family = AF_INET; memcpy(&r->sa.sin.sin_addr, h->h_addr, sizeof(struct in_addr)); + setport(&r->sa, r->port); r->func(r, ARES_OK); } sel_rmtimer(&r->t); @@ -1098,20 +1105,32 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, { struct timeval tv; unsigned long pt; + int af = AF_UNSPEC; + const char *fam = "ANY"; char *p; - int i = 0; + int i = 0, j; + struct addrinfo *ai, *ailist, aihint = { 0 }; /* --- Fill in the easy bits of address --- */ r->bg.tag = ""; r->addr = 0; r->func = func; - if (mystrieq(av[i], "inet")) i++; + if (mystrieq(av[i], "any")) + { fam = "ANY"; af = AF_UNSPEC; i++; } + else for (j = 0; j < NADDRFAM; j++) { + if (mystrieq(av[i], aftab[j].name)) { + assert(udpsock[j].fd >= 0); + fam = aftab[j].name; + af = aftab[j].af; + i++; + break; + } + } if (ac - i != 1 && ac - i != 2) { - a_fail(a, "bad-addr-syntax", "[inet] ADDRESS [PORT]", A_END); + a_fail(a, "bad-addr-syntax", "[FAMILY] ADDRESS [PORT]", A_END); goto fail; } - r->sa.sin.sin_family = AF_INET; r->addr = xstrdup(av[i]); if (!av[i + 1]) pt = TRIPE_PORT; @@ -1130,7 +1149,7 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, a_fail(a, "invalid-port", "%lu", pt, A_END); goto fail; } - r->sa.sin.sin_port = htons(pt); + r->port = pt; /* --- Report backgrounding --- * * @@ -1140,14 +1159,43 @@ static void a_resolve(admin *a, admin_resop *r, const char *tag, if (a_bgadd(a, &r->bg, tag, a_rescancel)) goto fail; - T( trace(T_ADMIN, "admin: %u, resop %s, hostname `%s'", - a->seq, BGTAG(r), r->addr); ) + T( trace(T_ADMIN, "admin: %u, resop %s, hostname `%s', family `%s'", + a->seq, BGTAG(r), r->addr, fam); ) + + /* --- Make sure the address family is something we can implement --- */ + + if (af != AF_UNSPEC && af != AF_INET) { + T( trace(T_ADMIN, "admin: resop %s failed: unsupported address family", + BGTAG(r)); ) + a_bgfail(&r->bg, "resolve-error", "%s", r->addr, A_END); + goto fail_release; + } + assert(udpsock[AFIX_INET].fd >= 0); /* --- If the name is numeric, do it the easy way --- */ - if (inet_aton(av[i], &r->sa.sin.sin_addr)) { - T( trace(T_ADMIN, "admin: resop %s done the easy way", BGTAG(r)); ) - func(r, ARES_OK); + aihint.ai_family = AF_INET; + aihint.ai_socktype = SOCK_DGRAM; + aihint.ai_protocol = IPPROTO_UDP; + aihint.ai_flags = AI_NUMERICHOST; + if (!getaddrinfo(av[i], 0, &aihint, &ailist)) { + for (ai = ailist; ai; ai = ai->ai_next) { + if ((j = afix(ai->ai_family)) >= 0 && udpsock[j].fd >= 0) + break; + } + if (!ai) { + T( trace(T_ADMIN, "admin: resop %s failed: " + "no suitable addresses returned", BGTAG(r)); ) + a_bgfail(&r->bg, "resolve-error", "%s" , r->addr, A_END); + func(r, ARES_FAIL); + } else { + T( trace(T_ADMIN, "admin: resop %s done the easy way", BGTAG(r)); ) + assert(ai->ai_addrlen <= sizeof(r->sa)); + memcpy(&r->sa, ai->ai_addr, ai->ai_addrlen); + setport(&r->sa, r->port); + func(r, ARES_OK); + } + freeaddrinfo(ailist); xfree(r->addr); a_bgrelease(&r->bg); return; @@ -1165,6 +1213,12 @@ fail: func(r, ARES_FAIL); if (r->addr) xfree(r->addr); xfree(r); + return; + +fail_release: + func(r, ARES_FAIL); + xfree(r->addr); + a_bgrelease(&r->bg); } /*----- Option parsing ----------------------------------------------------*/ @@ -1848,7 +1902,6 @@ static void acmd_addr(admin *a, unsigned ac, char *av[]) if ((p = a_findpeer(a, av[0])) != 0) { ad = p_addr(p); - assert(ad->sa.sa_family == AF_INET); a_info(a, "?ADDR", ad, A_END); a_ok(a); }