]> git.saurik.com Git - apple/libinfo.git/blob - lookup.subproj/lu_utils.c
Libinfo-222.3.5.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 = 0;
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 boolean_t msgh_simple;
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 msgh_simple = !(r->head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
224
225 req = _lu_worklist_remove(r->head.msgh_local_port);
226 if (req == NULL)
227 {
228 free(r);
229 return KERN_FAILURE;
230 }
231
232 if (msgh_simple && ((mig_reply_error_t *) r)->RetCode != KERN_SUCCESS)
233 {
234 _lu_free_request(req);
235 status = ((mig_reply_error_t *) r)->RetCode;
236 free(r);
237 return status;
238 }
239
240 *buf = r->reply_data.address;
241 *len = r->reply_data.size;
242
243 free(r);
244
245 _lu_free_request(req);
246 return KERN_SUCCESS;
247 }
248
249 static void
250 _lu_worklist_append(_lu_async_request_t *r)
251 {
252 _lu_async_request_t *p;
253
254 if (r == NULL) return;
255
256 pthread_mutex_lock(&_lu_worklist_lock);
257
258 if (_lu_worklist == NULL)
259 {
260 _lu_worklist = r;
261 pthread_mutex_unlock(&_lu_worklist_lock);
262 return;
263 }
264
265 for (p = _lu_worklist; p->next != NULL; p = p->next);
266 p->next = r;
267
268 pthread_mutex_unlock(&_lu_worklist_lock);
269 }
270
271 void
272 lu_async_call_cancel(mach_port_t p)
273 {
274 _lu_async_request_t *req;
275
276 req = _lu_worklist_remove(p);
277 if (req != NULL) _lu_free_request(req);
278 else if (p != MACH_PORT_NULL) mach_port_destroy(mach_task_self(), p);
279 }
280
281 static _lu_async_request_t *
282 _lu_create_request(uint32_t proc, const char *buf, uint32_t len, void *callback, void *context)
283 {
284 _lu_async_request_t *r;
285 kern_return_t status;
286
287 if (_lu_port == MACH_PORT_NULL) return NULL;
288
289 r = (_lu_async_request_t *)calloc(1, sizeof(_lu_async_request_t));
290 if (r == NULL) return NULL;
291
292 status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(r->reply_port));
293 if (status != KERN_SUCCESS)
294 {
295 _lu_free_request(r);
296 return NULL;
297 }
298
299 r->retry = MAX_LOOKUP_ATTEMPTS;
300
301 r->context = context;
302 r->callback = callback;
303 r->proc = proc;
304
305 r->request_buffer = malloc(len * BYTES_PER_XDR_UNIT);
306 memcpy(r->request_buffer, buf, len * BYTES_PER_XDR_UNIT);
307 r->request_buffer_len = len;
308
309 r->next = NULL;
310
311 return r;
312 }
313
314 kern_return_t
315 lu_async_start(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len, void *callback, void *context)
316 {
317 _lu_async_request_t *r;
318 kern_return_t status;
319 uint32_t retry;
320
321 if (p == NULL) return KERN_FAILURE;
322
323 *p = MACH_PORT_NULL;
324
325 if (!_lu_running()) return KERN_FAILURE;
326
327 /* Make a request struct to keep track */
328 r = _lu_create_request(proc, buf, len, callback, context);
329 if (r == NULL) return KERN_FAILURE;
330
331 status = MIG_SERVER_DIED;
332 for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
333 {
334 /* send to lookupd */
335 status = _lu_async_send(r);
336 }
337
338 if (status != KERN_SUCCESS)
339 {
340 _lu_free_request(r);
341 return status;
342 }
343
344 /* Add request to worklist */
345 _lu_worklist_append(r);
346
347 *p = r->reply_port;
348 return KERN_SUCCESS;
349 }
350
351 kern_return_t
352 lu_async_send(mach_port_t *p, uint32_t proc, const char *buf, uint32_t len)
353 {
354 return lu_async_start(p, proc, buf, len, NULL, NULL);
355 }
356
357 int
358 lu_async_handle_reply(void *msg, char **buf, uint32_t *len, void **callback, void **context)
359 {
360 _lu_reply_msg_t *r;
361 _lu_async_request_t *req;
362 kern_return_t status;
363 uint32_t retry;
364 boolean_t msgh_simple;
365
366 if (msg == NULL) return -1;
367 r = (_lu_reply_msg_t *)msg;
368
369 /* If reply status was an error, resend */
370 if (r->head.msgh_id != LU_MESSAGE_REPLY_ID)
371 {
372 if (r->head.msgh_id == MACH_NOTIFY_SEND_ONCE)
373 {
374 /* if MiG server (lookupd) died */
375 req = _lu_worklist_find(r->head.msgh_local_port);
376 if (req == NULL) return -1;
377
378 status = MIG_SERVER_DIED;
379 for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
380 {
381 /* send to lookupd */
382 status = _lu_async_send(req);
383 }
384
385 if (status != KERN_SUCCESS) return -1;
386 }
387 return MIG_REPLY_MISMATCH;
388 }
389
390 msgh_simple = !(r->head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
391
392 req = _lu_worklist_remove(r->head.msgh_local_port);
393 if (req == NULL) return -1;
394
395 *callback = req->callback;
396 *context = req->context;
397 _lu_free_request(req);
398
399 if (msgh_simple && ((mig_reply_error_t *) r)->RetCode != KERN_SUCCESS)
400 {
401 return ((mig_reply_error_t *) r)->RetCode;
402 }
403
404 *buf = r->reply_data.address;
405 *len = r->reply_data.size;
406
407 return 0;
408 }
409
410 ni_proplist *
411 _lookupd_xdr_dictionary(XDR *inxdr)
412 {
413 int i, nkeys, j, nvals;
414 char *key, *val;
415 ni_proplist *l;
416
417 if (!xdr_int(inxdr, &nkeys)) return NULL;
418
419 l = (ni_proplist *)malloc(sizeof(ni_proplist));
420 NI_INIT(l);
421
422 l->ni_proplist_len = nkeys;
423 l->ni_proplist_val = NULL;
424 if (nkeys > 0)
425 {
426 l->ni_proplist_val = (ni_property *)calloc(nkeys, sizeof(ni_property));
427 }
428
429 for (i = 0; i < nkeys; i++)
430 {
431 key = NULL;
432 if (!xdr_string(inxdr, &key, -1))
433 {
434 ni_proplist_free(l);
435 return NULL;
436 }
437
438 l->ni_proplist_val[i].nip_name = key;
439
440 if (!xdr_int(inxdr, &nvals))
441 {
442 ni_proplist_free(l);
443 return NULL;
444 }
445
446 l->ni_proplist_val[i].nip_val.ni_namelist_len = nvals;
447 if (nvals > 0)
448 {
449 l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)calloc(nvals, sizeof(ni_name));
450 }
451
452 for (j = 0; j < nvals; j++)
453 {
454 val = NULL;
455 if (!xdr_string(inxdr, &val, -1))
456 {
457 ni_proplist_free(l);
458 return NULL;
459 }
460
461 l->ni_proplist_val[i].nip_val.ni_namelist_val[j] = val;
462 }
463 }
464
465 return l;
466 }
467
468 int
469 lookupd_query(ni_proplist *l, ni_proplist ***out)
470 {
471 unsigned datalen;
472 XDR outxdr;
473 XDR inxdr;
474 int proc;
475 char *listbuf, *s;
476 char databuf[_LU_MAXLUSTRLEN * BYTES_PER_XDR_UNIT];
477 int n, i, j, na;
478 kern_return_t status;
479 ni_property *p;
480
481 if (l == NULL) return 0;
482 if (out == NULL) return 0;
483
484 if (_lu_port == MACH_PORT_NULL) return 0;
485
486 status = _lookup_link(_lu_port, "query", &proc);
487 if (status != KERN_SUCCESS) return 0;
488
489 xdrmem_create(&outxdr, databuf, sizeof(databuf), XDR_ENCODE);
490
491 na = l->ni_proplist_len;
492
493 /* Encode attribute count */
494 if (!xdr_int(&outxdr, &na))
495 {
496 xdr_destroy(&outxdr);
497 return 0;
498 }
499
500 for (i = 0; i < l->ni_proplist_len; i++)
501 {
502 p = &(l->ni_proplist_val[i]);
503 s = p->nip_name;
504 if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
505 {
506 xdr_destroy(&outxdr);
507 return 0;
508 }
509
510 if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len)))
511 {
512 xdr_destroy(&outxdr);
513 return 0;
514 }
515
516 for (j = 0; j < p->nip_val.ni_namelist_len; j++)
517 {
518 s = p->nip_val.ni_namelist_val[j];
519 if (!xdr_string(&outxdr, &s, _LU_MAXLUSTRLEN))
520 {
521 xdr_destroy(&outxdr);
522 return 0;
523 }
524 }
525 }
526
527 listbuf = NULL;
528 datalen = 0;
529
530 n = xdr_getpos(&outxdr);
531 status = _lookup_all(_lu_port, proc, (void *)databuf, n, &listbuf, &datalen);
532 if (status != KERN_SUCCESS)
533 {
534 xdr_destroy(&outxdr);
535 return 0;
536 }
537
538 xdr_destroy(&outxdr);
539 datalen *= BYTES_PER_XDR_UNIT;
540 xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE);
541
542 if (!xdr_int(&inxdr, &n))
543 {
544 xdr_destroy(&inxdr);
545 return 0;
546 }
547
548 if (n == 0)
549 {
550 xdr_destroy(&inxdr);
551 return 0;
552 }
553
554 *out = (ni_proplist **)malloc(n * sizeof(ni_proplist *));
555
556 for (i = 0; i < n; i++)
557 {
558 (*out)[i] = _lookupd_xdr_dictionary(&inxdr);
559 }
560
561 xdr_destroy(&inxdr);
562
563 vm_deallocate(mach_task_self(), (vm_address_t)listbuf, datalen);
564
565 return n;
566 }
567
568 ni_proplist *
569 lookupd_make_query(char *cat, char *fmt, ...)
570 {
571 va_list ap;
572 char *arg, *f;
573 int na, x;
574 ni_proplist *l;
575 ni_property *p;
576
577 if (fmt == NULL) return NULL;
578 if (fmt[0] != 'k') return NULL;
579
580 l = (ni_proplist *)malloc(sizeof(ni_proplist));
581 NI_INIT(l);
582
583 na = 0;
584 x = -1;
585
586 if (cat != NULL)
587 {
588 l->ni_proplist_val = (ni_property *)malloc(sizeof(ni_property));
589 p = &(l->ni_proplist_val[0]);
590 arg = "_lookup_category";
591 p->nip_name = strdup(arg);
592 p->nip_val.ni_namelist_len = 1;
593 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
594 p->nip_val.ni_namelist_val[0] = strdup(cat);
595
596 l->ni_proplist_len++;
597 x++;
598 }
599
600 va_start(ap, fmt);
601 for (f = fmt; (*f) != '\0'; f++)
602 {
603 arg = va_arg(ap, char *);
604 if (*f == 'k')
605 {
606 l->ni_proplist_val = (ni_property *)realloc(l->ni_proplist_val, (l->ni_proplist_len + 1) * sizeof(ni_property));
607
608 p = &(l->ni_proplist_val[l->ni_proplist_len]);
609 p->nip_name = strdup(arg);
610 p->nip_val.ni_namelist_len = 0;
611 p->nip_val.ni_namelist_val = NULL;
612
613 l->ni_proplist_len++;
614 x++;
615 }
616 else
617 {
618 p = &(l->ni_proplist_val[x]);
619 if (p->nip_val.ni_namelist_len == 0)
620 {
621 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
622 }
623 else
624 {
625 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));
626 }
627 p->nip_val.ni_namelist_val[p->nip_val.ni_namelist_len] = strdup(arg);
628 p->nip_val.ni_namelist_len++;
629 }
630 }
631 va_end(ap);
632
633 return l;
634 }
635
636 void
637 ni_property_merge(ni_property *a, ni_property *b)
638 {
639 int i, j, addme;
640
641 if (a == NULL) return;
642 if (b == NULL) return;
643
644 for (j = 0; j < b->nip_val.ni_namelist_len; j++)
645 {
646 addme = 1;
647 for (i = 0; i < (a->nip_val.ni_namelist_len) && (addme == 1); i++)
648 {
649 if (!strcmp(a->nip_val.ni_namelist_val[i], b->nip_val.ni_namelist_val[j])) addme = 0;
650 }
651
652 if (addme == 1)
653 {
654 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));
655 a->nip_val.ni_namelist_val[a->nip_val.ni_namelist_len] = strdup(b->nip_val.ni_namelist_val[j]);
656 a->nip_val.ni_namelist_len++;
657 }
658 }
659 }
660
661 void
662 ni_proplist_merge(ni_proplist *a, ni_proplist *b)
663 {
664 ni_index wa, wb;
665 int addme;
666
667 if (a == NULL) return;
668 if (b == NULL) return;
669
670 for (wb = 0; wb < b->ni_proplist_len; wb++)
671 {
672 addme = 1;
673 for (wa = 0; (wa < a->ni_proplist_len) && (addme == 1) ; wa++)
674 {
675 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name)) addme = 0;
676 }
677 if (addme == 1)
678 {
679 a->ni_proplist_val = (ni_property *)realloc(a->ni_proplist_val, (a->ni_proplist_len + 1) * sizeof(ni_property));
680 a->ni_proplist_val[a->ni_proplist_len].nip_name = strdup(b->ni_proplist_val[wb].nip_name);
681 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_len = 0;
682 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_val = NULL;
683 a->ni_proplist_len++;
684 }
685 }
686
687 for (wb = 0; wb < b->ni_proplist_len; wb++)
688 {
689 for (wa = 0; wa < a->ni_proplist_len; wa++)
690 {
691 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name))
692 {
693 ni_property_merge(&(a->ni_proplist_val[wa]), &(b->ni_proplist_val[wb]));
694 }
695 }
696 }
697 }
698
699 static void
700 _lu_data_free(void *x)
701 {
702 struct _lu_data_s *t;
703 int i;
704
705 if (x == NULL) return;
706
707 t = (struct _lu_data_s *)x;
708
709 for (i = 0; i < t->icount; i++)
710 {
711 if ((t->idata[i] != NULL) && (t->idata_destructor[i] != NULL))
712 {
713 (*(t->idata_destructor[i]))(t->idata[i]);
714 }
715
716 t->idata[i] = NULL;
717 t->idata_destructor[i] = NULL;
718 }
719
720 if (t->ikey != NULL) free(t->ikey);
721 t->ikey = NULL;
722
723 if (t->idata != NULL) free(t->idata);
724 t->idata = NULL;
725
726 if (t->idata_destructor != NULL) free(t->idata_destructor);
727 t->idata_destructor = NULL;
728
729 free(t);
730 }
731
732 static void
733 _lu_data_init()
734 {
735 pthread_key_create(&_info_key, _lu_data_free);
736 return;
737 }
738
739 static struct _lu_data_s *
740 _lu_data_get()
741 {
742 struct _lu_data_s *libinfo_data;
743
744 /*
745 * Only one thread should create the _info_key
746 */
747 pthread_once(&_info_key_initialized, _lu_data_init);
748
749 /* Check if this thread already created libinfo_data */
750 libinfo_data = pthread_getspecific(_info_key);
751 if (libinfo_data != NULL) return libinfo_data;
752
753 libinfo_data = (struct _lu_data_s *)calloc(1, sizeof(struct _lu_data_s));
754
755 pthread_setspecific(_info_key, libinfo_data);
756 return libinfo_data;
757 }
758
759 void *
760 _lu_data_create_key(unsigned int key, void (*destructor)(void *))
761 {
762 struct _lu_data_s *libinfo_data;
763 unsigned int i, n;
764
765 libinfo_data = _lu_data_get();
766
767 for (i = 0; i < libinfo_data->icount; i++)
768 {
769 if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
770 }
771
772 i = libinfo_data->icount;
773 n = i + 1;
774
775 if (i == 0)
776 {
777 libinfo_data->ikey = (unsigned int *)malloc(sizeof(unsigned int));
778 libinfo_data->idata = (void **)malloc(sizeof(void *));
779 libinfo_data->idata_destructor = (void (**)(void *))malloc(sizeof(void (*)(void *)));
780 }
781 else
782 {
783 libinfo_data->ikey = (unsigned int *)realloc(libinfo_data->ikey, n * sizeof(unsigned int));
784 libinfo_data->idata = (void **)realloc(libinfo_data->idata, n * sizeof(void *));
785 libinfo_data->idata_destructor = (void (**)(void *))realloc(libinfo_data->idata_destructor, n * sizeof(void (*)(void *)));
786 }
787
788 libinfo_data->ikey[i] = key;
789 libinfo_data->idata[i] = NULL;
790 libinfo_data->idata_destructor[i] = destructor;
791 libinfo_data->icount++;
792
793 return NULL;
794 }
795
796 static unsigned int
797 _lu_data_index(unsigned int key, struct _lu_data_s *libinfo_data)
798 {
799 unsigned int i;
800
801 if (libinfo_data == NULL) return (unsigned int)-1;
802
803 for (i = 0; i < libinfo_data->icount; i++)
804 {
805 if (libinfo_data->ikey[i] == key) return i;
806 }
807
808 return (unsigned int)-1;
809 }
810
811 void
812 _lu_data_set_key(unsigned int key, void *data)
813 {
814 struct _lu_data_s *libinfo_data;
815 unsigned int i;
816
817 libinfo_data = _lu_data_get();
818
819 i = _lu_data_index(key, libinfo_data);
820 if (i == (unsigned int)-1) return;
821
822 libinfo_data->idata[i] = data;
823 }
824
825 void *
826 _lu_data_get_key(unsigned int key)
827 {
828 struct _lu_data_s *libinfo_data;
829 unsigned int i;
830
831 libinfo_data = _lu_data_get();
832
833 i = _lu_data_index(key, libinfo_data);
834 if (i == (unsigned int)-1) return NULL;
835
836 return libinfo_data->idata[i];
837 }
838
839 void
840 _lu_data_free_vm_xdr(struct lu_thread_info *tdata)
841 {
842 if (tdata == NULL) return;
843
844 if (tdata->lu_vm != NULL)
845 {
846 vm_deallocate(mach_task_self(), (vm_address_t)tdata->lu_vm, tdata->lu_vm_length);
847 tdata->lu_vm = NULL;
848 }
849 tdata->lu_vm_length = 0;
850 tdata->lu_vm_cursor = 0;
851
852 if (tdata->lu_xdr != NULL)
853 {
854 xdr_destroy(tdata->lu_xdr);
855 free(tdata->lu_xdr);
856 tdata->lu_xdr = NULL;
857 }
858 }
859
860 int
861 _lu_xdr_attribute(XDR *xdr, char **key, char ***val, unsigned int *count)
862 {
863 unsigned int i, j, len;
864 char **x, *s;
865
866 if (xdr == NULL) return -1;
867 if (key == NULL) return -1;
868 if (val == NULL) return -1;
869 if (count == NULL) return -1;
870
871 *key = NULL;
872 *val = NULL;
873 *count = 0;
874
875 if (!xdr_string(xdr, key, -1)) return -1;
876
877 if (!xdr_int(xdr, &len))
878 {
879 free(*key);
880 *key = NULL;
881 return -1;
882 }
883
884 if (len == 0) return 0;
885 *count = len;
886
887 x = (char **)calloc(len + 1, sizeof(char *));
888 *val = x;
889
890 for (i = 0; i < len; i++)
891 {
892 s = NULL;
893 if (!xdr_string(xdr, &s, -1))
894 {
895 for (j = 0; j < i; j++) free(x[j]);
896 free(x);
897 *val = NULL;
898 free(*key);
899 *key = NULL;
900 *count = 0;
901 return -1;
902 }
903 x[i] = s;
904 }
905
906 x[len] = NULL;
907
908 return 0;
909 }
910
911 kern_return_t
912 _lookup_link(mach_port_t server, lookup_name name, int *procno)
913 {
914 kern_return_t status;
915 security_token_t token;
916 unsigned int n;
917
918 token.val[0] = -1;
919 token.val[1] = -1;
920
921 status = MIG_SERVER_DIED;
922 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
923 {
924 status = _lookup_link_secure(server, name, procno, &token);
925 }
926
927 if (status != KERN_SUCCESS)
928 {
929 #ifdef DEBUG
930 syslog(LOG_DEBUG, "pid %u _lookup_link %s status %u", getpid(), name, status);
931 #endif
932 return status;
933 }
934
935 if (token.val[0] != 0)
936 {
937 #ifdef DEBUG
938 syslog(LOG_DEBUG, "pid %u _lookup_link %s auth failure uid=%d", getpid(), name, token.val[0]);
939 #endif
940 return KERN_FAILURE;
941 }
942
943 #ifdef DEBUG
944 syslog(LOG_DEBUG, "pid %u _lookup_link %s = %d", getpid(), name, *procno);
945 #endif
946 return status;
947 }
948
949 kern_return_t
950 _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)
951 {
952 kern_return_t status;
953 security_token_t token;
954 unsigned int n;
955
956 token.val[0] = -1;
957 token.val[1] = -1;
958
959 status = MIG_SERVER_DIED;
960 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
961 {
962 status = _lookup_one_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
963 }
964
965 if (status != KERN_SUCCESS)
966 {
967 #ifdef DEBUG
968 syslog(LOG_DEBUG, "pid %u _lookup_one %d status %u", getpid(), proc, status);
969 #endif
970 return status;
971 }
972
973 if (token.val[0] != 0)
974 {
975 #ifdef DEBUG
976 syslog(LOG_DEBUG, "pid %u _lookup_one %d auth failure uid=%d", getpid(), proc, token.val[0]);
977 #endif
978 return KERN_FAILURE;
979 }
980
981 #ifdef DEBUG
982 syslog(LOG_DEBUG, "pid %u _lookup_one %d", getpid(), proc);
983 #endif
984 return status;
985 }
986
987 kern_return_t
988 _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)
989 {
990 kern_return_t status;
991 security_token_t token;
992 unsigned int n;
993
994 token.val[0] = -1;
995 token.val[1] = -1;
996
997 status = MIG_SERVER_DIED;
998 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
999 {
1000 status = _lookup_all_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
1001 }
1002
1003 if (status != KERN_SUCCESS)
1004 {
1005 #ifdef DEBUG
1006 syslog(LOG_DEBUG, "pid %u _lookup_all %d status %u", getpid(), proc, status);
1007 #endif
1008 return status;
1009 }
1010
1011 if (token.val[0] != 0)
1012 {
1013 #ifdef DEBUG
1014 syslog(LOG_DEBUG, "pid %u _lookup_all %d auth failure uid=%d", getpid(), proc, token.val[0]);
1015 #endif
1016 return KERN_FAILURE;
1017 }
1018
1019 #ifdef DEBUG
1020 syslog(LOG_DEBUG, "pid %u _lookup_all %d", getpid(), proc);
1021 #endif
1022 return status;
1023 }
1024
1025 kern_return_t
1026 _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)
1027 {
1028 kern_return_t status;
1029 security_token_t token;
1030 unsigned int n;
1031
1032 token.val[0] = -1;
1033 token.val[1] = -1;
1034
1035 status = MIG_SERVER_DIED;
1036 for (n = 0; (status == MIG_SERVER_DIED) && (n < MAX_LOOKUP_ATTEMPTS); n++)
1037 {
1038 status = _lookup_ooall_secure(server, proc, indata, indataCnt, outdata, outdataCnt, &token);
1039 }
1040
1041 if (status != KERN_SUCCESS)
1042 {
1043 #ifdef DEBUG
1044 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d status %u", getpid(), proc, status);
1045 #endif
1046 return status;
1047 }
1048
1049 if (token.val[0] != 0)
1050 {
1051 #ifdef DEBUG
1052 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d auth failure uid=%d", getpid(), proc, token.val[0]);
1053 #endif
1054 return KERN_FAILURE;
1055 }
1056
1057 #ifdef DEBUG
1058 syslog(LOG_DEBUG, "pid %u _lookup_ooall %d", getpid(), proc);
1059 #endif
1060 return status;
1061 }