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