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)
27 static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
28 static char rcsid[] = "$Id: gethostnamadr.c,v 1.1.1.1 2003/11/19 01:51:27 kyu3 Exp $";
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 <paths.h>
40 #include <string.h>
41 #include <arpa/nameser.h>		/* XXX hack for _res */
42 #include <resolv.h>			/* XXX hack for _res */
43 
44 #include "Socklib_internals.h"
45 
46 
47 enum service_type {
48   SERVICE_NONE = 0,
49   SERVICE_BIND,
50   SERVICE_HOSTS,
51   SERVICE_NIS };
52 #define SERVICE_MAX	SERVICE_NIS
53 
54 static struct {
55   const char *name;
56   enum service_type type;
57 } service_names[] = {
58   { "hosts", SERVICE_HOSTS },
59   { _PATH_HOSTS, SERVICE_HOSTS },
60   { "hosttable", SERVICE_HOSTS },
61   { "htable", SERVICE_HOSTS },
62   { "bind", SERVICE_BIND },
63   { "dns", SERVICE_BIND },
64   { "domain", SERVICE_BIND },
65   { "yp", SERVICE_NIS },
66   { "yellowpages", SERVICE_NIS },
67   { "nis", SERVICE_NIS },
68   { 0, SERVICE_NONE }
69 };
70 
71 static enum service_type service_order[SERVICE_MAX + 1];
72 static int service_done = 0;
73 
74 static enum service_type
get_service_name(const char * name)75 get_service_name(const char *name) {
76 	int i;
77 	for(i = 0; service_names[i].type != SERVICE_NONE; i++) {
78 		if(!strcasecmp(name, service_names[i].name)) {
79 			return service_names[i].type;
80 		}
81 	}
82 	return SERVICE_NONE;
83 }
84 
85 static void
init_services()86 init_services()
87 {
88 	char *cp, *p, buf[BUFSIZ];
89 	register int cc = 0;
90 	FILE *fd;
91 
92 	if ((fd = (FILE *)fopen(_PATH_HOSTCONF, "r")) == NULL) {
93 				/* make some assumptions */
94 		service_order[0] = SERVICE_HOSTS;
95 		service_order[1] = SERVICE_BIND;
96 		service_order[2] = SERVICE_NONE;
97 	} else {
98 		while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) {
99 			if(buf[0] == '#')
100 				continue;
101 
102 			p = buf;
103 			while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
104 				;
105 			if (cp == NULL)
106 				continue;
107 			do {
108 				if (isalpha(cp[0])) {
109 					service_order[cc] = get_service_name(cp);
110 					if(service_order[cc] != SERVICE_NONE)
111 						cc++;
112 				}
113 				while ((cp = strsep(&p, "\n \t,:;")) != NULL && *cp == '\0')
114 					;
115 			} while(cp != NULL && cc < SERVICE_MAX);
116 		}
117 		service_order[cc] = SERVICE_NONE;
118 		fclose(fd);
119 	}
120 	service_done = 1;
121 }
122 
123 struct hostent *
gethostbyname(const char * name)124 gethostbyname(const char *name)
125 {
126 	struct hostent *hp;
127 
128 	if (_res.options & RES_USE_INET6) {		/* XXX */
129 		hp = gethostbyname2(name, AF_INET6);	/* XXX */
130 		if (hp)					/* XXX */
131 			return (hp);			/* XXX */
132 	}						/* XXX */
133 	return (gethostbyname2(name, AF_INET));
134 }
135 
136 struct hostent *
gethostbyname2(const char * name,int type)137 gethostbyname2(const char *name, int type)
138 {
139 	struct hostent *hp = 0;
140 	int nserv = 0;
141 
142 	if (!service_done)
143 		init_services();
144 
145 	while (!hp) {
146 		switch (service_order[nserv]) {
147 		      case SERVICE_NONE:
148 			return NULL;
149 		      case SERVICE_HOSTS:
150 			hp = _gethostbyhtname(name, type);
151 			break;
152 		      case SERVICE_BIND:
153 			hp = _gethostbydnsname(name, type);
154 			break;
155 		      case SERVICE_NIS:
156 			hp = _gethostbynisname(name, type);
157 			break;
158 		}
159 		nserv++;
160 	}
161 	return hp;
162 }
163 
164 struct hostent *
gethostbyaddr(const char * addr,socklen_t len,int type)165 gethostbyaddr(const char *addr, socklen_t len, int type)
166 {
167 	struct hostent *hp = 0;
168 	int nserv = 0;
169 
170 	if (!service_done)
171 		init_services();
172 
173 	while (!hp) {
174 		switch (service_order[nserv]) {
175 		      case SERVICE_NONE:
176 			return 0;
177 		      case SERVICE_HOSTS:
178 			hp = _gethostbyhtaddr(addr, len, type);
179 			break;
180 		      case SERVICE_BIND:
181 			hp = _gethostbydnsaddr(addr, len, type);
182 			break;
183 		      case SERVICE_NIS:
184 			hp = _gethostbynisaddr(addr, len, type);
185 			break;
186 		}
187 		nserv++;
188 	}
189 	return hp;
190 }
191 
192 #ifdef _THREAD_SAFE
193 struct hostent_data;
194 
195 /*
196  * Temporary function (not thread safe)
197  */
gethostbyaddr_r(const char * addr,int len,int type,struct hostent * result,struct hostent_data * buffer)198 int gethostbyaddr_r(const char *addr, int len, int type,
199 	struct hostent *result, struct hostent_data *buffer)
200 {
201 	struct hostent *hp;
202 	int ret;
203 	if ((hp = gethostbyaddr(addr, len, type)) == NULL) {
204 		ret = -1;
205 	} else {
206 		memcpy(result, hp, sizeof(struct hostent));
207 		ret = 0;
208 	}
209 	return(ret);
210 }
211 #endif
212 
213 void
sethostent(int stayopen)214 sethostent(int stayopen)
215 {
216 	_sethosthtent(stayopen);
217 	_sethostdnsent(stayopen);
218 }
219 
220 void
endhostent()221 endhostent()
222 {
223 	_endhosthtent();
224 	_endhostdnsent();
225 }
226