Example #1
0
void 
mesh_state_cleanup(struct mesh_state* mstate)
{
	struct mesh_area* mesh;
	int i;
	if(!mstate)
		return;
	mesh = mstate->s.env->mesh;
	/* drop unsent replies */
	if(!mstate->replies_sent) {
		struct mesh_reply* rep;
		struct mesh_cb* cb;
		for(rep=mstate->reply_list; rep; rep=rep->next) {
			comm_point_drop_reply(&rep->query_reply);
			mesh->num_reply_addrs--;
		}
		for(cb=mstate->cb_list; cb; cb=cb->next) {
			fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
			(*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
				sec_status_unchecked, NULL);
			mesh->num_reply_addrs--;
		}
	}

	/* de-init modules */
	for(i=0; i<mesh->mods.num; i++) {
		fptr_ok(fptr_whitelist_mod_clear(mesh->mods.mod[i]->clear));
		(*mesh->mods.mod[i]->clear)(&mstate->s, i);
		mstate->s.minfo[i] = NULL;
		mstate->s.ext_state[i] = module_finished;
	}
	alloc_reg_release(mstate->s.env->alloc, mstate->s.region);
}
Example #2
0
void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
	enum module_ev ev, struct outbound_entry* e)
{
	enum module_ext_state s;
	verbose(VERB_ALGO, "mesh_run: start");
	while(mstate) {
		/* run the module */
		fptr_ok(fptr_whitelist_mod_operate(
			mesh->mods.mod[mstate->s.curmod]->operate));
		(*mesh->mods.mod[mstate->s.curmod]->operate)
			(&mstate->s, ev, mstate->s.curmod, e);

		/* examine results */
		mstate->s.reply = NULL;
		regional_free_all(mstate->s.env->scratch);
		s = mstate->s.ext_state[mstate->s.curmod];
		verbose(VERB_ALGO, "mesh_run: %s module exit state is %s", 
			mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
		e = NULL;
		if(mesh_continue(mesh, mstate, s, &ev))
			continue;

		/* run more modules */
		ev = module_event_pass;
		if(mesh->run.count > 0) {
			/* pop random element off the runnable tree */
			mstate = (struct mesh_state*)mesh->run.root->key;
			(void)rbtree_delete(&mesh->run, mstate);
		} else mstate = NULL;
	}
	if(verbosity >= VERB_ALGO) {
		mesh_stats(mesh, "mesh_run: end");
		mesh_log_list(mesh);
	}
}
Example #3
0
/** call timeouts handlers, and return how long to wait for next one or -1 */
static void handle_timeouts(struct event_base* base, struct timeval* now, 
	struct timeval* wait)
{
	struct event* p;
#ifndef S_SPLINT_S
	wait->tv_sec = (time_t)-1;
#endif

