ipc.c revision 1.11
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); 33static void ipc_child_quit(struct nsd* nsd) ATTR_NORETURN; 34 35static void 36ipc_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 57void 58child_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 119void 120parent_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 169static void 170send_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 184int packet_read_query_section(buffer_type *packet, uint8_t* dest, uint16_t* qtype, uint16_t* qclass); 185static void 186debug_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 208static void 209send_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 */ 229static void 230child_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 */ 260void 261stats_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 total->rixfr += s->rixfr; 288 289 total->db_disk = s->db_disk; 290 total->db_mem = s->db_mem; 291} 292 293/** subtract stats from total */ 294void 295stats_subtract(struct nsdst* total, struct nsdst* s) 296{ 297 unsigned i; 298 for(i=0; i<sizeof(total->qtype)/sizeof(stc_type); i++) 299 total->qtype[i] -= s->qtype[i]; 300 for(i=0; i<sizeof(total->qclass)/sizeof(stc_type); i++) 301 total->qclass[i] -= s->qclass[i]; 302 total->qudp -= s->qudp; 303 total->qudp6 -= s->qudp6; 304 total->ctcp -= s->ctcp; 305 total->ctcp6 -= s->ctcp6; 306 total->ctls -= s->ctls; 307 total->ctls6 -= s->ctls6; 308 for(i=0; i<sizeof(total->rcode)/sizeof(stc_type); i++) 309 total->rcode[i] -= s->rcode[i]; 310 for(i=0; i<sizeof(total->opcode)/sizeof(stc_type); i++) 311 total->opcode[i] -= s->opcode[i]; 312 total->dropped -= s->dropped; 313 total->truncated -= s->truncated; 314 total->wrongzone -= s->wrongzone; 315 total->txerr -= s->txerr; 316 total->rxerr -= s->rxerr; 317 total->edns -= s->edns; 318 total->ednserr -= s->ednserr; 319 total->raxfr -= s->raxfr; 320 total->nona -= s->nona; 321 total->rixfr -= s->rixfr; 322} 323 324#define FINAL_STATS_TIMEOUT 10 /* seconds */ 325static void 326read_child_stats(struct nsd* nsd, struct nsd_child* child, int fd) 327{ 328 struct nsdst s; 329 errno=0; 330 if(block_read(nsd, fd, &s, sizeof(s), FINAL_STATS_TIMEOUT)!=sizeof(s)) { 331 log_msg(LOG_ERR, "problems reading finalstats from server " 332 "%d: %s", (int)child->pid, strerror(errno)); 333 } else { 334 stats_add(&nsd->st, &s); 335 child->query_count = s.qudp + s.qudp6 + s.ctcp + s.ctcp6 336 + s.ctls + s.ctls6; 337 /* we know that the child is going to close the connection 338 * now (this is an ACK of the QUIT_W_STATS so we know the 339 * child is done, no longer sending e.g. NOTIFY contents) */ 340 child_is_done(nsd, fd); 341 } 342} 343#endif /* BIND8_STATS */ 344 345void 346parent_handle_child_command(netio_type *ATTR_UNUSED(netio), 347 netio_handler_type *handler, 348 netio_event_types_type event_types) 349{ 350 sig_atomic_t mode; 351 int len; 352 struct main_ipc_handler_data *data = 353 (struct main_ipc_handler_data*)handler->user_data; 354 355 /* do a nonblocking write to the child if it is ready. */ 356 if (event_types & NETIO_EVENT_WRITE) { 357 if(data->child->need_to_send_STATS && 358 !data->child->need_to_exit) { 359 send_stat_to_child(data, handler->fd); 360 } else if(data->child->need_to_send_QUIT) { 361 send_quit_to_child(data, handler->fd); 362 if(!data->child->need_to_send_QUIT) 363 handler->event_types = NETIO_EVENT_READ; 364 } else { 365 handler->event_types = NETIO_EVENT_READ; 366 } 367 } 368 369 if (!(event_types & NETIO_EVENT_READ)) { 370 return; 371 } 372 373 if (data->forward_mode) { 374 int got_acl; 375 /* forward the data to xfrd */ 376 DEBUG(DEBUG_IPC,2, (LOG_INFO, 377 "main passed packet readup %d", (int)data->got_bytes)); 378 if(data->got_bytes < sizeof(data->total_bytes)) 379 { 380 if ((len = read(handler->fd, 381 (char*)&data->total_bytes+data->got_bytes, 382 sizeof(data->total_bytes)-data->got_bytes)) == -1) { 383 log_msg(LOG_ERR, "handle_child_command: read: %s", 384 strerror(errno)); 385 return; 386 } 387 if(len == 0) { 388 /* EOF */ 389 data->forward_mode = 0; 390 return; 391 } 392 data->got_bytes += len; 393 if(data->got_bytes < sizeof(data->total_bytes)) 394 return; 395 data->total_bytes = ntohs(data->total_bytes); 396 buffer_clear(data->packet); 397 if(data->total_bytes > buffer_capacity(data->packet)) { 398 log_msg(LOG_ERR, "internal error: ipc too large"); 399 exit(1); 400 } 401 return; 402 } 403 /* read the packet */ 404 if(data->got_bytes-sizeof(data->total_bytes) < data->total_bytes) { 405 if((len = read(handler->fd, buffer_current(data->packet), 406 data->total_bytes - (data->got_bytes-sizeof(data->total_bytes)) 407 )) == -1 ) { 408 log_msg(LOG_ERR, "handle_child_command: read: %s", 409 strerror(errno)); 410 return; 411 } 412 if(len == 0) { 413 /* EOF */ 414 data->forward_mode = 0; 415 return; 416 } 417 data->got_bytes += len; 418 buffer_skip(data->packet, len); 419 /* read rest later */ 420 return; 421 } 422 /* read the acl numbers */ 423 got_acl = data->got_bytes - sizeof(data->total_bytes) - data->total_bytes; 424 if((len = read(handler->fd, (char*)&data->acl_num+got_acl, 425 sizeof(data->acl_num)+sizeof(data->acl_xfr)-got_acl)) == -1 ) { 426 log_msg(LOG_ERR, "handle_child_command: read: %s", 427 strerror(errno)); 428 return; 429 } 430 if(len == 0) { 431 /* EOF */ 432 data->forward_mode = 0; 433 return; 434 } 435 got_acl += len; 436 data->got_bytes += len; 437 if(got_acl >= (int)(sizeof(data->acl_num)+sizeof(data->acl_xfr))) { 438 uint16_t len = htons(data->total_bytes); 439 DEBUG(DEBUG_IPC,2, (LOG_INFO, 440 "main fwd passed packet write %d", (int)data->got_bytes)); 441#ifndef NDEBUG 442 if(nsd_debug_level >= 2) 443 debug_print_fwd_name(len, data->packet, data->acl_num); 444#endif 445 data->forward_mode = 0; 446 mode = NSD_PASS_TO_XFRD; 447 if(!write_socket(*data->xfrd_sock, &mode, sizeof(mode)) || 448 !write_socket(*data->xfrd_sock, &len, sizeof(len)) || 449 !write_socket(*data->xfrd_sock, buffer_begin(data->packet), 450 data->total_bytes) || 451 !write_socket(*data->xfrd_sock, &data->acl_num, 452 sizeof(data->acl_num)) || 453 !write_socket(*data->xfrd_sock, &data->acl_xfr, 454 sizeof(data->acl_xfr))) { 455 log_msg(LOG_ERR, "error in ipc fwd main2xfrd: %s", 456 strerror(errno)); 457 } 458 } 459 return; 460 } 461 462 /* read command from ipc */ 463 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 464 log_msg(LOG_ERR, "handle_child_command: read: %s", 465 strerror(errno)); 466 return; 467 } 468 if (len == 0) 469 { 470 child_is_done(data->nsd, handler->fd); 471 return; 472 } 473 474 switch (mode) { 475 case NSD_QUIT: 476 data->nsd->mode = mode; 477 break; 478#ifdef BIND8_STATS 479 case NSD_QUIT_WITH_STATS: 480 read_child_stats(data->nsd, data->child, handler->fd); 481 break; 482#endif /* BIND8_STATS */ 483 case NSD_STATS: 484 data->nsd->signal_hint_stats = 1; 485 break; 486 case NSD_REAP_CHILDREN: 487 data->nsd->signal_hint_child = 1; 488 break; 489 case NSD_PASS_TO_XFRD: 490 /* set mode for handle_child_command; echo to xfrd. */ 491 data->forward_mode = 1; 492 data->got_bytes = 0; 493 data->total_bytes = 0; 494 break; 495 default: 496 log_msg(LOG_ERR, "handle_child_command: bad mode %d", 497 (int) mode); 498 break; 499 } 500} 501 502void 503parent_check_all_children_exited(struct nsd* nsd) 504{ 505 size_t i; 506 for(i=0; i < nsd->child_count; i++) { 507 if(!nsd->children[i].need_to_exit) 508 return; 509 if(!nsd->children[i].has_exited) 510 return; 511 } 512 nsd->mode = NSD_QUIT_SYNC; 513 DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: all children exited. quit sync.")); 514} 515 516void 517parent_handle_reload_command(netio_type *ATTR_UNUSED(netio), 518 netio_handler_type *handler, 519 netio_event_types_type event_types) 520{ 521 sig_atomic_t mode; 522 int len; 523 size_t i; 524 struct nsd *nsd = (struct nsd*) handler->user_data; 525 if (!(event_types & NETIO_EVENT_READ)) { 526 return; 527 } 528 /* read command from ipc */ 529 if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) { 530 log_msg(LOG_ERR, "handle_reload_command: read: %s", 531 strerror(errno)); 532 return; 533 } 534 if (len == 0) 535 { 536 assert(handler->fd != -1); /* or read() would have failed */ 537 close(handler->fd); 538 handler->fd = -1; 539 540 log_msg(LOG_ERR, "handle_reload_cmd: reload closed cmd channel"); 541 nsd->reload_failed = 1; 542 return; 543 } 544 switch (mode) { 545 case NSD_QUIT_SYNC: 546 /* set all children to exit, only then notify xfrd. */ 547 /* so that buffered packets to pass to xfrd can arrive. */ 548 for(i=0; i < nsd->child_count; i++) { 549 nsd->children[i].need_to_exit = 1; 550 if(nsd->children[i].pid > 0 && 551 nsd->children[i].child_fd != -1) { 552 nsd->children[i].need_to_send_QUIT = 1; 553 nsd->children[i].handler->event_types 554 |= NETIO_EVENT_WRITE; 555 } else { 556 if(nsd->children[i].child_fd == -1) 557 nsd->children[i].has_exited = 1; 558 } 559 } 560 parent_check_all_children_exited(nsd); 561 break; 562 default: 563 log_msg(LOG_ERR, "handle_reload_command: bad mode %d", 564 (int) mode); 565 break; 566 } 567} 568 569static void 570xfrd_send_reload_req(xfrd_state_type* xfrd) 571{ 572 sig_atomic_t req = NSD_RELOAD; 573 uint64_t p = xfrd->last_task->data; 574 udb_ptr_unlink(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 575 task_process_sync(xfrd->nsd->task[xfrd->nsd->mytask]); 576 /* ask server_main for a reload */ 577 if(write(xfrd->ipc_handler.ev_fd, &req, sizeof(req)) == -1) { 578 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 579 udb_ptr_set(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask], p); 580 if(errno == EAGAIN || errno == EINTR) 581 return; /* try again later */ 582 log_msg(LOG_ERR, "xfrd: problems sending reload command: %s", 583 strerror(errno)); 584 return; 585 } 586 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: asked nsd to reload new updates")); 587 /* swapped task to other side, start to use other task udb. */ 588 xfrd->nsd->mytask = 1 - xfrd->nsd->mytask; 589 task_remap(xfrd->nsd->task[xfrd->nsd->mytask]); 590 udb_ptr_init(xfrd->last_task, xfrd->nsd->task[xfrd->nsd->mytask]); 591 assert(udb_base_get_userdata(xfrd->nsd->task[xfrd->nsd->mytask])->data == 0); 592 if(!xfrd->reload_cmd_first_sent) 593 xfrd->reload_cmd_first_sent = xfrd_time(); 594 xfrd->reload_cmd_last_sent = xfrd_time(); 595 xfrd->need_to_send_reload = 0; 596 xfrd->can_send_reload = 0; 597} 598 599void 600ipc_xfrd_set_listening(struct xfrd_state* xfrd, short mode) 601{ 602 int fd = xfrd->ipc_handler.ev_fd; 603 struct event_base* base = xfrd->event_base; 604 event_del(&xfrd->ipc_handler); 605 memset(&xfrd->ipc_handler, 0, sizeof(xfrd->ipc_handler)); 606 event_set(&xfrd->ipc_handler, fd, mode, xfrd_handle_ipc, xfrd); 607 if(event_base_set(base, &xfrd->ipc_handler) != 0) 608 log_msg(LOG_ERR, "ipc: cannot set event_base"); 609 /* no timeout for IPC events */ 610 if(event_add(&xfrd->ipc_handler, NULL) != 0) 611 log_msg(LOG_ERR, "ipc: cannot add event"); 612 xfrd->ipc_handler_flags = mode; 613} 614 615static void 616xfrd_send_shutdown_req(xfrd_state_type* xfrd) 617{ 618 sig_atomic_t cmd = NSD_SHUTDOWN; 619 xfrd->ipc_send_blocked = 1; 620 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 621 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send shutdown")); 622 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 623 log_msg(LOG_ERR, "xfrd: error writing shutdown to main: %s", 624 strerror(errno)); 625 } 626 xfrd->need_to_send_shutdown = 0; 627} 628 629static void 630xfrd_send_quit_req(xfrd_state_type* xfrd) 631{ 632 sig_atomic_t cmd = NSD_QUIT; 633 xfrd->ipc_send_blocked = 1; 634 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 635 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send ackreload(quit)")); 636 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 637 log_msg(LOG_ERR, "xfrd: error writing ack to main: %s", 638 strerror(errno)); 639 } 640 xfrd->need_to_send_quit = 0; 641} 642 643static void 644xfrd_send_stats(xfrd_state_type* xfrd) 645{ 646 sig_atomic_t cmd = NSD_STATS; 647 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send stats")); 648 if(!write_socket(xfrd->ipc_handler.ev_fd, &cmd, sizeof(cmd))) { 649 log_msg(LOG_ERR, "xfrd: error writing stats to main: %s", 650 strerror(errno)); 651 } 652 xfrd->need_to_send_stats = 0; 653} 654 655void 656xfrd_handle_ipc(int ATTR_UNUSED(fd), short event, void* arg) 657{ 658 xfrd_state_type* xfrd = (xfrd_state_type*)arg; 659 if ((event & EV_READ)) 660 { 661 /* first attempt to read as a signal from main 662 * could block further send operations */ 663 xfrd_handle_ipc_read(&xfrd->ipc_handler, xfrd); 664 } 665 if ((event & EV_WRITE)) 666 { 667 if(xfrd->ipc_send_blocked) { /* wait for RELOAD_DONE */ 668 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 669 return; 670 } 671 if(xfrd->need_to_send_shutdown) { 672 xfrd_send_shutdown_req(xfrd); 673 } else if(xfrd->need_to_send_quit) { 674 xfrd_send_quit_req(xfrd); 675 } else if(xfrd->can_send_reload && xfrd->need_to_send_reload) { 676 xfrd_send_reload_req(xfrd); 677 } else if(xfrd->need_to_send_stats) { 678 xfrd_send_stats(xfrd); 679 } 680 if(!(xfrd->can_send_reload && xfrd->need_to_send_reload) && 681 !xfrd->need_to_send_shutdown && 682 !xfrd->need_to_send_quit && 683 !xfrd->need_to_send_stats) { 684 /* disable writing for now */ 685 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ); 686 } 687 } 688 689} 690 691static void 692xfrd_handle_ipc_read(struct event* handler, xfrd_state_type* xfrd) 693{ 694 sig_atomic_t cmd; 695 int len; 696 697 if(xfrd->ipc_conn->is_reading==2) { 698 buffer_type* tmp = xfrd->ipc_pass; 699 uint32_t acl_num; 700 int32_t acl_xfr; 701 /* read acl_num */ 702 int ret = conn_read(xfrd->ipc_conn); 703 if(ret == -1) { 704 log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno)); 705 xfrd->ipc_conn->is_reading = 0; 706 return; 707 } 708 if(ret == 0) 709 return; 710 buffer_flip(xfrd->ipc_conn->packet); 711 xfrd->ipc_pass = xfrd->ipc_conn->packet; 712 xfrd->ipc_conn->packet = tmp; 713 xfrd->ipc_conn->is_reading = 0; 714 acl_num = buffer_read_u32(xfrd->ipc_pass); 715 acl_xfr = (int32_t)buffer_read_u32(xfrd->ipc_pass); 716 xfrd_handle_passed_packet(xfrd->ipc_conn->packet, acl_num, acl_xfr); 717 return; 718 } 719 if(xfrd->ipc_conn->is_reading) { 720 /* reading an IPC message */ 721 buffer_type* tmp; 722 int ret = conn_read(xfrd->ipc_conn); 723 if(ret == -1) { 724 log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno)); 725 xfrd->ipc_conn->is_reading = 0; 726 return; 727 } 728 if(ret == 0) 729 return; 730 buffer_flip(xfrd->ipc_conn->packet); 731 /* use ipc_conn to read remaining data as well */ 732 tmp = xfrd->ipc_pass; 733 xfrd->ipc_conn->is_reading=2; 734 xfrd->ipc_pass = xfrd->ipc_conn->packet; 735 xfrd->ipc_conn->packet = tmp; 736 xfrd->ipc_conn->total_bytes = sizeof(xfrd->ipc_conn->msglen); 737 xfrd->ipc_conn->msglen = 2*sizeof(uint32_t); 738 buffer_clear(xfrd->ipc_conn->packet); 739 buffer_set_limit(xfrd->ipc_conn->packet, xfrd->ipc_conn->msglen); 740 return; 741 } 742 743 if((len = read(handler->ev_fd, &cmd, sizeof(cmd))) == -1) { 744 if(errno != EINTR && errno != EAGAIN) 745 log_msg(LOG_ERR, "xfrd_handle_ipc: read: %s", 746 strerror(errno)); 747 return; 748 } 749 if(len == 0) 750 { 751 /* parent closed the connection. Quit */ 752 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main closed connection.")); 753 xfrd->shutdown = 1; 754 return; 755 } 756 757 switch(cmd) { 758 case NSD_QUIT: 759 case NSD_SHUTDOWN: 760 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main sent shutdown cmd.")); 761 xfrd->shutdown = 1; 762 break; 763 case NSD_RELOAD_FAILED: 764 xfrd->reload_failed = 1; 765 /* fall through */ 766 case NSD_RELOAD_DONE: 767 /* reload has finished */ 768 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv %s", 769 xfrd->reload_failed ? "RELOAD FAILED" : "RELOAD DONE")); 770 if(block_read(NULL, handler->ev_fd, &xfrd->reload_pid, 771 sizeof(pid_t), -1) != sizeof(pid_t)) { 772 log_msg(LOG_ERR, "xfrd cannot get reload_pid"); 773 } 774 /* read the not-mytask for the results and soainfo */ 775 xfrd_process_task_result(xfrd, 776 xfrd->nsd->task[1-xfrd->nsd->mytask]); 777 /* reset the IPC, (and the nonblocking ipc write; 778 the new parent does not want half a packet) */ 779 xfrd->can_send_reload = 1; 780 xfrd->ipc_send_blocked = 0; 781 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 782 xfrd_reopen_logfile(); 783 if(!xfrd->reload_failed) { 784 xfrd_check_failed_updates(); 785 xfrd->reload_cmd_first_sent = 0; 786 } else { 787 /* make reload happen again, right away */ 788 xfrd_set_reload_now(xfrd); 789 } 790 xfrd_prepare_zones_for_reload(); 791 xfrd->reload_failed = 0; 792 break; 793 case NSD_PASS_TO_XFRD: 794 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv PASS_TO_XFRD")); 795 xfrd->ipc_conn->is_reading = 1; 796 break; 797 case NSD_RELOAD_REQ: 798 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD_REQ")); 799 /* make reload happen, right away, and schedule file check */ 800 task_new_check_zonefiles(xfrd->nsd->task[xfrd->nsd->mytask], 801 xfrd->last_task, NULL); 802 xfrd_set_reload_now(xfrd); 803 break; 804 case NSD_RELOAD: 805 /* main tells us that reload is done, stop ipc send to main */ 806 DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD")); 807 ipc_xfrd_set_listening(xfrd, EV_PERSIST|EV_READ|EV_WRITE); 808 xfrd->need_to_send_quit = 1; 809 break; 810 default: 811 log_msg(LOG_ERR, "xfrd_handle_ipc: bad mode %d (%d)", (int)cmd, 812 (int)ntohl(cmd)); 813 break; 814 } 815 816 if(xfrd->ipc_conn->is_reading) { 817 /* setup read of info */ 818 xfrd->ipc_conn->total_bytes = 0; 819 xfrd->ipc_conn->msglen = 0; 820 buffer_clear(xfrd->ipc_conn->packet); 821 } 822} 823