#include <syslog.h>
#include <unistd.h>
#include <grp.h>
#include <pwd.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/mach_error.h>
#include <servers/bootstrap.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOReturn.h>
#include "FakeUPSPlugin.h"
extern "C"
{
#include <IOKit/IOCFUnserialize.h>
#include "fakeupsServer.h" }
#define kUPSBootstrapServerName "com.apple.FakeUPS.control"
#define kSysLogLevel LOG_ERR
void initMigServer(void);
void mig_server_callback(
CFMachPortRef port,
void *msg,
CFIndex size,
void *info);
static boolean_t pm_mig_demux(
mach_msg_header_t * request,
mach_msg_header_t * reply);
extern "C" {
boolean_t fakeups_server(
mach_msg_header_t *,
mach_msg_header_t *);
}
kern_return_t _fakeups_set_properties
(
mach_port_t server,
vm_offset_t properties,
mach_msg_type_number_t propertiesCnt,
int *return_val
)
{
CFTypeRef unwrapped_data = NULL;
CFDictionaryRef *transmitted_properties = NULL;
CFStringRef *errorResultString = NULL;
unwrapped_data = IOCFUnserialize(
(const char *)properties, kCFAllocatorDefault,
0, errorResultString);
if( unwrapped_data )
{
transmitted_properties = (CFDictionaryRef *)unwrapped_data;
} else {
*return_val = kIOReturnError;
goto exit;
}
CFShow(transmitted_properties);
exit:
return KERN_SUCCESS;
}
void initMigServer(void)
{
#if 0
kern_return_t kern_result = 0;
CFMachPortRef cf_mach_port = 0;
CFRunLoopSourceRef cfmp_rls = 0;
mach_port_t our_port;
cf_mach_port = CFMachPortCreate(0, mig_server_callback, 0, 0);
if(!cf_mach_port) {
syslog(kSysLogLevel, "error error creating CFMachPort\n");
goto bail;
}
our_port = CFMachPortGetPort(cf_mach_port);
cfmp_rls = CFMachPortCreateRunLoopSource(0, cf_mach_port, 0);
if(!cfmp_rls) {
syslog(kSysLogLevel, "error error no CFMachPort RunLoopSource!\n");
goto bail;
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), cfmp_rls, kCFRunLoopDefaultMode);
kern_result = bootstrap_create_service(
bootstrap_port,
kUPSBootstrapServerName,
&our_port);
if (BOOTSTRAP_SUCCESS != kern_result) {
goto bail;
}
kern_result = bootstrap_check_in(
bootstrap_port,
kUPSBootstrapServerName,
&our_port);
if (BOOTSTRAP_SUCCESS != kern_result) {
goto bail;
}
switch (kern_result) {
case BOOTSTRAP_NOT_PRIVILEGED:
syslog(kSysLogLevel, "UPSFaker exit: BOOTSTRAP_NOT_PRIVILIGED");
break;
case BOOTSTRAP_SERVICE_ACTIVE:
syslog(kSysLogLevel, "UPSFaker exit: BOOTSTRAP_SERVICE_ACTIVE");
break;
default:
syslog(kSysLogLevel, "UPSFaker exit: undefined mig error 0x%08x", kern_result);
break;
}
bail:
if(cfmp_rls) CFRelease(cfmp_rls);
#endif
return;
}
static boolean_t pm_mig_demux(
mach_msg_header_t * request,
mach_msg_header_t * reply)
{
boolean_t processed = FALSE;
processed = fakeups_server(request, reply);
if(processed) return true;
reply->msgh_bits = MACH_MSGH_BITS(
MACH_MSGH_BITS_REMOTE(request->msgh_bits), 0);
reply->msgh_remote_port = request->msgh_remote_port;
reply->msgh_size = sizeof(mig_reply_error_t);
reply->msgh_local_port = MACH_PORT_NULL;
reply->msgh_id = request->msgh_id + 100;
((mig_reply_error_t *)reply)->NDR = NDR_record;
((mig_reply_error_t *)reply)->RetCode = MIG_BAD_ID;
return processed;
}
__private_extern__ void mig_server_callback(
CFMachPortRef port,
void *msg,
CFIndex size,
void *info)
{
mig_reply_error_t * bufRequest = (mig_reply_error_t *)msg;
mig_reply_error_t * bufReply = (mig_reply_error_t *) CFAllocatorAllocate(
NULL, _fakeups_subsystem.maxsize, 0);
mach_msg_return_t mr;
int options;
(void) pm_mig_demux(&bufRequest->Head, &bufReply->Head);
if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
(bufReply->RetCode != KERN_SUCCESS)) {
if (bufReply->RetCode == MIG_NO_REPLY) {
CFAllocatorDeallocate(NULL, bufReply);
return;
}
bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
mach_msg_destroy(&bufRequest->Head);
}
if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
mach_msg_destroy(&bufReply->Head);
}
CFAllocatorDeallocate(NULL, bufReply);
return;
}
options = MACH_SEND_MSG;
if ( MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits)
== MACH_MSG_TYPE_MOVE_SEND_ONCE)
{
options |= MACH_SEND_TIMEOUT;
}
mr = mach_msg(&bufReply->Head,
options,
bufReply->Head.msgh_size,
0,
MACH_PORT_NULL,
MACH_MSG_TIMEOUT_NONE,
MACH_PORT_NULL);
switch (mr) {
case MACH_SEND_INVALID_DEST:
case MACH_SEND_TIMED_OUT:
mach_msg_destroy(&bufReply->Head);
break;
default :
break;
}
CFAllocatorDeallocate(NULL, bufReply);
}