	while((rbnode_t*)(p = (struct event*)rbtree_first(base->times))
		!=RBTREE_NULL) {
#ifndef S_SPLINT_S
		if(p->ev_timeout.tv_sec > now->tv_sec ||
			(p->ev_timeout.tv_sec==now->tv_sec && 
		 	p->ev_timeout.tv_usec > now->tv_usec)) {
			/* there is a next larger timeout. wait for it */
			wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
			if(now->tv_usec > p->ev_timeout.tv_usec) {
				wait->tv_sec--;
				wait->tv_usec = 1000000 - (now->tv_usec -
					p->ev_timeout.tv_usec);
			} else {
				wait->tv_usec = p->ev_timeout.tv_usec 
					- now->tv_usec;
			}
			return;
		}
#endif
		/* event times out, remove it */
		(void)rbtree_delete(base->times, p);
		p->ev_events &= ~EV_TIMEOUT;
		fptr_ok(fptr_whitelist_event(p->ev_callback));
		(*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
	}
}
Example #4
0
/** handle is_signal events and see if signalled */
static void _getdns_handle_signal(struct _getdns_event* ev)
{
	DWORD ret;
	//log_assert(ev->is_signal && ev->hEvent);
	/* see if the event is signalled */
	ret = WSAWaitForMultipleEvents(1, &ev->hEvent, 0 /* any object */,
		0 /* return immediately */, 0 /* not alertable for IOcomple*/);
	if(ret == WSA_WAIT_IO_COMPLETION || ret == WSA_WAIT_FAILED) {
		log_err("getdns: WSAWaitForMultipleEvents(signal) failed: %s",
			wsa_strerror(WSAGetLastError()));
		return;
	}
	if(ret == WSA_WAIT_TIMEOUT) {
		/* not signalled */
		return;
	}

	/* reset the signal */
	if(!WSAResetEvent(ev->hEvent))
		log_err("getdns: WSAResetEvent failed: %s",
			wsa_strerror(WSAGetLastError()));
	/* do the callback (which may set the signal again) */
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	(*ev->ev_callback)(ev->ev_fd, ev->ev_events, ev->ev_arg);
}
Example #5
0
/** pass time */
static void
time_passes(struct replay_runtime* runtime, struct replay_moment* mom)
{
	struct fake_timer *t;
	struct timeval tv = mom->elapse;
	if(mom->string) {
		char* xp = macro_process(runtime->vars, runtime, mom->string);
		double sec;
		if(!xp) fatal_exit("could not macro expand %s", mom->string);
		verbose(VERB_ALGO, "EVAL %s", mom->string);
		sec = atof(xp);
		free(xp);
#ifndef S_SPLINT_S
		tv.tv_sec = sec;
		tv.tv_usec = (int)((sec - (double)tv.tv_sec) *1000000. + 0.5);
#endif
	}
	timeval_add(&runtime->now_tv, &tv);
	runtime->now_secs = (time_t)runtime->now_tv.tv_sec;
#ifndef S_SPLINT_S
	log_info("elapsed %d.%6.6d  now %d.%6.6d", 
		(int)tv.tv_sec, (int)tv.tv_usec,
		(int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec);
#endif
	/* see if any timers have fired; and run them */
	while( (t=replay_get_oldest_timer(runtime)) ) {
		t->enabled = 0;
		log_info("fake_timer callback");
		fptr_ok(fptr_whitelist_comm_timer(t->cb));
		(*t->cb)(t->cb_arg);
	}
}
Example #6
0
/**
 * callback results to mesh cb entry
 * @param m: mesh state to send it for.
 * @param rcode: if not 0, error code.
 * @param rep: reply to send (or NULL if rcode is set).
 * @param r: callback entry
 */
static void
mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
	struct mesh_cb* r)
{
	int secure;
	char* reason = NULL;
	/* bogus messages are not made into servfail, sec_status passed 
	 * to the callback function */
	if(rep && rep->security == sec_status_secure)
		secure = 1;
	else	secure = 0;
	if(!rep && rcode == LDNS_RCODE_NOERROR)
		rcode = LDNS_RCODE_SERVFAIL;
	if(!rcode && rep->security == sec_status_bogus) {
		if(!(reason = errinf_to_str(&m->s)))
			rcode = LDNS_RCODE_SERVFAIL;
	}
	/* send the reply */
	if(rcode) {
		fptr_ok(fptr_whitelist_mesh_cb(r->cb));
		(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL);
	} else {
		size_t udp_size = r->edns.udp_size;
		ldns_buffer_clear(r->buf);
		r->edns.edns_version = EDNS_ADVERTISED_VERSION;
		r->edns.udp_size = EDNS_ADVERTISED_SIZE;
		r->edns.ext_rcode = 0;
		r->edns.bits &= EDNS_DO;
		if(!reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 
			r->qflags, r->buf, 0, 1, 
			m->s.env->scratch, udp_size, &r->edns, 
			(int)(r->edns.bits & EDNS_DO), secure)) 
		{
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
				sec_status_unchecked, NULL);
		} else {
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
				rep->security, reason);
		}
	}
	free(reason);
	m->s.env->mesh->num_reply_addrs--;
}
Example #7
0
/** signal handler */
static RETSIGTYPE sigh(int sig)
{
	struct event* ev;
	if(!signal_base || sig < 0 || sig >= MAX_SIG)
		return;
	ev = signal_base->signals[sig];
	if(!ev)
		return;
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	(*ev->ev_callback)(sig, EV_SIGNAL, ev->ev_arg);
}
Example #8
0
/** set content of event */
void event_set(struct event* ev, int fd, short bits, 
	void (*cb)(int, short, void *), void* arg)
{
	ev->node.key = ev;
	ev->ev_fd = fd;
	ev->ev_events = bits;
	ev->ev_callback = cb;
	fptr_ok(fptr_whitelist_event(ev->ev_callback));
	ev->ev_arg = arg;
	ev->added = 0;
}
Example #9
0
void 
modstack_desetup(struct module_stack* stack, struct module_env* env)
{
        int i;
        for(i=0; i<stack->num; i++) {
                fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
                (*stack->mod[i]->deinit)(env, i);
        }
        stack->num = 0;
        free(stack->mod);
        stack->mod = NULL;
}
Example #10
0
/** print mem stats */
static int
print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
{
	int m;
	size_t msg, rrset, val, iter;
#ifdef HAVE_SBRK
	extern void* unbound_start_brk;
	void* cur = sbrk(0);
	if(!print_longnum(ssl, "mem.total.sbrk"SQ, 
		(size_t)((char*)cur - (char*)unbound_start_brk))) return 0;
#endif /* HAVE_SBRK */
	msg = slabhash_get_mem(daemon->env->msg_cache);
	rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
	val=0;
	iter=0;
	m = modstack_find(&worker->env.mesh->mods, "validator");
	if(m != -1) {
		fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
			mods.mod[m]->get_mem));
		val = (*worker->env.mesh->mods.mod[m]->get_mem)
			(&worker->env, m);
	}
	m = modstack_find(&worker->env.mesh->mods, "iterator");
	if(m != -1) {
		fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
			mods.mod[m]->get_mem));
		iter = (*worker->env.mesh->mods.mod[m]->get_mem)
			(&worker->env, m);
	}

	if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
		return 0;
	if(!print_longnum(ssl, "mem.cache.message"SQ, msg))
		return 0;
	if(!print_longnum(ssl, "mem.mod.iterator"SQ, iter))
		return 0;
	if(!print_longnum(ssl, "mem.mod.validator"SQ, val))
		return 0;
	return 1;
}
Example #11
0
/* timers in testbound for autotrust. statistics tested in tpkg. */
struct comm_timer* comm_timer_create(struct comm_base* base, 
	void (*cb)(void*), void* cb_arg)
{
	struct replay_runtime* runtime = (struct replay_runtime*)base;
	struct fake_timer* t = (struct fake_timer*)calloc(1, sizeof(*t));
	t->cb = cb;
	t->cb_arg = cb_arg;
	fptr_ok(fptr_whitelist_comm_timer(t->cb)); /* check in advance */
	t->runtime = runtime;
	t->next = runtime->timer_list;
	runtime->timer_list = t;
	return (struct comm_timer*)t;
}
Example #12
0
/**
 * Continue processing the mesh state at another module.
 * Handles module to modules tranfer of control.
 * Handles module finished.
 * @param mesh: the mesh area.
 * @param mstate: currently active mesh state.
 * 	Deleted if finished, calls _done and _supers to 
 * 	send replies to clients and inform other mesh states.
 * 	This in turn may create additional runnable mesh states.
 * @param s: state at which the current module exited.
 * @param ev: the event sent to the module.
 * 	returned is the event to send to the next module.
 * @return true if continue processing at the new module.
 * 	false if not continued processing is needed.
 */
