From: Wouter Wijngaards Date: Tue, 12 Dec 2017 15:39:45 +0000 (+0000) Subject: - authzone work, transfer connect. X-Git-Tag: release-1.7.0rc1~138 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=30da6bde6f2524cff19a0afdb9b9504b68579d08;p=thirdparty%2Funbound.git - authzone work, transfer connect. git-svn-id: file:///svn/unbound/trunk@4420 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index 71aa945c7..46df1780d 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,9 @@ 12 December 2017: Ralph - Fix qname-minimisation documentation (A QTYPE, not NS) +12 December 2017: Wouter + - authzone work, transfer connect. + 7 December 2017: Ralph - Check whether --with-libunbound-only is set when using --with-nettle or --with-nss. diff --git a/services/authzone.c b/services/authzone.c index 819b8bb19..4eb6a69ca 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -3317,10 +3317,15 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env) } } - /* always new cp? TODO */ - /* TODO: set REUSEADDR and tcp nonblock, and call connect on fd */ + /* remove previous TCP connection (if any) */ + if(xfr->task_transfer->cp) { + comm_point_delete(xfr->task_transfer->cp); + xfr->task_transfer->cp = NULL; + } + + /* connect on fd */ if(!xfr->task_transfer->cp) { - int fd = xfr_fd_for_master(env, &addr, addrlen, master->host); + int fd = outnet_get_tcp_fd(&addr, addrlen, env->cfg->tcp_mss); if(fd == -1) { char zname[255+1]; dname_str(xfr->name, zname); @@ -3328,6 +3333,16 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env) "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); @@ -3339,9 +3354,6 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env) /* set timeout on TCP connection */ comm_point_start_listening(xfr->task_transfer->cp, fd, AUTH_TRANSFER_TIMEOUT); - } else { - comm_point_start_listening(xfr->task_transfer->cp, -1, - AUTH_TRANSFER_TIMEOUT); } /* set the packet to be written */ @@ -3486,13 +3498,28 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err, struct module_env* env; log_assert(xfr->task_probe); env = xfr->task_probe->env; - - /* TODO */ - (void)xfr; - (void)env; (void)repinfo; - (void)c; - (void)err; + + if(err != NETEVENT_NOERROR) { + /* connection failed, closed, or timeout */ + /* stop this transfer, cleanup + * and continue task_transfer*/ + verbose(VERB_ALGO, "xfr stopped, connection lost to %s", + xfr->task_transfer->master->host); + comm_point_close(c); + xfr_transfer_nexttarget_or_end(xfr, env); + return 0; + } + + /* TODO: handle returned packet */ + /* if it fails, cleanup and end this transfer */ + /* if it needs to fallback from IXFR to AXFR, do that */ + /* if it is good, link it into the list of data */ + + /* if we want to read more messages, setup the commpoint to read + * a DNS packet, and the timeout */ + c->tcp_is_reading = 1; + comm_point_start_listening(c, -1, AUTH_TRANSFER_TIMEOUT); return 0; } diff --git a/services/outside_network.c b/services/outside_network.c index ec9e11a0e..1e4059888 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -198,21 +198,17 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s) return 1; } -/** use next free buffer to service a tcp query */ -static int -outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) +/** get TCP file descriptor for address, returns -1 on failure, + * 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) { - struct pending_tcp* pend = w->outnet->tcp_free; int s; #ifdef SO_REUSEADDR int on = 1; #endif - log_assert(pend); - log_assert(pkt); - log_assert(w->addrlen > 0); - /* open socket */ #ifdef INET6 - if(addr_is_ip6(&w->addr, w->addrlen)) + if(addr_is_ip6(addr, addrlen)) s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); else #endif @@ -220,12 +216,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) if(s == -1) { #ifndef USE_WINSOCK log_err_addr("outgoing tcp: socket", strerror(errno), - &w->addr, w->addrlen); + addr, addrlen); #else log_err_addr("outgoing tcp: socket", - wsa_strerror(WSAGetLastError()), &w->addr, w->addrlen); + wsa_strerror(WSAGetLastError()), addr, addrlen); #endif - return 0; + return -1; } #ifdef SO_REUSEADDR @@ -235,11 +231,11 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) " setsockopt(.. SO_REUSEADDR ..) failed"); } #endif - if (w->outnet->tcp_mss > 0) { + + if(tcp_mss > 0) { #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG) if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, - (void*)&w->outnet->tcp_mss, - (socklen_t)sizeof(w->outnet->tcp_mss)) < 0) { + (void*)&tcp_mss, (socklen_t)sizeof(tcp_mss)) < 0) { verbose(VERB_ALGO, "outgoing tcp:" " setsockopt(.. TCP_MAXSEG ..) failed"); } @@ -249,6 +245,49 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) #endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */ } + return s; +} + +/** connect tcp connection to addr, 0 on failure */ +int +outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen) +{ + if(connect(s, (struct sockaddr*)addr, addrlen) == -1) { +#ifndef USE_WINSOCK +#ifdef EINPROGRESS + if(errno != EINPROGRESS) { +#endif + if(tcp_connect_errno_needs_log( + (struct sockaddr*)addr, addrlen)) + log_err_addr("outgoing tcp: connect", + strerror(errno), addr, addrlen); + close(s); +#ifdef EINPROGRESS + } +#endif +#else /* USE_WINSOCK */ + if(WSAGetLastError() != WSAEINPROGRESS && + WSAGetLastError() != WSAEWOULDBLOCK) { + closesocket(s); + } +#endif + return 0; + } + return 1; +} + +/** use next free buffer to service a tcp query */ +static int +outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) +{ + struct pending_tcp* pend = w->outnet->tcp_free; + int s; + log_assert(pend); + log_assert(pkt); + log_assert(w->addrlen > 0); + /* open socket */ + s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss); + if(!pick_outgoing_tcp(w, s)) return 0; diff --git a/services/outside_network.h b/services/outside_network.h index befd512f0..04e89a0b7 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -533,6 +533,13 @@ size_t outnet_get_mem(struct outside_network* outnet); */ size_t serviced_get_mem(struct serviced_query* sq); +/** get TCP file descriptor for address, returns -1 on failure, + * 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); + +/** connect tcp connection to addr, 0 on failure */ +int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen); + /** callback for incoming udp answers from the network */ int outnet_udp_cb(struct comm_point* c, void* arg, int error, struct comm_reply *reply_info); diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 48ca36357..cb7167477 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -1458,4 +1458,16 @@ int comm_point_send_udp_msg(struct comm_point *ATTR_UNUSED(c), return 0; } +int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss)) +{ + return -1; +} + +int outnet_tcp_connect(int ATTR_UNUSED(s), struct sockaddr_storage* ATTR_UNUSED(addr), + socklen_t ATTR_UNUSED(addrlen)) +{ + return 0; +} + /*********** End of Dummy routines ***********/