xref: /csrg-svn/lib/libc/net/gethostnamadr.c (revision 25302)
121374Sdist /*
2*25302Skjd  * 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*25302Skjd static char sccsid[] = "@(#)gethostnamadr.c	5.10 (Berkeley) 10/25/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 
29*25302Skjd typedef union {
30*25302Skjd     HEADER qb1;
31*25302Skjd     char qb2[PACKETSZ];
32*25302Skjd } querybuf;
3324509Sbloom 
34*25302Skjd static union {
35*25302Skjd     long al;
36*25302Skjd     char ac;
37*25302Skjd } align;
38*25302Skjd 
39*25302Skjd 
4015662Sralph static struct hostent *
4118505Sralph getanswer(msg, msglen, iquery)
4218505Sralph 	char *msg;
4318505Sralph 	int msglen, iquery;
4415662Sralph {
4518505Sralph 	register HEADER *hp;
4618505Sralph 	register char *cp;
4718505Sralph 	register int n;
48*25302Skjd 	querybuf answer;
4918505Sralph 	char *eom, *bp, **ap;
5025153Sbloom 	int type, class, ancount, qdcount, buflen;
5124687Sbloom 	int haveanswer, getclass;
5224687Sbloom 	char **hap;
5315662Sralph 
54*25302Skjd 	n = res_send(msg, msglen, (char *)&answer, sizeof(answer));
5518505Sralph 	if (n < 0) {
5624733Sbloom #ifdef DEBUG
5718505Sralph 		if (_res.options & RES_DEBUG)
5818531Sralph 			printf("res_send failed\n");
5924733Sbloom #endif
6018505Sralph 		return (NULL);
6115662Sralph 	}
62*25302Skjd 	eom = (char *)&answer + n;
6318505Sralph 	/*
6418505Sralph 	 * find first satisfactory answer
6518505Sralph 	 */
66*25302Skjd 	hp = (HEADER *) &answer;
6718505Sralph 	ancount = ntohs(hp->ancount);
6825153Sbloom 	qdcount = ntohs(hp->qdcount);
6918505Sralph 	if (hp->rcode != NOERROR || ancount == 0) {
7024733Sbloom #ifdef DEBUG
7118505Sralph 		if (_res.options & RES_DEBUG)
7218505Sralph 			printf("rcode = %d, ancount=%d\n", hp->rcode, ancount);
7324733Sbloom #endif
7418505Sralph 		return (NULL);
7518505Sralph 	}
7618505Sralph 	bp = hostbuf;
7718505Sralph 	buflen = sizeof(hostbuf);
78*25302Skjd 	cp = (char *)&answer + sizeof(HEADER);
7925153Sbloom 	if (qdcount) {
8018505Sralph 		if (iquery) {
81*25302Skjd 			if ((n = dn_expand((char *)&answer, cp, bp, buflen)) <
82*25302Skjd 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;
9824687Sbloom 	host.h_addr_list = h_addr_ptrs;
9924687Sbloom 	haveanswer = 0;
10018505Sralph 	while (--ancount >= 0 && cp < eom) {
101*25302Skjd 		if ((n = dn_expand((char *)&answer, cp, bp, buflen)) < 0)
10224687Sbloom 			break;
10318505Sralph 		cp += n;
10418505Sralph 		type = getshort(cp);
10518505Sralph  		cp += sizeof(u_short);
10618505Sralph 		class = getshort(cp);
10718505Sralph  		cp += sizeof(u_short) + sizeof(u_long);
10818505Sralph 		n = getshort(cp);
10918505Sralph 		cp += sizeof(u_short);
11018505Sralph 		if (type == T_CNAME) {
11118505Sralph 			cp += n;
11218505Sralph 			if (ap >= &host_aliases[MAXALIASES-1])
11318505Sralph 				continue;
11418505Sralph 			*ap++ = bp;
11518505Sralph 			n = strlen(bp) + 1;
11618505Sralph 			bp += n;
11718505Sralph 			buflen -= n;
11818505Sralph 			continue;
11918505Sralph 		}
12025153Sbloom 		if (type == T_PTR) {
121*25302Skjd 			if ((n = dn_expand((char *)&answer, cp, bp, buflen)) <
122*25302Skjd 0) {
12325153Sbloom 				cp += n;
12425153Sbloom 				continue;
12525153Sbloom 			}
12625153Sbloom 			cp += n;
12725153Sbloom 			host.h_name = bp;
12825153Sbloom 			return(&host);
12925153Sbloom 		}
13024687Sbloom 		if (type != T_A)  {
13124733Sbloom #ifdef DEBUG
13218505Sralph 			if (_res.options & RES_DEBUG)
13318505Sralph 				printf("unexpected answer type %d, size %d\n",
13418505Sralph 					type, n);
13524733Sbloom #endif
13624687Sbloom 			cp += n;
13718505Sralph 			continue;
13818505Sralph 		}
13924687Sbloom 		if (haveanswer) {
14024687Sbloom 			if (n != host.h_length) {
14124687Sbloom 				cp += n;
14224687Sbloom 				continue;
14324687Sbloom 			}
14424687Sbloom 			if (class != getclass) {
14524687Sbloom 				cp += n;
14624687Sbloom 				continue;
14724687Sbloom 			}
14824687Sbloom 		} else {
14924687Sbloom 			host.h_length = n;
15024687Sbloom 			getclass = class;
15124687Sbloom 			host.h_addrtype = C_IN ? AF_INET : AF_UNSPEC;
15224687Sbloom 			if (!iquery) {
15324687Sbloom 				host.h_name = bp;
15424687Sbloom 				bp += strlen(bp) + 1;
15524687Sbloom 			}
15618505Sralph 		}
157*25302Skjd 
158*25302Skjd 		bp += ((u_long)bp % sizeof(align));
159*25302Skjd 
16018505Sralph 		if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
16124733Sbloom #ifdef DEBUG
16218505Sralph 			if (_res.options & RES_DEBUG)
16318505Sralph 				printf("size (%d) too big\n", n);
16424733Sbloom #endif
16524687Sbloom 			break;
16618505Sralph 		}
16724687Sbloom 		bcopy(cp, *hap++ = bp, n);
16824687Sbloom 		bp +=n;
16924687Sbloom 		cp += n;
17024687Sbloom 		haveanswer++;
17124687Sbloom 	}
17224687Sbloom 	if (haveanswer) {
17324687Sbloom 		*ap = NULL;
17424687Sbloom 		*hap = NULL;
17518505Sralph 		return (&host);
17624687Sbloom 	} else
17724687Sbloom 		return (NULL);
17815662Sralph }
17915662Sralph 
18015662Sralph struct hostent *
18118505Sralph gethostbyname(name)
18218505Sralph 	char *name;
18315662Sralph {
18418505Sralph 	int n;
185*25302Skjd 	querybuf buf;
18615662Sralph 
18724687Sbloom 	n = res_mkquery(QUERY, name, C_ANY, T_A, (char *)NULL, 0, NULL,
188*25302Skjd 		(char *)&buf, sizeof(buf));
18918505Sralph 	if (n < 0) {
19024733Sbloom #ifdef DEBUG
19118505Sralph 		if (_res.options & RES_DEBUG)
19218531Sralph 			printf("res_mkquery failed\n");
19324733Sbloom #endif
19418505Sralph 		return (NULL);
19517761Sserge 	}
196*25302Skjd 	return(getanswer((char *)&buf, n, 0));
19715662Sralph }
19815662Sralph 
19915662Sralph struct hostent *
20018505Sralph gethostbyaddr(addr, len, type)
20115662Sralph 	char *addr;
20218505Sralph 	int len, type;
20315662Sralph {
20418505Sralph 	int n;
205*25302Skjd 	querybuf buf;
20625153Sbloom 	register struct hostent *hp;
20725153Sbloom 	char qbuf[MAXDNAME];
20815662Sralph 
20918505Sralph 	if (type != AF_INET)
21018505Sralph 		return (NULL);
21125153Sbloom 	(void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
21225153Sbloom 		(*(unsigned *)addr >> 24 & 0xff),
21325153Sbloom 		(*(unsigned *)addr >> 16 & 0xff),
21425153Sbloom 		(*(unsigned *)addr >> 8 & 0xff),
21525153Sbloom 		(*(unsigned *)addr & 0xff));
21625153Sbloom 	n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL,
217*25302Skjd 		(char *)&buf, sizeof(buf));
21818505Sralph 	if (n < 0) {
21924733Sbloom #ifdef DEBUG
22018505Sralph 		if (_res.options & RES_DEBUG)
22118531Sralph 			printf("res_mkquery failed\n");
22224733Sbloom #endif
22318505Sralph 		return (NULL);
22417761Sserge 	}
225*25302Skjd 	if ((hp = getanswer((char *)&buf, n, 1)) == NULL)
22625153Sbloom 		return(NULL);
22725153Sbloom 	hp->h_addrtype = type;
22825153Sbloom 	hp->h_length = len;
22925282Sbloom 	h_addr_ptrs[0] = (char *)&host_addr;
23025153Sbloom 	h_addr_ptrs[1] = (char *)0;
23125153Sbloom 	host_addr = *(struct in_addr *)addr;
23225153Sbloom 	return(hp);
23315662Sralph }
234*25302Skjd 
235