static int
mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
	enum module_ext_state s, enum module_ev* ev)
{
	mstate->num_activated++;
	if(mstate->num_activated > MESH_MAX_ACTIVATION) {
		/* module is looping. Stop it. */
		log_err("internal error: looping module stopped");
		log_query_info(VERB_QUERY, "pass error for qstate",
			&mstate->s.qinfo);
		s = module_error;
	}
	if(s == module_wait_module || s == module_restart_next) {
		/* start next module */
		mstate->s.curmod++;
		if(mesh->mods.num == mstate->s.curmod) {
			log_err("Cannot pass to next module; at last module");
			log_query_info(VERB_QUERY, "pass error for qstate",
				&mstate->s.qinfo);
			mstate->s.curmod--;
			return mesh_continue(mesh, mstate, module_error, ev);
		}
		if(s == module_restart_next) {
			fptr_ok(fptr_whitelist_mod_clear(
				mesh->mods.mod[mstate->s.curmod]->clear));
			(*mesh->mods.mod[mstate->s.curmod]->clear)
				(&mstate->s, mstate->s.curmod);
			mstate->s.minfo[mstate->s.curmod] = NULL;
		}
		*ev = module_event_pass;
		return 1;
	}
	if(s == module_error && mstate->s.return_rcode == LDNS_RCODE_NOERROR) {
		/* error is bad, handle pass back up below */
		mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
	}
	if(s == module_error || s == module_finished) {
		if(mstate->s.curmod == 0) {
			mesh_query_done(mstate);
			mesh_walk_supers(mesh, mstate);
			mesh_state_delete(&mstate->s);
			return 0;
		}
		/* pass along the locus of control */
		mstate->s.curmod --;
		*ev = module_event_moddone;
		return 1;
	}
	return 0;
}
Example #13
0
/** call select and callbacks for that */
static int handle_select(struct event_base* base, struct timeval* wait)
{
	fd_set r, w;
	int ret, i;

#ifndef S_SPLINT_S
	if(wait->tv_sec==(time_t)-1)
		wait = NULL;
#endif
	memmove(&r, &base->reads, sizeof(fd_set));
	memmove(&w, &base->writes, sizeof(fd_set));
	memmove(&base->ready, &base->content, sizeof(fd_set));

	if((ret = select(base->maxfd+1, &r, &w, NULL, wait)) == -1) {
		ret = errno;
		if(settime(base) < 0)
			return -1;
		errno = ret;
		if(ret == EAGAIN || ret == EINTR)
			return 0;
		return -1;
	}
	if(settime(base) < 0)
		return -1;
	
	for(i=0; i<base->maxfd+1; i++) {
		short bits = 0;
		if(!base->fds[i] || !(FD_ISSET(i, &base->ready))) {
			continue;
		}
		if(FD_ISSET(i, &r)) {
			bits |= EV_READ;
			ret--;
		}
		if(FD_ISSET(i, &w)) {
			bits |= EV_WRITE;
			ret--;
		}
		bits &= base->fds[i]->ev_events;
		if(bits) {
			fptr_ok(fptr_whitelist_event(
				base->fds[i]->ev_callback));
			(*base->fds[i]->ev_callback)(base->fds[i]->ev_fd, 
				bits, base->fds[i]->ev_arg);
			if(ret==0)
				break;
		}
	}
	return 0;
}
Example #14
0
void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
{
	struct mesh_state_ref* ref;
	RBTREE_FOR(ref, struct mesh_state_ref*, &mstate->super_set)
	{
		/* make super runnable */
		(void)rbtree_insert(&mesh->run, &ref->s->run_node);
		/* callback the function to inform super of result */
		fptr_ok(fptr_whitelist_mod_inform_super(
			mesh->mods.mod[ref->s->s.curmod]->inform_super));
		(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s, 
			ref->s->s.curmod, &ref->s->s);
	}
}
Example #15
0
/** detect dependency cycle for query and target */
static int
causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen,
	uint16_t t, uint16_t c)
{
	struct query_info qinf;
	qinf.qname = name;
	qinf.qname_len = namelen;
	qinf.qtype = t;
	qinf.qclass = c;
	fptr_ok(fptr_whitelist_modenv_detect_cycle(
		qstate->env->detect_cycle));
	return (*qstate->env->detect_cycle)(qstate, &qinf, 
		(uint16_t)(BIT_RD|BIT_CD), qstate->is_priming,
		qstate->is_valrec);
}
Example #16
0
void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), 
	void* arg)
{
	struct tube* tube = (struct tube*)arg;
	uint8_t* buf;
	uint32_t len = 0;
	verbose(VERB_ALGO, "tube handle_signal");
	while(tube_poll(tube)) {
		if(tube_read_msg(tube, &buf, &len, 1)) {
			fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
			(*tube->listen_cb)(tube, buf, len, NETEVENT_NOERROR, 
				tube->listen_arg);
		}
	}
}
Example #17
0
/*
 * Inserts a node into a red black tree.
 *
 * Returns NULL on failure or the pointer to the newly added node
 * otherwise.
 */
