1968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 2968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Copyright 1998 by the Massachusetts Institute of Technology. 3968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Copyright (C) 2004-2010 by Daniel Stenberg 4968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * 5968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Permission to use, copy, modify, and distribute this 6968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software and its documentation for any purpose and without 7968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * fee is hereby granted, provided that the above copyright 8968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice appear in all copies and that both that copyright 9968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * notice and this permission notice appear in supporting 10968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * documentation, and that the name of M.I.T. not be used in 11968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * advertising or publicity pertaining to distribution of the 12968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * software without specific, written prior permission. 13968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * M.I.T. makes no representations about the suitability of 14968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this software for any purpose. It is provided "as is" 15968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * without express or implied warranty. 16968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 17968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 18968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_setup.h" 19968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 20968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_SOCKET_H 21968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/socket.h> 22968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 23968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_UIO_H 24968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/uio.h> 25968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 26968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_IN_H 27968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netinet/in.h> 28968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 29968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETINET_TCP_H 30968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netinet/tcp.h> 31968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 32968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_NETDB_H 33968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <netdb.h> 34968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 35968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_H 36968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser.h> 37968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 38968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include "nameser.h" 39968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 40968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_ARPA_NAMESER_COMPAT_H 41968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <arpa/nameser_compat.h> 42968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 43968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 44968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_TIME_H 45968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/time.h> 46968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 47968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 48968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_STRINGS_H 49968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <strings.h> 50968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 51968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_UNISTD_H 52968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <unistd.h> 53968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 54968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_SYS_IOCTL_H 55968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/ioctl.h> 56968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 57968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef NETWARE 58968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# include <sys/filio.h> 59968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 60968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 61968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <assert.h> 62968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <string.h> 63968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <stdlib.h> 64968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <fcntl.h> 65968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include <time.h> 66968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 67968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares.h" 68968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_dns.h" 69968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_nowarn.h" 70968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#include "ares_private.h" 71968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 72968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 73968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int try_again(int errnum); 74968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void write_tcp_data(ares_channel channel, fd_set *write_fds, 75968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t write_fd, struct timeval *now); 76968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_tcp_data(ares_channel channel, fd_set *read_fds, 77968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t read_fd, struct timeval *now); 78968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_udp_packets(ares_channel channel, fd_set *read_fds, 79968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t read_fd, struct timeval *now); 80968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void advance_tcp_send_queue(ares_channel channel, int whichserver, 81968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t num_bytes); 82968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_timeouts(ares_channel channel, struct timeval *now); 83968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_broken_connections(ares_channel channel, 84968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now); 85968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_answer(ares_channel channel, unsigned char *abuf, 86968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int alen, int whichserver, int tcp, 87968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now); 88968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void handle_error(ares_channel channel, int whichserver, 89968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now); 90968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void skip_server(ares_channel channel, struct query *query, 91968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int whichserver); 92968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void next_server(ares_channel channel, struct query *query, 93968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now); 94968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_tcp_socket(ares_channel channel, struct server_state *server); 95968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_udp_socket(ares_channel channel, struct server_state *server); 96968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_questions(const unsigned char *qbuf, int qlen, 97968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *abuf, int alen); 98968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_address(struct sockaddr *sa, struct ares_addr *aa); 99968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void end_query(ares_channel channel, struct query *query, int status, 100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned char *abuf, int alen); 101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* return true if now is exactly check time or later */ 103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares__timedout(struct timeval *now, 104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *check) 105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold long secs = (now->tv_sec - check->tv_sec); 107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(secs > 0) 109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; /* yes, timed out */ 110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(secs < 0) 111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; /* nope, not timed out */ 112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* if the full seconds were identical, check the sub second parts */ 114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return (now->tv_usec - check->tv_usec >= 0); 115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* add the specific number of milliseconds to the time in the first argument */ 118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldint ares__timeadd(struct timeval *now, 119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int millisecs) 120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold now->tv_sec += millisecs/1000; 122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold now->tv_usec += (millisecs%1000)*1000; 123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(now->tv_usec >= 1000000) { 125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ++(now->tv_sec); 126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold now->tv_usec -= 1000000; 127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* return time offset between now and (future) check, in milliseconds */ 133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldlong ares__timeoffset(struct timeval *now, 134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *check) 135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return (check->tv_sec - now->tv_sec)*1000 + 137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (check->tv_usec - now->tv_usec)/1000; 138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* 142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * generic process function 143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void processfds(ares_channel channel, 145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fd_set *read_fds, ares_socket_t read_fd, 146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fd_set *write_fds, ares_socket_t write_fd) 147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval now = ares__tvnow(); 149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold write_tcp_data(channel, write_fds, write_fd, &now); 151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold read_tcp_data(channel, read_fds, read_fd, &now); 152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold read_udp_packets(channel, read_fds, read_fd, &now); 153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold process_timeouts(channel, &now); 154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold process_broken_connections(channel, &now); 155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Something interesting happened on the wire, or there was a timeout. 158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * See what's up and respond accordingly. 159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds) 161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold processfds(channel, read_fds, ARES_SOCKET_BAD, write_fds, ARES_SOCKET_BAD); 163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Something interesting happened on the wire, or there was a timeout. 166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * See what's up and respond accordingly. 167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares_process_fd(ares_channel channel, 169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t read_fd, /* use ARES_SOCKET_BAD or valid 170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold file descriptors */ 171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t write_fd) 172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold processfds(channel, NULL, read_fd, NULL, write_fd); 174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Return 1 if the specified error number describes a readiness error, or 0 178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * otherwise. This is mostly for HP-UX, which could return EAGAIN or 179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * EWOULDBLOCK. See this man page 180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * 181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html? 182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * manpage=/usr/share/man/man2.Z/send.2 183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int try_again(int errnum) 185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if !defined EWOULDBLOCK && !defined EAGAIN 187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#error "Neither EWOULDBLOCK nor EAGAIN defined" 188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold switch (errnum) 190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef EWOULDBLOCK 192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case EWOULDBLOCK: 193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; 194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined EAGAIN && EAGAIN != EWOULDBLOCK 196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case EAGAIN: 197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; 198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 202968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 203968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any TCP sockets select true for writing, write out queued data 204968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * we have for them. 205968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 206968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void write_tcp_data(ares_channel channel, 207968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fd_set *write_fds, 208968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t write_fd, 209968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 210968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 211968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 212968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct send_request *sendreq; 213968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct iovec *vec; 214968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i; 215968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t scount; 216968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t wcount; 217968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold size_t n; 218968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 219968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!write_fds && (write_fd == ARES_SOCKET_BAD)) 220968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* no possible action */ 221968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 222968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 223968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 224968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 225968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Make sure server has data to send and is selected in write_fds or 226968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold write_fd. */ 227968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[i]; 228968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD || 229968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->is_broken) 230968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 231968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 232968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(write_fds) { 233968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!FD_ISSET(server->tcp_socket, write_fds)) 234968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 235968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 236968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else { 237968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(server->tcp_socket != write_fd) 238968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 239968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 240968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 241968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(write_fds) 242968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If there's an error and we close this socket, then open 243968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * another with the same fd to talk to another server, then we 244968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * don't want to think that it was the new socket that was 245968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * ready. This is not disastrous, but is likely to result in 246968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * extra system calls and confusion. */ 247968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold FD_CLR(server->tcp_socket, write_fds); 248968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 249968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Count the number of send queue items. */ 250968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold n = 0; 251968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 252968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold n++; 253968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 254968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Allocate iovecs so we can send all our data at once. */ 255968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold vec = malloc(n * sizeof(struct iovec)); 256968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (vec) 257968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 258968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Fill in the iovecs and send. */ 259968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold n = 0; 260968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 261968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 262968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold vec[n].iov_base = (char *) sendreq->data; 263968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold vec[n].iov_len = sendreq->len; 264968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold n++; 265968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 266968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold wcount = (ssize_t)writev(server->tcp_socket, vec, (int)n); 267968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(vec); 268968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (wcount < 0) 269968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 270968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!try_again(SOCKERRNO)) 271968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 272968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 273968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 274968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 275968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Advance the send queue by as many bytes as we sent. */ 276968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold advance_tcp_send_queue(channel, i, wcount); 277968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 278968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 279968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 280968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Can't allocate iovecs; just send the first request. */ 281968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq = server->qhead; 282968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 283968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold scount = swrite(server->tcp_socket, sendreq->data, sendreq->len); 284968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (scount < 0) 285968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 286968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!try_again(SOCKERRNO)) 287968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 288968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 289968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 290968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 291968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Advance the send queue by as many bytes as we sent. */ 292968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold advance_tcp_send_queue(channel, i, scount); 293968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 294968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 295968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 296968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 297968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Consume the given number of bytes from the head of the TCP send queue. */ 298968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void advance_tcp_send_queue(ares_channel channel, int whichserver, 299968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t num_bytes) 300968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 301968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct send_request *sendreq; 302968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server = &channel->servers[whichserver]; 303968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold while (num_bytes > 0) { 304968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq = server->qhead; 305968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((size_t)num_bytes >= sendreq->len) { 306968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold num_bytes -= sendreq->len; 307968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->qhead = sendreq->next; 308968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sendreq->data_storage) 309968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(sendreq->data_storage); 310968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(sendreq); 311968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->qhead == NULL) { 312968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0); 313968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->qtail = NULL; 314968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 315968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* qhead is NULL so we cannot continue this loop */ 316968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 317968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 318968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 319968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else { 320968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data += num_bytes; 321968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->len -= num_bytes; 322968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold num_bytes = 0; 323968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 324968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 325968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 326968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 327968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any TCP socket selects true for reading, read some data, 328968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * allocate a buffer if we finish reading the length word, and process 329968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * a packet if we finish reading one. 330968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 331968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_tcp_data(ares_channel channel, fd_set *read_fds, 332968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t read_fd, struct timeval *now) 333968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 334968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 335968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i; 336968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t count; 337968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 338968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!read_fds && (read_fd == ARES_SOCKET_BAD)) 339968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* no possible action */ 340968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 341968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 342968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 343968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 344968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Make sure the server has a socket and is selected in read_fds. */ 345968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[i]; 346968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_socket == ARES_SOCKET_BAD || server->is_broken) 347968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 348968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 349968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(read_fds) { 350968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!FD_ISSET(server->tcp_socket, read_fds)) 351968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 352968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 353968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else { 354968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(server->tcp_socket != read_fd) 355968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 356968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 357968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 358968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(read_fds) 359968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If there's an error and we close this socket, then open 360968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * another with the same fd to talk to another server, then we 361968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * don't want to think that it was the new socket that was 362968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * ready. This is not disastrous, but is likely to result in 363968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * extra system calls and confusion. */ 364968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold FD_CLR(server->tcp_socket, read_fds); 365968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 366968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_lenbuf_pos != 2) 367968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 368968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We haven't yet read a length word, so read that (or 369968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * what's left to read of it). 370968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 371968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold count = sread(server->tcp_socket, 372968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_lenbuf + server->tcp_lenbuf_pos, 373968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 2 - server->tcp_lenbuf_pos); 374968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (count <= 0) 375968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 376968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!(count == -1 && try_again(SOCKERRNO))) 377968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 378968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 379968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 380968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 381968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_lenbuf_pos += (int)count; 382968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_lenbuf_pos == 2) 383968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 384968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We finished reading the length word. Decode the 385968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * length and allocate a buffer for the data. 386968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 387968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_length = server->tcp_lenbuf[0] << 8 388968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold | server->tcp_lenbuf[1]; 389968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer = malloc(server->tcp_length); 390968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!server->tcp_buffer) 391968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 392968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer_pos = 0; 393968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 394968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 395968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 396968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 397968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Read data into the allocated buffer. */ 398968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold count = sread(server->tcp_socket, 399968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer + server->tcp_buffer_pos, 400968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_length - server->tcp_buffer_pos); 401968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (count <= 0) 402968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 403968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!(count == -1 && try_again(SOCKERRNO))) 404968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 405968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 406968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 407968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 408968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer_pos += (int)count; 409968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_buffer_pos == server->tcp_length) 410968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 411968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We finished reading this answer; process it and 412968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * prepare to read another length word. 413968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 414968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold process_answer(channel, server->tcp_buffer, server->tcp_length, 415968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold i, 1, now); 416968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_buffer) 417968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(server->tcp_buffer); 418968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer = NULL; 419968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_lenbuf_pos = 0; 420968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer_pos = 0; 421968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 422968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 423968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 424968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 425968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 426968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any UDP sockets select true for reading, process them. */ 427968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void read_udp_packets(ares_channel channel, fd_set *read_fds, 428968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t read_fd, struct timeval *now) 429968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 430968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 431968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i; 432968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ssize_t count; 433968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned char buf[PACKETSZ + 1]; 434968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM 435968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socklen_t fromlen; 436968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold union { 437968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr sa; 438968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in sa4; 439968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 sa6; 440968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } from; 441968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 442968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 443968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!read_fds && (read_fd == ARES_SOCKET_BAD)) 444968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* no possible action */ 445968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 446968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 447968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 448968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 449968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Make sure the server has a socket and is selected in read_fds. */ 450968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[i]; 451968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 452968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->udp_socket == ARES_SOCKET_BAD || server->is_broken) 453968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 454968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 455968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(read_fds) { 456968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(!FD_ISSET(server->udp_socket, read_fds)) 457968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 458968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 459968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else { 460968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(server->udp_socket != read_fd) 461968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 462968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 463968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 464968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if(read_fds) 465968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If there's an error and we close this socket, then open 466968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * another with the same fd to talk to another server, then we 467968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * don't want to think that it was the new socket that was 468968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * ready. This is not disastrous, but is likely to result in 469968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * extra system calls and confusion. */ 470968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold FD_CLR(server->udp_socket, read_fds); 471968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 472968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* To reduce event loop overhead, read and process as many 473968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * packets as we can. */ 474968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold do { 475968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM 476968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->addr.family == AF_INET) 477968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fromlen = sizeof(from.sa4); 478968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 479968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold fromlen = sizeof(from.sa6); 480968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf), 481968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 0, &from.sa, &fromlen); 482968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 483968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold count = sread(server->udp_socket, buf, sizeof(buf)); 484968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 485968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (count == -1 && try_again(SOCKERRNO)) 486968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold continue; 487968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (count <= 0) 488968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 489968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef HAVE_RECVFROM 490968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (!same_address(&from.sa, &server->addr)) 491968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* The address the response comes from does not match 492968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * the address we sent the request to. Someone may be 493968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * attempting to perform a cache poisoning attack. */ 494968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 495968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 496968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 497968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold process_answer(channel, buf, (int)count, i, 0, now); 498968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } while (count > 0); 499968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 500968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 501968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 502968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* If any queries have timed out, note the timeout and move them on. */ 503968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_timeouts(ares_channel channel, struct timeval *now) 504968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 505968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold time_t t; /* the time of the timeouts we're processing */ 506968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct query *query; 507968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node* list_head; 508968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node* list_node; 509968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 510968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Process all the timeouts that have fired since the last time we 511968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * processed timeouts. If things are going well, then we'll have 512968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * hundreds/thousands of queries that fall into future buckets, and 513968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * only a handful of requests that fall into the "now" bucket, so 514968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this should be quite quick. 515968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 516968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (t = channel->last_timeout_processed; t <= now->tv_sec; t++) 517968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 518968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold list_head = &(channel->queries_by_timeout[t % ARES_TIMEOUT_TABLE_SIZE]); 519968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (list_node = list_head->next; list_node != list_head; ) 520968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 521968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query = list_node->data; 522968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold list_node = list_node->next; /* in case the query gets deleted */ 523968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (query->timeout.tv_sec && ares__timedout(now, &query->timeout)) 524968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 525968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->error_status = ARES_ETIMEOUT; 526968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ++query->timeouts; 527968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 528968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 529968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 530968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 531968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold channel->last_timeout_processed = now->tv_sec; 532968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 533968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 534968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Handle an answer from a server. */ 535968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_answer(ares_channel channel, unsigned char *abuf, 536968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int alen, int whichserver, int tcp, 537968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 538968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 539968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int tc, rcode; 540968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned short id; 541968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct query *query; 542968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node* list_head; 543968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node* list_node; 544968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 545968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If there's no room in the answer for a header, we can't do much 546968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * with it. */ 547968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (alen < HFIXEDSZ) 548968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 549968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 550968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Grab the query ID, truncate bit, and response code from the packet. */ 551968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold id = DNS_HEADER_QID(abuf); 552968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold tc = DNS_HEADER_TC(abuf); 553968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold rcode = DNS_HEADER_RCODE(abuf); 554968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 555968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Find the query corresponding to this packet. The queries are 556968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * hashed/bucketed by query id, so this lookup should be quick. 557968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Note that both the query id and the questions must be the same; 558968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * when the query id wraps around we can have multiple outstanding 559968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * queries with the same query id, so we need to check both the id and 560968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * question. 561968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 562968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query = NULL; 563968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold list_head = &(channel->queries_by_qid[id % ARES_QID_TABLE_SIZE]); 564968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (list_node = list_head->next; list_node != list_head; 565968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold list_node = list_node->next) 566968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 567968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct query *q = list_node->data; 568968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((q->qid == id) && same_questions(q->qbuf, q->qlen, abuf, alen)) 569968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 570968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query = q; 571968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 572968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 573968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 574968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!query) 575968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 576968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 577968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If we got a truncated UDP packet and are not ignoring truncation, 578968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * don't accept the packet, and switch the query to TCP if we hadn't 579968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * done so already. 580968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 581968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC)) 582968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 583968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!query->using_tcp) 584968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 585968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->using_tcp = 1; 586968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__send_query(channel, query, now); 587968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 588968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 589968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 590968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 591968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we 592968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * are ignoring truncation. 593968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 594968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (alen > PACKETSZ && !tcp) 595968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold alen = PACKETSZ; 596968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 597968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If we aren't passing through all error packets, discard packets 598968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * with SERVFAIL, NOTIMP, or REFUSED response codes. 599968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 600968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!(channel->flags & ARES_FLAG_NOCHECKRESP)) 601968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 602968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED) 603968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 604968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold skip_server(channel, query, whichserver); 605968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (query->server == whichserver) 606968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 607968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 608968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 609968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 610968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 611968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold end_query(channel, query, ARES_SUCCESS, abuf, alen); 612968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 613968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 614968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* Close all the connections that are no longer usable. */ 615968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void process_broken_connections(ares_channel channel, 616968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 617968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 618968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i; 619968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 620968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 621968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server = &channel->servers[i]; 622968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->is_broken) 623968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 624968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold handle_error(channel, i, now); 625968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 626968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 627968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 628968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 629968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void handle_error(ares_channel channel, int whichserver, 630968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 631968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 632968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 633968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct query *query; 634968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node list_head; 635968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct list_node* list_node; 636968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 637968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[whichserver]; 638968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 639968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Reset communications with this server. */ 640968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__close_sockets(channel, server); 641968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 642968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Tell all queries talking to this server to move on and not try 643968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this server again. We steal the current list of queries that were 644968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * in-flight to this server, since when we call next_server this can 645968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * cause the queries to be re-sent to this server, which will 646968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * re-insert these queries in that same server->queries_to_server 647968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * list. 648968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 649968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__init_list_head(&list_head); 650968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__swap_lists(&list_head, &(server->queries_to_server)); 651968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (list_node = list_head.next; list_node != &list_head; ) 652968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 653968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query = list_node->data; 654968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold list_node = list_node->next; /* in case the query gets deleted */ 655968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold assert(query->server == whichserver); 656968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold skip_server(channel, query, whichserver); 657968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 658968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 659968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Each query should have removed itself from our temporary list as 660968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * it re-sent itself or finished up... 661968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 662968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold assert(ares__is_list_empty(&list_head)); 663968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 664968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 665968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void skip_server(ares_channel channel, struct query *query, 666968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int whichserver) { 667968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* The given server gave us problems with this query, so if we have 668968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * the luxury of using other servers, then let's skip the 669968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * potentially broken server and just use the others. If we only 670968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * have one server and we need to retry then we should just go ahead 671968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * and re-use that server, since it's our only hope; perhaps we 672968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * just got unlucky, and retrying will work (eg, the server timed 673968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * out our TCP connection just as we were sending another request). 674968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 675968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (channel->nservers > 1) 676968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 677968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->server_info[whichserver].skip_server = 1; 678968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 679968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 680968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 681968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void next_server(ares_channel channel, struct query *query, 682968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 683968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 684968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We need to try each server channel->tries times. We have channel->nservers 685968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * servers to try. In total, we need to do channel->nservers * channel->tries 686968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * attempts. Use query->try to remember how many times we already attempted 687968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * this query. Use modular arithmetic to find the next server to try. */ 688968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold while (++(query->try_count) < (channel->nservers * channel->tries)) 689968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 690968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 691968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 692968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Move on to the next server. */ 693968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->server = (query->server + 1) % channel->nservers; 694968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[query->server]; 695968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 696968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We don't want to use this server if (1) we decided this 697968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * connection is broken, and thus about to be closed, (2) 698968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * we've decided to skip this server because of earlier 699968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * errors we encountered, or (3) we already sent this query 700968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * over this exact connection. 701968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 702968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!server->is_broken && 703968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold !query->server_info[query->server].skip_server && 704968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold !(query->using_tcp && 705968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (query->server_info[query->server].tcp_connection_generation == 706968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_connection_generation))) 707968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 708968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__send_query(channel, query, now); 709968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 710968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 711968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 712968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* You might think that with TCP we only need one try. However, 713968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * even when using TCP, servers can time-out our connection just 714968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * as we're sending a request, or close our connection because 715968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * they die, or never send us a reply because they get wedged or 716968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * tickle a bug that drops our request. 717968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 718968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 719968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 720968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* If we are here, all attempts to perform query failed. */ 721968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold end_query(channel, query, query->error_status, NULL, 0); 722968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 723968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 724968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares__send_query(ares_channel channel, struct query *query, 725968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct timeval *now) 726968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 727968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct send_request *sendreq; 728968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server; 729968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int timeplus; 730968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 731968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server = &channel->servers[query->server]; 732968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (query->using_tcp) 733968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 734968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Make sure the TCP socket for this server is set up and queue 735968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * a send request. 736968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 737968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->tcp_socket == ARES_SOCKET_BAD) 738968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 739968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (open_tcp_socket(channel, server) == -1) 740968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 741968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold skip_server(channel, query, query->server); 742968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 743968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 744968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 745968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 746968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq = calloc(1, sizeof(struct send_request)); 747968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!sendreq) 748968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 749968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold end_query(channel, query, ARES_ENOMEM, NULL, 0); 750968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 751968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 752968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* To make the common case fast, we avoid copies by using the 753968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * query's tcpbuf for as long as the query is alive. In the rare 754968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * case where the query ends while it's queued for transmission, 755968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * then we give the sendreq its own copy of the request packet 756968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * and put it in sendreq->data_storage. 757968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 758968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data_storage = NULL; 759968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data = query->tcpbuf; 760968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->len = query->tcplen; 761968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->owner_query = query; 762968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->next = NULL; 763968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->qtail) 764968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->qtail->next = sendreq; 765968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 766968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 767968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 1); 768968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->qhead = sendreq; 769968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 770968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->qtail = sendreq; 771968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->server_info[query->server].tcp_connection_generation = 772968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_connection_generation; 773968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 774968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 775968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 776968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (server->udp_socket == ARES_SOCKET_BAD) 777968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 778968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (open_udp_socket(channel, server) == -1) 779968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 780968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold skip_server(channel, query, query->server); 781968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 782968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 783968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 784968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 785968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (swrite(server->udp_socket, query->qbuf, query->qlen) == -1) 786968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 787968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* FIXME: Handle EAGAIN here since it likely can happen. */ 788968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold skip_server(channel, query, query->server); 789968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold next_server(channel, query, now); 790968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return; 791968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 792968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 793968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold timeplus = channel->timeout << (query->try_count / channel->nservers); 794968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold timeplus = (timeplus * (9 + (rand () & 7))) / 16; 795968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->timeout = *now; 796968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__timeadd(&query->timeout, 797968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold timeplus); 798968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Keep track of queries bucketed by timeout, so we can process 799968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * timeout events quickly. 800968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 801968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->queries_by_timeout)); 802968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__insert_in_list( 803968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold &(query->queries_by_timeout), 804968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold &(channel->queries_by_timeout[query->timeout.tv_sec % 805968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ARES_TIMEOUT_TABLE_SIZE])); 806968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 807968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Keep track of queries bucketed by server, so we can process server 808968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * errors quickly. 809968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 810968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->queries_to_server)); 811968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__insert_in_list(&(query->queries_to_server), 812968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold &(server->queries_to_server)); 813968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 814968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 815968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold/* 816968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * setsocknonblock sets the given socket to either blocking or non-blocking 817968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * mode based on the 'nonblock' boolean argument. This function is highly 818968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * portable. 819968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 820968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int setsocknonblock(ares_socket_t sockfd, /* operate on this */ 821968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int nonblock /* TRUE or FALSE */) 822968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 823968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined(USE_BLOCKING_SOCKETS) 824968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 825968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; /* returns success */ 826968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 827968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_FCNTL_O_NONBLOCK) 828968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 829968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* most recent unix versions */ 830968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int flags; 831968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags = fcntl(sockfd, F_GETFL, 0); 832968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (FALSE != nonblock) 833968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 834968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else 835968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); 836968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 837968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTL_FIONBIO) 838968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 839968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* older unix versions */ 840968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int flags; 841968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags = nonblock; 842968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ioctl(sockfd, FIONBIO, &flags); 843968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 844968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTLSOCKET_FIONBIO) 845968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 846968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef WATT32 847968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char flags; 848968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 849968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Windows */ 850968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned long flags; 851968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 852968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold flags = nonblock; 853968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return ioctlsocket(sockfd, FIONBIO, &flags); 854968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 855968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) 856968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 857968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Amiga */ 858968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return IoctlSocket(sockfd, FIONBIO, (long)nonblock); 859968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 860968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) 861968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 862968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* BeOS */ 863968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold long b = nonblock ? 1 : 0; 864968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); 865968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 866968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#else 867968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold# error "no non-blocking method was found/used/set" 868968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 869968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 870968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 871968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int configure_socket(ares_socket_t s, int family, ares_channel channel) 872968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 873968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold union { 874968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr sa; 875968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in sa4; 876968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 sa6; 877968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } local; 878968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 879968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold setsocknonblock(s, TRUE); 880968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 881968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#if defined(FD_CLOEXEC) && !defined(MSDOS) 882968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Configure the socket fd as close-on-exec. */ 883968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) 884968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 885968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 886968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 887968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Set the socket's send and receive buffer sizes. */ 888968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((channel->socket_send_buffer_size > 0) && 889968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold setsockopt(s, SOL_SOCKET, SO_SNDBUF, 890968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (void *)&channel->socket_send_buffer_size, 891968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(channel->socket_send_buffer_size)) == -1) 892968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 893968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 894968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((channel->socket_receive_buffer_size > 0) && 895968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold setsockopt(s, SOL_SOCKET, SO_RCVBUF, 896968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (void *)&channel->socket_receive_buffer_size, 897968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(channel->socket_receive_buffer_size)) == -1) 898968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 899968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 900968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef SO_BINDTODEVICE 901968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (channel->local_dev_name[0]) { 902968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, 903968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold channel->local_dev_name, sizeof(channel->local_dev_name))) { 904968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Only root can do this, and usually not fatal if it doesn't work, so */ 905968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* just continue on. */ 906968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 907968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 908968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 909968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 910968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (family == AF_INET) { 911968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (channel->local_ip4) { 912968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(&local.sa4, 0, sizeof(local.sa4)); 913968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold local.sa4.sin_family = AF_INET; 914968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold local.sa4.sin_addr.s_addr = htonl(channel->local_ip4); 915968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (bind(s, &local.sa, sizeof(local.sa4)) < 0) 916968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 917968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 918968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 919968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold else if (family == AF_INET6) { 920968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (memcmp(channel->local_ip6, &ares_in6addr_any, sizeof(channel->local_ip6)) != 0) { 921968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(&local.sa6, 0, sizeof(local.sa6)); 922968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold local.sa6.sin6_family = AF_INET6; 923968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&local.sa6.sin6_addr, channel->local_ip6, sizeof(channel->local_ip6)); 924968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (bind(s, &local.sa, sizeof(local.sa6)) < 0) 925968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 926968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 927968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 928968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 929968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 930968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 931968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 932968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_tcp_socket(ares_channel channel, struct server_state *server) 933968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 934968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t s; 935968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int opt; 936968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socklen_t salen; 937968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold union { 938968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in sa4; 939968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 sa6; 940968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } saddr; 941968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr *sa; 942968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 943968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold switch (server->addr.family) 944968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 945968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET: 946968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sa = (void *)&saddr.sa4; 947968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold salen = sizeof(saddr.sa4); 948968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(sa, 0, salen); 949968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa4.sin_family = AF_INET; 950968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa4.sin_port = (unsigned short)(channel->tcp_port & 0xffff); 951968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, 952968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(server->addr.addrV4)); 953968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 954968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET6: 955968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sa = (void *)&saddr.sa6; 956968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold salen = sizeof(saddr.sa6); 957968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(sa, 0, salen); 958968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa6.sin6_family = AF_INET6; 959968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa6.sin6_port = (unsigned short)(channel->tcp_port & 0xffff); 960968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, 961968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(server->addr.addrV6)); 962968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 963968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold default: 964968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 965968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 966968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 967968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Acquire a socket. */ 968968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold s = socket(server->addr.family, SOCK_STREAM, 0); 969968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (s == ARES_SOCKET_BAD) 970968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 971968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 972968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Configure it. */ 973968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (configure_socket(s, server->addr.family, channel) < 0) 974968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 975968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 976968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 977968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 978968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 979968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#ifdef TCP_NODELAY 980968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* 981968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not 982968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * in configure_socket). In general, in DNS lookups we're pretty much 983968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * interested in firing off a single request and then waiting for a reply, 984968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * so batching isn't very interesting. 985968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 986968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold opt = 1; 987968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, 988968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold (void *)&opt, sizeof(opt)) == -1) 989968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 990968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 991968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 992968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 993968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold#endif 994968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 995968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Connect to the server. */ 996968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (connect(s, sa, salen) == -1) 997968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 998968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int err = SOCKERRNO; 999968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1000968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (err != EINPROGRESS && err != EWOULDBLOCK) 1001968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1002968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 1003968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 1004968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1005968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1006968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1007968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (channel->sock_create_cb) 1008968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1009968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int err = channel->sock_create_cb(s, SOCK_STREAM, 1010968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold channel->sock_create_cb_data); 1011968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (err < 0) 1012968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1013968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 1014968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return err; 1015968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1016968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1017968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1018968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold SOCK_STATE_CALLBACK(channel, s, 1, 0); 1019968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_buffer_pos = 0; 1020968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_socket = s; 1021968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->tcp_connection_generation = ++channel->tcp_connection_generation; 1022968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1023968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1024968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1025968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int open_udp_socket(ares_channel channel, struct server_state *server) 1026968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 1027968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socket_t s; 1028968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares_socklen_t salen; 1029968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold union { 1030968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in sa4; 1031968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr_in6 sa6; 1032968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } saddr; 1033968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct sockaddr *sa; 1034968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1035968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold switch (server->addr.family) 1036968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1037968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET: 1038968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sa = (void *)&saddr.sa4; 1039968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold salen = sizeof(saddr.sa4); 1040968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(sa, 0, salen); 1041968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa4.sin_family = AF_INET; 1042968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa4.sin_port = (unsigned short)(channel->udp_port & 0xffff); 1043968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&saddr.sa4.sin_addr, &server->addr.addrV4, 1044968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(server->addr.addrV4)); 1045968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1046968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET6: 1047968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sa = (void *)&saddr.sa6; 1048968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold salen = sizeof(saddr.sa6); 1049968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memset(sa, 0, salen); 1050968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa6.sin6_family = AF_INET6; 1051968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold saddr.sa6.sin6_port = (unsigned short)(channel->udp_port & 0xffff); 1052968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(&saddr.sa6.sin6_addr, &server->addr.addrV6, 1053968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sizeof(server->addr.addrV6)); 1054968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1055968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold default: 1056968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 1057968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1058968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1059968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Acquire a socket. */ 1060968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold s = socket(server->addr.family, SOCK_DGRAM, 0); 1061968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (s == ARES_SOCKET_BAD) 1062968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 1063968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1064968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Set the socket non-blocking. */ 1065968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (configure_socket(s, server->addr.family, channel) < 0) 1066968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1067968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 1068968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 1069968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1070968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1071968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Connect to the server. */ 1072968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (connect(s, sa, salen) == -1) 1073968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1074968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int err = SOCKERRNO; 1075968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1076968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (err != EINPROGRESS && err != EWOULDBLOCK) 1077968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1078968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 1079968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return -1; 1080968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1081968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1082968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1083968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (channel->sock_create_cb) 1084968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1085968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int err = channel->sock_create_cb(s, SOCK_DGRAM, 1086968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold channel->sock_create_cb_data); 1087968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (err < 0) 1088968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1089968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sclose(s); 1090968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return err; 1091968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1092968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1093968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1094968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold SOCK_STATE_CALLBACK(channel, s, 1, 0); 1095968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1096968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->udp_socket = s; 1097968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1098968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1099968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1100968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_questions(const unsigned char *qbuf, int qlen, 1101968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *abuf, int alen) 1102968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 1103968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct { 1104968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold const unsigned char *p; 1105968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int qdcount; 1106968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold char *name; 1107968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold long namelen; 1108968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int type; 1109968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int dnsclass; 1110968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } q, a; 1111968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i, j; 1112968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1113968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (qlen < HFIXEDSZ || alen < HFIXEDSZ) 1114968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1115968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1116968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Extract qdcount from the request and reply buffers and compare them. */ 1117968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.qdcount = DNS_HEADER_QDCOUNT(qbuf); 1118968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.qdcount = DNS_HEADER_QDCOUNT(abuf); 1119968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (q.qdcount != a.qdcount) 1120968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1121968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1122968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* For each question in qbuf, find it in abuf. */ 1123968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.p = qbuf + HFIXEDSZ; 1124968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < q.qdcount; i++) 1125968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1126968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Decode the question in the query. */ 1127968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) 1128968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold != ARES_SUCCESS) 1129968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1130968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.p += q.namelen; 1131968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (q.p + QFIXEDSZ > qbuf + qlen) 1132968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1133968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(q.name); 1134968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1135968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1136968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.type = DNS_QUESTION_TYPE(q.p); 1137968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.dnsclass = DNS_QUESTION_CLASS(q.p); 1138968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold q.p += QFIXEDSZ; 1139968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1140968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Search for this question in the answer. */ 1141968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.p = abuf + HFIXEDSZ; 1142968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (j = 0; j < a.qdcount; j++) 1143968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1144968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Decode the question in the answer. */ 1145968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) 1146968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold != ARES_SUCCESS) 1147968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1148968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(q.name); 1149968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1150968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1151968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.p += a.namelen; 1152968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (a.p + QFIXEDSZ > abuf + alen) 1153968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1154968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(q.name); 1155968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(a.name); 1156968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1157968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1158968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.type = DNS_QUESTION_TYPE(a.p); 1159968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.dnsclass = DNS_QUESTION_CLASS(a.p); 1160968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold a.p += QFIXEDSZ; 1161968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1162968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Compare the decoded questions. */ 1163968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (strcasecmp(q.name, a.name) == 0 && q.type == a.type 1164968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold && q.dnsclass == a.dnsclass) 1165968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1166968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(a.name); 1167968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1168968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1169968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(a.name); 1170968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1171968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1172968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(q.name); 1173968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (j == a.qdcount) 1174968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; 1175968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1176968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; 1177968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1178968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1179968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic int same_address(struct sockaddr *sa, struct ares_addr *aa) 1180968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 1181968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold void *addr1; 1182968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold void *addr2; 1183968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1184968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sa->sa_family == aa->family) 1185968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1186968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold switch (aa->family) 1187968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1188968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET: 1189968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr1 = &aa->addrV4; 1190968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr2 = &((struct sockaddr_in *)sa)->sin_addr; 1191968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (memcmp(addr1, addr2, sizeof(aa->addrV4)) == 0) 1192968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; /* match */ 1193968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1194968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold case AF_INET6: 1195968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr1 = &aa->addrV6; 1196968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold addr2 = &((struct sockaddr_in6 *)sa)->sin6_addr; 1197968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (memcmp(addr1, addr2, sizeof(aa->addrV6)) == 0) 1198968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 1; /* match */ 1199968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1200968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold default: 1201968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold break; 1202968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1203968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1204968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold return 0; /* different */ 1205968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1206968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1207968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldstatic void end_query (ares_channel channel, struct query *query, int status, 1208968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold unsigned char *abuf, int alen) 1209968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 1210968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold int i; 1211968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1212968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* First we check to see if this query ended while one of our send 1213968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * queues still has pointers to it. 1214968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 1215968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 1216968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1217968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct server_state *server = &channel->servers[i]; 1218968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold struct send_request *sendreq; 1219968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) 1220968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sendreq->owner_query == query) 1221968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1222968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->owner_query = NULL; 1223968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold assert(sendreq->data_storage == NULL); 1224968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (status == ARES_SUCCESS) 1225968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1226968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We got a reply for this query, but this queued 1227968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * sendreq points into this soon-to-be-gone query's 1228968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * tcpbuf. Probably this means we timed out and queued 1229968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * the query for retransmission, then received a 1230968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * response before actually retransmitting. This is 1231968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * perfectly fine, so we want to keep the connection 1232968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * running smoothly if we can. But in the worst case 1233968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * we may have sent only some prefix of the query, 1234968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * with some suffix of the query left to send. Also, 1235968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * the buffer may be queued on multiple queues. To 1236968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * prevent dangling pointers to the query's tcpbuf and 1237968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * handle these cases, we just give such sendreqs 1238968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * their own copy of the query packet. 1239968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 1240968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data_storage = malloc(sendreq->len); 1241968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (sendreq->data_storage != NULL) 1242968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1243968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold memcpy(sendreq->data_storage, sendreq->data, sendreq->len); 1244968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data = sendreq->data_storage; 1245968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1246968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1247968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if ((status != ARES_SUCCESS) || (sendreq->data_storage == NULL)) 1248968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1249968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* We encountered an error (probably a timeout, 1250968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * suggesting the DNS server we're talking to is 1251968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * probably unreachable, wedged, or severely 1252968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * overloaded) or we couldn't copy the request, so 1253968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * mark the connection as broken. When we get to 1254968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * process_broken_connections() we'll close the 1255968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * connection and try to re-send requests to another 1256968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * server. 1257968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 1258968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold server->is_broken = 1; 1259968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Just to be paranoid, zero out this sendreq... */ 1260968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->data = NULL; 1261968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold sendreq->len = 0; 1262968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1263968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1264968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1265968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1266968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Invoke the callback */ 1267968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->callback(query->arg, status, query->timeouts, abuf, alen); 1268968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__free_query(query); 1269968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1270968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Simple cleanup policy: if no queries are remaining, close all 1271968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold * network sockets unless STAYOPEN is set. 1272968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold */ 1273968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold if (!(channel->flags & ARES_FLAG_STAYOPEN) && 1274968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__is_list_empty(&(channel->all_queries))) 1275968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold { 1276968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold for (i = 0; i < channel->nservers; i++) 1277968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__close_sockets(channel, &channel->servers[i]); 1278968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold } 1279968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1280968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold 1281968bf19396ad404e89420f5d67900fce13f4186cGilad Arnoldvoid ares__free_query(struct query *query) 1282968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold{ 1283968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Remove the query from all the lists in which it is linked */ 1284968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->queries_by_qid)); 1285968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->queries_by_timeout)); 1286968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->queries_to_server)); 1287968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold ares__remove_from_list(&(query->all_queries)); 1288968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Zero out some important stuff, to help catch bugs */ 1289968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->callback = NULL; 1290968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold query->arg = NULL; 1291968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold /* Deallocate the memory associated with the query */ 1292968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(query->tcpbuf); 1293968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(query->server_info); 1294968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold free(query); 1295968bf19396ad404e89420f5d67900fce13f4186cGilad Arnold} 1296