⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dnsres.c

📁 快速开发
💻 C
字号:
/* * Copyright (c) 1985, 1988, 1993 *    The Regents of the University of California.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by the University of *      California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc. * All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met:  * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of Silicon Graphics, Inc. nor the names of its *    contributors may be used to endorse or promote products derived from *    this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "stx.h"#define MAXPACKET 1024#if !defined(NETDB_INTERNAL) && defined(h_NETDB_INTERNAL)#define NETDB_INTERNAL h_NETDB_INTERNAL#endif/* New in Solaris 7 */#ifdef ns_get16#define _getshort(cp) ns_get16(cp)#define _getlong(cp)  ns_get32(cp)#endiftypedef union {    HEADER hdr;    u_char buf[MAXPACKET];} querybuf_t;int _stx_dns_ttl;static int parse_answer(querybuf_t *ans, int len, struct in_addr *addrs,			int *num_addrs){    char buf[MAXPACKET];    HEADER *ahp;    u_char *cp, *eoa;    int type, n, i;    ahp = &ans->hdr;    eoa = ans->buf + len;    cp = ans->buf + sizeof(HEADER);    h_errno = TRY_AGAIN;    _stx_dns_ttl = -1;    i = 0;    while (ahp->qdcount > 0) {	ahp->qdcount--;	cp += dn_skipname(cp, eoa) + QFIXEDSZ;    }    while (ahp->ancount > 0 && cp < eoa && i < *num_addrs) {	ahp->ancount--;	if ((n = dn_expand(ans->buf, eoa, cp, buf, sizeof(buf))) < 0)	    return -1;	cp += n;	if (cp + 4 + 4 + 2 >= eoa)	    return -1;	type = _getshort(cp);	cp += 4;	if (type == T_A)	    _stx_dns_ttl = _getlong(cp);	cp += 4;	n = _getshort(cp);	cp += 2;	if (type == T_A) {	    if (n > sizeof(*addrs) || cp + n > eoa)		return -1;	    memcpy(&addrs[i++], cp, n);	}	cp += n;    }    *num_addrs = i;    return 0;}static int query_domain(st_netfd_t nfd, const char *name,			struct in_addr *addrs, int *num_addrs,			st_utime_t timeout){    querybuf_t qbuf;    u_char *buf = qbuf.buf;    HEADER *hp = &qbuf.hdr;    int blen = sizeof(qbuf);    int i, len, id;    for (i = 0; i < _res.nscount; i++) {	len = res_mkquery(QUERY, name, C_IN, T_A, NULL, 0, NULL, buf, blen);	if (len <= 0) {	    h_errno = NO_RECOVERY;	    return -1;	}	id = hp->id;	if (st_sendto(nfd, buf, len, (struct sockaddr *)&(_res.nsaddr_list[i]),		      sizeof(struct sockaddr), timeout) != len) {	    h_errno = NETDB_INTERNAL;	    /* EINTR means interrupt by other thread, NOT by a caught signal */	    if (errno == EINTR)		return -1;	    continue;	}	/* Wait for reply */	do {	    len = st_recvfrom(nfd, buf, blen, NULL, NULL, timeout);	    if (len <= 0)		break;	} while (id != hp->id);	if (len < HFIXEDSZ) {	    h_errno = NETDB_INTERNAL;	    if (len >= 0)		errno = EMSGSIZE;	    else if (errno == EINTR)  /* see the comment above */		return -1;	    continue;	}	hp->ancount = ntohs(hp->ancount);	hp->qdcount = ntohs(hp->qdcount);	if ((hp->rcode != NOERROR) || (hp->ancount == 0)) {	    switch (hp->rcode) {	    case NXDOMAIN:		h_errno = HOST_NOT_FOUND;		break;	    case SERVFAIL:		h_errno = TRY_AGAIN;		break;	    case NOERROR:		h_errno = NO_DATA;		break;	    case FORMERR:	    case NOTIMP:	    case REFUSED:	    default:		h_errno = NO_RECOVERY;	    }	    continue;	}	if (parse_answer(&qbuf, len, addrs, num_addrs) == 0)	    return 0;    }    return -1;}#define CLOSE_AND_RETURN(ret) \  {                           \    n = errno;                \    st_netfd_close(nfd);      \    errno = n;                \    return (ret);             \  }int _stx_dns_getaddrlist(const char *host, struct in_addr *addrs,                         int *num_addrs, st_utime_t timeout){    char name[MAXDNAME], **domain;    const char *cp;    int s, n, maxlen, dots;    int trailing_dot, tried_as_is;    st_netfd_t nfd;    if ((_res.options & RES_INIT) == 0 && res_init() == -1) {	h_errno = NETDB_INTERNAL;	return -1;    }    if (_res.options & RES_USEVC) {	h_errno = NETDB_INTERNAL;	errno = ENOSYS;	return -1;    }    if (!host || *host == '\0') {	h_errno = HOST_NOT_FOUND;	return -1;    }    /* Create UDP socket */    if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {	h_errno = NETDB_INTERNAL;	return -1;    }    if ((nfd = st_netfd_open_socket(s)) == NULL) {	h_errno = NETDB_INTERNAL;	n = errno;	close(s);	errno = n;	return -1;    }    maxlen = sizeof(name) - 1;    n = 0;    dots = 0;    trailing_dot = 0;    tried_as_is = 0;    for (cp = host; *cp && n < maxlen; cp++) {	dots += (*cp == '.');	name[n++] = *cp;    }    if (name[n - 1] == '.')	trailing_dot = 1;    /*     * If there are dots in the name already, let's just give it a try     * 'as is'.  The threshold can be set with the "ndots" option.     */    if (dots >= _res.ndots) {	if (query_domain(nfd, host, addrs, num_addrs, timeout) == 0)	    CLOSE_AND_RETURN(0);	if (h_errno == NETDB_INTERNAL && errno == EINTR)	    CLOSE_AND_RETURN(-1);	tried_as_is = 1;    }    /*     * We do at least one level of search if     *     - there is no dot and RES_DEFNAME is set, or     *     - there is at least one dot, there is no trailing dot,     *       and RES_DNSRCH is set.     */    if ((!dots && (_res.options & RES_DEFNAMES)) ||	(dots && !trailing_dot && (_res.options & RES_DNSRCH))) {	name[n++] = '.';	for (domain = _res.dnsrch; *domain; domain++) {	    strncpy(name + n, *domain, maxlen - n);	    if (query_domain(nfd, name, addrs, num_addrs, timeout) == 0)		CLOSE_AND_RETURN(0);	    if (h_errno == NETDB_INTERNAL && errno == EINTR)		CLOSE_AND_RETURN(-1);	    if (!(_res.options & RES_DNSRCH))		break;	}    }    /*     * If we have not already tried the name "as is", do that now.     * note that we do this regardless of how many dots were in the     * name or whether it ends with a dot.     */    if (!tried_as_is) {	if (query_domain(nfd, host, addrs, num_addrs, timeout) == 0)	    CLOSE_AND_RETURN(0);    }    CLOSE_AND_RETURN(-1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -