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