verify.c revision 1.1.1.3 1 1.1 christos /*
2 1.1 christos * verify.c -- running verifiers and serving the zone to be verified.
3 1.1 christos *
4 1.1 christos * Copyright (c) 2012-2020, NLnet Labs. All rights reserved.
5 1.1 christos *
6 1.1 christos * See LICENSE for the license.
7 1.1 christos *
8 1.1 christos */
9 1.1 christos
10 1.1 christos #include "config.h"
11 1.1 christos
12 1.1 christos #include <assert.h>
13 1.1 christos #include <ctype.h>
14 1.1 christos #include <errno.h>
15 1.1 christos #include <stdarg.h>
16 1.1 christos #include <stdio.h>
17 1.1 christos #include <stdlib.h>
18 1.1 christos #include <string.h>
19 1.1 christos #ifdef HAVE_SYSLOG_H
20 1.1 christos #include <syslog.h>
21 1.1 christos #endif /* HAVE_SYSLOG_H */
22 1.1 christos #include <unistd.h>
23 1.1 christos #include <fcntl.h>
24 1.1 christos #include <sys/wait.h>
25 1.1 christos
26 1.1 christos #include "region-allocator.h"
27 1.1 christos #include "namedb.h"
28 1.1 christos #include "nsd.h"
29 1.1 christos #include "options.h"
30 1.1 christos #include "difffile.h"
31 1.1 christos #include "verify.h"
32 1.1 christos #include "popen3.h"
33 1.1 christos
34 1.1 christos struct zone *verify_next_zone(struct nsd *nsd, struct zone *zone)
35 1.1 christos {
36 1.1 christos int verify;
37 1.1 christos struct radnode *node;
38 1.1 christos
39 1.1 christos if(zone != NULL) {
40 1.1 christos node = radix_next(zone->node);
41 1.1 christos } else {
42 1.1 christos node = radix_first(nsd->db->zonetree);
43 1.1 christos }
44 1.1 christos
45 1.1 christos while(node != NULL) {
46 1.1 christos zone = (struct zone *)node->elem;
47 1.1 christos verify = zone->opts->pattern->verify_zone;
48 1.1 christos if(verify == VERIFY_ZONE_INHERIT) {
49 1.1 christos verify = nsd->options->verify_zones;
50 1.1 christos }
51 1.1 christos if(verify && zone->is_updated && !zone->is_checked) {
52 1.1 christos return zone;
53 1.1 christos }
54 1.1 christos node = radix_next(node);
55 1.1 christos }
56 1.1 christos
57 1.1 christos return NULL;
58 1.1 christos }
59 1.1 christos
60 1.1 christos static inline ssize_t fill_buffer(struct verifier_stream *stream)
61 1.1 christos {
62 1.1 christos ssize_t cnt = 0;
63 1.1 christos
64 1.1 christos assert(stream);
65 1.1 christos assert(stream->fd != -1);
66 1.1 christos assert(stream->cnt <= LOGBUFSIZE);
67 1.1 christos assert(stream->off <= stream->cnt);
68 1.1 christos
69 1.1 christos // move data to start of buffer assuming all complete lines are printed
70 1.1 christos if (stream->off) {
71 1.1 christos size_t len = stream->cnt - stream->off;
72 1.1 christos memmove(stream->buf, stream->buf + stream->off, len);
73 1.1 christos stream->off = 0;
74 1.1 christos stream->cnt = len;
75 1.1 christos stream->buf[stream->cnt] = '\0'; // always null-terminate
76 1.1 christos }
77 1.1 christos
78 1.1 christos // read data if space is available
79 1.1 christos cnt = read(stream->fd, stream->buf + stream->cnt, LOGBUFSIZE - stream->cnt);
80 1.1 christos if (cnt > 0)
81 1.1 christos stream->cnt += (size_t)cnt;
82 1.1 christos assert(stream->cnt <= LOGBUFSIZE);
83 1.1 christos assert(stream->off <= stream->cnt);
84 1.1 christos stream->buf[stream->cnt] = '\0'; // always null-terminate
85 1.1 christos
86 1.1 christos return cnt;
87 1.1 christos }
88 1.1 christos
89 1.1 christos static inline size_t print_line(struct verifier_stream *stream, int eof)
90 1.1 christos {
91 1.1 christos char *eol = NULL;
92 1.1 christos size_t len;
93 1.1 christos const char *fmt;
94 1.1 christos
95 1.1 christos if (stream->cnt == 0)
96 1.1 christos return 0;
97 1.1 christos assert(stream->off <= stream->cnt);
98 1.1 christos if (stream->off == stream->cnt)
99 1.1 christos return 0;
100 1.1 christos
101 1.1 christos // try to locate natural line break
102 1.1 christos assert(stream->buf[stream->cnt] == '\0');
103 1.1 christos if ((eol = strchr(stream->buf + stream->off, '\n'))) {
104 1.1 christos len = eol - (stream->buf + stream->off);
105 1.1 christos } else {
106 1.1 christos len = stream->cnt - stream->off;
107 1.1 christos }
108 1.1 christos
109 1.1 christos assert(len <= (stream->cnt - stream->off));
110 1.1 christos // wait for buffer to contain a full line except on eof
111 1.1 christos if (len < LOGLINELEN && !eol && !eof)
112 1.1 christos return 0;
113 1.1 christos
114 1.1 christos if (len > LOGLINELEN) {
115 1.1.1.2 christos fmt = stream->cut ? "verifier: .. %.*s .." : "verifier: %.*s ..";
116 1.1 christos len = LOGLINELEN; // remainder printed next iteration
117 1.1 christos stream->cut = 1;
118 1.1 christos } else {
119 1.1.1.2 christos fmt = stream->cut ? "verifier: .. %.*s" : "verifier: %.*s";
120 1.1 christos stream->cut = 0;
121 1.1 christos }
122 1.1 christos log_msg(stream->priority, fmt, len, stream->buf + stream->off);
123 1.1 christos
124 1.1 christos stream->off += len + (eol != NULL);
125 1.1 christos assert(stream->off <= stream->cnt);
126 1.1 christos return len;
127 1.1 christos }
128 1.1 christos
129 1.1 christos /*
130 1.1 christos * Log verifier output on STDOUT and STDERR. Lines longer than LOGLINELEN are
131 1.1 christos * split over multiple lines. Line-breaks are indicated in the log with "...".
132 1.1 christos */
133 1.1 christos static void verify_handle_stream(int fd, short event, void *arg)
134 1.1 christos {
135 1.1 christos int eof = 0;
136 1.1 christos ssize_t cnt;
137 1.1 christos struct verifier *verifier;
138 1.1 christos struct verifier_stream *stream;
139 1.1 christos
140 1.1.1.3 christos assert((event & EV_READ));
141 1.1 christos assert(arg != NULL);
142 1.1 christos
143 1.1 christos verifier = (struct verifier *)arg;
144 1.1 christos if (fd == verifier->output_stream.fd) {
145 1.1 christos stream = &verifier->output_stream;
146 1.1 christos } else {
147 1.1 christos assert(fd == verifier->error_stream.fd);
148 1.1 christos stream = &verifier->error_stream;
149 1.1 christos }
150 1.1 christos
151 1.1 christos assert(stream);
152 1.1 christos assert(stream->fd != -1);
153 1.1 christos
154 1.1 christos do {
155 1.1 christos cnt = fill_buffer(stream);
156 1.1 christos eof = !cnt || (cnt < 0 && errno != EAGAIN && errno != EINTR);
157 1.1 christos while (print_line(stream, eof)) ;
158 1.1 christos } while (cnt > 0);
159 1.1 christos
160 1.1 christos if(eof) {
161 1.1 christos event_del(&stream->event);
162 1.1 christos close(stream->fd);
163 1.1 christos stream->fd = -1;
164 1.1 christos }
165 1.1 christos }
166 1.1 christos
167 1.1 christos static void kill_verifier(struct verifier *verifier)
168 1.1 christos {
169 1.1 christos assert(verifier != NULL);
170 1.1 christos assert(verifier->zone != NULL);
171 1.1 christos
172 1.1 christos if(kill(verifier->pid, SIGTERM) == -1) {
173 1.1 christos log_msg(LOG_ERR, "verify: cannot kill verifier for "
174 1.1 christos "zone %s (pid %d): %s",
175 1.1 christos verifier->zone->opts->name,
176 1.1 christos verifier->pid,
177 1.1 christos strerror(errno));
178 1.1 christos }
179 1.1 christos }
180 1.1 christos
181 1.1 christos static void close_stream(struct verifier *verifier, struct verifier_stream *stream)
182 1.1 christos {
183 1.1 christos if (stream->fd == -1)
184 1.1 christos return;
185 1.1 christos verify_handle_stream(stream->fd, EV_READ, verifier);
186 1.1 christos if (stream->fd == -1)
187 1.1 christos return;
188 1.1 christos event_del(&stream->event);
189 1.1 christos close(stream->fd);
190 1.1 christos stream->fd = -1;
191 1.1 christos }
192 1.1 christos
193 1.1 christos static void close_verifier(struct verifier *verifier)
194 1.1 christos {
195 1.1 christos /* unregister events and close streams (in that order) */
196 1.1 christos if(verifier->timeout.tv_sec > 0) {
197 1.1 christos event_del(&verifier->timeout_event);
198 1.1 christos verifier->timeout.tv_sec = 0;
199 1.1 christos verifier->timeout.tv_usec = 0;
200 1.1 christos }
201 1.1 christos
202 1.1 christos if(verifier->zone_feed.fh != NULL) {
203 1.1 christos event_del(&verifier->zone_feed.event);
204 1.1 christos fclose(verifier->zone_feed.fh);
205 1.1 christos verifier->zone_feed.fh = NULL;
206 1.1 christos region_destroy(verifier->zone_feed.region);
207 1.1 christos }
208 1.1 christos
209 1.1 christos close_stream(verifier, &verifier->error_stream);
210 1.1 christos close_stream(verifier, &verifier->output_stream);
211 1.1 christos
212 1.1 christos verifier->zone->is_ok = verifier->was_ok;
213 1.1 christos verifier->pid = -1;
214 1.1 christos verifier->zone = NULL;
215 1.1 christos }
216 1.1 christos
217 1.1 christos /*
218 1.1 christos * Feed zone to verifier over STDIN as it becomes available.
219 1.1 christos */
220 1.1 christos static void verify_handle_feed(int fd, short event, void *arg)
221 1.1 christos {
222 1.1 christos struct verifier *verifier;
223 1.1 christos struct rr *rr;
224 1.1 christos
225 1.1 christos (void)fd;
226 1.1 christos assert(event == EV_WRITE);
227 1.1 christos assert(arg != NULL);
228 1.1 christos
229 1.1 christos verifier = (struct verifier *)arg;
230 1.1 christos if((rr = zone_rr_iter_next(&verifier->zone_feed.rriter)) != NULL) {
231 1.1 christos print_rr(verifier->zone_feed.fh,
232 1.1 christos verifier->zone_feed.rrprinter,
233 1.1 christos rr,
234 1.1 christos verifier->zone_feed.region,
235 1.1 christos verifier->zone_feed.buffer);
236 1.1 christos } else {
237 1.1 christos event_del(&verifier->zone_feed.event);
238 1.1 christos fclose(verifier->zone_feed.fh);
239 1.1 christos verifier->zone_feed.fh = NULL;
240 1.1 christos region_destroy(verifier->zone_feed.region);
241 1.1 christos }
242 1.1 christos }
243 1.1 christos
244 1.1 christos /*
245 1.1 christos * This handler will be called when a verifier-timeout alarm goes off. It just
246 1.1 christos * kills the verifier. server_verify_zones will make sure the zone will be
247 1.1 christos * considered bad.
248 1.1 christos */
249 1.1 christos void verify_handle_timeout(int fd, short event, void *arg)
250 1.1 christos {
251 1.1 christos struct verifier *verifier;
252 1.1 christos
253 1.1 christos (void)fd;
254 1.1.1.3 christos assert((event & EV_TIMEOUT));
255 1.1 christos assert(arg != NULL);
256 1.1 christos
257 1.1 christos verifier = (struct verifier *)arg;
258 1.1 christos verifier->zone->is_bad = 1;
259 1.1 christos
260 1.1 christos log_msg(LOG_ERR, "verify: verifier for zone %s (pid %d) timed out",
261 1.1 christos verifier->zone->opts->name, verifier->pid);
262 1.1 christos
263 1.1 christos /* kill verifier, process reaped by exit handler */
264 1.1 christos kill_verifier(verifier);
265 1.1 christos }
266 1.1 christos
267 1.1 christos void verify_handle_signal(int sig, short event, void *arg)
268 1.1 christos {
269 1.1 christos char buf[1] = { '\0' };
270 1.1 christos struct nsd *nsd;
271 1.1 christos
272 1.1 christos assert(sig == SIGCHLD);
273 1.1.1.3 christos assert((event & EV_SIGNAL));
274 1.1 christos assert(arg != NULL);
275 1.1 christos
276 1.1 christos nsd = (struct nsd *)arg;
277 1.1.1.2 christos if(write(nsd->verifier_pipe[1], buf, sizeof(buf)) == -1) {
278 1.1.1.2 christos log_msg(LOG_ERR, "verify_handle_signal: write failed: %s",
279 1.1.1.2 christos strerror(errno));
280 1.1.1.2 christos }
281 1.1 christos }
282 1.1 christos
283 1.1 christos /*
284 1.1 christos * Reap process and update status of respective zone based on the exit code
285 1.1 christos * of a verifier. Everything from STDOUT and STDERR still available is read and
286 1.1 christos * written to the log as it might contain valuable information.
287 1.1 christos *
288 1.1 christos * NOTE: A timeout might have caused the verifier to be terminated.
289 1.1 christos */
290 1.1 christos void verify_handle_exit(int fd, short event, void *arg)
291 1.1 christos {
292 1.1 christos int wstatus;
293 1.1 christos pid_t pid;
294 1.1 christos struct nsd *nsd;
295 1.1 christos char buf[1];
296 1.1 christos
297 1.1.1.3 christos assert((event & EV_READ));
298 1.1 christos assert(arg != NULL);
299 1.1 christos
300 1.1 christos nsd = (struct nsd *)arg;
301 1.1 christos
302 1.1.1.2 christos if(read(fd, buf, sizeof(buf)) == -1) {
303 1.1.1.2 christos if(errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK)
304 1.1.1.2 christos log_msg(LOG_ERR, "verify_handle_exit: read failed: %s",
305 1.1.1.2 christos strerror(errno));
306 1.1.1.2 christos }
307 1.1 christos
308 1.1 christos while(((pid = waitpid(-1, &wstatus, WNOHANG)) == -1 && errno == EINTR)
309 1.1 christos || (pid > 0))
310 1.1 christos {
311 1.1 christos struct verifier *verifier = NULL;
312 1.1 christos
313 1.1 christos for(size_t i = 0; !verifier && i < nsd->verifier_limit; i++) {
314 1.1 christos if(nsd->verifiers[i].zone != NULL &&
315 1.1 christos nsd->verifiers[i].pid == pid)
316 1.1 christos {
317 1.1 christos verifier = &nsd->verifiers[i];
318 1.1 christos }
319 1.1 christos }
320 1.1 christos
321 1.1 christos if(verifier == NULL) {
322 1.1 christos continue;
323 1.1 christos }
324 1.1 christos
325 1.1 christos if(!WIFEXITED(wstatus)) {
326 1.1 christos log_msg(LOG_ERR, "verify: verifier for zone %s "
327 1.1 christos "(pid %d) exited abnormally",
328 1.1 christos verifier->zone->opts->name, pid);
329 1.1 christos } else {
330 1.1 christos int priority = LOG_INFO;
331 1.1 christos int status = WEXITSTATUS(wstatus);
332 1.1 christos if(status != 0) {
333 1.1 christos priority = LOG_ERR;
334 1.1 christos verifier->zone->is_bad = 1;
335 1.1 christos }
336 1.1 christos log_msg(priority, "verify: verifier for zone %s "
337 1.1 christos "(pid %d) exited with %d",
338 1.1 christos verifier->zone->opts->name, pid, status);
339 1.1 christos }
340 1.1 christos
341 1.1 christos close_verifier(verifier);
342 1.1 christos nsd->verifier_count--;
343 1.1 christos }
344 1.1 christos
345 1.1 christos while(nsd->mode == NSD_RUN &&
346 1.1 christos nsd->verifier_count < nsd->verifier_limit &&
347 1.1 christos nsd->next_zone_to_verify != NULL)
348 1.1 christos {
349 1.1 christos verify_zone(nsd, nsd->next_zone_to_verify);
350 1.1 christos nsd->next_zone_to_verify
351 1.1 christos = verify_next_zone(nsd, nsd->next_zone_to_verify);
352 1.1 christos }
353 1.1 christos
354 1.1 christos if(nsd->next_zone_to_verify == NULL && nsd->verifier_count == 0) {
355 1.1 christos event_base_loopexit(nsd->event_base, NULL);
356 1.1 christos return;
357 1.1 christos }
358 1.1 christos }
359 1.1 christos
360 1.1 christos /*
361 1.1 christos * A parent may be terminated (by the NSD_QUIT signal (nsdc stop command)).
362 1.1 christos * When a reload server process is running, the parent will then send a
363 1.1 christos * NSD_QUIT command to that server. This handler makes sure that this command
364 1.1 christos * is not neglected and that the reload server process will exit (gracefully).
365 1.1 christos */
366 1.1 christos void
367 1.1 christos verify_handle_command(int fd, short event, void *arg)
368 1.1 christos {
369 1.1 christos struct nsd *nsd = (struct nsd *)arg;
370 1.1 christos int len;
371 1.1 christos sig_atomic_t mode;
372 1.1 christos
373 1.1 christos assert(nsd != NULL);
374 1.1.1.3 christos assert((event & (EV_READ
375 1.1 christos #ifdef EV_CLOSED
376 1.1 christos | EV_CLOSED
377 1.1 christos #endif
378 1.1.1.3 christos )));
379 1.1 christos
380 1.1 christos if((len = read(fd, &mode, sizeof(mode))) == -1) {
381 1.1 christos log_msg(LOG_ERR, "verify: verify_handle_command: read: %s",
382 1.1 christos strerror(errno));
383 1.1 christos return;
384 1.1 christos } else if(len == 0) {
385 1.1 christos log_msg(LOG_INFO, "verify: command channel closed");
386 1.1 christos mode = NSD_QUIT;
387 1.1 christos } else if(mode != NSD_QUIT) {
388 1.1 christos log_msg(LOG_ERR, "verify: bad command: %d", (int)mode);
389 1.1 christos return;
390 1.1 christos }
391 1.1 christos
392 1.1 christos nsd->mode = mode;
393 1.1 christos
394 1.1 christos if(nsd->verifier_count == 0) {
395 1.1 christos event_base_loopexit(nsd->event_base, NULL);
396 1.1 christos return; /* exit early if no verifiers are executing */
397 1.1 christos }
398 1.1 christos
399 1.1 christos /* kill verifiers, processes reaped elsewhere */
400 1.1 christos for(size_t i = 0; i < nsd->verifier_limit; i++) {
401 1.1 christos if(nsd->verifiers[i].zone != NULL) {
402 1.1 christos kill_verifier(&nsd->verifiers[i]);
403 1.1 christos }
404 1.1 christos }
405 1.1 christos }
406 1.1 christos
407 1.1 christos /*
408 1.1 christos * A verifier is executed for the specified zone (if a verifier is configured
409 1.1 christos * and the zone has not been verified before). If one of the verifiers exits
410 1.1 christos * with non-zero, the zone is marked bad and nsd drops the zone update and
411 1.1 christos * reloads again.
412 1.1 christos */
413 1.1 christos void verify_zone(struct nsd *nsd, struct zone *zone)
414 1.1 christos {
415 1.1 christos struct verifier *verifier = NULL;
416 1.1 christos int32_t timeout;
417 1.1 christos char **command;
418 1.1 christos FILE *fin;
419 1.1 christos int fdin, fderr, fdout, flags;
420 1.1 christos
421 1.1 christos assert(nsd != NULL);
422 1.1 christos assert(nsd->verifier_count < nsd->verifier_limit);
423 1.1 christos assert(zone != NULL);
424 1.1 christos
425 1.1 christos fin = NULL;
426 1.1 christos fdin = fdout = fderr = -1;
427 1.1 christos
428 1.1 christos /* search for available verifier slot */
429 1.1 christos for(size_t i = 0; i < nsd->verifier_limit && !verifier; i++) {
430 1.1 christos if(nsd->verifiers[i].zone == NULL) {
431 1.1 christos verifier = &nsd->verifiers[i];
432 1.1 christos }
433 1.1 christos }
434 1.1 christos
435 1.1 christos assert(verifier != NULL);
436 1.1 christos
437 1.1 christos if(zone->opts->pattern->verifier != NULL) {
438 1.1 christos command = zone->opts->pattern->verifier;
439 1.1 christos } else if (nsd->options->verifier != NULL) {
440 1.1 christos command = nsd->options->verifier;
441 1.1 christos } else {
442 1.1 christos log_msg(LOG_ERR, "verify: no verifier for zone %s",
443 1.1 christos zone->opts->name);
444 1.1 christos return;
445 1.1 christos }
446 1.1 christos
447 1.1 christos if(zone->opts->pattern->verifier_timeout
448 1.1 christos != VERIFIER_TIMEOUT_INHERIT)
449 1.1 christos {
450 1.1 christos timeout = zone->opts->pattern->verifier_timeout;
451 1.1 christos } else {
452 1.1 christos timeout = nsd->options->verifier_timeout;
453 1.1 christos }
454 1.1 christos
455 1.1 christos if(zone->opts->pattern->verifier_feed_zone
456 1.1 christos != VERIFIER_FEED_ZONE_INHERIT)
457 1.1 christos {
458 1.1 christos fdin = zone->opts->pattern->verifier_feed_zone ? -2 : -1;
459 1.1 christos } else {
460 1.1 christos fdin = nsd->options->verifier_feed_zone ? -2 : -1;
461 1.1 christos }
462 1.1 christos
463 1.1 christos assert(timeout >= 0);
464 1.1 christos
465 1.1 christos setenv("VERIFY_ZONE", zone->opts->name, 1);
466 1.1 christos setenv("VERIFY_ZONE_ON_STDIN", fdin == -2 ? "yes" : "no", 1);
467 1.1 christos
468 1.1 christos verifier->pid = popen3(
469 1.1 christos command, fdin == -2 ? &fdin : NULL, &fdout, &fderr);
470 1.1 christos if(verifier->pid == -1) {
471 1.1 christos log_msg(LOG_ERR, "verify: could not start verifier for zone "
472 1.1 christos "%s: %s", zone->opts->name, strerror(errno));
473 1.1 christos goto fail_popen3;
474 1.1 christos }
475 1.1 christos flags = fcntl(fderr, F_GETFL, 0);
476 1.1 christos if (fcntl(fderr, F_SETFL, flags | O_NONBLOCK) == -1) {
477 1.1 christos log_msg(LOG_ERR, "verify: fcntl(stderr, ..., O_NONBLOCK) for "
478 1.1 christos "zone %s: %s",
479 1.1 christos zone->opts->name, strerror(errno));
480 1.1 christos goto fail_fcntl;
481 1.1 christos }
482 1.1 christos flags = fcntl(fdout, F_GETFL, 0);
483 1.1 christos if(fcntl(fdout, F_SETFL, flags | O_NONBLOCK) == -1) {
484 1.1 christos log_msg(LOG_ERR, "verify: fcntl(stdout, ..., O_NONBLOCK) for "
485 1.1 christos "zone %s: %s",
486 1.1 christos zone->opts->name, strerror(errno));
487 1.1 christos goto fail_fcntl;
488 1.1 christos }
489 1.1 christos if (fdin >= 0) {
490 1.1 christos if ((fin = fdopen(fdin, "w")) == NULL) {
491 1.1 christos log_msg(LOG_ERR, "verify: fdopen(stdin, ...) for "
492 1.1 christos "zone %s: %s",
493 1.1 christos zone->opts->name, strerror(errno));
494 1.1 christos goto fail_fcntl;
495 1.1 christos }
496 1.1 christos /* write unbuffered */
497 1.1 christos setbuf(fin, NULL);
498 1.1 christos }
499 1.1 christos
500 1.1 christos verifier->zone = zone;
501 1.1 christos verifier->was_ok = zone->is_ok;
502 1.1 christos
503 1.1 christos unsetenv("VERIFY_ZONE");
504 1.1 christos unsetenv("VERIFY_ZONE_ON_STDIN");
505 1.1 christos
506 1.1 christos verifier->error_stream.fd = fderr;
507 1.1 christos verifier->error_stream.cnt = 0;
508 1.1 christos verifier->error_stream.off = 0;
509 1.1 christos verifier->error_stream.buf[0] = '\0';
510 1.1 christos event_set(&verifier->error_stream.event,
511 1.1 christos verifier->error_stream.fd,
512 1.1 christos EV_READ|EV_PERSIST,
513 1.1 christos verify_handle_stream,
514 1.1 christos verifier);
515 1.1 christos event_base_set(nsd->event_base, &verifier->error_stream.event);
516 1.1 christos if(event_add(&verifier->error_stream.event, NULL) != 0) {
517 1.1 christos log_msg(LOG_ERR, "verify: could not add error event for "
518 1.1 christos "zone %s", zone->opts->name);
519 1.1 christos goto fail_stderr;
520 1.1 christos }
521 1.1 christos
522 1.1 christos verifier->output_stream.fd = fdout;
523 1.1 christos verifier->output_stream.cnt = 0;
524 1.1 christos verifier->output_stream.off = 0;
525 1.1 christos verifier->output_stream.buf[0] = '\0';
526 1.1 christos event_set(&verifier->output_stream.event,
527 1.1 christos verifier->output_stream.fd,
528 1.1 christos EV_READ|EV_PERSIST,
529 1.1 christos verify_handle_stream,
530 1.1 christos verifier);
531 1.1 christos event_base_set(nsd->event_base, &verifier->output_stream.event);
532 1.1 christos if(event_add(&verifier->output_stream.event, NULL) != 0) {
533 1.1 christos log_msg(LOG_ERR, "verify: could not add output event for "
534 1.1 christos "zone %s", zone->opts->name);
535 1.1 christos goto fail_stdout;
536 1.1 christos }
537 1.1 christos
538 1.1 christos if(fin != NULL) {
539 1.1 christos verifier->zone_feed.fh = fin;
540 1.1 christos
541 1.1 christos zone_rr_iter_init(&verifier->zone_feed.rriter, zone);
542 1.1 christos
543 1.1 christos verifier->zone_feed.rrprinter
544 1.1 christos = create_pretty_rr(nsd->server_region);
545 1.1 christos verifier->zone_feed.region
546 1.1 christos = region_create(xalloc, free);
547 1.1 christos verifier->zone_feed.buffer
548 1.1 christos = buffer_create(nsd->server_region, MAX_RDLENGTH);
549 1.1 christos
550 1.1 christos event_set(&verifier->zone_feed.event,
551 1.1 christos fileno(verifier->zone_feed.fh),
552 1.1 christos EV_WRITE|EV_PERSIST,
553 1.1 christos &verify_handle_feed,
554 1.1 christos verifier);
555 1.1 christos event_base_set(nsd->event_base, &verifier->zone_feed.event);
556 1.1 christos if(event_add(&verifier->zone_feed.event, NULL) != 0) {
557 1.1 christos log_msg(LOG_ERR, "verify: could not add input event "
558 1.1 christos "for zone %s", zone->opts->name);
559 1.1 christos goto fail_stdin;
560 1.1 christos }
561 1.1 christos }
562 1.1 christos
563 1.1 christos if(timeout > 0) {
564 1.1 christos verifier->timeout.tv_sec = timeout;
565 1.1 christos verifier->timeout.tv_usec = 0;
566 1.1 christos event_set(&verifier->timeout_event,
567 1.1 christos -1,
568 1.1 christos EV_TIMEOUT,
569 1.1 christos verify_handle_timeout,
570 1.1 christos verifier);
571 1.1 christos event_base_set(nsd->event_base, &verifier->timeout_event);
572 1.1 christos if(event_add(&verifier->timeout_event, &verifier->timeout) != 0) {
573 1.1 christos log_msg(LOG_ERR, "verify: could not add timeout event "
574 1.1 christos "for zone %s", zone->opts->name);
575 1.1 christos goto fail_timeout;
576 1.1 christos }
577 1.1 christos
578 1.1 christos log_msg(LOG_INFO, "verify: started verifier for zone %s "
579 1.1 christos "(pid %d), timeout is %d seconds",
580 1.1 christos zone->opts->name, verifier->pid, timeout);
581 1.1 christos } else {
582 1.1 christos log_msg(LOG_INFO, "verify: started verifier for zone %s "
583 1.1 christos "(pid %d)", zone->opts->name, verifier->pid);
584 1.1 christos }
585 1.1 christos
586 1.1 christos zone->is_ok = 1;
587 1.1 christos nsd->verifier_count++;
588 1.1 christos return;
589 1.1 christos
590 1.1 christos fail_timeout:
591 1.1 christos verifier->timeout.tv_sec = 0;
592 1.1 christos verifier->timeout.tv_usec = 0;
593 1.1 christos if(fin != NULL) {
594 1.1 christos event_del(&verifier->zone_feed.event);
595 1.1 christos }
596 1.1 christos fail_stdin:
597 1.1 christos verifier->zone_feed.fh = NULL;
598 1.1 christos event_del(&verifier->output_stream.event);
599 1.1 christos fail_stdout:
600 1.1 christos verifier->output_stream.fd = -1;
601 1.1 christos event_del(&verifier->error_stream.event);
602 1.1 christos fail_stderr:
603 1.1 christos verifier->error_stream.fd = -1;
604 1.1 christos fail_fcntl:
605 1.1 christos kill_verifier(verifier);
606 1.1 christos if(fin != NULL) {
607 1.1 christos fclose(fin);
608 1.1 christos } else if (fdin >= 0) {
609 1.1 christos close(fdin);
610 1.1 christos }
611 1.1 christos close(fdout);
612 1.1 christos close(fderr);
613 1.1 christos fail_popen3:
614 1.1 christos zone->is_bad = 1;
615 1.1 christos verifier->pid = -1;
616 1.1 christos verifier->zone = NULL;
617 1.1 christos }
618