void namedb_close (struct namedb *db) { namedb_fd_close(db); if (db) { namedb_destroy(db); } }
/* * Serve DNS requests. */ void server_child(struct nsd *nsd) { size_t i; region_type *server_region = region_create(xalloc, free); netio_type *netio = netio_create(server_region); netio_handler_type *tcp_accept_handlers; query_type *udp_query; sig_atomic_t mode; assert(nsd->server_kind != NSD_SERVER_MAIN); DEBUG(DEBUG_IPC, 2, (LOG_INFO, "child process started")); if (!(nsd->server_kind & NSD_SERVER_TCP)) { close_all_sockets(nsd->tcp, nsd->ifs); } if (!(nsd->server_kind & NSD_SERVER_UDP)) { close_all_sockets(nsd->udp, nsd->ifs); } if (nsd->this_child && nsd->this_child->parent_fd != -1) { netio_handler_type *handler; handler = (netio_handler_type *) region_alloc( server_region, sizeof(netio_handler_type)); handler->fd = nsd->this_child->parent_fd; handler->timeout = NULL; handler->user_data = (struct ipc_handler_conn_data*)region_alloc( server_region, sizeof(struct ipc_handler_conn_data)); ((struct ipc_handler_conn_data*)handler->user_data)->nsd = nsd; ((struct ipc_handler_conn_data*)handler->user_data)->conn = xfrd_tcp_create(server_region); handler->event_types = NETIO_EVENT_READ; handler->event_handler = child_handle_parent_command; netio_add_handler(netio, handler); } if (nsd->server_kind & NSD_SERVER_UDP) { udp_query = query_create(server_region, compressed_dname_offsets, compression_table_size); for (i = 0; i < nsd->ifs; ++i) { struct udp_handler_data *data; netio_handler_type *handler; data = (struct udp_handler_data *) region_alloc( server_region, sizeof(struct udp_handler_data)); data->query = udp_query; data->nsd = nsd; data->socket = &nsd->udp[i]; handler = (netio_handler_type *) region_alloc( server_region, sizeof(netio_handler_type)); handler->fd = nsd->udp[i].s; handler->timeout = NULL; handler->user_data = data; handler->event_types = NETIO_EVENT_READ; handler->event_handler = handle_udp; netio_add_handler(netio, handler); } } /* * Keep track of all the TCP accept handlers so we can enable * and disable them based on the current number of active TCP * connections. */ tcp_accept_handlers = (netio_handler_type *) region_alloc( server_region, nsd->ifs * sizeof(netio_handler_type)); if (nsd->server_kind & NSD_SERVER_TCP) { for (i = 0; i < nsd->ifs; ++i) { struct tcp_accept_handler_data *data; netio_handler_type *handler; data = (struct tcp_accept_handler_data *) region_alloc( server_region, sizeof(struct tcp_accept_handler_data)); data->nsd = nsd; data->socket = &nsd->tcp[i]; data->tcp_accept_handler_count = nsd->ifs; data->tcp_accept_handlers = tcp_accept_handlers; handler = &tcp_accept_handlers[i]; handler->fd = nsd->tcp[i].s; handler->timeout = NULL; handler->user_data = data; handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_ACCEPT; handler->event_handler = handle_tcp_accept; netio_add_handler(netio, handler); } } /* The main loop... */ while ((mode = nsd->mode) != NSD_QUIT) { if(mode == NSD_RUN) nsd->mode = mode = server_signal_mode(nsd); /* Do we need to do the statistics... */ if (mode == NSD_STATS) { #ifdef BIND8_STATS /* Dump the statistics */ bind8_stats(nsd); #else /* !BIND8_STATS */ log_msg(LOG_NOTICE, "Statistics support not enabled at compile time."); #endif /* BIND8_STATS */ nsd->mode = NSD_RUN; } else if (mode == NSD_REAP_CHILDREN) { /* got signal, notify parent. parent reaps terminated children. */ if (nsd->this_child->parent_fd != -1) { sig_atomic_t parent_notify = NSD_REAP_CHILDREN; if (write(nsd->this_child->parent_fd, &parent_notify, sizeof(parent_notify)) == -1) { log_msg(LOG_ERR, "problems sending command from %d to parent: %s", (int) nsd->this_child->pid, strerror(errno)); } } else /* no parent, so reap 'em */ while (waitpid(0, NULL, WNOHANG) > 0) ; nsd->mode = NSD_RUN; } else if(mode == NSD_RUN) { /* Wait for a query... */ if (netio_dispatch(netio, NULL, NULL) == -1) { if (errno != EINTR) { log_msg(LOG_ERR, "netio_dispatch failed: %s", strerror(errno)); break; } } } else if(mode == NSD_QUIT) { /* ignore here, quit */ } else { log_msg(LOG_ERR, "mode bad value %d, back to service.", mode); nsd->mode = NSD_RUN; } } #ifdef BIND8_STATS bind8_stats(nsd); #endif /* BIND8_STATS */ namedb_fd_close(nsd->db); region_destroy(server_region); server_shutdown(nsd); }