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