diff options
Diffstat (limited to 'ares_send.c')
-rw-r--r-- | ares_send.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/ares_send.c b/ares_send.c new file mode 100644 index 0000000..b17b912 --- /dev/null +++ b/ares_send.c @@ -0,0 +1,104 @@ +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +static const char rcsid[] = "$Id$"; + +#include <sys/types.h> + +#ifdef WIN32 +#include "nameser.h" +#else +#include <netinet/in.h> +#include <arpa/nameser.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, + ares_callback callback, void *arg) +{ + struct query *query; + int i; + time_t now; + + /* Verify that the query is at least long enough to hold the header. */ + if (qlen < HFIXEDSZ || qlen >= (1 << 16)) + { + callback(arg, ARES_EBADQUERY, NULL, 0); + return; + } + + /* Allocate space for query and allocated fields. */ + query = malloc(sizeof(struct query)); + if (!query) + { + callback(arg, ARES_ENOMEM, NULL, 0); + return; + } + query->tcpbuf = malloc(qlen + 2); + if (!query->tcpbuf) + { + free(query); + callback(arg, ARES_ENOMEM, NULL, 0); + return; + } + query->skip_server = malloc(channel->nservers * sizeof(int)); + if (!query->skip_server) + { + free(query->tcpbuf); + free(query); + callback(arg, ARES_ENOMEM, NULL, 0); + return; + } + + /* Compute the query ID. Start with no timeout. */ + query->qid = DNS_HEADER_QID(qbuf); + query->timeout = 0; + + /* Form the TCP query buffer by prepending qlen (as two + * network-order bytes) to qbuf. + */ + query->tcpbuf[0] = (qlen >> 8) & 0xff; + query->tcpbuf[1] = qlen & 0xff; + memcpy(query->tcpbuf + 2, qbuf, qlen); + query->tcplen = qlen + 2; + + /* Fill in query arguments. */ + query->qbuf = query->tcpbuf + 2; + query->qlen = qlen; + query->callback = callback; + query->arg = arg; + + /* Initialize query status. */ + query->try = 0; + query->server = 0; + for (i = 0; i < channel->nservers; i++) + query->skip_server[i] = 0; + query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ; + query->error_status = ARES_ECONNREFUSED; + + /* Chain the query into this channel's query list. */ + query->next = channel->queries; + channel->queries = query; + + /* Perform the first query action. */ + time(&now); + ares__send_query(channel, query, now); +} |