xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 25282)
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*25282Sbloom static char sccsid[] = "@(#)gethostnamadr.c	5.9 (Berkeley) 10/24/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];
2725153Sbloom static struct in_addr host_addr;
2815662Sralph 
2924509Sbloom 
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;
4025153Sbloom 	int type, class, ancount, qdcount, buflen;
4124687Sbloom 	int haveanswer, getclass;
4224687Sbloom 	char **hap;
4315662Sralph 
4418531Sralph 	n = res_send(msg, msglen, answer, sizeof(answer));
4518505Sralph 	if (n < 0) {
4624733Sbloom #ifdef DEBUG
4718505Sralph 		if (_res.options & RES_DEBUG)
4818531Sralph 			printf("res_send failed\n");
4924733Sbloom #endif
5018505Sralph 		return (NULL);
5115662Sralph 	}
5218505Sralph 	eom = answer + n;
5318505Sralph 	/*
5418505Sralph 	 * find first satisfactory answer
5518505Sralph 	 */
5618505Sralph 	hp = (HEADER *) answer;
5718505Sralph 	ancount = ntohs(hp->ancount);
5825153Sbloom 	qdcount = ntohs(hp->qdcount);
5918505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
6024733Sbloom #ifdef DEBUG
6118505Sralph 		if (_res.options & RES_DEBUG)
6218505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
6324733Sbloom #endif
6418505Sralph 		return (NULL);
6518505Sralph 	}
6618505Sralph 	bp = hostbuf;
6718505Sralph 	buflen = sizeof(hostbuf);
6818505Sralph 	cp = answer + sizeof(HEADER);
6925153Sbloom 	if (qdcount) {
7018505Sralph 		if (iquery) {
7118505Sralph 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
7218505Sralph 				return (NULL);
7318505Sralph 			cp += n + QFIXEDSZ;
7418505Sralph 			host.h_name = bp;
7518505Sralph 			n = strlen(bp) + 1;
7618505Sralph 			bp += n;
7718505Sralph 			buflen -= n;
7818505Sralph 		} else
7918505Sralph 			cp += dn_skip(cp) + QFIXEDSZ;
8025153Sbloom 		while (--qdcount > 0)
8125153Sbloom 			cp += dn_skip(cp) + QFIXEDSZ;
8218505Sralph 	} else if (iquery)
8318505Sralph 		return (NULL);
8424687Sbloom 	ap = host_aliases;
8524687Sbloom 	host.h_aliases = host_aliases;
8624687Sbloom 	hap = h_addr_ptrs;
8724687Sbloom 	host.h_addr_list = h_addr_ptrs;
8824687Sbloom 	haveanswer = 0;
8918505Sralph 	while (--ancount >= 0 && cp < eom) {
9018505Sralph 		if ((n = dn_expand(answer, cp, bp, buflen)) < 0)
9124687Sbloom 			break;
9218505Sralph 		cp += n;
9318505Sralph 		type = getshort(cp);
9418505Sralph  		cp += sizeof(u_short);
9518505Sralph 		class = getshort(cp);
9618505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
9718505Sralph 		n = getshort(cp);
9818505Sralph 		cp += sizeof(u_short);
9918505Sralph 		if (type == T_CNAME) {
10018505Sralph 			cp += n;
10118505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
10218505Sralph 				continue;
10318505Sralph 			*ap++ = bp;
10418505Sralph 			n = strlen(bp) + 1;
10518505Sralph 			bp += n;
10618505Sralph 			buflen -= n;
10718505Sralph 			continue;
10818505Sralph 		}
10925153Sbloom 		if (type == T_PTR) {
11025153Sbloom 			if ((n = dn_expand(answer, cp, bp, buflen)) < 0) {
11125153Sbloom 				cp += n;
11225153Sbloom 				continue;
11325153Sbloom 			}
11425153Sbloom 			cp += n;
11525153Sbloom 			host.h_name = bp;
11625153Sbloom 			return(&host);
11725153Sbloom 		}
11824687Sbloom 		if (type != T_A)  {
11924733Sbloom #ifdef DEBUG
12018505Sralph 			if (_res.options & RES_DEBUG)
12118505Sralph 				printf("unexpected answer type %d, size %d\n",
12218505Sralph 					type, n);
12324733Sbloom #endif
12424687Sbloom 			cp += n;
12518505Sralph 			continue;
12618505Sralph 		}
12724687Sbloom 		if (haveanswer) {
12824687Sbloom 			if (n != host.h_length) {
12924687Sbloom 				cp += n;
13024687Sbloom 				continue;
13124687Sbloom 			}
13224687Sbloom 			if (class != getclass) {
13324687Sbloom 				cp += n;
13424687Sbloom 				continue;
13524687Sbloom 			}
13624687Sbloom 		} else {
13724687Sbloom 			host.h_length = n;
13824687Sbloom 			getclass = class;
13924687Sbloom 			host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC;
14024687Sbloom 			if (!iquery) {
14124687Sbloom 				host.h_name = bp;
14224687Sbloom 				bp += strlen(bp) + 1;
14324687Sbloom 			}
14418505Sralph 		}
14518505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
14624733Sbloom #ifdef DEBUG
14718505Sralph 			if (_res.options & RES_DEBUG)
14818505Sralph 				printf("size (%d) too big\n", n);
14924733Sbloom #endif
15024687Sbloom 			break;
15118505Sralph 		}
15224687Sbloom 		bcopy(cp, *hap++ = bp, n);
15324687Sbloom 		bp +=n;
15424687Sbloom 		cp += n;
15524687Sbloom 		haveanswer++;
15624687Sbloom 	}
15724687Sbloom 	if (haveanswer) {
15824687Sbloom 		*ap = NULL;
15924687Sbloom 		*hap = NULL;
16018505Sralph 		return (&host);
16124687Sbloom 	} else
16224687Sbloom 		return (NULL);
16315662Sralph }
16415662Sralph 
16515662Sralph struct hostent *
16618505Sralph gethostbyname(name)
16718505Sralph 	char *name;
16815662Sralph {
16918505Sralph 	int n;
17024687Sbloom 	char buf[BUFSIZ+1];
17115662Sralph 
17224687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
17324713Sbloom 		buf, sizeof(buf));
17418505Sralph 	if (n < 0) {
17524733Sbloom #ifdef DEBUG
17618505Sralph 		if (_res.options & RES_DEBUG)
17718531Sralph 			printf("res_mkquery failed\n");
17824733Sbloom #endif
17918505Sralph 		return (NULL);
18017761Sserge 	}
18124687Sbloom 	return(getanswer(buf, n, 0));
18215662Sralph }
18315662Sralph 
18415662Sralph struct hostent *
18518505Sralph gethostbyaddr(addr, len, type)
18615662Sralph 	char *addr;
18718505Sralph 	int len, type;
18815662Sralph {
18918505Sralph 	int n;
19024687Sbloom 	char buf[BUFSIZ+1];
19125153Sbloom 	register struct hostent *hp;
19225153Sbloom 	char qbuf[MAXDNAME];
19315662Sralph 
19418505Sralph 	if (type != AF_INET)
19518505Sralph 		return (NULL);
19625153Sbloom 	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
19725153Sbloom 		(*(unsigned *)addr >> 24 & 0xff),
19825153Sbloom 		(*(unsigned *)addr >> 16 & 0xff),
19925153Sbloom 		(*(unsigned *)addr >> 8 & 0xff),
20025153Sbloom 		(*(unsigned *)addr & 0xff));
20125153Sbloom 	n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
20224713Sbloom 		buf, sizeof(buf));
20318505Sralph 	if (n < 0) {
20424733Sbloom #ifdef DEBUG
20518505Sralph 		if (_res.options & RES_DEBUG)
20618531Sralph 			printf("res_mkquery failed\n");
20724733Sbloom #endif
20818505Sralph 		return (NULL);
20917761Sserge 	}
21025153Sbloom 	if ((hp = getanswer(buf, n, 1)) == NULL)
21125153Sbloom 		return(NULL);
21225153Sbloom 	hp->h_addrtype = type;
21325153Sbloom 	hp->h_length = len;
214*25282Sbloom 	h_addr_ptrs[0] = (char *)&host_addr;
21525153Sbloom 	h_addr_ptrs[1] = (char *)0;
21625153Sbloom 	host_addr = *(struct in_addr *)addr;
21725153Sbloom 	return(hp);
21815662Sralph }
219