12 static int want(const char *owner
,const char type
[2])
19 pos
= dns_packet_skipname(response
,response_len
,12); if (!pos
) return 0;
22 while (pos
< response_len
) {
23 pos
= dns_packet_getname(response
,response_len
,pos
,&d
); if (!pos
) return 0;
24 pos
= dns_packet_copy(response
,response_len
,pos
,x
,10); if (!pos
) return 0;
25 if (dns_domain_equal(d
,owner
))
26 if (byte_equal(type
,2,x
))
28 uint16_unpack_big(x
+ 8,&datalen
);
36 static char clientloc
[2];
37 static struct tai now
;
40 static char data
[32767];
42 static unsigned int dpos
;
46 static int find(char *d
,int flagwild
)
57 r
= cdb_findnext(&c
,d
,dns_domain_length(d
));
59 dlen
= cdb_datalen(&c
);
60 if (dlen
> sizeof data
) return -1;
61 if (cdb_read(&c
,data
,dlen
,cdb_datapos(&c
)) == -1) return -1;
62 dpos
= dns_packet_copy(data
,dlen
,0,type
,2); if (!dpos
) return -1;
63 dpos
= dns_packet_copy(data
,dlen
,dpos
,&ch
,1); if (!dpos
) return -1;
64 if ((ch
== '=' + 1) || (ch
== '*' + 1)) {
66 dpos
= dns_packet_copy(data
,dlen
,dpos
,recordloc
,2); if (!dpos
) return -1;
67 if (byte_diff(recordloc
,2,clientloc
)) continue;
69 if (flagwild
!= (ch
== '*')) continue;
70 dpos
= dns_packet_copy(data
,dlen
,dpos
,ttlstr
,4); if (!dpos
) return -1;
71 uint32_unpack_big(ttlstr
,&ttl
);
72 dpos
= dns_packet_copy(data
,dlen
,dpos
,ttd
,8); if (!dpos
) return -1;
73 if (byte_diff(ttd
,8,"\0\0\0\0\0\0\0\0")) {
74 tai_unpack(ttd
,&cutoff
);
76 if (tai_less(&cutoff
,&now
)) continue;
77 tai_sub(&cutoff
,&cutoff
,&now
);
78 newttl
= tai_approx(&cutoff
);
79 if (newttl
<= 2.0) newttl
= 2.0;
80 if (newttl
>= 3600.0) newttl
= 3600.0;
84 if (!tai_less(&cutoff
,&now
)) continue;
90 static int dobytes(unsigned int len
)
93 if (len
> 20) return 0;
94 dpos
= dns_packet_copy(data
,dlen
,dpos
,buf
,len
);
96 return response_addbytes(buf
,len
);
99 static int doname(void)
101 dpos
= dns_packet_getname(data
,dlen
,dpos
,&d1
);
103 return response_addname(d1
);
106 static int doit(char *q
,char qtype
[2])
118 int flagauthoritative
;
126 anpos
= response_len
;
131 flagauthoritative
= 0;
133 while (r
= find(control
,0)) {
134 if (r
== -1) return 0;
135 if (byte_equal(type
,2,DNS_T_SOA
)) flagauthoritative
= 1;
136 if (byte_equal(type
,2,DNS_T_NS
)) flagns
= 1;
139 if (!*control
) return 0; /* q is not within our bailiwick */
144 if (!flagauthoritative
) {
146 goto AUTHORITY
; /* q is in a child zone */
158 while (r
= find(wild
,wild
!= q
)) {
159 if (r
== -1) return 0;
161 if (flaggavesoa
&& byte_equal(type
,2,DNS_T_SOA
)) continue;
162 if (byte_diff(type
,2,qtype
) && byte_diff(qtype
,2,DNS_T_ANY
) && byte_diff(type
,2,DNS_T_CNAME
)) continue;
163 if (byte_equal(type
,2,DNS_T_A
) && (dlen
- dpos
== 4)) {
165 i
= dns_random(addrnum
+ 1);
167 if ((i
< addrnum
) && (addrnum
< 8))
168 byte_copy(addr
[addrnum
],4,addr
[i
]);
169 byte_copy(addr
[i
],4,data
+ dpos
);
171 if (addrnum
< 1000000) ++addrnum
;
174 if (!response_rstart(q
,type
,ttl
)) return 0;
175 if (byte_equal(type
,2,DNS_T_NS
) || byte_equal(type
,2,DNS_T_CNAME
) || byte_equal(type
,2,DNS_T_PTR
)) {
176 if (!doname()) return 0;
178 else if (byte_equal(type
,2,DNS_T_MX
)) {
179 if (!dobytes(2)) return 0;
180 if (!doname()) return 0;
182 else if (byte_equal(type
,2,DNS_T_SOA
)) {
183 if (!doname()) return 0;
184 if (!doname()) return 0;
185 if (!dobytes(20)) return 0;
189 if (!response_addbytes(data
+ dpos
,dlen
- dpos
)) return 0;
190 response_rfinish(RESPONSE_ANSWER
);
192 for (i
= 0;i
< addrnum
;++i
)
194 if (!response_rstart(q
,DNS_T_A
,addrttl
)) return 0;
195 if (!response_addbytes(addr
[i
],4)) return 0;
196 response_rfinish(RESPONSE_ANSWER
);
199 if (flagfound
) break;
200 if (wild
== control
) break;
201 if (!*wild
) break; /* impossible */
211 aupos
= response_len
;
213 if (flagauthoritative
&& (aupos
== anpos
)) {
215 while (r
= find(control
,0)) {
216 if (r
== -1) return 0;
217 if (byte_equal(type
,2,DNS_T_SOA
)) {
218 if (!response_rstart(control
,DNS_T_SOA
,ttl
)) return 0;
219 if (!doname()) return 0;
220 if (!doname()) return 0;
221 if (!dobytes(20)) return 0;
222 response_rfinish(RESPONSE_AUTHORITY
);
228 if (want(control
,DNS_T_NS
)) {
230 while (r
= find(control
,0)) {
231 if (r
== -1) return 0;
232 if (byte_equal(type
,2,DNS_T_NS
)) {
233 if (!response_rstart(control
,DNS_T_NS
,ttl
)) return 0;
234 if (!doname()) return 0;
235 response_rfinish(RESPONSE_AUTHORITY
);
240 arpos
= response_len
;
243 while (bpos
< arpos
) {
244 bpos
= dns_packet_skipname(response
,arpos
,bpos
); if (!bpos
) return 0;
245 bpos
= dns_packet_copy(response
,arpos
,bpos
,x
,10); if (!bpos
) return 0;
246 if (byte_equal(x
,2,DNS_T_NS
) || byte_equal(x
,2,DNS_T_MX
)) {
247 if (byte_equal(x
,2,DNS_T_NS
)) {
248 if (!dns_packet_getname(response
,arpos
,bpos
,&d1
)) return 0;
251 if (!dns_packet_getname(response
,arpos
,bpos
+ 2,&d1
)) return 0;
252 case_lowerb(d1
,dns_domain_length(d1
));
253 if (want(d1
,DNS_T_A
)) {
255 while (r
= find(d1
,0)) {
256 if (r
== -1) return 0;
257 if (byte_equal(type
,2,DNS_T_A
)) {
258 if (!response_rstart(d1
,DNS_T_A
,ttl
)) return 0;
259 if (!dobytes(4)) return 0;
260 response_rfinish(RESPONSE_ADDITIONAL
);
265 uint16_unpack_big(x
+ 8,&u16
);
269 if (flagauthoritative
&& (response_len
> 512)) {
270 byte_zero(response
+ RESPONSE_ADDITIONAL
,2);
271 response_len
= arpos
;
272 if (response_len
> 512) {
273 byte_zero(response
+ RESPONSE_AUTHORITY
,2);
274 response_len
= aupos
;
281 int respond(char *q
,char qtype
[2],char ip
[4])
288 fd
= open_read("data.cdb");
289 if (fd
== -1) return 0;
292 byte_zero(clientloc
,2);
295 byte_copy(key
+ 2,4,ip
);
296 r
= cdb_find(&c
,key
,6);
297 if (!r
) r
= cdb_find(&c
,key
,5);
298 if (!r
) r
= cdb_find(&c
,key
,4);
299 if (!r
) r
= cdb_find(&c
,key
,3);
300 if (!r
) r
= cdb_find(&c
,key
,2);
301 if (r
== -1) return 0;
302 if (r
&& (cdb_datalen(&c
) == 2))
303 if (cdb_read(&c
,clientloc
,2,cdb_datapos(&c
)) == -1) return 0;