#include "cci_common.h"
#include <syslog.h>
#include <Kerberos/kipc_server.h>
#include "cci_migServer.h"
#include "ccs_server.h"
static kipc_boolean_t ccs_server_demux (mach_msg_header_t *request,
mach_msg_header_t *reply)
{
kipc_boolean_t handled = false;
if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
kern_return_t err = KERN_SUCCESS;
handled = 1;
err = mach_port_mod_refs (mach_task_self (), request->msgh_local_port,
MACH_PORT_RIGHT_RECEIVE, -1);
if (!err) {
err = ccs_server_remove_client (request->msgh_local_port);
}
cci_check_error (err);
}
if (!handled) {
handled = ccapi_server (request, reply);
}
return handled;
}
int main (int argc, const char *argv[])
{
cc_int32 err = 0;
openlog (argv[0], LOG_CONS | LOG_PID, LOG_AUTH);
syslog (LOG_INFO, "Starting up.");
if (!err) {
err = ccs_server_initialize ();
}
if (!err) {
err = kipc_server_run_server (ccs_server_demux);
}
ccs_server_cleanup ();
syslog (LOG_NOTICE, "Exiting: %s (%d)", kipc_error_string (err), err);
return err ? 1 : 0;
}
kern_return_t ccs_mipc_create_client_connection (mach_port_t in_server_port,
mach_port_t *out_connection_port)
{
kern_return_t err = KERN_SUCCESS;
mach_port_t connection_port = MACH_PORT_NULL;
mach_port_t old_notification_target = MACH_PORT_NULL;
if (!err) {
err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &connection_port);
}
if (!err) {
err = mach_port_move_member (mach_task_self (), connection_port, kipc_server_get_listen_portset ());
}
if (!err) {
err = mach_port_request_notification (mach_task_self (), connection_port,
MACH_NOTIFY_NO_SENDERS, 1, connection_port,
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target );
}
if (!err) {
err = ccs_server_add_client (connection_port);
}
if (!err) {
*out_connection_port = connection_port;
connection_port = MACH_PORT_NULL;
}
if (connection_port != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), connection_port); }
return cci_check_error (err);
}
kern_return_t ccs_mipc_handle_message (mach_port_t in_connection_port,
cci_mipc_inl_request_t in_inl_request,
mach_msg_type_number_t in_inl_requestCnt,
cci_mipc_ool_request_t in_ool_request,
mach_msg_type_number_t in_ool_requestCnt,
cci_mipc_inl_reply_t out_inl_reply,
mach_msg_type_number_t *out_inl_replyCnt,
cci_mipc_ool_reply_t *out_ool_reply,
mach_msg_type_number_t *out_ool_replyCnt )
{
kern_return_t err = KERN_SUCCESS;
cci_stream_t request_stream = NULL;
cci_stream_t reply_stream = NULL;
if (!err) {
err = cci_stream_new (&request_stream);
}
if (!err) {
if (in_inl_requestCnt) {
err = cci_stream_write (request_stream, in_inl_request, in_inl_requestCnt);
} else if (in_ool_requestCnt) {
err = cci_stream_write (request_stream, in_ool_request, in_ool_requestCnt);
} else {
err = cci_check_error (ccErrBadInternalMessage);
}
}
if (!err) {
err = ccs_server_ipc (request_stream, &reply_stream);
}
if (!err) {
mach_msg_type_number_t reply_length = cci_stream_size (reply_stream);
if (reply_length > *out_inl_replyCnt) {
cci_mipc_ool_reply_t ool_reply = NULL;
mach_msg_type_number_t ool_reply_length = 0;
cci_debug_printf ("%s choosing out of line buffer (size is %d)",
__FUNCTION__, reply_length);
err = vm_read (mach_task_self (),
(vm_address_t) cci_stream_data (reply_stream), reply_length,
(vm_address_t *) &ool_reply, &ool_reply_length);
if (!err) {
*out_inl_replyCnt = 0;
*out_ool_reply = ool_reply;
*out_ool_replyCnt = ool_reply_length;
ool_reply = NULL;
ool_reply_length = 0;
}
if (ool_reply_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_reply, ool_reply_length); }
} else {
*out_ool_replyCnt = 0;
*out_inl_replyCnt = reply_length;
memcpy (out_inl_reply, cci_stream_data (reply_stream), reply_length);
}
}
cci_stream_release (request_stream);
cci_stream_release (reply_stream);
if (in_ool_requestCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_request, in_ool_requestCnt); }
return cci_check_error (err);
}