#include <sys/time.h>
#include <unistd.h>
#include "system/select.h"
+#include "../lib/util/debug.h"
static int destroy_dns_connection(struct dns_connection *conn)
{
TALLOC_CTX *mem_ctx,
struct dns_connection **result )
{
- uint32_t ulAddress;
- struct hostent *pHost;
- struct sockaddr_in s_in;
+ struct addrinfo hints;
+ struct addrinfo *ai_result = NULL;
+ struct addrinfo *rp;
struct dns_connection *conn;
- int res;
+ int ret;
+ char service[16];
+
+ snprintf(service, sizeof(service), "%d", DNS_TCP_PORT);
if (!(conn = talloc(mem_ctx, struct dns_connection))) {
return ERROR_DNS_NO_MEMORY;
}
- if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
- if ( (pHost = gethostbyname( nameserver )) == NULL ) {
- TALLOC_FREE(conn);
- return ERROR_DNS_INVALID_NAME_SERVER;
- }
- memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
- }
+ 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;
- conn->s = socket( PF_INET, SOCK_STREAM, 0 );
- if (conn->s == -1) {
+ ret = getaddrinfo(nameserver, service, &hints, &ai_result);
+ if (ret != 0) {
+ DEBUG(1,("dns_tcp_open: getaddrinfo: %s\n", gai_strerror(ret)));
TALLOC_FREE(conn);
- return ERROR_DNS_CONNECTION_FAILED;
+ return ERROR_DNS_INVALID_NAME_SERVER;
}
- talloc_set_destructor(conn, destroy_dns_connection);
+ 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;
+ }
+ do {
+ ret = connect(conn->s, rp->ai_addr, rp->ai_addrlen);
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret != -1) {
+ /* Successful connect */
+ break;
+ }
+ close(conn->s);
+ }
- s_in.sin_family = AF_INET;
- s_in.sin_addr.s_addr = ulAddress;
- s_in.sin_port = htons( DNS_TCP_PORT );
+ freeaddrinfo(ai_result);
- res = connect(conn->s, (struct sockaddr*)&s_in, sizeof( s_in ));
- if (res == -1) {
+ /* Failed to connect with any address */
+ if (rp == NULL) {
TALLOC_FREE(conn);
return ERROR_DNS_CONNECTION_FAILED;
}
- conn->hType = DNS_TCP;
+ talloc_set_destructor(conn, destroy_dns_connection);
+ conn->hType = DNS_TCP;
*result = conn;
return ERROR_DNS_SUCCESS;
}
/********************************************************************
-********************************************************************/
+ * ********************************************************************/
static DNS_ERROR dns_udp_open( const char *nameserver,
TALLOC_CTX *mem_ctx,
struct dns_connection **result )
{
- unsigned long ulAddress;
- struct hostent *pHost;
- struct sockaddr_in RecvAddr;
+ struct addrinfo hints;
+ struct addrinfo *ai_result = NULL;
+ struct addrinfo *rp;
+ struct sockaddr_storage RecvAddr;
struct dns_connection *conn;
+ int 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;
}
- if ( (ulAddress = inet_addr( nameserver )) == INADDR_NONE ) {
- if ( (pHost = gethostbyname( nameserver )) == NULL ) {
- TALLOC_FREE(conn);
- return ERROR_DNS_INVALID_NAME_SERVER;
+ 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)));
+ TALLOC_FREE(conn);
+ return ERROR_DNS_INVALID_NAME_SERVER;
+ }
+
+ 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;
}
- memcpy( &ulAddress, pHost->h_addr, pHost->h_length );
+ close(conn->s);
}
- /* Create a socket for sending data */
+ freeaddrinfo(ai_result);
- conn->s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
- if (conn->s == -1) {
+ /* 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 (in this example case "123.456.789.1")
- and the specified port number. */
+ the receiver and the specified port number. */
- ZERO_STRUCT(RecvAddr);
- RecvAddr.sin_family = AF_INET;
- RecvAddr.sin_port = htons( DNS_UDP_PORT );
- RecvAddr.sin_addr.s_addr = ulAddress;
+ RecvAddrLen = sizeof(RecvAddr);
+ if (getpeername(conn->s,
+ (struct sockaddr *)&RecvAddr,
+ &RecvAddrLen) == -1) {
+ TALLOC_FREE(conn);
+ return ERROR_DNS_CONNECTION_FAILED;
+ }
conn->hType = DNS_UDP;
- memcpy( &conn->RecvAddr, &RecvAddr, sizeof( struct sockaddr_in ) );
+ memcpy(&conn->RecvAddr, &RecvAddr, sizeof(struct sockaddr_storage));
*result = conn;
return ERROR_DNS_SUCCESS;
/********************************************************************
********************************************************************/
-DNS_ERROR dns_open_connection( const char *nameserver, int32 dwType,
+DNS_ERROR dns_open_connection( const char *nameserver, int32_t dwType,
TALLOC_CTX *mem_ctx,
struct dns_connection **conn )
{
return ERROR_DNS_INVALID_PARAMETER;
}
-static DNS_ERROR write_all(int fd, uint8 *data, size_t len)
+static DNS_ERROR write_all(int fd, uint8_t *data, size_t len)
{
size_t total = 0;
while (total < len) {
- ssize_t ret = write(fd, data + total, len - total);
+ ssize_t ret;
+
+ do {
+ ret = write(fd, data + total, len - total);
+ } while ((ret == -1) && (errno == EINTR));
if (ret <= 0) {
/*
static DNS_ERROR dns_send_tcp(struct dns_connection *conn,
const struct dns_buffer *buf)
{
- uint16 len = htons(buf->offset);
+ uint16_t len = htons(buf->offset);
DNS_ERROR err;
- err = write_all(conn->s, (uint8 *)&len, sizeof(len));
+ err = write_all(conn->s, (uint8_t *)&len, sizeof(len));
if (!ERR_DNS_IS_OK(err)) return err;
return write_all(conn->s, buf->data, buf->offset);
{
ssize_t ret;
- ret = sendto(conn->s, buf->data, buf->offset, 0,
+ do {
+ ret = sendto(conn->s, buf->data, buf->offset, 0,
(struct sockaddr *)&conn->RecvAddr,
sizeof(conn->RecvAddr));
+ } while ((ret == -1) && (errno == EINTR));
if (ret != buf->offset) {
return ERROR_DNS_SOCKET_ERROR;
return ERROR_DNS_INVALID_PARAMETER;
}
-static DNS_ERROR read_all(int fd, uint8 *data, size_t len)
+static DNS_ERROR read_all(int fd, uint8_t *data, size_t len)
{
size_t total = 0;
pfd.events = POLLIN|POLLHUP;
fd_ready = poll(&pfd, 1, 10000);
+ if (fd_ready == -1) {
+ if (errno == EINTR) {
+ continue;
+ }
+ return ERROR_DNS_SOCKET_ERROR;
+ }
if ( fd_ready == 0 ) {
/* read timeout */
return ERROR_DNS_SOCKET_ERROR;
}
- ret = read(fd, data + total, len - total);
+ do {
+ ret = read(fd, data + total, len - total);
+ } while ((ret == -1) && (errno == EINTR));
+
if (ret <= 0) {
/* EOF or error */
return ERROR_DNS_SOCKET_ERROR;
{
struct dns_buffer *buf;
DNS_ERROR err;
- uint16 len;
+ uint16_t len;
if (!(buf = talloc_zero(mem_ctx, struct dns_buffer))) {
return ERROR_DNS_NO_MEMORY;
}
- err = read_all(conn->s, (uint8 *)&len, sizeof(len));
+ err = read_all(conn->s, (uint8_t *)&len, sizeof(len));
if (!ERR_DNS_IS_OK(err)) {
return err;
}
buf->size = ntohs(len);
- if (buf->size) {
- if (!(buf->data = talloc_array(buf, uint8, buf->size))) {
- TALLOC_FREE(buf);
- return ERROR_DNS_NO_MEMORY;
- }
- } else {
- buf->data = NULL;
+ if (buf->size == 0) {
+ *presult = buf;
+ return ERROR_DNS_SUCCESS;
+ }
+
+ if (!(buf->data = talloc_array(buf, uint8_t, buf->size))) {
+ TALLOC_FREE(buf);
+ return ERROR_DNS_NO_MEMORY;
}
- err = read_all(conn->s, buf->data, buf->size);
+ err = read_all(conn->s, buf->data, talloc_get_size(buf->data));
if (!ERR_DNS_IS_OK(err)) {
TALLOC_FREE(buf);
return err;
* UDP based DNS can only be 512 bytes
*/
- if (!(buf->data = talloc_array(buf, uint8, 512))) {
+ if (!(buf->data = talloc_array(buf, uint8_t, 512))) {
TALLOC_FREE(buf);
return ERROR_DNS_NO_MEMORY;
}
- received = recv(conn->s, (void *)buf->data, 512, 0);
+ do {
+ received = recv(conn->s, (void *)buf->data, 512, 0);
+ } while ((received == -1) && (errno == EINTR));
if (received == -1) {
TALLOC_FREE(buf);