release
[hcoop/zz_old/debian/djbdns.git] / pickdns.c
1 #include <unistd.h>
2 #include "byte.h"
3 #include "case.h"
4 #include "dns.h"
5 #include "open.h"
6 #include "cdb.h"
7 #include "response.h"
8
9 const char *fatal = "pickdns: fatal: ";
10 const char *starting = "starting pickdns\n";
11
12 static char seed[128];
13
14 void initialize(void)
15 {
16 dns_random_init(seed);
17 }
18
19 static struct cdb c;
20 static char key[258];
21 static char data[512];
22
23 static int doit(char *q,char qtype[2],char ip[4])
24 {
25 int r;
26 uint32 dlen;
27 unsigned int qlen;
28 int flaga;
29 int flagmx;
30
31 qlen = dns_domain_length(q);
32 if (qlen > 255) return 0; /* impossible */
33
34 flaga = byte_equal(qtype,2,DNS_T_A);
35 flagmx = byte_equal(qtype,2,DNS_T_MX);
36 if (byte_equal(qtype,2,DNS_T_ANY)) flaga = flagmx = 1;
37 if (!flaga && !flagmx) goto REFUSE;
38
39 key[0] = '%';
40 byte_copy(key + 1,4,ip);
41
42 r = cdb_find(&c,key,5);
43 if (!r) r = cdb_find(&c,key,4);
44 if (!r) r = cdb_find(&c,key,3);
45 if (!r) r = cdb_find(&c,key,2);
46 if (r == -1) return 0;
47
48 key[0] = '+';
49 byte_zero(key + 1,2);
50 if (r && (cdb_datalen(&c) == 2))
51 if (cdb_read(&c,key + 1,2,cdb_datapos(&c)) == -1) return 0;
52
53 byte_copy(key + 3,qlen,q);
54 case_lowerb(key + 3,qlen + 3);
55
56 r = cdb_find(&c,key,qlen + 3);
57 if (!r) {
58 byte_zero(key + 1,2);
59 r = cdb_find(&c,key,qlen + 3);
60 }
61 if (!r) goto REFUSE;
62 if (r == -1) return 0;
63 dlen = cdb_datalen(&c);
64
65 if (dlen > 512) dlen = 512;
66 if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return 0;
67
68 if (flaga) {
69 dns_sortip(data,dlen);
70 if (dlen > 12) dlen = 12;
71 while (dlen >= 4) {
72 dlen -= 4;
73 if (!response_rstart(q,DNS_T_A,5)) return 0;
74 if (!response_addbytes(data + dlen,4)) return 0;
75 response_rfinish(RESPONSE_ANSWER);
76 }
77 }
78
79 return 1;
80
81
82 REFUSE:
83 response[2] &= ~4;
84 response[3] &= ~15;
85 response[3] |= 5;
86 return 1;
87 }
88
89 int respond(char *q,char qtype[2],char ip[4])
90 {
91 int fd;
92 int result;
93
94 fd = open_read("data.cdb");
95 if (fd == -1) return 0;
96 cdb_init(&c,fd);
97 result = doit(q,qtype,ip);
98 cdb_free(&c);
99 close(fd);
100 return result;
101 }