release
[hcoop/zz_old/debian/djbdns.git] / rbldns.c
CommitLineData
dc0d77d7
CE
1#include <unistd.h>
2#include "str.h"
3#include "byte.h"
4#include "ip4.h"
5#include "open.h"
6#include "env.h"
7#include "cdb.h"
8#include "dns.h"
9#include "dd.h"
10#include "strerr.h"
11#include "response.h"
12
13static char *base;
14
15static struct cdb c;
16static char key[5];
17static char data[100 + IP4_FMT];
18
19static int doit(char *q,char qtype[2])
20{
21 int flaga;
22 int flagtxt;
23 char ch;
24 char reverseip[4];
25 char ip[4];
26 uint32 ipnum;
27 int r;
28 uint32 dlen;
29 int i;
30
31 flaga = byte_equal(qtype,2,DNS_T_A);
32 flagtxt = byte_equal(qtype,2,DNS_T_TXT);
33 if (byte_equal(qtype,2,DNS_T_ANY)) flaga = flagtxt = 1;
34 if (!flaga && !flagtxt) goto REFUSE;
35
36 if (dd(q,base,reverseip) != 4) goto REFUSE;
37 uint32_unpack(reverseip,&ipnum);
38 uint32_pack_big(ip,ipnum);
39
40 for (i = 0;i <= 24;++i) {
41 ipnum >>= i;
42 ipnum <<= i;
43 uint32_pack_big(key,ipnum);
44 key[4] = 32 - i;
45 r = cdb_find(&c,key,5);
46 if (r == -1) return 0;
47 if (r) break;
48 }
49 if (!r) { response_nxdomain(); return 1; }
50
51 r = cdb_find(&c,"",0);
52 if (r == -1) return 0;
53 if (r && ((dlen = cdb_datalen(&c)) >= 4)) {
54 if (dlen > 100) dlen = 100;
55 if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return 0;
56 }
57 else {
58 dlen = 12;
59 byte_copy(data,dlen,"\177\0\0\2Listed $");
60 }
61
62 if ((dlen >= 5) && (data[dlen - 1] == '$')) {
63 --dlen;
64 dlen += ip4_fmt(data + dlen,ip);
65 }
66
67 if (flaga) {
68 if (!response_rstart(q,DNS_T_A,2048)) return 0;
69 if (!response_addbytes(data,4)) return 0;
70 response_rfinish(RESPONSE_ANSWER);
71 }
72 if (flagtxt) {
73 if (!response_rstart(q,DNS_T_TXT,2048)) return 0;
74 ch = dlen - 4;
75 if (!response_addbytes(&ch,1)) return 0;
76 if (!response_addbytes(data + 4,dlen - 4)) return 0;
77 response_rfinish(RESPONSE_ANSWER);
78 }
79
80 return 1;
81
82
83 REFUSE:
84 response[2] &= ~4;
85 response[3] &= ~15;
86 response[3] |= 5;
87 return 1;
88}
89
90int respond(char *q,char qtype[2],char ip[4])
91{
92 int fd;
93 int result;
94
95 fd = open_read("data.cdb");
96 if (fd == -1) return 0;
97 cdb_init(&c,fd);
98 result = doit(q,qtype);
99 cdb_free(&c);
100 close(fd);
101 return result;
102}
103
104const char *fatal = "rbldns: fatal: ";
105const char *starting = "starting rbldns\n";
106
107void initialize(void)
108{
109 char *x;
110
111 x = env_get("BASE");
112 if (!x)
113 strerr_die2x(111,fatal,"$BASE not set");
114 if (!dns_domain_fromdot(&base,x,str_len(x)))
115 strerr_die2x(111,fatal,"unable to parse $BASE");
116}