gethostnamadr.c revision 21673
1/*-
2 * Copyright (c) 1994, Garrett Wollman
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#if defined(LIBC_SCCS) && !defined(lint)
27static char sccsid[] = "@(#)$FreeBSD: head/lib/libc/net/gethostnamadr.c 21673 1997-01-14 07:20:47Z jkh $";
28static char rcsid[] = "$FreeBSD: head/lib/libc/net/gethostnamadr.c 21673 1997-01-14 07:20:47Z jkh $";
29#endif /* LIBC_SCCS and not lint */
30
31#include <sys/param.h>
32#include <sys/socket.h>
33#include <netinet/in.h>
34#include <arpa/inet.h>
35#include <netdb.h>
36#include <stdio.h>
37#include <ctype.h>
38#include <errno.h>
39#include <string.h>
40#include <arpa/nameser.h>		/* XXX hack for _res */
41#include <resolv.h>			/* XXX hack for _res */
42
43#define _PATH_HOSTCONF	"/etc/host.conf"
44
45enum service_type {
46  SERVICE_NONE = 0,
47  SERVICE_BIND,
48  SERVICE_HOSTS,
49  SERVICE_NIS };
50#define SERVICE_MAX	SERVICE_NIS
51
52static struct {
53  const char *name;
54  enum service_type type;
55} service_names[] = {
56  { "hosts", SERVICE_HOSTS },
57  { "/etc/hosts", SERVICE_HOSTS },
58  { "hosttable", SERVICE_HOSTS },
59  { "htable", SERVICE_HOSTS },
60  { "bind", SERVICE_BIND },
61  { "dns", SERVICE_BIND },
62  { "domain", SERVICE_BIND },
63  { "yp", SERVICE_NIS },
64  { "yellowpages", SERVICE_NIS },
65  { "nis", SERVICE_NIS },
66  { 0, SERVICE_NONE }
67};
68
69static enum service_type service_order[SERVICE_MAX + 1];
70static int service_done = 0;
71
72static enum service_type
73get_service_name(const char *name) {
74	int i;
75	for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
76		if(!strcasecmp(name, service_names[i].name)) {
77			return service_names[i].type;
78		}
79	}
80	return SERVICE_NONE;
81}
82
83static void
84init_services()
85{
86	char *cp, *p, buf[BUFSIZ];
87	register int cc = 0;
88	FILE *fd;
89
90	if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
91				/* make some assumptions */
92		service_order[0] = SERVICE_BIND;
93		service_order[1] = SERVICE_HOSTS;
94		service_order[2] = SERVICE_NONE;
95	} else {
96		while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
97			if(buf[0] == '#')
98				continue;
99
100			p = buf;
101			while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
102				;
103			if (cp == NULL)
104				continue;
105			do {
106				if (isalpha(cp[0])) {
107					service_order[cc] = get_service_name(cp);
108					if(service_order[cc] != SERVICE_NONE)
109						cc++;
110				}
111				while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
112					;
113			} while(cp != NULL && cc < SERVICE_MAX);
114		}
115		service_order[cc] = SERVICE_NONE;
116		fclose(fd);
117	}
118	service_done = 1;
119}
120
121struct hostent *
122gethostbyname(const char *name)
123{
124	struct hostent *hp;
125
126	if (_res.options & RES_USE_INET6) {		/* XXX */
127		hp = gethostbyname2(name, AF_INET6);	/* XXX */
128		if (hp)					/* XXX */
129			return (hp);			/* XXX */
130	}						/* XXX */
131	return (gethostbyname2(name, AF_INET));
132}
133
134struct hostent *
135gethostbyname2(const char *name, int type)
136{
137	struct hostent *hp = 0;
138	int nserv = 0;
139
140	if (!service_done)
141		init_services();
142
143	while (!hp) {
144		switch (service_order[nserv]) {
145		      case SERVICE_NONE:
146			return NULL;
147		      case SERVICE_HOSTS:
148			hp = _gethostbyhtname(name, type);
149			break;
150		      case SERVICE_BIND:
151			hp = _gethostbydnsname(name, type);
152			break;
153		      case SERVICE_NIS:
154			hp = _gethostbynisname(name, type);
155			break;
156		}
157		nserv++;
158	}
159	return hp;
160}
161
162struct hostent *
163gethostbyaddr(const char *addr, int len, int type)
164{
165	struct hostent *hp = 0;
166	int nserv = 0;
167
168	if (!service_done)
169		init_services();
170
171	while (!hp) {
172		switch (service_order[nserv]) {
173		      case SERVICE_NONE:
174			return 0;
175		      case SERVICE_HOSTS:
176			hp = _gethostbyhtaddr(addr, len, type);
177			break;
178		      case SERVICE_BIND:
179			hp = _gethostbydnsaddr(addr, len, type);
180			break;
181		      case SERVICE_NIS:
182			hp = _gethostbynisaddr(addr, len, type);
183			break;
184		}
185		nserv++;
186	}
187	return hp;
188}
189
190#ifdef _THREAD_SAFE
191struct hostent_data;
192
193/*
194 * Temporary function (not thread safe)
195 */
196int gethostbyaddr_r(const char *addr, int len, int type,
197	struct hostent *result, struct hostent_data *buffer)
198{
199	struct hostent *hp = 0;
200	int ret;
201	if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
202		ret = -1;
203	} else {
204		memcpy(result, hp, sizeof(struct hostent));
205		ret = 0;
206	}
207	return(ret);
208}
209#endif
210
211void
212sethostent(stayopen)
213	int stayopen;
214{
215	_sethosthtent(stayopen);
216	_sethostdnsent(stayopen);
217}
218
219void
220endhostent()
221{
222	_endhosthtent();
223	_endhostdnsent();
224}
225