getdns_rbnode_t *
getdns_rbtree_insert (getdns_rbtree_t *rbtree, getdns_rbnode_t *data)
{
	/* XXX Not necessary, but keeps compiler quiet... */
	int r = 0;

	/* We start at the root of the tree */
	getdns_rbnode_t	*node = rbtree->root;
	getdns_rbnode_t	*parent = RBTREE_NULL;

	fptr_ok(fptr_whitelist_getdns_rbtree_cmp(rbtree->cmp));
	/* Lets find the new parent... */
	while (node != RBTREE_NULL) {
		/* Compare two keys, do we have a duplicate? */
		if ((r = rbtree->cmp(data->key, node->key)) == 0) {
			return NULL;
		}
		parent = node;

		if (r < 0) {
			node = node->left;
		} else {
			node = node->right;
		}
	}

	/* Initialize the new node */
	data->parent = parent;
	data->left = data->right = RBTREE_NULL;
	data->color = RED;
	rbtree->count++;

	/* Insert it into the tree... */
	if (parent != RBTREE_NULL) {
		if (r < 0) {
			parent->left = data;
		} else {
			parent->right = data;
		}
	} else {
		rbtree->root = data;
	}

	/* Fix up the red-black properties... */
	getdns_rbtree_insert_fixup(rbtree, data);

	return data;
}
Example #18
0
static int
generate_cname_request(struct module_qstate* qstate,
	struct ub_packed_rrset_key* alias_rrset)
{
	struct module_qstate* subq = NULL;
	struct query_info subqi;

	memset(&subqi, 0, sizeof(subqi));
	get_cname_target(alias_rrset, &subqi.qname, &subqi.qname_len);
	if(!subqi.qname)
		return 0;    /* unexpected: not a valid CNAME RDATA */
	subqi.qtype = qstate->qinfo.qtype;
	subqi.qclass = qstate->qinfo.qclass;
	fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
	return (*qstate->env->attach_sub)(qstate, &subqi, BIT_RD, 0, 0, &subq);
}
Example #19
0
uint64_t
alloc_get_id(struct alloc_cache* alloc)
{
	uint64_t id = alloc->next_id++;
	if(id == alloc->last_id) {
		log_warn("rrset alloc: out of 64bit ids. Clearing cache.");
		fptr_ok(fptr_whitelist_alloc_cleanup(alloc->cleanup));
		(*alloc->cleanup)(alloc->cleanup_arg);

		/* start back at first number */   	/* like in alloc_init*/
		alloc->next_id = (uint64_t)alloc->thread_num; 	
		alloc->next_id <<= THRNUM_SHIFT; 	/* in steps for comp. */
		alloc->next_id += 1;			/* portability. */
		/* and generate new and safe id */
		id = alloc->next_id++;
	}
	return id;
}
Example #20
0
/** enumerate all subkeys of base, and call process(hk, arg) on them */
void enum_guids(const char* base, void (*process_it)(HKEY,void*), void* arg)
{
	char subname[1024];
	HKEY base_hk, sub_hk;
	DWORD sz = sizeof(subname);
	DWORD i = 0, ret;
	if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)base,
		0, /* reserved, mustbezero */
		NULL, /* class of key, ignored */
		REG_OPTION_NON_VOLATILE, /* values saved on disk */
		KEY_WRITE|KEY_ENUMERATE_SUB_KEYS,
		NULL, /* use default security descriptor */
		&base_hk, /* result */
		NULL)) /* not interested if key new or existing */
	{
		log_win_err("could not open enum registry key", GetLastError());
		return;
	}
	while( (ret=RegEnumKeyEx(base_hk, i, (LPTSTR)subname, &sz, NULL, NULL,
		0, NULL)) == ERROR_SUCCESS) {
		verbose(VERB_ALGO, "enum %d %s", (int)i, subname);
		/* process it */
		if(RegOpenKeyEx(base_hk, (LPCTSTR)subname, 0, KEY_WRITE,
			&sub_hk)) {
			log_win_err("enum cannot RegOpenKey", GetLastError());
		} else {
			fptr_ok(fptr_whitelist_enum_reg(process_it));
			(*process_it)(sub_hk, arg);
			RegCloseKey(sub_hk);
		}
		/* prepare for next iteration */
		i++;
		sz = sizeof(subname);
	}
	if(ret == ERROR_MORE_DATA) {
		log_err("part of %s has registry keys that are too long", base);
	} else if(ret != ERROR_NO_MORE_ITEMS) {
		log_win_err("cannot RegEnumKey", GetLastError());
	}
	RegCloseKey(base_hk);	
}
Example #21
0
/** call timeouts handlers, and return how long to wait for next one or -1 */
void _getdns_handle_timeouts(struct _getdns_event_base* base, struct timeval* now,
        struct timeval* wait)
{
        struct _getdns_event* p;
#ifndef S_SPLINT_S
        wait->tv_sec = (time_t)-1;
#endif
	//verbose(VERB_CLIENT, "winsock_event handle_timeouts");

