/* Create a new NetIO descriptor with TCP_SER method */ netio_desc_t *netio_desc_create_tcp_ser(char *nio_name,char *port) { netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; if (netio_tcp_ser_create(&nio->u.nid,port) == -1) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_TCP_SER; nio->send = (void *)netio_tcp_send; nio->recv = (void *)netio_tcp_recv; nio->free = (void *)netio_tcp_free; nio->dptr = &nio->u.nid; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with VDE method */ netio_desc_t *netio_desc_create_vde(char *nio_name,char *control,char *local) { netio_vde_desc_t *nvd; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nvd = &nio->u.nvd; if (netio_vde_create(nvd,control,local) == -1) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_VDE; nio->send = (void *)netio_vde_send; nio->recv = (void *)netio_vde_recv; nio->free = (void *)netio_vde_free; nio->save_cfg = netio_vde_save_cfg; nio->dptr = &nio->u.nvd; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with TAP method */ netio_desc_t *netio_desc_create_tap(char *nio_name,char *tap_name) { netio_tap_desc_t *ntd; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; ntd = &nio->u.ntd; if (netio_tap_create(ntd,tap_name) == -1) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_TAP; nio->send = (void *)netio_tap_send; nio->recv = (void *)netio_tap_recv; nio->free = (void *)netio_tap_free; nio->save_cfg = netio_tap_save_cfg; nio->dptr = &nio->u.ntd; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with FIFO method */ netio_desc_t *netio_desc_create_fifo(char *nio_name) { netio_fifo_desc_t *nfd; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nfd = &nio->u.nfd; pthread_mutex_init(&nfd->lock,NULL); pthread_mutex_init(&nfd->endpoint_lock,NULL); pthread_cond_init(&nfd->cond,NULL); nio->type = NETIO_TYPE_FIFO; nio->send = (void *)netio_fifo_send; nio->recv = (void *)netio_fifo_recv; nio->free = (void *)netio_fifo_free; nio->dptr = nfd; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with UNIX method */ netio_desc_t *netio_desc_create_unix(char *nio_name,char *local,char *remote) { netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; if (netio_unix_create(&nio->u.nud,local,remote) == -1) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_UNIX; nio->send = (void *)netio_unix_send; nio->recv = (void *)netio_unix_recv; nio->free = (void *)netio_unix_free; nio->save_cfg = netio_unix_save_cfg; nio->dptr = &nio->u.nud; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/** * Create zone transfer handler. * */ xfrhandler_type* xfrhandler_create() { xfrhandler_type* xfrh = NULL; CHECKALLOC(xfrh = (xfrhandler_type*) malloc(sizeof(xfrhandler_type))); xfrh->engine = NULL; xfrh->packet = NULL; xfrh->netio = NULL; xfrh->tcp_set = NULL; xfrh->tcp_waiting_first = NULL; xfrh->udp_waiting_first = NULL; xfrh->udp_waiting_last = NULL; xfrh->udp_use_num = 0; xfrh->start_time = 0; xfrh->current_time = 0; xfrh->got_time = 0; xfrh->need_to_exit = 0; xfrh->started = 0; /* notify */ xfrh->notify_waiting_first = NULL; xfrh->notify_waiting_last = NULL; xfrh->notify_udp_num = 0; /* setup */ xfrh->netio = netio_create(); if (!xfrh->netio) { ods_log_error("[%s] unable to create xfrhandler: " "netio_create() failed", xfrh_str); xfrhandler_cleanup(xfrh); return NULL; } xfrh->packet = buffer_create(PACKET_BUFFER_SIZE); if (!xfrh->packet) { ods_log_error("[%s] unable to create xfrhandler: " "buffer_create() failed", xfrh_str); xfrhandler_cleanup(xfrh); return NULL; } xfrh->tcp_set = tcp_set_create(); if (!xfrh->tcp_set) { ods_log_error("[%s] unable to create xfrhandler: " "tcp_set_create() failed", xfrh_str); xfrhandler_cleanup(xfrh); return NULL; } xfrh->dnshandler.fd = -1; xfrh->dnshandler.user_data = (void*) xfrh; xfrh->dnshandler.timeout = 0; xfrh->dnshandler.event_types = NETIO_EVENT_READ; xfrh->dnshandler.event_handler = xfrhandler_handle_dns; xfrh->dnshandler.free_handler = 0; return xfrh; }
/** * Create dns handler. * */ dnshandler_type* dnshandler_create(allocator_type* allocator, listener_type* interfaces) { dnshandler_type* dnsh = NULL; if (!allocator || !interfaces || interfaces->count <= 0) { return NULL; } dnsh = (dnshandler_type*) allocator_alloc(allocator, sizeof(dnshandler_type)); if (!dnsh) { ods_log_error("[%s] unable to create dnshandler: " "allocator_alloc() failed", dnsh_str); return NULL; } dnsh->allocator = allocator; dnsh->need_to_exit = 0; dnsh->engine = NULL; dnsh->interfaces = interfaces; dnsh->socklist = NULL; dnsh->netio = NULL; dnsh->query = NULL; /* setup */ dnsh->socklist = (socklist_type*) allocator_alloc(allocator, sizeof(socklist_type)); if (!dnsh->socklist) { ods_log_error("[%s] unable to create socklist: " "allocator_alloc() failed", dnsh_str); dnshandler_cleanup(dnsh); return NULL; } dnsh->netio = netio_create(allocator); if (!dnsh->netio) { ods_log_error("[%s] unable to create dnshandler: " "netio_create() failed", dnsh_str); dnshandler_cleanup(dnsh); return NULL; } dnsh->query = query_create(); if (!dnsh->query) { ods_log_error("[%s] unable to create dnshandler: " "query_create() failed", dnsh_str); dnshandler_cleanup(dnsh); return NULL; } dnsh->xfrhandler.fd = -1; dnsh->xfrhandler.user_data = (void*) dnsh; dnsh->xfrhandler.timeout = 0; dnsh->xfrhandler.event_types = NETIO_EVENT_READ; dnsh->xfrhandler.event_handler = dnshandler_handle_xfr; return dnsh; }
/* Create a new NetIO descriptor with NULL method */ netio_desc_t *netio_desc_create_null(char *nio_name) { netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nio->type = NETIO_TYPE_NULL; nio->send = (void *)netio_null_send; nio->recv = (void *)netio_null_recv; nio->save_cfg = netio_null_save_cfg; nio->dptr = NULL; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with raw Ethernet method */ netio_desc_t *netio_desc_create_lnxeth(char *nio_name,char *dev_name) { netio_lnxeth_desc_t *nled; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nled = &nio->u.nled; if (strlen(dev_name) >= NETIO_DEV_MAXLEN) { fprintf(stderr,"netio_desc_create_lnxeth: bad Ethernet device string " "specified.\n"); netio_free(nio,NULL); return NULL; } strcpy(nled->dev_name,dev_name); nled->fd = lnx_eth_init_socket(dev_name); nled->dev_id = lnx_eth_get_dev_index(dev_name); if (nled->fd < 0) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_LINUX_ETH; nio->send = (void *)netio_lnxeth_send; nio->recv = (void *)netio_lnxeth_recv; nio->free = (void *)netio_lnxeth_free; nio->save_cfg = netio_lnxeth_save_cfg; nio->dptr = &nio->u.nled; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
/* Create a new NetIO descriptor with UDP method */ netio_desc_t *netio_desc_create_udp(char *nio_name,int local_port, char *remote_host,int remote_port) { netio_inet_desc_t *nid; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nid = &nio->u.nid; nid->local_port = local_port; nid->remote_port = remote_port; if (!(nid->remote_host = strdup(remote_host))) { fprintf(stderr,"netio_desc_create_udp: insufficient memory\n"); goto error; } if ((nid->fd = udp_connect(local_port,remote_host,remote_port)) < 0) { fprintf(stderr,"netio_desc_create_udp: unable to connect to %s:%d\n", remote_host,remote_port); goto error; } nio->type = NETIO_TYPE_UDP; nio->send = (void *)netio_udp_send; nio->recv = (void *)netio_udp_recv; nio->free = (void *)netio_udp_free; nio->save_cfg = netio_udp_save_cfg; nio->dptr = &nio->u.nid; if (netio_record(nio) == -1) goto error; return nio; error: netio_free(nio,NULL); return NULL; }
/* Create a new NetIO descriptor with auto UDP method */ netio_desc_t *netio_desc_create_udp_auto(char *nio_name,char *local_addr, int port_start,int port_end) { netio_inet_desc_t *nid; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nid = &nio->u.nid; nid->local_port = -1; nid->remote_host = NULL; nid->remote_port = -1; if ((nid->fd = udp_listen_range(local_addr,port_start,port_end, &nid->local_port)) < 0) { fprintf(stderr, "netio_desc_create_udp_auto: unable to create socket " "(addr=%s,port_start=%d,port_end=%d)\n", local_addr,port_start,port_end); goto error; } nio->type = NETIO_TYPE_UDP_AUTO; nio->send = (void *)netio_udp_send; nio->recv = (void *)netio_udp_recv; nio->free = (void *)netio_udp_free; nio->save_cfg = netio_udp_save_cfg; nio->dptr = &nio->u.nid; if (netio_record(nio) == -1) goto error; return nio; error: netio_free(nio,NULL); return NULL; }
/* Create a new NetIO descriptor with generic raw Ethernet method */ netio_desc_t *netio_desc_create_geneth(char *nio_name,char *dev_name) { netio_geneth_desc_t *nged; netio_desc_t *nio; if (!(nio = netio_create(nio_name))) return NULL; nged = &nio->u.nged; if (strlen(dev_name) >= NETIO_DEV_MAXLEN) { fprintf(stderr,"netio_desc_create_geneth: bad Ethernet device string " "specified.\n"); netio_free(nio,NULL); return NULL; } strcpy(nged->dev_name,dev_name); if (!(nged->pcap_dev = gen_eth_init(dev_name))) { netio_free(nio,NULL); return NULL; } nio->type = NETIO_TYPE_GEN_ETH; nio->send = (void *)netio_geneth_send; nio->recv = (void *)netio_geneth_recv; nio->free = (void *)netio_geneth_free; nio->save_cfg = netio_geneth_save_cfg; nio->dptr = &nio->u.nged; if (netio_record(nio) == -1) { netio_free(nio,NULL); return NULL; } return nio; }
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); }