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