        while((_getdns_rbnode_t*)(p = (struct _getdns_event*)_getdns_rbtree_first(base->times))
                !=RBTREE_NULL) {
#ifndef S_SPLINT_S
                if(p->ev_timeout.tv_sec > now->tv_sec ||
                        (p->ev_timeout.tv_sec==now->tv_sec &&
                        p->ev_timeout.tv_usec > now->tv_usec)) {
                        /* there is a next larger timeout. wait for it */
                        wait->tv_sec = p->ev_timeout.tv_sec - now->tv_sec;
                        if(now->tv_usec > p->ev_timeout.tv_usec) {
                                wait->tv_sec--;
                                wait->tv_usec = 1000000 - (now->tv_usec -
                                        p->ev_timeout.tv_usec);
                        } else {
                                wait->tv_usec = p->ev_timeout.tv_usec
                                        - now->tv_usec;
                        }
			//verbose(VERB_CLIENT, "winsock_event wait=" ARG_LL "d.%6.6d",
			//	(long long)wait->tv_sec, (int)wait->tv_usec);
                        return;
                }
#endif
                /* event times out, remove it */
                (void)_getdns_rbtree_delete(base->times, p);
                p->ev_events &= ~EV_TIMEOUT;
                fptr_ok(fptr_whitelist_event(p->ev_callback));
                (*p->ev_callback)(p->ev_fd, EV_TIMEOUT, p->ev_arg);
        }
	//verbose(VERB_CLIENT, "winsock_event wait=(-1)");
}
Example #22
0
int 
modstack_setup(struct module_stack* stack, const char* module_conf,
	struct module_env* env)
{
        int i;
        if(stack->num != 0)
                modstack_desetup(stack, env);
        /* fixed setup of the modules */
        if(!modstack_config(stack, module_conf)) {
		return 0;
        }
        env->need_to_validate = 0; /* set by module init below */
        for(i=0; i<stack->num; i++) {
                verbose(VERB_OPS, "init module %d: %s",
                        i, stack->mod[i]->name);
                fptr_ok(fptr_whitelist_mod_init(stack->mod[i]->init));
                if(!(*stack->mod[i]->init)(env, i)) {
                        log_err("module init for module %s failed",
                                stack->mod[i]->name);
			return 0;
                }
        }
	return 1;
}
Example #23
0
/** Report on memory usage by this thread and global */
static void
worker_mem_report(struct worker* ATTR_UNUSED(worker), 
	struct serviced_query* ATTR_UNUSED(cur_serv))
{
#ifdef UNBOUND_ALLOC_STATS
	/* debug func in validator module */
	size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
	size_t me, iter, val, anch;
	int i;
	if(verbosity < VERB_ALGO) 
		return;
	front = listen_get_mem(worker->front);
	back = outnet_get_mem(worker->back);
	msg = slabhash_get_mem(worker->env.msg_cache);
	rrset = slabhash_get_mem(&worker->env.rrset_cache->table);
	infra = infra_get_mem(worker->env.infra_cache);
	mesh = mesh_get_mem(worker->env.mesh);
	ac = alloc_get_mem(&worker->alloc);
	superac = alloc_get_mem(&worker->daemon->superalloc);
	anch = anchors_get_mem(worker->env.anchors);
	iter = 0;
	val = 0;
	for(i=0; i<worker->env.mesh->mods.num; i++) {
		fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
			mods.mod[i]->get_mem));
		if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
			val += (*worker->env.mesh->mods.mod[i]->get_mem)
				(&worker->env, i);
		else	iter += (*worker->env.mesh->mods.mod[i]->get_mem)
				(&worker->env, i);
	}
	me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig)
		+ comm_point_get_mem(worker->cmd_com) 
		+ sizeof(worker->rndstate) 
		+ regional_get_mem(worker->scratchpad) 
		+ sizeof(*worker->env.scratch_buffer) 
		+ sldns_buffer_capacity(worker->env.scratch_buffer)
		+ forwards_get_mem(worker->env.fwds)
		+ hints_get_mem(worker->env.hints);
	if(worker->thread_num == 0)
		me += acl_list_get_mem(worker->daemon->acl);
	if(cur_serv) {
		me += serviced_get_mem(cur_serv);
	}
	total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me;
	log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
		"rrset=%u infra=%u iter=%u val=%u anchors=%u "
		"alloccache=%u globalalloccache=%u me=%u",
		(unsigned)total, (unsigned)front, (unsigned)back, 
		(unsigned)mesh, (unsigned)msg, (unsigned)rrset, 
		(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
		(unsigned)ac, (unsigned)superac, (unsigned)me);
	debug_total_mem(total);
