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

📄 resolv.c

📁 linux下用PCMCIA无线网卡虚拟无线AP的程序源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* resolv.c: DNS Resolver * * Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>, *                     The Silver Hammer Group, Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * *  5-Oct-2000 W. Greathouse  wgreathouse@smva.com *                              Fix memory leak and memory corruption. *                              -- Every name resolution resulted in *                                 a new parse of resolv.conf and new *                                 copy of nameservers allocated by *                                 strdup. *                              -- Every name resolution resulted in *                                 a new read of resolv.conf without *                                 resetting index from prior read... *                                 resulting in exceeding array bounds. * *                              Limit nameservers read from resolv.conf * *                              Add "search" domains from resolv.conf * *                              Some systems will return a security *                              signature along with query answer for *                              dynamic DNS entries. *                              -- skip/ignore this answer * *                              Include arpa/nameser.h for defines. * *                              General cleanup * * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl> *   partial IPv6 support (i.e. gethostbyname2() and resolve_address2() *   functions added), IPv6 nameservers are also supported. * */#define __FORCE_GLIBC__#include <features.h>#include <string.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <unistd.h>#include <resolv.h>#include <netdb.h>#include <ctype.h>#include <arpa/nameser.h>#define MAX_RECURSE 5#define REPLY_TIMEOUT 10#define MAX_RETRIES 15#define MAX_SERVERS 3#define MAX_SEARCH 4#undef DEBUG/*#define DEBUG*/#ifdef DEBUG#define DPRINTF(X,args...) fprintf(stderr, X, ##args)#else#define DPRINTF(X,args...)#endif /* DEBUG */struct resolv_header {	int id;	int qr,opcode,aa,tc,rd,ra,rcode;	int qdcount;	int ancount;	int nscount;	int arcount;};struct resolv_question {	char * dotted;	int qtype;	int qclass;};struct resolv_answer {	char * dotted;	int atype;	int aclass;	int ttl;	int rdlength;	unsigned char * rdata;	int rdoffset;};extern int nameservers;extern char * nameserver[MAX_SERVERS];extern int searchdomains;extern char * searchdomain[MAX_SEARCH];extern struct hostent * get_hosts_byname(const char * name);extern struct hostent * get_hosts_byaddr(const char * addr, int len, int type);extern struct hostent * read_etc_hosts(const char * name, int ip);extern int resolve_address(const char * address, int nscount, 	char ** nsip, struct in_addr * in);extern int resolve_mailbox(const char * address, int nscount, 	char ** nsip, struct in_addr * in);extern int dns_lookup(const char * name, int type, int nscount, 	char ** nsip, unsigned char ** outpacket, struct resolv_answer * a);int encode_dotted(const char * dotted, unsigned char * dest, int maxlen);int decode_dotted(const unsigned char * message, int offset, 	char * dest, int maxlen);int length_dotted(const unsigned char * message, int offset);int encode_header(struct resolv_header * h, unsigned char * dest, int maxlen);int decode_header(unsigned char * data, struct resolv_header * h);int encode_question(struct resolv_question * q,	unsigned char * dest, int maxlen);int decode_question(unsigned char * message, int offset,	struct resolv_question * q);int encode_answer(struct resolv_answer * a,	unsigned char * dest, int maxlen);int decode_answer(unsigned char * message, int offset,	struct resolv_answer * a);int length_question(unsigned char * message, int offset);extern int open_nameservers(void);#ifdef L_encodehint encode_header(struct resolv_header *h, unsigned char *dest, int maxlen){	if (maxlen < HFIXEDSZ)		return -1;	dest[0] = (h->id & 0xff00) >> 8;	dest[1] = (h->id & 0x00ff) >> 0;	dest[2] = (h->qr ? 0x80 : 0) |		((h->opcode & 0x0f) << 3) |		(h->aa ? 0x04 : 0) | 		(h->tc ? 0x02 : 0) | 		(h->rd ? 0x01 : 0);	dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f);	dest[4] = (h->qdcount & 0xff00) >> 8;	dest[5] = (h->qdcount & 0x00ff) >> 0;	dest[6] = (h->ancount & 0xff00) >> 8;	dest[7] = (h->ancount & 0x00ff) >> 0;	dest[8] = (h->nscount & 0xff00) >> 8;	dest[9] = (h->nscount & 0x00ff) >> 0;	dest[10] = (h->arcount & 0xff00) >> 8;	dest[11] = (h->arcount & 0x00ff) >> 0;	return HFIXEDSZ;}#endif#ifdef L_decodehint decode_header(unsigned char *data, struct resolv_header *h){	h->id = (data[0] << 8) | data[1];	h->qr = (data[2] & 0x80) ? 1 : 0;	h->opcode = (data[2] >> 3) & 0x0f;	h->aa = (data[2] & 0x04) ? 1 : 0;	h->tc = (data[2] & 0x02) ? 1 : 0;	h->rd = (data[2] & 0x01) ? 1 : 0;	h->ra = (data[3] & 0x80) ? 1 : 0;	h->rcode = data[3] & 0x0f;	h->qdcount = (data[4] << 8) | data[5];	h->ancount = (data[6] << 8) | data[7];	h->nscount = (data[8] << 8) | data[9];	h->arcount = (data[10] << 8) | data[11];	return HFIXEDSZ;}#endif#ifdef L_encoded/* Encode a dotted string into nameserver transport-level encoding.   This routine is fairly dumb, and doesn't attempt to compress   the data */int encode_dotted(const char *dotted, unsigned char *dest, int maxlen){	int used = 0;	while (dotted && *dotted) {		char *c = strchr(dotted, '.');		int l = c ? c - dotted : strlen(dotted);		if (l >= (maxlen - used - 1))			return -1;		dest[used++] = l;		memcpy(dest + used, dotted, l);		used += l;		if (c)			dotted = c + 1;		else			break;	}	if (maxlen < 1)		return -1;	dest[used++] = 0;	return used;}#endif#ifdef L_decoded/* Decode a dotted string from nameserver transport-level encoding.   This routine understands compressed data. */int decode_dotted(const unsigned char *data, int offset,				  char *dest, int maxlen){	int l;	int measure = 1;	int total = 0;	int used = 0;	if (!data)		return -1;	while ((l=data[offset++])) {		if (measure)		    total++;		if ((l & 0xc0) == (0xc0)) {			if (measure)				total++;			/* compressed item, redirect */			offset = ((l & 0x3f) << 8) | data[offset];			measure = 0;			continue;		}		if ((used + l + 1) >= maxlen)			return -1;		memcpy(dest + used, data + offset, l);		offset += l;		used += l;		if (measure)			total += l;		if (data[offset] != 0)			dest[used++] = '.';		else			dest[used++] = '\0';	}	DPRINTF("Total decode len = %d\n", total);	return total;}#endif#ifdef L_lengthdint length_dotted(const unsigned char *data, int offset){	int orig_offset = offset;	int l;	if (!data)		return -1;	while ((l = data[offset++])) {		if ((l & 0xc0) == (0xc0)) {			offset++;			break;		}		offset += l;	}	return offset - orig_offset;}#endif#ifdef L_encodeqint encode_question(struct resolv_question *q,					unsigned char *dest, int maxlen){	int i;	i = encode_dotted(q->dotted, dest, maxlen);	if (i < 0)		return i;	dest += i;	maxlen -= i;	if (maxlen < 4)		return -1;	dest[0] = (q->qtype & 0xff00) >> 8;	dest[1] = (q->qtype & 0x00ff) >> 0;	dest[2] = (q->qclass & 0xff00) >> 8;	dest[3] = (q->qclass & 0x00ff) >> 0;	return i + 4;}#endif#ifdef L_decodeqint decode_question(unsigned char *message, int offset,					struct resolv_question *q){	char temp[256];	int i;	i = decode_dotted(message, offset, temp, sizeof(temp));	if (i < 0)		return i;	offset += i;	q->dotted = strdup(temp);	q->qtype = (message[offset + 0] << 8) | message[offset + 1];	q->qclass = (message[offset + 2] << 8) | message[offset + 3];	return i + 4;}#endif#ifdef L_lengthqint length_question(unsigned char *message, int offset){	int i;	i = length_dotted(message, offset);	if (i < 0)		return i;	return i + 4;}#endif#ifdef L_encodeaint encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen){	int i;	i = encode_dotted(a->dotted, dest, maxlen);	if (i < 0)		return i;	dest += i;	maxlen -= i;	if (maxlen < (RRFIXEDSZ+a->rdlength))		return -1;	*dest++ = (a->atype & 0xff00) >> 8;	*dest++ = (a->atype & 0x00ff) >> 0;	*dest++ = (a->aclass & 0xff00) >> 8;	*dest++ = (a->aclass & 0x00ff) >> 0;	*dest++ = (a->ttl & 0xff000000) >> 24;	*dest++ = (a->ttl & 0x00ff0000) >> 16;	*dest++ = (a->ttl & 0x0000ff00) >> 8;	*dest++ = (a->ttl & 0x000000ff) >> 0;	*dest++ = (a->rdlength & 0xff00) >> 8;	*dest++ = (a->rdlength & 0x00ff) >> 0;	memcpy(dest, a->rdata, a->rdlength);	return i + RRFIXEDSZ + a->rdlength;}#endif#ifdef L_decodeaint decode_answer(unsigned char *message, int offset,				  struct resolv_answer *a){	char temp[256];	int i;	i = decode_dotted(message, offset, temp, sizeof(temp));	if (i < 0)		return i;	message += offset + i;	a->dotted = strdup(temp);	a->atype = (message[0] << 8) | message[1];	message += 2;	a->aclass = (message[0] << 8) | message[1];	message += 2;	a->ttl = (message[0] << 24) |		(message[1] << 16) | (message[2] << 8) | (message[3] << 0);	message += 4;	a->rdlength = (message[0] << 8) | message[1];	message += 2;	a->rdata = message;	a->rdoffset = offset + i + RRFIXEDSZ;	DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength);	return i + RRFIXEDSZ + a->rdlength;}#endif#ifdef L_encodepint encode_packet(struct resolv_header *h,	struct resolv_question **q,	struct resolv_answer **an,	struct resolv_answer **ns,	struct resolv_answer **ar,	unsigned char *dest, int maxlen){	int i, total = 0;	int j;	i = encode_header(h, dest, maxlen);	if (i < 0)		return i;	dest += i;	maxlen -= i;	total += i;	for (j = 0; j < h->qdcount; j++) {		i = encode_question(q[j], dest, maxlen);		if (i < 0)			return i;		dest += i;		maxlen -= i;		total += i;	}	for (j = 0; j < h->ancount; j++) {		i = encode_answer(an[j], dest, maxlen);		if (i < 0)			return i;		dest += i;		maxlen -= i;		total += i;	}	for (j = 0; j < h->nscount; j++) {		i = encode_answer(ns[j], dest, maxlen);		if (i < 0)			return i;		dest += i;		maxlen -= i;		total += i;	}	for (j = 0; j < h->arcount; j++) {		i = encode_answer(ar[j], dest, maxlen);		if (i < 0)			return i;		dest += i;		maxlen -= i;		total += i;	}	return total;}#endif#ifdef L_decodepint decode_packet(unsigned char *data, struct resolv_header *h){	return decode_header(data, h);}#endif#ifdef L_formqueryint form_query(int id, const char *name, int type, unsigned char *packet,			   int maxlen){	struct resolv_header h;	struct resolv_question q;	int i, j;	memset(&h, 0, sizeof(h));	h.id = id;	h.qdcount = 1;	q.dotted = (char *) name;	q.qtype = type;	q.qclass = C_IN; /* CLASS_IN */	i = encode_header(&h, packet, maxlen);	if (i < 0)		return i;	j = encode_question(&q, packet + i, maxlen - i);	if (j < 0)		return j;	return i + j;}#endif#ifdef L_dnslookupint dns_caught_signal = 0;void dns_catch_signal(int signo){	dns_caught_signal = 1;}int dns_lookup(const char *name, int type, int nscount, char **nsip,			   unsigned char **outpacket, struct resolv_answer *a){	static int id = 1;	int i, j, len, fd, pos;	static int ns = 0;	struct sockaddr_in sa;#ifdef __UCLIBC_HAS_IPV6__	struct sockaddr_in6 sa6;#endif /* __UCLIBC_HAS_IPV6__ */	int oldalarm;	__sighandler_t oldhandler;	struct resolv_header h;	struct resolv_question q;	int retries = 0;	unsigned char * packet = malloc(PACKETSZ);	unsigned char * lookup = malloc(MAXDNAME);	int variant = 0;#ifdef __UCLIBC_HAS_IPV6__	int v6;#endif /* __UCLIBC_HAS_IPV6__ */	fd = -1;	if (!packet || !lookup || !nscount)	    goto fail;	DPRINTF("Looking up type %d answer for '%s'\n", type, name);	ns %= nscount;	while (retries++ < MAX_RETRIES) {#ifdef __UCLIBC_HAS_IPV6__		v6 = (inet_pton(AF_INET6, nsip[ns], &sa6.sin6_addr) > 0);#endif /* __UCLIBC_HAS_IPV6__ */		if (fd != -1)			close(fd);#ifndef __UCLIBC_HAS_IPV6__		fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);#else /* __UCLIBC_HAS_IPV6__ */		fd = socket(v6 ? AF_INET6 : AF_INET, SOCK_DGRAM, IPPROTO_UDP);#endif /* __UCLIBC_HAS_IPV6__ */		if (fd == -1)			goto fail;		memset(packet, 0, PACKETSZ);		memset(&h, 0, sizeof(h));		h.id = ++id;		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 < searchdomains && strchr(lookup, '.') == NULL)		{		    strncat(lookup,".", MAXDNAME);		    strncat(lookup,searchdomain[variant], MAXDNAME);		}		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, NAMESERVER_PORT, nsip[ns]);#ifndef __UCLIBC_HAS_IPV6__		sa.sin_family = AF_INET;		sa.sin_port = htons(NAMESERVER_PORT);		sa.sin_addr.s_addr = inet_addr(nsip[ns]);#else /* __UCLIBC_HAS_IPV6__ */		if (v6) {			sa6.sin6_family = AF_INET6;			sa6.sin6_port = htons(NAMESERVER_PORT);			/* sa6.sin6_addr is already here */		} else {			sa.sin_family = AF_INET;			sa.sin_port = htons(NAMESERVER_PORT);			sa.sin_addr.s_addr = inet_addr(nsip[ns]);		}#endif /* __UCLIBC_HAS_IPV6__ */#ifndef __UCLIBC_HAS_IPV6__		if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {#else /* __UCLIBC_HAS_IPV6__ */		if (connect(fd, (struct sockaddr *) (v6 ? &sa6 : &sa), 			    v6 ? sizeof(sa6) : sizeof(sa)) == -1) {#endif /* __UCLIBC_HAS_IPV6__ */			if (errno == ENETUNREACH) {				/* routing error, presume not transient */				goto tryall;			} else				/* retry */				continue;		}		DPRINTF("Transmitting packet of length %d, id=%d, qr=%d\n",				len, h.id, h.qr);		send(fd, packet, len, 0);		dns_caught_signal = 0;		oldalarm = alarm(REPLY_TIMEOUT);		oldhandler = signal(SIGALRM, dns_catch_signal);		i = recv(fd, packet, PACKETSZ, 0);		alarm(0);		signal(SIGALRM, oldhandler);		alarm(oldalarm);		DPRINTF("Timeout=%d, len=%d\n", dns_caught_signal, i);		if (dns_caught_signal)			/* timed out, so retry send and receive,			   to next nameserver on queue */			goto again;		if (i < HFIXEDSZ)			/* too short ! */			goto again;		decode_header(packet, &h);		DPRINTF("id = %d, qr = %d\n", h.id, h.qr);		if ((h.id != id) || (!h.qr))			/* unsolicited */			goto again;		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)

⌨️ 快捷键说明

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