xref: /openbsd-src/usr.sbin/nsd/ipc.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*
2  * ipc.c - Interprocess communication routines. Handlers read and write.
3  *
4  * Copyright (c) 2001-2011, 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 "ipc.h"
15 #include "buffer.h"
16 #include "xfrd-tcp.h"
17 #include "nsd.h"
18 #include "namedb.h"
19 #include "xfrd.h"
20 #include "xfrd-notify.h"
21 
22 /* set is_ok for the zone according to the zone message */
23 static zone_type* handle_xfrd_zone_state(struct nsd* nsd, buffer_type* packet);
24 /* write ipc ZONE_STATE message into the buffer */
25 static void write_zone_state_packet(buffer_type* packet, zone_type* zone);
26 /* attempt to send NSD_STATS command to child fd */
27 static void send_stat_to_child(struct main_ipc_handler_data* data, int fd);
28 /* write IPC expire notification msg to a buffer */
29 static void xfrd_write_expire_notification(buffer_type* buffer, xfrd_zone_t* zone);
30 /* send reload request over the IPC channel */
31 static void xfrd_send_reload_req(xfrd_state_t* xfrd);
32 /* send quit request over the IPC channel */
33 static void xfrd_send_quit_req(xfrd_state_t* xfrd);
34 /* get SOA INFO out of IPC packet buffer */
35 static void xfrd_handle_ipc_SOAINFO(xfrd_state_t* xfrd, buffer_type* packet);
36 /* perform read part of handle ipc for xfrd */
37 static void xfrd_handle_ipc_read(netio_handler_type *handler, xfrd_state_t* xfrd);
38 
39 static zone_type*
40 handle_xfrd_zone_state(struct nsd* nsd, buffer_type* packet)
41 {
42 	uint8_t ok;
43 	const dname_type *dname;
44 	domain_type *domain;
45 	zone_type *zone;
46 
47 	ok = buffer_read_u8(packet);
48 	dname = (dname_type*)buffer_current(packet);
49 	DEBUG(DEBUG_IPC,1, (LOG_INFO, "handler zone state %s is %s",
50 		dname_to_string(dname, NULL), ok?"ok":"expired"));
51 	/* find in zone_types, if does not exist, we cannot serve anyway */
52 	/* find zone in config, since that one always exists */
53 	domain = domain_table_find(nsd->db->domains, dname);
54 	if(!domain) {
55 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "zone state msg, empty zone (domain %s)",
56 			dname_to_string(dname, NULL)));
57 		return NULL;
58 	}
59 	zone = domain_find_zone(domain);
60 	if(!zone || dname_compare(domain_dname(zone->apex), dname) != 0) {
61 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "zone state msg, empty zone (zone %s)",
62 			dname_to_string(dname, NULL)));
63 		return NULL;
64 	}
65 	assert(zone);
66 	/* only update zone->is_ok if needed to minimize copy-on-write
67 	   of memory pages shared after fork() */
68 	if(ok && !zone->is_ok)
69 		zone->is_ok = 1;
70 	if(!ok && zone->is_ok)
71 		zone->is_ok = 0;
72 	return zone;
73 }
74 
75 void
76 child_handle_parent_command(netio_type *ATTR_UNUSED(netio),
77 		      netio_handler_type *handler,
78 		      netio_event_types_type event_types)
79 {
80 	sig_atomic_t mode;
81 	int len;
82 	struct ipc_handler_conn_data *data =
83 		(struct ipc_handler_conn_data *) handler->user_data;
84 	if (!(event_types & NETIO_EVENT_READ)) {
85 		return;
86 	}
87 
88 	if(data->conn->is_reading) {
89 		int ret = conn_read(data->conn);
90 		if(ret == -1) {
91 			log_msg(LOG_ERR, "handle_parent_command: error in conn_read: %s",
92 				strerror(errno));
93 			data->conn->is_reading = 0;
94 			return;
95 		}
96 		if(ret == 0) {
97 			return; /* continue later */
98 		}
99 		/* completed */
100 		data->conn->is_reading = 0;
101 		buffer_flip(data->conn->packet);
102 		(void)handle_xfrd_zone_state(data->nsd, data->conn->packet);
103 		return;
104 	}
105 
106 	if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) {
107 		log_msg(LOG_ERR, "handle_parent_command: read: %s",
108 			strerror(errno));
109 		return;
110 	}
111 	if (len == 0)
112 	{
113 		/* parent closed the connection. Quit */
114 		data->nsd->mode = NSD_QUIT;
115 		return;
116 	}
117 
118 	switch (mode) {
119 	case NSD_STATS:
120 	case NSD_QUIT:
121 		data->nsd->mode = mode;
122 		break;
123 	case NSD_ZONE_STATE:
124 		data->conn->is_reading = 1;
125 		data->conn->total_bytes = 0;
126 		data->conn->msglen = 0;
127 		data->conn->fd = handler->fd;
128 		buffer_clear(data->conn->packet);
129 		break;
130 	default:
131 		log_msg(LOG_ERR, "handle_parent_command: bad mode %d",
132 			(int) mode);
133 		break;
134 	}
135 }
136 
137 void
138 parent_handle_xfrd_command(netio_type *ATTR_UNUSED(netio),
139 		      netio_handler_type *handler,
140 		      netio_event_types_type event_types)
141 {
142 	sig_atomic_t mode;
143 	int len;
144 	struct ipc_handler_conn_data *data =
145 		(struct ipc_handler_conn_data *) handler->user_data;
146 	if (!(event_types & NETIO_EVENT_READ)) {
147 		return;
148 	}
149 
150 	if(data->conn->is_reading) {
151 		/* handle ZONE_STATE forward to children */
152 		int ret = conn_read(data->conn);
153 		size_t i;
154 		zone_type* zone;
155 		if(ret == -1) {
156 			log_msg(LOG_ERR, "main xfrd listener: error in conn_read: %s",
157 				strerror(errno));
158 			data->conn->is_reading = 0;
159 			return;
160 		}
161 		if(ret == 0) {
162 			return; /* continue later */
163 		}
164 		/* completed */
165 		data->conn->is_reading = 0;
166 		buffer_flip(data->conn->packet);
167 		zone = handle_xfrd_zone_state(data->nsd, data->conn->packet);
168 		if(!zone)
169 			return;
170 		/* forward to all children */
171 		for (i = 0; i < data->nsd->child_count; ++i) {
172 			if(!zone->dirty[i]) {
173 				zone->dirty[i] = 1;
174 				stack_push(data->nsd->children[i].dirty_zones, zone);
175 				data->nsd->children[i].handler->event_types |=
176 					NETIO_EVENT_WRITE;
177 			}
178 		}
179 		return;
180 	}
181 
182 	if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) {
183 		log_msg(LOG_ERR, "handle_xfrd_command: read: %s",
184 			strerror(errno));
185 		return;
186 	}
187 	if (len == 0)
188 	{
189 		DEBUG(DEBUG_IPC,1, (LOG_ERR, "handle_xfrd_command: xfrd closed channel."));
190 		close(handler->fd);
191 		handler->fd = -1;
192 		return;
193 	}
194 
195 	switch (mode) {
196 	case NSD_RELOAD:
197 		data->nsd->signal_hint_reload = 1;
198 		break;
199 	case NSD_QUIT:
200 		data->nsd->mode = mode;
201 		break;
202 	case NSD_REAP_CHILDREN:
203 		data->nsd->signal_hint_child = 1;
204 		break;
205 	case NSD_ZONE_STATE:
206 		data->conn->is_reading = 1;
207 		data->conn->total_bytes = 0;
208 		data->conn->msglen = 0;
209 		data->conn->fd = handler->fd;
210 		buffer_clear(data->conn->packet);
211 		break;
212 	default:
213 		log_msg(LOG_ERR, "handle_xfrd_command: bad mode %d",
214 			(int) mode);
215 		break;
216 	}
217 }
218 
219 static void
220 write_zone_state_packet(buffer_type* packet, zone_type* zone)
221 {
222 	sig_atomic_t cmd = NSD_ZONE_STATE;
223 	uint8_t ok = zone->is_ok;
224 	uint16_t sz;
225 	if(!zone->apex) {
226 		return;
227 	}
228 	sz = dname_total_size(domain_dname(zone->apex)) + 1;
229 	sz = htons(sz);
230 
231 	buffer_clear(packet);
232 	buffer_write(packet, &cmd, sizeof(cmd));
233 	buffer_write(packet, &sz, sizeof(sz));
234 	buffer_write(packet, &ok, sizeof(ok));
235 	buffer_write(packet, domain_dname(zone->apex),
236 		dname_total_size(domain_dname(zone->apex)));
237 	buffer_flip(packet);
238 }
239 
240 static void
241 send_stat_to_child(struct main_ipc_handler_data* data, int fd)
242 {
243 	sig_atomic_t cmd = NSD_STATS;
244 	if(write(fd, &cmd, sizeof(cmd)) == -1) {
245 		if(errno == EAGAIN || errno == EINTR)
246 			return; /* try again later */
247 		log_msg(LOG_ERR, "svrmain: problems sending stats to child %d command: %s",
248 			(int)data->child->pid, strerror(errno));
249 		return;
250 	}
251 	data->child->need_to_send_STATS = 0;
252 }
253 
254 int packet_read_query_section(buffer_type *packet, uint8_t* dest, uint16_t* qtype, uint16_t* qclass);
255 static void
256 debug_print_fwd_name(int ATTR_UNUSED(len), buffer_type* packet, int acl_num)
257 {
258 	uint8_t qnamebuf[MAXDOMAINLEN];
259 	uint16_t qtype, qclass;
260 	const dname_type* dname;
261 	region_type* tempregion = region_create(xalloc, free);
262 
263 	size_t bufpos = buffer_position(packet);
264 	buffer_rewind(packet);
265 	buffer_skip(packet, 12);
266 	if(packet_read_query_section(packet, qnamebuf, &qtype, &qclass)) {
267 		dname = dname_make(tempregion, qnamebuf, 1);
268 		log_msg(LOG_INFO, "main: fwd packet for %s, acl %d",
269 			dname_to_string(dname,0), acl_num);
270 	} else {
271 		log_msg(LOG_INFO, "main: fwd packet badqname, acl %d", acl_num);
272 	}
273 	buffer_set_position(packet, bufpos);
274 	region_destroy(tempregion);
275 }
276 
277 static void
278 send_quit_to_child(struct main_ipc_handler_data* data, int fd)
279 {
280 	sig_atomic_t cmd = NSD_QUIT;
281 	if(write(fd, &cmd, sizeof(cmd)) == -1) {
282 		if(errno == EAGAIN || errno == EINTR)
283 			return; /* try again later */
284 		log_msg(LOG_ERR, "svrmain: problems sending quit to child %d command: %s",
285 			(int)data->child->pid, strerror(errno));
286 		return;
287 	}
288 	data->child->need_to_send_QUIT = 0;
289 	DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: sent quit to child %d",
290 		(int)data->child->pid));
291 }
292 
293 void
294 parent_handle_child_command(netio_type *ATTR_UNUSED(netio),
295 		      netio_handler_type *handler,
296 		      netio_event_types_type event_types)
297 {
298 	sig_atomic_t mode;
299 	int len;
300 	struct main_ipc_handler_data *data =
301 		(struct main_ipc_handler_data*)handler->user_data;
302 
303 	/* do a nonblocking write to the child if it is ready. */
304 	if (event_types & NETIO_EVENT_WRITE) {
305 		if(!data->busy_writing_zone_state &&
306 			!data->child->need_to_send_STATS &&
307 			!data->child->need_to_send_QUIT &&
308 			!data->child->need_to_exit &&
309 			data->child->dirty_zones->num > 0) {
310 			/* create packet from next dirty zone */
311 			zone_type* zone = (zone_type*)stack_pop(data->child->dirty_zones);
312 			assert(zone);
313 			zone->dirty[data->child_num] = 0;
314 			data->busy_writing_zone_state = 1;
315 			write_zone_state_packet(data->write_conn->packet, zone);
316 			data->write_conn->msglen = buffer_limit(data->write_conn->packet);
317 			data->write_conn->total_bytes = sizeof(uint16_t); /* len bytes already in packet */
318 			data->write_conn->fd = handler->fd;
319 		}
320 		if(data->busy_writing_zone_state) {
321 			/* write more of packet */
322 			int ret = conn_write(data->write_conn);
323 			if(ret == -1) {
324 				log_msg(LOG_ERR, "handle_child_cmd %d: could not write: %s",
325 					(int)data->child->pid, strerror(errno));
326 				data->busy_writing_zone_state = 0;
327 			} else if(ret == 1) {
328 				data->busy_writing_zone_state = 0; /* completed */
329 			}
330 		} else if(data->child->need_to_send_STATS &&
331 			  !data->child->need_to_exit) {
332 			send_stat_to_child(data, handler->fd);
333 		} else if(data->child->need_to_send_QUIT) {
334 			send_quit_to_child(data, handler->fd);
335 			if(!data->child->need_to_send_QUIT)
336 				handler->event_types = NETIO_EVENT_READ;
337 		}
338 		if(!data->busy_writing_zone_state &&
339 			!data->child->need_to_send_STATS &&
340 			!data->child->need_to_send_QUIT &&
341 			data->child->dirty_zones->num == 0) {
342 			handler->event_types = NETIO_EVENT_READ;
343 		}
344 	}
345 
346 	if (!(event_types & NETIO_EVENT_READ)) {
347 		return;
348 	}
349 
350 	if (data->forward_mode) {
351 		int got_acl;
352 		/* forward the data to xfrd */
353 		DEBUG(DEBUG_IPC,2, (LOG_INFO,
354 			"main passed packet readup %d", (int)data->got_bytes));
355 		if(data->got_bytes < sizeof(data->total_bytes))
356 		{
357 			if ((len = read(handler->fd,
358 				(char*)&data->total_bytes+data->got_bytes,
359 				sizeof(data->total_bytes)-data->got_bytes)) == -1) {
360 				log_msg(LOG_ERR, "handle_child_command: read: %s",
361 					strerror(errno));
362 				return;
363 			}
364 			if(len == 0) {
365 				/* EOF */
366 				data->forward_mode = 0;
367 				return;
368 			}
369 			data->got_bytes += len;
370 			if(data->got_bytes < sizeof(data->total_bytes))
371 				return;
372 			data->total_bytes = ntohs(data->total_bytes);
373 			buffer_clear(data->packet);
374 			if(data->total_bytes > buffer_capacity(data->packet)) {
375 				log_msg(LOG_ERR, "internal error: ipc too large");
376 				exit(1);
377 			}
378 			return;
379 		}
380 		/* read the packet */
381 		if(data->got_bytes-sizeof(data->total_bytes) < data->total_bytes) {
382 			if((len = read(handler->fd, buffer_current(data->packet),
383 				data->total_bytes - (data->got_bytes-sizeof(data->total_bytes))
384 				)) == -1 ) {
385 				log_msg(LOG_ERR, "handle_child_command: read: %s",
386 					strerror(errno));
387 				return;
388 			}
389 			if(len == 0) {
390 				/* EOF */
391 				data->forward_mode = 0;
392 				return;
393 			}
394 			data->got_bytes += len;
395 			buffer_skip(data->packet, len);
396 			/* read rest later */
397 			return;
398 		}
399 		/* read the acl number */
400 		got_acl = data->got_bytes - sizeof(data->total_bytes) - data->total_bytes;
401 		if((len = read(handler->fd, (char*)&data->acl_num+got_acl,
402 			sizeof(data->acl_num)-got_acl)) == -1 ) {
403 			log_msg(LOG_ERR, "handle_child_command: read: %s",
404 				strerror(errno));
405 			return;
406 		}
407 		if(len == 0) {
408 			/* EOF */
409 			data->forward_mode = 0;
410 			return;
411 		}
412 		got_acl += len;
413 		data->got_bytes += len;
414 		if(got_acl >= (int)sizeof(data->acl_num)) {
415 			uint16_t len = htons(data->total_bytes);
416 			DEBUG(DEBUG_IPC,2, (LOG_INFO,
417 				"main fwd passed packet write %d", (int)data->got_bytes));
418 #ifndef NDEBUG
419 			if(nsd_debug_level >= 2)
420 				debug_print_fwd_name(len, data->packet, data->acl_num);
421 #endif
422 			data->forward_mode = 0;
423 			mode = NSD_PASS_TO_XFRD;
424 			if(!write_socket(*data->xfrd_sock, &mode, sizeof(mode)) ||
425 			   !write_socket(*data->xfrd_sock, &len, sizeof(len)) ||
426 			   !write_socket(*data->xfrd_sock, buffer_begin(data->packet),
427 				data->total_bytes) ||
428 			   !write_socket(*data->xfrd_sock, &data->acl_num,
429 			   	sizeof(data->acl_num))) {
430 				log_msg(LOG_ERR, "error in ipc fwd main2xfrd: %s",
431 					strerror(errno));
432 			}
433 		}
434 		return;
435 	}
436 
437 	/* read command from ipc */
438 	if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) {
439 		log_msg(LOG_ERR, "handle_child_command: read: %s",
440 			strerror(errno));
441 		return;
442 	}
443 	if (len == 0)
444 	{
445 		size_t i;
446 		if(handler->fd > 0) close(handler->fd);
447 		for(i=0; i<data->nsd->child_count; ++i)
448 			if(data->nsd->children[i].child_fd == handler->fd) {
449 				data->nsd->children[i].child_fd = -1;
450 				data->nsd->children[i].has_exited = 1;
451 				DEBUG(DEBUG_IPC,1, (LOG_INFO,
452 					"server %d closed cmd channel",
453 					(int) data->nsd->children[i].pid));
454 			}
455 		handler->fd = -1;
456 		parent_check_all_children_exited(data->nsd);
457 		return;
458 	}
459 
460 	switch (mode) {
461 	case NSD_QUIT:
462 		data->nsd->mode = mode;
463 		break;
464 	case NSD_STATS:
465 		data->nsd->signal_hint_stats = 1;
466 		break;
467 	case NSD_REAP_CHILDREN:
468 		data->nsd->signal_hint_child = 1;
469 		break;
470 	case NSD_PASS_TO_XFRD:
471 		/* set mode for handle_child_command; echo to xfrd. */
472 		data->forward_mode = 1;
473 		data->got_bytes = 0;
474 		data->total_bytes = 0;
475 		break;
476 	default:
477 		log_msg(LOG_ERR, "handle_child_command: bad mode %d",
478 			(int) mode);
479 		break;
480 	}
481 }
482 
483 void
484 parent_check_all_children_exited(struct nsd* nsd)
485 {
486 	size_t i;
487 	for(i=0; i < nsd->child_count; i++) {
488 		if(!nsd->children[i].need_to_exit)
489 		      return;
490 		if(!nsd->children[i].has_exited)
491 		      return;
492 	}
493 	nsd->mode = NSD_QUIT_SYNC;
494 	DEBUG(DEBUG_IPC,2, (LOG_INFO, "main: all children exited. quit sync."));
495 }
496 
497 void
498 parent_handle_reload_command(netio_type *ATTR_UNUSED(netio),
499 		      netio_handler_type *handler,
500 		      netio_event_types_type event_types)
501 {
502 	sig_atomic_t mode;
503 	int len;
504 	size_t i;
505 	struct nsd *nsd = (struct nsd*) handler->user_data;
506 	if (!(event_types & NETIO_EVENT_READ)) {
507 		return;
508 	}
509 	/* read command from ipc */
510 	if ((len = read(handler->fd, &mode, sizeof(mode))) == -1) {
511 		log_msg(LOG_ERR, "handle_reload_command: read: %s",
512 			strerror(errno));
513 		return;
514 	}
515 	if (len == 0)
516 	{
517 		if(handler->fd > 0) {
518 			close(handler->fd);
519 			handler->fd = -1;
520 		}
521 		log_msg(LOG_ERR, "handle_reload_cmd: reload closed cmd channel");
522 		return;
523 	}
524 	switch (mode) {
525 	case NSD_QUIT_SYNC:
526 		/* set all children to exit, only then notify xfrd. */
527 		/* so that buffered packets to pass to xfrd can arrive. */
528 		for(i=0; i < nsd->child_count; i++) {
529 			nsd->children[i].need_to_exit = 1;
530 			if(nsd->children[i].pid > 0 &&
531 			   nsd->children[i].child_fd > 0) {
532 				nsd->children[i].need_to_send_QUIT = 1;
533 				nsd->children[i].handler->event_types
534 					|= NETIO_EVENT_WRITE;
535 			} else {
536 				if(nsd->children[i].child_fd == -1)
537 					nsd->children[i].has_exited = 1;
538 			}
539 		}
540 		parent_check_all_children_exited(nsd);
541 		break;
542 	default:
543 		log_msg(LOG_ERR, "handle_reload_command: bad mode %d",
544 			(int) mode);
545 		break;
546 	}
547 }
548 
549 static void
550 xfrd_write_expire_notification(buffer_type* buffer, xfrd_zone_t* zone)
551 {
552 	sig_atomic_t cmd = NSD_ZONE_STATE;
553 	uint8_t ok = 1;
554 	uint16_t sz = dname_total_size(zone->apex) + 1;
555 	sz = htons(sz);
556 	if(zone->state == xfrd_zone_expired)
557 		ok = 0;
558 
559 	DEBUG(DEBUG_IPC,1, (LOG_INFO,
560 		"xfrd encoding ipc zone state msg for zone %s state %d.",
561 		zone->apex_str, (int)zone->state));
562 
563 	buffer_clear(buffer);
564 	buffer_write(buffer, &cmd, sizeof(cmd));
565 	buffer_write(buffer, &sz, sizeof(sz));
566 	buffer_write(buffer, &ok, sizeof(ok));
567 	buffer_write(buffer, zone->apex, dname_total_size(zone->apex));
568 	buffer_flip(buffer);
569 }
570 
571 static void
572 xfrd_send_reload_req(xfrd_state_t* xfrd)
573 {
574 	sig_atomic_t req = NSD_RELOAD;
575 	/* ask server_main for a reload */
576 	if(write(xfrd->ipc_handler.fd, &req, sizeof(req)) == -1) {
577 		if(errno == EAGAIN || errno == EINTR)
578 			return; /* try again later */
579 		log_msg(LOG_ERR, "xfrd: problems sending reload command: %s",
580 			strerror(errno));
581 		return;
582 	}
583 	DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: asked nsd to reload new updates"));
584 	xfrd_prepare_zones_for_reload();
585 	xfrd->reload_cmd_last_sent = xfrd_time();
586 	xfrd->need_to_send_reload = 0;
587 	xfrd->can_send_reload = 0;
588 }
589 
590 static void
591 xfrd_send_quit_req(xfrd_state_t* xfrd)
592 {
593 	sig_atomic_t cmd = NSD_QUIT;
594 	xfrd->ipc_send_blocked = 1;
595 	xfrd->ipc_handler.event_types &= (~NETIO_EVENT_WRITE);
596 	xfrd->sending_zone_state = 0;
597 	DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc send ackreload(quit)"));
598 	if(write_socket(xfrd->ipc_handler.fd, &cmd, sizeof(cmd)) == -1) {
599 		log_msg(LOG_ERR, "xfrd: error writing ack to main: %s",
600 			strerror(errno));
601 	}
602 	xfrd->need_to_send_quit = 0;
603 }
604 
605 static void
606 xfrd_handle_ipc_SOAINFO(xfrd_state_t* xfrd, buffer_type* packet)
607 {
608 	xfrd_soa_t soa;
609 	xfrd_soa_t* soa_ptr = &soa;
610 	xfrd_zone_t* zone;
611 	/* dname is sent in memory format */
612 	const dname_type* dname = (const dname_type*)buffer_begin(packet);
613 
614 	/* find zone and decode SOA */
615 	zone = (xfrd_zone_t*)rbtree_search(xfrd->zones, dname);
616 	buffer_skip(packet, dname_total_size(dname));
617 
618 	if(!buffer_available(packet, sizeof(uint32_t)*6 + sizeof(uint8_t)*2)) {
619 		/* NSD has zone without any info */
620 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "SOAINFO for %s lost zone",
621 			dname_to_string(dname,0)));
622 		soa_ptr = NULL;
623 	} else {
624 		/* read soa info */
625 		memset(&soa, 0, sizeof(soa));
626 		/* left out type, klass, count for speed */
627 		soa.type = htons(TYPE_SOA);
628 		soa.klass = htons(CLASS_IN);
629 		soa.ttl = htonl(buffer_read_u32(packet));
630 		soa.rdata_count = htons(7);
631 		soa.prim_ns[0] = buffer_read_u8(packet);
632 		if(!buffer_available(packet, soa.prim_ns[0]))
633 			return;
634 		buffer_read(packet, soa.prim_ns+1, soa.prim_ns[0]);
635 		soa.email[0] = buffer_read_u8(packet);
636 		if(!buffer_available(packet, soa.email[0]))
637 			return;
638 		buffer_read(packet, soa.email+1, soa.email[0]);
639 
640 		soa.serial = htonl(buffer_read_u32(packet));
641 		soa.refresh = htonl(buffer_read_u32(packet));
642 		soa.retry = htonl(buffer_read_u32(packet));
643 		soa.expire = htonl(buffer_read_u32(packet));
644 		soa.minimum = htonl(buffer_read_u32(packet));
645 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "SOAINFO for %s %u",
646 			dname_to_string(dname,0), ntohl(soa.serial)));
647 	}
648 
649 	if(!zone) {
650 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: zone %s master zone updated",
651 			dname_to_string(dname,0)));
652 		notify_handle_master_zone_soainfo(xfrd->notify_zones,
653 			dname, soa_ptr);
654 		return;
655 	}
656 	xfrd_handle_incoming_soa(zone, soa_ptr, xfrd_time());
657 }
658 
659 void
660 xfrd_handle_ipc(netio_type* ATTR_UNUSED(netio),
661 	netio_handler_type *handler,
662 	netio_event_types_type event_types)
663 {
664 	xfrd_state_t* xfrd = (xfrd_state_t*)handler->user_data;
665         if ((event_types & NETIO_EVENT_READ))
666 	{
667 		/* first attempt to read as a signal from main
668 		 * could block further send operations */
669 		xfrd_handle_ipc_read(handler, xfrd);
670 	}
671         if ((event_types & NETIO_EVENT_WRITE))
672 	{
673 		if(xfrd->ipc_send_blocked) { /* wait for SOA_END */
674 			handler->event_types = NETIO_EVENT_READ;
675 			return;
676 		}
677 		/* if necessary prepare a packet */
678 		if(!(xfrd->can_send_reload && xfrd->need_to_send_reload) &&
679 			!xfrd->need_to_send_quit &&
680 			!xfrd->sending_zone_state &&
681 			xfrd->dirty_zones->num > 0) {
682 			xfrd_zone_t* zone = (xfrd_zone_t*)stack_pop(xfrd->dirty_zones);
683 			assert(zone);
684 			zone->dirty = 0;
685 			xfrd->sending_zone_state = 1;
686 			xfrd_write_expire_notification(xfrd->ipc_conn_write->packet, zone);
687 			xfrd->ipc_conn_write->msglen = buffer_limit(xfrd->ipc_conn_write->packet);
688 			/* skip length bytes; they are encoded in the packet, after cmd */
689 			xfrd->ipc_conn_write->total_bytes = sizeof(uint16_t);
690 		}
691 		/* write a bit */
692 		if(xfrd->sending_zone_state) {
693 			/* call conn_write */
694 			int ret = conn_write(xfrd->ipc_conn_write);
695 			if(ret == -1) {
696 				log_msg(LOG_ERR, "xfrd: error in write ipc: %s", strerror(errno));
697 				xfrd->sending_zone_state = 0;
698 			}
699 			else if(ret == 1) { /* done */
700 				xfrd->sending_zone_state = 0;
701 			}
702 		} else if(xfrd->need_to_send_quit) {
703 			xfrd_send_quit_req(xfrd);
704 		} else if(xfrd->can_send_reload && xfrd->need_to_send_reload) {
705 			xfrd_send_reload_req(xfrd);
706 		}
707 		if(!(xfrd->can_send_reload && xfrd->need_to_send_reload) &&
708 			!xfrd->need_to_send_quit &&
709 			!xfrd->sending_zone_state &&
710 			xfrd->dirty_zones->num == 0) {
711 			handler->event_types = NETIO_EVENT_READ; /* disable writing for now */
712 		}
713 	}
714 
715 }
716 
717 static void
718 xfrd_handle_ipc_read(netio_handler_type *handler, xfrd_state_t* xfrd)
719 {
720         sig_atomic_t cmd;
721         int len;
722 
723 	if(xfrd->ipc_conn->is_reading==2) {
724 		buffer_type* tmp = xfrd->ipc_pass;
725 		uint32_t acl_num;
726 		/* read acl_num */
727 		int ret = conn_read(xfrd->ipc_conn);
728 		if(ret == -1) {
729 			log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno));
730 			xfrd->ipc_conn->is_reading = 0;
731 			return;
732 		}
733 		if(ret == 0)
734 			return;
735 		buffer_flip(xfrd->ipc_conn->packet);
736 		xfrd->ipc_pass = xfrd->ipc_conn->packet;
737 		xfrd->ipc_conn->packet = tmp;
738 		xfrd->ipc_conn->is_reading = 0;
739 		acl_num = buffer_read_u32(xfrd->ipc_pass);
740 		xfrd_handle_passed_packet(xfrd->ipc_conn->packet, acl_num);
741 		return;
742 	}
743 	if(xfrd->ipc_conn->is_reading) {
744 		/* reading an IPC message */
745 		int ret = conn_read(xfrd->ipc_conn);
746 		if(ret == -1) {
747 			log_msg(LOG_ERR, "xfrd: error in read ipc: %s", strerror(errno));
748 			xfrd->ipc_conn->is_reading = 0;
749 			return;
750 		}
751 		if(ret == 0)
752 			return;
753 		buffer_flip(xfrd->ipc_conn->packet);
754 		if(xfrd->ipc_is_soa) {
755 			xfrd->ipc_conn->is_reading = 0;
756 			xfrd_handle_ipc_SOAINFO(xfrd, xfrd->ipc_conn->packet);
757 		} else 	{
758 			/* use ipc_conn to read remaining data as well */
759 			buffer_type* tmp = xfrd->ipc_pass;
760 			xfrd->ipc_conn->is_reading=2;
761 			xfrd->ipc_pass = xfrd->ipc_conn->packet;
762 			xfrd->ipc_conn->packet = tmp;
763 			xfrd->ipc_conn->total_bytes = sizeof(xfrd->ipc_conn->msglen);
764 			xfrd->ipc_conn->msglen = sizeof(uint32_t);
765 			buffer_clear(xfrd->ipc_conn->packet);
766 			buffer_set_limit(xfrd->ipc_conn->packet, xfrd->ipc_conn->msglen);
767 		}
768 		return;
769 	}
770 
771         if((len = read(handler->fd, &cmd, sizeof(cmd))) == -1) {
772                 log_msg(LOG_ERR, "xfrd_handle_ipc: read: %s",
773                         strerror(errno));
774                 return;
775         }
776         if(len == 0)
777         {
778 		/* parent closed the connection. Quit */
779 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main closed connection."));
780 		xfrd->shutdown = 1;
781 		return;
782         }
783 
784         switch(cmd) {
785         case NSD_QUIT:
786         case NSD_SHUTDOWN:
787 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: main send shutdown cmd."));
788                 xfrd->shutdown = 1;
789                 break;
790 	case NSD_SOA_BEGIN:
791 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv SOA_BEGIN"));
792 		/* reload starts sending SOA INFOs; don't block */
793 		xfrd->parent_soa_info_pass = 1;
794 		/* reset the nonblocking ipc write;
795 		   the new parent does not want half a packet */
796 		xfrd->sending_zone_state = 0;
797 		break;
798 	case NSD_SOA_INFO:
799 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv SOA_INFO"));
800 		assert(xfrd->parent_soa_info_pass);
801 		xfrd->ipc_is_soa = 1;
802 		xfrd->ipc_conn->is_reading = 1;
803                 break;
804 	case NSD_SOA_END:
805 		/* reload has finished */
806 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv SOA_END"));
807 		xfrd->can_send_reload = 1;
808 		xfrd->parent_soa_info_pass = 0;
809 		xfrd->ipc_send_blocked = 0;
810 		handler->event_types |= NETIO_EVENT_WRITE;
811 		xfrd_reopen_logfile();
812 		xfrd_check_failed_updates();
813 		xfrd_send_expy_all_zones();
814 		break;
815 	case NSD_PASS_TO_XFRD:
816 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv PASS_TO_XFRD"));
817 		xfrd->ipc_is_soa = 0;
818 		xfrd->ipc_conn->is_reading = 1;
819 		break;
820 	case NSD_RELOAD:
821 		/* main tells us that reload is done, stop ipc send to main */
822 		DEBUG(DEBUG_IPC,1, (LOG_INFO, "xfrd: ipc recv RELOAD"));
823 		handler->event_types |= NETIO_EVENT_WRITE;
824 		xfrd->need_to_send_quit = 1;
825 		break;
826         default:
827                 log_msg(LOG_ERR, "xfrd_handle_ipc: bad mode %d (%d)", (int)cmd,
828 			ntohl(cmd));
829                 break;
830         }
831 
832 	if(xfrd->ipc_conn->is_reading) {
833 		/* setup read of info */
834 		xfrd->ipc_conn->total_bytes = 0;
835 		xfrd->ipc_conn->msglen = 0;
836 		buffer_clear(xfrd->ipc_conn->packet);
837 	}
838 }
839 
840