2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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
22 * @APPLE_LICENSE_HEADER_END@
27 #include <mach/mach.h>
32 #include "_lu_types.h"
36 #define MAX_LOOKUP_ATTEMPTS 10
38 static pthread_key_t _info_key
= NULL
;
39 static pthread_once_t _info_key_initialized
= PTHREAD_ONCE_INIT
;
46 void (**idata_destructor
)(void *);
49 #define _LU_MAXLUSTRLEN 256
52 _lookupd_xdr_dictionary(XDR
*inxdr
)
54 int i
, nkeys
, j
, nvals
;
58 if (!xdr_int(inxdr
, &nkeys
)) return NULL
;
60 l
= (ni_proplist
*)malloc(sizeof(ni_proplist
));
63 l
->ni_proplist_len
= nkeys
;
64 l
->ni_proplist_val
= NULL
;
67 i
= nkeys
* sizeof(ni_property
);
68 l
->ni_proplist_val
= (ni_property
*)calloc(1, i
);
71 for (i
= 0; i
< nkeys
; i
++)
74 if (!xdr_string(inxdr
, &key
, -1))
80 l
->ni_proplist_val
[i
].nip_name
= key
;
82 if (!xdr_int(inxdr
, &nvals
))
88 l
->ni_proplist_val
[i
].nip_val
.ni_namelist_len
= nvals
;
91 j
= nvals
* sizeof(ni_name
);
92 l
->ni_proplist_val
[i
].nip_val
.ni_namelist_val
= (ni_name
*)calloc(1, j
);
95 for (j
= 0; j
< nvals
; j
++)
98 if (!xdr_string(inxdr
, &val
, -1))
104 l
->ni_proplist_val
[i
].nip_val
.ni_namelist_val
[j
] = val
;
112 lookupd_query(ni_proplist
*l
, ni_proplist
***out
)
119 char databuf
[_LU_MAXLUSTRLEN
* BYTES_PER_XDR_UNIT
];
121 kern_return_t status
;
124 if (l
== NULL
) return 0;
125 if (out
== NULL
) return 0;
127 if (_lu_port
== NULL
) return 0;
129 status
= _lookup_link(_lu_port
, "query", &proc
);
130 if (status
!= KERN_SUCCESS
) return 0;
132 xdrmem_create(&outxdr
, databuf
, sizeof(databuf
), XDR_ENCODE
);
134 na
= l
->ni_proplist_len
;
136 /* Encode attribute count */
137 if (!xdr_int(&outxdr
, &na
))
139 xdr_destroy(&outxdr
);
143 for (i
= 0; i
< l
->ni_proplist_len
; i
++)
145 p
= &(l
->ni_proplist_val
[i
]);
147 if (!xdr_string(&outxdr
, &s
, _LU_MAXLUSTRLEN
))
149 xdr_destroy(&outxdr
);
154 if (!xdr_int(&outxdr
, &(p
->nip_val
.ni_namelist_len
)))
156 xdr_destroy(&outxdr
);
160 for (j
= 0; j
< p
->nip_val
.ni_namelist_len
; j
++)
163 if (!xdr_string(&outxdr
, &s
, _LU_MAXLUSTRLEN
))
165 xdr_destroy(&outxdr
);
168 p
->nip_val
.ni_namelist_val
[j
] = s
;
175 n
= xdr_getpos(&outxdr
) / BYTES_PER_XDR_UNIT
;
176 status
= _lookup_all(_lu_port
, proc
, (unit
*)databuf
, n
, &listbuf
, &datalen
);
177 if (status
!= KERN_SUCCESS
)
179 xdr_destroy(&outxdr
);
183 xdr_destroy(&outxdr
);
186 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
187 datalen
*= BYTES_PER_XDR_UNIT
;
190 xdrmem_create(&inxdr
, listbuf
, datalen
, XDR_DECODE
);
192 if (!xdr_int(&inxdr
, &n
))
204 *out
= (ni_proplist
**)malloc(n
* sizeof(ni_proplist
*));
206 for (i
= 0; i
< n
; i
++)
208 (*out
)[i
] = _lookupd_xdr_dictionary(&inxdr
);
213 vm_deallocate(mach_task_self(), (vm_address_t
)listbuf
, datalen
);
219 lookupd_make_query(char *cat
, char *fmt
, ...)
227 if (fmt
== NULL
) return NULL
;
228 if (fmt
[0] != 'k') return NULL
;
230 l
= (ni_proplist
*)malloc(sizeof(ni_proplist
));
238 l
->ni_proplist_val
= (ni_property
*)malloc(sizeof(ni_property
));
239 p
= &(l
->ni_proplist_val
[0]);
240 arg
= "_lookup_category";
241 p
->nip_name
= strdup(arg
);
242 p
->nip_val
.ni_namelist_len
= 1;
243 p
->nip_val
.ni_namelist_val
= (ni_name
*)malloc(sizeof(ni_name
));
244 p
->nip_val
.ni_namelist_val
[0] = strdup(cat
);
246 l
->ni_proplist_len
++;
251 for (f
= fmt
; *f
!= NULL
; f
++)
253 arg
= va_arg(ap
, char *);
256 l
->ni_proplist_val
= (ni_property
*)realloc(l
->ni_proplist_val
, (l
->ni_proplist_len
+ 1) * sizeof(ni_property
));
258 p
= &(l
->ni_proplist_val
[l
->ni_proplist_len
]);
259 p
->nip_name
= strdup(arg
);
260 p
->nip_val
.ni_namelist_len
= 0;
261 p
->nip_val
.ni_namelist_val
= NULL
;
263 l
->ni_proplist_len
++;
268 p
= &(l
->ni_proplist_val
[x
]);
269 if (p
->nip_val
.ni_namelist_len
== 0)
271 p
->nip_val
.ni_namelist_val
= (ni_name
*)malloc(sizeof(ni_name
));
275 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
));
277 p
->nip_val
.ni_namelist_val
[p
->nip_val
.ni_namelist_len
] = strdup(arg
);
278 p
->nip_val
.ni_namelist_len
++;
287 ni_property_merge(ni_property
*a
, ni_property
*b
)
291 if (a
== NULL
) return;
292 if (b
== NULL
) return;
294 for (j
= 0; j
< b
->nip_val
.ni_namelist_len
; j
++)
297 for (i
= 0; i
< (a
->nip_val
.ni_namelist_len
) && (addme
== 1); i
++)
299 if (!strcmp(a
->nip_val
.ni_namelist_val
[i
], b
->nip_val
.ni_namelist_val
[j
])) addme
= 0;
304 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
));
305 a
->nip_val
.ni_namelist_val
[a
->nip_val
.ni_namelist_len
] = strdup(b
->nip_val
.ni_namelist_val
[j
]);
306 a
->nip_val
.ni_namelist_len
++;
312 ni_proplist_merge(ni_proplist
*a
, ni_proplist
*b
)
317 if (a
== NULL
) return;
318 if (b
== NULL
) return;
320 for (wb
= 0; wb
< b
->ni_proplist_len
; wb
++)
323 for (wa
= 0; (wa
< a
->ni_proplist_len
) && (addme
== 1) ; wa
++)
325 if (!strcmp(a
->ni_proplist_val
[wa
].nip_name
, b
->ni_proplist_val
[wb
].nip_name
)) addme
= 0;
329 a
->ni_proplist_val
= (ni_property
*)realloc(a
->ni_proplist_val
, (a
->ni_proplist_len
+ 1) * sizeof(ni_property
));
330 a
->ni_proplist_val
[a
->ni_proplist_len
].nip_name
= strdup(b
->ni_proplist_val
[wb
].nip_name
);
331 a
->ni_proplist_val
[a
->ni_proplist_len
].nip_val
.ni_namelist_len
= 0;
332 a
->ni_proplist_val
[a
->ni_proplist_len
].nip_val
.ni_namelist_val
= NULL
;
333 a
->ni_proplist_len
++;
337 for (wb
= 0; wb
< b
->ni_proplist_len
; wb
++)
339 for (wa
= 0; wa
< a
->ni_proplist_len
; wa
++)
341 if (!strcmp(a
->ni_proplist_val
[wa
].nip_name
, b
->ni_proplist_val
[wb
].nip_name
))
343 ni_property_merge(&(a
->ni_proplist_val
[wa
]), &(b
->ni_proplist_val
[wb
]));
350 _lu_data_free(void *x
)
352 struct _lu_data_s
*t
;
355 if (x
== NULL
) return;
357 t
= (struct _lu_data_s
*)x
;
359 for (i
= 0; i
< t
->icount
; i
++)
361 if ((t
->idata
[i
] != NULL
) && (t
->idata_destructor
[i
] != NULL
))
363 (*(t
->idata_destructor
[i
]))(t
->idata
[i
]);
367 t
->idata_destructor
[i
] = NULL
;
370 if (t
->ikey
!= NULL
) free(t
->ikey
);
373 if (t
->idata
!= NULL
) free(t
->idata
);
376 if (t
->idata_destructor
!= NULL
) free(t
->idata_destructor
);
377 t
->idata_destructor
= NULL
;
385 pthread_key_create(&_info_key
, _lu_data_free
);
389 static struct _lu_data_s
*
392 struct _lu_data_s
*libinfo_data
;
395 * Only one thread should create the _info_key
397 pthread_once(&_info_key_initialized
, _lu_data_init
);
399 /* Check if this thread already created libinfo_data */
400 libinfo_data
= pthread_getspecific(_info_key
);
401 if (libinfo_data
!= NULL
) return libinfo_data
;
403 libinfo_data
= (struct _lu_data_s
*)calloc(1, sizeof(struct _lu_data_s
));
405 pthread_setspecific(_info_key
, libinfo_data
);
410 _lu_data_create_key(unsigned int key
, void (*destructor
)(void *))
412 struct _lu_data_s
*libinfo_data
;
415 libinfo_data
= _lu_data_get();
417 for (i
= 0; i
< libinfo_data
->icount
; i
++)
419 if (libinfo_data
->ikey
[i
] == key
) return libinfo_data
->idata
[i
];
422 i
= libinfo_data
->icount
;
427 libinfo_data
->ikey
= (unsigned int *)malloc(sizeof(unsigned int));
428 libinfo_data
->idata
= (void **)malloc(sizeof(void *));
429 libinfo_data
->idata_destructor
= (void (**)(void *))malloc(sizeof(void (*)(void *)));
433 libinfo_data
->ikey
= (unsigned int *)realloc(libinfo_data
->ikey
, n
* sizeof(unsigned int));
434 libinfo_data
->idata
= (void **)realloc(libinfo_data
->idata
, n
* sizeof(void *));
435 libinfo_data
->idata_destructor
= (void (**)(void *))realloc(libinfo_data
->idata_destructor
, n
* sizeof(void (*)(void *)));
438 libinfo_data
->ikey
[i
] = key
;
439 libinfo_data
->idata
[i
] = NULL
;
440 libinfo_data
->idata_destructor
[i
] = destructor
;
441 libinfo_data
->icount
++;
447 _lu_data_index(unsigned int key
, struct _lu_data_s
*libinfo_data
)
451 if (libinfo_data
== NULL
) return (unsigned int)-1;
453 for (i
= 0; i
< libinfo_data
->icount
; i
++)
455 if (libinfo_data
->ikey
[i
] == key
) return i
;
458 return (unsigned int)-1;
462 _lu_data_set_key(unsigned int key
, void *data
)
464 struct _lu_data_s
*libinfo_data
;
467 libinfo_data
= _lu_data_get();
469 i
= _lu_data_index(key
, libinfo_data
);
470 if (i
== (unsigned int)-1) return;
472 libinfo_data
->idata
[i
] = data
;
476 _lu_data_get_key(unsigned int key
)
478 struct _lu_data_s
*libinfo_data
;
481 libinfo_data
= _lu_data_get();
483 i
= _lu_data_index(key
, libinfo_data
);
484 if (i
== (unsigned int)-1) return NULL
;
486 return libinfo_data
->idata
[i
];
490 _lu_data_free_vm_xdr(struct lu_thread_info
*tdata
)
492 if (tdata
== NULL
) return;
494 if (tdata
->lu_vm
!= NULL
)
496 vm_deallocate(mach_task_self(), (vm_address_t
)tdata
->lu_vm
, tdata
->lu_vm_length
);
499 tdata
->lu_vm_length
= 0;
500 tdata
->lu_vm_cursor
= 0;
502 if (tdata
->lu_xdr
!= NULL
)
504 xdr_destroy(tdata
->lu_xdr
);
506 tdata
->lu_xdr
= NULL
;
511 _lu_xdr_attribute(XDR
*xdr
, char **key
, char ***val
, unsigned int *count
)
513 unsigned int i
, j
, len
;
516 if (xdr
== NULL
) return -1;
517 if (key
== NULL
) return -1;
518 if (val
== NULL
) return -1;
519 if (count
== NULL
) return -1;
525 if (!xdr_string(xdr
, key
, -1)) return -1;
527 if (!xdr_int(xdr
, &len
))
534 if (len
== 0) return 0;
537 x
= (char **)calloc(len
+ 1, sizeof(char *));
540 for (i
= 0; i
< len
; i
++)
543 if (!xdr_string(xdr
, &s
, -1))
545 for (j
= 0; j
< i
; j
++) free(x
[j
]);
562 _lookup_link(mach_port_t server
, lookup_name name
, int *procno
)
564 kern_return_t status
;
565 security_token_t token
;
571 status
= MIG_SERVER_DIED
;
572 for (n
= 0; (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
574 status
= _lookup_link_secure(server
, name
, procno
, &token
);
577 if (status
!= KERN_SUCCESS
)
580 syslog(LOG_DEBUG
, "pid %u _lookup_link %s status %u", getpid(), name
, status
);
585 if (token
.val
[0] != 0)
588 syslog(LOG_DEBUG
, "pid %u _lookup_link %s auth failure uid=%d", getpid(), name
, token
.val
[0]);
594 syslog(LOG_DEBUG
, "pid %u _lookup_link %s = %d", getpid(), name
, *procno
);
600 _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
)
602 kern_return_t status
;
603 security_token_t token
;
609 status
= MIG_SERVER_DIED
;
610 for (n
= 0; (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
612 status
= _lookup_one_secure(server
, proc
, indata
, indataCnt
, outdata
, outdataCnt
, &token
);
615 if (status
!= KERN_SUCCESS
)
618 syslog(LOG_DEBUG
, "pid %u _lookup_one %d status %u", getpid(), proc
, status
);
623 if (token
.val
[0] != 0)
626 syslog(LOG_DEBUG
, "pid %u _lookup_one %d auth failure uid=%d", getpid(), proc
, token
.val
[0]);
632 syslog(LOG_DEBUG
, "pid %u _lookup_one %d", getpid(), proc
);
638 _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
)
640 kern_return_t status
;
641 security_token_t token
;
647 status
= MIG_SERVER_DIED
;
648 for (n
= 0; (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
650 status
= _lookup_all_secure(server
, proc
, indata
, indataCnt
, outdata
, outdataCnt
, &token
);
653 if (status
!= KERN_SUCCESS
)
656 syslog(LOG_DEBUG
, "pid %u _lookup_all %d status %u", getpid(), proc
, status
);
661 if (token
.val
[0] != 0)
664 syslog(LOG_DEBUG
, "pid %u _lookup_all %d auth failure uid=%d", getpid(), proc
, token
.val
[0]);
670 syslog(LOG_DEBUG
, "pid %u _lookup_all %d", getpid(), proc
);
676 _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
)
678 kern_return_t status
;
679 security_token_t token
;
685 status
= MIG_SERVER_DIED
;
686 for (n
= 0; (status
== MIG_SERVER_DIED
) && (n
< MAX_LOOKUP_ATTEMPTS
); n
++)
688 status
= _lookup_ooall_secure(server
, proc
, indata
, indataCnt
, outdata
, outdataCnt
, &token
);
691 if (status
!= KERN_SUCCESS
)
694 syslog(LOG_DEBUG
, "pid %u _lookup_ooall %d status %u", getpid(), proc
, status
);
699 if (token
.val
[0] != 0)
702 syslog(LOG_DEBUG
, "pid %u _lookup_ooall %d auth failure uid=%d", getpid(), proc
, token
.val
[0]);
708 syslog(LOG_DEBUG
, "pid %u _lookup_ooall %d", getpid(), proc
);