1 /* 2 * ipc.c - Interprocess communication routines. Handlers read and write. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 #include <errno.h> 12 #include <unistd.h> 13 #include <stdlib.h> 14 #include <fcntl.h> 15 #include "ipc.h" 16 #include "buffer.h" 17 #include "xfrd-tcp.h" 18 #include "nsd.h" 19 #include "namedb.h" 20 #include "xfrd.h" 21 #include "xfrd-notify.h" 22 #include "difffile.h" 23 #include "rrl.h" 24 25 /* attempt to send NSD_STATS command to child fd */ 26 static void send_stat_to_child(struct main_ipc_handler_data* data, int fd); 27 /* send reload request over the IPC channel */ 28 static void xfrd_send_reload_req(xfrd_state_type* xfrd); 29 /* send quit request over the IPC channel */ 30 static void xfrd_send_quit_req(xfrd_state_type* xfrd); 31 /* perform read part of handle ipc for xfrd */ 32 static void xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd); 33 static void ipc_child_quit(struct nsd* nsd) ATTR_NORETURN; 34 35 static void 36 ipc_child_quit(struct nsd* nsd) 37 { 38 /* call shutdown and quit routines */ 39 nsd->mode = NSD_QUIT; 40 service_remaining_tcp(nsd); 41 #ifdef BIND8_STATS 42 bind8_stats(nsd); 43 #endif /* BIND8_STATS */ 44 45 #ifdef MEMCLEAN /* OS collects memory pages */ 46 #ifdef RATELIMIT 47 rrl_deinit(nsd->this_child->child_num); 48 #endif 49 event_base_free(nsd->event_base); 50 region_destroy(nsd->server_region); 51 #endif 52 server_shutdown(nsd); 53 exit(0); 54 } 55 56 void 57 child_handle_parent_command(int fd, short event, void* arg) 58 { 59 sig_atomic_t mode; 60 int len; 61 struct ipc_handler_conn_data *data = 62 (struct ipc_handler_conn_data *) arg; 63 if (!(event & EV_READ)) { 64 return; 65 } 66 67 if ((len = read(fd, &mode, sizeof(mode))) == -1) { 68 log_msg(LOG_ERR, "handle_parent_command: read: %s", 69 strerror(errno)); 70 return; 71 } 72 if (len == 0) 73 { 74 /* parent closed the connection. Quit */ 75 ipc_child_quit(data->nsd); 76 return; 77 } 78 79 switch (mode) { 80 case NSD_STATS: 81 data->nsd->mode = mode; 82 break; 83 case NSD_QUIT: 84 ipc_child_quit(data->nsd); 85 break; 86 case NSD_QUIT_CHILD: 87 /* close our listening sockets and ack */ 88 server_close_all_sockets(data->nsd->udp, data->nsd->ifs); 89 server_close_all_sockets(data->nsd->tcp, data->nsd->ifs); 90 /* mode == NSD_QUIT_CHILD */ 91 if(write(fd, &mode, sizeof(mode)) == -1) { 92 VERBOSITY(3, (LOG_INFO, "quit child write: %s", 93 strerror(errno))); 94 } 95 ipc_child_quit(data->nsd); 96 break; 97 case NSD_QUIT_WITH_STATS: 98 #ifdef BIND8_STATS 99 DEBUG(DEBUG_IPC, 2, (LOG_INFO, "quit QUIT_WITH_STATS")); 100 /* reply with ack and stats and then quit */ 101 if(!write_socket(fd, &mode, sizeof(mode))) { 102 log_msg(LOG_ERR, "cannot write quitwst to parent"); 103 } 104 if(!write_socket(fd, &data->nsd->st, sizeof(data->nsd->st))) { 105 log_msg(LOG_ERR, "cannot write stats to parent"); 106 } 107 fsync(fd); 108 #endif /* BIND8_STATS */ 109 ipc_child_quit(data->nsd); 110 break; 111 default: 112 log_msg(LOG_ERR, "handle_parent_command: bad mode %d", 113 (int) mode); 114 break; 115 } 116 } 117 118 void 119 parent_handle_xfrd_command(netio_type *ATTR_UNUSED(netio), 120 netio_handler_type *handler, 121 netio_event_types_type event_types) 122 { 123 sig_atomic_t mode; 124 int len; 125 struct ipc_handler_conn_data *data = 126 (struct ipc_handler_conn_data *) handler->user_data; 127 if (!(event_types & NETIO_EVENT_READ)) { 128 return; 129 } 130 131 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 132 log_msg(LOG_ERR, "handle_xfrd_command: read: %s", 133 strerror(errno)); 134 return; 135 } 136 if (len == 0) 137 { 138 /* xfrd closed, we must quit */ 139 DEBUG(DEBUG_IPC,1, (LOG_INFO, "handle_xfrd_command: xfrd closed channel.")); 140 close(handler->fd); 141 handler->fd = -1; 142 data->nsd->mode = NSD_SHUTDOWN; 143 return; 144 } 145 146 switch (mode) { 147 case NSD_RELOAD: 148 DEBUG(DEBUG_IPC,1, (LOG_INFO, "parent handle xfrd command RELOAD")); 149 data->nsd->signal_hint_reload = 1; 150 break; 151 case NSD_QUIT: 152 case NSD_SHUTDOWN: 153 data->nsd->mode = mode; 154 break; 155 case NSD_STATS: 156 data->nsd->signal_hint_stats = 1; 157 break; 158 case NSD_REAP_CHILDREN: 159 data->nsd->signal_hint_child = 1; 160 break; 161 default: 162 log_msg(LOG_ERR, "handle_xfrd_command: bad mode %d", 163 (int) mode); 164 break; 165 } 166 } 167 168 static void 169 send_stat_to_child(struct main_ipc_handler_data* data, int fd) 170 { 171 sig_atomic_t cmd = NSD_STATS; 172 if(write(fd, &cmd, sizeof(cmd)) == -1) { 173 if(errno == EAGAIN || errno == EINTR) 174 return; /* try again later */ 175 log_msg(LOG_ERR, "svrmain: problems sending stats to child %d command: %s", 176 (int)data->child->pid, strerror(errno)); 177 return; 178 } 179 data->child->need_to_send_STATS = 0; 180 } 181 182 #ifndef NDEBUG 183 int packet_read_query_section(buffer_type *packet, uint8_t* dest, uint16_t* qtype, uint16_t* qclass); 184 static void 185 debug_print_fwd_name(int ATTR_UNUSED(len), buffer_type* packet, int acl_num) 186 { 187 uint8_t qnamebuf[MAXDOMAINLEN]; 188 uint16_t qtype, qclass; 189 const dname_type* dname; 190 region_type* tempregion = region_create(xalloc, free); 191 192 size_t bufpos = buffer_position(packet); 193 buffer_rewind(packet); 194 buffer_skip(packet, 12); 195 if(packet_read_query_section(packet, qnamebuf, &qtype, &qclass)) { 196 dname = dname_make(tempregion, qnamebuf, 1); 197 log_msg(LOG_INFO, "main: fwd packet for %s, acl %d", 198 dname_to_string(dname,0), acl_num); 199 } else { 200 log_msg(LOG_INFO, "main: fwd packet badqname, acl %d", acl_num); 201 } 202 buffer_set_position(packet, bufpos); 203 region_destroy(tempregion); 204 } 205 #endif 206 207 static void 208 send_quit_to_child(struct main_ipc_handler_data* data, int fd) 209 { 210 #ifdef BIND8_STATS 211 sig_atomic_t cmd = NSD_QUIT_WITH_STATS; 212 #else 213 sig_atomic_t cmd = NSD_QUIT; 214 #endif 215 if(write(fd, &cmd, sizeof(cmd)) == -1) { 216 if(errno == EAGAIN || errno == EINTR) 217 return; /* try again later */ 218 log_msg(LOG_ERR, "svrmain: problems sending quit to child %d command: %s", 219 (int)data->child->pid, strerror(errno)); 220 return; 221 } 222 data->child->need_to_send_QUIT = 0; 223 DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: sent quit to child %d", 224 (int)data->child->pid)); 225 } 226 227 /** the child is done, mark it as exited */ 228 static void 229 child_is_done(struct nsd* nsd, int fd) 230 { 231 size_t i; 232 if(fd != -1) close(fd); 233 for(i=0; i<nsd->child_count; ++i) 234 if(nsd->children[i].child_fd == fd) { 235 nsd->children[i].child_fd = -1; 236 nsd->children[i].handler->fd = -1; 237 if(nsd->children[i].need_to_exit) { 238 DEBUG(DEBUG_IPC,1, (LOG_INFO, "server %d is done", 239 (int)nsd->children[i].pid)); 240 nsd->children[i].has_exited = 1; 241 } else { 242 log_msg(LOG_WARNING, 243 "server %d died unexpectedly, restarting", 244 (int)nsd->children[i].pid); 245 /* this child is now going to be re-forked as 246 * a subprocess of this server-main, and if a 247 * reload is in progress the other children 248 * are subprocesses of reload. Until the 249 * reload is done and they are all reforked. */ 250 nsd->children[i].pid = -1; 251 nsd->restart_children = 1; 252 } 253 } 254 parent_check_all_children_exited(nsd); 255 } 256 257 #ifdef BIND8_STATS 258 /** add stats to total */ 259 void 260 stats_add(struct nsdst* total, struct nsdst* s) 261 { 262 unsigned i; 263 for(i=0; i<sizeof(total->qtype)/sizeof(stc_type); i++) 264 total->qtype[i] += s->qtype[i]; 265 for(i=0; i<sizeof(total->qclass)/sizeof(stc_type); i++) 266 total->qclass[i] += s->qclass[i]; 267 total->qudp += s->qudp; 268 total->qudp6 += s->qudp6; 269 total->ctcp += s->ctcp; 270 total->ctcp6 += s->ctcp6; 271 total->ctls += s->ctls; 272 total->ctls6 += s->ctls6; 273 for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++) 274 total->rcode[i] += s->rcode[i]; 275 for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++) 276 total->opcode[i] += s->opcode[i]; 277 total->dropped += s->dropped; 278 total->truncated += s->truncated; 279 total->wrongzone += s->wrongzone; 280 total->txerr += s->txerr; 281 total->rxerr += s->rxerr; 282 total->edns += s->edns; 283 total->ednserr += s->ednserr; 284 total->raxfr += s->raxfr; 285 total->nona += s->nona; 286 287 total->db_disk = s->db_disk; 288 total->db_mem = s->db_mem; 289 } 290 291 /** subtract stats from total */ 292 void 293 stats_subtract(struct nsdst* total, struct nsdst* s) 294 { 295 unsigned i; 296 for(i=0; i<sizeof(total->qtype)/sizeof(stc_type); i++) 297 total->qtype[i] -= s->qtype[i]; 298 for(i=0; i<sizeof(total->qclass)/sizeof(stc_type); i++) 299 total->qclass[i] -= s->qclass[i]; 300 total->qudp -= s->qudp; 301 total->qudp6 -= s->qudp6; 302 total->ctcp -= s->ctcp; 303 total->ctcp6 -= s->ctcp6; 304 total->ctls -= s->ctls; 305 total->ctls6 -= s->ctls6; 306 for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++) 307 total->rcode[i] -= s->rcode[i]; 308 for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++) 309 total->opcode[i] -= s->opcode[i]; 310 total->dropped -= s->dropped; 311 total->truncated -= s->truncated; 312 total->wrongzone -= s->wrongzone; 313 total->txerr -= s->txerr; 314 total->rxerr -= s->rxerr; 315 total->edns -= s->edns; 316 total->ednserr -= s->ednserr; 317 total->raxfr -= s->raxfr; 318 total->nona -= s->nona; 319 } 320 321 #define FINAL_STATS_TIMEOUT 10 /* seconds */ 322 static void 323 read_child_stats(struct nsd* nsd, struct nsd_child* child, int fd) 324 { 325 struct nsdst s; 326 errno=0; 327 if(block_read(nsd, fd, &s, sizeof(s), FINAL_STATS_TIMEOUT)!=sizeof(s)) { 328 log_msg(LOG_ERR, "problems reading finalstats from server " 329 "%d: %s", (int)child->pid, strerror(errno)); 330 } else { 331 stats_add(&nsd->st, &s); 332 child->query_count = s.qudp + s.qudp6 + s.ctcp + s.ctcp6 333 + s.ctls + s.ctls6; 334 /* we know that the child is going to close the connection 335 * now (this is an ACK of the QUIT_W_STATS so we know the 336 * child is done, no longer sending e.g. NOTIFY contents) */ 337 child_is_done(nsd, fd); 338 } 339 } 340 #endif /* BIND8_STATS */ 341 342 void 343 parent_handle_child_command(netio_type *ATTR_UNUSED(netio), 344 netio_handler_type *handler, 345 netio_event_types_type event_types) 346 { 347 sig_atomic_t mode; 348 int len; 349 struct main_ipc_handler_data *data = 350 (struct main_ipc_handler_data*)handler->user_data; 351 352 /* do a nonblocking write to the child if it is ready. */ 353 if (event_types & NETIO_EVENT_WRITE) { 354 if(data->child->need_to_send_STATS && 355 !data->child->need_to_exit) { 356 send_stat_to_child(data, handler->fd); 357 } else if(data->child->need_to_send_QUIT) { 358 send_quit_to_child(data, handler->fd); 359 if(!data->child->need_to_send_QUIT) 360 handler->event_types = NETIO_EVENT_READ; 361 } else { 362 handler->event_types = NETIO_EVENT_READ; 363 } 364 } 365 366 if (!(event_types & NETIO_EVENT_READ)) { 367 return; 368 } 369 370 if (data->forward_mode) { 371 int got_acl; 372 /* forward the data to xfrd */ 373 DEBUG(DEBUG_IPC,2, (LOG_INFO, 374 "main passed packet readup %d", (int)data->got_bytes)); 375 if(data->got_bytes < sizeof(data->total_bytes)) 376 { 377 if ((len = read(handler->fd, 378 (char*)&data->total_bytes+data->got_bytes, 379 sizeof(data->total_bytes)-data->got_bytes)) == -1) { 380 log_msg(LOG_ERR, "handle_child_command: read: %s", 381 strerror(errno)); 382 return; 383 } 384 if(len == 0) { 385 /* EOF */ 386 data->forward_mode = 0; 387 return; 388 } 389 data->got_bytes += len; 390 if(data->got_bytes < sizeof(data->total_bytes)) 391 return; 392 data->total_bytes = ntohs(data->total_bytes); 393 buffer_clear(data->packet); 394 if(data->total_bytes > buffer_capacity(data->packet)) { 395 log_msg(LOG_ERR, "internal error: ipc too large"); 396 exit(1); 397 } 398 return; 399 } 400 /* read the packet */ 401 if(data->got_bytes-sizeof(data->total_bytes) < data->total_bytes) { 402 if((len = read(handler->fd, buffer_current(data->packet), 403 data->total_bytes - (data->got_bytes-sizeof(data->total_bytes)) 404 )) == -1 ) { 405 log_msg(LOG_ERR, "handle_child_command: read: %s", 406 strerror(errno)); 407 return; 408 } 409 if(len == 0) { 410 /* EOF */ 411 data->forward_mode = 0; 412 return; 413 } 414 data->got_bytes += len; 415 buffer_skip(data->packet, len); 416 /* read rest later */ 417 return; 418 } 419 /* read the acl numbers */ 420 got_acl = data->got_bytes - sizeof(data->total_bytes) - data->total_bytes; 421 if((len = read(handler->fd, (char*)&data->acl_num+got_acl, 422 sizeof(data->acl_num)+sizeof(data->acl_xfr)-got_acl)) == -1 ) { 423 log_msg(LOG_ERR, "handle_child_command: read: %s", 424 strerror(errno)); 425 return; 426 } 427 if(len == 0) { 428 /* EOF */ 429 data->forward_mode = 0; 430 return; 431 } 432 got_acl += len; 433 data->got_bytes += len; 434 if(got_acl >= (int)(sizeof(data->acl_num)+sizeof(data->acl_xfr))) { 435 uint16_t len = htons(data->total_bytes); 436 DEBUG(DEBUG_IPC,2, (LOG_INFO, 437 "main fwd passed packet write %d", (int)data->got_bytes)); 438 #ifndef NDEBUG 439 if(nsd_debug_level >= 2) 440 debug_print_fwd_name(len, data->packet, data->acl_num); 441 #endif 442 data->forward_mode = 0; 443 mode = NSD_PASS_TO_XFRD; 444 if(!write_socket(*data->xfrd_sock, &mode, sizeof(mode)) || 445 !write_socket(*data->xfrd_sock, &len, sizeof(len)) || 446 !write_socket(*data->xfrd_sock, buffer_begin(data->packet), 447 data->total_bytes) || 448 !write_socket(*data->xfrd_sock, &data->acl_num, 449 sizeof(data->acl_num)) || 450 !write_socket(*data->xfrd_sock, &data->acl_xfr, 451 sizeof(data->acl_xfr))) { 452 log_msg(LOG_ERR, "error in ipc fwd main2xfrd: %s", 453 strerror(errno)); 454 } 455 } 456 return; 457 } 458 459 /* read command from ipc */ 460 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 461 log_msg(LOG_ERR, "handle_child_command: read: %s", 462 strerror(errno)); 463 return; 464 } 465 if (len == 0) 466 { 467 child_is_done(data->nsd, handler->fd); 468 return; 469 } 470 471 switch (mode) { 472 case NSD_QUIT: 473 data->nsd->mode = mode; 474 break; 475 #ifdef BIND8_STATS 476 case NSD_QUIT_WITH_STATS: 477 read_child_stats(data->nsd, data->child, handler->fd); 478 break; 479 #endif /* BIND8_STATS */ 480 case NSD_STATS: 481 data->nsd->signal_hint_stats = 1; 482 break; 483 case NSD_REAP_CHILDREN: 484 data->nsd->signal_hint_child = 1; 485 break; 486 case NSD_PASS_TO_XFRD: 487 /* set mode for handle_child_command; echo to xfrd. */ 488 data->forward_mode = 1; 489 data->got_bytes = 0; 490 data->total_bytes = 0; 491 break; 492 default: 493 log_msg(LOG_ERR, "handle_child_command: bad mode %d", 494 (int) mode); 495 break; 496 } 497 } 498 499 void 500 parent_check_all_children_exited(struct nsd* nsd) 501 { 502 size_t i; 503 for(i=0; i < nsd->child_count; i++) { 504 if(!nsd->children[i].need_to_exit) 505 return; 506 if(!nsd->children[i].has_exited) 507 return; 508 } 509 nsd->mode = NSD_QUIT_SYNC; 510 DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: all children exited. quit sync.")); 511 } 512 513 void 514 parent_handle_reload_command(netio_type *ATTR_UNUSED(netio), 515 netio_handler_type *handler, 516 netio_event_types_type event_types) 517 { 518 sig_atomic_t mode; 519 int len; 520 size_t i; 521 struct nsd *nsd = (struct nsd*) handler->user_data; 522 if (!(event_types & NETIO_EVENT_READ)) { 523 return; 524 } 525 /* read command from ipc */ 526 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 527 log_msg(LOG_ERR, "handle_reload_command: read: %s", 528 strerror(errno)); 529 return; 530 } 531 if (len == 0) 532 { 533 assert(handler->fd != -1); /* or read() would have failed */ 534 close(handler->fd); 535 handler->fd = -1; 536 537 log_msg(LOG_ERR, "handle_reload_cmd: reload closed cmd channel"); 538 nsd->reload_failed = 1; 539 return; 540 } 541 switch (mode) { 542 case NSD_QUIT_SYNC: 543 /* set all children to exit, only then notify xfrd. */ 544 /* so that buffered packets to pass to xfrd can arrive. */ 545 for(i=0; i < nsd->child_count; i++) { 546 nsd->children[i].need_to_exit = 1; 547 if(nsd->children[i].pid > 0 && 548 nsd->children[i].child_fd != -1) { 549 nsd->children[i].need_to_send_QUIT = 1; 550 nsd->children[i].handler->event_types 551 |= NETIO_EVENT_WRITE; 552 } else { 553 if(nsd->children[i].child_fd == -1) 554 nsd->children[i].has_exited = 1; 555 } 556 } 557 parent_check_all_children_exited(nsd); 558 break; 559 default: 560 log_msg(LOG_ERR, "handle_reload_command: bad mode %d", 561 (int) mode); 562 break; 563 } 564 } 565 566 static void 567 xfrd_send_reload_req(xfrd_state_type* xfrd) 568 { 569 sig_atomic_t req = NSD_RELOAD; 570 uint64_t p = xfrd->last_task->data; 571 udb_ptr_unlink(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 572 task_process_sync(xfrd->nsd->task[xfrd->nsd->mytask]); 573 /* ask server_main for a reload */ 574 if(write(xfrd->ipc_handler.ev_fd, &req, sizeof(req)) == -1) { 575 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 576 udb_ptr_set(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask], p); 577 if(errno == EAGAIN || errno == EINTR) 578 return; /* try again later */ 579 log_msg(LOG_ERR, "xfrd: problems sending reload command: %s", 580 strerror(errno)); 581 return; 582 } 583 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: asked nsd to reload new updates")); 584 /* swapped task to other side, start to use other task udb. */ 585 xfrd->nsd->mytask = 1 - xfrd->nsd->mytask; 586 task_remap(xfrd->nsd->task[xfrd->nsd->mytask]); 587 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 588 assert(udb_base_get_userdata(xfrd->nsd->task[xfrd->nsd->mytask])->data == 0); 589 590 xfrd_prepare_zones_for_reload(); 591 xfrd->reload_cmd_last_sent = xfrd_time(); 592 xfrd->need_to_send_reload = 0; 593 xfrd->can_send_reload = 0; 594 } 595 596 void 597 ipc_xfrd_set_listening(struct xfrd_state* xfrd, short mode) 598 { 599 int fd = xfrd->ipc_handler.ev_fd; 600 struct event_base* base = xfrd->event_base; 601 event_del(&xfrd->ipc_handler); 602 memset(&xfrd->ipc_handler, 0, sizeof(xfrd->ipc_handler)); 603 event_set(&xfrd->ipc_handler, fd, mode, xfrd_handle_ipc, xfrd); 604 if(event_base_set(base, &xfrd->ipc_handler) != 0) 605 log_msg(LOG_ERR, "ipc: cannot set event_base"); 606 /* no timeout for IPC events */ 607 if(event_add(&xfrd->ipc_handler, NULL) != 0) 608 log_msg(LOG_ERR, "ipc: cannot add event"); 609 xfrd->ipc_handler_flags = mode; 610 } 611 612 static void 613 xfrd_send_shutdown_req(xfrd_state_type* xfrd) 614 { 615 sig_atomic_t cmd = NSD_SHUTDOWN; 616 xfrd->ipc_send_blocked = 1; 617 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 618 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send shutdown")); 619 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 620 log_msg(LOG_ERR, "xfrd: error writing shutdown to main: %s", 621 strerror(errno)); 622 } 623 xfrd->need_to_send_shutdown = 0; 624 } 625 626 static void 627 xfrd_send_quit_req(xfrd_state_type* xfrd) 628 { 629 sig_atomic_t cmd = NSD_QUIT; 630 xfrd->ipc_send_blocked = 1; 631 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 632 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send ackreload(quit)")); 633 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 634 log_msg(LOG_ERR, "xfrd: error writing ack to main: %s", 635 strerror(errno)); 636 } 637 xfrd->need_to_send_quit = 0; 638 } 639 640 static void 641 xfrd_send_stats(xfrd_state_type* xfrd) 642 { 643 sig_atomic_t cmd = NSD_STATS; 644 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send stats")); 645 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 646 log_msg(LOG_ERR, "xfrd: error writing stats to main: %s", 647 strerror(errno)); 648 } 649 xfrd->need_to_send_stats = 0; 650 } 651 652 void 653 xfrd_handle_ipc(int ATTR_UNUSED(fd), short event, void* arg) 654 { 655 xfrd_state_type* xfrd = (xfrd_state_type*)arg; 656 if ((event & EV_READ)) 657 { 658 /* first attempt to read as a signal from main 659 * could block further send operations */ 660 xfrd_handle_ipc_read(&xfrd->ipc_handler, xfrd); 661 } 662 if ((event & EV_WRITE)) 663 { 664 if(xfrd->ipc_send_blocked) { /* wait for RELOAD_DONE */ 665 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 666 return; 667 } 668 if(xfrd->need_to_send_shutdown) { 669 xfrd_send_shutdown_req(xfrd); 670 } else if(xfrd->need_to_send_quit) { 671 xfrd_send_quit_req(xfrd); 672 } else if(xfrd->can_send_reload && xfrd->need_to_send_reload) { 673 xfrd_send_reload_req(xfrd); 674 } else if(xfrd->need_to_send_stats) { 675 xfrd_send_stats(xfrd); 676 } 677 if(!(xfrd->can_send_reload && xfrd->need_to_send_reload) && 678 !xfrd->need_to_send_shutdown && 679 !xfrd->need_to_send_quit && 680 !xfrd->need_to_send_stats) { 681 /* disable writing for now */ 682 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 683 } 684 } 685 686 } 687 688 static void 689 xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd) 690 { 691 sig_atomic_t cmd; 692 int len; 693 694 if(xfrd->ipc_conn->is_reading==2) { 695 buffer_type* tmp = xfrd->ipc_pass; 696 uint32_t acl_num; 697 int32_t acl_xfr; 698 /* read acl_num */ 699 int ret = conn_read(xfrd->ipc_conn); 700 if(ret == -1) { 701 log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno)); 702 xfrd->ipc_conn->is_reading = 0; 703 return; 704 } 705 if(ret == 0) 706 return; 707 buffer_flip(xfrd->ipc_conn->packet); 708 xfrd->ipc_pass = xfrd->ipc_conn->packet; 709 xfrd->ipc_conn->packet = tmp; 710 xfrd->ipc_conn->is_reading = 0; 711 acl_num = buffer_read_u32(xfrd->ipc_pass); 712 acl_xfr = (int32_t)buffer_read_u32(xfrd->ipc_pass); 713 xfrd_handle_passed_packet(xfrd->ipc_conn->packet, acl_num, acl_xfr); 714 return; 715 } 716 if(xfrd->ipc_conn->is_reading) { 717 /* reading an IPC message */ 718 buffer_type* tmp; 719 int ret = conn_read(xfrd->ipc_conn); 720 if(ret == -1) { 721 log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno)); 722 xfrd->ipc_conn->is_reading = 0; 723 return; 724 } 725 if(ret == 0) 726 return; 727 buffer_flip(xfrd->ipc_conn->packet); 728 /* use ipc_conn to read remaining data as well */ 729 tmp = xfrd->ipc_pass; 730 xfrd->ipc_conn->is_reading=2; 731 xfrd->ipc_pass = xfrd->ipc_conn->packet; 732 xfrd->ipc_conn->packet = tmp; 733 xfrd->ipc_conn->total_bytes = sizeof(xfrd->ipc_conn->msglen); 734 xfrd->ipc_conn->msglen = 2*sizeof(uint32_t); 735 buffer_clear(xfrd->ipc_conn->packet); 736 buffer_set_limit(xfrd->ipc_conn->packet, xfrd->ipc_conn->msglen); 737 return; 738 } 739 740 if((len = read(handler->ev_fd, &cmd, sizeof(cmd))) == -1) { 741 if(errno != EINTR && errno != EAGAIN) 742 log_msg(LOG_ERR, "xfrd_handle_ipc: read: %s", 743 strerror(errno)); 744 return; 745 } 746 if(len == 0) 747 { 748 /* parent closed the connection. Quit */ 749 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main closed connection.")); 750 xfrd->shutdown = 1; 751 return; 752 } 753 754 switch(cmd) { 755 case NSD_QUIT: 756 case NSD_SHUTDOWN: 757 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main sent shutdown cmd.")); 758 xfrd->shutdown = 1; 759 break; 760 case NSD_RELOAD_DONE: 761 /* reload has finished */ 762 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_DONE")); 763 if(block_read(NULL, handler->ev_fd, &xfrd->reload_pid, 764 sizeof(pid_t), -1) != sizeof(pid_t)) { 765 log_msg(LOG_ERR, "xfrd cannot get reload_pid"); 766 } 767 /* read the not-mytask for the results and soainfo */ 768 xfrd_process_task_result(xfrd, 769 xfrd->nsd->task[1-xfrd->nsd->mytask]); 770 /* reset the IPC, (and the nonblocking ipc write; 771 the new parent does not want half a packet) */ 772 xfrd->can_send_reload = 1; 773 xfrd->ipc_send_blocked = 0; 774 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 775 xfrd_reopen_logfile(); 776 xfrd_check_failed_updates(); 777 break; 778 case NSD_PASS_TO_XFRD: 779 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv PASS_TO_XFRD")); 780 xfrd->ipc_conn->is_reading = 1; 781 break; 782 case NSD_RELOAD_REQ: 783 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_REQ")); 784 /* make reload happen, right away, and schedule file check */ 785 task_new_check_zonefiles(xfrd->nsd->task[xfrd->nsd->mytask], 786 xfrd->last_task, NULL); 787 xfrd_set_reload_now(xfrd); 788 break; 789 case NSD_RELOAD: 790 /* main tells us that reload is done, stop ipc send to main */ 791 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD")); 792 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 793 xfrd->need_to_send_quit = 1; 794 break; 795 default: 796 log_msg(LOG_ERR, "xfrd_handle_ipc: bad mode %d (%d)", (int)cmd, 797 (int)ntohl(cmd)); 798 break; 799 } 800 801 if(xfrd->ipc_conn->is_reading) { 802 /* setup read of info */ 803 xfrd->ipc_conn->total_bytes = 0; 804 xfrd->ipc_conn->msglen = 0; 805 buffer_clear(xfrd->ipc_conn->packet); 806 } 807 } 808