243 #define LIBDNS_INTERNAL
251 #define DEF_DNS_REPLY_SIZE 4096
252 #define MAX_DNS_REPLY_SIZE 65536
253 #define MAX_DNS_QUERY_SIZE 2048
273 #define TEST_HAVE_DNS_REPLY_PACKET(r) ((r)->end > (r)->buf)
274 #define SET_HAVE_DNS_REPLY_PACKET(r, l) ((r)->end = (r)->buf + (l))
275 #define SET_NO_DNS_REPLY_PACKET(r) ((r)->end = (r)->buf)
277 #define INET_ADDR_LEN 4
278 #define INET6_ADDR_LEN 16
311 static int dns_res_query(
const char *name,
int class,
int type,
312 unsigned char *answer,
int anslen)
315 HEADER *reply_header = (HEADER *) answer;
334 reply_header->rcode = NOERROR;
336 #define NO_MKQUERY_DATA_BUF ((unsigned char *) 0)
337 #define NO_MKQUERY_DATA_LEN ((int) 0)
338 #define NO_MKQUERY_NEWRR ((unsigned char *) 0)
342 msg_buf,
sizeof(msg_buf))) < 0) {
347 }
else if ((len = res_send(msg_buf, len, answer, anslen)) < 0) {
353 switch (reply_header->rcode) {
358 if (reply_header->ancount != 0)
376 static int dns_res_search(
const char *name,
int class,
int type,
377 unsigned char *answer,
int anslen,
int keep_notfound)
394 #define NOT_FOUND_H_ERRNO(he) ((he) == HOST_NOT_FOUND || (he) == NO_DATA)
398 memset(answer, 0, anslen);
399 len = res_query(name,
class, type, answer, anslen);
401 if (len < 0 && h_errno == 0) {
403 msg_warn(
"res_query(\"%s\", %d, %d, %p, %d) returns %d with h_errno==0"
404 " -- setting h_errno=TRY_AGAIN",
405 name,
class, type, answer, anslen, len);
419 static int dns_query(
const char *name,
int type,
unsigned flags,
422 HEADER *reply_header;
424 unsigned long saved_options;
430 if (reply->
buf == 0) {
438 if ((_res.options & RES_INIT) == 0 && res_init() < 0) {
448 #define USER_FLAGS (RES_DEBUG | RES_DNSRCH | RES_DEFNAMES | RES_USE_DNSSEC)
451 msg_panic(
"dns_query: bad flags: %d", flags);
456 #define XTRA_FLAGS (RES_USE_EDNS0)
465 #define SAVE_FLAGS (USER_FLAGS | XTRA_FLAGS)
474 _res.options &= ~saved_options;
475 _res.options |= flags;
477 len = dns_res_query((
char *) name, C_IN, type, reply->
buf,
480 len = dns_res_search((
char *) name, C_IN, type, reply->
buf,
481 reply->
buf_len, keep_notfound);
483 _res.options &= ~flags;
484 _res.options |= saved_options;
485 reply_header = (HEADER *) reply->
buf;
486 reply->
rcode = reply_header->rcode;
490 "Name service error for name=%s type=%s: %s",
514 reply->
buf = (
unsigned char *)
524 msg_panic(
"dns_query: bad length %d (h_errno=%s)",
531 msg_warn(
"reply length %d > buffer length %d for name=%s type=%s",
540 #if RES_USE_DNSSEC != 0
550 reply->
auth_count = ntohs(reply_header->nscount);
552 msg_info(
"dns_query: reply len=%d ancount=%d nscount=%d",
561 }
else if (keep_notfound) {
564 msg_panic(
"dns_query: unexpected reply status: %s",
571 static int dns_skip_query(
DNS_REPLY *reply)
581 while (query_count-- > 0) {
582 if (pos >= reply->
end)
584 len = dn_skipname(pos, reply->
end);
587 pos += len + QFIXEDSZ;
595 static int dns_get_fixed(
unsigned char *pos,
DNS_FIXED *fixed)
602 if (fixed->
class != C_IN) {
611 static int valid_rr_name(
const char *name,
const char *location,
626 #define REJECT_NAME 0
630 gripe =
"numeric domain name";
633 gripe =
"malformed domain name";
646 query_name = (len < 0 ?
"*unparsable*" : temp);
647 msg_warn(
"%s in %s of %s record for %s: %.100s",
648 gripe, location,
dns_strtype(type), query_name, name);
655 static int dns_get_rr(
DNS_RR **list,
const char *orig_name,
DNS_REPLY *reply,
656 unsigned char *pos,
char *rr_name,
660 char *tempbuf = temp;
669 #define MIN2(a, b) ((unsigned)(a) < (unsigned)(b) ? (a) : (b))
673 switch (fixed->
type) {
675 msg_panic(
"dns_get_rr: don't know how to extract resource type %s",
684 if (dn_expand(reply->
buf, reply->
end, pos, temp,
sizeof(temp)) < 0)
686 if (!valid_rr_name(temp,
"resource data", fixed->
type, reply))
688 data_len = strlen(temp) + 1;
692 if (dn_expand(reply->
buf, reply->
end, pos, temp,
sizeof(temp)) < 0)
697 if (!valid_rr_name(temp,
"resource data", fixed->
type, reply))
699 data_len = strlen(temp) + 1;
703 msg_warn(
"extract_answer: bad address length: %d", fixed->
length);
706 if (fixed->
length >
sizeof(temp))
707 msg_panic(
"dns_get_rr: length %d > DNS_NAME_LEN",
709 memcpy(temp, pos, fixed->
length);
715 msg_warn(
"extract_answer: bad address length: %d", fixed->
length);
718 if (fixed->
length >
sizeof(temp))
719 msg_panic(
"dns_get_rr: length %d > DNS_NAME_LEN",
721 memcpy(temp, pos, fixed->
length);
731 data_len =
MIN2(pos[0] + 1,
MIN2(fixed->
length + 1,
sizeof(temp)));
732 for (src = pos + 1, dst = (
unsigned char *) (temp);
733 dst < (
unsigned char *) (temp) + data_len - 1; ) {
735 *dst++ = (
ISPRINT(ch) ? ch :
' ');
752 tempbuf = (
char *) pos;
763 comp_len = dn_skipname(pos, reply->
end);
767 comp_len = dn_skipname(pos, reply->
end);
771 if (reply->
end - pos <
sizeof(soa_buf)) {
780 tempbuf = (
char *) soa_buf;
781 data_len =
sizeof(soa_buf);
785 fixed->
ttl, pref, tempbuf, data_len);
791 static int dns_get_alias(
DNS_REPLY *reply,
unsigned char *pos,
792 DNS_FIXED *fixed,
char *cname,
int c_len)
794 if (fixed->
type != T_CNAME)
796 if (dn_expand(reply->
buf, reply->
end, pos, cname, c_len) < 0)
798 if (!valid_rr_name(cname,
"resource data", fixed->
type, reply))
805 static int dns_get_answer(
const char *orig_name,
DNS_REPLY *reply,
int type,
815 int resource_found = 0;
824 if ((status = dns_skip_query(reply)) < 0)
832 #define CORRUPT(status) { \
833 if (rrlist && *rrlist) { \
834 dns_rr_free(*rrlist); \
843 while (answer_count-- > 0) {
848 if (pos >= reply->
end)
858 if (pos + RRFIXEDSZ > reply->
end)
860 if ((status = dns_get_fixed(pos, &fixed)) !=
DNS_OK)
862 if (!valid_rr_name(rr_name,
"resource name", fixed.
type, reply))
867 msg_info(
"dns_get_answer: type %s for %s",
876 if (type == fixed.
type || type == T_ANY) {
878 if ((status = dns_get_rr(&rr, orig_name, reply, pos, rr_name,
885 }
else if (not_found_status !=
DNS_RETRY)
886 not_found_status = status;
889 }
else if (fixed.
type == T_CNAME) {
891 if (cname && c_len > 0)
892 if ((status = dns_get_alias(reply, pos, &fixed, cname, c_len)) !=
DNS_OK)
909 return (not_found_status);
916 int *rcode,
unsigned lflags)
919 int c_len =
sizeof(cname);
923 int maybe_secure = 1;
924 const char *orig_name = name;
939 "Name service error for %s: invalid host or domain name",
953 "Name service error for %s: invalid host or domain name",
965 for (count = 0; count < 10; count++) {
970 status = dns_query(name, type, flags, &reply, why, lflags);
972 *rcode = reply.
rcode;
984 (void) dns_get_answer(orig_name, &reply, T_SOA, rrlist, fqdn,
985 cname, c_len, &maybe_secure);
994 status = dns_get_answer(orig_name, &reply, type, rrlist, fqdn,
995 cname, c_len, &maybe_secure);
1000 "Malformed or unexpected name server reply",
1014 "Error looking up name=%s type=%s: "
1015 "Invalid DNS reply filter syntax",
1020 }
else if (*rrlist == 0) {
1023 "Error looking up name=%s type=%s: "
1024 "DNS reply filter drops all results",
1032 msg_info(
"dns_lookup: %s aliased to %s", name, cname);
1040 if (maybe_secure == 0)
1041 flags &= ~RES_USE_DNSSEC;
1048 msg_warn(
"dns_lookup: Name server loop for %s", name);
1059 unsigned type, next;
1061 int hpref_status = INT_MIN;
1068 #define SAVE_HPREF_STATUS() do { \
1069 hpref_status = status; \
1071 hpref_rcode = *rcode; \
1072 if (why && status != DNS_OK) \
1073 vstring_strcpy(hpref_rtext ? hpref_rtext : \
1074 (hpref_rtext = vstring_alloc(VSTRING_LEN(why))), \
1075 vstring_str(why)); \
1076 hpref_h_errno = h_errno; \
1080 #define RESTORE_HPREF_STATUS() do { \
1081 status = hpref_status; \
1083 *rcode = hpref_rcode; \
1084 if (why && status != DNS_OK) \
1085 vstring_strcpy(why, vstring_str(hpref_rtext)); \
1086 SET_H_ERRNO(hpref_h_errno); \
1091 va_start(ap, lflags);
1092 for (type = va_arg(ap,
unsigned); type != 0; type = next) {
1093 next = va_arg(ap,
unsigned);
1095 msg_info(
"lookup %s type %s flags %s",
1098 fqdn, why, rcode, lflags);
1117 if (status >= hpref_status)
1121 if (status < hpref_status)
1132 int lflags,
unsigned *types)
1134 unsigned type, next;
1136 int hpref_status = INT_MIN;
1144 for (type = *types++; type != 0; type = next) {
1147 msg_info(
"lookup %s type %s flags %s",
1150 fqdn, why, rcode, lflags);
1169 if (status >= hpref_status)
1172 if (status < hpref_status)
#define DNS_REQ_FLAG_NCACHE_TTL
int valid_hostaddr(const char *addr, int gripe)
struct DNS_REPLY DNS_REPLY
const char * dns_strtype(unsigned)
#define RESTORE_HPREF_STATUS()
const char * dns_str_resflags(unsigned long)
NORETURN msg_panic(const char *fmt,...)
void * myrealloc(void *ptr, ssize_t len)
#define MAX_DNS_REPLY_SIZE
#define DEF_DNS_REPLY_SIZE
int dns_lookup_rl(const char *name, unsigned flags, DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why, int *rcode, int lflags,...)
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
#define SET_HAVE_DNS_REPLY_PACKET(r, l)
DNS_RR * dns_rr_create(const char *, const char *, ushort, ushort, unsigned, unsigned, const char *, size_t)
int valid_hostname(const char *name, int gripe)
const char * dns_strerror(unsigned)
#define TEST_HAVE_DNS_REPLY_PACKET(r)
MAPS * dns_rr_filter_maps
#define NO_MKQUERY_DATA_BUF
#define DNS_REQ_FLAG_STOP_OK
void msg_warn(const char *fmt,...)
#define SET_NO_DNS_REPLY_PACKET(r)
#define NO_MKQUERY_DATA_LEN
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
#define NOT_FOUND_H_ERRNO(he)
DNS_RR * dns_rr_append(DNS_RR *, DNS_RR *)
#define SAVE_HPREF_STATUS()
int dns_lookup_rv(const char *name, unsigned flags, DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why, int *rcode, int lflags, unsigned *types)
#define DNS_REQ_FLAG_STOP_INVAL
VSTRING * vstring_free(VSTRING *vp)
unsigned int dnssec_valid
#define MAX_DNS_QUERY_SIZE
int dns_rr_filter_execute(DNS_RR **rrlist)
#define DNS_REQ_FLAG_STOP_MX_POLICY
void dns_rr_free(DNS_RR *)
unsigned char * answer_start
int dns_lookup_x(const char *name, unsigned type, unsigned flags, DNS_RR **rrlist, VSTRING *fqdn, VSTRING *why, int *rcode, unsigned lflags)
unsigned char * query_start
#define DNS_REQ_FLAG_STOP_NULLMX
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)
bool var_dns_ncache_ttl_fix