1 /* $OpenBSD: common.c,v 1.4 2018/12/15 15:16:12 eric Exp $ */
2 /*
3 * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <arpa/nameser.h>
22
23 #include <err.h>
24 #include <errno.h>
25 #include <inttypes.h>
26 #include <netdb.h>
27 #include <resolv.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "common.h"
32
33 int long_err;
34 int gai_errno;
35 int rrset_errno;
36
37
38 char *
gethostarg(char * n)39 gethostarg(char *n)
40 {
41 if (n == NULL)
42 return (n);
43 if (!strcmp(n, "NULL"))
44 return (NULL);
45 if (!strcmp(n, "EMPTY"))
46 return ("");
47 return (n);
48 }
49
50 const char *rrsetstrerror(int);
51 char * print_addr(const struct sockaddr *, char *, size_t);
52
53 struct kv { int code; const char *name; };
54
55 struct kv kv_family[] = {
56 { AF_UNIX, "unix" },
57 { AF_INET, "inet" },
58 { AF_INET6, "inet6" },
59 { 0, NULL, }
60 };
61 struct kv kv_socktype[] = {
62 { SOCK_STREAM, "stream" },
63 { SOCK_DGRAM, "dgram" },
64 { SOCK_RAW, "raw" },
65 { SOCK_SEQPACKET, "seqpacket" },
66 { 0, NULL, }
67 };
68 struct kv kv_protocol[] = {
69 { IPPROTO_UDP, "udp" },
70 { IPPROTO_TCP, "tcp" },
71 { IPPROTO_ICMP, "icmp" },
72 { IPPROTO_ICMPV6, "icmpv6" },
73 { 0, NULL, }
74 };
75
76 static const char *
kv_lookup_name(struct kv * kv,int code,char * buf,size_t sz)77 kv_lookup_name(struct kv *kv, int code, char *buf, size_t sz)
78 {
79 while (kv->name) {
80 if (kv->code == code)
81 return (kv->name);
82 kv++;
83 }
84 snprintf(buf, sz, "%i", code);
85 return (buf);
86 }
87
88 struct keyval {
89 const char *key;
90 int value;
91 };
92
93 static struct keyval kv_class[] = {
94 { "IN", C_IN },
95 { "CHAOS", C_CHAOS },
96 { "HS", C_HS },
97 { "ANY", C_ANY },
98 { NULL, 0 },
99 };
100
101 static struct keyval kv_type[] = {
102 { "A", T_A },
103 { "NS", T_NS },
104 { "MD", T_MD },
105 { "MF", T_MF },
106 { "CNAME", T_CNAME },
107 { "SOA", T_SOA },
108 { "MB", T_MB },
109 { "MG", T_MG },
110 { "MR", T_MR },
111 { "NULL", T_NULL },
112 { "WKS", T_WKS },
113 { "PTR", T_PTR },
114 { "HINFO", T_HINFO },
115 { "MINFO", T_MINFO },
116 { "MX", T_MX },
117 { "TXT", T_TXT },
118
119 { "AAAA", T_AAAA },
120
121 { "AXFR", T_AXFR },
122 { "MAILB", T_MAILB },
123 { "MAILA", T_MAILA },
124 { "ANY", T_ANY },
125 { NULL, 0 },
126 };
127
128 static struct keyval kv_rcode[] = {
129 { "NOERROR", NOERROR },
130 { "FORMERR", FORMERR },
131 { "SERVFAIL", SERVFAIL },
132 { "NXDOMAIN", NXDOMAIN },
133 { "NOTIMP", NOTIMP },
134 { "REFUSED", REFUSED },
135 { NULL, 0 },
136 };
137
138 static struct keyval kv_resopt[] = {
139 { "DEBUG", RES_DEBUG },
140 { "AAONLY", RES_AAONLY },
141 { "USEVC", RES_USEVC },
142 { "PRIMARY", RES_PRIMARY },
143 { "IGNTC", RES_IGNTC },
144 { "RECURSE", RES_RECURSE },
145 { "DEFNAMES", RES_DEFNAMES },
146 { "STAYOPEN", RES_STAYOPEN },
147 { "DNSRCH", RES_DNSRCH },
148 { "INSECURE1", RES_INSECURE1 },
149 { "INSECURE2", RES_INSECURE2 },
150 { "NOALIASES", RES_NOALIASES },
151 { "USE_INET6", RES_USE_INET6 },
152 { "USE_EDNS0", RES_USE_EDNS0 },
153 { "USE_DNSSEC", RES_USE_DNSSEC },
154 { NULL, 0 },
155 };
156
157 const char *
rcodetostr(uint16_t v)158 rcodetostr(uint16_t v)
159 {
160 static char buf[16];
161 size_t i;
162
163 for(i = 0; kv_rcode[i].key; i++)
164 if (kv_rcode[i].value == v)
165 return (kv_rcode[i].key);
166
167 snprintf(buf, sizeof buf, "%"PRIu16"?", v);
168
169 return (buf);
170 }
171
172 const char *
typetostr(uint16_t v)173 typetostr(uint16_t v)
174 {
175 static char buf[16];
176 size_t i;
177
178 for(i = 0; kv_type[i].key; i++)
179 if (kv_type[i].value == v)
180 return (kv_type[i].key);
181
182 snprintf(buf, sizeof buf, "%"PRIu16"?", v);
183
184 return (buf);
185 }
186
187 const char *
classtostr(uint16_t v)188 classtostr(uint16_t v)
189 {
190 static char buf[16];
191 size_t i;
192
193 for(i = 0; kv_class[i].key; i++)
194 if (kv_class[i].value == v)
195 return (kv_class[i].key);
196
197 snprintf(buf, sizeof buf, "%"PRIu16"?", v);
198
199 return (buf);
200 }
201
202 uint16_t
strtotype(const char * name)203 strtotype(const char *name)
204 {
205 size_t i;
206
207 for(i = 0; kv_type[i].key; i++)
208 if (!strcasecmp(kv_type[i].key, name))
209 return (kv_type[i].value);
210
211 return (0);
212 }
213
214 uint16_t
strtoclass(const char * name)215 strtoclass(const char *name)
216 {
217 size_t i;
218
219 for(i = 0; kv_class[i].key; i++)
220 if (!strcasecmp(kv_class[i].key, name))
221 return (kv_class[i].value);
222
223 return (0);
224 }
225
226 int
strtoresopt(const char * name)227 strtoresopt(const char *name)
228 {
229 size_t i;
230
231 for(i = 0; kv_resopt[i].key; i++)
232 if (!strcasecmp(kv_resopt[i].key, name))
233 return (kv_resopt[i].value);
234
235 return (0);
236 }
237
238 void
parseresopt(const char * name)239 parseresopt(const char *name)
240 {
241 static int init = 0;
242 int flag, neg = 0;
243
244 if (init == 0) {
245 res_init();
246 init = 1;
247 }
248
249 if (name[0] == '-') {
250 neg = 1;
251 name++;
252 }
253 else if (name[0] == '+')
254 name++;
255
256 flag = strtoresopt(name);
257 if (flag == 0)
258 errx(1, "unknown reslover option %s", name);
259
260 if (neg)
261 _res.options &= ~flag;
262 else
263 _res.options |= flag;
264 }
265
266 void
print_hostent(struct hostent * e)267 print_hostent(struct hostent *e)
268 {
269 char buf[256], **c;
270
271 printf("name = \"%s\"\n", e->h_name);
272 printf("aliases =");
273 for(c = e->h_aliases; *c; c++)
274 printf(" \"%s\"", *c);
275 printf("\n");
276 printf("addrtype = %i\n", e->h_addrtype);
277 printf("addrlength = %i\n", e->h_length);
278 printf("addr_list =");
279 for(c = e->h_addr_list; *c; c++) {
280 printf(" %s", inet_ntop(e->h_addrtype, *c, buf, sizeof buf));
281 }
282 printf("\n");
283 }
284
285 void
print_netent(struct netent * e)286 print_netent(struct netent *e)
287 {
288 char buf[256], **c;
289 uint32_t addr;
290
291 /* network number are given in host order */
292 addr = htonl(e->n_net);
293
294 printf("name = \"%s\"\n", e->n_name);
295 printf("aliases =");
296 for (c = e->n_aliases; *c; c++)
297 printf(" \"%s\"", *c);
298 printf("\n");
299 printf("addrtype = %i\n", e->n_addrtype);
300 printf("net = %s\n", inet_ntop(e->n_addrtype, &addr, buf, sizeof buf));
301 }
302
303 void
print_addrinfo(struct addrinfo * ai)304 print_addrinfo(struct addrinfo *ai)
305 {
306 char buf[256], bf[64], bt[64], bp[64];
307
308 printf("family=%s socktype=%s protocol=%s addr=%s canonname=%s\n",
309 kv_lookup_name(kv_family, ai->ai_family, bf, sizeof bf),
310 kv_lookup_name(kv_socktype, ai->ai_socktype, bt, sizeof bt),
311 kv_lookup_name(kv_protocol, ai->ai_protocol, bp, sizeof bp),
312 print_addr(ai->ai_addr, buf, sizeof buf),
313 ai->ai_canonname);
314 }
315
316 const char *
rrsetstrerror(int e)317 rrsetstrerror(int e)
318 {
319 switch (e) {
320 case 0:
321 return "OK";
322 case ERRSET_NONAME:
323 return "ERRSET_NONAME";
324 case ERRSET_NODATA:
325 return "ERRSET_NODATA";
326 case ERRSET_NOMEMORY:
327 return "ERRSET_NOMEMORY";
328 case ERRSET_INVAL:
329 return "ERRSET_INVAL";
330 case ERRSET_FAIL:
331 return "ERRSET_FAIL";
332 default:
333 return "???";
334 }
335 }
336
337 void
print_rrsetinfo(struct rrsetinfo * rrset)338 print_rrsetinfo(struct rrsetinfo * rrset)
339 {
340 printf("rri_flags=%u\n", rrset->rri_flags);
341 printf("rri_rdclass=%u\n", rrset->rri_rdclass);
342 printf("rri_rdtype=%u\n", rrset->rri_rdtype);
343 printf("rri_ttl=%u\n", rrset->rri_ttl);
344 printf("rri_nrdatas=%u\n", rrset->rri_nrdatas);
345 printf("rri_nsigs=%u\n", rrset->rri_nsigs);
346 printf("rri_name=\"%s\"\n", rrset->rri_name);
347 }
348
349 void
print_errors(void)350 print_errors(void)
351 {
352 switch (long_err) {
353 case 0:
354 return;
355 case 1:
356 printf(" => errno %i, h_errno %i", errno, h_errno);
357 printf(", rrset_errno %i", rrset_errno);
358 printf(", gai_errno %i", gai_errno);
359 printf ("\n");
360 return;
361 default:
362 printf(" => errno %i: %s\n => h_errno %i: %s\n => rrset_errno %i: %s\n",
363 errno, errno ? strerror(errno) : "ok",
364 h_errno, h_errno ? hstrerror(h_errno) : "ok",
365 rrset_errno, rrset_errno ? rrsetstrerror(rrset_errno) : "ok");
366 printf(" => gai_errno %i: %s\n",
367 gai_errno, gai_errno ? gai_strerror(gai_errno) : "ok");
368 }
369 }
370
371
372 static char *
print_host(const struct sockaddr * sa,char * buf,size_t len)373 print_host(const struct sockaddr *sa, char *buf, size_t len)
374 {
375 switch (sa->sa_family) {
376 case AF_INET:
377 inet_ntop(AF_INET, &((struct sockaddr_in*)sa)->sin_addr,
378 buf, len);
379 break;
380 case AF_INET6:
381 inet_ntop(AF_INET6, &((struct sockaddr_in6*)sa)->sin6_addr,
382 buf, len);
383 break;
384 default:
385 buf[0] = '\0';
386 }
387 return (buf);
388 }
389
390
391 char *
print_addr(const struct sockaddr * sa,char * buf,size_t len)392 print_addr(const struct sockaddr *sa, char *buf, size_t len)
393 {
394 char h[256];
395
396 print_host(sa, h, sizeof h);
397
398 switch (sa->sa_family) {
399 case AF_INET:
400 snprintf(buf, len, "%s:%i", h,
401 ntohs(((struct sockaddr_in*)(sa))->sin_port));
402 break;
403 case AF_INET6:
404 snprintf(buf, len, "[%s]:%i", h,
405 ntohs(((struct sockaddr_in6*)(sa))->sin6_port));
406 break;
407 default:
408 snprintf(buf, len, "?");
409 break;
410 }
411
412 return (buf);
413 }
414
415 void
packed_init(struct packed * pack,char * data,size_t len)416 packed_init(struct packed *pack, char *data, size_t len)
417 {
418 pack->data = data;
419 pack->len = len;
420 pack->offset = 0;
421 pack->err = NULL;
422 }
423
424
425 static ssize_t
dname_expand(const unsigned char * data,size_t len,size_t offset,size_t * newoffset,char * dst,size_t max)426 dname_expand(const unsigned char *data, size_t len, size_t offset,
427 size_t *newoffset, char *dst, size_t max)
428 {
429 size_t n, count, end, ptr, start;
430 ssize_t res;
431
432 if (offset >= len)
433 return (-1);
434
435 res = 0;
436 end = start = offset;
437
438 for(; (n = data[offset]); ) {
439 if ((n & 0xc0) == 0xc0) {
440 if (offset + 2 > len)
441 return (-1);
442 ptr = 256 * (n & ~0xc0) + data[offset + 1];
443 if (ptr >= start)
444 return (-1);
445 if (end < offset + 2)
446 end = offset + 2;
447 offset = ptr;
448 continue;
449 }
450 if (offset + n + 1 > len)
451 return (-1);
452
453
454 /* copy n + at offset+1 */
455 if (dst != NULL && max != 0) {
456 count = (max < n + 1) ? (max) : (n + 1);
457 memmove(dst, data + offset, count);
458 dst += count;
459 max -= count;
460 }
461 res += n + 1;
462 offset += n + 1;
463 if (end < offset)
464 end = offset;
465 }
466 if (end < offset + 1)
467 end = offset + 1;
468
469 if (dst != NULL && max != 0)
470 dst[0] = 0;
471 if (newoffset)
472 *newoffset = end;
473 return (res + 1);
474 }
475
476 static int
unpack_data(struct packed * p,void * data,size_t len)477 unpack_data(struct packed *p, void *data, size_t len)
478 {
479 if (p->err)
480 return (-1);
481
482 if (p->len - p->offset < len) {
483 p->err = "too short";
484 return (-1);
485 }
486
487 memmove(data, p->data + p->offset, len);
488 p->offset += len;
489
490 return (0);
491 }
492
493 static int
unpack_u16(struct packed * p,uint16_t * u16)494 unpack_u16(struct packed *p, uint16_t *u16)
495 {
496 if (unpack_data(p, u16, 2) == -1)
497 return (-1);
498
499 *u16 = ntohs(*u16);
500
501 return (0);
502 }
503
504 static int
unpack_u32(struct packed * p,uint32_t * u32)505 unpack_u32(struct packed *p, uint32_t *u32)
506 {
507 if (unpack_data(p, u32, 4) == -1)
508 return (-1);
509
510 *u32 = ntohl(*u32);
511
512 return (0);
513 }
514
515 static int
unpack_inaddr(struct packed * p,struct in_addr * a)516 unpack_inaddr(struct packed *p, struct in_addr *a)
517 {
518 return (unpack_data(p, a, 4));
519 }
520
521 static int
unpack_in6addr(struct packed * p,struct in6_addr * a6)522 unpack_in6addr(struct packed *p, struct in6_addr *a6)
523 {
524 return (unpack_data(p, a6, 16));
525 }
526
527 static int
unpack_dname(struct packed * p,char * dst,size_t max)528 unpack_dname(struct packed *p, char *dst, size_t max)
529 {
530 ssize_t e;
531
532 if (p->err)
533 return (-1);
534
535 e = dname_expand(p->data, p->len, p->offset, &p->offset, dst, max);
536 if (e == -1) {
537 p->err = "bad domain name";
538 return (-1);
539 }
540 if (e < 0 || e > MAXDNAME) {
541 p->err = "domain name too long";
542 return (-1);
543 }
544
545 return (0);
546 }
547
548 int
unpack_header(struct packed * p,struct header * h)549 unpack_header(struct packed *p, struct header *h)
550 {
551 if (unpack_data(p, h, HFIXEDSZ) == -1)
552 return (-1);
553
554 h->flags = ntohs(h->flags);
555 h->qdcount = ntohs(h->qdcount);
556 h->ancount = ntohs(h->ancount);
557 h->nscount = ntohs(h->nscount);
558 h->arcount = ntohs(h->arcount);
559
560 return (0);
561 }
562
563 int
unpack_query(struct packed * p,struct query * q)564 unpack_query(struct packed *p, struct query *q)
565 {
566 unpack_dname(p, q->q_dname, sizeof(q->q_dname));
567 unpack_u16(p, &q->q_type);
568 unpack_u16(p, &q->q_class);
569
570 return (p->err) ? (-1) : (0);
571 }
572
573 int
unpack_rr(struct packed * p,struct rr * rr)574 unpack_rr(struct packed *p, struct rr *rr)
575 {
576 uint16_t rdlen;
577 size_t save_offset;
578
579 unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
580 unpack_u16(p, &rr->rr_type);
581 unpack_u16(p, &rr->rr_class);
582 unpack_u32(p, &rr->rr_ttl);
583 unpack_u16(p, &rdlen);
584
585 if (p->err)
586 return (-1);
587
588 if (p->len - p->offset < rdlen) {
589 p->err = "too short";
590 return (-1);
591 }
592
593 save_offset = p->offset;
594
595 switch(rr->rr_type) {
596
597 case T_CNAME:
598 unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
599 break;
600
601 case T_MX:
602 unpack_u16(p, &rr->rr.mx.preference);
603 unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
604 break;
605
606 case T_NS:
607 unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
608 break;
609
610 case T_PTR:
611 unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
612 break;
613
614 case T_SOA:
615 unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
616 unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
617 unpack_u32(p, &rr->rr.soa.serial);
618 unpack_u32(p, &rr->rr.soa.refresh);
619 unpack_u32(p, &rr->rr.soa.retry);
620 unpack_u32(p, &rr->rr.soa.expire);
621 unpack_u32(p, &rr->rr.soa.minimum);
622 break;
623
624 case T_A:
625 if (rr->rr_class != C_IN)
626 goto other;
627 unpack_inaddr(p, &rr->rr.in_a.addr);
628 break;
629
630 case T_AAAA:
631 if (rr->rr_class != C_IN)
632 goto other;
633 unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
634 break;
635 default:
636 other:
637 rr->rr.other.rdata = p->data + p->offset;
638 rr->rr.other.rdlen = rdlen;
639 p->offset += rdlen;
640 }
641
642 if (p->err)
643 return (-1);
644
645 /* make sure that the advertised rdlen is really ok */
646 if (p->offset - save_offset != rdlen)
647 p->err = "bad dlen";
648
649 return (p->err) ? (-1) : (0);
650 }
651
652 int
sockaddr_from_str(struct sockaddr * sa,int family,const char * str)653 sockaddr_from_str(struct sockaddr *sa, int family, const char *str)
654 {
655 struct in_addr ina;
656 struct in6_addr in6a;
657 struct sockaddr_in *sin;
658 struct sockaddr_in6 *sin6;
659
660 switch (family) {
661 case PF_UNSPEC:
662 if (sockaddr_from_str(sa, PF_INET, str) == 0)
663 return (0);
664 return sockaddr_from_str(sa, PF_INET6, str);
665
666 case PF_INET:
667 if (inet_pton(PF_INET, str, &ina) != 1)
668 return (-1);
669
670 sin = (struct sockaddr_in *)sa;
671 memset(sin, 0, sizeof *sin);
672 sin->sin_len = sizeof(struct sockaddr_in);
673 sin->sin_family = PF_INET;
674 sin->sin_addr.s_addr = ina.s_addr;
675 return (0);
676
677 case PF_INET6:
678 if (inet_pton(PF_INET6, str, &in6a) != 1)
679 return (-1);
680
681 sin6 = (struct sockaddr_in6 *)sa;
682 memset(sin6, 0, sizeof *sin6);
683 sin6->sin6_len = sizeof(struct sockaddr_in6);
684 sin6->sin6_family = PF_INET6;
685 sin6->sin6_addr = in6a;
686 return (0);
687
688 default:
689 break;
690 }
691
692 return (-1);
693 }
694