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