Ejemplo n.º 1
0
void
dns_req_free(getdns_dns_req * req)
{
	if (!req) {
		return;
	}
	getdns_network_req *net_req = NULL;
	struct getdns_context *context = req->context;

	/* free extensions */
	getdns_dict_destroy(req->extensions);

	/* free network requests */
	net_req = req->first_req;
	while (net_req) {
		getdns_network_req *next = net_req->next;
		network_req_free(net_req);
		net_req = next;
	}

    if (req->local_timeout_id != 0) {
        getdns_context_clear_timeout(context, req->local_timeout_id);
    }

    getdns_context_clear_timeout(context, req->trans_id);

	/* free strduped name */
	GETDNS_FREE(req->my_mf, req->name);

	GETDNS_FREE(req->my_mf, req);
}
Ejemplo n.º 2
0
getdns_return_t
getdns_rr_dict2str_scan(
    const getdns_dict *rr_dict, char **str, int *str_len)
{
	getdns_return_t r;
	gldns_buffer gbuf;
	uint8_t buf_spc[4096], *buf = buf_spc, *scan_buf;
	size_t sz, scan_sz;
	int prev_str_len;
	char *prev_str;
	int sz_needed;

	if (!rr_dict || !str || !*str || !str_len)
		return GETDNS_RETURN_INVALID_PARAMETER;

	gldns_buffer_init_frm_data(&gbuf, buf, sizeof(buf_spc));
	r = _getdns_rr_dict2wire(rr_dict, &gbuf);
	if (gldns_buffer_position(&gbuf) > sizeof(buf_spc)) {
		if (!(buf = GETDNS_XMALLOC(
		    rr_dict->mf, uint8_t, (sz = gldns_buffer_position(&gbuf))))) {
			return GETDNS_RETURN_MEMORY_ERROR;
		}
		gldns_buffer_init_frm_data(&gbuf, buf, sz);
		r = _getdns_rr_dict2wire(rr_dict, &gbuf);
	}
	if (r) {
		if (buf != buf_spc)
			GETDNS_FREE(rr_dict->mf, buf);
		return r;
	}
	scan_buf = gldns_buffer_begin(&gbuf);
	scan_sz  = gldns_buffer_position(&gbuf);
	prev_str = *str;
	prev_str_len = *str_len;
	sz = (size_t)*str_len;
	sz_needed = gldns_wire2str_rr_scan(
	    &scan_buf, &scan_sz, str, &sz, NULL, 0);

	if (sz_needed > prev_str_len) {
		*str = prev_str + sz_needed;
		*str_len = prev_str_len - sz_needed;
		r = GETDNS_RETURN_NEED_MORE_SPACE;
	} else  {
		*str_len = sz;
		**str = 0;
	}
	if (buf != buf_spc)
		GETDNS_FREE(rr_dict->mf, buf);
	return r;
}
Ejemplo n.º 3
0
static void tcp_connection_destroy(tcp_connection *conn)
{
	struct mem_funcs *mf;
	getdns_eventloop *loop;

	tcp_to_write *cur, *next;

	mf = &conn->super.l->set->context->mf;
	if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
		return;

	if (conn->event.ev)
		loop->vmt->clear(loop, &conn->event);

	if (conn->event.read_cb||conn->event.write_cb||conn->event.timeout_cb) {
		conn->event.read_cb    = conn->event.write_cb =
		conn->event.timeout_cb = NULL;
	}
	if (conn->fd >= 0) {
		(void) _getdns_closesocket(conn->fd);
		conn->fd = -1;
	}
	if (conn->read_buf) {
		GETDNS_FREE(*mf, conn->read_buf);
		conn->read_buf = conn->read_pos = NULL;
		conn->to_read = 0;
	}
	if ((cur = conn->to_write)) {
		while (cur) {
			next = cur->next;
			GETDNS_FREE(*mf, cur);
			cur = next;
		}
		conn->to_write = NULL;
	}
	if (conn->to_answer > 0)
		return;

	/* Unlink this connection */
	(void) _getdns_rbtree_delete(
	    &conn->super.l->set->connections_set, conn);
	DEBUG_SERVER("[connection del] count: %d\n",
	    (int)conn->super.l->set->connections_set.count);
	if ((*conn->super.prev_next = conn->super.next))
		conn->super.next->prev_next = conn->super.prev_next;

	free_listen_set_when_done(conn->super.l->set);
	GETDNS_FREE(*mf, conn);
}
Ejemplo n.º 4
0
Archivo: list.c Proyecto: ATP93/getdns
/*---------------------------------------- getdns_list_destroy */
void
getdns_list_destroy(struct getdns_list *list)
{
	size_t i;

	if (!list)
		return;

	for (i = 0; i < list->numinuse; i++)
		_getdns_list_destroy_item(list, i);

	if (list->items)
		GETDNS_FREE(list->mf, list->items);
	GETDNS_FREE(list->mf, list);
}				/* getdns_list_destroy */
Ejemplo n.º 5
0
static void
_getdns_cancel_reply(getdns_context *context, connection *conn)
{
	struct mem_funcs *mf;

	if (!conn)
		return;

	if (context && context->server &&
	    _getdns_rbtree_search(&context->server->connections_set, conn)
	    != &conn->super)
		return;

	if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
		tcp_connection *tcp_conn = (tcp_connection *)conn;

		if (tcp_conn->to_answer > 0 && --tcp_conn->to_answer == 0 &&
		    tcp_conn->fd == -1)
			tcp_connection_destroy(tcp_conn);

	} else if (conn->l->transport == GETDNS_TRANSPORT_UDP &&
	    (mf = &conn->l->set->context->mf)) {
		listen_set *set = conn->l->set;

		/* Unlink this connection */
		(void) _getdns_rbtree_delete(
		    &set->connections_set, conn);
		DEBUG_SERVER("[connection del] count: %d\n",
		    (int)set->connections_set.count);
		if ((*conn->prev_next = conn->next))
			conn->next->prev_next = conn->prev_next;
		GETDNS_FREE(*mf, conn);
		free_listen_set_when_done(set);
	}
}
Ejemplo n.º 6
0
getdns_return_t
_getdns_fp2rr_list(struct mem_funcs *mf,
    FILE *in, getdns_list **rr_list, const char *origin, uint32_t default_ttl)
{
	struct gldns_file_parse_state pst;
	getdns_list *rrs;
	getdns_return_t r = GETDNS_RETURN_GOOD;
	uint8_t *rr;
	size_t len, dname_len;
	getdns_dict *rr_dict;

	if (!in || !rr_list)
		return GETDNS_RETURN_INVALID_PARAMETER;

	if (!origin) {
		*pst.origin = 0;
		pst.origin_len = 1;

	} else if (gldns_str2wire_dname_buf(origin,pst.origin,&pst.origin_len))
		return GETDNS_RETURN_GENERIC_ERROR;

	*pst.prev_rr = 0;
	pst.prev_rr_len = 1;
	pst.default_ttl = default_ttl;
	pst.lineno = 1;

	if (!(rrs = _getdns_list_create_with_mf(mf)))
		return GETDNS_RETURN_MEMORY_ERROR;
	

	if (!(rr = GETDNS_XMALLOC(*mf, uint8_t, GLDNS_RR_BUF_SIZE)))
		r = GETDNS_RETURN_MEMORY_ERROR;

	else while (r == GETDNS_RETURN_GOOD && !feof(in)) {
		len = GLDNS_RR_BUF_SIZE;
		dname_len = 0;
		if (gldns_fp2wire_rr_buf(in, rr, &len, &dname_len, &pst))
			break;
		if (dname_len && dname_len < sizeof(pst.prev_rr)) {
			memcpy(pst.prev_rr, rr, dname_len);
			pst.prev_rr_len = dname_len;
		}
		if (len == 0)
			continue;
		if ((r = _getdns_wire2rr_dict(mf, rr, len, &rr_dict)))
			break;
		r = _getdns_list_append_dict(rrs, rr_dict);
		getdns_dict_destroy(rr_dict);
	}
	if (rr)
		GETDNS_FREE(*mf, rr);
	if (r)
		getdns_list_destroy(rrs);
	else
		*rr_list = rrs;
	return r;
}
Ejemplo n.º 7
0
static void tcp_write_cb(void *userarg)
{
	tcp_connection *conn = (tcp_connection *)userarg;
	struct mem_funcs *mf;
	getdns_eventloop *loop;

	tcp_to_write *to_write;
	ssize_t written;

	assert(userarg);

	if (!(mf = &conn->super.l->set->context->mf))
		return;

	if (getdns_context_get_eventloop(conn->super.l->set->context, &loop))
		return;

	/* Reset tcp_connection idle timeout */
	loop->vmt->clear(loop, &conn->event);

	if (!conn->to_write) {
		conn->event.write_cb = NULL;
		(void) loop->vmt->schedule(loop, conn->fd,
		    DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
		return;
	}
	to_write = conn->to_write;
	if (conn->fd == -1 || 
	    (written = send(conn->fd,
	    (const void *)&to_write->write_buf[to_write->written],
	    to_write->write_buf_len - to_write->written, 0)) == -1) {

		if (conn->fd != -1) {
			if (_getdns_socketerror_wants_retry()) {
				(void) loop->vmt->schedule(loop, conn->fd,
				    DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
				return;
			}
			DEBUG_SERVER("I/O error from send(): %s\n",
	        	     	_getdns_errnostr());
		}
		/* IO error, close connection */
		tcp_connection_destroy(conn);
		return;
	}
	to_write->written += written;
	if (to_write->written == to_write->write_buf_len) {
		conn->to_write = to_write->next;
		GETDNS_FREE(*mf, to_write);
	}
	if (!conn->to_write)
		conn->event.write_cb = NULL;

	(void) loop->vmt->schedule(loop, conn->fd,
	    DOWNSTREAM_IDLE_TIMEOUT, &conn->event);
}
Ejemplo n.º 8
0
void
network_req_free(getdns_network_req * net_req)
{
	if (!net_req) {
		return;
	}
	if (net_req->result) {
		ldns_pkt_free(net_req->result);
	}
	GETDNS_FREE(net_req->owner->my_mf, net_req);
}
Ejemplo n.º 9
0
getdns_return_t
_getdns_str2rr_dict(struct mem_funcs *mf,
    const char *str, getdns_dict **rr_dict, const char *origin, uint32_t default_ttl)
{
	uint8_t wire_spc[4096], *wire = wire_spc;
	uint8_t origin_spc[256], *origin_wf;
	size_t origin_len = sizeof(origin_spc), wire_len = sizeof(wire_spc);
	int e;
	getdns_return_t r;

	if (!str || !rr_dict)
		return GETDNS_RETURN_INVALID_PARAMETER;

	if (!origin)
		origin_wf = NULL;

	else if (gldns_str2wire_dname_buf(origin, origin_spc, &origin_len))
		return GETDNS_RETURN_GENERIC_ERROR;
	else
		origin_wf = origin_spc;

	e = gldns_str2wire_rr_buf(str, wire, &wire_len,
	    NULL, default_ttl, origin_wf, origin_len, NULL, 0);
	if (GLDNS_WIREPARSE_ERROR(e) == GLDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL) {

		if (!(wire = GETDNS_XMALLOC(
		    *mf, uint8_t, (wire_len = GLDNS_RR_BUF_SIZE))))
			return GETDNS_RETURN_MEMORY_ERROR;
		e = gldns_str2wire_rr_buf(str, wire, &wire_len,
	            NULL, default_ttl, origin_wf, origin_len, NULL, 0);
	}
	if (e) {
		if (wire != wire_spc)
			GETDNS_FREE(*mf, wire);
		return GETDNS_RETURN_GENERIC_ERROR;
	}
	r = _getdns_wire2rr_dict(mf, wire, wire_len, rr_dict);
	if (wire != wire_spc)
		GETDNS_FREE(*mf, wire);
	return r;
}
Ejemplo n.º 10
0
getdns_return_t
_getdns_get_pubkey_pinset_from_list(const getdns_list *pinset_list,
				    struct mem_funcs *mf,
				    sha256_pin_t **pinset_out)
{
	getdns_return_t r;
	size_t pins, i;
	sha256_pin_t *out = NULL, *onext = NULL;
	getdns_dict * pin;
	getdns_bindata * data = NULL;
	
	if (r = getdns_list_get_length(pinset_list, &pins), r)
		return r;
	for (i = 0; i < pins; i++)
	{
		if (r = getdns_list_get_dict(pinset_list, i, &pin), r)
			goto fail;
		/* does the pin have the right digest type? */
		if (r = getdns_dict_get_bindata(pin, "digest", &data), r)
			goto fail;
		if (data->size != sha256.size ||
		    memcmp(data->data, sha256.data, sha256.size)) {
			r = GETDNS_RETURN_INVALID_PARAMETER;
			goto fail;
		}
		/* if it does, is the value the right length? */
		if (r = getdns_dict_get_bindata(pin, "value", &data), r)
			goto fail;
		if (data->size != SHA256_DIGEST_LENGTH) {
			r = GETDNS_RETURN_INVALID_PARAMETER;
			goto fail;
		}
		/* make a new pin */
		onext = GETDNS_MALLOC(*mf, sha256_pin_t);
		if (onext == NULL) {
			r = GETDNS_RETURN_MEMORY_ERROR;
			goto fail;
		}
		onext->next = out;
		memcpy(onext->pin, data->data, SHA256_DIGEST_LENGTH);
		out = onext;
	}
	
	*pinset_out = out;
	return GETDNS_RETURN_GOOD;
 fail:
	while (out) {
		onext = out->next;
		GETDNS_FREE(*mf, out);
		out = onext;
	}
	return r;
}
Ejemplo n.º 11
0
Archivo: libuv.c Proyecto: ATP93/getdns
static void
getdns_libuv_close_cb(uv_handle_t *handle)
{
	poll_timer *my_ev = (poll_timer *)handle->data;

	DEBUG_UV("enter libuv_close_cb(el_ev->ev = %p, to_close = %d)\n"
	        , my_ev, my_ev->to_close);
	if (--my_ev->to_close) {
		DEBUG_UV(
		     "exit  libuv_close_cb(el_ev->ev = %p, to_close = %d)\n"
		    , my_ev, my_ev->to_close);
		return;
	}
	DEBUG_UV("enter libuv_close_cb to_free: %p\n", my_ev);
	GETDNS_FREE(my_ev->mf, my_ev);
	DEBUG_UV("enter libuv_close_cb freed: %p\n", my_ev);
}
Ejemplo n.º 12
0
Archivo: list.c Proyecto: ATP93/getdns
struct getdns_list *
getdns_list_create_with_extended_memory_functions(
	void *userarg,
	void *(*malloc)(void *userarg, size_t),
	void *(*realloc)(void *userarg, void *, size_t),
	void (*free)(void *userarg, void *))
{
	struct getdns_list *list;
	mf_union mf;

	if (!malloc || !realloc || !free)
		return NULL;

	mf.ext.malloc = malloc;
	list = userarg == MF_PLAIN
		 ? (struct getdns_list *)(*mf.pln.malloc)(
			   sizeof(struct getdns_list))
		 : (struct getdns_list *)(*mf.ext.malloc)(userarg,
			   sizeof(struct getdns_list));
	if (!list)
		return NULL;

	list->mf.mf_arg         = userarg;
	list->mf.mf.ext.malloc  = malloc;
	list->mf.mf.ext.realloc = realloc;
	list->mf.mf.ext.free    = free;

	list->numinuse = 0;
	if (!(list->items = GETDNS_XMALLOC(
	    list->mf, getdns_item, GETDNS_LIST_BLOCKSZ))) {
		GETDNS_FREE(list->mf, list);
		return NULL;
	}
	list->numalloc = GETDNS_LIST_BLOCKSZ;
	return list;
}
Ejemplo n.º 13
0
getdns_return_t
getdns_reply(getdns_context *context,
    const getdns_dict *reply, getdns_transaction_t request_id)
{
	/* TODO: Check request_id at context->outbound_requests */
	connection *conn = (connection *)(intptr_t)request_id;
	struct mem_funcs *mf;
	getdns_eventloop *loop;
	uint8_t buf[65536];
	size_t len;
	getdns_return_t r;

	if (!conn)
		return GETDNS_RETURN_INVALID_PARAMETER;

	if (!context || !context->server) {
		if (!context)
			context = conn->l->set->context;

	} else if (_getdns_rbtree_search(&context->server->connections_set, conn)
	    != &conn->super)
		return GETDNS_RETURN_NO_SUCH_LIST_ITEM;

	if (!reply) {
		_getdns_cancel_reply(context, conn);
		return GETDNS_RETURN_GOOD;
	}
	if (!(mf = &conn->l->set->context->mf))
		return GETDNS_RETURN_GENERIC_ERROR;;

	if ((r = getdns_context_get_eventloop(conn->l->set->context, &loop)))
		return r;

	len = sizeof(buf);
	if ((r = getdns_msg_dict2wire_buf(reply, buf, &len)))
		return r;

	else if (conn->l->transport == GETDNS_TRANSPORT_UDP) {
		listener *l = conn->l;

		if (conn->l->fd >= 0 && sendto(conn->l->fd, (void *)buf, len, 0,
		    (struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
			/* TODO: handle _getdns_socketerror_wants_retry() */

			/* IO error, never cleanup a listener because of I/O error */
			DEBUG_SERVER("I/O error from sendto(): %s\n",
				     _getdns_errnostr());
		}
		/* Unlink this connection */
		(void) _getdns_rbtree_delete(
		    &l->set->connections_set, conn);
		DEBUG_SERVER("[connection del] count: %d\n",
		    (int)l->set->connections_set.count);
		if ((*conn->prev_next = conn->next))
			conn->next->prev_next = conn->prev_next;

		GETDNS_FREE(*mf, conn);
		if (l->fd < 0)
			free_listen_set_when_done(l->set);

	} else if (conn->l->transport == GETDNS_TRANSPORT_TCP) {
		tcp_connection *conn = (tcp_connection *)(intptr_t)request_id;
		tcp_to_write **to_write_p;
		tcp_to_write *to_write;

		if (conn->fd == -1) {
			if (conn->to_answer > 0)
				--conn->to_answer;
			tcp_connection_destroy(conn);
			return GETDNS_RETURN_GOOD;
		}
		if (!(to_write = (tcp_to_write *)GETDNS_XMALLOC(
		    *mf, uint8_t, sizeof(tcp_to_write) + len + 2))) {
			tcp_connection_destroy(conn);
			return GETDNS_RETURN_MEMORY_ERROR;
		}

		to_write->write_buf_len = len + 2;
		to_write->write_buf[0] = (len >> 8) & 0xFF;
		to_write->write_buf[1] = len & 0xFF;
		to_write->written = 0;
		to_write->next = NULL;
		(void) memcpy(to_write->write_buf + 2, buf, len);

		/* Append to_write to conn->to_write list */
		for ( to_write_p = &conn->to_write
		    ; *to_write_p
		    ; to_write_p = &(*to_write_p)->next)
			; /* pass */
		*to_write_p = to_write;

		if (conn->to_answer > 0)
			conn->to_answer--;

		/* When event is scheduled, and doesn't have tcp_write_cb:
		 * reschedule.
		 */
		if (conn->event.write_cb == NULL) {
			if (conn->event.ev)
				loop->vmt->clear(loop, &conn->event);
			conn->event.write_cb = tcp_write_cb;
			(void) loop->vmt->schedule(loop,
			    conn->fd, DOWNSTREAM_IDLE_TIMEOUT,
			    &conn->event);
		}
	}
Ejemplo n.º 14
0
static void
getdns_libevent_cleanup(getdns_eventloop *loop)
{
	getdns_libevent *ext = (getdns_libevent *)loop;
	GETDNS_FREE(ext->mf, ext);
}