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