xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 25386)
121374Sdist /*
225302Skjd  * Copyright (c) 1985 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*25386Skjd static char sccsid[] = "@(#)gethostnamadr.c	6.2 (Berkeley) 11/04/85";
921374Sdist #endif not lint
1021374Sdist 
1118505Sralph #include <sys/types.h>
12*25386Skjd #include <sys/param.h>
1318505Sralph #include <sys/socket.h>
1418505Sralph #include <netinet/in.h>
1518505Sralph #include <netdb.h>
1615662Sralph #include <stdio.h>
1724508Sbloom #include <arpa/nameser.h>
1824508Sbloom #include <arpa/resolv.h>
1915662Sralph 
2015662Sralph #define	MAXALIASES	35
2124687Sbloom #define MAXADDRS	35
2215662Sralph 
2324687Sbloom static char *h_addr_ptrs[MAXADDRS + 1];
2424687Sbloom 
2524687Sbloom static struct hostent host;
2615662Sralph static char *host_aliases[MAXALIASES];
2715912Sralph static char hostbuf[BUFSIZ+1];
2825153Sbloom static struct in_addr host_addr;
2915662Sralph 
3025302Skjd typedef union {
3125302Skjd     HEADER qb1;
3225302Skjd     char qb2[PACKETSZ];
3325302Skjd } querybuf;
3424509Sbloom 
3525302Skjd static union {
3625302Skjd     long al;
3725302Skjd     char ac;
3825302Skjd } align;
3925302Skjd 
4025302Skjd 
4115662Sralph static struct hostent *
4218505Sralph getanswer(msg, msglen, iquery)
4318505Sralph 	char *msg;
4418505Sralph 	int msglen, iquery;
4515662Sralph {
4618505Sralph 	register HEADER *hp;
4718505Sralph 	register char *cp;
4818505Sralph 	register int n;
4925302Skjd 	querybuf answer;
5018505Sralph 	char *eom, *bp, **ap;
5125153Sbloom 	int type, class, ancount, qdcount, buflen;
5224687Sbloom 	int haveanswer, getclass;
5324687Sbloom 	char **hap;
5415662Sralph 
5525302Skjd 	n = res_send(msg, msglen, (char *)&answer, sizeof(answer));
5618505Sralph 	if (n < 0) {
5724733Sbloom #ifdef DEBUG
5818505Sralph 		if (_res.options & RES_DEBUG)
5918531Sralph 			printf("res_send failed\n");
6024733Sbloom #endif
6118505Sralph 		return (NULL);
6215662Sralph 	}
6325302Skjd 	eom = (char *)&answer + n;
6418505Sralph 	/*
6518505Sralph 	 * find first satisfactory answer
6618505Sralph 	 */
6725302Skjd 	hp = (HEADER *) &answer;
6818505Sralph 	ancount = ntohs(hp->ancount);
6925153Sbloom 	qdcount = ntohs(hp->qdcount);
7018505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
7124733Sbloom #ifdef DEBUG
7218505Sralph 		if (_res.options & RES_DEBUG)
7318505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
7424733Sbloom #endif
7518505Sralph 		return (NULL);
7618505Sralph 	}
7718505Sralph 	bp = hostbuf;
7818505Sralph 	buflen = sizeof(hostbuf);
7925302Skjd 	cp = (char *)&answer + sizeof(HEADER);
8025153Sbloom 	if (qdcount) {
8118505Sralph 		if (iquery) {
82*25386Skjd 			if ((n = dn_expand((char *)&answer, cp, bp, buflen)) <0)
8318505Sralph 				return (NULL);
8418505Sralph 			cp += n + QFIXEDSZ;
8518505Sralph 			host.h_name = bp;
8618505Sralph 			n = strlen(bp) + 1;
8718505Sralph 			bp += n;
8818505Sralph 			buflen -= n;
8918505Sralph 		} else
9018505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
9125153Sbloom 		while (--qdcount > 0)
9225153Sbloom 			cp += dn_skip(cp) + QFIXEDSZ;
9318505Sralph 	} else if (iquery)
9418505Sralph 		return (NULL);
9524687Sbloom 	ap = host_aliases;
9624687Sbloom 	host.h_aliases = host_aliases;
9724687Sbloom 	hap = h_addr_ptrs;
98*25386Skjd #ifdef BSD4_3
9924687Sbloom 	host.h_addr_list = h_addr_ptrs;
100*25386Skjd #endif
10124687Sbloom 	haveanswer = 0;
10218505Sralph 	while (--ancount >= 0 && cp < eom) {
10325302Skjd 		if ((n = dn_expand((char *)&answer, cp, bp, buflen)) < 0)
10424687Sbloom 			break;
10518505Sralph 		cp += n;
10618505Sralph 		type = getshort(cp);
10718505Sralph  		cp += sizeof(u_short);
10818505Sralph 		class = getshort(cp);
10918505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
11018505Sralph 		n = getshort(cp);
11118505Sralph 		cp += sizeof(u_short);
11218505Sralph 		if (type == T_CNAME) {
11318505Sralph 			cp += n;
11418505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
11518505Sralph 				continue;
11618505Sralph 			*ap++ = bp;
11718505Sralph 			n = strlen(bp) + 1;
11818505Sralph 			bp += n;
11918505Sralph 			buflen -= n;
12018505Sralph 			continue;
12118505Sralph 		}
12225153Sbloom 		if (type == T_PTR) {
12325302Skjd 			if ((n = dn_expand((char *)&answer, cp, bp, buflen)) <
12425302Skjd 0) {
12525153Sbloom 				cp += n;
12625153Sbloom 				continue;
12725153Sbloom 			}
12825153Sbloom 			cp += n;
12925153Sbloom 			host.h_name = bp;
130*25386Skjd #ifdef BSD4_3
13125153Sbloom 			return(&host);
132*25386Skjd #else
133*25386Skjd 			haveanswer++;
134*25386Skjd 			break;
135*25386Skjd #endif
13625153Sbloom 		}
13724687Sbloom 		if (type != T_A)  {
13824733Sbloom #ifdef DEBUG
13918505Sralph 			if (_res.options & RES_DEBUG)
14018505Sralph 				printf("unexpected answer type %d, size %d\n",
14118505Sralph 					type, n);
14224733Sbloom #endif
14324687Sbloom 			cp += n;
14418505Sralph 			continue;
14518505Sralph 		}
14624687Sbloom 		if (haveanswer) {
14724687Sbloom 			if (n != host.h_length) {
14824687Sbloom 				cp += n;
14924687Sbloom 				continue;
15024687Sbloom 			}
15124687Sbloom 			if (class != getclass) {
15224687Sbloom 				cp += n;
15324687Sbloom 				continue;
15424687Sbloom 			}
15524687Sbloom 		} else {
15624687Sbloom 			host.h_length = n;
15724687Sbloom 			getclass = class;
158*25386Skjd 			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
15924687Sbloom 			if (!iquery) {
16024687Sbloom 				host.h_name = bp;
16124687Sbloom 				bp += strlen(bp) + 1;
16224687Sbloom 			}
16318505Sralph 		}
16425302Skjd 
16525302Skjd 		bp += ((u_long)bp % sizeof(align));
16625302Skjd 
16718505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
16824733Sbloom #ifdef DEBUG
16918505Sralph 			if (_res.options & RES_DEBUG)
17018505Sralph 				printf("size (%d) too big\n", n);
17124733Sbloom #endif
17224687Sbloom 			break;
17318505Sralph 		}
17424687Sbloom 		bcopy(cp, *hap++ = bp, n);
17524687Sbloom 		bp +=n;
17624687Sbloom 		cp += n;
17724687Sbloom 		haveanswer++;
17824687Sbloom 	}
17924687Sbloom 	if (haveanswer) {
18024687Sbloom 		*ap = NULL;
18124687Sbloom 		*hap = NULL;
182*25386Skjd #ifndef BSD4_3
183*25386Skjd 		host.h_addr = h_addr_ptrs[0];
184*25386Skjd #endif
18518505Sralph 		return (&host);
18624687Sbloom 	} else
18724687Sbloom 		return (NULL);
18815662Sralph }
18915662Sralph 
19015662Sralph struct hostent *
19118505Sralph gethostbyname(name)
19218505Sralph 	char *name;
19315662Sralph {
19418505Sralph 	int n;
19525302Skjd 	querybuf buf;
19615662Sralph 
19724687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
19825302Skjd 		(char *)&buf, sizeof(buf));
19918505Sralph 	if (n < 0) {
20024733Sbloom #ifdef DEBUG
20118505Sralph 		if (_res.options & RES_DEBUG)
20218531Sralph 			printf("res_mkquery failed\n");
20324733Sbloom #endif
20418505Sralph 		return (NULL);
20517761Sserge 	}
20625302Skjd 	return(getanswer((char *)&buf, n, 0));
20715662Sralph }
20815662Sralph 
20915662Sralph struct hostent *
21018505Sralph gethostbyaddr(addr, len, type)
21115662Sralph 	char *addr;
21218505Sralph 	int len, type;
21315662Sralph {
21418505Sralph 	int n;
21525302Skjd 	querybuf buf;
21625153Sbloom 	register struct hostent *hp;
21725153Sbloom 	char qbuf[MAXDNAME];
21815662Sralph 
21918505Sralph 	if (type != AF_INET)
22018505Sralph 		return (NULL);
22125153Sbloom 	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
22225153Sbloom 		(*(unsigned *)addr >> 24 & 0xff),
22325153Sbloom 		(*(unsigned *)addr >> 16 & 0xff),
22425153Sbloom 		(*(unsigned *)addr >> 8 & 0xff),
22525153Sbloom 		(*(unsigned *)addr & 0xff));
22625153Sbloom 	n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
22725302Skjd 		(char *)&buf, sizeof(buf));
22818505Sralph 	if (n < 0) {
22924733Sbloom #ifdef DEBUG
23018505Sralph 		if (_res.options & RES_DEBUG)
23118531Sralph 			printf("res_mkquery failed\n");
23224733Sbloom #endif
23318505Sralph 		return (NULL);
23417761Sserge 	}
23525302Skjd 	if ((hp = getanswer((char *)&buf, n, 1)) == NULL)
23625153Sbloom 		return(NULL);
23725153Sbloom 	hp->h_addrtype = type;
23825153Sbloom 	hp->h_length = len;
23925282Sbloom 	h_addr_ptrs[0] = (char *)&host_addr;
24025153Sbloom 	h_addr_ptrs[1] = (char *)0;
24125153Sbloom 	host_addr = *(struct in_addr *)addr;
24225153Sbloom 	return(hp);
24315662Sralph }
24425302Skjd 
245