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