diff options
| -rw-r--r-- | libc/inet/Makefile | 5 | ||||
| -rw-r--r-- | libc/inet/resolv.c | 261 | 
2 files changed, 233 insertions, 33 deletions
| diff --git a/libc/inet/Makefile b/libc/inet/Makefile index 9971dff53..ff366f82e 100644 --- a/libc/inet/Makefile +++ b/libc/inet/Makefile @@ -33,8 +33,9 @@ MSRC2=resolv.c  MOBJ2=encodeh.o decodeh.o encoded.o decoded.o lengthd.o encodeq.o \  	decodeq.o lengthq.o encodea.o decodea.o encodep.o decodep.o \  	formquery.o dnslookup.o resolveaddress.o resolvemailbox.o \ -	opennameservers.o closenameservers.o resolvename.o gethostbyname.o\ -	gethostbyaddr.o +	opennameservers.o closenameservers.o resolvename.o gethostbyname.o \ +	gethostbyaddr.o res_init.o res_query.o getnetbyname.o \ +	read_etc_hosts.o get_hosts_byname.o get_hosts_byaddr.o  MSRC3=socketcalls.c  MOBJ3= accept.o bind.o connect.o getpeername.o getsockname.o getsockopt.o \ diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c index 38aa9b272..d02d29fbc 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -49,6 +49,7 @@  #include <cfgfile.h>  #include <resolv.h>  #include <netdb.h> +#include <ctype.h>  #include <arpa/nameser.h>  #define MAX_RECURSE 5 @@ -59,16 +60,20 @@  #undef DEBUG  #ifdef DEBUG -static inline void DPRINTF(const char *format, ...) -{ -	va_list args; -	va_start(args, format); -	vfprintf(stderr, format, args); -	va_end(args); -} +#define DPRINTF(X,args...) fprintf(stderr, X, ##args)  #else -static inline void DPRINTF(const char *format, ...) { } -#endif +#define DPRINTF(X,args...) +#endif /* DEBUG */ + + +extern int nameservers; +extern const char * nameserver[MAX_SERVERS]; +extern int searchdomains; +extern const 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); +  #ifdef L_encodeh  int encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) @@ -461,8 +466,6 @@ int dns_lookup(const char *name, int type, int nscount, const char **nsip,  	unsigned char * packet = malloc(PACKETSZ);  	unsigned char * lookup = malloc(MAXDNAME);  	int variant = 0; -	extern int searchdomains; -	extern const char * searchdomain[MAX_SEARCH];  	fd = -1; @@ -753,10 +756,6 @@ int resolve_mailbox(const char *address,  }  #endif -extern int nameservers; -extern const char * nameserver[MAX_SERVERS]; -extern int searchdomains; -extern const char * searchdomain[MAX_SEARCH];  #ifdef L_opennameservers @@ -765,26 +764,57 @@ const char * nameserver[MAX_SERVERS];  int searchdomains;  const char * searchdomain[MAX_SEARCH]; +/* + *	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; -	char **arg;  	int i; +#define RESOLV_ARGS 5 +	char szBuffer[128], *p, *argv[RESOLV_ARGS]; +	int argc;  	if (nameservers > 0)   	    return 0; -	if ((fp = fopen("/etc/resolv.conf", "r"))) { -		if (0 != (arg = cfgfind(fp, "nameserver"))) { -			for (i=1; arg[i] && nameservers <= MAX_SERVERS; i++) { -				nameserver[nameservers++] = strdup(arg[i]); -				DPRINTF("adding nameserver %s\n",arg[i]); +	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]); +				}  			} -		} -		if (0 != (arg = cfgfind(fp, "search"))) { -			for (i=1; arg[i] && searchdomains <= MAX_SEARCH; i++) { -				searchdomain[searchdomains++] = strdup(arg[i]); -				DPRINTF("adding search %s\n",arg[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); @@ -796,12 +826,19 @@ int open_nameservers()  }  #endif +  #ifdef L_closenameservers +  void close_nameservers(void)  { - -	while (nameservers > 0) -		free((void*)nameserver[--nameservers]); +	while (nameservers > 0) { +		free(nameserver[--nameservers]); +		nameserver[nameservers] = NULL; +	} +	while (searchdomains > 0) { +		free(searchdomain[--searchdomains]); +		searchdomain[searchdomains] = NULL; +	}  }  #endif @@ -836,6 +873,7 @@ const char *resolve_name(const char *name, int mailbox)  }  #endif +  #ifdef L_gethostbyname  struct hostent *gethostbyname(const char *name) @@ -844,6 +882,7 @@ struct hostent *gethostbyname(const char *name)  	static char namebuf[256];  	static struct in_addr in;  	static struct in_addr *addr_list[2]; +	struct hostent *hp;  	unsigned char *packet;  	struct resolv_answer a;  	int i; @@ -853,13 +892,16 @@ struct hostent *gethostbyname(const char *name)  	if (!name)  		return 0; -	 + +	if ((hp = get_hosts_byname(name))) /* do /etc/hosts first */ +		return(hp); +  	memset(&h, 0, sizeof(h));  	addr_list[0] = ∈  	addr_list[1] = 0; -	strcpy(namebuf, name); +	strncpy(namebuf, name, sizeof(namebuf));  	/* First check if this is already an address */  	if (inet_aton(name, &in)) { @@ -909,6 +951,66 @@ struct hostent *gethostbyname(const char *name)  }  #endif + +#ifdef L_getnetbyname + +struct netent * getnetbyname(const char * name) +{ +	return NULL; +} +#endif + + +#ifdef L_res_init + +int res_init() +{ +	return(0); +} +#endif + + +#ifdef L_res_query + +#ifndef MIN +#define MIN(x, y)	((x) < (y) ? (x) : (y)) +#endif + +int res_query(const char *dname, int class, int type, +              unsigned char *answer, int anslen) +{ +	unsigned char * packet = 0; +	struct resolv_answer a; +	int i; + +	open_nameservers(); +	 +	if (!dname || class != 1 /* CLASS_IN */) +		return(-1); +		 +	memset((char *) &a, '\0', sizeof(a)); + +	i = dns_lookup(dname, type, nameservers, nameserver, &packet, &a); +	 +	if (i < 0) +		return(-1); +			 +	free(a.dotted); +		 +	if (a.atype == type) { /* CNAME*/ +		if (anslen && answer) +			memcpy(answer, a.rdata, MIN(anslen, a.rdlength)); +		if (packet) +			free(packet); +		return(MIN(anslen, a.rdlength)); +	} +	if (packet) +		free(packet); +	return 0; +} +#endif + +  #ifdef L_gethostbyaddr  struct hostent *gethostbyaddr(const char *addr, int len, int type) @@ -917,6 +1019,7 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type)  	static char namebuf[256];  	static struct in_addr in;  	static struct in_addr *addr_list[2]; +	struct hostent *hp;  	unsigned char *packet;  	struct resolv_answer a;  	int i; @@ -925,6 +1028,9 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type)  	if (!addr || (len != sizeof(in)) || (type != AF_INET))  		return 0; +	if ((hp = get_hosts_byaddr(addr, len, type))) /* do /etc/hosts first */ +		return(hp); +  	memcpy(&in.s_addr, addr, len);  	open_nameservers(); @@ -978,3 +1084,96 @@ struct hostent *gethostbyaddr(const char *addr, int len, int type)  	return &h;  }  #endif + + +#ifdef L_read_etc_hosts + +struct hostent * read_etc_hosts(const char * name, int ip) +{ +	static struct hostent	h; +	static struct in_addr	in; +	static struct in_addr	*addr_list[2]; +	static char				line[80]; +	FILE					*fp; +	char					*cp; +#define		 MAX_ALIAS		5 +	char					*alias[MAX_ALIAS]; +	int						aliases, i; + +	if ((fp = fopen("/etc/hosts", "r")) == NULL && +			(fp = fopen("/etc/config/hosts", "r")) == NULL) +		return((struct hostent *) NULL); + +	while (fgets(line, sizeof(line), fp)) { +		if ((cp = strchr(line, '#'))) +			*cp = '\0'; +		aliases = 0; + +		cp = line; +		while (*cp) { +			while (*cp && isspace(*cp)) +				*cp++ = '\0'; +			if (!*cp) +				continue; +			if (aliases < MAX_ALIAS) +				alias[aliases++] = cp; +			while (*cp && !isspace(*cp)) +				cp++; +		} + +		if (aliases < 2) +			continue; /* syntax error really */ +		 +		if (ip) { +			if (strcmp(name, alias[0]) != 0) +				continue; +		} else { +			for (i = 1; i < aliases; i++) +				if (strcasecmp(name, alias[i]) == 0) +					break; +			if (i >= aliases) +				continue; +		} + +		if (inet_aton(alias[0], &in) == 0) +			break; /* bad ip address */ + +		addr_list[0] = ∈ +		addr_list[1] = 0; +		h.h_name = alias[1]; +		h.h_addrtype = AF_INET; +		h.h_length = sizeof(in); +		h.h_addr_list = (char**) addr_list; +		fclose(fp); +		return(&h); +	} +	fclose(fp); +	return((struct hostent *) NULL); +} +#endif + + +#ifdef L_get_hosts_byname + +struct hostent * get_hosts_byname(const char * name) +{ +	return(read_etc_hosts(name, 0)); +} +#endif + + +#ifdef L_get_hosts_byaddr + +struct hostent * get_hosts_byaddr(const char * addr, int len, int type) +{ +	char	ipaddr[20]; + +	if (type != AF_INET || len != sizeof(struct in_addr)) +		return((struct hostent *) NULL); + +	strcpy(ipaddr, inet_ntoa(* (struct in_addr *) addr)); +	return(read_etc_hosts(ipaddr, 1)); +} +#endif + + | 
