xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 21374)
1*21374Sdist /*
2*21374Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21374Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21374Sdist  * specifies the terms and conditions for redistribution.
5*21374Sdist  */
615662Sralph 
7*21374Sdist #ifndef lint
8*21374Sdist static char sccsid[] = "@(#)gethostnamadr.c	5.1 (Berkeley) 05/30/85";
9*21374Sdist #endif not lint
10*21374Sdist 
1118546Sralph /*
1218546Sralph  * Copyright (c) 1985 Regents of the University of California
1318546Sralph  *	All Rights Reserved
1418546Sralph  */
1518546Sralph 
1618505Sralph #include <sys/types.h>
1718505Sralph #include <sys/socket.h>
1818505Sralph #include <netinet/in.h>
1918505Sralph #include <netdb.h>
2015662Sralph #include <stdio.h>
2118505Sralph #include <nameser.h>
2218505Sralph #include <resolv.h>
2315662Sralph 
2415662Sralph #define	MAXALIASES	35
2515662Sralph 
2615662Sralph static struct hostent host;
2715662Sralph static char *host_aliases[MAXALIASES];
2815912Sralph static char hostbuf[BUFSIZ+1];
2915662Sralph 
3015662Sralph static struct hostent *
3118505Sralph getanswer(msg, msglen, iquery)
3218505Sralph 	char *msg;
3318505Sralph 	int msglen, iquery;
3415662Sralph {
3518505Sralph 	register HEADER *hp;
3618505Sralph 	register char *cp;
3718505Sralph 	register int n;
3818505Sralph 	char answer[PACKETSZ];
3918505Sralph 	char *eom, *bp, **ap;
4018505Sralph 	int type, class, ancount, buflen;
4115662Sralph 
4218531Sralph 	n = res_send(msg, msglen, answer, sizeof(answer));
4318505Sralph 	if (n < 0) {
4418505Sralph 		if (_res.options & RES_DEBUG)
4518531Sralph 			printf("res_send failed\n");
4618505Sralph 		return (NULL);
4715662Sralph 	}
4818505Sralph 	eom = answer + n;
4918505Sralph 	/*
5018505Sralph 	 * find first satisfactory answer
5118505Sralph 	 */
5218505Sralph 	hp = (HEADER *) answer;
5318505Sralph 	ancount = ntohs(hp->ancount);
5418505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
5518505Sralph 		if (_res.options & RES_DEBUG)
5618505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
5718505Sralph 		return (NULL);
5818505Sralph 	}
5918505Sralph 	bp = hostbuf;
6018505Sralph 	buflen = sizeof(hostbuf);
6118505Sralph 	ap = host_aliases;
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);
7618505Sralph 	while (--ancount >= 0 && cp < eom) {
7718505Sralph 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
7818505Sralph 			return (NULL);
7918505Sralph 		cp += n;
8018505Sralph 		type = getshort(cp);
8118505Sralph  		cp += sizeof(u_short);
8218505Sralph 		class = getshort(cp);
8318505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
8418505Sralph 		n = getshort(cp);
8518505Sralph 		cp += sizeof(u_short);
8618505Sralph 		if (type == T_CNAME) {
8718505Sralph 			cp += n;
8818505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
8918505Sralph 				continue;
9018505Sralph 			*ap++ = bp;
9118505Sralph 			n = strlen(bp) + 1;
9218505Sralph 			bp += n;
9318505Sralph 			buflen -= n;
9418505Sralph 			continue;
9518505Sralph 		}
9618505Sralph 		if (type != T_A || n != 4) {
9718505Sralph 			if (_res.options & RES_DEBUG)
9818505Sralph 				printf("unexpected answer type %d, size %d\n",
9918505Sralph 					type, n);
10018505Sralph 			continue;
10118505Sralph 		}
10218505Sralph 		if (!iquery) {
10318505Sralph 			host.h_name = bp;
10418505Sralph 			bp += strlen(bp) + 1;
10518505Sralph 		}
10618505Sralph 		*ap = NULL;
10718505Sralph 		host.h_aliases = host_aliases;
10818505Sralph 		host.h_addrtype = class == C_IN ? AF_INET : AF_UNSPEC;
10918505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
11018505Sralph 			if (_res.options & RES_DEBUG)
11118505Sralph 				printf("size (%d) too big\n", n);
11218505Sralph 			return (NULL);
11318505Sralph 		}
11418505Sralph 		bcopy(cp, host.h_addr = bp, host.h_length = n);
11518505Sralph 		return (&host);
11618505Sralph 	}
11718505Sralph 	return (NULL);
11815662Sralph }
11915662Sralph 
12015662Sralph struct hostent *
12118505Sralph gethostbyname(name)
12218505Sralph 	char *name;
12315662Sralph {
12418505Sralph 	int n;
12515662Sralph 
12618531Sralph 	n = res_mkquery(QUERY, name, C_ANY, T_A, NULL, 0, NULL,
12718531Sralph 		hostbuf, sizeof(hostbuf));
12818505Sralph 	if (n < 0) {
12918505Sralph 		if (_res.options & RES_DEBUG)
13018531Sralph 			printf("res_mkquery failed\n");
13118505Sralph 		return (NULL);
13217761Sserge 	}
13318505Sralph 	return (getanswer(hostbuf, n, 0));
13415662Sralph }
13515662Sralph 
13615662Sralph struct hostent *
13718505Sralph gethostbyaddr(addr, len, type)
13815662Sralph 	char *addr;
13918505Sralph 	int len, type;
14015662Sralph {
14118505Sralph 	int n;
14215662Sralph 
14318505Sralph 	if (type != AF_INET)
14418505Sralph 		return (NULL);
14518531Sralph 	n = res_mkquery(IQUERY, NULL, C_IN, T_A, addr, len, NULL,
14618531Sralph 		hostbuf, sizeof(hostbuf));
14718505Sralph 	if (n < 0) {
14818505Sralph 		if (_res.options & RES_DEBUG)
14918531Sralph 			printf("res_mkquery failed\n");
15018505Sralph 		return (NULL);
15117761Sserge 	}
15218505Sralph 	return (getanswer(hostbuf, n, 1));
15315662Sralph }
154