From 84e819dc312bf04da272a7800ebbd5ee9ef1366f Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 31 Jan 2018 14:59:17 +0000 Subject: [PATCH] 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 --- services/authzone.c | 124 +++++-------------------------------- services/outside_network.c | 116 ++++++++++++++++++++++++++++++++++ services/outside_network.h | 35 +++++++++++ testcode/fake_event.c | 31 +++++++++- 4 files changed, 197 insertions(+), 109 deletions(-) diff --git a/services/authzone.c b/services/authzone.c index b391eb24c..6efe2e1f8 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -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, diff --git a/services/outside_network.c b/services/outside_network.c index 1e4059888..bda2fa12e 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -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) diff --git a/services/outside_network.h b/services/outside_network.h index 04e89a0b7..674acff9a 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -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); diff --git a/testcode/fake_event.c b/testcode/fake_event.c index cb7167477..e999896ec 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -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; } -- 2.47.3