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

📄 resolv.c

📁 Axis 221 camera embedded programing interface
💻 C
📖 第 1 页 / 共 4 页
字号:
	j = __encode_question(&q, packet + i, maxlen - i);	if (j < 0)		return j;	return i + j;}#endif#ifdef L_dnslookup#ifdef __UCLIBC_HAS_THREADS__static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;# define LOCK	__pthread_mutex_lock(&mylock)# define UNLOCK	__pthread_mutex_unlock(&mylock);#else# define LOCK# define UNLOCK#endif/* Just for the record, having to lock __dns_lookup() just for these two globals * is pretty lame.  I think these two variables can probably be de-global-ized,  * which should eliminate the need for doing locking here...  Needs a closer  * look anyways. */static int ns=0, id=1;int __dns_lookup(const char *name, int type, int nscount, char **nsip,			   unsigned char **outpacket, struct resolv_answer *a){	int i, j, len, fd, pos, rc;	struct timeval tv;	fd_set fds;	struct resolv_header h;	struct resolv_question q;	int retries = 0;	unsigned char * packet = malloc(PACKETSZ);	char *dns, *lookup = malloc(MAXDNAME);	int variant = -1;	struct sockaddr_in sa;#ifdef __UCLIBC_HAS_IPV6__	int v6;	struct sockaddr_in6 sa6;#endif	fd = -1;	if (!packet || !lookup || !nscount)	    goto fail;	DPRINTF("Looking up type %d answer for '%s'\n", type, name);	LOCK;	ns %= nscount;	UNLOCK;	while (retries < MAX_RETRIES) {		if (fd != -1)			close(fd);		memset(packet, 0, PACKETSZ);		memset(&h, 0, sizeof(h));		/* Mess with globals while under lock */		LOCK;		++id;		id &= 0xffff;		h.id = id;		dns = nsip[ns];		UNLOCK;		h.qdcount = 1;		h.rd = 1;		DPRINTF("encoding header\n", h.rd);		i = __encode_header(&h, packet, PACKETSZ);		if (i < 0)			goto fail;		strncpy(lookup,name,MAXDNAME);		if (variant >= 0) {                        BIGLOCK;                        if (variant < __searchdomains) {                                strncat(lookup,".", MAXDNAME);                                strncat(lookup,__searchdomain[variant], MAXDNAME);                        }                        BIGUNLOCK;                }		DPRINTF("lookup name: %s\n", lookup);		q.dotted = (char *)lookup;		q.qtype = type;		q.qclass = C_IN; /* CLASS_IN */		j = __encode_question(&q, packet+i, PACKETSZ-i);		if (j < 0)			goto fail;		len = i + j;		DPRINTF("On try %d, sending query to port %d of machine %s\n",				retries+1, NAMESERVER_PORT, dns);#ifdef __UCLIBC_HAS_IPV6__		v6 = inet_pton(AF_INET6, dns, &sa6.sin6_addr) > 0;		fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);#else		fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);#endif		if (fd < 0) {                    retries++;		    continue;		}		/* Connect to the UDP socket so that asyncronous errors are returned */		 #ifdef __UCLIBC_HAS_IPV6__		if (v6) {		    sa6.sin6_family = AF_INET6;		    sa6.sin6_port = htons(NAMESERVER_PORT);		    /* sa6.sin6_addr is already here */		    rc = connect(fd, (struct sockaddr *) &sa6, sizeof(sa6));		} else {#endif		    sa.sin_family = AF_INET;		    sa.sin_port = htons(NAMESERVER_PORT);		    sa.sin_addr.s_addr = inet_addr(dns);		    rc = connect(fd, (struct sockaddr *) &sa, sizeof(sa));#ifdef __UCLIBC_HAS_IPV6__		}#endif		if (rc < 0) {		    if (errno == ENETUNREACH) {			/* routing error, presume not transient */			goto tryall;		    } else			/* retry */                        retries++;			continue;		}		DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",				len, h.id, h.qr);		send(fd, packet, len, 0);		FD_ZERO(&fds);		FD_SET(fd, &fds);		tv.tv_sec = REPLY_TIMEOUT;		tv.tv_usec = 0;		if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) {		    DPRINTF("Timeout\n");			/* timed out, so retry send and receive, 			 * to next nameserver on queue */			goto tryall;		}		len = recv(fd, packet, 512, 0);		if (len < HFIXEDSZ) {			/* too short ! */			goto again;		}		__decode_header(packet, &h);		DPRINTF("id = %d, qr = %d\n", h.id, h.qr);		LOCK;		if ((h.id != id) || (!h.qr)) {			UNLOCK;			/* unsolicited */			goto again;		}		UNLOCK;		DPRINTF("Got response %s\n", "(i think)!");		DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",				h.qdcount, h.ancount, h.nscount, h.arcount);		DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",				h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode);		if ((h.rcode) || (h.ancount < 1)) {			/* negative result, not present */			goto again;		}		pos = HFIXEDSZ;		for (j = 0; j < h.qdcount; j++) {			DPRINTF("Skipping question %d at %d\n", j, pos);			i = __length_question(packet, pos);			DPRINTF("Length of question %d is %d\n", j, i);			if (i < 0)				goto again;			pos += i;		}		DPRINTF("Decoding answer at pos %d\n", pos);		for (j=0;j<h.ancount;j++)		{		    i = __decode_answer(packet, pos, a);		    if (i<0) {			DPRINTF("failed decode %d\n", i);			goto again;		    }		    /* For all but T_SIG, accept first answer */		    if (a->atype != T_SIG)			break;		    DPRINTF("skipping T_SIG %d\n", i);		    free(a->dotted);		    pos += i;		}		DPRINTF("Answer name = |%s|\n", a->dotted);		DPRINTF("Answer type = |%d|\n", a->atype);		close(fd);		if (outpacket)			*outpacket = packet;		else			free(packet);		free(lookup);		return (len);				/* success! */	  tryall:		/* if there are other nameservers, give them a go,		   otherwise return with error */		{		    variant = -1;                    LOCK;                    ns = (ns + 1) % nscount;                    if (ns == 0)                      retries++;                    UNLOCK;                    continue;		}	  again:		/* if there are searchdomains, try them or fallback as passed */		{		    int sdomains;		    BIGLOCK;		    sdomains=__searchdomains;		    BIGUNLOCK;		    if (variant < sdomains - 1) {			/* next search */			variant++;		    } else {			/* next server, first search */			LOCK;			ns = (ns + 1) % nscount;                        if (ns == 0)                          retries++;			UNLOCK;			variant = -1;		    }		}	}fail:	if (fd != -1)	    close(fd);	if (lookup)	    free(lookup);	if (packet)	    free(packet);	h_errno = NETDB_INTERNAL;	return -1;}#endif#ifdef L_opennameserversint __nameservers;char * __nameserver[MAX_SERVERS];int __searchdomains;char * __searchdomain[MAX_SEARCH];#ifdef __UCLIBC_HAS_THREADS__pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER;#endif/* *	we currently read formats not quite the same as that on normal *	unix systems, we can have a list of nameservers after the keyword. */int __open_nameservers(){	FILE *fp;	int i;#define RESOLV_ARGS 5	char szBuffer[128], *p, *argv[RESOLV_ARGS];	int argc;	BIGLOCK;	if (__nameservers > 0) { 	    BIGUNLOCK;	    return 0;	}	if ((fp = fopen("/etc/resolv.conf", "r")) ||			(fp = fopen("/etc/config/resolv.conf", "r")))	{		while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) {			for (p = szBuffer; *p && isspace(*p); p++)				/* skip white space */;			if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */				continue;			argc = 0;			while (*p && argc < RESOLV_ARGS) {				argv[argc++] = p;				while (*p && !isspace(*p) && *p != '\n')					p++;				while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */					*p++ = '\0';			}			if (strcmp(argv[0], "nameserver") == 0) {				for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) {					__nameserver[__nameservers++] = strdup(argv[i]);					DPRINTF("adding nameserver %s\n", argv[i]);				}			}			/* domain and search are mutually exclusive, the last one wins */			if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) {				while (__searchdomains > 0) {					free(__searchdomain[--__searchdomains]);					__searchdomain[__searchdomains] = NULL;				}				for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) {					__searchdomain[__searchdomains++] = strdup(argv[i]);					DPRINTF("adding search %s\n", argv[i]);				}			}		}		fclose(fp);		DPRINTF("nameservers = %d\n", __nameservers);		BIGUNLOCK;		return 0;	}	DPRINTF("failed to open %s\n", "resolv.conf");	h_errno = NO_RECOVERY;	BIGUNLOCK;	return -1;}#endif#ifdef L_closenameserversvoid __close_nameservers(void){	BIGLOCK;	while (__nameservers > 0) {		free(__nameserver[--__nameservers]);		__nameserver[__nameservers] = NULL;	}	while (__searchdomains > 0) {		free(__searchdomain[--__searchdomains]);		__searchdomain[__searchdomains] = NULL;	}	BIGUNLOCK;}#endif#ifdef L_gethostbynamestruct hostent *gethostbyname(const char *name){	static struct hostent h;	static char buf[sizeof(struct in_addr) +			sizeof(struct in_addr *)*2 +			sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];	struct hostent *hp;	gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);	return hp;}#endif#ifdef L_gethostbyname2struct hostent *gethostbyname2(const char *name, int family){#ifndef __UCLIBC_HAS_IPV6__	return family == AF_INET ? gethostbyname(name) : (struct hostent*)0;#else /* __UCLIBC_HAS_IPV6__ */	static struct hostent h;	static char buf[sizeof(struct in6_addr) +			sizeof(struct in6_addr *)*2 +			sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];	struct hostent *hp;	gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno);	return hp;#endif /* __UCLIBC_HAS_IPV6__ */}#endif#ifdef L_res_initstruct __res_state _res;int res_init(void){	struct __res_state *rp = &(_res);	__close_nameservers();	__open_nameservers();	rp->retrans = RES_TIMEOUT;	rp->retry = 4;	rp->options = RES_INIT;	rp->id = (u_int) random();	rp->nsaddr.sin_addr.s_addr = INADDR_ANY;	rp->nsaddr.sin_family = AF_INET;	rp->nsaddr.sin_port = htons(NAMESERVER_PORT);	rp->ndots = 1;	/** rp->pfcode = 0; **/	rp->_vcsock = -1;	/** rp->_flags = 0; **/	/** rp->qhook = NULL; **/	/** rp->rhook = NULL; **/	/** rp->_u._ext.nsinit = 0; **/	BIGLOCK;	if(__searchdomains) {		int i;		for(i=0; i<__searchdomains; i++) {			rp->dnsrch[i] = __searchdomain[i];		}	}	if(__nameservers) {		int i;		struct in_addr a;		for(i=0; i<__nameservers; i++) {			if (inet_aton(__nameserver[i], &a)) {				rp->nsaddr_list[i].sin_addr = a;				rp->nsaddr_list[i].sin_family = AF_INET;				rp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);			}		}	}	rp->nscount = __nameservers;	BIGUNLOCK;	return(0);}void res_close( void ){	return;}#endif#ifdef L_res_query#ifndef MIN#define MIN(x, y)	((x) < (y) ? (x) : (y))#endifint res_query(const char *dname, int class, int type,              unsigned char *answer, int anslen){	int i;	unsigned char * packet = 0;	struct resolv_answer a;	int __nameserversXX;	char ** __nameserverXX;	__open_nameservers();	if (!dname || class != 1 /* CLASS_IN */) {		h_errno = NO_RECOVERY;		return(-1);	}	memset((char *) &a, '\0', sizeof(a));	BIGLOCK;	__nameserversXX=__nameservers;	__nameserverXX=__nameserver;	BIGUNLOCK;	i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a);	if (i < 0) {		h_errno = TRY_AGAIN;		return(-1);	}	free(a.dotted);	if (a.atype == type) { /* CNAME*/		int len = MIN(anslen, i);		memcpy(answer, packet, len);		if (packet)			free(packet);		return(len);	}	if (packet)		free(packet);	return i;}/* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure * is detected.  Error code, if any, is left in h_errno. */int res_search(name, class, type, answer, anslen)	const char *name;	/* domain name */	int class, type;	/* class and type of query */	u_char *answer;		/* buffer to put answer */	int anslen;		/* size of answer */{	const char *cp, * const *domain;	HEADER *hp = (HEADER *)(void *)answer;	u_int dots;	int trailing_dot, ret, saved_herrno;	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;	if ((!name || !answer) || ((_res.options & RES_INIT) == 0 && res_init() == -1)) {		h_errno = NETDB_INTERNAL;		return (-1);	}	errno = 0;	h_errno = HOST_NOT_FOUND;	/* default, if we never query */	dots = 0;	for (cp = name; *cp; cp++)		dots += (*cp == '.');	trailing_dot = 0;	if (cp > name && *--cp == '.')		trailing_dot++;	/*	 * 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.	 */	saved_herrno = -1;	if (dots >= _res.ndots) {		ret = res_querydomain(name, NULL, class, type, answer, anslen);		if (ret > 0)			return (ret);		saved_herrno = h_errno;		tried_as_is++;	}	/*	 * 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))) {		int done = 0;		for (domain = (const char * const *)_res.dnsrch;		   *domain && !done;		   domain++) {			ret = res_querydomain(name, *domain, class, type,			    answer, anslen);			if (ret > 0)				return (ret);			/*			 * If no server present, give up.			 * If name isn't found in this domain,			 * keep trying higher domains in the search list			 * (if that's enabled).			 * On a NO_DATA error, keep trying, otherwise			 * a wildcard entry of another type could keep us			 * from finding this entry higher in the domain.			 * If we get some other error (negative answer or			 * server failure), then stop searching up,			 * but try the input name below in case it's			 * fully-qualified.			 */			if (errno == ECONNREFUSED) {				h_errno = TRY_AGAIN;				return (-1);			}			switch (h_errno) {			case NO_DATA:				got_nodata++;				/* FALLTHROUGH */			case HOST_NOT_FOUND:				/* keep trying */				break;			case TRY_AGAIN:				if (hp->rcode == SERVFAIL) {					/* try next search element, if any */					got_servfail++;					break;				}				/* FALLTHROUGH */			default:				/* anything else implies that we're done */				done++;			}			/*			 * if we got here for some reason other than DNSRCH,			 * we only wanted one iteration of the loop, so stop.			 */			if (!(_res.options & RES_DNSRCH))				done++;		}	}	/*	 * 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) {		ret = res_querydomain(name, NULL, class, type, answer, anslen);		if (ret > 0)			return (ret);	}

⌨️ 快捷键说明

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