118 |
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (remote_type)) |
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (remote_type)) |
119 |
return KERN_INVALID_RIGHT; |
return KERN_INVALID_RIGHT; |
120 |
|
|
|
if (local_type || local_name) |
|
|
{ |
|
|
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (local_type)) |
|
|
return KERN_INVALID_RIGHT; |
|
|
} |
|
|
|
|
121 |
/* Fetch remote port from IPC object. */ |
/* Fetch remote port from IPC object. */ |
122 |
|
|
123 |
kr = ipc_object_lookup (task->ipc_object, remote_name, &entry); |
kr = ipc_object_lookup (task->ipc_object, remote_name, &entry); |
136 |
msgh->msgh_local_port = (rtmk_port_t) entry->ie_port; |
msgh->msgh_local_port = (rtmk_port_t) entry->ie_port; |
137 |
|
|
138 |
/* Fetch local port from IPC object. */ |
/* Fetch local port from IPC object. */ |
139 |
if (local_name) |
if (local_type) |
140 |
{ |
{ |
141 |
|
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (local_type)) |
142 |
|
return KERN_INVALID_RIGHT; |
143 |
|
|
144 |
kr = ipc_object_lookup (task->ipc_object, local_name, &entry); |
kr = ipc_object_lookup (task->ipc_object, local_name, &entry); |
145 |
if (kr) |
if (kr) |
146 |
return kr; |
return kr; |
483 |
} |
} |
484 |
else |
else |
485 |
{ |
{ |
486 |
assert (0); |
struct vm_map_copy *copy = *(struct vm_map_copy **) data_ptr; |
487 |
} |
vm_offset_t dst_addr; |
|
} |
|
|
|
|
|
/* Calulcat length of inline data and skip over it. */ |
|
|
if (LIKELY (type->msgt_inline)) |
|
|
start = WORD_ALIGN (data_ptr + length); |
|
|
else |
|
|
start = data_ptr + sizeof (vm_offset_t); |
|
|
} |
|
|
return KERN_SUCCESS; |
|
|
} |
|
|
|
|
|
/* Convert message stored in KMSG to intermedate format where port |
|
|
names are resolved to ipc_port structures and out-of-line data |
|
|
in mapped into kernel address space. */ |
|
|
kern_return_t |
|
|
copyin_body (struct task *task, struct ipc_kmsg *kmsg) |
|
|
{ |
|
|
struct rtmk_msg_type_long *type_long; |
|
|
struct rtmk_msg_type *type; |
|
|
struct ipc_entry *entry; |
|
|
vm_offset_t start, end; |
|
|
kern_return_t kr; |
|
|
|
|
|
start = (vm_offset_t) (&kmsg->header + 1); |
|
|
end = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length; |
|
|
|
|
|
/* Loop through all type elements of the message body. */ |
|
488 |
|
|
489 |
while (start < end) |
kr = vm_map_copyout (task->map, copy, & dst_addr); |
490 |
{ |
if (kr) |
491 |
unsigned int header_size, number, length, size, i; |
assert (kr == KERN_SUCCESS); |
492 |
vm_offset_t data_ptr; |
*(vm_offset_t *) data_ptr = dst_addr; |
|
|
|
|
/* If we we have a long format message type header we |
|
|
get length and number fields from long structure. */ |
|
|
type = (struct rtmk_msg_type *) start; |
|
|
size = type->msgt_length; |
|
|
|
|
|
if (LIKELY (! type->msgt_long)) |
|
|
{ |
|
|
header_size = sizeof (struct rtmk_msg_type); |
|
|
number = type->msgt_number; |
|
|
} |
|
|
else |
|
|
{ |
|
|
type_long = (struct rtmk_msg_type_long *) type; |
|
|
header_size = sizeof (struct rtmk_msg_type_long); |
|
|
number = type_long->msgtl_number; |
|
|
} |
|
|
|
|
|
/* DATA_PTR points to where the inline data begins. */ |
|
|
data_ptr = ((vm_offset_t) type) + header_size; |
|
|
|
|
|
/* If TYPE->MSGT_TYPE specifys any port type we must |
|
|
handle right manipulation. This is a pretty common case. */ |
|
|
if (RTMK_MSG_TYPE_PORT_ANY (type->msgt_type)) |
|
|
{ |
|
|
rtmk_port_t *port_name; |
|
|
struct ipc_port *port; |
|
|
|
|
|
/* ??? ports can not be in out-of-line memory? */ |
|
|
assert (type->msgt_inline == true); |
|
|
port_name = (rtmk_port_t *) data_ptr; |
|
|
|
|
|
/* Loop through all elements and take actions upon them. */ |
|
|
for (i = 0; i < number; i++) |
|
|
{ |
|
|
if (port_name [i]) |
|
|
{ |
|
|
kr = ipc_object_lookup (task->ipc_object, port_name [i], |
|
|
& entry); |
|
|
if (kr != KERN_SUCCESS) |
|
|
return kr; |
|
|
|
|
|
port = entry->ie_port; |
|
|
} |
|
|
else |
|
|
port = 0; |
|
|
|
|
|
/* Store pointer to port structure in place for port name. */ |
|
|
port_name [i] = (rtmk_port_t) port; |
|
493 |
} |
} |
494 |
} |
} |
|
|
|
|
/* Out-of-line memory. ??? not supported yet, just skip it. */ |
|
|
else if (type->msgt_inline == false) |
|
|
{ |
|
|
/* ??? handle OOL memory here. */ |
|
|
} |
|
495 |
|
|
496 |
/* Calulcat length of inline data and skip over it. */ |
/* Calulcat length of inline data and skip over it. */ |
|
length = ((number * size) + 7) >> 3; |
|
497 |
if (LIKELY (type->msgt_inline)) |
if (LIKELY (type->msgt_inline)) |
498 |
start = WORD_ALIGN (data_ptr + length); |
start = WORD_ALIGN (data_ptr + length); |
499 |
else |
else |
500 |
start = data_ptr + sizeof (rtmk_port_t *); /* ??? ptr */ |
start = data_ptr + sizeof (vm_offset_t); |
501 |
} |
} |
502 |
return KERN_SUCCESS; |
return KERN_SUCCESS; |
503 |
} |
} |
504 |
|
|
|
/* Convert message stored in KMSG from intermedate format to format |
|
|
that can be directly copied to user-land task. Out-of-line data |
|
|
is mapped in TASK's addres space, and ports are resolved. */ |
|
|
static kern_return_t |
|
|
copyout_body (struct task *task, struct ipc_kmsg *kmsg) |
|
|
{ |
|
|
struct rtmk_msg_type_long *type_long; |
|
|
struct rtmk_msg_type *type; |
|
|
vm_offset_t start, end; |
|
|
kern_return_t kr; |
|
|
|
|
|
start = (vm_offset_t) (&kmsg->header + 1); |
|
|
end = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length; |
|
|
|
|
|
/* Loop through all type elements of the message body. */ |
|
|
|
|
|
while (start < end) |
|
|
{ |
|
|
unsigned int header_size, number, length, size, i; |
|
|
vm_offset_t data_ptr; |
|
|
|
|
|
/* If we we have a long format message type header we |
|
|
get length and number fields from long structure. */ |
|
|
type = (struct rtmk_msg_type *) start; |
|
|
size = type->msgt_length; |
|
|
|
|
|
if (LIKELY (! type->msgt_long)) |
|
|
{ |
|
|
header_size = sizeof (struct rtmk_msg_type); |
|
|
number = type->msgt_number; |
|
|
} |
|
|
else |
|
|
{ |
|
|
type_long = (struct rtmk_msg_type_long *) type; |
|
|
header_size = sizeof (struct rtmk_msg_type_long); |
|
|
number = type_long->msgtl_number; |
|
|
} |
|
|
|
|
|
/* DATA_PTR points to where the inline data begins. */ |
|
|
data_ptr = ((vm_offset_t) type) + header_size; |
|
|
|
|
|
/* If TYPE->MSGT_TYPE specifys any port type we must |
|
|
handle right manipulation. This is a pretty common case. */ |
|
|
if (RTMK_MSG_TYPE_PORT_ANY (type->msgt_type)) |
|
|
{ |
|
|
struct ipc_port **port; |
|
|
rtmk_port_t *port_name; |
|
|
|
|
|
/* ??? ports can not be in out-of-line memory? */ |
|
|
assert (type->msgt_inline == true); |
|
|
|
|
|
port_name = (rtmk_port_t *) data_ptr; |
|
|
port = (struct ipc_port **) data_ptr; |
|
|
|
|
|
/* Loop through all elements and take actions upon them. */ |
|
|
for (i = 0; i < number; i++) |
|
|
{ |
|
|
if (port [i]) |
|
|
{ |
|
|
kr = ipc_object_copyout (task->ipc_object, port [i], |
|
|
type->msgt_type, & port_name [i]); |
|
|
if (kr != KERN_SUCCESS) |
|
|
return kr; |
|
|
} |
|
|
else |
|
|
port_name [i] = RTMK_PORT_NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Out-of-line memory. ??? not supported yet, just skip it. */ |
|
|
else if (type->msgt_inline == false) |
|
|
{ |
|
|
/* ??? */ |
|
|
} |
|
|
|
|
|
/* Calulcat length of inline data and skip over it. */ |
|
|
length = ((number * size) + 7) >> 3; |
|
|
if (LIKELY (type->msgt_inline)) |
|
|
start = WORD_ALIGN (data_ptr + length); |
|
|
else |
|
|
start = data_ptr + sizeof (rtmk_port_t *); /* ??? ptr */ |
|
|
} |
|
|
return KERN_SUCCESS; |
|
|
} |
|
505 |
|
|
506 |
static kern_return_t |
static kern_return_t |
507 |
copyout_header (struct task *task, struct ipc_kmsg *kmsg) |
copyout_header (struct task *task, struct ipc_kmsg *kmsg) |