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 char* q = 0;
8 if (!dns_packet_getname(buf,len,pos + 2,&q)) return -1;
9 len = fmt_dns_domain(0, q);
10 free(q);
11 return len + 1;
12 (void)datalen;
13 }
14
getit(struct dns_result * out,unsigned int i,unsigned int offset,const char * buf,unsigned int len,unsigned int pos,uint16 datalen)15 static int getit(struct dns_result* out, unsigned int i, unsigned int offset,
16 const char* buf, unsigned int len, unsigned int pos, uint16 datalen)
17 {
18 unsigned char pref[2];
19 char* q = 0;
20 struct dns_mx* mx = &out->rr.mx[i];
21
22 if (!dns_packet_copy(buf,len,pos,pref,2)) return -1;
23 mx->distance = uint16_get_msb(pref);
24 if (!dns_packet_getname(buf,len,pos + 2,&q)) return -1;
25 mx->name = out->__buffer + offset;
26 len = fmt_dns_domain(mx->name, q);
27 mx->name[len] = 0;
28 free(q);
29 return len + 1;
30 (void)datalen;
31 }
32
33 /** Extract mail exchanger (MX) records from a DNS response packet. */
dns_mx_packet(struct dns_result * out,const char * buf,unsigned int len)34 int dns_mx_packet(struct dns_result* out, const char* buf, unsigned int len)
35 {
36 return dns_packet_extract(out, buf, len, DNS_T_MX, DNS_C_IN, sizeit, getit);
37 }
38
39 /** Request the mail exchanger (MX) records for a domain name. */
dns_mx_r(struct dns_transmit * tx,struct dns_result * out,const char * fqdn)40 int dns_mx_r(struct dns_transmit* tx, struct dns_result* out, const char* fqdn)
41 {
42 char *q = 0;
43 if (!dns_domain_fromdot(&q,fqdn,strlen(fqdn))) return -1;
44 if (dns_resolve(tx,q,DNS_T_MX) == -1) { free(q); return -1; }
45 free(q);
46 if (dns_mx_packet(out,tx->packet,tx->packetlen) == -1) return -1;
47 dns_transmit_free(tx);
48 return 0;
49 }
50
51 /** \fn dns_mx(struct dns_result*, const char*)
52 Request the mail exchanger (MX) records for a domain name.
53 */
DNS_R_FN_WRAP(mx,const char *)54 DNS_R_FN_WRAP(mx, const char*)
55
56 #ifdef SELFTEST_MAIN
57 #include "dns-responder.c"
58 DUMP
59 {
60 int i;
61
62 dns_sort_mx(rr->mx, count);
63 for (i = 0; i < count; ++i)
64 obuf_putf(&outbuf, "d{ }d{: \"}s{\"\n}", i, rr->mx[i].distance, rr->mx[i].name);
65 }
66 RESPONSE responses[] = {
67 { 1, 3, 0, {
68 { "\300\014", 2, 15, 1, 86400, "2\1\2mx\vfuturequest\3net\0", 22 },
69 { "\300\014", 2, 1, 1, 123456, "\3ns2\300\061", 6 },
70 { "\300\014", 2, 1, 1, 123456, "\3ns1\300\061", 6 },
71 { "\300\014", 2, 1, 1, 123456, "\3ns3\300\061", 6 },
72 }
73 },
74 { 5, 0, 0, {
75 { "\300\014", 2, 15, 1, 86400, "\0\024\4alt1\5aspmx\1l\6google\3com\0", 27 },
76 { "\300\014", 2, 15, 1, 86400, "\0\012\5aspmx\1l\6google\3com\0", 22, },
77 { "\300\014", 2, 15, 1, 86400, "\0\036\4alt2\5aspmx\1l\6google\3com\0", 27 },
78 { "\300\014", 2, 15, 1, 86400, "\0\050\4alt3\5aspmx\1l\6google\3com\0", 27 },
79 { "\300\014", 2, 15, 1, 86400, "\0\062\4alt4\5aspmx\1l\6google\3com\0", 27 },
80 }
81 },
82 };
83 MAIN
84 {
85 const char* names[] = { "untroubled.org", "google.com", NULL };
86 do_dns_respond_tests(dns_mx, names, responses, 2);
87 }
88 #endif
89 #ifdef SELFTEST_EXP
90 32: 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
91 Question: untroubled.org. QTYPE=15 QCLASS=1
92 result=0
93 untroubled.org: count=1
94 0 12801: "mx.futurequest.net"
95 28: 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: google.com. QTYPE=15 QCLASS=1
97 result=0
98 google.com: count=5
99 0 10: "aspmx.l.google.com"
100 1 20: "alt1.aspmx.l.google.com"
101 2 30: "alt2.aspmx.l.google.com"
102 3 40: "alt3.aspmx.l.google.com"
103 4 50: "alt4.aspmx.l.google.com"
104 #endif
105