Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/libc/minires.c')
-rw-r--r--winsup/cygwin/libc/minires.c995
1 files changed, 0 insertions, 995 deletions
diff --git a/winsup/cygwin/libc/minires.c b/winsup/cygwin/libc/minires.c
deleted file mode 100644
index c401e7c60..000000000
--- a/winsup/cygwin/libc/minires.c
+++ /dev/null
@@ -1,995 +0,0 @@
-/* minires.c. Stub synchronous resolver for Cygwin.
-
- Copyright 2006, 2008, 2009 Red Hat, Inc.
-
- Written by Pierre A. Humblet <Pierre.Humblet@ieee.org>
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#include "minires.h"
-
-/***********************************************************************
-
-Utilities
-
-***********************************************************************/
-/***********************************************************************
-
-dprintf
-***********************************************************************/
-void minires_dprintf(const char * format, ...)
-{
- va_list args;
-
- va_start(args, format);
- fprintf(stderr, "Minires: ");
- vfprintf(stderr, format, args);
- va_end(args);
-}
-
-/***********************************************************************
-
-scanline
-Put pointers in list[] to the beginning of each space or comma delimited
-word in "in", and put the lengths in sizes[] (counting the final 0).
-Return the number of words found
-***********************************************************************/
-static int scanline(char * in, char **list, int * sizes, int maxnum)
-{
- int i;
- char * startp;
- for (i = 0; i < maxnum; i++) {
- while((*in) && (isspace((unsigned char)*in) || *in == ',')) in++;
- if (*in == 0)
- break;
- startp = in++;
- while((*in) && !isspace((unsigned char)*in) && *in != ',') in++;
- list[i] = startp;
- sizes[i] = in - startp + 1;
- if (*in)
- *in++ = 0;
- }
- return i;
-}
-
-/***********************************************************************
-
-Read the search string.
-
-***********************************************************************/
-void minires_get_search(char * string, res_state statp)
-{
- char * words[MAXDNSRCH+1], * ptr;
- int sizes[MAXDNSRCH+1];
- int i, j, debug = statp->options & RES_DEBUG;
-
- i = scanline(string, words, sizes, MAXDNSRCH+1);
- ptr = statp->defdname;
- for (j = 0; j < i; j++) {
- if (j < MAXDNSRCH
- && ptr + sizes[j] < &statp->defdname[DIM(statp->defdname)]) {
- statp->dnsrch[j] = strcpy(ptr, words[j]);
- statp->dnsrch[j+1] = NULL;
- ptr += sizes[j];
- DPRINTF(debug, "search \"%s\"\n", words[j]);
- }
- else
- DPRINTF(debug, "no space for \"%s\"\n", words[j]);
- }
-}
-
-/***********************************************************************
-
-Read options
-
-
-***********************************************************************/
-static void get_options(res_state statp, int i, char **words)
-{
- char *ptr;
- int value;
-
- while (i-- > 0) {
- if (!strcasecmp("debug", words[i])) {
- statp->options |= RES_DEBUG;
- DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
- continue;
- }
- if (!strcasecmp("inet6", words[i])) {
- statp->options |= RES_USE_INET6;
- DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
- continue;
- }
- if (!strcasecmp("osquery", words[i])) {
- statp->use_os = 1;
- DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]);
- continue;
- }
-
- if ((ptr = strchr(words[i], ':'))) {
- *ptr++ = 0;
- value = atoi(ptr);
- /* Not supported
- if (!strcasecmp("ndots", words[i])) {
- statp->ndots = value;
- continue;
- }
- */
- if (!strcasecmp("retry", words[i])
- || !strcasecmp("attempts", words[i])) {
- if (value < 1)
- value = 1;
- else if (value > RES_MAXRETRY)
- value = RES_MAXRETRY;
- statp->retry = value;
- DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
- continue;
- }
- if (!strcasecmp("retrans", words[i])
- || !strcasecmp("timeout", words[i])) {
- if (value < 1)
- value = 1;
- else if (value > RES_MAXRETRANS)
- value = RES_MAXRETRANS;
- statp->retrans = value;
- DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value);
- continue;
- }
- }
- DPRINTF(statp->options & RES_DEBUG, "unknown option: \"%s\"\n", words[i]);
- }
-}
-
-/***********************************************************************
-
-Read the resolv.conf file.
-We only look for nameserver, domain, search and options
-
-***********************************************************************/
-#if MAXNS > MAXDNSRCH + 1
-#define MAXSIZE MAXNS
-#else
-#define MAXSIZE MAXDNSRCH + 1 /* Make unused one visible */
-#endif
-static void get_resolv(res_state statp)
-{
- FILE * fd;
- char *words[MAXSIZE + 1], line[4096], *ptr;
- int sizes[DIM(words)];
- int i, j, ns = 0, have_search, have_address, debug = statp->options & RES_DEBUG;
-
- fd = fopen(_PATH_RESCONF, "r");
- DPRINTF(debug, _PATH_RESCONF ": %s\n", fd?"OK":strerror(errno));
- if (fd == NULL)
- return;
-
- statp->use_os = 0; /* Do not use os_query, except if allowed by "options" */
- have_search = (statp->dnsrch[0] != NULL);
- have_address = (statp->nscount != 0);
-
- while ( fgets(line, sizeof(line), fd) != 0) {
- DPRINTF(debug, "resolv.conf %s", line);
- if ((i = scanline(line, words, sizes, DIM(words))) > 0) {
- if (!have_address
- && !strncasecmp("nameserver", words[0], sizes[0])) {
- for ( j = 1; j < i ; j++) {
- unsigned int address;
- address = cygwin_inet_addr(words[j]);
- if (address == -1) {
- DPRINTF(debug, "invalid server \"%s\"\n", words[j]);
- }
- else if (ns >= MAXNS) {
- DPRINTF(debug, "no space for server \"%s\"\n", words[j]);
- }
- else {
- statp->nsaddr_list[ns++].sin_addr.s_addr = address;
- statp->nscount++;
- DPRINTF(debug, "server \"%s\"\n", words[j]);
- }
- }
- }
- else if (!have_search
- && (!strncasecmp("search", words[0], sizes[0])
- || !strncasecmp("domain", words[0], sizes[0]))) {
- ptr = statp->defdname;
- for (j = 0; j + 1 < i; j++) {
- if (j < MAXDNSRCH
- && ptr + sizes[j + 1] < &statp->defdname[DIM(statp->defdname)]) {
- statp->dnsrch[j] = strcpy(ptr, words[j+1]);
- statp->dnsrch[j+1] = 0;
- ptr += sizes[j+1];
- DPRINTF(debug, "domain|search \"%s\"\n", statp->dnsrch[j]);
- }
- else {
- DPRINTF(debug, "no space for \"%s\"\n", words[j+1]);
- }
- }
- }
- /* Options line */
- else if (!strncasecmp("options", words[0], sizes[0]))
- get_options(statp, i - 1, &words[1]);
- }
- }
- fclose(fd);
- return;
-}
-
-/****************************************************************************/
-/*
- open_sock()
- Create a datagram socket and call bind.
-
-****************************************************************************/
-
-static int open_sock(struct sockaddr_in *CliAddr, int debug)
-{
- int fd;
-
- DPRINTF(debug, "opening UDP socket\n");
-
- /* Create a datagram socket */
- if ((fd = cygwin_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
- DPRINTF(debug, "socket(UDP): %s\n", strerror(errno));
- return -1;
- }
- /* Set non-blocking */
- if (fcntl64(fd, F_SETFL, O_NONBLOCK) < 0) {
- DPRINTF(debug, "fcntl: %s\n", strerror(errno));
- return -1;
- }
- /* Set close on exec flag */
- if (fcntl64(fd, F_SETFD, 1) == -1) {
- DPRINTF(debug, "fcntl: %s\n", strerror(errno));
- return -1;
- }
-
- CliAddr->sin_family = AF_INET;
- CliAddr->sin_addr.s_addr = htonl(INADDR_ANY);
- CliAddr->sin_port = htons(0);
- bzero(CliAddr->sin_zero, sizeof(CliAddr->sin_zero));
- /* Get a port */
- if (cygwin_bind(fd, (struct sockaddr *) CliAddr, sizeof(*CliAddr)) < 0) {
- DPRINTF(debug, "bind: %s\n", strerror(errno));
- return -1;
- }
- return fd;
-}
-
-/*****************************************************************
- *
- __res_state()
- Undocumented but public. Accessed through _res
-
- *****************************************************************/
-static struct __res_state res;
-struct __res_state *__res_state(void)
-{
- return & res;
-}
-
-/*****************************************************************
- *
- res_init()
-
- *****************************************************************/
-int res_ninit(res_state statp)
-{
- int i;
-
- statp->res_h_errno = NETDB_SUCCESS;
- /* Only debug may be set before calling init */
- statp->options &= RES_DEBUG;
- statp->options |= RES_INIT | RES_DEFAULT;
- statp->nscount = 0;
- statp->os_query = NULL;
- statp->retrans = RES_TIMEOUT; /* timeout in seconds */
- statp->retry = RES_MAXRETRY; /* max number of retries */
- statp->use_os = 1; /* use os_query if available and allowed by get_resolv */
- statp->mypid = -1;
- statp->sockfd = -1;
- /* Use the pid and the ppid for random seed, from the point of view of an outsider.
- Mix the upper and lower bits as they are not used equally */
- i = getpid();
- statp->id = (ushort) (getppid() ^ (i << 8) ^ (i >> 8));
- for (i = 0; i < DIM(statp->dnsrch); i++) statp->dnsrch[i] = 0;
-
- /* resolv.conf (dns servers & search list)*/
- get_resolv(statp);
- /* Get dns servers and search list from an os-specific routine, set os_query */
- get_dns_info(statp);
-
- if (statp->nscount == 0 && !statp->os_query) {
- errno = ENONET;
- statp->res_h_errno = NETDB_INTERNAL;
- DPRINTF(statp->options & RES_DEBUG, "no dns server found\n");
- return -1;
- }
- for (i = 0; i < statp->nscount; i++) {
- statp->nsaddr_list[i].sin_family = AF_INET;
- statp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
- bzero(statp->nsaddr_list[i].sin_zero, sizeof(statp->nsaddr_list[i].sin_zero));
- }
- return 0;
-}
-
-int res_init()
-{
- int r = res_ninit(& res);
- h_errno = res.res_h_errno;
- return r;
-}
-
-/*****************************************************************
- *
- res_close()
-
- *****************************************************************/
-void res_nclose(res_state statp)
-{
- int res;
- if (statp->sockfd != -1) {
- res = close(statp->sockfd);
- DPRINTF(statp->options & RES_DEBUG, "close sockfd %d: %s\n",
- statp->sockfd, (res == 0)?"OK":strerror(errno));
- statp->sockfd = -1;
- }
-}
-
-void res_close()
-{
- res_nclose(& res);
-}
-
-/*****************************************************************
- *
- get_tcp_buf()
-
- *****************************************************************/
-static int get_tcp_buf(int fd, unsigned char *buf, int size, int debug)
-{
- int res;
- while (size > 0) {
- if ((res = read(fd, buf, size)) < 0) {
- DPRINTF(debug, "read: %s\n", strerror(errno));
- return -1;
- }
- DPRINTF(debug, "read %d out of %d\n", res, size);
- size -= res;
- buf += res;
- }
- return 0;
-}
-
-/*****************************************************************
- *
- get_tcp()
-
- *****************************************************************/
-static int get_tcp(struct sockaddr_in *CliAddr,
- const unsigned char * MsgPtr, int MsgLength,
- unsigned char * AnsPtr, int AnsLength, int debug)
-{
- int fd, res = -1;
- unsigned short ans_length;
- union {short len; u_char buf[sizeof(short)];} len_buf;
-
- DPRINTF(debug, "retrying with TCP\n");
-
- /* Create a tcp socket */
- if ((fd = cygwin_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
- DPRINTF(debug, "socket(TCP): %s\n", strerror(errno));
- return -1;
- }
-
- if (cygwin_connect(fd, (struct sockaddr *) CliAddr, sizeof(* CliAddr)) < 0) {
- DPRINTF(debug, "connect: %s\n", strerror(errno));
- goto done;
- }
-
- /* Send the length then the message */
- len_buf.len = htons(MsgLength);
- if (write(fd, len_buf.buf, sizeof(len_buf)) != sizeof(len_buf)
- || write(fd, MsgPtr, MsgLength) != MsgLength) {
- DPRINTF(debug, "write: %s\n", strerror(errno));
- goto done;
- }
-
- /* Read the answer length */
- if (get_tcp_buf(fd, len_buf.buf, sizeof(len_buf), debug))
- goto done;
- ans_length = ntohs(len_buf.len);
-
- /* Read the answer */
- if (get_tcp_buf(fd, AnsPtr, MIN(ans_length, AnsLength), debug))
- goto done;
- res = ans_length;
-
- done:
- close (fd);
- return res;
-}
-
-/*****************************************************************
- **
- res_send
- Assumes that the message is a query starting with a short id.
- Handles retransmissions until that id is received.
-
-*****************************************************************/
-int res_nsend( res_state statp, const unsigned char * MsgPtr,
- int MsgLength, unsigned char * AnsPtr, int AnsLength)
-{
- /* Current server, shared by all tasks */
- volatile static unsigned int SServ = 0XFFFFFFFF;
- int tcp;
- const int debug = statp->options & RES_DEBUG;
-
- fd_set fdset_read;
- int rslt, addrLen, transNum, wServ;
- struct sockaddr_in mySockAddr, dnsSockAddr;
- struct timeval timeOut;
-
- statp->res_h_errno = NETDB_SUCCESS;
- if (((statp->options & RES_INIT) == 0) && (res_ninit(statp) != 0))
- return -1;
-
- /* Close the socket if it had been opened before a fork.
- Reuse of pid's cannot hurt */
- if ((statp->sockfd != -1) && (statp->mypid != getpid())) {
- res_nclose(statp);
- }
-
- /* Open a socket for this process */
- if (statp->sockfd == -1) {
- /* Create a non-blocking, close on exec socket and bind it (to any port) */
- statp->sockfd = open_sock(& mySockAddr, debug);
- if (statp->sockfd < 0 ) {
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- }
- statp->mypid = getpid();
- if (SServ == 0XFFFFFFFF) /* Pseudo random */
- SServ = statp->id % statp->nscount;
- }
-
- transNum = 0;
- while ( transNum++ < statp->retry) {
- if ((wServ = SServ + 1) >= statp->nscount)
- wServ = 0;
- SServ = wServ;
-
- /* There exists attacks on DNS where many wrong answers with guessed id's and
- spoofed source address and port are generated at about the time when the
- program is tricked into resolving a name.
- This routine runs through the retry loop for each incorrect answer.
- It is thus extremely likely that such attacks will cause a TRY_AGAIN return,
- probably causing the calling program to retry after a delay.
-
- Note that valid late or duplicate answers to a previous questions also cause
- a retry, although this is minimized by flushing the socket before sending the
- new question.
- */
-
- /* Flush duplicate or late answers */
- while ((rslt = cygwin_recvfrom( statp->sockfd, AnsPtr, AnsLength, 0, NULL, NULL)) >= 0) {
- DPRINTF(debug, "Flushed %d bytes\n", rslt);
- }
- DPRINTF(debug && (errno != EWOULDBLOCK),
- "Unexpected errno for flushing recvfrom: %s", strerror(errno));
-
- /* Send the message */
- rslt = cygwin_sendto(statp->sockfd, MsgPtr, MsgLength, 0,
- (struct sockaddr *) &statp->nsaddr_list[wServ],
- sizeof(struct sockaddr_in));
- DPRINTF(debug, "sendto: server %08x sockfd %d %s\n",
- statp->nsaddr_list[wServ].sin_addr.s_addr,
- statp->sockfd, (rslt == MsgLength)?"OK":strerror(errno));
- if (rslt != MsgLength) {
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- };
- /*
- Wait for a reply with select()
- */
- FD_ZERO(&fdset_read);
- FD_SET (statp->sockfd, &fdset_read );
- timeOut.tv_sec = statp->retrans;
- timeOut.tv_usec = 0;
- rslt = cygwin_select(statp->sockfd + 1, &fdset_read, NULL, NULL, &timeOut);
- if ( rslt == 0 ) { /* Timeout */
- DPRINTF(statp->options & RES_DEBUG, "timeout for server %08x\n",
- statp->nsaddr_list[wServ].sin_addr.s_addr);
- continue;
- }
- else if ((rslt != 1) || (FD_ISSET(statp->sockfd, &fdset_read) == 0)) {
- DPRINTF(debug, "select: %s\n", strerror(errno));
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- }
-
- addrLen = sizeof(dnsSockAddr);
- rslt = cygwin_recvfrom(statp->sockfd, AnsPtr, AnsLength, 0,
- (struct sockaddr *) & dnsSockAddr, & addrLen);
- if (rslt <= 0) {
- DPRINTF(debug, "recvfrom: %s\n", strerror(errno));
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- }
- DPRINTF(debug, "recvfrom: %d bytes from %08x\n", rslt, dnsSockAddr.sin_addr.s_addr);
- /*
- Prepare to retry with tcp
- */
- for (tcp = 0; tcp < 2; tcp++) {
- /* Check if this is the expected message from the expected server */
- if ((memcmp(& dnsSockAddr, & statp->nsaddr_list[wServ],
- (char *) & dnsSockAddr.sin_zero[0] - (char *) & dnsSockAddr) == 0)
- && (rslt >= HFIXEDSZ)
- && (*MsgPtr == *AnsPtr) /* Ids match */
- && (*(MsgPtr + 1) == *(AnsPtr + 1))
- && ((AnsPtr[2] & QR) != 0)
- && (AnsPtr[4] == 0)
- /* We check the question if present.
- Some servers don't return it on error, in particular
- when the name in the question is not valid. */
- && (((AnsPtr[5] == 0)
- && ((AnsPtr[3] & ERR_MASK) != NOERROR))
- || ((AnsPtr[5] == 1)
- && (rslt >= MsgLength)
- && (memcmp(MsgPtr + HFIXEDSZ, AnsPtr + HFIXEDSZ, MsgLength - HFIXEDSZ) == 0)))) {
- if ((AnsPtr[3] & ERR_MASK) == NOERROR) {
- if ((AnsPtr[2] & TC) && (tcp == 0) && !(statp->options & RES_IGNTC)) {
- /* Truncated. Try TCP */
- rslt = get_tcp(&statp->nsaddr_list[wServ], MsgPtr, MsgLength,
- AnsPtr, AnsLength, statp->options & RES_DEBUG);
- continue /* Tcp loop */;
- }
- else if ((AnsPtr[6] | AnsPtr[7])!= 0)
- return rslt;
- else
- statp->res_h_errno = NO_DATA;
- }
-#if 0
- NETDB_INTERNAL -1 /* see errno */
- NETDB_SUCCESS 0 /* no problem */
- HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
- TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */
- Also seen returned by some servers when the name is too long
- NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
- NO_DATA 4 /* Valid name, no data record of requested type */
-#endif
- else {
- switch (AnsPtr[3] & ERR_MASK) {
- /* return HOST_NOT_FOUND even for non-authoritative answers */
- case NXDOMAIN:
- case FORMERR:
- statp->res_h_errno = HOST_NOT_FOUND;
- break;
- case SERVFAIL:
- statp->res_h_errno = TRY_AGAIN;
- break;
- default:
- statp->res_h_errno = NO_RECOVERY;
- }
- }
- return -1;
- }
- else {
- DPRINTF(debug, "unexpected answer\n");
- break;
- }
- } /* TCP */
- }
- DPRINTF(debug, "too many retries\n");
- statp->res_h_errno = TRY_AGAIN;
- return -1;
-}
-
-int res_send( const unsigned char * MsgPtr, int MsgLength,
- unsigned char * AnsPtr, int AnsLength)
-{
- int r = res_nsend(& res, MsgPtr, MsgLength, AnsPtr, AnsLength);
- h_errno = res.res_h_errno;
- return r;
-}
-
-/*****************************************************************
- *
- res_mkquery
-
- Return: packet size
- -1 name format is incorrect
-*****************************************************************/
-int res_nmkquery (res_state statp,
- int op, const char * dnameptr, int qclass, int qtype,
- const unsigned char * dataptr, int datalen,
- const unsigned char * newrr, unsigned char * buf, int buflen)
-{
- int i, len;
- const char * ptr;
- unsigned int id4;
-
- if (op == QUERY) {
- /* Write the name and verify buffer length */
- len = dn_comp(dnameptr, buf + HFIXEDSZ, buflen - HFIXEDSZ - QFIXEDSZ, NULL, NULL);
- if (len < 0) {
- DPRINTF(statp->options & RES_DEBUG,
- "\"%s\" invalid or buffer too short\n", dnameptr);
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- }
-
- /* Fill the header */
- PUTSHORT(statp->id, buf);
- PUTSHORT(RD, buf);
- PUTSHORT(1, buf); /* Number of questions */
- for (i = 0; i < 3; i++)
- PUTSHORT(0, buf); /* Number of answers */
-
- /* Write qtype and qclass */
- buf += len;
- PUTSHORT(qtype, buf);
- PUTSHORT(qclass, buf);
-
- /* Update id. The current query adds entropy to the next query id */
- for (id4 = qtype, i = 0, ptr = dnameptr; *ptr; ptr++, i += 3)
- id4 ^= *ptr << (i & 0xF);
- i = 1 + statp->id % 15; /* Between 1 and 16 */
- /* id dependent rotation, also brings MSW to LSW */
- id4 = (id4 << i) ^ (id4 >> (16 - i)) ^ (id4 >> (32 - i));
- if ((short) id4)
- statp->id ^= (short) id4;
- else
- statp->id++; /* Force change */
-
- return len + (HFIXEDSZ + QFIXEDSZ); /* packet size */
- }
- else { /* Not implemented */
- errno = ENOSYS;
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
- }
-}
-
-int res_mkquery (int op, const char * dnameptr, int qclass, int qtype,
- const unsigned char * dataptr, int datalen,
- const unsigned char * newrr, unsigned char * buf, int buflen)
-{
- int r = res_nmkquery (& res, op, dnameptr, qclass, qtype,
- dataptr, datalen, newrr, buf, buflen);
- h_errno = res.res_h_errno;
- return r;
-
-}
-
-/*****************************************************************
- * res_query()
- *****************************************************************/
-
-int res_nquery( res_state statp, const char * DomName, int Class, int Type,
- unsigned char * AnsPtr, int AnsLength)
-{
- u_char packet[PACKETSZ];
- int len;
-
- DPRINTF(statp->options & RES_DEBUG, "query \"%s\" type %d\n", DomName, Type);
- statp->res_h_errno = NETDB_SUCCESS;
-
- /* If a hook exists to a native implementation, use it */
- if (statp->os_query)
- return ((os_query_t *) statp->os_query)(statp, DomName, Class, Type, AnsPtr, AnsLength);
-
- if ((len = res_nmkquery (statp, QUERY, DomName, Class, Type,
- 0, 0, 0, packet, PACKETSZ)) < 0)
- return -1;
- return res_nsend( statp, packet, len, AnsPtr, AnsLength);
-}
-
-int res_query( const char * DomName, int Class, int Type, unsigned char * AnsPtr, int AnsLength)
-{
- int r = res_nquery(& res, DomName, Class, Type, AnsPtr, AnsLength);
- h_errno = res.res_h_errno;
- return r;
-}
-
-/*****************************************************************
- * res_querydomain()
- *****************************************************************/
-int res_nquerydomain( res_state statp, const char * Name, const char * DomName,
- int Class, int Type, unsigned char * AnsPtr, int AnsLength)
-{
- char fqdn[MAXDNAME], *ptr;
- int nlen;
-
- if (!DomName)
- ptr = (char *) Name;
- else if ((nlen = strlen(Name)) >= sizeof(fqdn) - 1)
- goto error;
- else {
- strcpy(fqdn, Name);
- ptr = &fqdn[nlen];
- if (nlen && *(ptr - 1) != '.')
- *(ptr++ - 1) = '.';
- fqdn[sizeof(fqdn) - 1] = 0;
- strncpy(ptr, DomName, sizeof(fqdn) - (ptr - fqdn));
- if (fqdn[sizeof(fqdn) - 1])
- goto error;
- ptr = fqdn;
- }
- return res_nquery(statp, ptr, Class, Type, AnsPtr, AnsLength);
-
- error:
- DPRINTF(statp->options & RES_DEBUG, "querydomain: name too long\n");
- errno = EINVAL;
- statp->res_h_errno = NETDB_INTERNAL;;
- return -1;
-}
-
-int res_querydomain( const char * Name, const char * DomName, int Class,
- int Type, unsigned char * AnsPtr, int AnsLength)
-{
- int r = res_nquerydomain(& res, Name, DomName, Class, Type, AnsPtr,
- AnsLength);
- h_errno = res.res_h_errno;
- return r;
-}
-
-/*****************************************************************
- *
- res_search()
-
- *****************************************************************/
-
-int res_nsearch( res_state statp, const char * DomName, int Class, int Type,
- unsigned char * AnsPtr, int AnsLength)
-{
- int len, stat, i;
- char fullDomName[MAXDNAME], *ptr, *sptr;
-
- DPRINTF(statp->options & RES_DEBUG, "search \"%s\" type %d\n", DomName, Type);
-
- if (((statp->options & RES_INIT) == 0) && (res_ninit(statp) != 0))
- return -1;
-
- stat = res_nquery( statp, DomName, Class, Type, AnsPtr, AnsLength);
-
- /* Check if will skip search */
- if (statp->res_h_errno != HOST_NOT_FOUND /* Success or hard failure */
- || ((ptr = strrchr(DomName, '.')) && (!*(ptr+1))) /* Final dot */
- || (((statp->options & RES_DNSRCH) == 0) /* Or no search */
- && ((ptr != NULL) /* And some dot */
- || ((statp->options & RES_DEFNAMES) == 0)))/* or no def domain */
- || (!(sptr = statp->dnsrch[0])))
- return stat;
-
- len = strlen(DomName);
- if (len >= MAXDNAME - 1) /* Space for next dot */
- goto error;
- strcpy(fullDomName, DomName);
- fullDomName[len++] = '.';
- fullDomName[MAXDNAME - 1] = 0; /* Overflow indicator */
- i = 0;
- do {
- strncpy(fullDomName + len, sptr, MAXDNAME - len);
- if (fullDomName[MAXDNAME - 1])
- goto error;
- stat = res_nquery(statp, fullDomName, Class, Type, AnsPtr, AnsLength);
- } while ((sptr = statp->dnsrch[++i]) != NULL
- && statp->res_h_errno == HOST_NOT_FOUND
- && (statp->options & RES_DNSRCH) != 0);
-
- /* Return last stat */
- return stat;
-
- error:
- DPRINTF(statp->options & RES_DEBUG, "name too long during search\n");
- errno = EINVAL;
- statp->res_h_errno = NETDB_INTERNAL;
- return -1;
-}
-
-int res_search( const char * DomName, int Class, int Type,
- unsigned char * AnsPtr, int AnsLength)
-{
- int r = res_nsearch(& res, DomName, Class, Type, AnsPtr, AnsLength);
- h_errno = res.res_h_errno;
- return r;
-}
-
-/*****************************************************************
- * dn_expand
- *****************************************************************/
-
-int dn_expand(const unsigned char *msg, const unsigned char *eomorig,
- const unsigned char *comp_dn, char *exp_dn, int length)
-{
- unsigned int len, complen = 0;
- const unsigned char *comp_dn_orig = comp_dn;
-/* char * exp_start = exp_dn; */
-
- errno = EINVAL;
- if (comp_dn >= eomorig)
- goto expand_fail;
- if ((len = *comp_dn++) == 0) /* Weird case */
- exp_dn++;
- else do {
- if (len <= MAXLABEL) {
- if ((length -= (len + 1)) >= 0 /* Need space for final . */
- && comp_dn + len <= eomorig) {
- do { *exp_dn++ = *comp_dn++; } while (--len != 0);
- *exp_dn++ = '.';
- }
- else
- goto expand_fail;
- }
- else if (len >= (128+64)) {
- if (!complen) /* Still in the original field? */
- complen = (comp_dn - comp_dn_orig) + 1;
- comp_dn = msg + (((len & ~(128+64)) << 8) + *comp_dn);
- if (comp_dn >= eomorig)
- goto expand_fail;
- }
- else
- goto expand_fail;
- } while ((len = *comp_dn++) != 0);
- /* Replace last . with a 0 */
- *(--exp_dn) = 0;
- if (!complen)
- complen = comp_dn - comp_dn_orig;
-/* fprintf(stderr, "dn_expand %s\n", exp_start); */
- return complen;
-
-expand_fail:
-/* fprintf(stderr, "dn_expand fails\n"); */
- return -1;
-}
-
-/*****************************************************************
- *
- dn_comp
-
- Return -1 in case of overflow, but still fill buffer correctly.
- We do not check the alphabet of the host names
- nor the length of the compressed name and we
- preserve the letter cases.
-
- *****************************************************************/
-int dn_comp(const char * exp_dn, u_char * comp_dn, int length,
- u_char ** dnptrs, u_char ** lastdnptr)
-{
- u_char *cptr = comp_dn, *dptr, *lptr, *rptr;
- unsigned int i, len;
- u_char * const eptr = comp_dn + length - 1; /* Last valid */
-
- errno = EINVAL;
-
- if (*exp_dn == '.' && !*(exp_dn + 1))
- exp_dn++;
- while (1) {
- if (*exp_dn == '.' || cptr > eptr)
- return -1;
- if (*exp_dn == 0) {
- *cptr++ = 0;
- break;
- }
- /* Try to compress */
- if (dnptrs) {
- for (i = 1; dnptrs[i]; i++) {
- dptr = dnptrs[i];
- if (dptr >= comp_dn) /* Handle name.name */
- continue;
- rptr = (u_char *) exp_dn;
- len = *dptr++;
- while (1) {
- do {
- if (*dptr++ != *rptr++)
- goto next_dn;
- } while (--len);
- len = *dptr++;
- if (len == 0) { /* last label */
- if (!*rptr || (*rptr == '.' && !*(rptr + 1))) { /* Full match */
- len = (dnptrs[i] - dnptrs[0]) | 0xC000;
- /* Write pointer */
- *cptr++ = len >> 8;
- if (cptr > eptr)
- return -1;
- *cptr++ = len;
- goto done;
- }
- goto next_dn;
- }
- if (*rptr++ != '.')
- goto next_dn;
- if (len >= 128 + 64) {
- dptr = dnptrs[0] + ((len - 128 - 64) << 8) + *dptr;
- len = *dptr++;
- }
- }
- next_dn: ;
- }
- /* Record label if asked and if space is available and if not too far off */
- if (lastdnptr && (lastdnptr != &dnptrs[i]) && (cptr - dnptrs[0]) < 0xC000) {
- dnptrs[i] = cptr;
- dnptrs[i+1] = NULL;
- }
- }
- /* Write label */
- lptr = cptr++; /* Length byte */
- rptr = (u_char *) exp_dn;
- do {
- if (cptr <= eptr)
- *cptr++ = *rptr;
- } while ((*++rptr != '.') && (*rptr != 0));
- len = rptr - (u_char *) exp_dn;
- if (len > MAXLABEL)
- return -1;
- *lptr = len;
- exp_dn = (char *) rptr;
- if (*exp_dn != 0)
- exp_dn++; /* Skip over . */
- }
- done:
- return cptr - comp_dn;
-}
-
-/*****************************************************************
- * dn_skipname
-
- Measures the compressed domain name length and returns it.
- *****************************************************************/
-int dn_skipname(const unsigned char *comp_dn, const unsigned char *eom)
-{
- int len;
- const unsigned char *comp_dn_orig = comp_dn;
-
- do {
- len = *comp_dn++;
- if (len >= (128 + 64)) {
- comp_dn++;
- break;
- }
- if (len > MAXLABEL ||
- (comp_dn += len) > eom)
- return -1;
- } while (len != 0);
-
- return comp_dn - comp_dn_orig;
-}
-
-/*****************************************************************
- * dn_length1 For internal use
-
- Return length of uncompressesed name incl final 0.
- *****************************************************************/
-
-int dn_length1(const unsigned char *msg, const unsigned char *eomorig,
- const unsigned char *comp_dn)
-{
- unsigned int len, length = 0;
-
- errno = EINVAL;
- if (comp_dn >= eomorig)
- goto expand_fail;
- else while ((len = *comp_dn++) != 0) {
- if (len <= MAXLABEL) {
- if ((comp_dn += len) <= eomorig)
- length += len + 1;
- else
- goto expand_fail;
- }
- else if (len >= (128+64)) {
- comp_dn = msg + (((len & ~(128+64)) << 8) + *comp_dn);
- if (comp_dn >= eomorig)
- goto expand_fail;
- }
- else
- goto expand_fail;
- }
- return length;
-
-expand_fail:
- return -1;
-}