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