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