98 |
kmem_free (VM_MAP_KERNEL (), (vm_offset_t) kmsg); |
kmem_free (VM_MAP_KERNEL (), (vm_offset_t) kmsg); |
99 |
} |
} |
100 |
|
|
101 |
|
/* Copy in header in KMSG to intermediate format (stored both |
102 |
|
in the message header and the kmsg structure). We return |
103 |
|
normal kernel return codes. TASK is that task that the |
104 |
|
message comes from. The IPC object is locked when this is |
105 |
|
called. */ |
106 |
static kern_return_t |
static kern_return_t |
107 |
copyin_header (struct task *task, struct ipc_kmsg *kmsg) |
copyin_header (struct task *task, struct ipc_kmsg *kmsg) |
108 |
{ |
{ |
113 |
kern_return_t kr; |
kern_return_t kr; |
114 |
|
|
115 |
remote_name = msgh->msgh_remote_port; |
remote_name = msgh->msgh_remote_port; |
116 |
remote_type = RTMK_MSGH_BITS_REMOTE (msgh->msgh_bits); |
local_name = msgh->msgh_local_port; |
|
|
|
|
local_name = msgh->msgh_local_port; |
|
|
local_type = RTMK_MSGH_BITS_LOCAL (msgh->msgh_bits); |
|
|
|
|
|
/* First of all check so that we got a valid header. */ |
|
|
|
|
|
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (remote_type)) |
|
|
return KERN_INVALID_RIGHT; |
|
|
|
|
|
/* Fetch remote port from IPC object. */ |
|
|
|
|
|
kr = ipc_object_lookup (task->ipc_object, remote_name, &entry); |
|
|
if (kr) |
|
|
return kr; |
|
|
|
|
|
if (! (IE_BITS_STATUS (entry->ie_bits) & IE_BITS_VALID)) |
|
|
return KERN_INVALID_RIGHT; |
|
|
|
|
|
if (! (IE_BITS_RIGHTS (entry->ie_bits) & RTMK_PORT_TYPE_SEND_RIGHTS)) |
|
|
return KERN_INVALID_RIGHT; |
|
117 |
|
|
118 |
/* ??? handle send-once right here? */ |
switch (msgh->msgh_bits |
119 |
|
& (RTMK_MSGH_BITS_LOCAL_MASK | RTMK_MSGH_BITS_REMOTE_MASK)) |
|
kmsg->destination_port = entry->ie_port; |
|
|
msgh->msgh_local_port = (rtmk_port_t) entry->ie_port; |
|
|
|
|
|
/* Fetch local port from IPC object. */ |
|
|
if (local_type) |
|
120 |
{ |
{ |
121 |
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (local_type)) |
/* Task is sending a RPC request to remote port. |
122 |
return KERN_INVALID_RIGHT; |
We do nothing really except fetching ports. */ |
123 |
|
case RTMK_MSGH_BITS (RTMK_MSG_TYPE_COPY_SEND, |
124 |
kr = ipc_object_lookup (task->ipc_object, local_name, &entry); |
RTMK_MSG_TYPE_MAKE_SEND_ONCE): |
125 |
if (kr) |
{ |
126 |
return kr; |
/* Fetch remote port from IPC object. */ |
127 |
|
kr = ipc_object_copyin (task->ipc_object, remote_name, |
128 |
if (! (IE_BITS_STATUS (entry->ie_bits) & IE_BITS_VALID)) |
RTMK_MSGH_BITS_REMOTE (msgh->msgh_bits), |
129 |
return KERN_INVALID_RIGHT; |
& kmsg->destination_port); |
130 |
|
if (kr) |
131 |
if (! (IE_BITS_RIGHTS (entry->ie_bits) & RTMK_PORT_TYPE_RECEIVE)) |
panic ("kr = %d", kr); |
132 |
return KERN_INVALID_RIGHT; |
msgh->msgh_local_port = (rtmk_port_t) kmsg->destination_port; |
133 |
|
|
134 |
/* ??? handle send-one right here? */ |
/* Fetch local port from IPC object. */ |
135 |
|
kr = ipc_object_copyin (task->ipc_object, local_name, |
136 |
|
RTMK_MSGH_BITS_LOCAL (msgh->msgh_bits), |
137 |
|
& kmsg->reply_port); |
138 |
|
if (kr) |
139 |
|
panic ("kr = %d", kr); |
140 |
|
msgh->msgh_remote_port = (rtmk_port_t) kmsg->reply_port; |
141 |
|
|
142 |
|
break; |
143 |
|
} |
144 |
|
|
145 |
kmsg->reply_port = entry->ie_port; |
/* Task is sending a RPC reply. We should remove send-once |
146 |
msgh->msgh_remote_port = (rtmk_port_t) entry->ie_port; |
rights from IPC object and possible deallocate entry. */ |
147 |
} |
case RTMK_MSGH_BITS (RTMK_MSG_TYPE_MOVE_SEND_ONCE, |
148 |
else |
0): |
149 |
{ |
{ |
150 |
kmsg->reply_port = 0; |
/* Fetch remote port from IPC object. */ |
151 |
msgh->msgh_remote_port = 0; |
kr = ipc_object_copyin (task->ipc_object, remote_name, |
152 |
} |
RTMK_MSGH_BITS_REMOTE (msgh->msgh_bits), |
153 |
|
& kmsg->destination_port); |
154 |
|
if (kr) |
155 |
|
panic ("kr = %d", kr); |
156 |
|
msgh->msgh_local_port = (rtmk_port_t) kmsg->destination_port; |
157 |
|
msgh->msgh_remote_port = 0; |
158 |
|
|
159 |
|
kmsg->reply_port = 0; |
160 |
|
msgh->msgh_remote_port = 0; |
161 |
|
|
162 |
|
break; |
163 |
|
} |
164 |
|
|
165 |
|
default: |
166 |
|
{ |
167 |
|
remote_type = RTMK_MSGH_BITS_REMOTE (msgh->msgh_bits); |
168 |
|
local_type = RTMK_MSGH_BITS_LOCAL (msgh->msgh_bits); |
169 |
|
|
170 |
|
/* First of all check so that we got a valid header. */ |
171 |
|
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (remote_type)) |
172 |
|
return KERN_INVALID_RIGHT; |
173 |
|
|
174 |
|
/* Fetch remote port from IPC object. */ |
175 |
|
kr = ipc_object_lookup (task->ipc_object, remote_name, &entry); |
176 |
|
if (kr) |
177 |
|
panic ("kr = %d", kr); |
178 |
|
|
179 |
|
|
180 |
|
if (! (IE_BITS_STATUS (entry->ie_bits) & IE_BITS_VALID)) |
181 |
|
return KERN_INVALID_RIGHT; |
182 |
|
|
183 |
|
if (! (IE_BITS_RIGHTS (entry->ie_bits) & RTMK_PORT_TYPE_SEND_RIGHTS)) |
184 |
|
return KERN_INVALID_RIGHT; |
185 |
|
|
186 |
|
|
187 |
|
/* Fetch local port from IPC object. */ |
188 |
|
if (local_type) |
189 |
|
{ |
190 |
|
if (! RTMK_MSG_TYPE_PORT_ANY_SEND (local_type)) |
191 |
|
return KERN_INVALID_RIGHT; |
192 |
|
|
193 |
|
kr = ipc_object_lookup (task->ipc_object, local_name, &entry); |
194 |
|
if (kr) |
195 |
|
panic ("kr = %d", kr); |
196 |
|
|
197 |
|
if (! (IE_BITS_STATUS (entry->ie_bits) & IE_BITS_VALID)) |
198 |
|
return KERN_INVALID_RIGHT; |
199 |
|
|
200 |
|
if (! (IE_BITS_RIGHTS (entry->ie_bits) & RTMK_PORT_TYPE_RECEIVE)) |
201 |
|
return KERN_INVALID_RIGHT; |
202 |
|
|
203 |
|
/* ??? handle send-one right here? */ |
204 |
|
|
205 |
|
kmsg->reply_port = entry->ie_port; |
206 |
|
msgh->msgh_remote_port = (rtmk_port_t) entry->ie_port; |
207 |
|
} |
208 |
|
else |
209 |
|
{ |
210 |
|
kmsg->reply_port = 0; |
211 |
|
msgh->msgh_remote_port = 0; |
212 |
|
} |
213 |
|
break; |
214 |
|
} |
215 |
|
} |
216 |
return KERN_SUCCESS; |
return KERN_SUCCESS; |
217 |
} |
} |
218 |
|
|
227 |
struct rtmk_msg_type_long *type_long; |
struct rtmk_msg_type_long *type_long; |
228 |
struct rtmk_msg_type *type; |
struct rtmk_msg_type *type; |
229 |
vm_offset_t start, end; |
vm_offset_t start, end; |
230 |
|
int port_p; |
231 |
|
|
232 |
start = (vm_offset_t) (&kmsg->header + 1); |
start = (vm_offset_t) (&kmsg->header + 1); |
233 |
end = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length; |
end = ((vm_offset_t) (&kmsg->header)) + kmsg->header.msgh_length; |
237 |
while (start < end) |
while (start < end) |
238 |
{ |
{ |
239 |
unsigned int header_size, number, length, size; |
unsigned int header_size, number, length, size; |
240 |
vm_offset_t data_ptr; |
vm_offset_t data_ptr, source_data; |
241 |
|
|
242 |
/* If we we have a long format message type header we |
/* If we we have a long format message type header we |
243 |
get length and number fields from long structure. */ |
get length and number fields from long structure. */ |
268 |
{ |
{ |
269 |
/* The sender should supply ready-made memory |
/* The sender should supply ready-made memory |
270 |
for us, so we don't need to do anything. */ |
for us, so we don't need to do anything. */ |
271 |
|
source_data = *(vm_offset_t *) data_ptr; |
272 |
|
} |
273 |
|
else |
274 |
|
source_data = data_ptr; |
275 |
|
|
276 |
|
port_p = RTMK_MSG_TYPE_PORT_ANY (type->msgt_type); |
277 |
|
if (port_p) |
278 |
|
{ |
279 |
|
struct ipc_port **port; |
280 |
|
int i; |
281 |
|
|
282 |
|
port = (struct ipc_port **) source_data; |
283 |
|
|
284 |
|
/* Loop through all elements and take actions upon them. */ |
285 |
|
for (i = 0; i < number; i++) |
286 |
|
{ |
287 |
|
if (port[i]) |
288 |
|
ipc_object_copyin_from_kernel (port [i], type->msgt_type); |
289 |
|
} |
290 |
} |
} |
291 |
|
|
292 |
/* Calulcat length of inline data and skip over it. */ |
/* Calulcat length of inline data and skip over it. */ |
318 |
while (start < end) |
while (start < end) |
319 |
{ |
{ |
320 |
unsigned int header_size, number, length, size, port_p, i; |
unsigned int header_size, number, length, size, port_p, i; |
|
struct ipc_entry *entry; |
|
321 |
vm_offset_t data_ptr; |
vm_offset_t data_ptr; |
322 |
|
|
323 |
/* If we we have a long format message type header we |
/* If we we have a long format message type header we |
360 |
{ |
{ |
361 |
if (port_name [i]) |
if (port_name [i]) |
362 |
{ |
{ |
363 |
/* ??? not lookup, do copyin */ |
kr = ipc_object_copyin (task->ipc_object, port_name [i], |
364 |
kr = ipc_object_lookup (task->ipc_object, port_name [i], |
type->msgt_type, &port); |
|
& entry); |
|
365 |
if (kr != KERN_SUCCESS) |
if (kr != KERN_SUCCESS) |
366 |
return kr; |
panic ("kr (%d) != 0, name is %x ", kr, port_name[i]); |
367 |
|
/*return kr;*/ |
|
port = entry->ie_port; |
|
368 |
} |
} |
369 |
else |
else |
370 |
port = 0; |
port = 0; |
395 |
{ |
{ |
396 |
if (port_name [i]) |
if (port_name [i]) |
397 |
{ |
{ |
398 |
kr = ipc_object_lookup (task->ipc_object, port_name [i], |
kr = ipc_object_copyin (task->ipc_object, port_name [i], |
399 |
& entry); |
type->msgt_type, &port); |
400 |
if (kr != KERN_SUCCESS) |
if (kr != KERN_SUCCESS) |
401 |
return kr; |
return kr; |
|
port = entry->ie_port; |
|
402 |
} |
} |
403 |
else |
else |
404 |
port = 0; |
port = 0; |
589 |
|
|
590 |
if (remote_port) |
if (remote_port) |
591 |
{ |
{ |
592 |
kr = ipc_object_copyout (task->ipc_object, remote_port, remote_type, |
kr = ipc_object_copyout_dest (task->ipc_object, remote_port, remote_type, |
593 |
& remote_name); |
& remote_name); |
594 |
if (kr != KERN_SUCCESS) |
if (kr != KERN_SUCCESS) |
595 |
return kr; |
return kr; |
596 |
msgh->msgh_local_port = remote_name; |
msgh->msgh_local_port = remote_name; |
601 |
|
|
602 |
if (local_port) |
if (local_port) |
603 |
{ |
{ |
604 |
kr = ipc_object_copyout (task->ipc_object, local_port, local_type, |
kr = ipc_object_copyout (task->ipc_object, local_port, local_type, |
605 |
& local_name); |
& local_name); |
606 |
if (kr != KERN_SUCCESS) |
if (kr != KERN_SUCCESS) |
607 |
return kr; |
return kr; |
651 |
kmsg->destination_port = (struct ipc_port *) msgh->msgh_remote_port; |
kmsg->destination_port = (struct ipc_port *) msgh->msgh_remote_port; |
652 |
kmsg->reply_port = (struct ipc_port *) msgh->msgh_local_port; |
kmsg->reply_port = (struct ipc_port *) msgh->msgh_local_port; |
653 |
|
|
654 |
|
ipc_object_copyin_from_kernel (kmsg->destination_port, |
655 |
|
RTMK_MSGH_BITS_REMOTE (msgh->msgh_bits)); |
656 |
|
ipc_object_copyin_from_kernel (kmsg->reply_port, |
657 |
|
RTMK_MSGH_BITS_LOCAL (msgh->msgh_bits)); |
658 |
|
|
659 |
/* Kernel never sends simple messages and it never sends to itself. */ |
/* Kernel never sends simple messages and it never sends to itself. */ |
660 |
|
|
661 |
kmsg->complex_p = true; |
kmsg->complex_p = true; |