xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24733)
121374Sdist /*
224687Sbloom  * Copyright (c) 1983 Regents of the University of California.
321374Sdist  * All rights reserved.  The Berkeley software License Agreement
421374Sdist  * specifies the terms and conditions for redistribution.
521374Sdist  */
615662Sralph 
721374Sdist #ifndef lint
8*24733Sbloom static char sccsid[] = "@(#)gethostnamadr.c	5.7 (Berkeley) 09/14/85";
921374Sdist #endif not lint
1021374Sdist 
1118505Sralph #include <sys/types.h>
1218505Sralph #include <sys/socket.h>
1318505Sralph #include <netinet/in.h>
1418505Sralph #include <netdb.h>
1515662Sralph #include <stdio.h>
1624508Sbloom #include <arpa/nameser.h>
1724508Sbloom #include <arpa/resolv.h>
1815662Sralph 
1915662Sralph #define	MAXALIASES	35
2024687Sbloom #define MAXADDRS	35
2115662Sralph 
2224687Sbloom static char *h_addr_ptrs[MAXADDRS + 1];
2324687Sbloom 
2424687Sbloom static struct hostent host;
2515662Sralph static char *host_aliases[MAXALIASES];
2615912Sralph static char hostbuf[BUFSIZ+1];
2715662Sralph 
2824509Sbloom 
2915662Sralph static struct hostent *
3018505Sralph getanswer(msg, msglen, iquery)
3118505Sralph 	char *msg;
3218505Sralph 	int msglen, iquery;
3315662Sralph {
3418505Sralph 	register HEADER *hp;
3518505Sralph 	register char *cp;
3618505Sralph 	register int n;
3718505Sralph 	char answer[PACKETSZ];
3818505Sralph 	char *eom, *bp, **ap;
3918505Sralph 	int type, class, ancount, buflen;
4024687Sbloom 	int haveanswer, getclass;
4124687Sbloom 	char **hap;
4215662Sralph 
4318531Sralph 	n = res_send(msg, msglen, answer, sizeof(answer));
4418505Sralph 	if (n < 0) {
45*24733Sbloom #ifdef DEBUG
4618505Sralph 		if (_res.options & RES_DEBUG)
4718531Sralph 			printf("res_send failed\n");
48*24733Sbloom #endif
4918505Sralph 		return (NULL);
5015662Sralph 	}
5118505Sralph 	eom = answer + n;
5218505Sralph 	/*
5318505Sralph 	 * find first satisfactory answer
5418505Sralph 	 */
5518505Sralph 	hp = (HEADER *) answer;
5618505Sralph 	ancount = ntohs(hp->ancount);
5718505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
58*24733Sbloom #ifdef DEBUG
5918505Sralph 		if (_res.options & RES_DEBUG)
6018505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
61*24733Sbloom #endif
6218505Sralph 		return (NULL);
6318505Sralph 	}
6418505Sralph 	bp = hostbuf;
6518505Sralph 	buflen = sizeof(hostbuf);
6618505Sralph 	cp = answer + sizeof(HEADER);
6718505Sralph 	if (hp->qdcount) {
6818505Sralph 		if (iquery) {
6918505Sralph 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
7018505Sralph 				return (NULL);
7118505Sralph 			cp += n + QFIXEDSZ;
7218505Sralph 			host.h_name = bp;
7318505Sralph 			n = strlen(bp) + 1;
7418505Sralph 			bp += n;
7518505Sralph 			buflen -= n;
7618505Sralph 		} else
7718505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
7818505Sralph 	} else if (iquery)
7918505Sralph 		return (NULL);
8024687Sbloom 	ap = host_aliases;
8124687Sbloom 	host.h_aliases = host_aliases;
8224687Sbloom 	hap = h_addr_ptrs;
8324687Sbloom 	host.h_addr_list = h_addr_ptrs;
8424687Sbloom 	haveanswer = 0;
8518505Sralph 	while (--ancount >= 0 && cp < eom) {
8618505Sralph 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
8724687Sbloom 			break;
8818505Sralph 		cp += n;
8918505Sralph 		type = getshort(cp);
9018505Sralph  		cp += sizeof(u_short);
9118505Sralph 		class = getshort(cp);
9218505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
9318505Sralph 		n = getshort(cp);
9418505Sralph 		cp += sizeof(u_short);
9518505Sralph 		if (type == T_CNAME) {
9618505Sralph 			cp += n;
9718505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
9818505Sralph 				continue;
9918505Sralph 			*ap++ = bp;
10018505Sralph 			n = strlen(bp) + 1;
10118505Sralph 			bp += n;
10218505Sralph 			buflen -= n;
10318505Sralph 			continue;
10418505Sralph 		}
10524687Sbloom 		if (type != T_A)  {
106*24733Sbloom #ifdef DEBUG
10718505Sralph 			if (_res.options & RES_DEBUG)
10818505Sralph 				printf("unexpected answer type %d, size %d\n",
10918505Sralph 					type, n);
110*24733Sbloom #endif
11124687Sbloom 			cp += n;
11218505Sralph 			continue;
11318505Sralph 		}
11424687Sbloom 		if (haveanswer) {
11524687Sbloom 			if (n != host.h_length) {
11624687Sbloom 				cp += n;
11724687Sbloom 				continue;
11824687Sbloom 			}
11924687Sbloom 			if (class != getclass) {
12024687Sbloom 				cp += n;
12124687Sbloom 				continue;
12224687Sbloom 			}
12324687Sbloom 		} else {
12424687Sbloom 			host.h_length = n;
12524687Sbloom 			getclass = class;
12624687Sbloom 			host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC;
12724687Sbloom 			if (!iquery) {
12824687Sbloom 				host.h_name = bp;
12924687Sbloom 				bp += strlen(bp) + 1;
13024687Sbloom 			}
13118505Sralph 		}
13218505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
133*24733Sbloom #ifdef DEBUG
13418505Sralph 			if (_res.options & RES_DEBUG)
13518505Sralph 				printf("size (%d) too big\n", n);
136*24733Sbloom #endif
13724687Sbloom 			break;
13818505Sralph 		}
13924687Sbloom 		bcopy(cp, *hap++ = bp, n);
14024687Sbloom 		bp +=n;
14124687Sbloom 		cp += n;
14224687Sbloom 		haveanswer++;
14324687Sbloom 	}
14424687Sbloom 	if (haveanswer) {
14524687Sbloom 		*ap = NULL;
14624687Sbloom 		*hap = NULL;
14718505Sralph 		return (&host);
14824687Sbloom 	} else
14924687Sbloom 		return (NULL);
15015662Sralph }
15115662Sralph 
15215662Sralph struct hostent *
15318505Sralph gethostbyname(name)
15418505Sralph 	char *name;
15515662Sralph {
15618505Sralph 	int n;
15724687Sbloom 	char buf[BUFSIZ+1];
15815662Sralph 
15924687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
16024713Sbloom 		buf, sizeof(buf));
16118505Sralph 	if (n < 0) {
162*24733Sbloom #ifdef DEBUG
16318505Sralph 		if (_res.options & RES_DEBUG)
16418531Sralph 			printf("res_mkquery failed\n");
165*24733Sbloom #endif
16618505Sralph 		return (NULL);
16717761Sserge 	}
16824687Sbloom 	return(getanswer(buf, n, 0));
16915662Sralph }
17015662Sralph 
17115662Sralph struct hostent *
17218505Sralph gethostbyaddr(addr, len, type)
17315662Sralph 	char *addr;
17418505Sralph 	int len, type;
17515662Sralph {
17618505Sralph 	int n;
17724687Sbloom 	char buf[BUFSIZ+1];
17815662Sralph 
17918505Sralph 	if (type != AF_INET)
18018505Sralph 		return (NULL);
18124687Sbloom 	n = res_mkquery(IQUERY, (char *)NULL, C_IN, T_A, addr, len, NULL,
18224713Sbloom 		buf, sizeof(buf));
18318505Sralph 	if (n < 0) {
184*24733Sbloom #ifdef DEBUG
18518505Sralph 		if (_res.options & RES_DEBUG)
18618531Sralph 			printf("res_mkquery failed\n");
187*24733Sbloom #endif
18818505Sralph 		return (NULL);
18917761Sserge 	}
19024687Sbloom 	return(getanswer(buf, n, 1));
19115662Sralph }
19224509Sbloom 
19324509Sbloom 
194