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