Mercurial > dnsbl
diff src/dnsbl.cpp @ 414:d5a1ed33d3ae
spf code now handles mx,exists,ptr tags, multiple A records, %{i} macro
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Tue, 25 Apr 2017 14:48:19 -0700 |
parents | 6b03435868cb |
children | 16451edcb962 |
line wrap: on
line diff
--- a/src/dnsbl.cpp Wed Apr 19 09:36:16 2017 -0700 +++ b/src/dnsbl.cpp Tue Apr 25 14:48:19 2017 -0700 @@ -297,14 +297,16 @@ // Ask a dns question and get an A record answer in network byte order. // We don't try very hard, just using the default resolver retry settings. // If we cannot get an answer, we just accept the mail. -// If the qtype is ns_t_txt, the answer is placed in txt_answer which +// If the qtype is ns_t_txt, the answer is placed in my_answer which // must be non-null, and the return value can be ignored. -// A null string is returned in txt_answer in the case of errors. -// If the qtype is ns_t_a, the ip address is returned in network byte order. +// A null string is returned in my_answer in the case of errors. +// If the qtype is ns_t_a, one of the ip addresses is returned in network byte order, +// and if my_answer is non-null, all the ip addresses are returned in +// my_answer (in network byte order), prepended with the count. // IP address 0 is returned in case of errors. // -uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *txt_answer, size_t txt_size) { - if (txt_answer) txt_answer[0] = '\0'; // return null string if there are no txt answers +uint32_t dns_interface(mlfiPriv &priv, const char *question, int qtype, bool maybe_ip, ns_map *nameservers, char *my_answer, size_t my_size) { + if (my_answer) my_answer[0] = '\0'; // return null string if there are no txt answers // tell sendmail we are still working #if _FFR_SMFI_PROGRESS @@ -412,17 +414,45 @@ } int rrnum = 0; if (qtype == ns_t_a) { + uint32_t *ans = (uint32_t *)my_answer; + size_t c = 0; + size_t m = my_size/4; // 1 + max ipv4 addresses that will fit in the answer buffer while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { if (ns_rr_type(rr) == qtype) { uint32_t address; memcpy(&address, ns_rr_rdata(rr), sizeof(address)); ret_address = address; + if (ans && (c < m-1)) { + c++; + ans[c] = address; } } } - if ((qtype == ns_t_txt) && (txt_answer) && (txt_size > 7)) { - txt_answer[0] = '\0'; // return null string if there are no txt answers - txt_size--; // allow room for terminating null; + if (ans && (c < m)) ans[0] = c; + } + if ((qtype == ns_t_mx) && (my_answer) && (my_size > 1)) { + uint32_t c = 0; + while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { + if (ns_rr_type(rr) == qtype) { + char exchange[NS_MAXDNAME]; + size_t rdlen = ns_rr_rdlen(rr); + const unsigned char *rdata = ns_rr_rdata(rr); + const uint16_t pri = ns_get16(rdata); + int len = dn_expand(glom.answer, glom.answer+glom.length, rdata + 2, exchange, sizeof(exchange)); + if ((len > 0) && (my_size > len+2)) { + strcpy(my_answer, exchange); + my_answer += len + 1; + my_size -= len + 1; + c++; + } + } + } + *my_answer = '\0'; // final trailing null + ret_address = htonl(c); + } + if ((qtype == ns_t_txt) && (my_answer) && (my_size > 7)) { + my_answer[0] = '\0'; // return null string if there are no txt answers + my_size--; // allow room for terminating null; while (ns_parserr(&handle, ns_s_an, rrnum++, &rr) == 0) { if (ns_rr_type(rr) == qtype) { size_t offset = 0; @@ -433,26 +463,26 @@ snprintf(text, sizeof(text), "found txt record rdlen = %d", rdlen); my_syslog(text); #endif - while ((offset < txt_size) && rdlen) { + while ((offset < my_size) && rdlen) { size_t slen = size_t(*(rdata++)); rdlen--; size_t m = min(slen, rdlen); - m = min(m, txt_size-offset); - memcpy(txt_answer+offset, rdata, m); + m = min(m, my_size-offset); + memcpy(my_answer+offset, rdata, m); offset += m; rdata += m; rdlen -= m; } - txt_answer[offset] = '\0'; // trailing null + my_answer[offset] = '\0'; // trailing null #ifdef RESOLVER_DEBUG - snprintf(text, sizeof(text), "found txt record %s", txt_answer); + snprintf(text, sizeof(text), "found txt record %s", my_answer); my_syslog(text); #endif - if (strncasecmp(txt_answer, "v=spf1 ", 7) == 0) break; + if (strncasecmp(my_answer, "v=spf1 ", 7) == 0) break; } } - if (strncasecmp(txt_answer, "v=spf1 ", 7) != 0) { - txt_answer[0] = '\0'; // return null string if there are no spf1 txt answers + if (strncasecmp(my_answer, "v=spf1 ", 7) != 0) { + my_answer[0] = '\0'; // return null string if there are no spf1 txt answers } } }