xref: /openbsd/usr.sbin/nsd/ipc.c (revision b71395ea)
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