Libinfo-222.4.6.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_rpc.c
1 /*
2 * Copyright (c) 1999-2002 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 * RPC lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28
29 #include <rpc/rpc.h>
30 #include <netdb.h>
31 #include <stdlib.h>
32 #include <mach/mach.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <netinet/in.h>
36 #include <pthread.h>
37
38 #include "_lu_types.h"
39 #include "lookup.h"
40 #include "lu_utils.h"
41 #include "lu_overrides.h"
42
43 static pthread_mutex_t _rpc_lock = PTHREAD_MUTEX_INITIALIZER;
44
45 #define RPC_GET_NAME 1
46 #define RPC_GET_NUM 2
47 #define RPC_GET_ENT 3
48
49 static void
50 free_rpc_data(struct rpcent *r)
51 {
52 char **aliases;
53
54 if (r == NULL) return;
55
56 if (r->r_name != NULL) free(r->r_name);
57
58 aliases = r->r_aliases;
59 if (aliases != NULL)
60 {
61 while (*aliases != NULL) free(*aliases++);
62 free(r->r_aliases);
63 }
64 }
65
66 static void
67 free_rpc(struct rpcent *r)
68 {
69 if (r == NULL) return;
70 free_rpc_data(r);
71 free(r);
72 }
73
74 static void
75 free_lu_thread_info_rpc(void *x)
76 {
77 struct lu_thread_info *tdata;
78
79 if (x == NULL) return;
80
81 tdata = (struct lu_thread_info *)x;
82
83 if (tdata->lu_entry != NULL)
84 {
85 free_rpc((struct rpcent *)tdata->lu_entry);
86 tdata->lu_entry = NULL;
87 }
88
89 _lu_data_free_vm_xdr(tdata);
90
91 free(tdata);
92 }
93
94 static struct rpcent *
95 extract_rpc(XDR *xdr)
96 {
97 struct rpcent *r;
98 int i, j, nvals, nkeys, status;
99 char *key, **vals;
100
101 if (xdr == NULL) return NULL;
102
103 if (!xdr_int(xdr, &nkeys)) return NULL;
104
105 r = (struct rpcent *)calloc(1, sizeof(struct rpcent));
106
107 for (i = 0; i < nkeys; i++)
108 {
109 key = NULL;
110 vals = NULL;
111 nvals = 0;
112
113 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
114 if (status < 0)
115 {
116 free_rpc(r);
117 return NULL;
118 }
119
120 if (nvals == 0)
121 {
122 free(key);
123 continue;
124 }
125
126 j = 0;
127
128 if ((r->r_name == NULL) && (!strcmp("name", key)))
129 {
130 r->r_name = vals[0];
131 if (nvals > 1)
132 {
133 r->r_aliases = (char **)calloc(nvals, sizeof(char *));
134 for (j = 1; j < nvals; j++) r->r_aliases[j-1] = vals[j];
135 }
136 j = nvals;
137 }
138 else if (!strcmp("number", key))
139 {
140 r->r_number= atoi(vals[0]);
141 }
142
143 free(key);
144 if (vals != NULL)
145 {
146 for (; j < nvals; j++) free(vals[j]);
147 free(vals);
148 }
149 }
150
151 if (r->r_name == NULL) r->r_name = strdup("");
152 if (r->r_aliases == NULL) r->r_aliases = (char **)calloc(1, sizeof(char *));
153
154 return r;
155 }
156
157 static struct rpcent *
158 copy_rpc(struct rpcent *in)
159 {
160 int i, len;
161 struct rpcent *r;
162
163 if (in == NULL) return NULL;
164
165 r = (struct rpcent *)calloc(1, sizeof(struct rpcent));
166
167 r->r_name = LU_COPY_STRING(in->r_name);
168
169 len = 0;
170 if (in->r_aliases != NULL)
171 {
172 for (len = 0; in->r_aliases[len] != NULL; len++);
173 }
174
175 r->r_aliases = (char **)calloc(len + 1, sizeof(char *));
176 for (i = 0; i < len; i++)
177 {
178 r->r_aliases[i] = strdup(in->r_aliases[i]);
179 }
180
181 r->r_number = in->r_number;
182
183 return r;
184 }
185
186 static void
187 recycle_rpc(struct lu_thread_info *tdata, struct rpcent *in)
188 {
189 struct rpcent *r;
190
191 if (tdata == NULL) return;
192 r = (struct rpcent *)tdata->lu_entry;
193
194 if (in == NULL)
195 {
196 free_rpc(r);
197 tdata->lu_entry = NULL;
198 }
199
200 if (tdata->lu_entry == NULL)
201 {
202 tdata->lu_entry = in;
203 return;
204 }
205
206 free_rpc_data(r);
207
208 r->r_name = in->r_name;
209 r->r_aliases = in->r_aliases;
210 r->r_number = in->r_number;
211
212 free(in);
213 }
214
215 static struct rpcent *
216 lu_getrpcbynumber(long number)
217 {
218 struct rpcent *r;
219 unsigned datalen;
220 XDR inxdr;
221 static int proc = -1;
222 char *lookup_buf;
223 int count;
224
225 if (proc < 0)
226 {
227 if (_lookup_link(_lu_port, "getrpcbynumber", &proc) != KERN_SUCCESS)
228 {
229 return NULL;
230 }
231 }
232
233 number = htonl(number);
234 datalen = 0;
235 lookup_buf = NULL;
236
237 if (_lookup_all(_lu_port, proc, (unit *)&number, 1, &lookup_buf, &datalen)
238 != KERN_SUCCESS)
239 {
240 return NULL;
241 }
242
243 datalen *= BYTES_PER_XDR_UNIT;
244 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
245
246 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
247
248 count = 0;
249 if (!xdr_int(&inxdr, &count))
250 {
251 xdr_destroy(&inxdr);
252 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
253 return NULL;
254 }
255
256 if (count == 0)
257 {
258 xdr_destroy(&inxdr);
259 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
260 return NULL;
261 }
262
263 r = extract_rpc(&inxdr);
264 xdr_destroy(&inxdr);
265 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
266
267 return r;
268 }
269
270 static struct rpcent *
271 lu_getrpcbyname(const char *name)
272 {
273 struct rpcent *r;
274 unsigned datalen;
275 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
276 XDR outxdr, inxdr;
277 static int proc = -1;
278 char *lookup_buf;
279 int count;
280
281 if (proc < 0)
282 {
283 if (_lookup_link(_lu_port, "getrpcbyname", &proc) != KERN_SUCCESS)
284 {
285 return NULL;
286 }
287 }
288
289 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
290 if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
291 {
292 xdr_destroy(&outxdr);
293 return NULL;
294 }
295
296 datalen = 0;
297 lookup_buf = NULL;
298
299 if (_lookup_all(_lu_port, proc, (unit *)namebuf,
300 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
301 != KERN_SUCCESS)
302 {
303 xdr_destroy(&outxdr);
304 return NULL;
305 }
306
307 xdr_destroy(&outxdr);
308
309 datalen *= BYTES_PER_XDR_UNIT;
310 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
311
312 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
313
314 count = 0;
315 if (!xdr_int(&inxdr, &count))
316 {
317 xdr_destroy(&inxdr);
318 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
319 return NULL;
320 }
321
322 if (count == 0)
323 {
324 xdr_destroy(&inxdr);
325 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
326 return NULL;
327 }
328
329 r = extract_rpc(&inxdr);
330 xdr_destroy(&inxdr);
331 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
332
333 return r;
334 }
335
336 static void
337 lu_endrpcent(void)
338 {
339 struct lu_thread_info *tdata;
340
341 tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
342 _lu_data_free_vm_xdr(tdata);
343 }
344
345 static void
346 lu_setrpcent()
347 {
348 lu_endrpcent();
349 }
350
351 static struct rpcent *
352 lu_getrpcent()
353 {
354 struct rpcent *r;
355 static int proc = -1;
356 struct lu_thread_info *tdata;
357
358 tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
359 if (tdata == NULL)
360 {
361 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
362 _lu_data_set_key(_lu_data_key_rpc, tdata);
363 }
364
365 if (tdata->lu_vm == NULL)
366 {
367 if (proc < 0)
368 {
369 if (_lookup_link(_lu_port, "getrpcent", &proc) != KERN_SUCCESS)
370 {
371 lu_endrpcent();
372 return NULL;
373 }
374 }
375
376 if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
377 {
378 lu_endrpcent();
379 return NULL;
380 }
381
382 /* mig stubs measure size in words (4 bytes) */
383 tdata->lu_vm_length *= 4;
384
385 if (tdata->lu_xdr != NULL)
386 {
387 xdr_destroy(tdata->lu_xdr);
388 free(tdata->lu_xdr);
389 }
390 tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
391
392 xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
393 if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
394 {
395 lu_endrpcent();
396 return NULL;
397 }
398 }
399
400 if (tdata->lu_vm_cursor == 0)
401 {
402 lu_endrpcent();
403 return NULL;
404 }
405
406 r = extract_rpc(tdata->lu_xdr);
407 if (r == NULL)
408 {
409 lu_endrpcent();
410 return NULL;
411 }
412
413 tdata->lu_vm_cursor--;
414
415 return r;
416 }
417
418 static struct rpcent *
419 getrpc(const char *name, long number, int source)
420 {
421 struct rpcent *res = NULL;
422 struct lu_thread_info *tdata;
423
424 tdata = _lu_data_create_key(_lu_data_key_rpc, free_lu_thread_info_rpc);
425 if (tdata == NULL)
426 {
427 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
428 _lu_data_set_key(_lu_data_key_rpc, tdata);
429 }
430
431 if (_lu_running())
432 {
433 switch (source)
434 {
435 case RPC_GET_NAME:
436 res = lu_getrpcbyname(name);
437 break;
438 case RPC_GET_NUM:
439 res = lu_getrpcbynumber(number);
440 break;
441 case RPC_GET_ENT:
442 res = lu_getrpcent();
443 break;
444 default: res = NULL;
445 }
446 }
447 else
448 {
449 pthread_mutex_lock(&_rpc_lock);
450 switch (source)
451 {
452 case RPC_GET_NAME:
453 res = copy_rpc(_old_getrpcbyname(name));
454 break;
455 case RPC_GET_NUM:
456 res = copy_rpc(_old_getrpcbynumber(number));
457 break;
458 case RPC_GET_ENT:
459 res = copy_rpc(_old_getrpcent());
460 break;
461 default: res = NULL;
462 }
463 pthread_mutex_unlock(&_rpc_lock);
464 }
465
466 recycle_rpc(tdata, res);
467 return (struct rpcent *)tdata->lu_entry;
468 }
469
470 struct rpcent *
471 getrpcbyname(const char *name)
472 {
473 return getrpc(name, -2, RPC_GET_NAME);
474 }
475
476 struct rpcent *
477 getrpcbynumber(long number)
478 {
479 return getrpc(NULL, number, RPC_GET_NUM);
480 }
481
482 struct rpcent *
483 getrpcent(void)
484 {
485 return getrpc(NULL, -2, RPC_GET_ENT);
486 }
487
488 void
489 setrpcent(int stayopen)
490 {
491 if (_lu_running()) lu_setrpcent();
492 else _old_setrpcent(stayopen);
493 }
494
495 void
496 endrpcent(void)
497 {
498 if (_lu_running()) lu_endrpcent();
499 else _old_endrpcent();
500 }