1*a9e85050Seric /* $OpenBSD: common.c,v 1.4 2018/12/15 15:16:12 eric Exp $ */
24c1e55dcSeric /*
34c1e55dcSeric * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
44c1e55dcSeric *
54c1e55dcSeric * Permission to use, copy, modify, and distribute this software for any
64c1e55dcSeric * purpose with or without fee is hereby granted, provided that the above
74c1e55dcSeric * copyright notice and this permission notice appear in all copies.
84c1e55dcSeric *
94c1e55dcSeric * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104c1e55dcSeric * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114c1e55dcSeric * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124c1e55dcSeric * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134c1e55dcSeric * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144c1e55dcSeric * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154c1e55dcSeric * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164c1e55dcSeric */
174c1e55dcSeric #include <sys/types.h>
184c1e55dcSeric #include <sys/socket.h>
194c1e55dcSeric #include <netinet/in.h>
204c1e55dcSeric #include <arpa/inet.h>
214c1e55dcSeric #include <arpa/nameser.h>
224c1e55dcSeric
234c1e55dcSeric #include <err.h>
244c1e55dcSeric #include <errno.h>
254c1e55dcSeric #include <inttypes.h>
264c1e55dcSeric #include <netdb.h>
274c1e55dcSeric #include <resolv.h>
284c1e55dcSeric #include <stdio.h>
294c1e55dcSeric #include <string.h>
304c1e55dcSeric
314c1e55dcSeric #include "common.h"
324c1e55dcSeric
334c1e55dcSeric int long_err;
344c1e55dcSeric int gai_errno;
354c1e55dcSeric int rrset_errno;
364c1e55dcSeric
374c1e55dcSeric
384c1e55dcSeric char *
gethostarg(char * n)394c1e55dcSeric gethostarg(char *n)
404c1e55dcSeric {
414c1e55dcSeric if (n == NULL)
424c1e55dcSeric return (n);
434c1e55dcSeric if (!strcmp(n, "NULL"))
444c1e55dcSeric return (NULL);
454c1e55dcSeric if (!strcmp(n, "EMPTY"))
464c1e55dcSeric return ("");
474c1e55dcSeric return (n);
484c1e55dcSeric }
494c1e55dcSeric
504c1e55dcSeric const char *rrsetstrerror(int);
514c1e55dcSeric char * print_addr(const struct sockaddr *, char *, size_t);
524c1e55dcSeric
534c1e55dcSeric struct kv { int code; const char *name; };
544c1e55dcSeric
554c1e55dcSeric struct kv kv_family[] = {
564c1e55dcSeric { AF_UNIX, "unix" },
574c1e55dcSeric { AF_INET, "inet" },
584c1e55dcSeric { AF_INET6, "inet6" },
594c1e55dcSeric { 0, NULL, }
604c1e55dcSeric };
614c1e55dcSeric struct kv kv_socktype[] = {
624c1e55dcSeric { SOCK_STREAM, "stream" },
634c1e55dcSeric { SOCK_DGRAM, "dgram" },
644c1e55dcSeric { SOCK_RAW, "raw" },
65c2ec5216Sguenther { SOCK_SEQPACKET, "seqpacket" },
664c1e55dcSeric { 0, NULL, }
674c1e55dcSeric };
684c1e55dcSeric struct kv kv_protocol[] = {
694c1e55dcSeric { IPPROTO_UDP, "udp" },
704c1e55dcSeric { IPPROTO_TCP, "tcp" },
71f2033d2fSeric { IPPROTO_ICMP, "icmp" },
72f2033d2fSeric { IPPROTO_ICMPV6, "icmpv6" },
734c1e55dcSeric { 0, NULL, }
744c1e55dcSeric };
754c1e55dcSeric
764c1e55dcSeric static const char *
kv_lookup_name(struct kv * kv,int code,char * buf,size_t sz)77f2033d2fSeric kv_lookup_name(struct kv *kv, int code, char *buf, size_t sz)
784c1e55dcSeric {
794c1e55dcSeric while (kv->name) {
804c1e55dcSeric if (kv->code == code)
814c1e55dcSeric return (kv->name);
824c1e55dcSeric kv++;
834c1e55dcSeric }
84f2033d2fSeric snprintf(buf, sz, "%i", code);
85f2033d2fSeric return (buf);
864c1e55dcSeric }
874c1e55dcSeric
884c1e55dcSeric struct keyval {
894c1e55dcSeric const char *key;
90*a9e85050Seric int value;
914c1e55dcSeric };
924c1e55dcSeric
934c1e55dcSeric static struct keyval kv_class[] = {
944c1e55dcSeric { "IN", C_IN },
954c1e55dcSeric { "CHAOS", C_CHAOS },
964c1e55dcSeric { "HS", C_HS },
974c1e55dcSeric { "ANY", C_ANY },
984c1e55dcSeric { NULL, 0 },
994c1e55dcSeric };
1004c1e55dcSeric
1014c1e55dcSeric static struct keyval kv_type[] = {
1024c1e55dcSeric { "A", T_A },
1034c1e55dcSeric { "NS", T_NS },
1044c1e55dcSeric { "MD", T_MD },
1054c1e55dcSeric { "MF", T_MF },
1064c1e55dcSeric { "CNAME", T_CNAME },
1074c1e55dcSeric { "SOA", T_SOA },
1084c1e55dcSeric { "MB", T_MB },
1094c1e55dcSeric { "MG", T_MG },
1104c1e55dcSeric { "MR", T_MR },
1114c1e55dcSeric { "NULL", T_NULL },
1124c1e55dcSeric { "WKS", T_WKS },
1134c1e55dcSeric { "PTR", T_PTR },
1144c1e55dcSeric { "HINFO", T_HINFO },
1154c1e55dcSeric { "MINFO", T_MINFO },
1164c1e55dcSeric { "MX", T_MX },
1174c1e55dcSeric { "TXT", T_TXT },
1184c1e55dcSeric
1194c1e55dcSeric { "AAAA", T_AAAA },
1204c1e55dcSeric
1214c1e55dcSeric { "AXFR", T_AXFR },
1224c1e55dcSeric { "MAILB", T_MAILB },
1234c1e55dcSeric { "MAILA", T_MAILA },
1244c1e55dcSeric { "ANY", T_ANY },
1254c1e55dcSeric { NULL, 0 },
1264c1e55dcSeric };
1274c1e55dcSeric
1284c1e55dcSeric static struct keyval kv_rcode[] = {
1294c1e55dcSeric { "NOERROR", NOERROR },
1304c1e55dcSeric { "FORMERR", FORMERR },
1314c1e55dcSeric { "SERVFAIL", SERVFAIL },
1324c1e55dcSeric { "NXDOMAIN", NXDOMAIN },
1334c1e55dcSeric { "NOTIMP", NOTIMP },
1344c1e55dcSeric { "REFUSED", REFUSED },
1354c1e55dcSeric { NULL, 0 },
1364c1e55dcSeric };
1374c1e55dcSeric
138*a9e85050Seric static struct keyval kv_resopt[] = {
139*a9e85050Seric { "DEBUG", RES_DEBUG },
140*a9e85050Seric { "AAONLY", RES_AAONLY },
141*a9e85050Seric { "USEVC", RES_USEVC },
142*a9e85050Seric { "PRIMARY", RES_PRIMARY },
143*a9e85050Seric { "IGNTC", RES_IGNTC },
144*a9e85050Seric { "RECURSE", RES_RECURSE },
145*a9e85050Seric { "DEFNAMES", RES_DEFNAMES },
146*a9e85050Seric { "STAYOPEN", RES_STAYOPEN },
147*a9e85050Seric { "DNSRCH", RES_DNSRCH },
148*a9e85050Seric { "INSECURE1", RES_INSECURE1 },
149*a9e85050Seric { "INSECURE2", RES_INSECURE2 },
150*a9e85050Seric { "NOALIASES", RES_NOALIASES },
151*a9e85050Seric { "USE_INET6", RES_USE_INET6 },
152*a9e85050Seric { "USE_EDNS0", RES_USE_EDNS0 },
153*a9e85050Seric { "USE_DNSSEC", RES_USE_DNSSEC },
154*a9e85050Seric { NULL, 0 },
155*a9e85050Seric };
1564c1e55dcSeric
1574c1e55dcSeric const char *
rcodetostr(uint16_t v)1584c1e55dcSeric rcodetostr(uint16_t v)
1594c1e55dcSeric {
1604c1e55dcSeric static char buf[16];
1614c1e55dcSeric size_t i;
1624c1e55dcSeric
1634c1e55dcSeric for(i = 0; kv_rcode[i].key; i++)
1644c1e55dcSeric if (kv_rcode[i].value == v)
1654c1e55dcSeric return (kv_rcode[i].key);
1664c1e55dcSeric
1674c1e55dcSeric snprintf(buf, sizeof buf, "%"PRIu16"?", v);
1684c1e55dcSeric
1694c1e55dcSeric return (buf);
1704c1e55dcSeric }
1714c1e55dcSeric
1724c1e55dcSeric const char *
typetostr(uint16_t v)1734c1e55dcSeric typetostr(uint16_t v)
1744c1e55dcSeric {
1754c1e55dcSeric static char buf[16];
1764c1e55dcSeric size_t i;
1774c1e55dcSeric
1784c1e55dcSeric for(i = 0; kv_type[i].key; i++)
1794c1e55dcSeric if (kv_type[i].value == v)
1804c1e55dcSeric return (kv_type[i].key);
1814c1e55dcSeric
1824c1e55dcSeric snprintf(buf, sizeof buf, "%"PRIu16"?", v);
1834c1e55dcSeric
1844c1e55dcSeric return (buf);
1854c1e55dcSeric }
1864c1e55dcSeric
1874c1e55dcSeric const char *
classtostr(uint16_t v)1884c1e55dcSeric classtostr(uint16_t v)
1894c1e55dcSeric {
1904c1e55dcSeric static char buf[16];
1914c1e55dcSeric size_t i;
1924c1e55dcSeric
1934c1e55dcSeric for(i = 0; kv_class[i].key; i++)
1944c1e55dcSeric if (kv_class[i].value == v)
1954c1e55dcSeric return (kv_class[i].key);
1964c1e55dcSeric
1974c1e55dcSeric snprintf(buf, sizeof buf, "%"PRIu16"?", v);
1984c1e55dcSeric
1994c1e55dcSeric return (buf);
2004c1e55dcSeric }
2014c1e55dcSeric
2024c1e55dcSeric uint16_t
strtotype(const char * name)2034c1e55dcSeric strtotype(const char *name)
2044c1e55dcSeric {
2054c1e55dcSeric size_t i;
2064c1e55dcSeric
2074c1e55dcSeric for(i = 0; kv_type[i].key; i++)
208*a9e85050Seric if (!strcasecmp(kv_type[i].key, name))
2094c1e55dcSeric return (kv_type[i].value);
2104c1e55dcSeric
2114c1e55dcSeric return (0);
2124c1e55dcSeric }
2134c1e55dcSeric
2144c1e55dcSeric uint16_t
strtoclass(const char * name)2154c1e55dcSeric strtoclass(const char *name)
2164c1e55dcSeric {
2174c1e55dcSeric size_t i;
2184c1e55dcSeric
2194c1e55dcSeric for(i = 0; kv_class[i].key; i++)
220*a9e85050Seric if (!strcasecmp(kv_class[i].key, name))
2214c1e55dcSeric return (kv_class[i].value);
2224c1e55dcSeric
2234c1e55dcSeric return (0);
2244c1e55dcSeric }
2254c1e55dcSeric
226*a9e85050Seric int
strtoresopt(const char * name)227*a9e85050Seric strtoresopt(const char *name)
228*a9e85050Seric {
229*a9e85050Seric size_t i;
230*a9e85050Seric
231*a9e85050Seric for(i = 0; kv_resopt[i].key; i++)
232*a9e85050Seric if (!strcasecmp(kv_resopt[i].key, name))
233*a9e85050Seric return (kv_resopt[i].value);
234*a9e85050Seric
235*a9e85050Seric return (0);
236*a9e85050Seric }
237*a9e85050Seric
238*a9e85050Seric void
parseresopt(const char * name)239*a9e85050Seric parseresopt(const char *name)
240*a9e85050Seric {
241*a9e85050Seric static int init = 0;
242*a9e85050Seric int flag, neg = 0;
243*a9e85050Seric
244*a9e85050Seric if (init == 0) {
245*a9e85050Seric res_init();
246*a9e85050Seric init = 1;
247*a9e85050Seric }
248*a9e85050Seric
249*a9e85050Seric if (name[0] == '-') {
250*a9e85050Seric neg = 1;
251*a9e85050Seric name++;
252*a9e85050Seric }
253*a9e85050Seric else if (name[0] == '+')
254*a9e85050Seric name++;
255*a9e85050Seric
256*a9e85050Seric flag = strtoresopt(name);
257*a9e85050Seric if (flag == 0)
258*a9e85050Seric errx(1, "unknown reslover option %s", name);
259*a9e85050Seric
260*a9e85050Seric if (neg)
261*a9e85050Seric _res.options &= ~flag;
262*a9e85050Seric else
263*a9e85050Seric _res.options |= flag;
264*a9e85050Seric }
265*a9e85050Seric
2664c1e55dcSeric void
print_hostent(struct hostent * e)2674c1e55dcSeric print_hostent(struct hostent *e)
2684c1e55dcSeric {
2694c1e55dcSeric char buf[256], **c;
2704c1e55dcSeric
2714c1e55dcSeric printf("name = \"%s\"\n", e->h_name);
2724c1e55dcSeric printf("aliases =");
2734c1e55dcSeric for(c = e->h_aliases; *c; c++)
2744c1e55dcSeric printf(" \"%s\"", *c);
2754c1e55dcSeric printf("\n");
2764c1e55dcSeric printf("addrtype = %i\n", e->h_addrtype);
2774c1e55dcSeric printf("addrlength = %i\n", e->h_length);
2784c1e55dcSeric printf("addr_list =");
2794c1e55dcSeric for(c = e->h_addr_list; *c; c++) {
2804c1e55dcSeric printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf));
2814c1e55dcSeric }
2824c1e55dcSeric printf("\n");
2834c1e55dcSeric }
2844c1e55dcSeric
2854c1e55dcSeric void
print_netent(struct netent * e)2864c1e55dcSeric print_netent(struct netent *e)
2874c1e55dcSeric {
2884c1e55dcSeric char buf[256], **c;
2894c1e55dcSeric uint32_t addr;
2904c1e55dcSeric
2914c1e55dcSeric /* network number are given in host order */
2924c1e55dcSeric addr = htonl(e->n_net);
2934c1e55dcSeric
2944c1e55dcSeric printf("name = \"%s\"\n", e->n_name);
2954c1e55dcSeric printf("aliases =");
2964c1e55dcSeric for (c = e->n_aliases; *c; c++)
2974c1e55dcSeric printf(" \"%s\"", *c);
2984c1e55dcSeric printf("\n");
2994c1e55dcSeric printf("addrtype = %i\n", e->n_addrtype);
3004c1e55dcSeric printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf));
3014c1e55dcSeric }
3024c1e55dcSeric
3034c1e55dcSeric void
print_addrinfo(struct addrinfo * ai)3044c1e55dcSeric print_addrinfo(struct addrinfo *ai)
3054c1e55dcSeric {
306f2033d2fSeric char buf[256], bf[64], bt[64], bp[64];
3074c1e55dcSeric
3084c1e55dcSeric printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n",
309f2033d2fSeric kv_lookup_name(kv_family, ai->ai_family, bf, sizeof bf),
310f2033d2fSeric kv_lookup_name(kv_socktype, ai->ai_socktype, bt, sizeof bt),
311f2033d2fSeric kv_lookup_name(kv_protocol, ai->ai_protocol, bp, sizeof bp),
3124c1e55dcSeric print_addr(ai->ai_addr, buf, sizeof buf),
3134c1e55dcSeric ai->ai_canonname);
3144c1e55dcSeric }
3154c1e55dcSeric
3164c1e55dcSeric const char *
rrsetstrerror(int e)3174c1e55dcSeric rrsetstrerror(int e)
3184c1e55dcSeric {
3194c1e55dcSeric switch (e) {
3204c1e55dcSeric case 0:
3214c1e55dcSeric return "OK";
3224c1e55dcSeric case ERRSET_NONAME:
3234c1e55dcSeric return "ERRSET_NONAME";
3244c1e55dcSeric case ERRSET_NODATA:
3254c1e55dcSeric return "ERRSET_NODATA";
3264c1e55dcSeric case ERRSET_NOMEMORY:
3274c1e55dcSeric return "ERRSET_NOMEMORY";
3284c1e55dcSeric case ERRSET_INVAL:
3294c1e55dcSeric return "ERRSET_INVAL";
3304c1e55dcSeric case ERRSET_FAIL:
3314c1e55dcSeric return "ERRSET_FAIL";
3324c1e55dcSeric default:
3334c1e55dcSeric return "???";
3344c1e55dcSeric }
3354c1e55dcSeric }
3364c1e55dcSeric
3374c1e55dcSeric void
print_rrsetinfo(struct rrsetinfo * rrset)3384c1e55dcSeric print_rrsetinfo(struct rrsetinfo * rrset)
3394c1e55dcSeric {
3404c1e55dcSeric printf("rri_flags=%u\n", rrset->rri_flags);
3414c1e55dcSeric printf("rri_rdclass=%u\n", rrset->rri_rdclass);
3424c1e55dcSeric printf("rri_rdtype=%u\n", rrset->rri_rdtype);
3434c1e55dcSeric printf("rri_ttl=%u\n", rrset->rri_ttl);
3444c1e55dcSeric printf("rri_nrdatas=%u\n", rrset->rri_nrdatas);
3454c1e55dcSeric printf("rri_nsigs=%u\n", rrset->rri_nsigs);
3464c1e55dcSeric printf("rri_name=\"%s\"\n", rrset->rri_name);
3474c1e55dcSeric }
3484c1e55dcSeric
3494c1e55dcSeric void
print_errors(void)3504c1e55dcSeric print_errors(void)
3514c1e55dcSeric {
3524c1e55dcSeric switch (long_err) {
3534c1e55dcSeric case 0:
3544c1e55dcSeric return;
3554c1e55dcSeric case 1:
3564c1e55dcSeric printf(" => errno %i, h_errno %i", errno, h_errno);
3574c1e55dcSeric printf(", rrset_errno %i", rrset_errno);
3584c1e55dcSeric printf(", gai_errno %i", gai_errno);
3594c1e55dcSeric printf ("\n");
3604c1e55dcSeric return;
3614c1e55dcSeric default:
3624c1e55dcSeric printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n",
3634c1e55dcSeric errno, errno ? strerror(errno) : "ok",
3644c1e55dcSeric h_errno, h_errno ? hstrerror(h_errno) : "ok",
3654c1e55dcSeric rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok");
3664c1e55dcSeric printf(" => gai_errno %i: %s\n",
3674c1e55dcSeric gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok");
3684c1e55dcSeric }
3694c1e55dcSeric }
3704c1e55dcSeric
3714c1e55dcSeric
3724c1e55dcSeric static char *
print_host(const struct sockaddr * sa,char * buf,size_t len)3734c1e55dcSeric print_host(const struct sockaddr *sa, char *buf, size_t len)
3744c1e55dcSeric {
3754c1e55dcSeric switch (sa->sa_family) {
3764c1e55dcSeric case AF_INET:
3774c1e55dcSeric inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr,
3784c1e55dcSeric buf, len);
3794c1e55dcSeric break;
3804c1e55dcSeric case AF_INET6:
3814c1e55dcSeric inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr,
3824c1e55dcSeric buf, len);
3834c1e55dcSeric break;
3844c1e55dcSeric default:
3854c1e55dcSeric buf[0] = '\0';
3864c1e55dcSeric }
3874c1e55dcSeric return (buf);
3884c1e55dcSeric }
3894c1e55dcSeric
3904c1e55dcSeric
3914c1e55dcSeric char *
print_addr(const struct sockaddr * sa,char * buf,size_t len)3924c1e55dcSeric print_addr(const struct sockaddr *sa, char *buf, size_t len)
3934c1e55dcSeric {
3944c1e55dcSeric char h[256];
3954c1e55dcSeric
3964c1e55dcSeric print_host(sa, h, sizeof h);
3974c1e55dcSeric
3984c1e55dcSeric switch (sa->sa_family) {
3994c1e55dcSeric case AF_INET:
4004c1e55dcSeric snprintf(buf, len, "%s:%i", h,
4014c1e55dcSeric ntohs(((struct sockaddr_in*)(sa))->sin_port));
4024c1e55dcSeric break;
4034c1e55dcSeric case AF_INET6:
4044c1e55dcSeric snprintf(buf, len, "[%s]:%i", h,
4054c1e55dcSeric ntohs(((struct sockaddr_in6*)(sa))->sin6_port));
4064c1e55dcSeric break;
4074c1e55dcSeric default:
4084c1e55dcSeric snprintf(buf, len, "?");
4094c1e55dcSeric break;
4104c1e55dcSeric }
4114c1e55dcSeric
4124c1e55dcSeric return (buf);
4134c1e55dcSeric }
4144c1e55dcSeric
4154c1e55dcSeric void
packed_init(struct packed * pack,char * data,size_t len)4164c1e55dcSeric packed_init(struct packed *pack, char *data, size_t len)
4174c1e55dcSeric {
4184c1e55dcSeric pack->data = data;
4194c1e55dcSeric pack->len = len;
4204c1e55dcSeric pack->offset = 0;
4214c1e55dcSeric pack->err = NULL;
4224c1e55dcSeric }
4234c1e55dcSeric
4244c1e55dcSeric
4254c1e55dcSeric static ssize_t
dname_expand(const unsigned char * data,size_t len,size_t offset,size_t * newoffset,char * dst,size_t max)4264c1e55dcSeric dname_expand(const unsigned char *data, size_t len, size_t offset,
4274c1e55dcSeric size_t *newoffset, char *dst, size_t max)
4284c1e55dcSeric {
4294c1e55dcSeric size_t n, count, end, ptr, start;
4304c1e55dcSeric ssize_t res;
4314c1e55dcSeric
4324c1e55dcSeric if (offset >= len)
4334c1e55dcSeric return (-1);
4344c1e55dcSeric
4354c1e55dcSeric res = 0;
4364c1e55dcSeric end = start = offset;
4374c1e55dcSeric
4384c1e55dcSeric for(; (n = data[offset]); ) {
4394c1e55dcSeric if ((n & 0xc0) == 0xc0) {
4404c1e55dcSeric if (offset + 2 > len)
4414c1e55dcSeric return (-1);
4424c1e55dcSeric ptr = 256 * (n & ~0xc0) + data[offset + 1];
4434c1e55dcSeric if (ptr >= start)
4444c1e55dcSeric return (-1);
4454c1e55dcSeric if (end < offset + 2)
4464c1e55dcSeric end = offset + 2;
4474c1e55dcSeric offset = ptr;
4484c1e55dcSeric continue;
4494c1e55dcSeric }
4504c1e55dcSeric if (offset + n + 1 > len)
4514c1e55dcSeric return (-1);
4524c1e55dcSeric
4534c1e55dcSeric
4544c1e55dcSeric /* copy n + at offset+1 */
4554c1e55dcSeric if (dst != NULL && max != 0) {
4564c1e55dcSeric count = (max < n + 1) ? (max) : (n + 1);
4574c1e55dcSeric memmove(dst, data + offset, count);
4584c1e55dcSeric dst += count;
4594c1e55dcSeric max -= count;
4604c1e55dcSeric }
4614c1e55dcSeric res += n + 1;
4624c1e55dcSeric offset += n + 1;
4634c1e55dcSeric if (end < offset)
4644c1e55dcSeric end = offset;
4654c1e55dcSeric }
4664c1e55dcSeric if (end < offset + 1)
4674c1e55dcSeric end = offset + 1;
4684c1e55dcSeric
4694c1e55dcSeric if (dst != NULL && max != 0)
4704c1e55dcSeric dst[0] = 0;
4714c1e55dcSeric if (newoffset)
4724c1e55dcSeric *newoffset = end;
4734c1e55dcSeric return (res + 1);
4744c1e55dcSeric }
4754c1e55dcSeric
4764c1e55dcSeric static int
unpack_data(struct packed * p,void * data,size_t len)4774c1e55dcSeric unpack_data(struct packed *p, void *data, size_t len)
4784c1e55dcSeric {
4794c1e55dcSeric if (p->err)
4804c1e55dcSeric return (-1);
4814c1e55dcSeric
4824c1e55dcSeric if (p->len - p->offset < len) {
4834c1e55dcSeric p->err = "too short";
4844c1e55dcSeric return (-1);
4854c1e55dcSeric }
4864c1e55dcSeric
4874c1e55dcSeric memmove(data, p->data + p->offset, len);
4884c1e55dcSeric p->offset += len;
4894c1e55dcSeric
4904c1e55dcSeric return (0);
4914c1e55dcSeric }
4924c1e55dcSeric
4934c1e55dcSeric static int
unpack_u16(struct packed * p,uint16_t * u16)4944c1e55dcSeric unpack_u16(struct packed *p, uint16_t *u16)
4954c1e55dcSeric {
4964c1e55dcSeric if (unpack_data(p, u16, 2) == -1)
4974c1e55dcSeric return (-1);
4984c1e55dcSeric
4994c1e55dcSeric *u16 = ntohs(*u16);
5004c1e55dcSeric
5014c1e55dcSeric return (0);
5024c1e55dcSeric }
5034c1e55dcSeric
5044c1e55dcSeric static int
unpack_u32(struct packed * p,uint32_t * u32)5054c1e55dcSeric unpack_u32(struct packed *p, uint32_t *u32)
5064c1e55dcSeric {
5074c1e55dcSeric if (unpack_data(p, u32, 4) == -1)
5084c1e55dcSeric return (-1);
5094c1e55dcSeric
5104c1e55dcSeric *u32 = ntohl(*u32);
5114c1e55dcSeric
5124c1e55dcSeric return (0);
5134c1e55dcSeric }
5144c1e55dcSeric
5154c1e55dcSeric static int
unpack_inaddr(struct packed * p,struct in_addr * a)5164c1e55dcSeric unpack_inaddr(struct packed *p, struct in_addr *a)
5174c1e55dcSeric {
5184c1e55dcSeric return (unpack_data(p, a, 4));
5194c1e55dcSeric }
5204c1e55dcSeric
5214c1e55dcSeric static int
unpack_in6addr(struct packed * p,struct in6_addr * a6)5224c1e55dcSeric unpack_in6addr(struct packed *p, struct in6_addr *a6)
5234c1e55dcSeric {
5244c1e55dcSeric return (unpack_data(p, a6, 16));
5254c1e55dcSeric }
5264c1e55dcSeric
5274c1e55dcSeric static int
unpack_dname(struct packed * p,char * dst,size_t max)5284c1e55dcSeric unpack_dname(struct packed *p, char *dst, size_t max)
5294c1e55dcSeric {
5304c1e55dcSeric ssize_t e;
5314c1e55dcSeric
5324c1e55dcSeric if (p->err)
5334c1e55dcSeric return (-1);
5344c1e55dcSeric
5354c1e55dcSeric e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max);
5364c1e55dcSeric if (e == -1) {
5374c1e55dcSeric p->err = "bad domain name";
5384c1e55dcSeric return (-1);
5394c1e55dcSeric }
5404c1e55dcSeric if (e < 0 || e > MAXDNAME) {
5414c1e55dcSeric p->err = "domain name too long";
5424c1e55dcSeric return (-1);
5434c1e55dcSeric }
5444c1e55dcSeric
5454c1e55dcSeric return (0);
5464c1e55dcSeric }
5474c1e55dcSeric
5484c1e55dcSeric int
unpack_header(struct packed * p,struct header * h)5494c1e55dcSeric unpack_header(struct packed *p, struct header *h)
5504c1e55dcSeric {
5514c1e55dcSeric if (unpack_data(p, h, HFIXEDSZ) == -1)
5524c1e55dcSeric return (-1);
5534c1e55dcSeric
5544c1e55dcSeric h->flags = ntohs(h->flags);
5554c1e55dcSeric h->qdcount = ntohs(h->qdcount);
5564c1e55dcSeric h->ancount = ntohs(h->ancount);
5574c1e55dcSeric h->nscount = ntohs(h->nscount);
5584c1e55dcSeric h->arcount = ntohs(h->arcount);
5594c1e55dcSeric
5604c1e55dcSeric return (0);
5614c1e55dcSeric }
5624c1e55dcSeric
5634c1e55dcSeric int
unpack_query(struct packed * p,struct query * q)5644c1e55dcSeric unpack_query(struct packed *p, struct query *q)
5654c1e55dcSeric {
5664c1e55dcSeric unpack_dname(p, q->q_dname, sizeof(q->q_dname));
5674c1e55dcSeric unpack_u16(p, &q->q_type);
5684c1e55dcSeric unpack_u16(p, &q->q_class);
5694c1e55dcSeric
5704c1e55dcSeric return (p->err) ? (-1) : (0);
5714c1e55dcSeric }
5724c1e55dcSeric
5734c1e55dcSeric int
unpack_rr(struct packed * p,struct rr * rr)5744c1e55dcSeric unpack_rr(struct packed *p, struct rr *rr)
5754c1e55dcSeric {
5764c1e55dcSeric uint16_t rdlen;
5774c1e55dcSeric size_t save_offset;
5784c1e55dcSeric
5794c1e55dcSeric unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
5804c1e55dcSeric unpack_u16(p, &rr->rr_type);
5814c1e55dcSeric unpack_u16(p, &rr->rr_class);
5824c1e55dcSeric unpack_u32(p, &rr->rr_ttl);
5834c1e55dcSeric unpack_u16(p, &rdlen);
5844c1e55dcSeric
5854c1e55dcSeric if (p->err)
5864c1e55dcSeric return (-1);
5874c1e55dcSeric
5884c1e55dcSeric if (p->len - p->offset < rdlen) {
5894c1e55dcSeric p->err = "too short";
5904c1e55dcSeric return (-1);
5914c1e55dcSeric }
5924c1e55dcSeric
5934c1e55dcSeric save_offset = p->offset;
5944c1e55dcSeric
5954c1e55dcSeric switch(rr->rr_type) {
5964c1e55dcSeric
5974c1e55dcSeric case T_CNAME:
5984c1e55dcSeric unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
5994c1e55dcSeric break;
6004c1e55dcSeric
6014c1e55dcSeric case T_MX:
6024c1e55dcSeric unpack_u16(p, &rr->rr.mx.preference);
6034c1e55dcSeric unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
6044c1e55dcSeric break;
6054c1e55dcSeric
6064c1e55dcSeric case T_NS:
6074c1e55dcSeric unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
6084c1e55dcSeric break;
6094c1e55dcSeric
6104c1e55dcSeric case T_PTR:
6114c1e55dcSeric unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
6124c1e55dcSeric break;
6134c1e55dcSeric
6144c1e55dcSeric case T_SOA:
6154c1e55dcSeric unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
6164c1e55dcSeric unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
6174c1e55dcSeric unpack_u32(p, &rr->rr.soa.serial);
6184c1e55dcSeric unpack_u32(p, &rr->rr.soa.refresh);
6194c1e55dcSeric unpack_u32(p, &rr->rr.soa.retry);
6204c1e55dcSeric unpack_u32(p, &rr->rr.soa.expire);
6214c1e55dcSeric unpack_u32(p, &rr->rr.soa.minimum);
6224c1e55dcSeric break;
6234c1e55dcSeric
6244c1e55dcSeric case T_A:
6254c1e55dcSeric if (rr->rr_class != C_IN)
6264c1e55dcSeric goto other;
6274c1e55dcSeric unpack_inaddr(p, &rr->rr.in_a.addr);
6284c1e55dcSeric break;
6294c1e55dcSeric
6304c1e55dcSeric case T_AAAA:
6314c1e55dcSeric if (rr->rr_class != C_IN)
6324c1e55dcSeric goto other;
6334c1e55dcSeric unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
6344c1e55dcSeric break;
6354c1e55dcSeric default:
6364c1e55dcSeric other:
6374c1e55dcSeric rr->rr.other.rdata = p->data + p->offset;
6384c1e55dcSeric rr->rr.other.rdlen = rdlen;
6394c1e55dcSeric p->offset += rdlen;
6404c1e55dcSeric }
6414c1e55dcSeric
6424c1e55dcSeric if (p->err)
6434c1e55dcSeric return (-1);
6444c1e55dcSeric
6454c1e55dcSeric /* make sure that the advertised rdlen is really ok */
6464c1e55dcSeric if (p->offset - save_offset != rdlen)
6474c1e55dcSeric p->err = "bad dlen";
6484c1e55dcSeric
6494c1e55dcSeric return (p->err) ? (-1) : (0);
6504c1e55dcSeric }
6514c1e55dcSeric
6524c1e55dcSeric int
sockaddr_from_str(struct sockaddr * sa,int family,const char * str)6534c1e55dcSeric sockaddr_from_str(struct sockaddr *sa, int family, const char *str)
6544c1e55dcSeric {
6554c1e55dcSeric struct in_addr ina;
6564c1e55dcSeric struct in6_addr in6a;
6574c1e55dcSeric struct sockaddr_in *sin;
6584c1e55dcSeric struct sockaddr_in6 *sin6;
6594c1e55dcSeric
6604c1e55dcSeric switch (family) {
6614c1e55dcSeric case PF_UNSPEC:
6624c1e55dcSeric if (sockaddr_from_str(sa, PF_INET, str) == 0)
6634c1e55dcSeric return (0);
6644c1e55dcSeric return sockaddr_from_str(sa, PF_INET6, str);
6654c1e55dcSeric
6664c1e55dcSeric case PF_INET:
6674c1e55dcSeric if (inet_pton(PF_INET, str, &ina) != 1)
6684c1e55dcSeric return (-1);
6694c1e55dcSeric
6704c1e55dcSeric sin = (struct sockaddr_in *)sa;
6714c1e55dcSeric memset(sin, 0, sizeof *sin);
6724c1e55dcSeric sin->sin_len = sizeof(struct sockaddr_in);
6734c1e55dcSeric sin->sin_family = PF_INET;
6744c1e55dcSeric sin->sin_addr.s_addr = ina.s_addr;
6754c1e55dcSeric return (0);
6764c1e55dcSeric
6774c1e55dcSeric case PF_INET6:
6784c1e55dcSeric if (inet_pton(PF_INET6, str, &in6a) != 1)
6794c1e55dcSeric return (-1);
6804c1e55dcSeric
6814c1e55dcSeric sin6 = (struct sockaddr_in6 *)sa;
6824c1e55dcSeric memset(sin6, 0, sizeof *sin6);
6834c1e55dcSeric sin6->sin6_len = sizeof(struct sockaddr_in6);
6844c1e55dcSeric sin6->sin6_family = PF_INET6;
6854c1e55dcSeric sin6->sin6_addr = in6a;
6864c1e55dcSeric return (0);
6874c1e55dcSeric
6884c1e55dcSeric default:
6894c1e55dcSeric break;
6904c1e55dcSeric }
6914c1e55dcSeric
6924c1e55dcSeric return (-1);
6934c1e55dcSeric }
694