1 /* sar.h - srvx asynchronous resolver
2 * Copyright 2005, 2007 Michael Poole <mdpoole@troilus.org>
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 #if defined(HAVE_NETINET_IN_H)
28 # include <netinet/in.h> /* sockaddr_in6 on some BSDs */
31 static const char hexdigits[] = "0123456789abcdef";
34 struct sar_getaddr_state;
35 struct sar_getname_state;
37 struct sar_family_helper {
38 const char *localhost_addr;
39 const char *unspec_addr;
43 unsigned int (*ntop)(char *output, unsigned int out_size, const struct sockaddr *sa, unsigned int socklen);
44 unsigned int (*pton)(struct sockaddr *sa, unsigned int socklen, unsigned int *bits, const char *input);
45 int (*get_port)(const struct sockaddr *sa, unsigned int socklen);
46 int (*set_port)(struct sockaddr *sa, unsigned int socklen, unsigned short port);
47 unsigned int (*build_addr_request)(struct sar_request *req, const char *node, const char *srv_node, unsigned int flags);
48 void (*build_ptr_name)(struct sar_getname_state *state, const struct sockaddr *sa, unsigned int socklen);
49 int (*decode_addr)(struct sar_getaddr_state *state, struct dns_rr *rr, unsigned char *raw, unsigned int raw_size);
51 struct sar_family_helper *next;
54 #define MAX_FAMILY AF_INET
55 static struct sar_family_helper sar_ipv4_helper;
58 # if AF_INET6 > MAX_FAMILY
60 # define MAX_FAMILY AF_INET6
62 static struct sar_family_helper sar_ipv6_helper;
65 static struct sar_family_helper *sar_helpers[MAX_FAMILY+1];
66 static struct sar_family_helper *sar_first_helper;
69 sar_ntop(char *output, unsigned int out_size, const struct sockaddr *sa, unsigned int socklen)
72 assert(output != NULL);
76 if (sa->sa_family <= MAX_FAMILY && sar_helpers[sa->sa_family]) {
77 pos = sar_helpers[sa->sa_family]->ntop(output, out_size, sa, socklen);
86 sar_pton(struct sockaddr *sa, unsigned int socklen, unsigned int *bits, const char *input)
88 struct sar_family_helper *helper;
92 assert(input != NULL);
94 memset(sa, 0, socklen);
97 for (helper = sar_first_helper; helper; helper = helper->next) {
98 if (socklen < helper->socklen)
100 len = helper->pton(sa, socklen, bits, input);
102 sa->sa_family = helper->family;
106 return 0; /* parse failed */
110 sar_get_port(const struct sockaddr *sa, unsigned int socklen)
112 if (sa->sa_family <= MAX_FAMILY
113 && sar_helpers[sa->sa_family]
114 && socklen >= sar_helpers[sa->sa_family]->socklen)
115 return sar_helpers[sa->sa_family]->get_port(sa, socklen);
120 sar_set_port(struct sockaddr *sa, unsigned int socklen, unsigned short port)
122 if (sa->sa_family <= MAX_FAMILY
123 && sar_helpers[sa->sa_family]
124 && socklen >= sar_helpers[sa->sa_family]->socklen)
125 return sar_helpers[sa->sa_family]->set_port(sa, socklen, port);
130 sar_strerror(enum sar_errcode errcode)
133 case SAI_SUCCESS: return "Resolution succeeded.";
134 case SAI_FAMILY: return "The requested address family is not supported.";
135 case SAI_SOCKTYPE: return "The requested socket type is not supported.";
136 case SAI_BADFLAGS: return "Invalid flags value.";
137 case SAI_NONAME: return "Unknown name or service.";
138 case SAI_SERVICE: return "The service is unavailable for that socket type.";
139 case SAI_ADDRFAMILY: return "The host has no address in the requested family.";
140 case SAI_NODATA: return "The host has no addresses at all.";
141 case SAI_MEMORY: return "Unable to allocate memory.";
142 case SAI_FAIL: return "The nameserver indicated a permanent error.";
143 case SAI_AGAIN: return "The nameserver indicated a temporary error.";
144 case SAI_MISMATCH: return "Mismatch between reverse and forward resolution.";
145 case SAI_SYSTEM: return strerror(errno);
146 default: return "Unknown resolver error code.";
151 sar_free(struct addrinfo *ai)
153 struct addrinfo *next;
154 for (; ai; ai = next) {
160 /** Global variables to support DNS name resolution. */
162 unsigned int sar_timeout;
163 unsigned int sar_retries;
164 unsigned int sar_ndots;
165 unsigned int sar_edns0;
166 char sar_localdomain[MAXLEN];
167 struct string_list *sar_search;
168 struct string_list *sar_nslist;
169 struct sockaddr_storage sar_bind_address;
171 static struct log_type *sar_log;
173 /* Except as otherwise noted, constants and formats are from RFC1035.
174 * This resolver is believed to implement the behaviors mandated (and
175 * in many cases those recommended) by these standards: RFC1035,
176 * RFC2671, RFC2782, RFC3596, RFC3597.
178 * Update queries (including RFC 2136) seems a likely candidate for
180 * DNSSEC (including RFCs 2535, 3007, 3655, etc) is less likely until
181 * a good application is found.
182 * Caching (RFC 2308) and redirection (RFC 2672) are much less likely,
183 * since most users will have a separate local, caching, recursive
185 * Other DNS extensions (at least through RFC 3755) are believed to be
186 * too rare or insufficiently useful to bother supporting.
188 * The following are useful Reasons For Concern:
189 * RFC1536, RFC1912, RFC2606, RFC3363, RFC3425, RFC3467
190 * http://www.iana.org/assignments/dns-parameters
191 * http://www.ietf.org/html.charters/dnsext-charter.html
194 struct sar_nameserver {
197 unsigned int req_sent;
198 unsigned int resp_used;
199 unsigned int resp_ignored;
200 unsigned int resp_servfail;
201 unsigned int resp_fallback;
202 unsigned int resp_failures;
203 unsigned int resp_scrambled;
205 struct sockaddr_storage ss;
208 /* EDNS0 uses 12 bit RCODEs, TSIG/TKEY use 16 bit RCODEs.
209 * Declare local RCODE failures here.*/
211 RCODE_TIMED_OUT = 65536,
212 RCODE_QUERY_TOO_LONG,
213 RCODE_LABEL_TOO_LONG,
214 RCODE_SOCKET_FAILURE,
218 #define DNS_NAME_LENGTH 256
220 #define RES_SIZE_FLAGS 0xc0
221 #define RES_SF_LABEL 0x00
222 #define RES_SF_POINTER 0xc0
224 static dict_t sar_requests;
225 static dict_t sar_nameservers;
226 static struct io_fd *sar_fd;
227 static int sar_fd_fd;
230 sar_rcode_text(unsigned int rcode)
233 case RCODE_NO_ERROR: return "No error";
234 case RCODE_FORMAT_ERROR: return "Format error";
235 case RCODE_SERVER_FAILURE: return "Server failure";
236 case RCODE_NAME_ERROR: return "Name error";
237 case RCODE_NOT_IMPLEMENTED: return "Feature not implemented";
238 case RCODE_REFUSED: return "Query refused";
239 case RCODE_BAD_OPT_VERSION: return "Unsupported EDNS option version";
240 case RCODE_TIMED_OUT: return "Request timed out";
241 case RCODE_QUERY_TOO_LONG: return "Query too long";
242 case RCODE_LABEL_TOO_LONG: return "Label too long";
243 case RCODE_SOCKET_FAILURE: return "Resolver socket failure";
244 case RCODE_DESTROYED: return "Request unexpectedly destroyed";
245 default: return "Unknown rcode";
250 sar_request_fail(struct sar_request *req, unsigned int rcode)
252 log_module(sar_log, LOG_DEBUG, "sar_request_fail({id=%d}, rcode=%d)", req->id, rcode);
255 req->cb_fail(req, rcode);
259 sar_request_abort(req);
262 static time_t next_sar_timeout;
265 sar_timeout_cb(void *data)
268 dict_iterator_t next;
269 time_t next_timeout = INT_MAX;
271 for (it = dict_first(sar_requests); it; it = next) {
272 struct sar_request *req;
275 next = iter_next(it);
276 if (req->expiry > next_timeout)
278 else if (req->expiry > now)
279 next_timeout = req->expiry;
280 else if (req->retries >= conf.sar_retries)
281 sar_request_fail(req, RCODE_TIMED_OUT);
283 sar_request_send(req);
285 if (next_timeout < INT_MAX) {
286 next_sar_timeout = next_timeout;
287 timeq_add(next_timeout, sar_timeout_cb, data);
292 sar_check_timeout(time_t when)
294 if (!next_sar_timeout || when < next_sar_timeout) {
295 timeq_del(0, sar_timeout_cb, NULL, TIMEQ_IGNORE_WHEN | TIMEQ_IGNORE_DATA);
296 timeq_add(when, sar_timeout_cb, NULL);
297 next_sar_timeout = when;
302 sar_request_cleanup(void *d)
304 struct sar_request *req = d;
305 log_module(sar_log, LOG_DEBUG, "sar_request_cleanup({id=%d})", req->id);
308 req->cb_fail(req, RCODE_DESTROYED);
313 sar_dns_init(const char *resolv_conf_path)
315 struct string_list *ns_sv;
316 struct string_list *ds_sv;
321 /* Initialize configuration defaults. */
322 conf.sar_localdomain[0] = '\0';
323 conf.sar_timeout = 3;
324 conf.sar_retries = 3;
327 ns_sv = alloc_string_list(4);
328 ds_sv = alloc_string_list(4);
330 /* Scan resolver configuration file. */
331 resolv_conf = fopen(resolv_conf_path, "r");
335 char linebuf[LINE_MAX], ch;
337 while (fgets(linebuf, sizeof(linebuf), resolv_conf)) {
338 ch = linebuf[len = strcspn(linebuf, " \t\r\n")];
340 arg = linebuf + len + 1;
341 if (!strcmp(linebuf, "nameserver")) {
343 ch = arg[len = strcspn(arg, " \t\r\n")];
345 string_list_append(ns_sv, strdup(arg));
348 } else if (!strcmp(linebuf, "domain")) {
350 safestrncpy(conf.sar_localdomain, arg, sizeof(conf.sar_localdomain));
352 } else if (!strcmp(linebuf, "search")) {
354 ch = arg[len = strcspn(arg, " \t\r\n")];
356 string_list_append(ds_sv, strdup(arg));
359 } else if (!strcmp(linebuf, "options")) {
361 ch = arg[len = strcspn(arg, " \t\r\n")];
363 opt = strchr(arg, ':');
366 if (!strcmp(arg, "timeout")) {
367 conf.sar_timeout = atoi(opt);
368 } else if (!strcmp(arg, "attempts")) {
369 conf.sar_retries = atoi(opt);
370 } else if (!strcmp(arg, "ndots")) {
371 conf.sar_ndots = atoi(opt);
372 } else if (!strcmp(arg, "edns0")) {
373 conf.sar_edns0 = atoi(opt);
375 } else if (!strcmp(arg, "edns0")) {
376 conf.sar_edns0 = 1440;
384 /* This is apparently what BIND defaults to using. */
385 string_list_append(ns_sv, "127.0.0.1");
388 /* Set default search path if domain is set. */
389 if (conf.sar_localdomain[0] != '\0' && ds_sv->used == 0)
390 string_list_append(ds_sv, strdup(conf.sar_localdomain));
392 /* Check configuration entries that might override resolv.conf. */
393 node = conf_get_data("modules/sar", RECDB_OBJECT);
396 struct string_list *slist;
398 str = database_get_data(node, "timeout", RECDB_QSTRING);
399 if (str) conf.sar_timeout = ParseInterval(str);
400 str = database_get_data(node, "retries", RECDB_QSTRING);
401 if (str) conf.sar_retries = atoi(str);
402 str = database_get_data(node, "ndots", RECDB_QSTRING);
403 if (str) conf.sar_ndots = atoi(str);
404 str = database_get_data(node, "edns0", RECDB_QSTRING);
405 if (str) conf.sar_edns0 = enabled_string(str);
406 str = database_get_data(node, "domain", RECDB_QSTRING);
407 if (str) safestrncpy(conf.sar_localdomain, str, sizeof(conf.sar_localdomain));
408 slist = database_get_data(node, "search", RECDB_STRING_LIST);
410 free_string_list(ds_sv);
411 ds_sv = string_list_copy(slist);
413 slist = database_get_data(node, "nameservers", RECDB_STRING_LIST);
415 free_string_list(ns_sv);
416 ns_sv = string_list_copy(slist);
418 sa = (struct sockaddr*)&conf.sar_bind_address;
419 memset(sa, 0, sizeof(conf.sar_bind_address));
420 str = database_get_data(node, "bind_address", RECDB_QSTRING);
421 if (str) sar_pton(sa, sizeof(conf.sar_bind_address), NULL, str);
422 str = database_get_data(node, "bind_port", RECDB_QSTRING);
424 if (sa->sa_family == AF_INET) {
425 struct sockaddr_in *sin = (struct sockaddr_in*)sa;
426 sin->sin_port = ntohs(atoi(str));
428 #if defined(AF_INET6)
429 else if (sa->sa_family == AF_INET6) {
430 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)sa;
431 sin6->sin6_port = ntohs(atoi(str));
437 /* Replace config lists with their new values. */
438 free_string_list(conf.sar_search);
439 conf.sar_search = ds_sv;
440 free_string_list(conf.sar_nslist);
441 conf.sar_nslist = ns_sv;
445 sar_request_abort(struct sar_request *req)
449 assert(dict_find(sar_requests, req->id_text, NULL) == req);
450 log_module(sar_log, LOG_DEBUG, "sar_request_abort({id=%d})", req->id);
453 dict_remove(sar_requests, req->id_text);
456 static struct sar_nameserver *
457 sar_our_server(const struct sockaddr_storage *ss, unsigned int ss_len)
461 for (it = dict_first(sar_nameservers); it; it = iter_next(it)) {
462 struct sar_nameserver *ns;
465 if (ns->ss_len == ss_len && !memcmp(ss, &ns->ss, ss_len))
472 sar_extract_name(const unsigned char *buf, unsigned int size, unsigned int *ppos)
474 struct string_buffer cv;
475 unsigned int pos, jumped;
481 cv.list = calloc(1, cv.size);
489 cv.list[cv.used - 1] = '\0'; /* chop off terminating '.' */
491 string_buffer_append(&cv, '\0');
494 switch (buf[pos] & RES_SIZE_FLAGS) {
496 unsigned int len = buf[pos];
497 if (pos + len + 1 >= size)
499 string_buffer_append_substring(&cv, (char*)buf + pos + 1, len);
500 string_buffer_append(&cv, '.');
505 if ((pos + 1 >= size) || (cv.used >= size))
509 pos = (buf[pos] & ~RES_SIZE_FLAGS) << 8 | buf[pos+1];
522 sar_decode_answer(struct sar_request *req, struct dns_header *hdr, unsigned char *buf, unsigned int size)
525 unsigned int ii, rr_count, pos;
528 /* Skip over query section. */
529 for (ii = 0, pos = 12; ii < hdr->qdcount; ++ii) {
530 /* Skip over compressed names. */
536 switch (buf[pos] & RES_SIZE_FLAGS) {
543 pos = (buf[pos] & ~RES_SIZE_FLAGS) << 8 | buf[pos+1];
551 /* Skip over null terminator, type and class part of question. */
555 /* Parse each RR in the answer. */
556 rr_count = hdr->ancount + hdr->nscount + hdr->arcount;
557 rr = calloc(1, rr_count * sizeof(rr[0]));
558 for (ii = 0; ii < rr_count; ++ii) {
559 rr[ii].name = sar_extract_name(buf, size, &pos);
564 if (pos + 10 > size) {
568 rr[ii].type = buf[pos+0] << 8 | buf[pos+1];
569 rr[ii].class = buf[pos+2] << 8 | buf[pos+3];
570 rr[ii].ttl = buf[pos+4] << 24 | buf[pos+5] << 16 | buf[pos+6] << 8 | buf[pos+7];
571 rr[ii].rdlength = buf[pos+8] << 8 | buf[pos+9];
572 rr[ii].rd_start = pos + 10;
573 pos = pos + rr[ii].rdlength + 10;
581 req->cb_ok(req, hdr, rr, buf, size);
585 dict_remove(sar_requests, req->id_text);
595 static const unsigned char *
596 sar_extract_rdata(struct dns_rr *rr, unsigned int len, unsigned char *raw, unsigned int raw_size)
598 if (len > rr->rdlength)
600 if (rr->rd_start + len > raw_size)
602 return raw + rr->rd_start;
606 sar_fd_readable(struct io_fd *fd)
608 struct sockaddr_storage ss;
609 struct dns_header hdr;
610 struct sar_nameserver *ns;
611 struct sar_request *req;
614 int res, rcode, buf_len;
617 assert(sar_fd == fd);
618 buf_len = conf.sar_edns0;
621 buf = alloca(buf_len);
623 res = recvfrom(sar_fd_fd, buf, buf_len, 0, (struct sockaddr*)&ss, &ss_len);
624 if (res < 12 || !(ns = sar_our_server(&ss, ss_len)))
626 hdr.id = buf[0] << 8 | buf[1];
627 hdr.flags = buf[2] << 8 | buf[3];
628 hdr.qdcount = buf[4] << 8 | buf[5];
629 hdr.ancount = buf[6] << 8 | buf[7];
630 hdr.nscount = buf[8] << 8 | buf[9];
631 hdr.arcount = buf[10] << 8 | buf[11];
633 sprintf(id_text, "%d", hdr.id);
634 req = dict_find(sar_requests, id_text, NULL);
635 log_module(sar_log, LOG_DEBUG, "sar_fd_readable(%p): hdr {id=%d, flags=0x%x, qdcount=%d, ancount=%d, nscount=%d, arcount=%d} -> req %p", fd, hdr.id, hdr.flags, hdr.qdcount, hdr.ancount, hdr.nscount, hdr.arcount, req);
636 if (!req || !req->retries || !(hdr.flags & REQ_FLAG_QR)) {
640 rcode = hdr.flags & REQ_FLAG_RCODE_MASK;
641 if (rcode != RCODE_NO_ERROR) {
642 sar_request_fail(req, rcode);
643 } else if (sar_decode_answer(req, &hdr, (unsigned char*)buf, res)) {
644 ns->resp_scrambled++;
645 sar_request_fail(req, RCODE_FORMAT_ERROR);
650 sar_build_nslist(struct string_list *nslist)
652 dict_iterator_t it, next;
653 struct sar_nameserver *ns;
656 for (it = dict_first(sar_nameservers); it; it = iter_next(it)) {
661 for (ii = 0; ii < nslist->used; ++ii) {
664 name = nslist->list[ii];
665 ns = dict_find(sar_nameservers, name, NULL);
667 ns = calloc(1, sizeof(*ns) + strlen(name) + 1);
668 ns->name = (char*)(ns + 1);
669 strcpy(ns->name, name);
670 ns->ss_len = sizeof(ns->ss);
671 if (!sar_pton((struct sockaddr*)&ns->ss, sizeof(ns->ss), NULL, name)) {
675 sar_set_port((struct sockaddr*)&ns->ss, sizeof(ns->ss), 53);
676 ns->ss_len = sar_helpers[ns->ss.ss_family]->socklen;
677 dict_insert(sar_nameservers, ns->name, ns);
682 for (it = dict_first(sar_nameservers); it; it = next) {
683 next = iter_next(it);
686 dict_remove(sar_nameservers, ns->name);
695 /* Build list of nameservers. */
696 sar_build_nslist(conf.sar_nslist);
698 if (conf.sar_bind_address.ss_family != 0) {
701 ai = (struct addrinfo*)&conf.sar_bind_address;
702 sar_fd_fd = socket(ai->ai_family, SOCK_DGRAM, 0);
704 log_module(sar_log, LOG_FATAL, "Unable to create resolver socket: %s", strerror(errno));
708 res = bind(sar_fd_fd, ai->ai_addr, ai->ai_addrlen);
710 log_module(sar_log, LOG_ERROR, "Unable to bind resolver socket to address [%s]:%s: %s", (char*)conf_get_data("modules/sar/bind_address", RECDB_QSTRING), (char*)conf_get_data("modules/sar/bind_port", RECDB_QSTRING), strerror(errno));
713 struct sar_nameserver *ns;
715 it = dict_first(sar_nameservers);
717 sar_fd_fd = socket(ns->ss.ss_family, SOCK_DGRAM, 0);
719 log_module(sar_log, LOG_FATAL, "Unable to create resolver socket: %s", strerror(errno));
724 sar_fd = ioset_add(sar_fd_fd);
726 log_module(sar_log, LOG_FATAL, "Unable to register resolver socket with event loop.");
729 sar_fd->state = IO_CONNECTED;
730 sar_fd->readable_cb = sar_fd_readable;
740 set_compare_charp(const void *a_, const void *b_)
742 char * const *a = a_, * const *b = b_;
743 return strcasecmp(*a, *b);
747 string_buffer_reserve(struct string_buffer *cv, unsigned int min_length)
749 if (cv->size < min_length) {
751 new_buffer = realloc(cv->list, min_length);
753 cv->size = min_length;
754 cv->list = new_buffer;
759 /** Append \a name to \a cv in compressed form. */
761 sar_append_name(struct string_buffer *cv, const char *name, struct name_ofs *ofs, unsigned int *used, unsigned int alloc)
763 struct name_ofs *pofs;
767 pofs = bsearch(&name, ofs, *used, sizeof(ofs[0]), set_compare_charp);
769 string_buffer_reserve(cv, cv->used + 2);
770 cv->list[cv->used++] = RES_SF_POINTER | (pofs->ofs >> 8);
771 cv->list[cv->used++] = pofs->ofs & 255;
774 len = strcspn(name, ".");
778 ofs[*used].name = name;
779 ofs[*used].ofs = cv->used;
780 qsort(ofs, (*used)++, sizeof(ofs[0]), set_compare_charp);
782 string_buffer_reserve(cv, cv->used + len + 1);
783 cv->list[cv->used] = RES_SF_LABEL | len;
784 memcpy(cv->list + cv->used + 1, name, len);
786 if (name[len] == '.')
788 else if (name[len] == '\0')
791 string_buffer_append(cv, '\0');
795 /** Build a DNS question packet from a variable-length argument list.
796 * In \a args, there is at least one pari consisting of const char
797 * *name and unsigned int qtype. A null name argument terminates the
801 sar_request_vbuild(struct sar_request *req, va_list args)
803 struct name_ofs suffixes[32];
804 struct string_buffer cv;
806 unsigned int suf_used;
808 unsigned int qdcount;
812 cv.list = calloc(1, cv.size);
814 val = REQ_OPCODE_QUERY | REQ_FLAG_RD;
815 cv.list[0] = req->id >> 8;
816 cv.list[1] = req->id & 255;
817 cv.list[2] = val >> 8;
818 cv.list[3] = val & 255;
819 cv.list[6] = cv.list[7] = cv.list[8] = cv.list[9] = cv.list[10] = 0;
821 for (qdcount = 0; (name = va_arg(args, const char*)); ++qdcount) {
822 if (sar_append_name(&cv, name, suffixes, &suf_used, ArrayLength(suffixes))) {
823 string_buffer_clean(&cv);
826 string_buffer_reserve(&cv, cv.used + 4);
827 val = va_arg(args, unsigned int);
828 cv.list[cv.used++] = val >> 8;
829 cv.list[cv.used++] = val & 255;
830 cv.list[cv.used++] = REQ_CLASS_IN >> 8;
831 cv.list[cv.used++] = REQ_CLASS_IN & 255;
833 cv.list[4] = qdcount >> 8;
834 cv.list[5] = qdcount & 255;
835 val = conf.sar_edns0;
837 string_buffer_reserve(&cv, cv.used + 11);
838 cv.list[cv.used + 0] = '\0'; /* empty name */
839 cv.list[cv.used + 1] = REQ_TYPE_OPT >> 8;
840 cv.list[cv.used + 2] = REQ_TYPE_OPT & 255;
841 cv.list[cv.used + 3] = val >> 8;
842 cv.list[cv.used + 4] = val & 255;
843 cv.list[cv.used + 5] = 0; /* extended-rcode */
844 cv.list[cv.used + 6] = 0; /* version */
845 cv.list[cv.used + 7] = 0; /* reserved */
846 cv.list[cv.used + 8] = 0; /* reserved */
847 cv.list[cv.used + 9] = 0; /* msb rdlen */
848 cv.list[cv.used + 10] = 0; /* lsb rdlen */
850 cv.list[11] = 1; /* update arcount */
851 } else cv.list[11] = 0;
855 req->body = (unsigned char*)cv.list;
856 req->body_len = cv.used;
860 /** Build a DNS question packet. After \a req, there is at least one
861 * pair consisting of const char *name and unsigned int qtype. A null
862 * name argument terminates the list.
865 sar_request_build(struct sar_request *req, ...)
869 va_start(vargs, req);
870 ret = sar_request_vbuild(req, vargs);
876 sar_request_send(struct sar_request *req)
880 /* make sure we have our local socket */
881 if (!sar_fd && sar_open_fd()) {
882 sar_request_fail(req, RCODE_SOCKET_FAILURE);
886 log_module(sar_log, LOG_DEBUG, "sar_request_send({id=%d})", req->id);
888 /* send query to each configured nameserver */
889 for (it = dict_first(sar_nameservers); it; it = iter_next(it)) {
890 struct sar_nameserver *ns;
894 res = sendto(sar_fd_fd, req->body, req->body_len, 0, (struct sockaddr*)&ns->ss, ns->ss_len);
897 log_module(sar_log, LOG_DEBUG, "Sent %u bytes to %s.", res, ns->name);
899 log_module(sar_log, LOG_ERROR, "Unable to send %u bytes to nameserver %s: %s", req->body_len, ns->name, strerror(errno));
901 assert(0 && "resolver sendto() unexpectedly returned zero");
904 /* Check that query timeout is soon enough. */
905 req->expiry = now + (conf.sar_timeout << ++req->retries);
906 sar_check_timeout(req->expiry);
910 sar_request_alloc(unsigned int data_len, sar_request_ok_cb ok_cb, sar_request_fail_cb fail_cb)
912 struct sar_request *req;
914 req = calloc(1, sizeof(*req) + data_len);
916 req->cb_fail = fail_cb;
918 req->id = rand() & 0xffff;
919 sprintf(req->id_text, "%d", req->id);
920 } while (dict_find(sar_requests, req->id_text, NULL));
921 dict_insert(sar_requests, req->id_text, req);
922 log_module(sar_log, LOG_DEBUG, "sar_request_alloc(%d) -> {id=%d}", data_len, req->id);
927 sar_request_simple(unsigned int data_len, sar_request_ok_cb ok_cb, sar_request_fail_cb fail_cb, ...)
929 struct sar_request *req;
931 req = sar_request_alloc(data_len, ok_cb, fail_cb);
935 va_start(args, fail_cb);
936 sar_request_vbuild(req, args);
938 sar_request_send(req);
949 struct service_byname {
950 const char *name; /* service name */
952 /* note: if valid != 0, port == 0, check canonical entry */
953 struct service_byname *canon; /* if NULL, this is canonical */
955 unsigned int valid : 1;
956 unsigned int srv : 1;
957 } protos[SERVICE_NUM_PROTOS];
960 struct service_byport {
963 struct service_byname *byname[SERVICE_NUM_PROTOS];
966 static dict_t services_byname; /* contains struct service_byname */
967 static dict_t services_byport; /* contains struct service_byport */
969 static struct service_byname *
970 sar_service_byname(const char *name, int autocreate)
972 struct service_byname *byname;
974 byname = dict_find(services_byname, name, NULL);
975 if (!byname && autocreate) {
976 byname = calloc(1, sizeof(*byname) + strlen(name) + 1);
977 byname->name = strcpy((char*)(byname + 1), name);
978 dict_insert(services_byname, byname->name, byname);
983 static struct service_byport *
984 sar_service_byport(unsigned int port, int autocreate)
986 struct service_byport *byport;
989 sprintf(port_text, "%d", port);
990 byport = dict_find(services_byport, port_text, NULL);
991 if (!byport && autocreate) {
992 byport = calloc(1, sizeof(*byport));
994 sprintf(byport->port_text, "%d", port);
995 dict_insert(services_byport, byport->port_text, byport);
1001 sar_services_load_file(const char *etc_services)
1003 static const char *whitespace = " \t\r\n";
1004 struct service_byname *canon;
1005 struct service_byport *byport;
1006 char *name, *port, *alias, *ptr;
1009 enum service_proto proto;
1010 char linebuf[LINE_MAX];
1012 file = fopen(etc_services, "r");
1015 while (fgets(linebuf, sizeof(linebuf), file)) {
1016 ptr = strchr(linebuf, '#');
1019 /* Tokenize canonical service name and port number. */
1020 name = strtok_r(linebuf, whitespace, &ptr);
1023 port = strtok_r(NULL, whitespace, &ptr);
1026 pnum = strtoul(port, &port, 10);
1027 if (pnum == 0 || *port++ != '/')
1029 if (!strcmp(port, "udp"))
1030 proto = SERVICE_UDP;
1031 else if (!strcmp(port, "tcp"))
1032 proto = SERVICE_TCP;
1035 /* Set up canonical name-indexed service entry. */
1036 canon = sar_service_byname(name, 1);
1037 if (canon->protos[proto].valid) {
1038 log_module(sar_log, LOG_ERROR, "Service %s/%s listed twice.", name, port);
1041 canon->protos[proto].canon = NULL;
1042 canon->protos[proto].port = pnum;
1043 canon->protos[proto].valid = 1;
1045 /* Set up port-indexed service entry. */
1046 byport = sar_service_byport(pnum, 1);
1047 if (!byport->byname[proto])
1048 byport->byname[proto] = canon;
1050 /* Add alias entries. */
1051 while ((alias = strtok_r(NULL, whitespace, &ptr))) {
1052 struct service_byname *byname;
1054 byname = sar_service_byname(alias, 1);
1055 if (byname->protos[proto].valid) {
1056 /* We do not log this since there are a lot of
1057 * duplicate aliases, some only differing in case. */
1060 byname->protos[proto].canon = canon;
1061 byname->protos[proto].port = pnum;
1062 byname->protos[proto].valid = 1;
1069 sar_services_init(const char *etc_services)
1071 /* These are a portion of the services listed at
1072 * http://www.dns-sd.org/ServiceTypes.html.
1074 static const char *tcp_srvs[] = { "cvspserver", "distcc", "ftp", "http",
1075 "imap", "ipp", "irc", "ldap", "login", "nfs", "pop3", "postgresql",
1076 "rsync", "sftp-ssh", "soap", "ssh", "telnet", "webdav", "xmpp-client",
1077 "xmpp-server", "xul-http", NULL };
1078 static const char *udp_srvs[] = { "bootps", "dns-update", "domain", "nfs",
1079 "ntp", "tftp", NULL };
1080 struct service_byname *byname;
1083 sar_services_load_file(etc_services);
1085 for (ii = 0; tcp_srvs[ii]; ++ii) {
1086 byname = sar_service_byname(tcp_srvs[ii], 1);
1087 byname->protos[SERVICE_TCP].srv = 1;
1090 for (ii = 0; udp_srvs[ii]; ++ii) {
1091 byname = sar_service_byname(udp_srvs[ii], 1);
1092 byname->protos[SERVICE_UDP].srv = 1;
1097 sar_register_helper(struct sar_family_helper *helper)
1099 assert(helper->family <= MAX_FAMILY);
1100 sar_helpers[helper->family] = helper;
1101 helper->next = sar_first_helper;
1102 sar_first_helper = helper;
1106 sar_addrlen(const struct sockaddr *sa, UNUSED_ARG(unsigned int size))
1108 return sa->sa_family <= MAX_FAMILY && sar_helpers[sa->sa_family]
1109 ? sar_helpers[sa->sa_family]->socklen : 0;
1112 struct sar_getaddr_state {
1113 struct sar_family_helper *helper;
1114 struct addrinfo *ai_head;
1115 struct addrinfo *ai_tail;
1118 unsigned int search_pos;
1119 unsigned int flags, socktype, protocol, port;
1120 unsigned int srv_ofs;
1121 char full_name[DNS_NAME_LENGTH];
1125 sar_getaddr_append(struct sar_getaddr_state *state, struct addrinfo *ai, int copy)
1129 log_module(sar_log, LOG_DEBUG, "sar_getaddr_append({full_name=%s}, ai=%p, copy=%d)", state->full_name, ai, copy);
1131 /* Set the appropriate pointer to the new element(s). */
1133 state->ai_tail->ai_next = ai;
1135 state->ai_head = ai;
1137 /* Find the end of the list. */
1139 /* Make sure we copy fields for both the first and last entries. */
1142 if (!ai->ai_addrlen) {
1143 assert(sar_helpers[ai->ai_family]);
1144 ai->ai_addrlen = sar_helpers[ai->ai_family]->socklen;
1146 #if defined(HAVE_SOCKADDR_SA_LEN)
1147 ai->ai_addr->sa_len = ai->ai_addrlen;
1149 ai->ai_addr->sa_family = ai->ai_family;
1150 ai->ai_socktype = state->socktype;
1151 ai->ai_protocol = state->protocol;
1158 for (count = 1; ai->ai_next; ++count, ai = ai->ai_next)
1162 /* Set the tail pointer and return count of appended items. */
1163 state->ai_tail = ai;
1167 static struct sar_request *
1168 sar_getaddr_request(struct sar_request *req)
1170 struct sar_getaddr_state *state;
1172 char full_name[DNS_NAME_LENGTH];
1174 state = (struct sar_getaddr_state*)(req + 1);
1176 /* If we can and should, append the current search domain. */
1177 if (state->search_pos < conf.sar_search->used)
1178 snprintf(full_name, sizeof(full_name), "%s.%s", state->full_name, conf.sar_search->list[state->search_pos]);
1179 else if (state->search_pos == conf.sar_search->used)
1180 safestrncpy(full_name, state->full_name, sizeof(full_name));
1182 log_module(sar_log, LOG_DEBUG, "sar_getaddr_request({id=%d}): failed", req->id);
1183 state->cb(state->cb_ctx, NULL, SAI_NONAME);
1187 /* Build the appropriate request for DNS record(s). */
1188 if (state->flags & SAI_ALL)
1189 len = sar_request_build(req, full_name + state->srv_ofs, REQ_QTYPE_ALL, NULL);
1190 else if (state->srv_ofs)
1191 len = state->helper->build_addr_request(req, full_name + state->srv_ofs, full_name, state->flags);
1193 len = state->helper->build_addr_request(req, full_name, NULL, state->flags);
1195 log_module(sar_log, LOG_DEBUG, "sar_getaddr_request({id=%d}): full_name=%s, srv_ofs=%d", req->id, full_name, state->srv_ofs);
1197 /* Check that the request could be built. */
1199 state->cb(state->cb_ctx, NULL, SAI_NODATA);
1203 /* Send the request. */
1204 sar_request_send(req);
1209 sar_getaddr_decode(struct sar_request *req, struct dns_header *hdr, struct dns_rr *rr, unsigned char *raw, unsigned int raw_size, unsigned int rr_idx)
1211 struct sar_getaddr_state *state;
1213 unsigned int jj, pos, hit;
1215 log_module(sar_log, LOG_DEBUG, " sar_getaddr_decode(id=%d, <hdr>, {type=%d, rdlength=%d, name=%s}, <data>, %u, <idx>)", hdr->id, rr[rr_idx].type, rr[rr_idx].rdlength, rr[rr_idx].name, raw_size);
1216 state = (struct sar_getaddr_state*)(req + 1);
1218 switch (rr[rr_idx].type) {
1220 if (state->flags & SAI_ALL)
1221 return sar_ipv4_helper.decode_addr(state, rr + rr_idx, raw, raw_size);
1222 #if defined(AF_INET6)
1223 else if (state->flags & SAI_V4MAPPED)
1224 return sar_ipv6_helper.decode_addr(state, rr + rr_idx, raw, raw_size);
1226 return state->helper->decode_addr(state, rr + rr_idx, raw, raw_size);
1229 #if defined(AF_INET6)
1230 if (state->flags & SAI_ALL)
1231 return sar_ipv6_helper.decode_addr(state, rr + rr_idx, raw, raw_size);
1232 return state->helper->decode_addr(state, rr + rr_idx, raw, raw_size);
1237 case REQ_TYPE_CNAME:
1238 /* there should be the canonical name next */
1239 pos = rr[rr_idx].rd_start;
1240 cname = sar_extract_name(raw, raw_size, &pos);
1242 return 0; /* XXX: eventually log the unhandled body */
1243 /* and it should correspond to some other answer in the response */
1244 for (jj = hit = 0; jj < hdr->ancount; ++jj) {
1245 if (strcasecmp(cname, rr[jj].name))
1247 hit += sar_getaddr_decode(req, hdr, rr, raw, raw_size, jj);
1249 /* XXX: if (!hit) handle or log the incomplete recursion; */
1253 /* TODO: decode the SRV record */
1261 sar_getaddr_ok(struct sar_request *req, struct dns_header *hdr, struct dns_rr *rr, unsigned char *raw, unsigned int raw_size)
1263 struct sar_getaddr_state *state;
1266 state = (struct sar_getaddr_state*)(req + 1);
1268 log_module(sar_log, LOG_DEBUG, "sar_getaddr_ok({id=%d}, {id=%d}, <rr>, <data>, %u)", req->id, hdr->id, raw_size);
1269 for (ii = 0; ii < hdr->ancount; ++ii)
1270 sar_getaddr_decode(req, hdr, rr, raw, raw_size, ii);
1272 /* If we found anything, report it, else try again. */
1274 state->cb(state->cb_ctx, state->ai_head, SAI_SUCCESS);
1276 sar_getaddr_request(req);
1280 sar_getaddr_fail(struct sar_request *req, UNUSED_ARG(unsigned int rcode))
1282 struct sar_getaddr_state *state;
1284 log_module(sar_log, LOG_DEBUG, "sar_getaddr_fail({id=%d}, rcode=%u)", req->id, rcode);
1285 state = (struct sar_getaddr_state*)(req + 1);
1286 state->cb(state->cb_ctx, NULL, SAI_FAIL);
1289 struct sar_request *
1290 sar_getaddr(const char *node, const char *service, const struct addrinfo *hints_, sar_addr_cb cb, void *cb_ctx)
1292 struct sockaddr_storage ss;
1293 struct addrinfo hints;
1294 struct sar_family_helper *helper;
1295 struct service_byname *svc;
1297 unsigned int portnum;
1299 enum service_proto proto;
1301 if (!node && !service) {
1302 cb(cb_ctx, NULL, SAI_NONAME);
1306 /* Initialize local hints structure. */
1308 memcpy(&hints, hints_, sizeof(hints));
1310 memset(&hints, 0, sizeof(hints));
1312 /* Translate socket type to internal protocol. */
1313 switch (hints.ai_socktype) {
1314 case 0: hints.ai_socktype = SOCK_STREAM; /* and fall through */
1315 case SOCK_STREAM: proto = SERVICE_TCP; break;
1316 case SOCK_DGRAM: proto = SERVICE_UDP; break;
1318 cb(cb_ctx, NULL, SAI_SOCKTYPE);
1322 /* Figure out preferred socket size. */
1323 if (hints.ai_family == AF_UNSPEC)
1324 hints.ai_family = AF_INET;
1325 if (hints.ai_family > MAX_FAMILY
1326 || !(helper = sar_helpers[hints.ai_family])) {
1327 cb(cb_ctx, NULL, SAI_FAMILY);
1330 hints.ai_addrlen = helper->socklen;
1332 /* If \a node is NULL, figure out the correct default from the
1333 * requested family and SAI_PASSIVE flag.
1336 node = (hints.ai_flags & SAI_PASSIVE) ? helper->unspec_addr : helper->localhost_addr;
1338 /* Try to parse (failing that, look up) \a service. */
1340 portnum = 0, svc = NULL;
1341 else if ((portnum = strtoul(service, &end, 10)), *end == '\0')
1343 else if ((svc = sar_service_byname(service, 0)) != NULL)
1344 portnum = svc->protos[proto].port;
1346 cb(cb_ctx, NULL, SAI_SERVICE);
1350 /* Try to parse \a node as a numeric hostname.*/
1351 pos = sar_pton((struct sockaddr*)&ss, sizeof(ss), NULL, node);
1352 if (pos && node[pos] == '\0') {
1353 struct addrinfo *ai;
1354 char canonname[SAR_NTOP_MAX];
1356 /* we have a valid address; use it */
1357 sar_set_port((struct sockaddr*)&ss, sizeof(ss), portnum);
1358 hints.ai_addrlen = sar_addrlen((struct sockaddr*)&ss, sizeof(ss));
1359 if (!hints.ai_addrlen) {
1360 cb(cb_ctx, NULL, SAI_FAMILY);
1363 pos = sar_ntop(canonname, sizeof(canonname), (struct sockaddr*)&ss, hints.ai_addrlen);
1365 /* allocate and fill in the addrinfo response */
1366 ai = calloc(1, sizeof(*ai) + hints.ai_addrlen + pos + 1);
1367 ai->ai_family = ss.ss_family;
1368 ai->ai_socktype = hints.ai_socktype;
1369 ai->ai_protocol = hints.ai_protocol;
1370 ai->ai_addrlen = hints.ai_addrlen;
1371 ai->ai_addr = memcpy(ai + 1, &ss, ai->ai_addrlen);
1372 ai->ai_canonname = strcpy((char*)ai->ai_addr + ai->ai_addrlen, canonname);
1373 cb(cb_ctx, ai, SAI_SUCCESS);
1375 } else if (hints.ai_flags & SAI_NUMERICHOST) {
1376 cb(cb_ctx, NULL, SAI_NONAME);
1379 struct sar_request *req;
1380 struct sar_getaddr_state *state;
1381 unsigned int len, ii;
1383 req = sar_request_alloc(sizeof(*state), sar_getaddr_ok, sar_getaddr_fail);
1385 state = (struct sar_getaddr_state*)(req + 1);
1386 state->helper = helper;
1387 state->ai_head = state->ai_tail = NULL;
1389 state->cb_ctx = cb_ctx;
1390 state->flags = hints.ai_flags;
1391 state->socktype = hints.ai_socktype;
1392 state->protocol = hints.ai_protocol;
1393 state->port = portnum;
1395 if ((state->flags & SAI_NOSRV) || !svc)
1397 else if (svc->protos[proto].srv)
1398 state->srv_ofs = snprintf(state->full_name, sizeof(state->full_name), "_%s._%s.", svc->name, (proto == SERVICE_UDP ? "udp" : "tcp"));
1399 else if (state->flags & SAI_FORCESRV)
1400 state->srv_ofs = snprintf(state->full_name, sizeof(state->full_name), "_%s._%s.", service, (proto == SERVICE_UDP ? "udp" : "tcp"));
1404 if (state->srv_ofs < sizeof(state->full_name))
1405 safestrncpy(state->full_name + state->srv_ofs, node, sizeof(state->full_name) - state->srv_ofs);
1407 for (ii = len = 0; node[ii]; ++ii)
1408 if (node[ii] == '.')
1410 if (len >= conf.sar_ndots)
1411 state->search_pos = conf.sar_search->used;
1413 state->search_pos = 0;
1415 /* XXX: fill in *state with any other fields needed to parse responses. */
1417 if (!sar_getaddr_request(req)) {
1425 struct sar_getname_state {
1430 unsigned int family;
1431 enum service_proto proto;
1432 unsigned short port;
1433 unsigned int doing_arpa : 1; /* checking .ip6.arpa vs .ip6.int */
1434 unsigned char original[16]; /* original address data */
1435 /* name must be long enough to hold "0.0.<etc>.ip6.arpa" */
1440 sar_getname_fail(struct sar_request *req, UNUSED_ARG(unsigned int rcode))
1442 struct sar_getname_state *state;
1445 state = (struct sar_getname_state*)(req + 1);
1446 if (state->doing_arpa) {
1447 len = strlen(state->name);
1449 strcpy(state->name + len - 4, "int");
1450 len = sar_request_build(req, state->name, REQ_TYPE_PTR, NULL);
1452 sar_request_send(req);
1456 state->cb(state->cb_ctx, NULL, NULL, SAI_FAIL);
1457 free(state->hostname);
1460 static const char *sar_getname_port(unsigned int port, unsigned int flags, char *tmpbuf, unsigned int tmpbuf_len)
1462 struct service_byport *service;
1463 enum service_proto proto;
1466 sprintf(port_text, "%d", port);
1467 proto = (flags & SNI_DGRAM) ? SERVICE_UDP : SERVICE_TCP;
1468 if (!(flags & SNI_NUMERICSERV)
1469 && (service = dict_find(services_byport, port_text, NULL))
1470 && service->byname[proto])
1471 return service->byname[proto]->name;
1472 snprintf(tmpbuf, tmpbuf_len, "%d", port);
1477 sar_getname_confirm(struct sar_request *req, struct dns_header *hdr, struct dns_rr *rr, unsigned char *raw, unsigned int raw_size)
1479 struct sar_getname_state *state;
1480 const unsigned char *data;
1481 const char *portname;
1483 unsigned int ii, nbr;
1485 state = (struct sar_getname_state*)(req + 1);
1486 for (ii = 0; ii < hdr->ancount; ++ii) {
1487 /* Is somebody confused or trying to play games? */
1488 if (rr[ii].class != REQ_CLASS_IN
1489 || strcasecmp(state->hostname, rr[ii].name))
1491 switch (rr[ii].type) {
1492 case REQ_TYPE_A: nbr = 4; break;
1493 case REQ_TYPE_AAAA: nbr = 16; break;
1496 data = sar_extract_rdata(rr, nbr, raw, raw_size);
1497 if (data && !memcmp(data, state->original, nbr)) {
1498 portname = sar_getname_port(state->port, state->flags, servbuf, sizeof(servbuf));
1499 state->cb(state->cb_ctx, state->hostname, portname, SAI_SUCCESS);
1500 free(state->hostname);
1504 state->cb(state->cb_ctx, NULL, NULL, SAI_MISMATCH);
1505 free(state->hostname);
1509 sar_getname_ok(struct sar_request *req, struct dns_header *hdr, struct dns_rr *rr, unsigned char *raw, unsigned int raw_size)
1511 struct sar_getname_state *state;
1512 const char *portname;
1513 unsigned int ii, pos;
1516 state = (struct sar_getname_state*)(req + 1);
1517 for (ii = 0; ii < hdr->ancount; ++ii) {
1518 if (rr[ii].type != REQ_TYPE_PTR
1519 || rr[ii].class != REQ_CLASS_IN
1520 || strcasecmp(rr[ii].name, state->name))
1522 pos = rr[ii].rd_start;
1523 state->hostname = sar_extract_name(raw, raw_size, &pos);
1527 if (!state->hostname) {
1528 state->cb(state->cb_ctx, NULL, NULL, SAI_NONAME);
1532 if (state->flags & SNI_PARANOID) {
1533 req->cb_ok = sar_getname_confirm;
1534 pos = sar_helpers[state->family]->build_addr_request(req, state->hostname, NULL, 0);
1536 sar_request_send(req);
1538 free(state->hostname);
1539 state->cb(state->cb_ctx, NULL, NULL, SAI_FAIL);
1544 portname = sar_getname_port(state->port, state->flags, servbuf, sizeof(servbuf));
1545 state->cb(state->cb_ctx, state->hostname, portname, SAI_SUCCESS);
1546 free(state->hostname);
1549 struct sar_request *
1550 sar_getname(const struct sockaddr *sa, unsigned int salen, int flags, sar_name_cb cb, void *cb_ctx)
1552 struct sar_family_helper *helper;
1553 struct sar_request *req;
1554 struct sar_getname_state *state;
1558 if (sa->sa_family > MAX_FAMILY
1559 || !(helper = sar_helpers[sa->sa_family])) {
1560 cb(cb_ctx, NULL, NULL, SAI_FAMILY);
1564 port = helper->get_port(sa, salen);
1566 if (flags & SNI_NUMERICHOST) {
1567 const char *servname;
1569 char host[SAR_NTOP_MAX], servbuf[16];
1571 /* If appropriate, try to look up service name. */
1572 servname = sar_getname_port(port, flags, servbuf, sizeof(servbuf));
1573 len = sar_ntop(host, sizeof(host), sa, salen);
1575 cb(cb_ctx, host, servname, SAI_SUCCESS);
1579 req = sar_request_alloc(sizeof(*state), sar_getname_ok, sar_getname_fail);
1581 state = (struct sar_getname_state*)(req + 1);
1583 state->cb_ctx = cb_ctx;
1584 state->flags = flags;
1585 state->family = sa->sa_family;
1588 helper->build_ptr_name(state, sa, salen);
1589 assert(strlen(state->name) < sizeof(state->name));
1590 len = sar_request_build(req, state->name, REQ_TYPE_PTR, NULL);
1592 cb(cb_ctx, NULL, NULL, SAI_NODATA);
1597 sar_request_send(req);
1602 ipv4_ntop(char *output, unsigned int out_size, const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1604 struct sockaddr_in *sin;
1605 unsigned int ip4, pos;
1607 sin = (struct sockaddr_in*)sa;
1608 ip4 = ntohl(sin->sin_addr.s_addr);
1609 pos = snprintf(output, out_size, "%u.%u.%u.%u", (ip4 >> 24), (ip4 >> 16) & 255, (ip4 >> 8) & 255, ip4 & 255);
1610 return (pos < out_size) ? pos : 0;
1614 sar_pton_ip4(const char *input, unsigned int *bits, uint32_t *output)
1616 unsigned int dots = 0, pos = 0, part = 0, ip = 0;
1618 /* Intentionally no support for bizarre IPv4 formats (plain
1619 * integers, octal or hex components) -- only vanilla dotted
1620 * decimal quads, optionally with trailing /nn.
1622 if (input[0] == '.')
1625 if (isdigit(input[pos])) {
1626 part = part * 10 + input[pos++] - '0';
1629 if ((dots == 3) && !isdigit(input[pos])) {
1630 *output = htonl(ip | part);
1633 } else if (input[pos] == '.') {
1634 if (input[++pos] == '.')
1636 ip |= part << (24 - 8 * dots++);
1638 } else if (bits && input[pos] == '/' && isdigit(input[pos + 1])) {
1642 len = strtoul(input + pos + 1, &term, 10);
1643 if (term <= input + pos + 1)
1648 return term - input;
1654 ipv4_pton(struct sockaddr *sa, UNUSED_ARG(unsigned int socklen), unsigned int *bits, const char *input)
1658 pos = sar_pton_ip4(input, bits, &((struct sockaddr_in*)sa)->sin_addr.s_addr);
1661 sa->sa_family = AF_INET;
1666 ipv4_get_port(const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1668 return ntohs(((const struct sockaddr_in*)sa)->sin_port);
1672 ipv4_set_port(struct sockaddr *sa, UNUSED_ARG(unsigned int socklen), unsigned short port)
1674 ((struct sockaddr_in*)sa)->sin_port = htons(port);
1679 ipv4_addr_request(struct sar_request *req, const char *node, const char *srv_node, UNUSED_ARG(unsigned int flags))
1683 len = sar_request_build(req, node, REQ_TYPE_A, srv_node, REQ_TYPE_SRV, NULL);
1685 len = sar_request_build(req, node, REQ_TYPE_A, NULL);
1690 ipv4_ptr_name(struct sar_getname_state *state, const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1692 const uint8_t *bytes;
1694 bytes = (uint8_t*)&((struct sockaddr_in*)sa)->sin_addr.s_addr;
1695 memcpy(state->original, bytes, 4);
1696 snprintf(state->name, sizeof(state->name),
1697 "%u.%u.%u.%u.in-addr.arpa",
1698 bytes[3], bytes[2], bytes[1], bytes[0]);
1702 ipv4_decode(struct sar_getaddr_state *state, struct dns_rr *rr, unsigned char *raw, UNUSED_ARG(unsigned int raw_size))
1704 struct sockaddr_in *sa;
1705 struct addrinfo *ai;
1707 if (rr->rdlength != 4)
1710 if (state->flags & SAI_CANONNAME) {
1711 ai = calloc(1, sizeof(*ai) + sizeof(*sa) + strlen(rr->name) + 1);
1712 sa = (struct sockaddr_in*)(ai->ai_addr = (struct sockaddr*)(ai + 1));
1713 ai->ai_canonname = strcpy((char*)(sa + 1), rr->name);
1715 ai = calloc(1, sizeof(*ai) + sizeof(*sa));
1716 sa = (struct sockaddr_in*)(ai->ai_addr = (struct sockaddr*)(ai + 1));
1717 ai->ai_canonname = NULL;
1720 ai->ai_family = AF_INET;
1721 sa->sin_port = htons(state->port);
1722 memcpy(&sa->sin_addr.s_addr, raw + rr->rd_start, 4);
1723 return sar_getaddr_append(state, ai, 1);
1726 static struct sar_family_helper sar_ipv4_helper = {
1729 sizeof(struct sockaddr_in),
1741 #if defined(AF_INET6)
1744 ipv6_ntop(char *output, unsigned int out_size, const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1746 struct sockaddr_in6 *sin6;
1747 unsigned int pos, part, max_start, max_zeros, curr_zeros, ii;
1748 unsigned short addr16;
1750 sin6 = (struct sockaddr_in6*)sa;
1751 /* Find longest run of zeros. */
1752 for (max_start = max_zeros = curr_zeros = ii = 0; ii < 8; ++ii) {
1753 addr16 = (sin6->sin6_addr.s6_addr[ii * 2] << 8) | sin6->sin6_addr.s6_addr[ii * 2 + 1];
1756 else if (curr_zeros > max_zeros) {
1757 max_start = ii - curr_zeros;
1758 max_zeros = curr_zeros;
1762 if (curr_zeros > max_zeros) {
1763 max_start = ii - curr_zeros;
1764 max_zeros = curr_zeros;
1767 /* Print out address. */
1768 #define APPEND(CH) do { output[pos++] = (CH); if (pos >= out_size) return 0; } while (0)
1769 for (pos = 0, ii = 0; ii < 8; ++ii) {
1770 if ((max_zeros > 0) && (ii == max_start)) {
1774 ii += max_zeros - 1;
1777 part = (sin6->sin6_addr.s6_addr[ii * 2] << 8) | sin6->sin6_addr.s6_addr[ii * 2 + 1];
1779 APPEND(hexdigits[part >> 12]);
1781 APPEND(hexdigits[(part >> 8) & 15]);
1783 APPEND(hexdigits[(part >> 4) & 15]);
1784 APPEND(hexdigits[part & 15]);
1794 static const unsigned char xdigit_value[256] = {
1795 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1796 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1798 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
1799 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1800 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1801 0,10,11,12,13,14,15, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1805 ipv6_pton(struct sockaddr *sa, UNUSED_ARG(unsigned int socklen), unsigned int *bits, const char *input)
1807 const char *part_start = NULL;
1808 struct sockaddr_in6 *sin6;
1811 unsigned int part = 0, pos = 0, ii = 0, cpos = 8;
1813 if (!(colon = strchr(input, ':')))
1815 dot = strchr(input, '.');
1816 if (dot && dot < colon)
1818 sin6 = (struct sockaddr_in6*)sa;
1819 /* Parse IPv6, possibly like ::127.0.0.1.
1820 * This is pretty straightforward; the only trick is borrowed
1821 * from Paul Vixie (BIND): when it sees a "::" continue as if
1822 * it were a single ":", but note where it happened, and fill
1823 * with zeros afterwards.
1825 if (input[pos] == ':') {
1826 if ((input[pos+1] != ':') || (input[pos+2] == ':'))
1830 part_start = input + pos;
1833 if (isxdigit(input[pos])) {
1834 part = (part << 4) | xdigit_value[(unsigned char)input[pos]];
1838 } else if (input[pos] == ':') {
1839 part_start = input + ++pos;
1840 if (input[pos] == '.')
1842 sin6->sin6_addr.s6_addr[ii * 2] = part >> 8;
1843 sin6->sin6_addr.s6_addr[ii * 2 + 1] = part & 255;
1846 if (input[pos] == ':') {
1852 } else if (input[pos] == '.') {
1855 len = sar_pton_ip4(part_start, bits, &ip4);
1856 if (!len || (ii > 6))
1858 memcpy(sin6->sin6_addr.s6_addr + ii * 2, &ip4, sizeof(ip4));
1862 pos = part_start + len - input;
1864 } else if (bits && input[pos] == '/' && isdigit(input[pos + 1])) {
1868 len = strtoul(input + pos + 1, &term, 10);
1869 if (term <= input + pos + 1)
1877 } else if (cpos <= 8) {
1878 sin6->sin6_addr.s6_addr[ii * 2] = part >> 8;
1879 sin6->sin6_addr.s6_addr[ii * 2 + 1] = part & 255;
1884 /* Shift stuff after "::" up and fill middle with zeros. */
1889 for (jj = 0; jj < ii - cpos; jj++)
1890 sin6->sin6_addr.s6_addr[15 - jj] = sin6->sin6_addr.s6_addr[ii - jj - 1];
1891 for (jj = 0; jj < 16 - ii; jj++)
1892 sin6->sin6_addr.s6_addr[cpos + jj] = 0;
1894 sa->sa_family = AF_INET6;
1899 ipv6_get_port(const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1901 return ntohs(((const struct sockaddr_in6*)sa)->sin6_port);
1905 ipv6_set_port(struct sockaddr *sa, UNUSED_ARG(unsigned int socklen), unsigned short port)
1907 ((struct sockaddr_in6*)sa)->sin6_port = htons(port);
1912 ipv6_addr_request(struct sar_request *req, const char *node, const char *srv_node, unsigned int flags)
1915 if (flags & SAI_V4MAPPED) {
1917 len = sar_request_build(req, node, REQ_TYPE_AAAA, node, REQ_TYPE_A, srv_node, REQ_TYPE_SRV, NULL);
1919 len = sar_request_build(req, node, REQ_TYPE_AAAA, node, REQ_TYPE_A, NULL);
1922 len = sar_request_build(req, node, REQ_TYPE_AAAA, srv_node, REQ_TYPE_SRV, NULL);
1924 len = sar_request_build(req, node, REQ_TYPE_AAAA, NULL);
1930 ipv6_ptr_name(struct sar_getname_state *state, const struct sockaddr *sa, UNUSED_ARG(unsigned int socklen))
1932 const uint8_t *bytes;
1933 unsigned int ii, jj;
1935 bytes = ((struct sockaddr_in6*)sa)->sin6_addr.s6_addr;
1936 memcpy(state->original, bytes, 16);
1937 for (jj = 0, ii = 16; ii > 0; ) {
1938 state->name[jj++] = hexdigits[bytes[--ii] & 15];
1939 state->name[jj++] = hexdigits[bytes[ii] >> 4];
1940 state->name[jj++] = '.';
1942 strcpy(state->name + jj, ".ip6.arpa");
1943 state->doing_arpa = 1;
1947 ipv6_decode(struct sar_getaddr_state *state, struct dns_rr *rr, unsigned char *raw, UNUSED_ARG(unsigned int raw_size))
1949 struct sockaddr_in6 *sa;
1950 struct addrinfo *ai;
1952 if (state->flags & SAI_CANONNAME) {
1953 ai = calloc(1, sizeof(*ai) + sizeof(*sa) + strlen(rr->name) + 1);
1954 sa = (struct sockaddr_in6*)(ai->ai_addr = (struct sockaddr*)(ai + 1));
1955 ai->ai_canonname = strcpy((char*)(sa + 1), rr->name);
1957 ai = calloc(1, sizeof(*ai) + sizeof(*sa));
1958 sa = (struct sockaddr_in6*)(ai->ai_addr = (struct sockaddr*)(ai + 1));
1959 ai->ai_canonname = NULL;
1962 if (rr->rdlength == 4) {
1963 sa->sin6_addr.s6_addr[10] = sa->sin6_addr.s6_addr[11] = 0xff;
1964 memcpy(sa->sin6_addr.s6_addr + 12, raw + rr->rd_start, 4);
1965 } else if (rr->rdlength == 16) {
1966 memcpy(sa->sin6_addr.s6_addr, raw + rr->rd_start, 16);
1972 ai->ai_family = AF_INET6;
1973 sa->sin6_port = htons(state->port);
1974 return sar_getaddr_append(state, ai, 1);
1977 static struct sar_family_helper sar_ipv6_helper = {
1980 sizeof(struct sockaddr_in6),
1992 #endif /* defined(AF_INET6) */
1997 ioset_close(sar_fd, 1);
1998 dict_delete(services_byname);
1999 dict_delete(services_byport);
2000 dict_delete(sar_nameservers);
2001 dict_delete(sar_requests);
2005 sar_conf_reload(void)
2008 const char *resolv_conf = "/etc/resolv.conf";
2009 const char *services = "/etc/services";
2012 node = conf_get_data("modules/sar", RECDB_OBJECT);
2014 str = database_get_data(node, "resolv_conf", RECDB_QSTRING);
2015 if (str) resolv_conf = str;
2016 str = database_get_data(node, "services", RECDB_QSTRING);
2017 if (str) services = str;
2019 sar_dns_init(resolv_conf);
2020 sar_services_init(services);
2026 reg_exit_func(sar_cleanup);
2027 sar_log = log_register_type("sar", NULL);
2029 sar_requests = dict_new();
2030 dict_set_free_data(sar_requests, sar_request_cleanup);
2032 sar_nameservers = dict_new();
2033 dict_set_free_data(sar_nameservers, free);
2035 services_byname = dict_new();
2036 dict_set_free_data(services_byname, free);
2038 services_byport = dict_new();
2039 dict_set_free_data(services_byport, free);
2041 sar_register_helper(&sar_ipv4_helper);
2042 #if defined(AF_INET6)
2043 sar_register_helper(&sar_ipv6_helper);
2046 conf_register_reload(sar_conf_reload);