From 81ca7eac3dd45ba245de2526187f76c665aae11e Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Fri, 22 Apr 2016 18:48:58 -0700 Subject: Refactor the dns_open_connection code so that duplicate code is removed and ensure that EINTR is handled in the UDP path. Signed-off-by: Richard Sharpe Reviewed-by: Volker Lendecke --- lib/addns/dnssock.c | 94 ++++++++++++++++++++++------------------------------- 1 file changed, 39 insertions(+), 55 deletions(-) (limited to 'lib/addns') diff --git a/lib/addns/dnssock.c b/lib/addns/dnssock.c index a45e3255a54..ec42b7ca689 100644 --- a/lib/addns/dnssock.c +++ b/lib/addns/dnssock.c @@ -37,30 +37,22 @@ static int destroy_dns_connection(struct dns_connection *conn) /******************************************************************** ********************************************************************/ -static DNS_ERROR dns_tcp_open( const char *nameserver, - TALLOC_CTX *mem_ctx, - struct dns_connection **result ) +static DNS_ERROR dns_open_helper(const char *nameserver, + const char *service, + struct addrinfo *hints, + TALLOC_CTX *mem_ctx, + struct dns_connection **ret_conn) { - struct addrinfo hints; - struct addrinfo *ai_result = NULL; - struct addrinfo *rp; - struct dns_connection *conn; int ret; - char service[16]; - - snprintf(service, sizeof(service), "%d", DNS_TCP_PORT); + struct addrinfo *rp; + struct addrinfo *ai_result = NULL; + struct dns_connection *conn = NULL; if (!(conn = talloc(mem_ctx, struct dns_connection))) { return ERROR_DNS_NO_MEMORY; } - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = 0; - hints.ai_protocol = IPPROTO_TCP; - - ret = getaddrinfo(nameserver, service, &hints, &ai_result); + ret = getaddrinfo(nameserver, service, hints, &ai_result); if (ret != 0) { DEBUG(1,("dns_tcp_open: getaddrinfo: %s\n", gai_strerror(ret))); TALLOC_FREE(conn); @@ -86,7 +78,6 @@ static DNS_ERROR dns_tcp_open( const char *nameserver, freeaddrinfo(ai_result); - /* Failed to connect with any address */ if (rp == NULL) { TALLOC_FREE(conn); return ERROR_DNS_CONNECTION_FAILED; @@ -94,6 +85,32 @@ static DNS_ERROR dns_tcp_open( const char *nameserver, talloc_set_destructor(conn, destroy_dns_connection); + *ret_conn = conn; + return ERROR_DNS_SUCCESS; +} + +static DNS_ERROR dns_tcp_open( const char *nameserver, + TALLOC_CTX *mem_ctx, + struct dns_connection **result ) +{ + struct addrinfo hints; + struct dns_connection *conn; + DNS_ERROR dns_ret; + char service[16]; + + snprintf(service, sizeof(service), "%d", DNS_TCP_PORT); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = 0; + hints.ai_protocol = IPPROTO_TCP; + + dns_ret = dns_open_helper(nameserver, service, &hints, mem_ctx, &conn); + if (!ERR_DNS_IS_OK(dns_ret)) { + return dns_ret; + } + conn->hType = DNS_TCP; *result = conn; return ERROR_DNS_SUCCESS; @@ -107,58 +124,26 @@ static DNS_ERROR dns_udp_open( const char *nameserver, struct dns_connection **result ) { struct addrinfo hints; - struct addrinfo *ai_result = NULL; - struct addrinfo *rp; struct sockaddr_storage RecvAddr; struct dns_connection *conn; - int ret; + DNS_ERROR dns_ret; socklen_t RecvAddrLen; char service[16]; snprintf(service, sizeof(service), "%d", DNS_UDP_PORT); - if (!(conn = talloc(NULL, struct dns_connection))) { - return ERROR_DNS_NO_MEMORY; - } - memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = 0; hints.ai_protocol = IPPROTO_UDP; - ret = getaddrinfo(nameserver, service, &hints, &ai_result); - if (ret != 0) { - DEBUG(1,("dns_ucp_open:getaddrinfo: %s\n", gai_strerror(ret))); + dns_ret = dns_open_helper(nameserver, service, &hints, mem_ctx, &conn); + if (!ERR_DNS_IS_OK(dns_ret)) { TALLOC_FREE(conn); - return ERROR_DNS_INVALID_NAME_SERVER; + return dns_ret; } - for (rp = ai_result; rp != NULL; rp = rp->ai_next) { - conn->s = socket(rp->ai_family, - rp->ai_socktype, - rp->ai_protocol); - if (conn->s == -1) { - continue; - } - ret = connect(conn->s, rp->ai_addr, rp->ai_addrlen); - if (ret != -1) { - /* Successful connect */ - break; - } - close(conn->s); - } - - freeaddrinfo(ai_result); - - /* Failed to connect with any address */ - if (rp == NULL) { - TALLOC_FREE(conn); - return ERROR_DNS_CONNECTION_FAILED; - } - - talloc_set_destructor(conn, destroy_dns_connection); - /* Set up the RecvAddr structure with the IP address of the receiver and the specified port number. */ @@ -166,7 +151,6 @@ static DNS_ERROR dns_udp_open( const char *nameserver, if (getpeername(conn->s, (struct sockaddr *)&RecvAddr, &RecvAddrLen) == -1) { - TALLOC_FREE(conn); return ERROR_DNS_CONNECTION_FAILED; } -- cgit v1.2.1