summaryrefslogtreecommitdiff
path: root/src/network/getnameinfo.c
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2014-06-02 04:47:45 -0400
committerRich Felker <dalias@aerifal.cx>2014-06-02 04:47:45 -0400
commit3330198060c7b3165a2fba530ffde5fc6706ecf2 (patch)
treebc87811d35022e240dfe8d24f96402ac2feaa65a /src/network/getnameinfo.c
parenta2a328bd896fa909542b492601e3689119b95de0 (diff)
downloadmusl-3330198060c7b3165a2fba530ffde5fc6706ecf2.tar.gz
switch standard resolver functions to use the new dns backend
this is the third phase of the "resolver overhaul" project. this commit removes all of the old dns code, and switches the __lookup_name backend (used by getaddrinfo, etc.) and the getnameinfo function to use the newly implemented __res_mkquery and __res_msend interfaces. for parsing the results, a new callback-based __dns_parse function, based on __dns_get_rr from the old dns code, is used.
Diffstat (limited to 'src/network/getnameinfo.c')
-rw-r--r--src/network/getnameinfo.c59
1 files changed, 53 insertions, 6 deletions
diff --git a/src/network/getnameinfo.c b/src/network/getnameinfo.c
index 33f89a38..dfcf6eda 100644
--- a/src/network/getnameinfo.c
+++ b/src/network/getnameinfo.c
@@ -5,15 +5,50 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include "__dns.h"
+
+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_send(const unsigned char *, int, unsigned char *, int);
+
+#define PTR_MAX (64 + sizeof ".in-addr.arpa")
+#define RR_PTR 12
+
+static void mkptr4(char *s, const unsigned char *ip)
+{
+ sprintf(s, "%d.%d.%d.%d.in-addr.arpa",
+ ip[3], ip[2], ip[1], ip[0]);
+}
+
+static void mkptr6(char *s, const unsigned char *ip)
+{
+ static const char xdigits[] = "0123456789abcdef";
+ int i;
+ for (i=15; i>=0; i--) {
+ *s++ = xdigits[ip[i]&15]; *s++ = '.';
+ *s++ = xdigits[ip[i]>>4]; *s++ = '.';
+ }
+ strcpy(s, "ip6.arpa");
+}
+
+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
+{
+ char tmp[256];
+ if (rr != RR_PTR) return 0;
+ if (__dn_expand(packet, (const unsigned char *)packet + 512,
+ data, tmp, sizeof tmp) > 0)
+ strcpy(c, tmp);
+ return 0;
+
+}
int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
char *restrict node, socklen_t nodelen,
char *restrict serv, socklen_t servlen,
int flags)
{
+ char ptr[PTR_MAX];
char buf[256];
- unsigned char reply[512];
int af = sa->sa_family;
unsigned char *a;
@@ -21,20 +56,32 @@ int getnameinfo(const struct sockaddr *restrict sa, socklen_t sl,
case AF_INET:
a = (void *)&((struct sockaddr_in *)sa)->sin_addr;
if (sl != sizeof(struct sockaddr_in)) return EAI_FAMILY;
+ mkptr4(ptr, a);
break;
case AF_INET6:
a = (void *)&((struct sockaddr_in6 *)sa)->sin6_addr;
if (sl != sizeof(struct sockaddr_in6)) return EAI_FAMILY;
+ if (memcmp(a, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12))
+ mkptr6(ptr, a);
+ else
+ mkptr4(ptr, a+12);
break;
default:
return EAI_FAMILY;
}
if (node && nodelen) {
- if ((flags & NI_NUMERICHOST)
- || __dns_query(reply, a, af, 1) <= 0
- || __dns_get_rr(buf, 0, 256, 1, reply, RR_PTR, 1) <= 0)
- {
+ buf[0] = 0;
+ if (!(flags & NI_NUMERICHOST)) {
+ unsigned char query[18+PTR_MAX], reply[512];
+ int qlen = __res_mkquery(0, ptr, 1, RR_PTR,
+ 0, 0, 0, query, sizeof query);
+ int rlen = __res_send(query, qlen, reply, sizeof reply);
+ buf[0] = 0;
+ if (rlen > 0)
+ __dns_parse(reply, rlen, dns_parse_callback, buf);
+ }
+ if (!*buf) {
if (flags & NI_NAMEREQD) return EAI_NONAME;
inet_ntop(af, a, buf, sizeof buf);
}