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