2 * Copyright (c) 1999-2004 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.0 (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@
25 * bootstrap -- fundamental service initiator and port server
26 * Mike DeMoney, NeXT, Inc.
27 * Copyright, 1990. All rights reserved.
29 * rpc_services.c -- implementation of bootstrap rpc services
32 #include <mach/mach.h>
33 #include <mach/mach_error.h>
37 #include <bsm/audit.h>
38 #include <bsm/libbsm.h>
40 #include "bootstrap_internal.h"
42 #include "bootstrap.h"
49 #define NULL ((void *)0)
52 #define bsstatus(servicep) \
53 (((servicep)->isActive) ? BOOTSTRAP_STATUS_ACTIVE : \
54 (((servicep)->server && (servicep)->server->servertype == DEMAND) ? \
55 BOOTSTRAP_STATUS_ON_DEMAND : BOOTSTRAP_STATUS_INACTIVE))
57 /* extern port_all_t backup_port; */
61 * bootstrap_create_server(mach_port_t bootstrap_port,
63 * integer_t server_uid,
64 * boolean_t on_demand,
65 * mach_port_t *server_portp)
67 * Returns send rights to server_port of service. At this point, the
68 * server appears active, so nothing will try to launch it. The server_port
69 * can be used to delare services associated with this server by calling
70 * bootstrap_create_service() and passing server_port as the bootstrap port.
72 * Errors: Returns appropriate kernel errors on rpc failure.
73 * Returns BOOTSTRAP_NOT_PRIVILEGED, if bootstrap port invalid.
75 __private_extern__ kern_return_t
76 x_bootstrap_create_server(
77 mach_port_t bootstrapport
,
81 audit_token_t client_audit_token
,
82 mach_port_t
*server_portp
)
85 struct auditinfo audit_info
;
86 bootstrap_info_t
*bootstrap
;
90 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
91 syslog(LOG_DEBUG
, "Server create attempt: \"%s\" bootstrap %x",
92 server_cmd
, bootstrapport
);
94 /* No forwarding allowed for this call - security risk (we run as root) */
95 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
96 syslog(LOG_DEBUG
, "Server create: \"%s\": invalid bootstrap %x",
97 server_cmd
, bootstrapport
);
98 return BOOTSTRAP_NOT_PRIVILEGED
;
101 /* get the identity of the requestor and set up audit_info of server */
102 audit_token_to_au32(client_audit_token
,
110 &audit_info
.ai_termid
);
112 if (client_euid
!= 0 && client_euid
!= server_uid
) {
113 syslog(LOG_NOTICE
, "Server create: \"%s\": insufficient privilege for specified uid (euid-%d != requested-%d)",
114 server_cmd
, client_euid
, server_uid
);
115 return BOOTSTRAP_NOT_PRIVILEGED
;
118 serverp
= new_server(
122 (on_demand
) ? DEMAND
: RESTARTABLE
,
124 setup_server(serverp
);
126 syslog(LOG_INFO
, "New server %x in bootstrap %x: \"%s\"",
127 serverp
->port
, bootstrapport
, server_cmd
);
128 *server_portp
= serverp
->port
;
129 return BOOTSTRAP_SUCCESS
;
134 * bootstrap_unprivileged(mach_port_t bootstrapport,
135 * mach_port_t *unprivportp)
137 * Given a bootstrap port, return its unprivileged equivalent. If
138 * the port is already unprivileged, another reference to the same
141 * This is most often used by servers, which are launched with their
142 * bootstrap port set to the privileged port for the server, to get
143 * an unprivileged version of the same port for use by its unprivileged
144 * children (or any offspring that it does not want to count as part
145 * of the "server" for mach_init registration and re-launch purposes).
147 __private_extern__ kern_return_t
148 x_bootstrap_unprivileged(
149 mach_port_t bootstrapport
,
150 mach_port_t
*unprivportp
)
152 bootstrap_info_t
*bootstrap
;
154 syslog(LOG_DEBUG
, "Get unprivileged attempt for bootstrap %x", bootstrapport
);
156 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
158 syslog(LOG_DEBUG
, "Get unprivileged: invalid bootstrap %x", bootstrapport
);
159 return BOOTSTRAP_NOT_PRIVILEGED
;
162 *unprivportp
= bootstrap
->bootstrap_port
;
164 syslog(LOG_DEBUG
, "Get unpriv bootstrap %x returned for bootstrap %x",
165 bootstrap
->bootstrap_port
, bootstrapport
);
166 return BOOTSTRAP_SUCCESS
;
172 * bootstrap_check_in(mach_port_t bootstrapport,
173 * name_t servicename,
174 * mach_port_t *serviceportp)
176 * Returns receive rights to service_port of service named by service_name.
178 * Errors: Returns appropriate kernel errors on rpc failure.
179 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
180 * Returns BOOTSTRAP_SERVICE_NOT_DECLARED, if service not declared
181 * in /etc/bootstrap.conf.
182 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
183 * registered or checked-in.
185 __private_extern__ kern_return_t
186 x_bootstrap_check_in(
187 mach_port_t bootstrapport
,
189 mach_port_t
*serviceportp
)
191 kern_return_t result
;
192 mach_port_t previous
;
195 bootstrap_info_t
*bootstrap
;
197 serverp
= lookup_server_by_port(bootstrapport
);
198 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
199 syslog(LOG_DEBUG
, "Service checkin attempt for service %s bootstrap %x",
200 servicename
, bootstrapport
);
202 servicep
= lookup_service_by_name(bootstrap
, servicename
);
203 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
204 syslog(LOG_DEBUG
, "bootstrap_check_in service %s unknown%s", servicename
,
205 forward_ok
? " forwarding" : "");
208 inherited_bootstrap_port
,
211 BOOTSTRAP_UNKNOWN_SERVICE
;
213 if (servicep
->server
!= NULL
&& servicep
->server
!= serverp
) {
214 syslog(LOG_DEBUG
, "bootstrap_check_in service %s not privileged",
216 return BOOTSTRAP_NOT_PRIVILEGED
;
218 if (!canReceive(servicep
->port
)) {
219 ASSERT(servicep
->isActive
);
220 syslog(LOG_DEBUG
, "bootstrap_check_in service %s already active",
222 return BOOTSTRAP_SERVICE_ACTIVE
;
224 syslog(LOG_DEBUG
, "Checkin service %s for bootstrap %x", servicename
,
225 bootstrap
->bootstrap_port
);
226 ASSERT(servicep
->isActive
== FALSE
);
227 servicep
->isActive
= TRUE
;
229 if (servicep
->server
!= NULL_SERVER
) {
230 /* registered server - service needs backup */
232 serverp
->active_services
++;
233 result
= mach_port_request_notification(
236 MACH_NOTIFY_PORT_DESTROYED
,
239 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
241 if (result
!= KERN_SUCCESS
)
242 panic("mach_port_request_notification(): %s", mach_error_string(result
));
244 /* one time use/created service */
245 servicep
->servicetype
= REGISTERED
;
246 result
= mach_port_request_notification(
249 MACH_NOTIFY_DEAD_NAME
,
252 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
254 if (result
!= KERN_SUCCESS
)
255 panic("mach_port_request_notification(): %s", mach_error_string(result
));
256 else if (previous
!= MACH_PORT_NULL
) {
257 syslog(LOG_DEBUG
, "deallocating old notification port (%x) for checked in service %x",
258 previous
, servicep
->port
);
259 result
= mach_port_deallocate(
262 if (result
!= KERN_SUCCESS
)
263 panic("mach_port_deallocate(): %s", mach_error_string(result
));
267 syslog(LOG_INFO
, "Check-in service %x in bootstrap %x: %s",
268 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
270 *serviceportp
= servicep
->port
;
271 return BOOTSTRAP_SUCCESS
;
276 * bootstrap_register(mach_port_t bootstrapport,
277 * name_t servicename,
278 * mach_port_t serviceport)
280 * Registers send rights for the port service_port for the service named by
281 * service_name. Registering a declared service or registering a service for
282 * which bootstrap has receive rights via a port backup notification is
284 * The previous service port will be deallocated. Restarting services wishing
285 * to resume service for previous clients must first attempt to checkin to the
288 * Errors: Returns appropriate kernel errors on rpc failure.
289 * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
290 * unprivileged bootstrap port.
291 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
292 * register or checked-in.
294 __private_extern__ kern_return_t
295 x_bootstrap_register(
296 mach_port_t bootstrapport
,
298 mach_port_t serviceport
)
300 kern_return_t result
;
303 bootstrap_info_t
*bootstrap
;
304 mach_port_t old_port
;
306 syslog(LOG_DEBUG
, "Register attempt for service %s port %x",
307 servicename
, serviceport
);
310 * Validate the bootstrap.
312 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
313 if (!bootstrap
|| !active_bootstrap(bootstrap
))
314 return BOOTSTRAP_NOT_PRIVILEGED
;
317 * If this bootstrap port is for a server, or it's an unprivileged
318 * bootstrap can't register the port.
320 serverp
= lookup_server_by_port(bootstrapport
);
321 servicep
= lookup_service_by_name(bootstrap
, servicename
);
322 if (servicep
&& servicep
->server
&& servicep
->server
!= serverp
)
323 return BOOTSTRAP_NOT_PRIVILEGED
;
325 if (servicep
== NULL
|| servicep
->bootstrap
!= bootstrap
) {
326 servicep
= new_service(bootstrap
,
332 syslog(LOG_DEBUG
, "Registered new service %s", servicename
);
334 if (servicep
->isActive
) {
335 syslog(LOG_DEBUG
, "Register: service %s already active, port %x",
336 servicep
->name
, servicep
->port
);
337 ASSERT(!canReceive(servicep
->port
));
338 return BOOTSTRAP_SERVICE_ACTIVE
;
340 old_port
= servicep
->port
;
341 if (servicep
->servicetype
== DECLARED
) {
342 servicep
->servicetype
= REGISTERED
;
344 if (servicep
->server
) {
345 ASSERT(servicep
->server
== serverp
);
346 ASSERT(active_server(serverp
));
347 servicep
->server
= NULL_SERVER
;
351 result
= mach_port_mod_refs(
354 MACH_PORT_RIGHT_RECEIVE
,
356 if (result
!= KERN_SUCCESS
)
357 panic("mach_port_mod_refs(): %s", mach_error_string(result
));
359 result
= mach_port_deallocate(
362 if (result
!= KERN_SUCCESS
)
363 panic("mach_port_mod_refs(): %s", mach_error_string(result
));
365 servicep
->port
= serviceport
;
366 servicep
->isActive
= TRUE
;
367 syslog(LOG_DEBUG
, "Re-registered inactive service %x bootstrap %x: %s",
368 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicename
);
371 /* detect the new service port going dead */
372 result
= mach_port_request_notification(
375 MACH_NOTIFY_DEAD_NAME
,
378 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
380 if (result
!= KERN_SUCCESS
) {
381 syslog(LOG_DEBUG
, "Can't request notification on service %x bootstrap %x: %s",
382 service_port
, servicep
->bootstrap
->bootstrap_port
, "must be dead");
383 delete_service(servicep
);
384 return BOOTSTRAP_SUCCESS
;
385 } else if (old_port
!= MACH_PORT_NULL
) {
386 syslog(LOG_DEBUG
, "deallocating old notification port (%x) for service %x",
387 old_port
, serviceport
);
388 result
= mach_port_deallocate(
391 if (result
!= KERN_SUCCESS
)
392 panic("mach_port_deallocate(): %s", mach_error_string(result
));
394 syslog(LOG_INFO
, "Registered service %x bootstrap %x: %s",
395 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
396 return BOOTSTRAP_SUCCESS
;
401 * bootstrap_look_up(mach_port_t bootstrapport,
402 * name_t servicename,
403 * mach_port_t *serviceportp)
405 * Returns send rights for the service port of the service named by
406 * service_name in *service_portp. Service is not guaranteed to be active.
408 * Errors: Returns appropriate kernel errors on rpc failure.
409 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
411 __private_extern__ kern_return_t
413 mach_port_t bootstrapport
,
415 mach_port_t
*serviceportp
)
418 bootstrap_info_t
*bootstrap
;
420 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
421 servicep
= lookup_service_by_name(bootstrap
, servicename
);
422 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
424 syslog(LOG_DEBUG
, "bootstrap_look_up service %s forwarding",
426 return bootstrap_look_up(inherited_bootstrap_port
,
430 syslog(LOG_DEBUG
, "bootstrap_look_up service %s unknown",
432 return BOOTSTRAP_UNKNOWN_SERVICE
;
435 *serviceportp
= servicep
->port
;
436 syslog(LOG_DEBUG
, "Lookup returns port %x for service %s", servicep
->port
, servicep
->name
);
437 return BOOTSTRAP_SUCCESS
;
442 * bootstrap_look_up_array(mach_port_t bootstrapport,
443 * name_array_t servicenames,
444 * int servicenames_cnt,
445 * mach_port_array_t *serviceports,
446 * int *serviceports_cnt,
447 * boolean_t *allservices_known)
449 * Returns port send rights in corresponding entries of the array service_ports
450 * for all services named in the array service_names. Service_ports_cnt is
451 * returned and will always equal service_names_cnt (assuming service_names_cnt
452 * is greater than or equal to zero).
454 * Errors: Returns appropriate kernel errors on rpc failure.
455 * Returns BOOTSTRAP_NO_MEMORY, if server couldn't obtain memory
457 * Unknown service names have the corresponding service
458 * port set to MACH_PORT_NULL.
459 * If all services are known, all_services_known is true on
461 * if any service is unknown, it's false.
463 __private_extern__ kern_return_t
464 x_bootstrap_look_up_array(
465 mach_port_t bootstrapport
,
466 name_array_t servicenames
,
467 unsigned int servicenames_cnt
,
468 mach_port_array_t
*serviceportsp
,
469 unsigned int *serviceports_cnt
,
470 boolean_t
*allservices_known
)
473 static mach_port_t service_ports
[BOOTSTRAP_MAX_LOOKUP_COUNT
];
475 if (servicenames_cnt
> BOOTSTRAP_MAX_LOOKUP_COUNT
)
476 return BOOTSTRAP_BAD_COUNT
;
477 *serviceports_cnt
= servicenames_cnt
;
478 *allservices_known
= TRUE
;
479 for (i
= 0; i
< servicenames_cnt
; i
++) {
480 if ( x_bootstrap_look_up(bootstrapport
,
483 != BOOTSTRAP_SUCCESS
)
485 *allservices_known
= FALSE
;
486 service_ports
[i
] = MACH_PORT_NULL
;
489 syslog(LOG_DEBUG
, "bootstrap_look_up_array returns %d ports", servicenames_cnt
);
490 *serviceportsp
= service_ports
;
491 return BOOTSTRAP_SUCCESS
;
496 * bootstrap_parent(mach_port_t bootstrapport,
497 * mach_port_t *parentport);
499 * Given a bootstrap subset port, return the parent bootstrap port.
500 * If the specified bootstrap port is already the root subset,
501 * MACH_PORT_NULL will be returned.
504 * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
505 * with an effective user id of root (as determined by the security
506 * token in the message trailer).
508 __private_extern__ kern_return_t
510 mach_port_t bootstrapport
,
511 security_token_t sectoken
,
512 mach_port_t
*parentport
)
514 bootstrap_info_t
*bootstrap
;
516 syslog(LOG_DEBUG
, "Parent attempt for bootstrap %x", bootstrapport
);
518 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
520 syslog(LOG_DEBUG
, "Parent attempt for bootstrap %x: invalid bootstrap",
522 return BOOTSTRAP_NOT_PRIVILEGED
;
524 if (sectoken
.val
[0]) {
525 syslog(LOG_NOTICE
, "Bootstrap parent for bootstrap %x: invalid security token (%d)",
526 bootstrapport
, sectoken
.val
[0]);
527 return BOOTSTRAP_NOT_PRIVILEGED
;
529 syslog(LOG_DEBUG
, "Returning bootstrap parent %x for bootstrap %x",
530 bootstrap
->parent
->bootstrap_port
, bootstrapport
);
531 *parentport
= bootstrap
->parent
->bootstrap_port
;
532 return BOOTSTRAP_SUCCESS
;
537 * bootstrap_status(mach_port_t bootstrapport,
538 * name_t servicename,
539 * bootstrap_status_t *serviceactive);
541 * Returns: service_active indicates if service is available.
543 * Errors: Returns appropriate kernel errors on rpc failure.
544 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
546 __private_extern__ kern_return_t
548 mach_port_t bootstrapport
,
550 bootstrap_status_t
*serviceactivep
)
553 bootstrap_info_t
*bootstrap
;
555 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
556 servicep
= lookup_service_by_name(bootstrap
, servicename
);
557 if (servicep
== NULL
) {
559 syslog(LOG_DEBUG
, "bootstrap_status forwarding status, server %s",
561 return bootstrap_status(inherited_bootstrap_port
,
565 syslog(LOG_DEBUG
, "bootstrap_status service %s unknown",
567 return BOOTSTRAP_UNKNOWN_SERVICE
;
570 *serviceactivep
= bsstatus(servicep
);
572 syslog(LOG_DEBUG
, "bootstrap_status server %s %sactive", servicename
,
573 servicep
->isActive
? "" : "in");
574 return BOOTSTRAP_SUCCESS
;
579 * bootstrap_info(mach_port_t bootstrapport,
580 * name_array_t *servicenamesp,
581 * int *servicenames_cnt,
582 * name_array_t *servernamesp,
583 * int *servernames_cnt,
584 * bootstrap_status_array_t *serviceactivesp,
585 * int *serviceactive_cnt);
587 * Returns bootstrap status for all known services.
589 * Errors: Returns appropriate kernel errors on rpc failure.
591 __private_extern__ kern_return_t
593 mach_port_t bootstrapport
,
594 name_array_t
*servicenamesp
,
595 unsigned int *servicenames_cnt
,
596 name_array_t
*servernamesp
,
597 unsigned int *servernames_cnt
,
598 bootstrap_status_array_t
*serviceactivesp
,
599 unsigned int *serviceactives_cnt
)
601 kern_return_t result
;
605 bootstrap_info_t
*bootstrap
;
606 name_array_t service_names
;
607 name_array_t server_names
;
608 bootstrap_status_array_t service_actives
;
610 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
612 for ( cnt
= i
= 0, servicep
= services
.next
614 ; servicep
= servicep
->next
, i
++)
616 if (lookup_service_by_name(bootstrap
, servicep
->name
) == servicep
)
621 result
= vm_allocate(mach_task_self(),
622 (vm_address_t
*)&service_names
,
623 cnt
* sizeof(service_names
[0]),
625 if (result
!= KERN_SUCCESS
)
626 return BOOTSTRAP_NO_MEMORY
;
628 result
= vm_allocate(mach_task_self(),
629 (vm_address_t
*)&server_names
,
630 cnt
* sizeof(server_names
[0]),
632 if (result
!= KERN_SUCCESS
) {
633 (void)vm_deallocate(mach_task_self(),
634 (vm_address_t
)service_names
,
635 cnt
* sizeof(service_names
[0]));
636 return BOOTSTRAP_NO_MEMORY
;
638 result
= vm_allocate(mach_task_self(),
639 (vm_address_t
*)&service_actives
,
640 cnt
* sizeof(service_actives
[0]),
642 if (result
!= KERN_SUCCESS
) {
643 (void)vm_deallocate(mach_task_self(),
644 (vm_address_t
)service_names
,
645 cnt
* sizeof(service_names
[0]));
646 (void)vm_deallocate(mach_task_self(),
647 (vm_address_t
)server_names
,
648 cnt
* sizeof(server_names
[0]));
649 return BOOTSTRAP_NO_MEMORY
;
652 for ( i
= 0, servicep
= services
.next
654 ; servicep
= servicep
->next
)
656 if ( lookup_service_by_name(bootstrap
, servicep
->name
)
659 strncpy(service_names
[i
],
661 sizeof(service_names
[0]));
662 service_names
[i
][sizeof(service_names
[0]) - 1] = '\0';
663 if (servicep
->server
) {
664 serverp
= servicep
->server
;
665 strncpy(server_names
[i
],
667 sizeof(server_names
[0]));
668 server_names
[i
][sizeof(server_names
[0]) - 1] = '\0';
669 syslog(LOG_DEBUG
, "bootstrap info service %s server %s %sactive",
671 serverp
->cmd
, servicep
->isActive
? "" : "in");
673 server_names
[i
][0] = '\0';
674 syslog(LOG_DEBUG
, "bootstrap info service %s %sactive",
675 servicep
->name
, servicep
->isActive
? "" : "in");
677 service_actives
[i
] = bsstatus(servicep
);
680 *servicenamesp
= service_names
;
681 *servernamesp
= server_names
;
682 *serviceactivesp
= service_actives
;
683 *servicenames_cnt
= *servernames_cnt
= *serviceactives_cnt
= cnt
;
685 return BOOTSTRAP_SUCCESS
;
690 * bootstrap_subset(mach_port_t bootstrapport,
691 * mach_port_t requestorport,
692 * mach_port_t *subsetport);
694 * Returns a new port to use as a bootstrap port. This port behaves
695 * exactly like the previous bootstrap_port, except that ports dynamically
696 * registered via bootstrap_register() are available only to users of this
697 * specific subset_port. Lookups on the subset_port will return ports
698 * registered with this port specifically, and ports registered with
699 * ancestors of this subset_port. Duplications of services already
700 * registered with an ancestor port may be registered with the subset port
701 * are allowed. Services already advertised may then be effectively removed
702 * by registering MACH_PORT_NULL for the service.
703 * When it is detected that the requestor_port is destroied the subset
704 * port and all services advertized by it are destroied as well.
706 * Errors: Returns appropriate kernel errors on rpc failure.
708 __private_extern__ kern_return_t
710 mach_port_t bootstrapport
,
711 mach_port_t requestorport
,
712 mach_port_t
*subsetportp
)
714 kern_return_t result
;
715 bootstrap_info_t
*bootstrap
;
716 bootstrap_info_t
*subset
;
717 mach_port_t new_bootstrapport
;
718 mach_port_t previous
;
720 syslog(LOG_DEBUG
, "Subset create attempt: bootstrap %x, requestor: %x",
721 bootstrapport
, requestorport
);
723 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
724 if (!bootstrap
|| !active_bootstrap(bootstrap
))
725 return BOOTSTRAP_NOT_PRIVILEGED
;
727 result
= mach_port_allocate(
729 MACH_PORT_RIGHT_RECEIVE
,
731 if (result
!= KERN_SUCCESS
)
732 panic("mach_port_allocate(): %s", mach_error_string(result
));
734 result
= mach_port_insert_right(
738 MACH_MSG_TYPE_MAKE_SEND
);
739 if (result
!= KERN_SUCCESS
)
740 panic("failed to insert send right(): %s", mach_error_string(result
));
742 result
= mach_port_insert_member(
746 if (result
!= KERN_SUCCESS
)
747 panic("port_set_add(): %s", mach_error_string(result
));
749 subset
= new_bootstrap(bootstrap
, new_bootstrapport
, requestorport
);
751 result
= mach_port_request_notification(
754 MACH_NOTIFY_DEAD_NAME
,
757 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
759 if (result
!= KERN_SUCCESS
) {
760 syslog(LOG_ERR
, "mach_port_request_notification(): %s", mach_error_string(result
));
761 mach_port_deallocate(mach_task_self(), requestorport
);
762 subset
->requestor_port
= MACH_PORT_NULL
;
763 deactivate_bootstrap(subset
);
764 } else if (previous
!= MACH_PORT_NULL
) {
765 syslog(LOG_DEBUG
, "deallocating old notification port (%x) for requestor %x",
766 previous
, requestorport
);
767 result
= mach_port_deallocate(
770 if (result
!= KERN_SUCCESS
)
771 panic("mach_port_deallocate(): %s", mach_error_string(result
));
774 syslog(LOG_INFO
, "Created bootstrap subset %x parent %x requestor %x",
775 new_bootstrapport
, bootstrapport
, requestorport
);
776 *subsetportp
= new_bootstrapport
;
777 return BOOTSTRAP_SUCCESS
;
782 * bootstrap_create_service(mach_port_t bootstrapport,
783 * name_t servicename,
784 * mach_port_t *serviceportp)
786 * Creates a service named "service_name" and returns send rights to that
787 * port in "service_port." The port may later be checked in as if this
788 * port were configured in the bootstrap configuration file.
790 * Errors: Returns appropriate kernel errors on rpc failure.
791 * Returns BOOTSTRAP_NAME_IN_USE, if service already exists.
793 __private_extern__ kern_return_t
794 x_bootstrap_create_service(
795 mach_port_t bootstrapport
,
797 mach_port_t
*serviceportp
)
801 bootstrap_info_t
*bootstrap
;
802 kern_return_t result
;
804 bootstrap
= lookup_bootstrap_by_port(bootstrapport
);
805 if (!bootstrap
|| !active_bootstrap(bootstrap
))
806 return BOOTSTRAP_NOT_PRIVILEGED
;
808 syslog(LOG_DEBUG
, "Service creation attempt for service %s bootstrap %x",
809 servicename
, bootstrapport
);
811 servicep
= lookup_service_by_name(bootstrap
, servicename
);
813 syslog(LOG_DEBUG
, "Service creation attempt for service %s failed, "
814 "service already exists", servicename
);
815 return BOOTSTRAP_NAME_IN_USE
;
818 serverp
= lookup_server_by_port(bootstrapport
);
820 result
= mach_port_allocate(mach_task_self(),
821 MACH_PORT_RIGHT_RECEIVE
,
823 if (result
!= KERN_SUCCESS
)
824 panic("port_allocate(): %s", mach_error_string(result
));
825 result
= mach_port_insert_right(mach_task_self(),
828 MACH_MSG_TYPE_MAKE_SEND
);
829 if (result
!= KERN_SUCCESS
)
830 panic("failed to insert send right(): %s", mach_error_string(result
));
835 servicep
= new_service(bootstrap
,
842 syslog(LOG_INFO
, "Created new service %x in bootstrap %x: %s",
843 servicep
->port
, bootstrap
->bootstrap_port
, servicename
);
845 return BOOTSTRAP_SUCCESS
;