release
[hcoop/zz_old/debian/djbdns.git] / dnsfilter.c
CommitLineData
dc0d77d7
CE
1#include <unistd.h>
2#include "strerr.h"
3#include "buffer.h"
4#include "stralloc.h"
5#include "alloc.h"
6#include "dns.h"
7#include "ip4.h"
8#include "byte.h"
9#include "scan.h"
10#include "taia.h"
11#include "sgetopt.h"
12#include "iopause.h"
13#include "error.h"
14#include "exit.h"
15
16#define FATAL "dnsfilter: fatal: "
17
18void nomem(void)
19{
20 strerr_die2x(111,FATAL,"out of memory");
21}
22
23struct line {
24 stralloc left;
25 stralloc middle;
26 stralloc right;
27 struct dns_transmit dt;
28 int flagactive;
29 iopause_fd *io;
30} *x;
31struct line tmp;
32unsigned int xmax = 1000;
33unsigned int xnum = 0;
34unsigned int numactive = 0;
35unsigned int maxactive = 10;
36
37static stralloc partial;
38
39char inbuf[1024];
40int inbuflen = 0;
41iopause_fd *inio;
42int flag0 = 1;
43
44iopause_fd *io;
45int iolen;
46
47char servers[64];
48char ip[4];
49char name[DNS_NAME4_DOMAIN];
50
51void errout(int i)
52{
53 int j;
54
55 if (!stralloc_copys(&x[i].middle,":")) nomem();
56 if (!stralloc_cats(&x[i].middle,error_str(errno))) nomem();
57 for (j = 0;j < x[i].middle.len;++j)
58 if (x[i].middle.s[j] == ' ')
59 x[i].middle.s[j] = '-';
60}
61
62int main(int argc,char **argv)
63{
64 struct taia stamp;
65 struct taia deadline;
66 int opt;
67 unsigned long u;
68 int i;
69 int j;
70 int r;
71
72 while ((opt = getopt(argc,argv,"c:l:")) != opteof)
73 switch(opt) {
74 case 'c':
75 scan_ulong(optarg,&u);
76 if (u < 1) u = 1;
77 if (u > 1000) u = 1000;
78 maxactive = u;
79 break;
80 case 'l':
81 scan_ulong(optarg,&u);
82 if (u < 1) u = 1;
83 if (u > 1000000) u = 1000000;
84 xmax = u;
85 break;
86 default:
87 strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]");
88 }
89
90 x = (struct line *) alloc(xmax * sizeof(struct line));
91 if (!x) nomem();
92 byte_zero(x,xmax * sizeof(struct line));
93
94 io = (iopause_fd *) alloc((xmax + 1) * sizeof(iopause_fd));
95 if (!io) nomem();
96
97 if (!stralloc_copys(&partial,"")) nomem();
98
99
100 while (flag0 || inbuflen || partial.len || xnum) {
101 taia_now(&stamp);
102 taia_uint(&deadline,120);
103 taia_add(&deadline,&deadline,&stamp);
104
105 iolen = 0;
106
107 if (flag0)
108 if (inbuflen < sizeof inbuf) {
109 inio = io + iolen++;
110 inio->fd = 0;
111 inio->events = IOPAUSE_READ;
112 }
113
114 for (i = 0;i < xnum;++i)
115 if (x[i].flagactive) {
116 x[i].io = io + iolen++;
117 dns_transmit_io(&x[i].dt,x[i].io,&deadline);
118 }
119
120 iopause(io,iolen,&deadline,&stamp);
121
122 if (flag0)
123 if (inbuflen < sizeof inbuf)
124 if (inio->revents) {
125 r = read(0,inbuf + inbuflen,(sizeof inbuf) - inbuflen);
126 if (r <= 0)
127 flag0 = 0;
128 else
129 inbuflen += r;
130 }
131
132 for (i = 0;i < xnum;++i)
133 if (x[i].flagactive) {
134 r = dns_transmit_get(&x[i].dt,x[i].io,&stamp);
135 if (r == -1) {
136 errout(i);
137 x[i].flagactive = 0;
138 --numactive;
139 }
140 else if (r == 1) {
141 if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1)
142 errout(i);
143 if (x[i].middle.len)
144 if (!stralloc_cats(&x[i].left,"=")) nomem();
145 x[i].flagactive = 0;
146 --numactive;
147 }
148 }
149
150 for (;;) {
151
152 if (xnum && !x[0].flagactive) {
153 buffer_put(buffer_1,x[0].left.s,x[0].left.len);
154 buffer_put(buffer_1,x[0].middle.s,x[0].middle.len);
155 buffer_put(buffer_1,x[0].right.s,x[0].right.len);
156 buffer_flush(buffer_1);
157 --xnum;
158 tmp = x[0];
159 for (i = 0;i < xnum;++i) x[i] = x[i + 1];
160 x[xnum] = tmp;
161 continue;
162 }
163
164 if ((xnum < xmax) && (numactive < maxactive)) {
165 i = byte_chr(inbuf,inbuflen,'\n');
166 if (inbuflen && (i == inbuflen)) {
167 if (!stralloc_catb(&partial,inbuf,inbuflen)) nomem();
168 inbuflen = 0;
169 continue;
170 }
171
172 if ((i < inbuflen) || (!flag0 && partial.len)) {
173 if (i < inbuflen) ++i;
174 if (!stralloc_catb(&partial,inbuf,i)) nomem();
175 inbuflen -= i;
176 for (j = 0;j < inbuflen;++j) inbuf[j] = inbuf[j + i];
177
178 if (partial.len) {
179 i = byte_chr(partial.s,partial.len,'\n');
180 i = byte_chr(partial.s,i,'\t');
181 i = byte_chr(partial.s,i,' ');
182
183 if (!stralloc_copyb(&x[xnum].left,partial.s,i)) nomem();
184 if (!stralloc_copys(&x[xnum].middle,"")) nomem();
185 if (!stralloc_copyb(&x[xnum].right,partial.s + i,partial.len - i)) nomem();
186 x[xnum].flagactive = 0;
187
188 partial.len = i;
189 if (!stralloc_0(&partial)) nomem();
190 if (ip4_scan(partial.s,ip)) {
191 dns_name4_domain(name,ip);
192 if (dns_resolvconfip(servers) == -1)
193 strerr_die2sys(111,FATAL,"unable to read /etc/resolv.conf: ");
194 if (dns_transmit_start(&x[xnum].dt,servers,1,name,DNS_T_PTR,"\0\0\0\0") == -1)
195 errout(xnum);
196 else {
197 x[xnum].flagactive = 1;
198 ++numactive;
199 }
200 }
201 ++xnum;
202 }
203
204 partial.len = 0;
205 continue;
206 }
207 }
208
209 break;
210 }
211 }
212
213 _exit(0);
214}