1 #include <string.h>
2
3 #include "dns.h"
4
sizeit(const char * buf,unsigned int len,unsigned int pos,uint16 datalen)5 static int sizeit(const char* buf, unsigned int len, unsigned int pos, uint16 datalen)
6 {
7 if (pos + datalen > len) return -1;
8 return datalen + 1;
9 (void)buf;
10 }
11
getit(struct dns_result * out,unsigned int i,unsigned int offset,const char * buf,unsigned int len,unsigned int pos,uint16 datalen)12 static int getit(struct dns_result* out, unsigned int i, unsigned int offset,
13 const char* buf, unsigned int len, unsigned int pos, uint16 datalen)
14 {
15 unsigned int txtlen;
16 char ch;
17 unsigned int j;
18 unsigned int k;
19 char* name = out->rr.name[i] = out->__buffer + offset;
20
21 for (txtlen = j = 0; j < datalen; ) {
22 ch = buf[pos + j];
23 txtlen += (unsigned char)ch;
24 j += (unsigned char)ch + 1;
25 }
26 txtlen = 0;
27 for (j = k = 0;j < datalen;++j) {
28 ch = buf[pos + j];
29 if (!txtlen)
30 txtlen = (unsigned char) ch;
31 else {
32 --txtlen;
33 if (ch < 32) ch = '?';
34 if (ch > 126) ch = '?';
35 name[k++] = ch;
36 }
37 }
38 name[k++] = 0;
39 return k;
40 (void)len;
41 }
42
43 /** Extract text (TXT) records from a DNS response packet. */
dns_txt_packet(struct dns_result * out,const char * buf,unsigned int len)44 int dns_txt_packet(struct dns_result* out, const char* buf, unsigned int len)
45 {
46 return dns_packet_extract(out, buf, len, DNS_T_TXT, DNS_C_IN, sizeit, getit);
47 }
48
49 /** Request the text (TXT) records for a domain name. */
dns_txt_r(struct dns_transmit * tx,struct dns_result * out,const char * fqdn)50 int dns_txt_r(struct dns_transmit* tx, struct dns_result* out, const char* fqdn)
51 {
52 char *q = 0;
53 if (!dns_domain_fromdot(&q,fqdn,strlen(fqdn))) return -1;
54 if (dns_resolve(tx,q,DNS_T_TXT) == -1) { free(q); return -1; }
55 if (dns_txt_packet(out,tx->packet,tx->packetlen) == -1) { free(q); return -1; }
56 free(q);
57 return 0;
58 }
59
60 /** \fn dns_txt(struct dns_result*, const char*)
61 Request the text (TXT) records for a domain name.
62 */
DNS_R_FN_WRAP(txt,const char *)63 DNS_R_FN_WRAP(txt, const char*)
64
65 #ifdef SELFTEST_MAIN
66 #include "dns-responder.c"
67 DUMP
68 {
69 int i;
70 for (i = 0; i < count; ++i) {
71 obuf_puts(&outbuf, rr->name[i]);
72 NL();
73 }
74 }
75 RESPONSE responses[] = {
76 { 2, 1, 0, {
77 { "\300\014", 2, 16, 1, 5, "\050http://www.spamhaus.org/sbl/query/SBL233", 41 },
78 { "\300\014", 2, 16, 1, 5, "\055http://www.spamhaus.org/query/bl?ip=127.0.0.2", 46 },
79 { "\300\026", 2, 2, 1, 3132, "\001g\002ns\300\036", 7 },
80 }
81 },
82 { 1, 1, 0, {
83 { "\300\014", 2, 16, 1, 512, "\037v=spf1 redirect=_spf.google.com", 32 },
84 { "\300\026", 2, 2, 1, 123456, "\003ns2\006google\300\022", 13 },
85 }
86 },
87 };
88 MAIN
89 {
90 const char* names[] = { "2.0.0.127.sbl-xbl.spamhaus.org", "gmail.com", NULL };
91 do_dns_respond_tests(dns_txt, names, responses, 2);
92 }
93 #endif
94 #ifdef SELFTEST_EXP
95 48: ID=XX QR=0 opcode=0 AA=0 TC=0 RD=1 RA=0 Z=0 RCODE=0 QDCOUNT=1 ANCOUNT=0 NSCOUNT=0 ARCOUNT=0
96 Question: 2.0.0.127.sbl-xbl.spamhaus.org. QTYPE=16 QCLASS=1
97 result=0
98 2.0.0.127.sbl-xbl.spamhaus.org: count=2
99 http://www.spamhaus.org/sbl/query/SBL233
100 http://www.spamhaus.org/query/bl?ip=127.0.0.2
101 27: ID=XX QR=0 opcode=0 AA=0 TC=0 RD=1 RA=0 Z=0 RCODE=0 QDCOUNT=1 ANCOUNT=0 NSCOUNT=0 ARCOUNT=0
102 Question: gmail.com. QTYPE=16 QCLASS=1
103 result=0
104 gmail.com: count=1
105 v=spf1 redirect=_spf.google.com
106 #endif
107