#include "configd.h"
#include "configd_server.h"
#include "session.h"
#include <bsm/libbsm.h>
#include <sys/types.h>
#include <unistd.h>
__private_extern__
int
__SCDynamicStoreOpen(SCDynamicStoreRef *store, CFStringRef name)
{
*store = (SCDynamicStoreRef)__SCDynamicStoreCreatePrivate(NULL, name, NULL, NULL);
if (storeData == NULL) {
sessionData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
storeData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
patternData = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
changedKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
deferredRemovals = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
removedSessionKeys = CFSetCreateMutable(NULL,
0,
&kCFTypeSetCallBacks);
}
return kSCStatusOK;
}
static CFStringRef
openMPCopyDescription(const void *info)
{
return CFStringCreateWithFormat(NULL, NULL, CFSTR("<SCDynamicStore MP>"));
}
__private_extern__
kern_return_t
_configopen(mach_port_t server,
xmlData_t nameRef,
mach_msg_type_number_t nameLen,
xmlData_t optionsRef,
mach_msg_type_number_t optionsLen,
mach_port_t *newServer,
int *sc_status,
audit_token_t audit_token)
{
CFDictionaryRef info;
serverSessionRef mySession;
CFStringRef name = NULL;
CFMutableDictionaryRef newInfo;
mach_port_t oldNotify;
CFDictionaryRef options = NULL;
CFStringRef sessionKey;
kern_return_t status;
SCDynamicStorePrivateRef storePrivate;
CFBooleanRef useSessionKeys = NULL;
*sc_status = kSCStatusOK;
if (!_SCUnserializeString(&name, NULL, (void *)nameRef, nameLen)) {
*sc_status = kSCStatusFailed;
}
if ((optionsRef != NULL) && (optionsLen > 0)) {
if (!_SCUnserialize((CFPropertyListRef *)&options, NULL, (void *)optionsRef, optionsLen)) {
*sc_status = kSCStatusFailed;
}
}
if (*sc_status != kSCStatusOK) {
goto done;
}
if (!isA_CFString(name)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
if (options != NULL) {
if (!isA_CFDictionary(options)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
useSessionKeys = CFDictionaryGetValue(options, kSCDynamicStoreUseSessionKeys);
if (useSessionKeys != NULL) {
if (!isA_CFBoolean(useSessionKeys)) {
*sc_status = kSCStatusInvalidArgument;
goto done;
}
}
}
mySession = addSession(server, openMPCopyDescription);
if (mySession == NULL) {
SC_log(LOG_NOTICE, "session is already open");
*sc_status = kSCStatusFailed;
goto done;
}
*newServer = mySession->key;
__MACH_PORT_DEBUG(TRUE, "*** _configopen (after addSession)", *newServer);
mySession->auditToken = audit_token;
mySession->serverRunLoopSource = CFMachPortCreateRunLoopSource(NULL, mySession->serverPort, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(),
mySession->serverRunLoopSource,
kCFRunLoopDefaultMode);
SC_trace(_configd_trace, "open : %5d : %@\n",
*newServer,
name);
*sc_status = __SCDynamicStoreOpen(&mySession->store, name);
storePrivate = (SCDynamicStorePrivateRef)mySession->store;
storePrivate->server = *newServer;
if (useSessionKeys != NULL) {
storePrivate->useSessionKeys = CFBooleanGetValue(useSessionKeys);
}
status = mach_port_request_notification(mach_task_self(),
*newServer,
MACH_NOTIFY_NO_SENDERS,
1,
*newServer,
MACH_MSG_TYPE_MAKE_SEND_ONCE,
&oldNotify);
if (status != KERN_SUCCESS) {
SC_log(LOG_NOTICE, "mach_port_request_notification() failed: %s", mach_error_string(status));
cleanupSession(*newServer);
*newServer = MACH_PORT_NULL;
*sc_status = kSCStatusFailed;
goto done;
}
__MACH_PORT_DEBUG(TRUE, "*** _configopen (after mach_port_request_notification)", *newServer);
if (oldNotify != MACH_PORT_NULL) {
SC_log(LOG_NOTICE, "oldNotify != MACH_PORT_NULL");
}
sessionKey = CFStringCreateWithFormat(NULL, NULL, CFSTR("%d"), *newServer);
info = CFDictionaryGetValue(sessionData, sessionKey);
if (info != NULL) {
newInfo = CFDictionaryCreateMutableCopy(NULL, 0, info);
} else {
newInfo = CFDictionaryCreateMutable(NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
CFDictionarySetValue(newInfo, kSCDName, name);
CFDictionarySetValue(sessionData, sessionKey, newInfo);
CFRelease(newInfo);
CFRelease(sessionKey);
done :
if (name != NULL) CFRelease(name);
if (options != NULL) CFRelease(options);
return KERN_SUCCESS;
}