1 #include "dns.h"
2 #include "byte.h"
3 #include "uint16_pack_big.h"
4 #include "uint32_pack_big.h"
5 #include "response.h"
6
7 unsigned char response[65535];
8 long long response_len = 0; /* <= 65535 */
9 static long long tctarget;
10
11 #define NAMES 100
12 static unsigned char name[NAMES][255];
13 static long long name_ptr[NAMES]; /* each < 16384 */
14 static long long name_num;
15
response_addbytes(const unsigned char * buf,long long len)16 int response_addbytes(const unsigned char *buf, long long len) {
17
18 if (len < 0) return 0;
19 if (len > 65535 - response_len) return 0;
20 byte_copy(response + response_len, len, buf);
21 response_len += len;
22 return 1;
23 }
24
response_addname(const unsigned char * d)25 int response_addname(const unsigned char *d) {
26
27 long long dlen;
28 long long i;
29 unsigned char buf[2];
30
31 dlen = dns_domain_length(d);
32
33 while (*d) {
34 for (i = 0; i < name_num; ++i)
35 if (dns_domain_equal(d, name[i])) {
36 uint16_pack_big(buf, 49152 + name_ptr[i]);
37 return response_addbytes(buf, 2);
38 }
39 if ((dlen <= 255) && (response_len < 16384))
40 if (name_num < NAMES) {
41 byte_copy(name[name_num], dlen, d);
42 name_ptr[name_num] = response_len;
43 ++name_num;
44 }
45 i = *d;
46 ++i;
47 if (!response_addbytes(d, i)) return 0;
48 d += i;
49 dlen -= i;
50 }
51 return response_addbytes(d, 1);
52 }
53
response_query(const unsigned char * q,const unsigned char qtype[2],const unsigned char qclass[2])54 int response_query(const unsigned char *q, const unsigned char qtype[2], const unsigned char qclass[2]) {
55
56 response_len = 0;
57 name_num = 0;
58 if (!response_addbytes((unsigned char *)"\0\0\201\200\0\1\0\0\0\0\0\0", 12)) return 0;
59 if (!response_addname(q)) return 0;
60 if (!response_addbytes(qtype, 2)) return 0;
61 if (!response_addbytes(qclass, 2)) return 0;
62 tctarget = response_len;
63 return 1;
64 }
65
66 static long long dpos;
67
68 static int flaghidettl = 0;
69
response_hidettl(void)70 void response_hidettl(void) {
71 flaghidettl = 1;
72 }
73
response_rstart(const unsigned char * d,const unsigned char type[2],crypto_uint32 ttl)74 int response_rstart(const unsigned char *d, const unsigned char type[2], crypto_uint32 ttl) {
75
76 unsigned char ttlstr[4];
77 if (!response_addname(d)) return 0;
78 if (!response_addbytes(type, 2)) return 0;
79 if (!response_addbytes(DNS_C_IN, 2)) return 0;
80 if (flaghidettl) ttl = 0;
81 uint32_pack_big(ttlstr, ttl);
82 if (!response_addbytes(ttlstr, 4)) return 0;
83 if (!response_addbytes((unsigned char *)"\0\0", 2)) return 0;
84 dpos = response_len;
85 return 1;
86 }
87
response_rfinish(int x)88 void response_rfinish(int x) {
89 uint16_pack_big(response + dpos - 2, response_len - dpos);
90 if (!++response[x + 1]) ++response[x];
91 }
92
response_cname(const unsigned char * c,const unsigned char * d,crypto_uint32 ttl)93 int response_cname(const unsigned char *c, const unsigned char *d, crypto_uint32 ttl) {
94 if (!response_rstart(c, DNS_T_CNAME, ttl)) return 0;
95 if (!response_addname(d)) return 0;
96 response_rfinish(RESPONSE_ANSWER);
97 return 1;
98 }
99
response_nxdomain(void)100 void response_nxdomain(void) {
101 response[3] |= 3;
102 response[2] |= 4;
103 }
104
response_servfail(void)105 void response_servfail(void) {
106 response[3] |= 2;
107 }
108
response_id(const unsigned char id[2])109 void response_id(const unsigned char id[2]) {
110 byte_copy(response, 2, id);
111 }
112
response_tc(void)113 void response_tc(void) {
114 response[2] |= 2;
115 response_len = tctarget;
116 byte_zero(response + 6, 6);
117 }
118