Libinfo-173.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_utils.c
1 /*
2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <mach/mach.h>
29 #include <pthread.h>
30 #ifdef DEBUG
31 #include <syslog.h>
32 #endif
33 #include "_lu_types.h"
34 #include "lookup.h"
35 #include "lu_utils.h"
36 #include "netdb_async.h"
37
38 #define MAX_LOOKUP_ATTEMPTS 10
39 #define _LU_MAXLUSTRLEN 256
40 #define QBUF_SIZE 4096
41
42 #define LU_MESSAGE_SEND_ID 4241776
43 #define LU_MESSAGE_REPLY_ID 4241876
44
45 static pthread_key_t _info_key = NULL;
46 static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT;
47
48 struct _lu_data_s
49 {
50 unsigned int icount;
51 unsigned int *ikey;
52 void **idata;
53 void (**idata_destructor)(void *);
54 };
55
56 typedef struct _lu_async_request_s
57 {
58 mach_port_t reply_port;
59 uint32_t retry;
60 uint32_t proc;
61 void *context;
62 void *callback;
63 ooline_data request_buffer;
64 mach_msg_type_number_t request_buffer_len;
65 struct _lu_async_request_s *next;
66 } _lu_async_request_t;
67
68 typedef struct
69 {
70 mach_msg_header_t head;
71 NDR_record_t NDR;
72 int proc;
73 mach_msg_type_number_t query_data_len;
74 unit query_data[QBUF_SIZE];
75 } _lu_query_msg_t;
76
77 typedef struct
78 {
79 mach_msg_header_t head;
80 mach_msg_body_t msgh_body;
81 mach_msg_ool_descriptor_t reply_data;
82 NDR_record_t NDR;
83 mach_msg_type_number_t reply_data_len;
84 mach_msg_format_0_trailer_t trailer;
85 } _lu_reply_msg_t;
86
87 static pthread_mutex_t _lu_worklist_lock = PTHREAD_MUTEX_INITIALIZER;
88 static _lu_async_request_t *_lu_worklist = NULL;
89
90 /* Send an asynchronous query message to lookupd */
91 static kern_return_t
92 _lu_async_send(_lu_async_request_t *r)
93 {
94 _lu_query_msg_t in;
95 register _lu_query_msg_t *inp = &in;
96 mach_msg_return_t status;
97 unsigned int msgh_size;
98
99 if (r == NULL) return KERN_FAILURE;
100
101 if (r->retry == 0) return MIG_SERVER_DIED;
102 r->retry--;
103
104 if (r->request_buffer_len > QBUF_SIZE) return MIG_ARRAY_TOO_LARGE;
105
106 msgh_size = (sizeof(_lu_query_msg_t) - 16384) + ((4 * r->request_buffer_len));
107 inp->head.msgh_bits = MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
108 inp->head.msgh_remote_port = _lu_port;
109 inp->head.msgh_local_port = r->reply_port;
110 inp->head.msgh_id = LU_MESSAGE_SEND_ID;
111 inp->NDR = NDR_record;
112 inp->proc = r->proc;
113 inp->query_data_len = r->request_buffer_len;
114 memcpy(inp->query_data, r->request_buffer, 4 * r->request_buffer_len);
115
116 status = mach_msg(&inp->head, MACH_SEND_MSG, msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
117 if (status == MACH_MSG_SUCCESS) return KERN_SUCCESS;
118
119 if (status == MACH_SEND_INVALID_REPLY)
120 {
121 mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1);
122 r->reply_port = MACH_PORT_NULL;
123 }
124
125 return status;
126 }
127
128 static _lu_async_request_t *
129 _lu_worklist_remove(mach_port_t p)
130 {
131 _lu_async_request_t *r, *n;
132
133 if (p == MACH_PORT_NULL) return NULL;
134 if (_lu_worklist == NULL) return NULL;
135
136 pthread_mutex_lock(&_lu_worklist_lock);
137
138 if (_lu_worklist->reply_port == p)
139 {
140 r = _lu_worklist;
141 _lu_worklist = r->next;
142 pthread_mutex_unlock(&_lu_worklist_lock);
143 return r;
144 }
145
146 for (r = _lu_worklist; r != NULL; r = r->next)
147 {
148 n = r->next;
149 if (n == NULL) break;
150
151 if (n->reply_port == p)
152 {
153 r->next = n->next;
154 pthread_mutex_unlock(&_lu_worklist_lock);
155 return n;
156 }
157 }
158
159 pthread_mutex_unlock(&_lu_worklist_lock);
160 return NULL;
161 }
162
163 static _lu_async_request_t *
164 _lu_worklist_find(mach_port_t p)
165 {
166 _lu_async_request_t *r;
167
168 if (p == MACH_PORT_NULL) return NULL;
169 if (_lu_worklist == NULL) return NULL;
170
171 pthread_mutex_lock(&_lu_worklist_lock);
172
173 for (r = _lu_worklist; r != NULL; r = r->next)
174 {
175 if (r->reply_port == p)
176 {
177 pthread_mutex_unlock(&_lu_worklist_lock);
178 return r;
179 }
180 }
181
182 pthread_mutex_unlock(&_lu_worklist_lock);
183 return NULL;
184 }
185
186 static void
187 _lu_free_request(_lu_async_request_t *r)
188 {
189 if (r == NULL) return;
190
191 if (r->request_buffer != NULL) free(r->request_buffer);
192 r->request_buffer = NULL;
193
194 if (r->reply_port != MACH_PORT_NULL) mach_port_destroy(mach_task_self(), r->reply_port);
195 r->reply_port = MACH_PORT_NULL;
196
197 free(r);
198 }
199
200 /* Receive an asynchronous reply message from lookupd */
201 kern_return_t
202 lu_async_receive(mach_port_t p, char **buf, uint32_t *len)
203 {
204 _lu_reply_msg_t *r;
205 kern_return_t status;
206 uint32_t size;
207 _lu_async_request_t *req;
208
209 size = sizeof(_lu_reply_msg_t);
210
211 r = (_lu_reply_msg_t *)calloc(1, size);
212 if (r == NULL) return KERN_RESOURCE_SHORTAGE;
213
214 r->head.msgh_local_port = p;
215 r->head.msgh_size = size;
216 status = mach_msg(&(r->head), MACH_RCV_MSG, 0, size, r->head.msgh_local_port, 0, MACH_PORT_NULL);
217 if (status != KERN_SUCCESS)
218 {
219 free(r);
220 return status;
221 }
222
223 req = _lu_worklist_remove(r->head.msgh_local_port);
224 if (req == NULL)
225 {
226 free(r);
227 return KERN_FAILURE;
228 }
229
230 *buf = r->reply_data.address;
231 *len = r->reply_data.size;
232
233 free(r);
234
235 _lu_free_request(req);
236 return KERN_SUCCESS;
237 }
238
239 static void
240 _lu_worklist_append(_lu_async_request_t *r)
241 {
242 _lu_async_request_t *p;
243
244 if (r == NULL) return;
245
246 pthread_mutex_lock(&_lu_worklist_lock);
247
248 if (_lu_worklist == NULL)
249 {
250 _lu_worklist = r;
251 pthread_mutex_unlock(&_lu_worklist_lock);
252 return;
253 }
254
255 for (p = _lu_worklist; p->next != NULL; p = p->next);
256 p->next = r;
257
258 pthread_mutex_unlock(&_lu_worklist_lock);
259 }
260
261 void
262 lu_async_call_cancel(mach_port_t p)
263 {
264 _lu_async_request_t *req;
265
266 req = _lu_worklist_remove(p);
267 if (req != NULL) _lu_free_request(req);
268 else if (p != MACH_PORT_NULL) mach_port_destroy(mach_task_self(), p);
269 }
270
271 static _lu_async_request_t *
272 _lu_create_request(uint32_t proc, const char *buf, uint32_t len, void *callback, void *context)
273 {
274 _lu_async_request_t *r;
275 kern_return_t status;
276
277 if (_lu_port == NULL) return NULL;
278
279 r = (_lu_async_request_t *)calloc(1, sizeof(_lu_async_request_t));
280 if (r == NULL) return NULL;
281
282 status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(r->reply_port));
283 if (status != KERN_SUCCESS)
284 {
285 _lu_free_request(r);
286 return NULL;
287 }
288
289 r->retry = MAX_LOOKUP_ATTEMPTS;
290
291 r->context = context;
292 r->callback = callback;
293 r->proc = proc;
294
295 r->request_buffer = malloc(len * BYTES_PER_XDR_UNIT);
296 memcpy(r->request_buffer, buf, len * BYTES_PER_XDR_UNIT);
297 r->request_buffer_len = len;
298
299 r->next = NULL;
300
301 return r;
302 }
303
304 kern_return_t
305 lu_async_start(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len, void *callback, void *context)
306 {
307 _lu_async_request_t *r;
308 kern_return_t status;
309 uint32_t retry;
310
311 if (p == NULL) return KERN_FAILURE;
312
313 *p = MACH_PORT_NULL;
314
315 if (!_lu_running()) return KERN_FAILURE;
316
317 /* Make a request struct to keep track */
318 r = _lu_create_request(proc, buf, len, callback, context);
319 if (r == NULL) return KERN_FAILURE;
320
321 status = MIG_SERVER_DIED;
322 for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
323 {
324 /* send to lookupd */
325 status = _lu_async_send(r);
326 }
327
328 if (status != KERN_SUCCESS)
329 {
330 _lu_free_request(r);
331 return status;
332 }
333
334 /* Add request to worklist */
335 _lu_worklist_append(r);
336
337 *p = r->reply_port;
338 return KERN_SUCCESS;
339 }
340
341 kern_return_t
342 lu_async_send(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len)
343 {
344 return lu_async_start(p, proc, buf, len, NULL, NULL);
345 }
346
347 int
348 lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, void **context)
349 {
350 _lu_reply_msg_t *r;
351 _lu_async_request_t *req;
352 kern_return_t status;
353 uint32_t retry;
354
355 if (msg == NULL) return -1;
356 r = (_lu_reply_msg_t *)msg;
357
358 /* If reply status was an error, resend */
359 if (r->head.msgh_id != LU_MESSAGE_REPLY_ID)
360 {
361 if (r->head.msgh_id == MACH_NOTIFY_SEND_ONCE)
362 {
363 /* if MiG server (lookupd) died */
364 req = _lu_worklist_find(r->head.msgh_local_port);
365 if (req == NULL) return -1;
366
367 status = MIG_SERVER_DIED;
368 for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
369 {
370 /* send to lookupd */
371 status = _lu_async_send(req);
372 }
373
374 if (status != KERN_SUCCESS) return -1;
375 }
376 return MIG_REPLY_MISMATCH;
377 }
378
379 req = _lu_worklist_remove(r->head.msgh_local_port);
380 if (req == NULL) return -1;
381
382 *buf = r->reply_data.address;
383 *len = r->reply_data.size;
384 *callback = req->callback;
385 *context = req->context;
386
387 _lu_free_request(req);
388 return 0;
389 }
390
391 ni_proplist *
392 _lookupd_xdr_dictionary(XDR *inxdr)
393 {
394 int i, nkeys, j, nvals;
395 char *key, *val;
396 ni_proplist *l;
397
398 if (!xdr_int(inxdr, &nkeys)) return NULL;
399
400 l = (ni_proplist *)malloc(sizeof(ni_proplist));
401 NI_INIT(l);
402
403 l->ni_proplist_len = nkeys;
404 l->ni_proplist_val = NULL;
405 if (nkeys > 0)
406 {
407 i = nkeys * sizeof(ni_property);
408 l->ni_proplist_val = (ni_property *)calloc(1, i);
409 }
410
411 for (i = 0; i < nkeys; i++)
412 {
413 key = NULL;
414 if (!xdr_string(inxdr, &key, -1))
415 {
416 ni_proplist_free(l);
417 return NULL;
418 }
419
420 l->ni_proplist_val[i].nip_name = key;
421
422 if (!xdr_int(inxdr, &nvals))
423 {
424 ni_proplist_free(l);
425 return NULL;
426 }
427
428 l->ni_proplist_val[i].nip_val.ni_namelist_len = nvals;
429 if (nvals > 0)
430 {
431 j = nvals * sizeof(ni_name);
432 l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(1, j);
433 }
434
435 for (j = 0; j < nvals; j++)
436 {
437 val = NULL;
438 if (!xdr_string(inxdr, &val, -1))
439 {
440 ni_proplist_free(l);
441 return NULL;
442 }
443
444 l->ni_proplist_val[i].nip_val.ni_namelist_val[j] = val;
445 }
446 }
447
448 return l;
449 }
450
451 int
452 lookupd_query(ni_proplist *l, ni_proplist ***out)
453 {
454 unsigned datalen;
455 XDR outxdr;
456 XDR inxdr;
457 int proc;
458 char *listbuf, *s;
459 char databuf[_LU_MAXLUSTRLEN * BYTES_PER_XDR_UNIT];
460 int n, i, j, na;
461 kern_return_t status;
462 ni_property *p;
463
464 if (l == NULL) return 0;
465 if (out == NULL) return 0;
466
467 if (_lu_port == NULL) return 0;
468
469 status = _lookup_link(_lu_port, "query", &proc);
470 if (status != KERN_SUCCESS) return 0;
471
472 xdrmem_create(&outxdr, databuf, sizeof(databuf), XDR_ENCODE);
473
474 na = l->ni_proplist_len;
475
476 /* Encode attribute count */
477 if (!xdr_int(&outxdr, &na))
478 {
479 xdr_destroy(&outxdr);
480 return 0;
481 }
482
483 for (i = 0; i < l->ni_proplist_len; i++)
484 {
485 p = &(l->ni_proplist_val[i]);
486 s = NULL;
487 if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
488 {
489 xdr_destroy(&outxdr);
490 return 0;
491 }
492 p->nip_name = s;
493
494 if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len)))
495 {
496 xdr_destroy(&outxdr);
497 return 0;
498 }
499
500 for (j = 0; j < p->nip_val.ni_namelist_len; j++)
501 {
502 s = NULL;
503 if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
504 {
505 xdr_destroy(&outxdr);
506 return 0;
507 }
508 p->nip_val.ni_namelist_val[j] = s;
509 }
510 }
511
512 listbuf = NULL;
513 datalen = 0;
514
515 n = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT;
516 status = _lookup_all(_lu_port, proc, (unit *)databuf, n, &listbuf, &datalen);
517 if (status != KERN_SUCCESS)
518 {
519 xdr_destroy(&outxdr);
520 return 0;
521 }
522
523 xdr_destroy(&outxdr);
524
525 #ifdef NOTDEF
526 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
527 datalen *= BYTES_PER_XDR_UNIT;
528 #endif
529
530 xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE);
531
532 if (!xdr_int(&inxdr, &n))
533 {
534 xdr_destroy(&inxdr);
535 return 0;
536 }
537
538 if (n == 0)
539 {
540 xdr_destroy(&inxdr);
541 return 0;
542 }
543
544 *out = (ni_proplist **)malloc(n * sizeof(ni_proplist *));
545
546 for (i = 0; i < n; i++)
547 {
548 (*out)[i] = _lookupd_xdr_dictionary(&inxdr);
549 }
550
551 xdr_destroy(&inxdr);
552
553 vm_deallocate(mach_task_self(), (vm_address_t)listbuf, datalen);
554
555 return n;
556 }
557
558 ni_proplist *
559 lookupd_make_query(char *cat, char *fmt, ...)
560 {
561 va_list ap;
562 char *arg, *f;
563 int na, x;
564 ni_proplist *l;
565 ni_property *p;
566
567 if (fmt == NULL) return NULL;
568 if (fmt[0] != 'k') return NULL;
569
570 l = (ni_proplist *)malloc(sizeof(ni_proplist));
571 NI_INIT(l);
572
573 na = 0;
574 x = -1;
575
576 if (cat != NULL)
577 {
578 l->ni_proplist_val = (ni_property *)malloc(sizeof(ni_property));
579 p = &(l->ni_proplist_val[0]);
580 arg = "_lookup_category";
581 p->nip_name = strdup(arg);
582 p->nip_val.ni_namelist_len = 1;
583 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
584 p->nip_val.ni_namelist_val[0] = strdup(cat);
585
586 l->ni_proplist_len++;
587 x++;
588 }
589
590 va_start(ap, fmt);
591 for (f = fmt; *f != NULL; f++)
592 {
593 arg = va_arg(ap, char *);
594 if (*f == 'k')
595 {
596 l->ni_proplist_val = (ni_property *)realloc(l->ni_proplist_val, (l->ni_proplist_len + 1) * sizeof(ni_property));
597
598 p = &(l->ni_proplist_val[l->ni_proplist_len]);
599 p->nip_name = strdup(arg);
600 p->nip_val.ni_namelist_len = 0;
601 p->nip_val.ni_namelist_val = NULL;
602
603 l->ni_proplist_len++;
604 x++;
605 }
606 else
607 {
608 p = &(l->ni_proplist_val[x]);
609 if (p->nip_val.ni_namelist_len == 0)
610 {
611 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
612 }
613 else
614 {
615 p->nip_val.ni_namelist_val = (ni_name *)realloc(p->nip_val.ni_namelist_val, (p->nip_val.ni_namelist_len + 1) * sizeof(ni_name));
616 }
617 p->nip_val.ni_namelist_val[p->nip_val.ni_namelist_len] = strdup(arg);
618 p->nip_val.ni_namelist_len++;
619 }
620 }
621 va_end(ap);
622
623 return l;
624 }
625
626 void
627 ni_property_merge(ni_property *a, ni_property *b)
628 {
629 int i, j, addme;
630
631 if (a == NULL) return;
632 if (b == NULL) return;
633
634 for (j = 0; j < b->nip_val.ni_namelist_len; j++)
635 {
636 addme = 1;
637 for (i = 0; i < (a->nip_val.ni_namelist_len) && (addme == 1); i++)
638 {
639 if (!strcmp(a->nip_val.ni_namelist_val[i], b->nip_val.ni_namelist_val[j])) addme = 0;
640 }
641
642 if (addme == 1)
643 {
644 a->nip_val.ni_namelist_val = (ni_name *)realloc(a->nip_val.ni_namelist_val, (a->nip_val.ni_namelist_len + 1) * sizeof(ni_name));
645 a->nip_val.ni_namelist_val[a->nip_val.ni_namelist_len] = strdup(b->nip_val.ni_namelist_val[j]);
646 a->nip_val.ni_namelist_len++;
647 }
648 }
649 }
650
651 void
652 ni_proplist_merge(ni_proplist *a, ni_proplist *b)
653 {
654 ni_index wa, wb;
655 int addme;
656
657 if (a == NULL) return;
658 if (b == NULL) return;
659
660 for (wb = 0; wb < b->ni_proplist_len; wb++)
661 {
662 addme = 1;
663 for (wa = 0; (wa < a->ni_proplist_len) && (addme == 1) ; wa++)
664 {
665 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name)) addme = 0;
666 }
667 if (addme == 1)
668 {
669 a->ni_proplist_val = (ni_property *)realloc(a->ni_proplist_val, (a->ni_proplist_len + 1) * sizeof(ni_property));
670 a->ni_proplist_val[a->ni_proplist_len].nip_name = strdup(b->ni_proplist_val[wb].nip_name);
671 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_len = 0;
672 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_val = NULL;
673 a->ni_proplist_len++;
674 }
675 }
676
677 for (wb = 0; wb < b->ni_proplist_len; wb++)
678 {
679 for (wa = 0; wa < a->ni_proplist_len; wa++)
680 {
681 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name))
682 {
683 ni_property_merge(&(a->ni_proplist_val[wa]), &(b->ni_proplist_val[wb]));
684 }
685 }
686 }
687 }
688
689 static void
690 _lu_data_free(void *x)
691 {
692 struct _lu_data_s *t;
693 int i;
694
695 if (x == NULL) return;
696
697 t = (struct _lu_data_s *)x;
698
699 for (i = 0; i < t->icount; i++)
700 {
701 if ((t->idata[i] != NULL) && (t->idata_destructor[i] != NULL))
702 {
703 (*(t->idata_destructor[i]))(t->idata[i]);
704 }
705
706 t->idata[i] = NULL;
707 t->idata_destructor[i] = NULL;
708 }
709
710 if (t->ikey != NULL) free(t->ikey);
711 t->ikey = NULL;
712
713 if (t->idata != NULL) free(t->idata);
714 t->idata = NULL;
715
716 if (t->idata_destructor != NULL) free(t->idata_destructor);
717 t->idata_destructor = NULL;
718
719 free(t);
720 }
721
722 static void
723 _lu_data_init()
724 {
725 pthread_key_create(&_info_key, _lu_data_free);
726 return;
727 }
728
729 static struct _lu_data_s *
730 _lu_data_get()
731 {
732 struct _lu_data_s *libinfo_data;
733
734 /*
735 * Only one thread should create the _info_key
736 */
737 pthread_once(&_info_key_initialized, _lu_data_init);
738
739 /* Check if this thread already created libinfo_data */
740 libinfo_data = pthread_getspecific(_info_key);
741 if (libinfo_data != NULL) return libinfo_data;
742
743 libinfo_data = (struct _lu_data_s *)calloc(1, sizeof(struct _lu_data_s));
744
745 pthread_setspecific(_info_key, libinfo_data);
746 return libinfo_data;
747 }
748
749 void *
750 _lu_data_create_key(unsigned int key, void (*destructor)(void *))
751 {
752 struct _lu_data_s *libinfo_data;
753 unsigned int i, n;
754
755 libinfo_data = _lu_data_get();
756
757 for (i = 0; i < libinfo_data->icount; i++)
758 {
759 if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
760 }
761
762 i = libinfo_data->icount;
763 n = i + 1;
764
765 if (i == 0)
766 {
767 libinfo_data->ikey = (unsigned int *)malloc(sizeof(unsigned int));
768 libinfo_data->idata = (void **)malloc(sizeof(void *));
769 libinfo_data->idata_destructor = (void (**)(void *))malloc(sizeof(void (*)(void *)));
770 }
771 else
772 {
773 libinfo_data->ikey = (unsigned int *)realloc(libinfo_data->ikey, n * sizeof(unsigned int));
774 libinfo_data->idata = (void **)realloc(libinfo_data->idata, n * sizeof(void *));
775 libinfo_data->idata_destructor = (void (**)(void *))realloc(libinfo_data->idata_destructor, n * sizeof(void (*)(void *)));
776 }
777
778 libinfo_data->ikey[i] = key;
779 libinfo_data->idata[i] = NULL;
780 libinfo_data->idata_destructor[i] = destructor;
781 libinfo_data->icount++;
782
783 return NULL;
784 }
785
786 static unsigned int
787 _lu_data_index(unsigned int key, struct _lu_data_s *libinfo_data)
788 {
789 unsigned int i;
790
791 if (libinfo_data == NULL) return (unsigned int)-1;
792
793 for (i = 0; i < libinfo_data->icount; i++)
794 {
795 if (libinfo_data->ikey[i] == key) return i;
796 }
797
798 return (unsigned int)-1;
799 }
800
801 void
802 _lu_data_set_key(unsigned int key, void *data)
803 {
804 struct _lu_data_s *libinfo_data;
805 unsigned int i;
806
807 libinfo_data = _lu_data_get();
808
809 i = _lu_data_index(key, libinfo_data);
810 if (i == (unsigned int)-1) return;
811
812 libinfo_data->idata[i] = data;
813 }
814
815 void *
816 _lu_data_get_key(unsigned int key)
817 {
818 struct _lu_data_s *libinfo_data;
819 unsigned int i;
820
821 libinfo_data = _lu_data_get();
822
823 i = _lu_data_index(key, libinfo_data);
824 if (i == (unsigned int)-1) return NULL;
825
826 return libinfo_data->idata[i];
827 }
828
829 void
830 _lu_data_free_vm_xdr(struct lu_thread_info *tdata)
831 {
832 if (tdata == NULL) return;
833
834 if (tdata->lu_vm != NULL)
835 {
836 vm_deallocate(mach_task_self(), (vm_address_t)tdata->lu_vm, tdata->lu_vm_length);
837 tdata->lu_vm = NULL;
838 }
839 tdata->lu_vm_length = 0;
840 tdata->lu_vm_cursor = 0;
841
842 if (tdata->lu_xdr != NULL)
843 {
844 xdr_destroy(tdata->lu_xdr);
845 free(tdata->lu_xdr);
846 tdata->lu_xdr = NULL;
847 }
848 }
849
850 int
851 _lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count)
852 {
853 unsigned int i, j, len;
854 char **x, *s;
855
856 if (xdr == NULL) return -1;
857 if (key == NULL) return -1;
858 if (val == NULL) return -1;
859 if (count == NULL) return -1;
860
861 *key = NULL;
862 *val = NULL;
863 *count = 0;
864
865 if (!xdr_string(xdr, key, -1)) return -1;
866
867 if (!xdr_int(xdr, &len))
868 {
869 free(*key);
870 *key = NULL;
871 return -1;
872 }
873
874 if (len == 0) return 0;
875 *count = len;
876
877 x = (char **)calloc(len + 1, sizeof(char *));
878 *val = x;
879
880 for (i = 0; i < len; i++)
881 {
882 s = NULL;
883 if (!xdr_string(xdr, &s, -1))
884 {
885 for (j = 0; j < i; j++) free(x[j]);
886 free(x);
887 *val = NULL;
888 free(*key);
889 *key = NULL;
890 *count = 0;
891 return -1;
892 }
893 x[i] = s;
894 }
895
896 x[len] = NULL;
897
898 return 0;
899 }
900
901 kern_return_t
902 _lookup_link(mach_port_t server, lookup_name name, int *procno)
903 {
904 kern_return_t status;
905 security_token_t token;
906 unsigned int n;
907
908 token.val[0] = -1;
909 token.val[1] = -1;
910
911 status = MIG_SERVER_DIED;
912 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
913 {
914 status = _lookup_link_secure(server, name, procno, &token);
915 }
916
917 if (status != KERN_SUCCESS)
918 {
919 #ifdef DEBUG
920 syslog(LOG_DEBUG, "pid %u _lookup_link %s status %u", getpid(), name, status);
921 #endif
922 return status;
923 }
924
925 if (token.val[0] != 0)
926 {
927 #ifdef DEBUG
928 syslog(LOG_DEBUG, "pid %u _lookup_link %s auth failure uid=%d", getpid(), name, token.val[0]);
929 #endif
930 return KERN_FAILURE;
931 }
932
933 #ifdef DEBUG
934 syslog(LOG_DEBUG, "pid %u _lookup_link %s = %d", getpid(), name, *procno);
935 #endif
936 return status;
937 }
938
939 kern_return_t
940 _lookup_one(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, inline_data outdata, mach_msg_type_number_t *outdataCnt)
941 {
942 kern_return_t status;
943 security_token_t token;
944 unsigned int n;
945
946 token.val[0] = -1;
947 token.val[1] = -1;
948
949 status = MIG_SERVER_DIED;
950 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
951 {
952 status = _lookup_one_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
953 }
954
955 if (status != KERN_SUCCESS)
956 {
957 #ifdef DEBUG
958 syslog(LOG_DEBUG, "pid %u _lookup_one %d status %u", getpid(), proc, status);
959 #endif
960 return status;
961 }
962
963 if (token.val[0] != 0)
964 {
965 #ifdef DEBUG
966 syslog(LOG_DEBUG, "pid %u _lookup_one %d auth failure uid=%d", getpid(), proc, token.val[0]);
967 #endif
968 return KERN_FAILURE;
969 }
970
971 #ifdef DEBUG
972 syslog(LOG_DEBUG, "pid %u _lookup_one %d", getpid(), proc);
973 #endif
974 return status;
975 }
976
977 kern_return_t
978 _lookup_all(mach_port_t server, int proc, inline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt)
979 {
980 kern_return_t status;
981 security_token_t token;
982 unsigned int n;
983
984 token.val[0] = -1;
985 token.val[1] = -1;
986
987 status = MIG_SERVER_DIED;
988 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
989 {
990 status = _lookup_all_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
991 }
992
993 if (status != KERN_SUCCESS)
994 {
995 #ifdef DEBUG
996 syslog(LOG_DEBUG, "pid %u _lookup_all %d status %u", getpid(), proc, status);
997 #endif
998 return status;
999 }
1000
1001 if (token.val[0] != 0)
1002 {
1003 #ifdef DEBUG
1004 syslog(LOG_DEBUG, "pid %u _lookup_all %d auth failure uid=%d", getpid(), proc, token.val[0]);
1005 #endif
1006 return KERN_FAILURE;
1007 }
1008
1009 #ifdef DEBUG
1010 syslog(LOG_DEBUG, "pid %u _lookup_all %d", getpid(), proc);
1011 #endif
1012 return status;
1013 }
1014
1015 kern_return_t
1016 _lookup_ooall(mach_port_t server, int proc, ooline_data indata, mach_msg_type_number_t indataCnt, ooline_data *outdata, mach_msg_type_number_t *outdataCnt)
1017 {
1018 kern_return_t status;
1019 security_token_t token;
1020 unsigned int n;
1021
1022 token.val[0] = -1;
1023 token.val[1] = -1;
1024
1025 status = MIG_SERVER_DIED;
1026 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
1027 {
1028 status = _lookup_ooall_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
1029 }
1030
1031 if (status != KERN_SUCCESS)
1032 {
1033 #ifdef DEBUG
1034 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d status %u", getpid(), proc, status);
1035 #endif
1036 return status;
1037 }
1038
1039 if (token.val[0] != 0)
1040 {
1041 #ifdef DEBUG
1042 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d auth failure uid=%d", getpid(), proc, token.val[0]);
1043 #endif
1044 return KERN_FAILURE;
1045 }
1046
1047 #ifdef DEBUG
1048 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d", getpid(), proc);
1049 #endif
1050 return status;
1051 }