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.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
35 #import "bootstrap_internal.h"
45 #define NULL ((void *)0)
48 #define bsstatus(servicep) \
49 (((servicep)->isActive) ? BOOTSTRAP_STATUS_ACTIVE : \
50 (((servicep)->server && (servicep)->server->servertype == DEMAND) ? \
51 BOOTSTRAP_STATUS_ON_DEMAND : BOOTSTRAP_STATUS_INACTIVE))
53 /* extern port_all_t backup_port; */
57 * bootstrap_create_server(mach_port_t bootstrap_port,
59 * integer_t server_uid,
60 * boolean_t on_demand,
61 * mach_port_t *server_portp)
63 * Returns send rights to server_port of service. At this point, the
64 * server appears active, so nothing will try to launch it. The server_port
65 * can be used to delare services associated with this server by calling
66 * bootstrap_create_service() and passing server_port as the bootstrap port.
68 * Errors: Returns appropriate kernel errors on rpc failure.
69 * Returns BOOTSTRAP_NOT_PRIVILEGED, if bootstrap port invalid.
72 x_bootstrap_create_server(
73 mach_port_t bootstrap_port
,
77 security_token_t sectoken
,
78 mach_port_t
*server_portp
)
81 bootstrap_info_t
*bootstrap
;
83 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
84 debug("Server create attempt: \"%s\" bootstrap %x",
85 server_cmd
, bootstrap_port
);
87 /* No forwarding allowed for this call - security risk (we run as root) */
88 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
89 debug("Server create: \"%s\": invalid bootstrap %x",
90 server_cmd
, bootstrap_port
);
91 return BOOTSTRAP_NOT_PRIVILEGED
;
94 /* only same uid (or root client) */
95 if (sectoken
.val
[0] && sectoken
.val
[0] != server_uid
) {
96 log("Server create: \"%s\": invalid security token (%d != %d)",
97 server_cmd
, sectoken
.val
[0], server_uid
);
98 return BOOTSTRAP_NOT_PRIVILEGED
;
100 serverp
= new_server(
104 (on_demand
) ? DEMAND
: RESTARTABLE
);
105 setup_server(serverp
);
107 info("New server %x in bootstrap %x: \"%s\"",
108 serverp
->port
, bootstrap_port
, server_cmd
);
109 *server_portp
= serverp
->port
;
110 return BOOTSTRAP_SUCCESS
;
115 * bootstrap_unprivileged(mach_port_t bootstrap_port,
116 * mach_port_t *unpriv_port)
118 * Given a bootstrap port, return its unprivileged equivalent. If
119 * the port is already unprivileged, another reference to the same
122 * This is most often used by servers, which are launched with their
123 * bootstrap port set to the privileged port for the server, to get
124 * an unprivileged version of the same port for use by its unprivileged
125 * children (or any offspring that it does not want to count as part
126 * of the "server" for mach_init registration and re-launch purposes).
129 x_bootstrap_unprivileged(
130 mach_port_t bootstrap_port
,
131 mach_port_t
*unpriv_portp
)
133 bootstrap_info_t
*bootstrap
;
135 debug("Get unprivileged attempt for bootstrap %x", bootstrap_port
);
137 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
138 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
139 debug("Get unprivileged: invalid bootstrap %x", bootstrap_port
);
140 return BOOTSTRAP_NOT_PRIVILEGED
;
143 *unpriv_portp
= bootstrap
->bootstrap_port
;
145 debug ("Get unpriv bootstrap %x returned for bootstrap %x",
146 bootstrap
->bootstrap_port
, bootstrap_port
);
147 return BOOTSTRAP_SUCCESS
;
153 * bootstrap_check_in(mach_port_t bootstrap_port,
154 * name_t service_name,
155 * mach_port_t *service_portp)
157 * Returns receive rights to service_port of service named by service_name.
159 * Errors: Returns appropriate kernel errors on rpc failure.
160 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
161 * Returns BOOTSTRAP_SERVICE_NOT_DECLARED, if service not declared
162 * in /etc/bootstrap.conf.
163 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
164 * registered or checked-in.
167 x_bootstrap_check_in(
168 mach_port_t bootstrap_port
,
170 mach_port_t
*service_portp
)
172 kern_return_t result
;
173 mach_port_t previous
;
176 bootstrap_info_t
*bootstrap
;
178 serverp
= lookup_server_by_port(bootstrap_port
);
179 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
180 debug("Service checkin attempt for service %s bootstrap %x",
181 service_name
, bootstrap_port
);
183 servicep
= lookup_service_by_name(bootstrap
, service_name
);
184 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
185 debug("bootstrap_check_in service %s unknown%s", service_name
,
186 forward_ok
? " forwarding" : "");
189 inherited_bootstrap_port
,
192 BOOTSTRAP_UNKNOWN_SERVICE
;
194 if (servicep
->server
!= NULL
&& servicep
->server
!= serverp
) {
195 debug("bootstrap_check_in service %s not privileged",
197 return BOOTSTRAP_NOT_PRIVILEGED
;
199 if (servicep
->servicetype
== SELF
|| !canReceive(servicep
->port
)) {
200 ASSERT(servicep
->isActive
);
201 debug("bootstrap_check_in service %s already active",
203 return BOOTSTRAP_SERVICE_ACTIVE
;
205 debug("Checkin service %s for bootstrap %x", service_name
,
206 bootstrap
->bootstrap_port
);
207 ASSERT(servicep
->isActive
== FALSE
);
208 servicep
->isActive
= TRUE
;
210 if (servicep
->server
!= NULL_SERVER
) {
211 /* registered server - service needs backup */
213 serverp
->active_services
++;
214 result
= mach_port_request_notification(
217 MACH_NOTIFY_PORT_DESTROYED
,
220 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
222 if (result
!= KERN_SUCCESS
)
223 kern_fatal(result
, "mach_port_request_notification");
225 /* one time use/created service */
226 servicep
->servicetype
= REGISTERED
;
227 result
= mach_port_request_notification(
230 MACH_NOTIFY_DEAD_NAME
,
233 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
235 if (result
!= KERN_SUCCESS
)
236 kern_fatal(result
, "mach_port_request_notification");
237 else if (previous
!= MACH_PORT_NULL
) {
238 debug("deallocating old notification port (%x) for checked in service %x",
239 previous
, servicep
->port
);
240 result
= mach_port_deallocate(
243 if (result
!= KERN_SUCCESS
)
244 kern_fatal(result
, "mach_port_deallocate");
248 info("Check-in service %x in bootstrap %x: %s",
249 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
251 *service_portp
= servicep
->port
;
252 return BOOTSTRAP_SUCCESS
;
257 * bootstrap_register(mach_port_t bootstrap_port,
258 * name_t service_name,
259 * mach_port_t service_port)
261 * Registers send rights for the port service_port for the service named by
262 * service_name. Registering a declared service or registering a service for
263 * which bootstrap has receive rights via a port backup notification is
265 * The previous service port will be deallocated. Restarting services wishing
266 * to resume service for previous clients must first attempt to checkin to the
269 * Errors: Returns appropriate kernel errors on rpc failure.
270 * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
271 * unprivileged bootstrap port.
272 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
273 * register or checked-in.
276 x_bootstrap_register(
277 mach_port_t bootstrap_port
,
279 mach_port_t service_port
)
281 kern_return_t result
;
284 bootstrap_info_t
*bootstrap
;
285 mach_port_t old_port
;
287 debug("Register attempt for service %s port %x",
288 service_name
, service_port
);
291 * Validate the bootstrap.
293 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
294 if (!bootstrap
|| !active_bootstrap(bootstrap
))
295 return BOOTSTRAP_NOT_PRIVILEGED
;
298 * If this bootstrap port is for a server, or it's an unprivileged
299 * bootstrap can't register the port.
301 serverp
= lookup_server_by_port(bootstrap_port
);
302 servicep
= lookup_service_by_name(bootstrap
, service_name
);
303 if (servicep
&& servicep
->server
&& servicep
->server
!= serverp
)
304 return BOOTSTRAP_NOT_PRIVILEGED
;
306 if (servicep
== NULL
|| servicep
->bootstrap
!= bootstrap
) {
307 servicep
= new_service(bootstrap
,
313 debug("Registered new service %s", service_name
);
315 if (servicep
->isActive
) {
316 debug("Register: service %s already active, port %x",
317 servicep
->name
, servicep
->port
);
318 ASSERT(!canReceive(servicep
->port
));
319 return BOOTSTRAP_SERVICE_ACTIVE
;
321 old_port
= servicep
->port
;
322 if (servicep
->servicetype
== DECLARED
) {
323 servicep
->servicetype
= REGISTERED
;
325 if (servicep
->server
) {
326 ASSERT(servicep
->server
== serverp
);
327 ASSERT(active_server(serverp
));
328 servicep
->server
= NULL_SERVER
;
332 result
= mach_port_mod_refs(
335 MACH_PORT_RIGHT_RECEIVE
,
337 if (result
!= KERN_SUCCESS
)
338 kern_fatal(result
, "mach_port_mod_refs");
340 result
= mach_port_deallocate(
343 if (result
!= KERN_SUCCESS
)
344 kern_fatal(result
, "mach_port_mod_refs");
346 servicep
->port
= service_port
;
347 servicep
->isActive
= TRUE
;
348 debug("Re-registered inactive service %x bootstrap %x: %s",
349 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, service_name
);
352 /* detect the new service port going dead */
353 result
= mach_port_request_notification(
356 MACH_NOTIFY_DEAD_NAME
,
359 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
361 if (result
!= KERN_SUCCESS
) {
362 debug("Can't request notification on service %x bootstrap %x: %s",
363 service_port
, servicep
->bootstrap
->bootstrap_port
, "must be dead");
364 delete_service(servicep
);
365 return BOOTSTRAP_SUCCESS
;
366 } else if (old_port
!= MACH_PORT_NULL
) {
367 debug("deallocating old notification port (%x) for service %x",
368 old_port
, service_port
);
369 result
= mach_port_deallocate(
372 if (result
!= KERN_SUCCESS
)
373 kern_fatal(result
, "mach_port_deallocate");
375 info("Registered service %x bootstrap %x: %s",
376 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
377 return BOOTSTRAP_SUCCESS
;
382 * bootstrap_look_up(mach_port_t bootstrap_port,
383 * name_t service_name,
384 * mach_port_t *service_portp)
386 * Returns send rights for the service port of the service named by
387 * service_name in *service_portp. Service is not guaranteed to be active.
389 * Errors: Returns appropriate kernel errors on rpc failure.
390 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
394 mach_port_t bootstrap_port
,
396 mach_port_t
*service_portp
)
399 bootstrap_info_t
*bootstrap
;
401 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
402 servicep
= lookup_service_by_name(bootstrap
, service_name
);
403 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
405 debug("bootstrap_look_up service %s forwarding",
407 return bootstrap_look_up(inherited_bootstrap_port
,
411 debug("bootstrap_look_up service %s unknown",
413 return BOOTSTRAP_UNKNOWN_SERVICE
;
416 *service_portp
= servicep
->port
;
417 debug("Lookup returns port %x for service %s",
420 return BOOTSTRAP_SUCCESS
;
425 * bootstrap_look_up_array(mach_port_t bootstrap_port,
426 * name_array_t service_names,
427 * int service_names_cnt,
428 * mach_port_array_t *service_ports,
429 * int *service_ports_cnt,
430 * boolean_t *all_services_known)
432 * Returns port send rights in corresponding entries of the array service_ports
433 * for all services named in the array service_names. Service_ports_cnt is
434 * returned and will always equal service_names_cnt (assuming service_names_cnt
435 * is greater than or equal to zero).
437 * Errors: Returns appropriate kernel errors on rpc failure.
438 * Returns BOOTSTRAP_NO_MEMORY, if server couldn't obtain memory
440 * Unknown service names have the corresponding service
441 * port set to MACH_PORT_NULL.
442 * If all services are known, all_services_known is true on
444 * if any service is unknown, it's false.
447 x_bootstrap_look_up_array(
448 mach_port_t bootstrap_port
,
449 name_array_t service_names
,
450 unsigned int service_names_cnt
,
451 mach_port_array_t
*service_portsp
,
452 unsigned int *service_ports_cnt
,
453 boolean_t
*all_services_known
)
456 static mach_port_t service_ports
[BOOTSTRAP_MAX_LOOKUP_COUNT
];
458 if (service_names_cnt
> BOOTSTRAP_MAX_LOOKUP_COUNT
)
459 return BOOTSTRAP_BAD_COUNT
;
460 *service_ports_cnt
= service_names_cnt
;
461 *all_services_known
= TRUE
;
462 for (i
= 0; i
< service_names_cnt
; i
++) {
463 if ( x_bootstrap_look_up(bootstrap_port
,
466 != BOOTSTRAP_SUCCESS
)
468 *all_services_known
= FALSE
;
469 service_ports
[i
] = MACH_PORT_NULL
;
472 debug("bootstrap_look_up_array returns %d ports", service_names_cnt
);
473 *service_portsp
= service_ports
;
474 return BOOTSTRAP_SUCCESS
;
479 * bootstrap_parent(mach_port_t bootstrap_port,
480 * mach_port_t *parent_port);
482 * Given a bootstrap subset port, return the parent bootstrap port.
483 * If the specified bootstrap port is already the root subset,
484 * MACH_PORT_NULL will be returned.
487 * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
488 * with an effective user id of root (as determined by the security
489 * token in the message trailer).
493 mach_port_t bootstrap_port
,
494 security_token_t sectoken
,
495 mach_port_t
*parent_port
)
498 bootstrap_info_t
*bootstrap
;
500 debug("Parent attempt for bootstrap %x", bootstrap_port
);
502 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
503 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
504 debug("Parent attempt for bootstrap %x: invalid bootstrap",
506 return BOOTSTRAP_NOT_PRIVILEGED
;
508 if (sectoken
.val
[0]) {
509 log("Bootstrap parent for bootstrap %x: invalid security token (%d)",
510 bootstrap_port
, sectoken
.val
[0]);
511 return BOOTSTRAP_NOT_PRIVILEGED
;
513 debug("Returning bootstrap parent %x for bootstrap %x",
514 bootstrap
->parent
->bootstrap_port
, bootstrap_port
);
515 *parent_port
= bootstrap
->parent
->bootstrap_port
;
516 return BOOTSTRAP_SUCCESS
;
518 debug("bootstrap parent for bootstrap %x: not implemented",
520 return BOOTSTRAP_NOT_PRIVILEGED
;
526 * bootstrap_status(mach_port_t bootstrap_port,
527 * name_t service_name,
528 * bootstrap_status_t *service_active);
530 * Returns: service_active indicates if service is available.
532 * Errors: Returns appropriate kernel errors on rpc failure.
533 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
537 mach_port_t bootstrap_port
,
539 bootstrap_status_t
*service_active
)
542 bootstrap_info_t
*bootstrap
;
544 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
545 servicep
= lookup_service_by_name(bootstrap
, service_name
);
546 if (servicep
== NULL
) {
548 debug("bootstrap_status forwarding status, server %s",
550 return bootstrap_status(inherited_bootstrap_port
,
554 debug("bootstrap_status service %s unknown",
556 return BOOTSTRAP_UNKNOWN_SERVICE
;
559 *service_active
= bsstatus(servicep
);
561 debug("bootstrap_status server %s %sactive", service_name
,
562 servicep
->isActive
? "" : "in");
563 return BOOTSTRAP_SUCCESS
;
568 * bootstrap_info(mach_port_t bootstrap_port,
569 * name_array_t *service_names,
570 * int *service_names_cnt,
571 * name_array_t *server_names,
572 * int *server_names_cnt,
573 * bootstrap_status_array_t *service_actives,
574 * int *service_active_cnt);
576 * Returns bootstrap status for all known services.
578 * Errors: Returns appropriate kernel errors on rpc failure.
582 mach_port_t bootstrap_port
,
583 name_array_t
*service_namesp
,
584 unsigned int *service_names_cnt
,
585 name_array_t
*server_namesp
,
586 unsigned int *server_names_cnt
,
587 bootstrap_status_array_t
*service_activesp
,
588 unsigned int *service_actives_cnt
)
590 kern_return_t result
;
594 bootstrap_info_t
*bootstrap
;
595 name_array_t service_names
;
596 name_array_t server_names
;
597 bootstrap_status_array_t service_actives
;
599 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
601 for ( cnt
= i
= 0, servicep
= services
.next
603 ; servicep
= servicep
->next
, i
++)
605 if (lookup_service_by_name(bootstrap
, servicep
->name
) == servicep
)
610 result
= vm_allocate(mach_task_self(),
611 (vm_address_t
*)&service_names
,
612 cnt
* sizeof(service_names
[0]),
614 if (result
!= KERN_SUCCESS
)
615 return BOOTSTRAP_NO_MEMORY
;
617 result
= vm_allocate(mach_task_self(),
618 (vm_address_t
*)&server_names
,
619 cnt
* sizeof(server_names
[0]),
621 if (result
!= KERN_SUCCESS
) {
622 (void)vm_deallocate(mach_task_self(),
623 (vm_address_t
)service_names
,
624 cnt
* sizeof(service_names
[0]));
625 return BOOTSTRAP_NO_MEMORY
;
627 result
= vm_allocate(mach_task_self(),
628 (vm_address_t
*)&service_actives
,
629 cnt
* sizeof(service_actives
[0]),
631 if (result
!= KERN_SUCCESS
) {
632 (void)vm_deallocate(mach_task_self(),
633 (vm_address_t
)service_names
,
634 cnt
* sizeof(service_names
[0]));
635 (void)vm_deallocate(mach_task_self(),
636 (vm_address_t
)server_names
,
637 cnt
* sizeof(server_names
[0]));
638 return BOOTSTRAP_NO_MEMORY
;
641 for ( i
= 0, servicep
= services
.next
643 ; servicep
= servicep
->next
)
645 if ( lookup_service_by_name(bootstrap
, servicep
->name
)
648 strncpy(service_names
[i
],
650 sizeof(service_names
[0]));
651 service_names
[i
][sizeof(service_names
[0]) - 1] = '\0';
652 if (servicep
->server
) {
653 serverp
= servicep
->server
;
654 strncpy(server_names
[i
],
656 sizeof(server_names
[0]));
657 server_names
[i
][sizeof(server_names
[0]) - 1] = '\0';
658 debug("bootstrap info service %s server %s %sactive",
660 serverp
->cmd
, servicep
->isActive
? "" : "in");
662 server_names
[i
][0] = '\0';
663 debug("bootstrap info service %s %sactive",
664 servicep
->name
, servicep
->isActive
? "" : "in");
666 service_actives
[i
] = bsstatus(servicep
);
669 *service_namesp
= service_names
;
670 *server_namesp
= server_names
;
671 *service_activesp
= service_actives
;
672 *service_names_cnt
= *server_names_cnt
=
673 *service_actives_cnt
= cnt
;
675 return BOOTSTRAP_SUCCESS
;
680 * bootstrap_subset(mach_port_t bootstrap_port,
681 * mach_port_t requestor_port,
682 * mach_port_t *subset_port);
684 * Returns a new port to use as a bootstrap port. This port behaves
685 * exactly like the previous bootstrap_port, except that ports dynamically
686 * registered via bootstrap_register() are available only to users of this
687 * specific subset_port. Lookups on the subset_port will return ports
688 * registered with this port specifically, and ports registered with
689 * ancestors of this subset_port. Duplications of services already
690 * registered with an ancestor port may be registered with the subset port
691 * are allowed. Services already advertised may then be effectively removed
692 * by registering MACH_PORT_NULL for the service.
693 * When it is detected that the requestor_port is destroied the subset
694 * port and all services advertized by it are destroied as well.
696 * Errors: Returns appropriate kernel errors on rpc failure.
700 mach_port_t bootstrap_port
,
701 mach_port_t requestor_port
,
702 mach_port_t
*subset_port
)
704 kern_return_t result
;
705 bootstrap_info_t
*bootstrap
;
706 bootstrap_info_t
*subset
;
707 mach_port_t new_bootstrap_port
;
708 mach_port_t previous
;
710 debug("Subset create attempt: bootstrap %x, requestor: %x",
711 bootstrap_port
, requestor_port
);
713 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
714 if (!bootstrap
|| !active_bootstrap(bootstrap
))
715 return BOOTSTRAP_NOT_PRIVILEGED
;
717 result
= mach_port_allocate(
719 MACH_PORT_RIGHT_RECEIVE
,
720 &new_bootstrap_port
);
721 if (result
!= KERN_SUCCESS
)
722 kern_fatal(result
, "mach_port_allocate");
724 result
= mach_port_insert_right(
728 MACH_MSG_TYPE_MAKE_SEND
);
729 if (result
!= KERN_SUCCESS
)
730 kern_fatal(result
, "failed to insert send right");
732 result
= mach_port_insert_member(
736 if (result
!= KERN_SUCCESS
)
737 kern_fatal(result
, "port_set_add");
739 subset
= new_bootstrap(bootstrap
, new_bootstrap_port
, requestor_port
);
741 result
= mach_port_request_notification(
744 MACH_NOTIFY_DEAD_NAME
,
747 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
749 if (result
!= KERN_SUCCESS
) {
750 kern_error(result
, "mach_port_request_notification");
751 mach_port_deallocate(mach_task_self(), requestor_port
);
752 subset
->requestor_port
= MACH_PORT_NULL
;
753 deactivate_bootstrap(subset
);
754 } else if (previous
!= MACH_PORT_NULL
) {
755 debug("deallocating old notification port (%x) for requestor %x",
756 previous
, requestor_port
);
757 result
= mach_port_deallocate(
760 if (result
!= KERN_SUCCESS
)
761 kern_fatal(result
, "mach_port_deallocate");
764 info("Created bootstrap subset %x parent %x requestor %x",
765 new_bootstrap_port
, bootstrap_port
, requestor_port
);
766 *subset_port
= new_bootstrap_port
;
767 return BOOTSTRAP_SUCCESS
;
772 * bootstrap_create_service(mach_port_t bootstrap_port,
773 * name_t service_name,
774 * mach_port_t *service_port)
776 * Creates a service named "service_name" and returns send rights to that
777 * port in "service_port." The port may later be checked in as if this
778 * port were configured in the bootstrap configuration file.
780 * Errors: Returns appropriate kernel errors on rpc failure.
781 * Returns BOOTSTRAP_NAME_IN_USE, if service already exists.
784 x_bootstrap_create_service(
785 mach_port_t bootstrap_port
,
787 mach_port_t
*service_port
)
791 bootstrap_info_t
*bootstrap
;
792 kern_return_t result
;
794 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
795 if (!bootstrap
|| !active_bootstrap(bootstrap
))
796 return BOOTSTRAP_NOT_PRIVILEGED
;
798 debug("Service creation attempt for service %s bootstrap %x",
799 service_name
, bootstrap_port
);
801 servicep
= lookup_service_by_name(bootstrap
, service_name
);
803 debug("Service creation attempt for service %s failed, "
804 "service already exists", service_name
);
805 return BOOTSTRAP_NAME_IN_USE
;
808 serverp
= lookup_server_by_port(bootstrap_port
);
810 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, service_port
);
811 if (result
!= KERN_SUCCESS
)
812 kern_fatal(result
, "port_allocate");
813 result
= mach_port_insert_right(mach_task_self(), *service_port
, *service_port
, MACH_MSG_TYPE_MAKE_SEND
);
814 if (result
!= KERN_SUCCESS
)
815 kern_fatal(result
, "failed to insert send right");
820 servicep
= new_service(bootstrap
,
827 info("Created new service %x in bootstrap %x: %s",
828 servicep
->port
, bootstrap
->bootstrap_port
, service_name
);
830 return BOOTSTRAP_SUCCESS
;