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