SCDNotifierInformViaMachPort.c [plain text]
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include "SCDynamicStoreInternal.h"
#include "config.h"
Boolean
SCDynamicStoreNotifyMachPort(SCDynamicStoreRef store, mach_msg_id_t identifier, mach_port_t *port)
{
SCDynamicStorePrivateRef storePrivate = (SCDynamicStorePrivateRef)store;
kern_return_t status;
mach_port_t oldNotify;
int sc_status;
if (store == NULL) {
_SCErrorSet(kSCStatusNoStoreSession);
return FALSE;
}
if (storePrivate->server == MACH_PORT_NULL) {
_SCErrorSet(kSCStatusNoStoreServer);
return FALSE;
}
if (storePrivate->notifyStatus != NotifierNotRegistered) {
_SCErrorSet(kSCStatusNotifierActive);
return FALSE;
}
status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, port);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_allocate(): %s"), mach_error_string(status));
_SCErrorSet(status);
return FALSE;
}
status = mach_port_insert_right(mach_task_self(),
*port,
*port,
MACH_MSG_TYPE_MAKE_SEND);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_insert_right(): %s"), mach_error_string(status));
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
status = mach_port_request_notification(mach_task_self(),
*port,
MACH_NOTIFY_NO_SENDERS,
1,
*port,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort mach_port_request_notification(): %s"), mach_error_string(status));
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
if (oldNotify != MACH_PORT_NULL) {
SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort(): oldNotify != MACH_PORT_NULL"));
}
retry :
status = notifyviaport(storePrivate->server,
*port,
identifier,
(int *)&sc_status);
if (status != KERN_SUCCESS) {
if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
(void) mach_port_deallocate(mach_task_self(), storePrivate->server);
} else {
SCLog(TRUE, LOG_ERR, CFSTR("SCDynamicStoreNotifyMachPort notifyviaport(): %s"), mach_error_string(status));
}
storePrivate->server = MACH_PORT_NULL;
if ((status == MACH_SEND_INVALID_DEST) || (status == MIG_SERVER_DIED)) {
if (__SCDynamicStoreReconnect(store)) {
goto retry;
}
(void) mach_port_deallocate(mach_task_self(), *port);
}
(void) mach_port_mod_refs(mach_task_self(), *port, MACH_PORT_RIGHT_RECEIVE, -1);
*port = MACH_PORT_NULL;
_SCErrorSet(status);
return FALSE;
}
__MACH_PORT_DEBUG(TRUE, "*** SCDynamicStoreNotifyMachPort", *port);
storePrivate->notifyStatus = Using_NotifierInformViaMachPort;
return TRUE;
}