auth zone move file descriptor functionality to outside network

for the unit test


git-svn-id: file:///svn/unbound/trunk@4482 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2018-01-31 14:59:17 +00:00
parent c1047e6a6c
commit 84e819dc31
4 changed files with 197 additions and 109 deletions

View file

@ -3399,67 +3399,6 @@ xfr_probe_nextmaster(struct auth_xfer* xfr)
return;
}
/** create fd to send to this master */
static int
xfr_fd_for_master(struct module_env* env, struct sockaddr_storage* to_addr,
socklen_t to_addrlen, char* host)
{
struct sockaddr_storage* addr;
socklen_t addrlen;
int i;
int try;
/* select interface */
if(addr_is_ip6(to_addr, to_addrlen)) {
if(env->outnet->num_ip6 == 0) {
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", host);
return -1;
}
i = ub_random_max(env->rnd, env->outnet->num_ip6);
addr = &env->outnet->ip6_ifs[i].addr;
addrlen = env->outnet->ip6_ifs[i].addrlen;
} else {
if(env->outnet->num_ip4 == 0) {
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", host);
return -1;
}
i = ub_random_max(env->rnd, env->outnet->num_ip4);
addr = &env->outnet->ip4_ifs[i].addr;
addrlen = env->outnet->ip4_ifs[i].addrlen;
}
/* create fd */
for(try = 0; try<1000; try++) {
int freebind = 0;
int noproto = 0;
int inuse = 0;
int port = ub_random(env->rnd)&0xffff;
int fd = -1;
if(addr_is_ip6(to_addr, to_addrlen)) {
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
sa.sin6_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
0, 0, 0, NULL, 0, freebind, 0);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
0, 0, 0, NULL, 0, freebind, 0);
}
if(fd != -1) {
return fd;
}
if(!inuse) {
return -1;
}
}
/* too many tries */
log_err("cannot send probe, ports are in use");
return -1;
}
/** create SOA probe packet for xfr */
static void
xfr_create_soa_probe_packet(struct auth_xfer* xfr, sldns_buffer* buf,
@ -4103,47 +4042,23 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
xfr->task_transfer->cp = NULL;
}
/* connect on fd */
if(!xfr->task_transfer->cp) {
int fd = outnet_get_tcp_fd(&addr, addrlen, env->cfg->tcp_mss);
if(fd == -1) {
char zname[255+1];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "cannot create fd for "
"xfr %s to %s", zname, master->host);
return 0;
}
fd_set_nonblock(fd);
if(!outnet_tcp_connect(fd, &addr, addrlen)) {
/* outnet_tcp_connect has closed fd on error for us */
char zname[255+1];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "cannot tcp connect() for"
"xfr %s to %s", zname, master->host);
return 0;
}
xfr->task_transfer->cp = comm_point_create_tcp_out(
env->worker_base, 65552,
auth_xfer_transfer_tcp_callback, xfr);
if(!xfr->task_transfer->cp) {
close(fd);
log_err("malloc failure");
return 0;
}
xfr->task_transfer->cp->repinfo.addrlen = addrlen;
memcpy(&xfr->task_transfer->cp->repinfo.addr, &addr, addrlen);
/* set timeout on TCP connection */
comm_point_start_listening(xfr->task_transfer->cp, fd,
AUTH_TRANSFER_TIMEOUT);
}
/* set the packet to be written */
/* create new ID */
xfr->task_transfer->id = (uint16_t)(ub_random(env->rnd)&0xffff);
xfr_create_ixfr_packet(xfr, xfr->task_transfer->cp->buffer,
xfr_create_ixfr_packet(xfr, env->scratch_buffer,
xfr->task_transfer->id);
/* connect on fd */
xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet,
auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen,
env->scratch_buffer, AUTH_TRANSFER_TIMEOUT);
if(!xfr->task_transfer->cp) {
char zname[255+1];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "cannot create tcp cp connection for "
"xfr %s to %s", zname, master->host);
return 0;
}
return 1;
}
@ -4750,22 +4665,15 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
xfr_create_soa_probe_packet(xfr, env->scratch_buffer,
xfr->task_probe->id);
if(!xfr->task_probe->cp) {
int fd = xfr_fd_for_master(env, &addr, addrlen, master->host);
if(fd == -1) {
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(!xfr->task_probe->cp) {
char zname[255+1];
dname_str(xfr->name, zname);
verbose(VERB_ALGO, "cannot create fd for "
verbose(VERB_ALGO, "cannot create udp cp for "
"probe %s to %s", zname, master->host);
return 0;
}
xfr->task_probe->cp = comm_point_create_udp(env->worker_base,
fd, env->outnet->udp_buff, auth_xfer_probe_udp_callback,
xfr);
if(!xfr->task_probe->cp) {
close(fd);
log_err("malloc failure");
return 0;
}
}
if(!xfr->task_probe->timer) {
xfr->task_probe->timer = comm_timer_create(env->worker_base,

View file

@ -2140,6 +2140,122 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
}
}
/** create fd to send to this destination */
static int
fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
socklen_t to_addrlen)
{
struct sockaddr_storage* addr;
socklen_t addrlen;
int i;
int try;
/* select interface */
if(addr_is_ip6(to_addr, to_addrlen)) {
if(outnet->num_ip6 == 0) {
char to[64];
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to);
return -1;
}
i = ub_random_max(outnet->rnd, outnet->num_ip6);
addr = &outnet->ip6_ifs[i].addr;
addrlen = outnet->ip6_ifs[i].addrlen;
} else {
if(outnet->num_ip4 == 0) {
char to[64];
addr_to_str(to_addr, to_addrlen, to, sizeof(to));
verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to);
return -1;
}
i = ub_random_max(outnet->rnd, outnet->num_ip4);
addr = &outnet->ip4_ifs[i].addr;
addrlen = outnet->ip4_ifs[i].addrlen;
}
/* create fd */
for(try = 0; try<1000; try++) {
int freebind = 0;
int noproto = 0;
int inuse = 0;
int port = ub_random(outnet->rnd)&0xffff;
int fd = -1;
if(addr_is_ip6(to_addr, to_addrlen)) {
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
sa.sin6_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
0, 0, 0, NULL, 0, freebind, 0);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
0, 0, 0, NULL, 0, freebind, 0);
}
if(fd != -1) {
return fd;
}
if(!inuse) {
return -1;
}
}
/* too many tries */
log_err("cannot send probe, ports are in use");
return -1;
}
struct comm_point*
outnet_comm_point_for_udp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen)
{
struct comm_point* cp;
int fd = fd_for_dest(outnet, to_addr, to_addrlen);
if(fd == -1) {
return NULL;
}
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
cb, cb_arg);
if(!cp) {
log_err("malloc failure");
close(fd);
return NULL;
}
return cp;
}
struct comm_point*
outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
sldns_buffer* query, int timeout)
{
struct comm_point* cp;
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
if(fd == -1) {
return 0;
}
fd_set_nonblock(fd);
if(!outnet_tcp_connect(fd, to_addr, to_addrlen)) {
/* outnet_tcp_connect has closed fd on error for us */
return 0;
}
cp = comm_point_create_tcp_out(outnet->base, 65552, cb, cb_arg);
if(!cp) {
log_err("malloc failure");
close(fd);
return 0;
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
/* set timeout on TCP connection */
comm_point_start_listening(cp, fd, timeout);
/* copy scratch buffer to cp->buffer */
sldns_buffer_copy(cp->buffer, query);
return cp;
}
/** get memory used by waiting tcp entry (in use or not) */
static size_t
waiting_tcp_get_mem(struct waiting_tcp* w)

View file

@ -537,6 +537,41 @@ size_t serviced_get_mem(struct serviced_query* sq);
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss);
/**
* Create udp commpoint suitable for sending packets to the destination.
* @param outnet: outside_network with the comm_base it is attached to,
* with the outgoing interfaces chosen from, and rnd gen for random.
* @param cb: callback function for the commpoint.
* @param cb_arg: callback argument for cb.
* @param to_addr: intended destination.
* @param to_addrlen: length of to_addr.
* @return commpoint that you can comm_point_send_udp_msg with, or NULL.
*/
struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen);
/**
* Create tcp commpoint suitable for communication to the destination.
* It also performs connect() to the to_addr.
* @param outnet: outside_network with the comm_base it is attached to,
* and the tcp_mss.
* @param cb: callback function for the commpoint.
* @param cb_arg: callback argument for cb.
* @param to_addr: intended destination.
* @param to_addrlen: length of to_addr.
* @param query: initial packet to send writing, in buffer. It is copied
* to the commpoint buffer that is created.
* @param timeout: timeout for the TCP connection.
* timeout in milliseconds, or -1 for no (change to the) timeout.
* So seconds*1000.
* @return commpoint that you can comm_point_send_udp_msg with, or NULL.
*/
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
struct sldns_buffer* query, int timeout);
/** connect tcp connection to addr, 0 on failure */
int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);

View file

@ -1437,7 +1437,6 @@ struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg))
{
/* could create a test framework; and intercept eg. authzone probes */
return NULL;
}
@ -1445,8 +1444,38 @@ struct comm_point* comm_point_create_tcp_out(struct comm_base*
ATTR_UNUSED(base), size_t ATTR_UNUSED(bufsize),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg))
{
return NULL;
}
struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen)
{
/* used by authzone transfers */
(void)outnet;
(void)cb;
(void)cb_arg;
(void)to_addr;
(void)to_addrlen;
/* TODO */
return NULL;
}
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
struct sldns_buffer* query, int timeout)
{
/* used by authzone transfers */
(void)outnet;
(void)cb;
(void)cb_arg;
(void)to_addr;
(void)to_addrlen;
(void)query;
(void)timeout;
/* TODO */
return NULL;
}