diff options
Diffstat (limited to 'ares_process.c')
-rw-r--r-- | ares_process.c | 133 |
1 files changed, 81 insertions, 52 deletions
diff --git a/ares_process.c b/ares_process.c index 4d7dcd3..1d1e7b8 100644 --- a/ares_process.c +++ b/ares_process.c @@ -1,6 +1,6 @@ /* Copyright 1998 by the Massachusetts Institute of Technology. - * Copyright (C) 2004-2013 by Daniel Stenberg + * Copyright (C) 2004-2016 by Daniel Stenberg * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without @@ -102,8 +102,7 @@ int ares__timedout(struct timeval *now, } /* add the specific number of milliseconds to the time in the first argument */ -int ares__timeadd(struct timeval *now, - int millisecs) +static void timeadd(struct timeval *now, int millisecs) { now->tv_sec += millisecs/1000; now->tv_usec += (millisecs%1000)*1000; @@ -112,19 +111,8 @@ int ares__timeadd(struct timeval *now, ++(now->tv_sec); now->tv_usec -= 1000000; } - - return 0; -} - -/* return time offset between now and (future) check, in milliseconds */ -long ares__timeoffset(struct timeval *now, - struct timeval *check) -{ - return (check->tv_sec - now->tv_sec)*1000 + - (check->tv_usec - now->tv_usec)/1000; } - /* * generic process function */ @@ -239,7 +227,7 @@ static void write_tcp_data(ares_channel channel, n++; /* Allocate iovecs so we can send all our data at once. */ - vec = malloc(n * sizeof(struct iovec)); + vec = ares_malloc(n * sizeof(struct iovec)); if (vec) { /* Fill in the iovecs and send. */ @@ -251,7 +239,7 @@ static void write_tcp_data(ares_channel channel, n++; } wcount = (ssize_t)writev(server->tcp_socket, vec, (int)n); - free(vec); + ares_free(vec); if (wcount < 0) { if (!try_again(SOCKERRNO)) @@ -293,8 +281,8 @@ static void advance_tcp_send_queue(ares_channel channel, int whichserver, num_bytes -= sendreq->len; server->qhead = sendreq->next; if (sendreq->data_storage) - free(sendreq->data_storage); - free(sendreq); + ares_free(sendreq->data_storage); + ares_free(sendreq); if (server->qhead == NULL) { SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0); server->qtail = NULL; @@ -373,9 +361,12 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, */ server->tcp_length = server->tcp_lenbuf[0] << 8 | server->tcp_lenbuf[1]; - server->tcp_buffer = malloc(server->tcp_length); - if (!server->tcp_buffer) + server->tcp_buffer = ares_malloc(server->tcp_length); + if (!server->tcp_buffer) { handle_error(channel, i, now); + return; /* bail out on malloc failure. TODO: make this + function return error codes */ + } server->tcp_buffer_pos = 0; } } @@ -400,8 +391,7 @@ static void read_tcp_data(ares_channel channel, fd_set *read_fds, */ process_answer(channel, server->tcp_buffer, server->tcp_length, i, 1, now); - if (server->tcp_buffer) - free(server->tcp_buffer); + ares_free(server->tcp_buffer); server->tcp_buffer = NULL; server->tcp_lenbuf_pos = 0; server->tcp_buffer_pos = 0; @@ -575,14 +565,15 @@ static void process_answer(ares_channel channel, unsigned char *abuf, packetsz = channel->ednspsz; if (rcode == NOTIMP || rcode == FORMERR || rcode == SERVFAIL) { - int qlen = alen - EDNSFIXEDSZ; + int qlen = (query->tcplen - 2) - EDNSFIXEDSZ; channel->flags ^= ARES_FLAG_EDNS; query->tcplen -= EDNSFIXEDSZ; query->qlen -= EDNSFIXEDSZ; query->tcpbuf[0] = (unsigned char)((qlen >> 8) & 0xff); query->tcpbuf[1] = (unsigned char)(qlen & 0xff); DNS_HEADER_SET_ARCOUNT(query->tcpbuf + 2, 0); - query->tcpbuf = realloc(query->tcpbuf, query->tcplen); + query->tcpbuf = ares_realloc(query->tcpbuf, query->tcplen); + query->qbuf = query->tcpbuf + 2; ares__send_query(channel, query, now); return; } @@ -781,12 +772,13 @@ void ares__send_query(ares_channel channel, struct query *query, return; } } - sendreq = calloc(1, sizeof(struct send_request)); + sendreq = ares_malloc(sizeof(struct send_request)); if (!sendreq) { end_query(channel, query, ARES_ENOMEM, NULL, 0); return; } + memset(sendreq, 0, sizeof(struct send_request)); /* To make the common case fast, we avoid copies by using the query's * tcpbuf for as long as the query is alive. In the rare case where the * query ends while it's queued for transmission, then we give the @@ -831,8 +823,7 @@ void ares__send_query(ares_channel channel, struct query *query, timeplus = channel->timeout << (query->try_count / channel->nservers); timeplus = (timeplus * (9 + (rand () & 7))) / 16; query->timeout = *now; - ares__timeadd(&query->timeout, - timeplus); + timeadd(&query->timeout, timeplus); /* Keep track of queries bucketed by timeout, so we can process * timeout events quickly. */ @@ -856,7 +847,7 @@ void ares__send_query(ares_channel channel, struct query *query, * portable. */ static int setsocknonblock(ares_socket_t sockfd, /* operate on this */ - int nonblock /* TRUE or FALSE */) + int nonblock /* TRUE or FALSE */) { #if defined(USE_BLOCKING_SOCKETS) @@ -870,7 +861,7 @@ static int setsocknonblock(ares_socket_t sockfd, /* operate on this */ if (FALSE != nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else - return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); /* LCOV_EXCL_LINE */ #elif defined(HAVE_IOCTL_FIONBIO) @@ -913,12 +904,12 @@ static int configure_socket(ares_socket_t s, int family, ares_channel channel) struct sockaddr_in6 sa6; } local; - setsocknonblock(s, TRUE); + (void)setsocknonblock(s, TRUE); -#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) && !defined(MSDOS) +#if defined(FD_CLOEXEC) && !defined(MSDOS) /* Configure the socket fd as close-on-exec. */ if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) - return -1; + return -1; /* LCOV_EXCL_LINE */ #endif /* Set the socket's send and receive buffer sizes. */ @@ -986,7 +977,11 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa4); memset(sa, 0, salen); saddr.sa4.sin_family = AF_INET; - saddr.sa4.sin_port = aresx_sitous(channel->tcp_port); + if (server->addr.tcp_port) { + saddr.sa4.sin_port = aresx_sitous(server->addr.tcp_port); + } else { + saddr.sa4.sin_port = aresx_sitous(channel->tcp_port); + } memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, sizeof(server->addr.addrV4)); break; @@ -995,16 +990,20 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa6); memset(sa, 0, salen); saddr.sa6.sin6_family = AF_INET6; - saddr.sa6.sin6_port = aresx_sitous(channel->tcp_port); + if (server->addr.tcp_port) { + saddr.sa6.sin6_port = aresx_sitous(server->addr.tcp_port); + } else { + saddr.sa6.sin6_port = aresx_sitous(channel->tcp_port); + } memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, sizeof(server->addr.addrV6)); break; default: - return -1; + return -1; /* LCOV_EXCL_LINE */ } /* Acquire a socket. */ - s = socket(server->addr.family, SOCK_STREAM | SOCK_CLOEXEC, 0); + s = socket(server->addr.family, SOCK_STREAM, 0); if (s == ARES_SOCKET_BAD) return -1; @@ -1031,6 +1030,17 @@ static int open_tcp_socket(ares_channel channel, struct server_state *server) } #endif + if (channel->sock_config_cb) + { + int err = channel->sock_config_cb(s, SOCK_STREAM, + channel->sock_config_cb_data); + if (err < 0) + { + sclose(s); + return err; + } + } + /* Connect to the server. */ if (connect(s, sa, salen) == -1) { @@ -1078,7 +1088,11 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa4); memset(sa, 0, salen); saddr.sa4.sin_family = AF_INET; - saddr.sa4.sin_port = aresx_sitous(channel->udp_port); + if (server->addr.udp_port) { + saddr.sa4.sin_port = aresx_sitous(server->addr.udp_port); + } else { + saddr.sa4.sin_port = aresx_sitous(channel->udp_port); + } memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, sizeof(server->addr.addrV4)); break; @@ -1087,16 +1101,20 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) salen = sizeof(saddr.sa6); memset(sa, 0, salen); saddr.sa6.sin6_family = AF_INET6; - saddr.sa6.sin6_port = aresx_sitous(channel->udp_port); + if (server->addr.udp_port) { + saddr.sa6.sin6_port = aresx_sitous(server->addr.udp_port); + } else { + saddr.sa6.sin6_port = aresx_sitous(channel->udp_port); + } memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, sizeof(server->addr.addrV6)); break; default: - return -1; + return -1; /* LCOV_EXCL_LINE */ } /* Acquire a socket. */ - s = socket(server->addr.family, SOCK_DGRAM | SOCK_CLOEXEC, 0); + s = socket(server->addr.family, SOCK_DGRAM, 0); if (s == ARES_SOCKET_BAD) return -1; @@ -1107,6 +1125,17 @@ static int open_udp_socket(ares_channel channel, struct server_state *server) return -1; } + if (channel->sock_config_cb) + { + int err = channel->sock_config_cb(s, SOCK_DGRAM, + channel->sock_config_cb_data); + if (err < 0) + { + sclose(s); + return err; + } + } + /* Connect to the server. */ if (connect(s, sa, salen) == -1) { @@ -1169,7 +1198,7 @@ static int same_questions(const unsigned char *qbuf, int qlen, q.p += q.namelen; if (q.p + QFIXEDSZ > qbuf + qlen) { - free(q.name); + ares_free(q.name); return 0; } q.type = DNS_QUESTION_TYPE(q.p); @@ -1184,14 +1213,14 @@ static int same_questions(const unsigned char *qbuf, int qlen, if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) != ARES_SUCCESS) { - free(q.name); + ares_free(q.name); return 0; } a.p += a.namelen; if (a.p + QFIXEDSZ > abuf + alen) { - free(q.name); - free(a.name); + ares_free(q.name); + ares_free(a.name); return 0; } a.type = DNS_QUESTION_TYPE(a.p); @@ -1202,13 +1231,13 @@ static int same_questions(const unsigned char *qbuf, int qlen, if (strcasecmp(q.name, a.name) == 0 && q.type == a.type && q.dnsclass == a.dnsclass) { - free(a.name); + ares_free(a.name); break; } - free(a.name); + ares_free(a.name); } - free(q.name); + ares_free(q.name); if (j == a.qdcount) return 0; } @@ -1237,7 +1266,7 @@ static int same_address(struct sockaddr *sa, struct ares_addr *aa) return 1; /* match */ break; default: - break; + break; /* LCOV_EXCL_LINE */ } } return 0; /* different */ @@ -1274,7 +1303,7 @@ static void end_query (ares_channel channel, struct query *query, int status, * to the query's tcpbuf and handle these cases, we just give * such sendreqs their own copy of the query packet. */ - sendreq->data_storage = malloc(sendreq->len); + sendreq->data_storage = ares_malloc(sendreq->len); if (sendreq->data_storage != NULL) { memcpy(sendreq->data_storage, sendreq->data, sendreq->len); @@ -1324,7 +1353,7 @@ void ares__free_query(struct query *query) query->callback = NULL; query->arg = NULL; /* Deallocate the memory associated with the query */ - free(query->tcpbuf); - free(query->server_info); - free(query); + ares_free(query->tcpbuf); + ares_free(query->server_info); + ares_free(query); } |