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