xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 24713)
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*24713Sbloom static char sccsid[] = "@(#)gethostnamadr.c	5.6 (Berkeley) 09/12/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) {
4518505Sralph 		if (_res.options & RES_DEBUG)
4618531Sralph 			printf("res_send failed\n");
4718505Sralph 		return (NULL);
4815662Sralph 	}
4918505Sralph 	eom = answer + n;
5018505Sralph 	/*
5118505Sralph 	 * find first satisfactory answer
5218505Sralph 	 */
5318505Sralph 	hp = (HEADER *) answer;
5418505Sralph 	ancount = ntohs(hp->ancount);
5518505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
5618505Sralph 		if (_res.options & RES_DEBUG)
5718505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
5818505Sralph 		return (NULL);
5918505Sralph 	}
6018505Sralph 	bp = hostbuf;
6118505Sralph 	buflen = sizeof(hostbuf);
6218505Sralph 	cp = answer + sizeof(HEADER);
6318505Sralph 	if (hp->qdcount) {
6418505Sralph 		if (iquery) {
6518505Sralph 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
6618505Sralph 				return (NULL);
6718505Sralph 			cp += n + QFIXEDSZ;
6818505Sralph 			host.h_name = bp;
6918505Sralph 			n = strlen(bp) + 1;
7018505Sralph 			bp += n;
7118505Sralph 			buflen -= n;
7218505Sralph 		} else
7318505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
7418505Sralph 	} else if (iquery)
7518505Sralph 		return (NULL);
7624687Sbloom 	ap = host_aliases;
7724687Sbloom 	host.h_aliases = host_aliases;
7824687Sbloom 	hap = h_addr_ptrs;
7924687Sbloom 	host.h_addr_list = h_addr_ptrs;
8024687Sbloom 	haveanswer = 0;
8118505Sralph 	while (--ancount >= 0 && cp < eom) {
8218505Sralph 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
8324687Sbloom 			break;
8418505Sralph 		cp += n;
8518505Sralph 		type = getshort(cp);
8618505Sralph  		cp += sizeof(u_short);
8718505Sralph 		class = getshort(cp);
8818505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
8918505Sralph 		n = getshort(cp);
9018505Sralph 		cp += sizeof(u_short);
9118505Sralph 		if (type == T_CNAME) {
9218505Sralph 			cp += n;
9318505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
9418505Sralph 				continue;
9518505Sralph 			*ap++ = bp;
9618505Sralph 			n = strlen(bp) + 1;
9718505Sralph 			bp += n;
9818505Sralph 			buflen -= n;
9918505Sralph 			continue;
10018505Sralph 		}
10124687Sbloom 		if (type != T_A)  {
10218505Sralph 			if (_res.options & RES_DEBUG)
10318505Sralph 				printf("unexpected answer type %d, size %d\n",
10418505Sralph 					type, n);
10524687Sbloom 			cp += n;
10618505Sralph 			continue;
10718505Sralph 		}
10824687Sbloom 		if (haveanswer) {
10924687Sbloom 			if (n != host.h_length) {
11024687Sbloom 				cp += n;
11124687Sbloom 				continue;
11224687Sbloom 			}
11324687Sbloom 			if (class != getclass) {
11424687Sbloom 				cp += n;
11524687Sbloom 				continue;
11624687Sbloom 			}
11724687Sbloom 		} else {
11824687Sbloom 			host.h_length = n;
11924687Sbloom 			getclass = class;
12024687Sbloom 			host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC;
12124687Sbloom 			if (!iquery) {
12224687Sbloom 				host.h_name = bp;
12324687Sbloom 				bp += strlen(bp) + 1;
12424687Sbloom 			}
12518505Sralph 		}
12618505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
12718505Sralph 			if (_res.options & RES_DEBUG)
12818505Sralph 				printf("size (%d) too big\n", n);
12924687Sbloom 			break;
13018505Sralph 		}
13124687Sbloom 		bcopy(cp, *hap++ = bp, n);
13224687Sbloom 		bp +=n;
13324687Sbloom 		cp += n;
13424687Sbloom 		haveanswer++;
13524687Sbloom 	}
13624687Sbloom 	if (haveanswer) {
13724687Sbloom 		*ap = NULL;
13824687Sbloom 		*hap = NULL;
13918505Sralph 		return (&host);
14024687Sbloom 	} else
14124687Sbloom 		return (NULL);
14215662Sralph }
14315662Sralph 
14415662Sralph struct hostent *
14518505Sralph gethostbyname(name)
14618505Sralph 	char *name;
14715662Sralph {
14818505Sralph 	int n;
14924687Sbloom 	char buf[BUFSIZ+1];
15015662Sralph 
15124687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
152*24713Sbloom 		buf, sizeof(buf));
15318505Sralph 	if (n < 0) {
15418505Sralph 		if (_res.options & RES_DEBUG)
15518531Sralph 			printf("res_mkquery failed\n");
15618505Sralph 		return (NULL);
15717761Sserge 	}
15824687Sbloom 	return(getanswer(buf, n, 0));
15915662Sralph }
16015662Sralph 
16115662Sralph struct hostent *
16218505Sralph gethostbyaddr(addr, len, type)
16315662Sralph 	char *addr;
16418505Sralph 	int len, type;
16515662Sralph {
16618505Sralph 	int n;
16724687Sbloom 	char buf[BUFSIZ+1];
16815662Sralph 
16918505Sralph 	if (type != AF_INET)
17018505Sralph 		return (NULL);
17124687Sbloom 	n = res_mkquery(IQUERY, (char *)NULL, C_IN, T_A, addr, len, NULL,
172*24713Sbloom 		buf, sizeof(buf));
17318505Sralph 	if (n < 0) {
17418505Sralph 		if (_res.options & RES_DEBUG)
17518531Sralph 			printf("res_mkquery failed\n");
17618505Sralph 		return (NULL);
17717761Sserge 	}
17824687Sbloom 	return(getanswer(buf, n, 1));
17915662Sralph }
18024509Sbloom 
18124509Sbloom 
182