void delete_bootstrap_services(bootstrap_info_t *bootstrap) { server_t *serverp; service_t *servicep; service_t *next; for ( servicep = FIRST(services) ; !IS_END(servicep, services) ; servicep = next) { next = NEXT(servicep); if (bootstrap != servicep->bootstrap) continue; if (!servicep->isActive || !servicep->server) { delete_service(servicep); continue; } serverp = servicep->server; delete_service(servicep); serverp->active_services--; if (!active_server(serverp)) delete_server(serverp); } }
/* * kern_return_t * bootstrap_register(mach_port_t bootstrap_port, * name_t service_name, * mach_port_t service_port) * * Registers send rights for the port service_port for the service named by * service_name. Registering a declared service or registering a service for * which bootstrap has receive rights via a port backup notification is * allowed. * The previous service port will be deallocated. Restarting services wishing * to resume service for previous clients must first attempt to checkin to the * service. * * Errors: Returns appropriate kernel errors on rpc failure. * Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to * unprivileged bootstrap port. * Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been * register or checked-in. */ kern_return_t x_bootstrap_register( mach_port_t bootstrap_port, name_t service_name, mach_port_t service_port) { kern_return_t result; service_t *servicep; server_t *serverp; bootstrap_info_t *bootstrap; mach_port_t old_port; debug("Register attempt for service %s port %x", service_name, service_port); /* * Validate the bootstrap. */ bootstrap = lookup_bootstrap_by_port(bootstrap_port); if (!bootstrap || !active_bootstrap(bootstrap)) return BOOTSTRAP_NOT_PRIVILEGED; /* * If this bootstrap port is for a server, or it's an unprivileged * bootstrap can't register the port. */ serverp = lookup_server_by_port(bootstrap_port); servicep = lookup_service_by_name(bootstrap, service_name); if (servicep && servicep->server && servicep->server != serverp) return BOOTSTRAP_NOT_PRIVILEGED; if (servicep == NULL || servicep->bootstrap != bootstrap) { servicep = new_service(bootstrap, service_name, service_port, ACTIVE, REGISTERED, NULL_SERVER); debug("Registered new service %s", service_name); } else { if (servicep->isActive) { debug("Register: service %s already active, port %x", servicep->name, servicep->port); ASSERT(!canReceive(servicep->port)); return BOOTSTRAP_SERVICE_ACTIVE; } old_port = servicep->port; if (servicep->servicetype == DECLARED) { servicep->servicetype = REGISTERED; if (servicep->server) { ASSERT(servicep->server == serverp); ASSERT(active_server(serverp)); servicep->server = NULL_SERVER; serverp->activity++; } result = mach_port_mod_refs( mach_task_self(), old_port, MACH_PORT_RIGHT_RECEIVE, -1); if (result != KERN_SUCCESS) kern_fatal(result, "mach_port_mod_refs"); } result = mach_port_deallocate( mach_task_self(), old_port); if (result != KERN_SUCCESS) kern_fatal(result, "mach_port_mod_refs"); servicep->port = service_port; servicep->isActive = TRUE; debug("Re-registered inactive service %x bootstrap %x: %s", servicep->port, servicep->bootstrap->bootstrap_port, service_name); } /* detect the new service port going dead */ result = mach_port_request_notification( mach_task_self(), service_port, MACH_NOTIFY_DEAD_NAME, 0, notify_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_port); if (result != KERN_SUCCESS) { debug("Can't request notification on service %x bootstrap %x: %s", service_port, servicep->bootstrap->bootstrap_port, "must be dead"); delete_service(servicep); return BOOTSTRAP_SUCCESS; } else if (old_port != MACH_PORT_NULL) { debug("deallocating old notification port (%x) for service %x", old_port, service_port); result = mach_port_deallocate( mach_task_self(), old_port); if (result != KERN_SUCCESS) kern_fatal(result, "mach_port_deallocate"); } info("Registered service %x bootstrap %x: %s", servicep->port, servicep->bootstrap->bootstrap_port, servicep->name); return BOOTSTRAP_SUCCESS; }