#else /* no UNBOUND_ALLOC_STATS */
	size_t val = 0;
	int i;
	if(verbosity < VERB_QUERY)
		return;
	for(i=0; i<worker->env.mesh->mods.num; i++) {
		fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
			mods.mod[i]->get_mem));
		if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
			val += (*worker->env.mesh->mods.mod[i]->get_mem)
				(&worker->env, i);
	}
	verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u",
		(unsigned)slabhash_get_mem(worker->env.msg_cache),
		(unsigned)slabhash_get_mem(&worker->env.rrset_cache->table),
		(unsigned)infra_get_mem(worker->env.infra_cache),
		(unsigned)val);
#endif /* UNBOUND_ALLOC_STATS */
}
Example #24
0
/** call select and callbacks for that */
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	fd_set r, w;
	int ret, i, timeout = 0, numwait = 0;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];

#ifndef S_SPLINT_S
	if (wait->tv_sec == (time_t)-1)
		wait = NULL;
#endif
	memmove(&r, &base->reads, sizeof(fd_set));
	memmove(&w, &base->writes, sizeof(fd_set));
	memmove(&base->ready, &base->content, sizeof(fd_set));
	/*
	if ((ret = select(base->max + 1, &r, &w, NULL, wait)) == -1) {
		ret = errno;
		if (settime(base) < 0)
			return -1;
		errno = ret;
		if (ret == EAGAIN || ret == EINTR)
			return 0;
		return -1;
	}
	*/

	/* prepare event array */
	for (i = 0; i<base->max; i++) {
		if (base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}

	ret = WSAWaitForMultipleEvents(base->max, base->waitfor,
		0 /* do not wait for all, just one will do */,
		wait ? timeout : WSA_INFINITE,
		0); /* we are not alertable (IO completion events) */
	if (ret == WSA_WAIT_IO_COMPLETION) {
		log_err("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
		return -1;
	}
	else if (ret == WSA_WAIT_FAILED) {
		log_err("getdns: WSAWaitForMultipleEvents failed: %s",
			wsa_strerror(WSAGetLastError()));
		return -1;
	}
	else if (ret == WSA_WAIT_TIMEOUT) {
		was_timeout = 1;
	}
	else
		startidx = ret - WSA_WAIT_EVENT_0;


	if (settime(base) < 0)
		return -1;

	for (i = 0; i<base->max + 1; i++) {
		short bits = 0;
		if (!base->items[i] || !(FD_ISSET(i, &base->ready))) {
			continue;
		}
		if (FD_ISSET(i, &r)) {
			bits |= EV_READ;
			ret--;
		}
		if (FD_ISSET(i, &w)) {
			bits |= EV_WRITE;
			ret--;
		}
		bits &= base->items[i]->ev_events;
		if (bits) {
			fptr_ok(fptr_whitelist_event(
				base->items[i]->ev_callback));
			(*base->items[i]->ev_callback)(base->items[i]->ev_fd,
				bits, base->items[i]->ev_arg);
			if (ret == 0)
				break;
		}
	}
	return 0;
}
Example #25
0
int _getdns_handle_select(struct _getdns_event_base* base, struct timeval* wait)
{
	DWORD timeout = 0; /* in milliseconds */	
	DWORD ret;
	WSANETWORKEVENTS netev;
	struct _getdns_event* eventlist[WSK_MAX_ITEMS];
	int i, numwait = 0, startidx = 0, was_timeout = 0;
	int newstickies = 0;
	struct timeval nultm;

	printf("in handle select\n");

#ifndef S_SPLINT_S
        if(wait->tv_sec==(time_t)-1)
                wait = NULL;
		if (wait)
		//	timeout = 10 + wait->tv_usec / 1000;
		 timeout = wait->tv_sec * 1000 + wait->tv_usec / 1000;
 	if(base->tcp_stickies) {
		wait = &nultm;
		nultm.tv_sec = 0;
		nultm.tv_usec = 0;
		timeout = 0; /* no waiting, we have sticky events */
	}
#endif

	/* prepare event array */
	for(i=0; i<base->max; i++) {
		if(base->items[i]->ev_fd == -1 && !base->items[i]->is_signal)
			continue; /* skip timer only events */
		eventlist[numwait] = base->items[i];
		base->waitfor[numwait++] = base->items[i]->hEvent;
		printf("winsock_event bmax=%d numwait=%d wait=%x "
			"timeout=%d hEvent %d\n", base->max, numwait, (int)wait, (int)timeout, base->items[i]->hEvent);
		if (numwait == WSK_MAX_ITEMS)
			break; /* sanity check */
	}
	//log_assert(numwait <= WSA_MAXIMUM_WAIT_EVENTS);

	/* do the wait */
	if(numwait == 0) {
		/* WSAWaitFor.. doesn't like 0 event objects */
		if(wait) {
			Sleep(timeout);
		}
		was_timeout = 1;
	}
	else {
		//g do not sched udp write
		for (i = 0; i<base->max; i++) {
			if (!base->items[i]->is_tcp && base->items[i]->ev_events&EV_WRITE) {
				//gprintf("skip UDP sched\n");
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					EV_WRITE & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
				return 0;
			}
	    } 
		//gprintf("before wait %d\n", base->items[0]->ev_events);
		ret = WSAWaitForMultipleEvents(numwait, base->waitfor,
			0 /* do not wait for all, just one will do */,
			wait?timeout:WSA_INFINITE,
			0); /* we are not alertable (IO completion events) */
		//gprintf("after wait %d %d\n", ret, numwait);
		if(ret == WSA_WAIT_IO_COMPLETION) {
			//printf("getdns: WSAWaitForMultipleEvents failed: WSA_WAIT_IO_COMPLETION");
			return -1;
		} else if(ret == WSA_WAIT_FAILED) {
			//printf("getdns: WSAWaitForMultipleEvents failed: %s", 
			//	wsa_strerror(WSAGetLastError()));
			return -1;
		} else if(ret == WSA_WAIT_TIMEOUT) {
			//printf("timeout\n");
			was_timeout = 1;
		} else
			startidx = ret - WSA_WAIT_EVENT_0;
	}
	////verbose(VERB_CLIENT, "winsock_event wake was_timeout=%d startidx=%d", 
	//	was_timeout, startidx);

	/* get new time after wait */
        if(settime(base) < 0)
               return -1;

	/* callbacks */
	if(base->tcp_stickies)
		startidx = 0; /* process all events, some are sticky */
	for(i=startidx; i<numwait; i++)
		eventlist[i]->just_checked = 1;

	//verbose(VERB_CLIENT, "winsock_event signals");
	for(i=startidx; i<numwait; i++) {
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(eventlist[i]->is_signal) {
			eventlist[i]->just_checked = 0;
			_getdns_handle_signal(eventlist[i]);
		}
	}
	/* early exit - do not process network, exit quickly */
	if(base->need_to_exit)
		return 0;

	//verbose(VERB_CLIENT, "winsock_event net");
	for(i=startidx; i<numwait; i++) {
		short bits = 0;
		/* eventlist[i] fired */
		/* see if eventlist[i] is still valid and just checked from
		 * WSAWaitForEvents */
		if(!base->waitfor[i])
			continue; /* was deleted */
		if(!eventlist[i]->just_checked)
			continue; /* added by other callback */
		if(eventlist[i]->is_signal)
			continue; /* not a network event at all */
		eventlist[i]->just_checked = 0;

		if(WSAEnumNetworkEvents(eventlist[i]->ev_fd, 
			base->waitfor[i], /* reset the event handle */
			/*NULL,*/ /* do not reset the event handle */
			&netev) != 0) {
			log_err("getdns: WSAEnumNetworkEvents failed: %s", 
				wsa_strerror(WSAGetLastError()));
			return -1;
		}
		if((netev.lNetworkEvents & FD_READ)) {
			if(netev.iErrorCode[FD_READ_BIT] != 0)
				printf("FD_READ_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_READ_BIT]));
			bits |= EV_READ;
			printf("FD_READ_BIT\n");
		}
		if((netev.lNetworkEvents & FD_WRITE)) {
			if(netev.iErrorCode[FD_WRITE_BIT] != 0)
				printf("FD_WRITE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_WRITE_BIT]));
			bits |= EV_WRITE;
			printf("FD_WRITE_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CONNECT)) {
			if(netev.iErrorCode[FD_CONNECT_BIT] != 0)
				printf("FD_CONNECT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CONNECT_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CONNECT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_ACCEPT)) {
			if(netev.iErrorCode[FD_ACCEPT_BIT] != 0)
				printf("FD_ACCEPT_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_ACCEPT_BIT]));
			bits |= EV_READ;
			printf("FD_ACCEPT_BIT\n");
		}
		if((netev.lNetworkEvents & FD_CLOSE)) {
			if(netev.iErrorCode[FD_CLOSE_BIT] != 0)
				printf("FD_CLOSE_BIT error: %s\n",
				wsa_strerror(netev.iErrorCode[FD_CLOSE_BIT]));
			bits |= EV_READ;
			bits |= EV_WRITE;
			printf("FD_CLOSE_BIT\n");
		}
		if(eventlist[i]->is_tcp && eventlist[i]->stick_events) {
			/*
			printf("winsock %d pass sticky %s%s\n",
				eventlist[i]->ev_fd,
   			    (eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/
			bits |= eventlist[i]->old_events;
		}
		if(eventlist[i]->is_tcp && bits) {
			eventlist[i]->old_events = bits;
			eventlist[i]->stick_events = 1;
			if((eventlist[i]->ev_events & bits)) {
				newstickies = 1;
			}
			/*
		printf("winsock %d store sticky %s%s",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
			*/	
		}
		if((bits & eventlist[i]->ev_events)) {
		/*     printf( "winsock event callback %p fd=%d "
			    "%s%s%s%s%s ; %s%s%s\n", 
				eventlist[i], eventlist[i]->ev_fd,
				(netev.lNetworkEvents&FD_READ)?" FD_READ":"",
				(netev.lNetworkEvents&FD_WRITE)?" FD_WRITE":"",
				(netev.lNetworkEvents&FD_CONNECT)?
					" FD_CONNECT":"",
			    (netev.lNetworkEvents&FD_ACCEPT)?
					" FD_ACCEPT":"",
				(netev.lNetworkEvents&FD_CLOSE)?" FD_CLOSE":"",
			    (bits&EV_READ)?" EV_READ":"",
			    (bits&EV_WRITE)?" EV_WRITE":"",
				(bits&EV_TIMEOUT)?" EV_TIMEOUT":"");
				*/
				fptr_ok(fptr_whitelist_event(
					eventlist[i]->ev_callback));
				(*eventlist[i]->ev_callback)(eventlist[i]->ev_fd,
					bits & eventlist[i]->ev_events,
					eventlist[i]->ev_arg);
		}
		/*
	   if(eventlist[i]->is_tcp && bits)
			printf( "winsock %d got sticky %s%s\n",
				eventlist[i]->ev_fd,
				(eventlist[i]->old_events&EV_READ)?"EV_READ":"",
				(eventlist[i]->old_events&EV_WRITE)?"EV_WRITE":"");
	   */
	}
	//verbose(VERB_CLIENT, "winsock_event net");
	if(base->tcp_reinvigorated) {
		printf("winsock_event reinvigorated\n");
		base->tcp_reinvigorated = 0;
		newstickies = 1;
	}
	base->tcp_stickies = newstickies;
	//gprintf("winsock_event handle_select end\n");
        return 0;
}
Example #26
0
int
tube_handle_listen(struct comm_point* c, void* arg, int error,
        struct comm_reply* ATTR_UNUSED(reply_info))
{
	struct tube* tube = (struct tube*)arg;
	ssize_t r;
	if(error != NETEVENT_NOERROR) {
		fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
		(*tube->listen_cb)(tube, NULL, 0, error, tube->listen_arg);
		return 0;
	}

	if(tube->cmd_read < sizeof(tube->cmd_len)) {
		/* complete reading the length of control msg */
		r = read(c->fd, ((uint8_t*)&tube->cmd_len) + tube->cmd_read,
			sizeof(tube->cmd_len) - tube->cmd_read);
		if(r==0) {
			/* error has happened or */
			/* parent closed pipe, must have exited somehow */
			fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
			(*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, 
				tube->listen_arg);
			return 0;
		}
		if(r==-1) {
			if(errno != EAGAIN && errno != EINTR) {
				log_err("rpipe error: %s", strerror(errno));
			}
			/* nothing to read now, try later */
			return 0;
		}
		tube->cmd_read += r;
		if(tube->cmd_read < sizeof(tube->cmd_len)) {
			/* not complete, try later */
			return 0;
		}
		tube->cmd_msg = (uint8_t*)calloc(1, tube->cmd_len);
		if(!tube->cmd_msg) {
			log_err("malloc failure");
			tube->cmd_read = 0;
			return 0;
		}
	}
	/* cmd_len has been read, read remainder */
	r = read(c->fd, tube->cmd_msg+tube->cmd_read-sizeof(tube->cmd_len),
		tube->cmd_len - (tube->cmd_read - sizeof(tube->cmd_len)));
	if(r==0) {
		/* error has happened or */
		/* parent closed pipe, must have exited somehow */
		fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
		(*tube->listen_cb)(tube, NULL, 0, NETEVENT_CLOSED, 
			tube->listen_arg);
		return 0;
	}
	if(r==-1) {
		/* nothing to read now, try later */
		if(errno != EAGAIN && errno != EINTR) {
			log_err("rpipe error: %s", strerror(errno));
		}
		return 0;
	}
	tube->cmd_read += r;
	if(tube->cmd_read < sizeof(tube->cmd_len) + tube->cmd_len) {
		/* not complete, try later */
		return 0;
	}
	tube->cmd_read = 0;

	fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
	(*tube->listen_cb)(tube, tube->cmd_msg, tube->cmd_len, 
		NETEVENT_NOERROR, tube->listen_arg);
		/* also frees the buf */
	tube->cmd_msg = NULL;
	return 0;
}