2 * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * bootstrap -- fundamental service initiator and port server
27 * Mike DeMoney, NeXT, Inc.
28 * Copyright, 1990. All rights reserved.
30 * rpc_services.c -- implementation of bootstrap rpc services
36 #import "bootstrap_internal.h"
46 #define NULL ((void *)0)
49 #define bsstatus(servicep) \
50 (((servicep)->isActive) ? BOOTSTRAP_STATUS_ACTIVE : \
51 (((servicep)->server && (servicep)->server->servertype == DEMAND) ? \
52 BOOTSTRAP_STATUS_ON_DEMAND : BOOTSTRAP_STATUS_INACTIVE))
54 /* extern port_all_t backup_port; */
58 * bootstrap_create_server(mach_port_t bootstrap_port,
60 * integer_t server_uid,
61 * boolean_t on_demand,
62 * mach_port_t *server_portp)
64 * Returns send rights to server_port of service. At this point, the
65 * server appears active, so nothing will try to launch it. The server_port
66 * can be used to delare services associated with this server by calling
67 * bootstrap_create_service() and passing server_port as the bootstrap port.
69 * Errors: Returns appropriate kernel errors on rpc failure.
70 * Returns BOOTSTRAP_NOT_PRIVILEGED, if bootstrap port invalid.
73 x_bootstrap_create_server(
74 mach_port_t bootstrap_port
,
78 security_token_t sectoken
,
79 mach_port_t
*server_portp
)
82 bootstrap_info_t
*bootstrap
;
84 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
85 debug("Server create attempt: \"%s\" bootstrap %x",
86 server_cmd
, bootstrap_port
);
88 /* No forwarding allowed for this call - security risk (we run as root) */
89 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
90 debug("Server create: \"%s\": invalid bootstrap %x",
91 server_cmd
, bootstrap_port
);
92 return BOOTSTRAP_NOT_PRIVILEGED
;
95 /* only same uid (or root client) */
96 if (sectoken
.val
[0] && sectoken
.val
[0] != server_uid
) {
97 log("Server create: \"%s\": invalid security token (%d != %d)",
98 server_cmd
, sectoken
.val
[0], server_uid
);
99 return BOOTSTRAP_NOT_PRIVILEGED
;
101 serverp
= new_server(
105 (on_demand
) ? DEMAND
: RESTARTABLE
);
106 setup_server(serverp
);
108 info("New server %x in bootstrap %x: \"%s\"",
109 serverp
->port
, bootstrap_port
, server_cmd
);
110 *server_portp
= serverp
->port
;
111 return BOOTSTRAP_SUCCESS
;
116 * bootstrap_unprivileged(mach_port_t bootstrap_port,
117 * mach_port_t *unpriv_port)
119 * Given a bootstrap port, return its unprivileged equivalent. If
120 * the port is already unprivileged, another reference to the same
123 * This is most often used by servers, which are launched with their
124 * bootstrap port set to the privileged port for the server, to get
125 * an unprivileged version of the same port for use by its unprivileged
126 * children (or any offspring that it does not want to count as part
127 * of the "server" for mach_init registration and re-launch purposes).
130 x_bootstrap_unprivileged(
131 mach_port_t bootstrap_port
,
132 mach_port_t
*unpriv_portp
)
134 bootstrap_info_t
*bootstrap
;
136 debug("Get unprivileged attempt for bootstrap %x", bootstrap_port
);
138 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
139 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
140 debug("Get unprivileged: invalid bootstrap %x", bootstrap_port
);
141 return BOOTSTRAP_NOT_PRIVILEGED
;
144 *unpriv_portp
= bootstrap
->bootstrap_port
;
146 debug ("Get unpriv bootstrap %x returned for bootstrap %x",
147 bootstrap
->bootstrap_port
, bootstrap_port
);
148 return BOOTSTRAP_SUCCESS
;
154 * bootstrap_check_in(mach_port_t bootstrap_port,
155 * name_t service_name,
156 * mach_port_t *service_portp)
158 * Returns receive rights to service_port of service named by service_name.
160 * Errors: Returns appropriate kernel errors on rpc failure.
161 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
162 * Returns BOOTSTRAP_SERVICE_NOT_DECLARED, if service not declared
163 * in /etc/bootstrap.conf.
164 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
165 * registered or checked-in.
168 x_bootstrap_check_in(
169 mach_port_t bootstrap_port
,
171 mach_port_t
*service_portp
)
173 kern_return_t result
;
174 mach_port_t previous
;
177 bootstrap_info_t
*bootstrap
;
179 serverp
= lookup_server_by_port(bootstrap_port
);
180 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
181 debug("Service checkin attempt for service %s bootstrap %x",
182 service_name
, bootstrap_port
);
184 servicep
= lookup_service_by_name(bootstrap
, service_name
);
185 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
186 debug("bootstrap_check_in service %s unknown%s", service_name
,
187 forward_ok
? " forwarding" : "");
190 inherited_bootstrap_port
,
193 BOOTSTRAP_UNKNOWN_SERVICE
;
195 if (servicep
->server
!= NULL
&& servicep
->server
!= serverp
) {
196 debug("bootstrap_check_in service %s not privileged",
198 return BOOTSTRAP_NOT_PRIVILEGED
;
200 if (servicep
->servicetype
== SELF
|| !canReceive(servicep
->port
)) {
201 ASSERT(servicep
->isActive
);
202 debug("bootstrap_check_in service %s already active",
204 return BOOTSTRAP_SERVICE_ACTIVE
;
206 debug("Checkin service %s for bootstrap %x", service_name
,
207 bootstrap
->bootstrap_port
);
208 ASSERT(servicep
->isActive
== FALSE
);
209 servicep
->isActive
= TRUE
;
211 if (servicep
->server
!= NULL_SERVER
) {
212 /* registered server - service needs backup */
214 serverp
->active_services
++;
215 result
= mach_port_request_notification(
218 MACH_NOTIFY_PORT_DESTROYED
,
221 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
223 if (result
!= KERN_SUCCESS
)
224 kern_fatal(result
, "mach_port_request_notification");
226 /* one time use/created service */
227 servicep
->servicetype
= REGISTERED
;
228 result
= mach_port_request_notification(
231 MACH_NOTIFY_DEAD_NAME
,
234 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
236 if (result
!= KERN_SUCCESS
)
237 kern_fatal(result
, "mach_port_request_notification");
238 else if (previous
!= MACH_PORT_NULL
) {
239 debug("deallocating old notification port (%x) for checked in service %x",
240 previous
, servicep
->port
);
241 result
= mach_port_deallocate(
244 if (result
!= KERN_SUCCESS
)
245 kern_fatal(result
, "mach_port_deallocate");
249 info("Check-in service %x in bootstrap %x: %s",
250 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
252 *service_portp
= servicep
->port
;
253 return BOOTSTRAP_SUCCESS
;
258 * bootstrap_register(mach_port_t bootstrap_port,
259 * name_t service_name,
260 * mach_port_t service_port)
262 * Registers send rights for the port service_port for the service named by
263 * service_name. Registering a declared service or registering a service for
264 * which bootstrap has receive rights via a port backup notification is
266 * The previous service port will be deallocated. Restarting services wishing
267 * to resume service for previous clients must first attempt to checkin to the
270 * Errors: Returns appropriate kernel errors on rpc failure.
271 * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
272 * unprivileged bootstrap port.
273 * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
274 * register or checked-in.
277 x_bootstrap_register(
278 mach_port_t bootstrap_port
,
280 mach_port_t service_port
)
282 kern_return_t result
;
285 bootstrap_info_t
*bootstrap
;
286 mach_port_t old_port
;
288 debug("Register attempt for service %s port %x",
289 service_name
, service_port
);
292 * Validate the bootstrap.
294 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
295 if (!bootstrap
|| !active_bootstrap(bootstrap
))
296 return BOOTSTRAP_NOT_PRIVILEGED
;
299 * If this bootstrap port is for a server, or it's an unprivileged
300 * bootstrap can't register the port.
302 serverp
= lookup_server_by_port(bootstrap_port
);
303 servicep
= lookup_service_by_name(bootstrap
, service_name
);
304 if (servicep
&& servicep
->server
&& servicep
->server
!= serverp
)
305 return BOOTSTRAP_NOT_PRIVILEGED
;
307 if (servicep
== NULL
|| servicep
->bootstrap
!= bootstrap
) {
308 servicep
= new_service(bootstrap
,
314 debug("Registered new service %s", service_name
);
316 if (servicep
->isActive
) {
317 debug("Register: service %s already active, port %x",
318 servicep
->name
, servicep
->port
);
319 ASSERT(!canReceive(servicep
->port
));
320 return BOOTSTRAP_SERVICE_ACTIVE
;
322 old_port
= servicep
->port
;
323 if (servicep
->servicetype
== DECLARED
) {
324 servicep
->servicetype
= REGISTERED
;
326 if (servicep
->server
) {
327 ASSERT(servicep
->server
== serverp
);
328 ASSERT(active_server(serverp
));
329 servicep
->server
= NULL_SERVER
;
333 result
= mach_port_mod_refs(
336 MACH_PORT_RIGHT_RECEIVE
,
338 if (result
!= KERN_SUCCESS
)
339 kern_fatal(result
, "mach_port_mod_refs");
341 result
= mach_port_deallocate(
344 if (result
!= KERN_SUCCESS
)
345 kern_fatal(result
, "mach_port_mod_refs");
347 servicep
->port
= service_port
;
348 servicep
->isActive
= TRUE
;
349 debug("Re-registered inactive service %x bootstrap %x: %s",
350 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, service_name
);
353 /* detect the new service port going dead */
354 result
= mach_port_request_notification(
357 MACH_NOTIFY_DEAD_NAME
,
360 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
362 if (result
!= KERN_SUCCESS
) {
363 debug("Can't request notification on service %x bootstrap %x: %s",
364 service_port
, servicep
->bootstrap
->bootstrap_port
, "must be dead");
365 delete_service(servicep
);
366 return BOOTSTRAP_SUCCESS
;
367 } else if (old_port
!= MACH_PORT_NULL
) {
368 debug("deallocating old notification port (%x) for service %x",
369 old_port
, service_port
);
370 result
= mach_port_deallocate(
373 if (result
!= KERN_SUCCESS
)
374 kern_fatal(result
, "mach_port_deallocate");
376 info("Registered service %x bootstrap %x: %s",
377 servicep
->port
, servicep
->bootstrap
->bootstrap_port
, servicep
->name
);
378 return BOOTSTRAP_SUCCESS
;
383 * bootstrap_look_up(mach_port_t bootstrap_port,
384 * name_t service_name,
385 * mach_port_t *service_portp)
387 * Returns send rights for the service port of the service named by
388 * service_name in *service_portp. Service is not guaranteed to be active.
390 * Errors: Returns appropriate kernel errors on rpc failure.
391 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
395 mach_port_t bootstrap_port
,
397 mach_port_t
*service_portp
)
400 bootstrap_info_t
*bootstrap
;
402 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
403 servicep
= lookup_service_by_name(bootstrap
, service_name
);
404 if (servicep
== NULL
|| servicep
->port
== MACH_PORT_NULL
) {
406 debug("bootstrap_look_up service %s forwarding",
408 return bootstrap_look_up(inherited_bootstrap_port
,
412 debug("bootstrap_look_up service %s unknown",
414 return BOOTSTRAP_UNKNOWN_SERVICE
;
417 *service_portp
= servicep
->port
;
418 debug("Lookup returns port %x for service %s",
421 return BOOTSTRAP_SUCCESS
;
426 * bootstrap_look_up_array(mach_port_t bootstrap_port,
427 * name_array_t service_names,
428 * int service_names_cnt,
429 * mach_port_array_t *service_ports,
430 * int *service_ports_cnt,
431 * boolean_t *all_services_known)
433 * Returns port send rights in corresponding entries of the array service_ports
434 * for all services named in the array service_names. Service_ports_cnt is
435 * returned and will always equal service_names_cnt (assuming service_names_cnt
436 * is greater than or equal to zero).
438 * Errors: Returns appropriate kernel errors on rpc failure.
439 * Returns BOOTSTRAP_NO_MEMORY, if server couldn't obtain memory
441 * Unknown service names have the corresponding service
442 * port set to MACH_PORT_NULL.
443 * If all services are known, all_services_known is true on
445 * if any service is unknown, it's false.
448 x_bootstrap_look_up_array(
449 mach_port_t bootstrap_port
,
450 name_array_t service_names
,
451 unsigned int service_names_cnt
,
452 mach_port_array_t
*service_portsp
,
453 unsigned int *service_ports_cnt
,
454 boolean_t
*all_services_known
)
457 static mach_port_t service_ports
[BOOTSTRAP_MAX_LOOKUP_COUNT
];
459 if (service_names_cnt
> BOOTSTRAP_MAX_LOOKUP_COUNT
)
460 return BOOTSTRAP_BAD_COUNT
;
461 *service_ports_cnt
= service_names_cnt
;
462 *all_services_known
= TRUE
;
463 for (i
= 0; i
< service_names_cnt
; i
++) {
464 if ( x_bootstrap_look_up(bootstrap_port
,
467 != BOOTSTRAP_SUCCESS
)
469 *all_services_known
= FALSE
;
470 service_ports
[i
] = MACH_PORT_NULL
;
473 debug("bootstrap_look_up_array returns %d ports", service_names_cnt
);
474 *service_portsp
= service_ports
;
475 return BOOTSTRAP_SUCCESS
;
480 * bootstrap_parent(mach_port_t bootstrap_port,
481 * mach_port_t *parent_port);
483 * Given a bootstrap subset port, return the parent bootstrap port.
484 * If the specified bootstrap port is already the root subset,
485 * MACH_PORT_NULL will be returned.
488 * Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
489 * with an effective user id of root (as determined by the security
490 * token in the message trailer).
494 mach_port_t bootstrap_port
,
495 security_token_t sectoken
,
496 mach_port_t
*parent_port
)
499 bootstrap_info_t
*bootstrap
;
501 debug("Parent attempt for bootstrap %x", bootstrap_port
);
503 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
504 if (!bootstrap
|| !active_bootstrap(bootstrap
)) {
505 debug("Parent attempt for bootstrap %x: invalid bootstrap",
507 return BOOTSTRAP_NOT_PRIVILEGED
;
509 if (sectoken
.val
[0]) {
510 log("Bootstrap parent for bootstrap %x: invalid security token (%d)",
511 bootstrap_port
, sectoken
.val
[0]);
512 return BOOTSTRAP_NOT_PRIVILEGED
;
514 debug("Returning bootstrap parent %x for bootstrap %x",
515 bootstrap
->parent
->bootstrap_port
, bootstrap_port
);
516 *parent_port
= bootstrap
->parent
->bootstrap_port
;
517 return BOOTSTRAP_SUCCESS
;
519 debug("bootstrap parent for bootstrap %x: not implemented",
521 return BOOTSTRAP_NOT_PRIVILEGED
;
527 * bootstrap_status(mach_port_t bootstrap_port,
528 * name_t service_name,
529 * bootstrap_status_t *service_active);
531 * Returns: service_active indicates if service is available.
533 * Errors: Returns appropriate kernel errors on rpc failure.
534 * Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
538 mach_port_t bootstrap_port
,
540 bootstrap_status_t
*service_active
)
543 bootstrap_info_t
*bootstrap
;
545 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
546 servicep
= lookup_service_by_name(bootstrap
, service_name
);
547 if (servicep
== NULL
) {
549 debug("bootstrap_status forwarding status, server %s",
551 return bootstrap_status(inherited_bootstrap_port
,
555 debug("bootstrap_status service %s unknown",
557 return BOOTSTRAP_UNKNOWN_SERVICE
;
560 *service_active
= bsstatus(servicep
);
562 debug("bootstrap_status server %s %sactive", service_name
,
563 servicep
->isActive
? "" : "in");
564 return BOOTSTRAP_SUCCESS
;
569 * bootstrap_info(mach_port_t bootstrap_port,
570 * name_array_t *service_names,
571 * int *service_names_cnt,
572 * name_array_t *server_names,
573 * int *server_names_cnt,
574 * bootstrap_status_array_t *service_actives,
575 * int *service_active_cnt);
577 * Returns bootstrap status for all known services.
579 * Errors: Returns appropriate kernel errors on rpc failure.
583 mach_port_t bootstrap_port
,
584 name_array_t
*service_namesp
,
585 unsigned int *service_names_cnt
,
586 name_array_t
*server_namesp
,
587 unsigned int *server_names_cnt
,
588 bootstrap_status_array_t
*service_activesp
,
589 unsigned int *service_actives_cnt
)
591 kern_return_t result
;
595 bootstrap_info_t
*bootstrap
;
596 name_array_t service_names
;
597 name_array_t server_names
;
598 bootstrap_status_array_t service_actives
;
600 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
602 for ( cnt
= i
= 0, servicep
= services
.next
604 ; servicep
= servicep
->next
, i
++)
606 if (lookup_service_by_name(bootstrap
, servicep
->name
) == servicep
)
611 result
= vm_allocate(mach_task_self(),
612 (vm_address_t
*)&service_names
,
613 cnt
* sizeof(service_names
[0]),
615 if (result
!= KERN_SUCCESS
)
616 return BOOTSTRAP_NO_MEMORY
;
618 result
= vm_allocate(mach_task_self(),
619 (vm_address_t
*)&server_names
,
620 cnt
* sizeof(server_names
[0]),
622 if (result
!= KERN_SUCCESS
) {
623 (void)vm_deallocate(mach_task_self(),
624 (vm_address_t
)service_names
,
625 cnt
* sizeof(service_names
[0]));
626 return BOOTSTRAP_NO_MEMORY
;
628 result
= vm_allocate(mach_task_self(),
629 (vm_address_t
*)&service_actives
,
630 cnt
* sizeof(service_actives
[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 (void)vm_deallocate(mach_task_self(),
637 (vm_address_t
)server_names
,
638 cnt
* sizeof(server_names
[0]));
639 return BOOTSTRAP_NO_MEMORY
;
642 for ( i
= 0, servicep
= services
.next
644 ; servicep
= servicep
->next
)
646 if ( lookup_service_by_name(bootstrap
, servicep
->name
)
649 strncpy(service_names
[i
],
651 sizeof(service_names
[0]));
652 service_names
[i
][sizeof(service_names
[0]) - 1] = '\0';
653 if (servicep
->server
) {
654 serverp
= servicep
->server
;
655 strncpy(server_names
[i
],
657 sizeof(server_names
[0]));
658 server_names
[i
][sizeof(server_names
[0]) - 1] = '\0';
659 debug("bootstrap info service %s server %s %sactive",
661 serverp
->cmd
, servicep
->isActive
? "" : "in");
663 server_names
[i
][0] = '\0';
664 debug("bootstrap info service %s %sactive",
665 servicep
->name
, servicep
->isActive
? "" : "in");
667 service_actives
[i
] = bsstatus(servicep
);
670 *service_namesp
= service_names
;
671 *server_namesp
= server_names
;
672 *service_activesp
= service_actives
;
673 *service_names_cnt
= *server_names_cnt
=
674 *service_actives_cnt
= cnt
;
676 return BOOTSTRAP_SUCCESS
;
681 * bootstrap_subset(mach_port_t bootstrap_port,
682 * mach_port_t requestor_port,
683 * mach_port_t *subset_port);
685 * Returns a new port to use as a bootstrap port. This port behaves
686 * exactly like the previous bootstrap_port, except that ports dynamically
687 * registered via bootstrap_register() are available only to users of this
688 * specific subset_port. Lookups on the subset_port will return ports
689 * registered with this port specifically, and ports registered with
690 * ancestors of this subset_port. Duplications of services already
691 * registered with an ancestor port may be registered with the subset port
692 * are allowed. Services already advertised may then be effectively removed
693 * by registering MACH_PORT_NULL for the service.
694 * When it is detected that the requestor_port is destroied the subset
695 * port and all services advertized by it are destroied as well.
697 * Errors: Returns appropriate kernel errors on rpc failure.
701 mach_port_t bootstrap_port
,
702 mach_port_t requestor_port
,
703 mach_port_t
*subset_port
)
705 kern_return_t result
;
706 bootstrap_info_t
*bootstrap
;
707 bootstrap_info_t
*subset
;
708 mach_port_t new_bootstrap_port
;
709 mach_port_t previous
;
711 debug("Subset create attempt: bootstrap %x, requestor: %x",
712 bootstrap_port
, requestor_port
);
714 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
715 if (!bootstrap
|| !active_bootstrap(bootstrap
))
716 return BOOTSTRAP_NOT_PRIVILEGED
;
718 result
= mach_port_allocate(
720 MACH_PORT_RIGHT_RECEIVE
,
721 &new_bootstrap_port
);
722 if (result
!= KERN_SUCCESS
)
723 kern_fatal(result
, "mach_port_allocate");
725 result
= mach_port_insert_right(
729 MACH_MSG_TYPE_MAKE_SEND
);
730 if (result
!= KERN_SUCCESS
)
731 kern_fatal(result
, "failed to insert send right");
733 result
= mach_port_insert_member(
737 if (result
!= KERN_SUCCESS
)
738 kern_fatal(result
, "port_set_add");
740 subset
= new_bootstrap(bootstrap
, new_bootstrap_port
, requestor_port
);
742 result
= mach_port_request_notification(
745 MACH_NOTIFY_DEAD_NAME
,
748 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
750 if (result
!= KERN_SUCCESS
) {
751 kern_error(result
, "mach_port_request_notification");
752 mach_port_deallocate(mach_task_self(), requestor_port
);
753 subset
->requestor_port
= MACH_PORT_NULL
;
754 deactivate_bootstrap(subset
);
755 } else if (previous
!= MACH_PORT_NULL
) {
756 debug("deallocating old notification port (%x) for requestor %x",
757 previous
, requestor_port
);
758 result
= mach_port_deallocate(
761 if (result
!= KERN_SUCCESS
)
762 kern_fatal(result
, "mach_port_deallocate");
765 info("Created bootstrap subset %x parent %x requestor %x",
766 new_bootstrap_port
, bootstrap_port
, requestor_port
);
767 *subset_port
= new_bootstrap_port
;
768 return BOOTSTRAP_SUCCESS
;
773 * bootstrap_create_service(mach_port_t bootstrap_port,
774 * name_t service_name,
775 * mach_port_t *service_port)
777 * Creates a service named "service_name" and returns send rights to that
778 * port in "service_port." The port may later be checked in as if this
779 * port were configured in the bootstrap configuration file.
781 * Errors: Returns appropriate kernel errors on rpc failure.
782 * Returns BOOTSTRAP_NAME_IN_USE, if service already exists.
785 x_bootstrap_create_service(
786 mach_port_t bootstrap_port
,
788 mach_port_t
*service_port
)
792 bootstrap_info_t
*bootstrap
;
793 kern_return_t result
;
795 bootstrap
= lookup_bootstrap_by_port(bootstrap_port
);
796 if (!bootstrap
|| !active_bootstrap(bootstrap
))
797 return BOOTSTRAP_NOT_PRIVILEGED
;
799 debug("Service creation attempt for service %s bootstrap %x",
800 service_name
, bootstrap_port
);
802 servicep
= lookup_service_by_name(bootstrap
, service_name
);
804 debug("Service creation attempt for service %s failed, "
805 "service already exists", service_name
);
806 return BOOTSTRAP_NAME_IN_USE
;
809 serverp
= lookup_server_by_port(bootstrap_port
);
811 result
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
, service_port
);
812 if (result
!= KERN_SUCCESS
)
813 kern_fatal(result
, "port_allocate");
814 result
= mach_port_insert_right(mach_task_self(), *service_port
, *service_port
, MACH_MSG_TYPE_MAKE_SEND
);
815 if (result
!= KERN_SUCCESS
)
816 kern_fatal(result
, "failed to insert send right");
821 servicep
= new_service(bootstrap
,
828 info("Created new service %x in bootstrap %x: %s",
829 servicep
->port
, bootstrap
->bootstrap_port
, service_name
);
831 return BOOTSTRAP_SUCCESS
;