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);
	}
}
Beispiel #2
0
/*
 * 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;
}