/* * The main server simply waits for signals and child processes to * terminate. Child processes are restarted as necessary. */ void server_main(struct nsd *nsd) { region_type *server_region = region_create(xalloc, free); netio_handler_type xfrd_listener; /* Ensure we are the main process */ assert(nsd->server_kind == NSD_SERVER_MAIN); xfrd_listener.user_data = (struct ipc_handler_conn_data*)region_alloc( server_region, sizeof(struct ipc_handler_conn_data)); xfrd_listener.fd = -1; ((struct ipc_handler_conn_data*)xfrd_listener.user_data)->nsd = nsd; ((struct ipc_handler_conn_data*)xfrd_listener.user_data)->conn = xfrd_tcp_create(server_region); nsd->pid = 0; nsd->child_count = 0; nsd->server_kind = NSD_SERVER_UDP; nsd->this_child = &nsd->children[0]; /* remove signal flags inherited from parent the parent will handle them. */ nsd->signal_hint_reload = 0; nsd->signal_hint_child = 0; nsd->signal_hint_quit = 0; nsd->signal_hint_shutdown = 0; nsd->signal_hint_stats = 0; nsd->signal_hint_statsusr = 0; close(nsd->this_child->child_fd); nsd->this_child->child_fd = -1; server_child(nsd); abort(); }
xfrd_tcp_set_t* xfrd_tcp_set_create(struct region* region) { int i; xfrd_tcp_set_t* tcp_set = region_alloc(region, sizeof(xfrd_tcp_set_t)); memset(tcp_set, 0, sizeof(xfrd_tcp_set_t)); tcp_set->tcp_count = 0; tcp_set->tcp_waiting_first = 0; tcp_set->tcp_waiting_last = 0; for(i=0; i<XFRD_MAX_TCP; i++) tcp_set->tcp_state[i] = xfrd_tcp_create(region); return tcp_set; }
void xfrd_init(int socket, struct nsd* nsd) { region_type* region; assert(xfrd == 0); /* to setup signalhandling */ nsd->server_kind = NSD_SERVER_BOTH; region = region_create(xalloc, free); xfrd = (xfrd_state_t*)region_alloc(region, sizeof(xfrd_state_t)); memset(xfrd, 0, sizeof(xfrd_state_t)); xfrd->region = region; xfrd->xfrd_start_time = time(0); xfrd->netio = netio_create(xfrd->region); xfrd->nsd = nsd; xfrd->packet = buffer_create(xfrd->region, QIOBUFSZ); xfrd->udp_waiting_first = NULL; xfrd->udp_waiting_last = NULL; xfrd->udp_use_num = 0; xfrd->ipc_pass = buffer_create(xfrd->region, QIOBUFSZ); xfrd->parent_soa_info_pass = 0; /* add the handlers already, because this involves allocs */ xfrd->reload_handler.fd = -1; xfrd->reload_handler.timeout = NULL; xfrd->reload_handler.user_data = xfrd; xfrd->reload_handler.event_types = NETIO_EVENT_TIMEOUT; xfrd->reload_handler.event_handler = xfrd_handle_reload; xfrd->reload_timeout.tv_sec = 0; xfrd->reload_cmd_last_sent = xfrd->xfrd_start_time; xfrd->can_send_reload = 1; xfrd->ipc_send_blocked = 0; xfrd->ipc_handler.fd = socket; xfrd->ipc_handler.timeout = NULL; xfrd->ipc_handler.user_data = xfrd; xfrd->ipc_handler.event_types = NETIO_EVENT_READ; xfrd->ipc_handler.event_handler = xfrd_handle_ipc; xfrd->ipc_conn = xfrd_tcp_create(xfrd->region); /* not reading using ipc_conn yet */ xfrd->ipc_conn->is_reading = 0; xfrd->ipc_conn->fd = xfrd->ipc_handler.fd; xfrd->ipc_conn_write = xfrd_tcp_create(xfrd->region); xfrd->ipc_conn_write->fd = xfrd->ipc_handler.fd; xfrd->need_to_send_reload = 0; xfrd->sending_zone_state = 0; xfrd->dirty_zones = stack_create(xfrd->region, nsd_options_num_zones(nsd->options)); xfrd->notify_waiting_first = NULL; xfrd->notify_waiting_last = NULL; xfrd->notify_udp_num = 0; xfrd->tcp_set = xfrd_tcp_set_create(xfrd->region); xfrd->tcp_set->tcp_timeout = nsd->tcp_timeout; srandom((unsigned long) getpid() * (unsigned long) time(NULL)); DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd pre-startup")); diff_snip_garbage(nsd->db, nsd->options); xfrd_init_zones(); xfrd_free_namedb(); xfrd_read_state(xfrd); xfrd_send_expy_all_zones(); /* add handlers after zone handlers so they are before them in list */ netio_add_handler(xfrd->netio, &xfrd->reload_handler); netio_add_handler(xfrd->netio, &xfrd->ipc_handler); DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd startup")); xfrd_main(); }
/* * 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); }