Libinfo-78.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_host.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * host lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28 #include <stdlib.h>
29 #include <mach/mach.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include "lookup.h"
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 #include "_lu_types.h"
36 #include <netdb.h>
37 #include "lu_utils.h"
38 #include <sys/socket.h>
39 #import <netinet/in.h>
40
41 extern struct hostent *_res_gethostbyaddr();
42 extern struct hostent *_res_gethostbyname();
43 extern struct hostent *_old_gethostbyaddr();
44 extern struct hostent *_old_gethostbyname();
45 extern struct hostent *_old_gethostent();
46 extern void _old_sethostent();
47 extern void _old_endhostent();
48 extern void _old_sethostfile();
49
50 extern int h_errno;
51
52 static lookup_state h_state = LOOKUP_CACHE;
53 /*
54 * The static return value from get*ent functions
55 */
56 static struct hostent global_h;
57 static int global_free = 1;
58 static char *h_data = NULL;
59 static unsigned h_datalen;
60 static int h_nentries;
61 static int h_start = 1;
62 static XDR h_xdr;
63
64 static void
65 freeold(void)
66 {
67 char **aliases;
68 int i;
69
70 if (global_free == 1) return;
71
72 free(global_h.h_name);
73 aliases = global_h.h_aliases;
74 if (aliases != NULL)
75 {
76 while (*aliases != NULL) free(*aliases++);
77 free(global_h.h_aliases);
78 }
79
80 for (i = 0; global_h.h_addr_list[i] != NULL; i++)
81 free(global_h.h_addr_list[i]);
82
83 free(global_h.h_addr_list);
84
85 global_free = 1;
86 }
87
88 static void
89 convert_h(_lu_hostent *lu_h)
90 {
91 int i, len, addr_len;
92
93 freeold();
94
95 global_h.h_name = strdup(lu_h->h_names.h_names_val[0]);
96
97 len = lu_h->h_names.h_names_len - 1;
98 global_h.h_aliases = (char **)malloc((len + 1) * sizeof(char *));
99
100 for (i = 0; i < len; i++)
101 {
102 global_h.h_aliases[i] = strdup(lu_h->h_names.h_names_val[i + 1]);
103 }
104
105 global_h.h_aliases[len] = NULL;
106
107 global_h.h_addrtype = AF_INET;
108 global_h.h_length = sizeof(long);
109
110 len = lu_h->h_addrs.h_addrs_len;
111 addr_len = sizeof(u_long *);
112
113 global_h.h_addr_list = (char **)malloc((len + 1) * addr_len);
114
115 for (i = 0; i < len; i++)
116 {
117 global_h.h_addr_list[i] = (char *)malloc(sizeof(long));
118 bcopy((const void *)&(lu_h->h_addrs.h_addrs_val[i]),
119 (void *)global_h.h_addr_list[i], sizeof(long));
120 }
121
122 global_h.h_addr_list[len] = NULL;
123
124 global_free = 0;
125 }
126
127 static struct hostent *
128 lu_gethostbyaddr(const char *addr, int len, int type)
129 {
130 unsigned datalen;
131 _lu_hostent_ptr lu_h;
132 XDR xdr;
133 long address;
134 static int proc = -1;
135 unit lookup_buf[MAX_INLINE_UNITS];
136
137 if (len != sizeof(long) || (type != AF_INET))
138 {
139 h_errno = HOST_NOT_FOUND;
140 return (NULL);
141 }
142
143 if (proc < 0)
144 {
145 if (_lookup_link(_lu_port, "gethostbyaddr", &proc) != KERN_SUCCESS)
146 {
147 h_errno = HOST_NOT_FOUND;
148 return (NULL);
149 }
150 }
151
152 bcopy(addr, &address, sizeof(address));
153 address = htonl(address);
154 datalen = MAX_INLINE_UNITS;
155 if (_lookup_one(_lu_port, proc, (unit *)&address, 1, lookup_buf, &datalen)
156 != KERN_SUCCESS)
157 {
158 h_errno = HOST_NOT_FOUND;
159 return (NULL);
160 }
161
162 datalen *= BYTES_PER_XDR_UNIT;
163 xdrmem_create(&xdr, lookup_buf, datalen, XDR_DECODE);
164 lu_h = NULL;
165 h_errno = HOST_NOT_FOUND;
166 if (!xdr__lu_hostent_ptr(&xdr, &lu_h) ||
167 !xdr_int(&xdr, &h_errno) || (lu_h == NULL))
168 {
169 xdr_destroy(&xdr);
170 return (NULL);
171 }
172
173 xdr_destroy(&xdr);
174
175 convert_h(lu_h);
176 xdr_free(xdr__lu_hostent_ptr, &lu_h);
177 return (&global_h);
178 }
179
180 static struct hostent *
181 lu_gethostbyname(const char *name)
182 {
183 unsigned datalen;
184 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
185 XDR outxdr;
186 XDR inxdr;
187 _lu_hostent_ptr lu_h;
188 static int proc = -1;
189 unit lookup_buf[MAX_INLINE_UNITS];
190
191 if (proc < 0)
192 {
193 if (_lookup_link(_lu_port, "gethostbyname", &proc) != KERN_SUCCESS)
194 {
195 h_errno = HOST_NOT_FOUND;
196 return (NULL);
197 }
198 }
199
200 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
201 if (!xdr__lu_string(&outxdr, &name))
202 {
203 xdr_destroy(&outxdr);
204 h_errno = HOST_NOT_FOUND;
205 return (NULL);
206 }
207
208 datalen = MAX_INLINE_UNITS;
209 if (_lookup_one(_lu_port, proc, (unit *)namebuf,
210 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, lookup_buf, &datalen)
211 != KERN_SUCCESS)
212 {
213 xdr_destroy(&outxdr);
214 h_errno = HOST_NOT_FOUND;
215 return (NULL);
216 }
217
218 xdr_destroy(&outxdr);
219
220 datalen *= BYTES_PER_XDR_UNIT;
221 xdrmem_create(&inxdr, lookup_buf, datalen,
222 XDR_DECODE);
223 lu_h = NULL;
224 h_errno = HOST_NOT_FOUND;
225 if (!xdr__lu_hostent_ptr(&inxdr, &lu_h) ||
226 !xdr_int(&inxdr, &h_errno) || (lu_h == NULL))
227 {
228 xdr_destroy(&inxdr);
229 return (NULL);
230 }
231
232 xdr_destroy(&inxdr);
233
234 convert_h(lu_h);
235 xdr_free(xdr__lu_hostent_ptr, &lu_h);
236 return (&global_h);
237 }
238
239 static void
240 lu_endhostent()
241 {
242 h_nentries = 0;
243 if (h_data != NULL)
244 {
245 freeold();
246 vm_deallocate(mach_task_self(), (vm_address_t)h_data, h_datalen);
247 h_data = NULL;
248 }
249 }
250
251 static void
252 lu_sethostent()
253 {
254 lu_endhostent();
255 h_start = 1;
256 }
257
258 static struct hostent *
259 lu_gethostent()
260 {
261 static int proc = -1;
262 _lu_hostent lu_h;
263
264 if (h_start == 1)
265 {
266 h_start = 0;
267
268 if (proc < 0)
269 {
270 if (_lookup_link(_lu_port, "gethostent", &proc) != KERN_SUCCESS)
271 {
272 lu_endhostent();
273 return (NULL);
274 }
275 }
276
277 if (_lookup_all(_lu_port, proc, NULL, 0, &h_data, &h_datalen)
278 != KERN_SUCCESS)
279 {
280 lu_endhostent();
281 return (NULL);
282 }
283
284 #ifdef NOTDEF
285 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
286 h_datalen *= BYTES_PER_XDR_UNIT;
287 #endif
288 xdrmem_create(&h_xdr, h_data, h_datalen,
289 XDR_DECODE);
290 if (!xdr_int(&h_xdr, &h_nentries))
291 {
292 xdr_destroy(&h_xdr);
293 lu_endhostent();
294 return (NULL);
295 }
296 }
297
298 if (h_nentries == 0)
299 {
300 xdr_destroy(&h_xdr);
301 lu_endhostent();
302 return (NULL);
303 }
304
305 bzero(&lu_h, sizeof(lu_h));
306 if (!xdr__lu_hostent(&h_xdr, &lu_h))
307 {
308 xdr_destroy(&h_xdr);
309 lu_endhostent();
310 return (NULL);
311 }
312
313 h_nentries--;
314 convert_h(&lu_h);
315 xdr_free(xdr__lu_hostent, &lu_h);
316 return (&global_h);
317 }
318
319 struct hostent *
320 gethostbyaddr(const char *addr, int len, int type)
321 {
322 struct hostent *res;
323
324 if (_lu_running())
325 {
326 res = lu_gethostbyaddr(addr, len, type);
327 }
328 else
329 {
330 res = _res_gethostbyaddr(addr, len, type);
331 if (res == NULL) res = _old_gethostbyaddr(addr, len, type);
332 }
333
334 return (res);
335 }
336
337 struct hostent *
338 gethostbyname(const char *name)
339 {
340 struct hostent *res;
341 struct in_addr addr;
342
343 if (_lu_running())
344 {
345 res = lu_gethostbyname(name);
346 }
347 else
348 {
349 res = _res_gethostbyname(name);
350 if (res == NULL) res = _old_gethostbyname(name);
351 }
352
353 if (res == NULL)
354 {
355 if (inet_aton(name, &addr) == 0) return NULL;
356 return gethostbyaddr((char *)&addr, sizeof(addr), AF_INET);
357 }
358
359 return res;
360 }
361
362 struct hostent *
363 gethostent(void)
364 {
365 GETENT(lu_gethostent, _old_gethostent, &h_state, struct hostent);
366 }
367
368 void
369 sethostent(int stayopen)
370 {
371 SETSTATE(lu_sethostent, _old_sethostent, &h_state, stayopen);
372 }
373
374 void
375 endhostent(void)
376 {
377 UNSETSTATE(lu_endhostent, _old_endhostent, &h_state);
378 }