|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28: * All Rights Reserved.
29: *
30: * Permission to use, copy, modify and distribute this software and its
31: * documentation is hereby granted, provided that both the copyright
32: * notice and this permission notice appear in all copies of the
33: * software, derivative works or modified versions, and any portions
34: * thereof, and that both notices appear in supporting documentation.
35: *
36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon
48: * the rights to redistribute these changes.
49: */
50: /*
51: * File: kern/ipc_kobject.c
52: * Author: Rich Draves
53: * Date: 1989
54: *
55: * Functions for letting a port represent a kernel object.
56: */
57:
58: #import <mach/features.h>
59:
60: #include <mach/port.h>
61: #include <mach/kern_return.h>
62: #include <mach/message.h>
63: #include <mach/mig_errors.h>
64: #include <mach/notify.h>
65: #include <kern/ipc_kobject.h>
66: #include <ipc/ipc_object.h>
67: #include <ipc/ipc_kmsg.h>
68: #include <ipc/ipc_port.h>
69: #include <ipc/ipc_thread.h>
70:
71: #if MACH_MACHINE_ROUTINES
72: #include <machine/machine_routines.h>
73: #endif
74:
75: /* Forward Declarations */
76:
77: boolean_t
78: ipc_kobject_notify(
79: mach_msg_header_t *request_header,
80: mach_msg_header_t *reply_header);
81:
82: #include <mach/ndr.h>
83:
84: /*
85: * Routine: ipc_kobject_server
86: * Purpose:
87: * Handle a message sent to the kernel.
88: * Generates a reply message.
89: * Conditions:
90: * Nothing locked.
91: */
92:
93: ipc_kmsg_t
94: ipc_kobject_server(
95: ipc_kmsg_t request)
96: {
97: mach_msg_size_t reply_size;
98: ipc_kmsg_t reply;
99: kern_return_t kr;
100: mig_routine_t routine;
101: ipc_port_t *destp;
102:
103: if (request->ikm_header.msgh_bits & MACH_MSGH_BITS_OLD_FORMAT) {
104: reply_size = ikm_less_overhead(2048);
105: reply = ikm_alloc(reply_size);
106: if (reply == IKM_NULL) {
107: printf("ipc_kobject_server: dropping request\n");
108: ipc_kmsg_destroy(request);
109: return IKM_NULL;
110: }
111: ikm_init(reply, reply_size);
112:
113: reply->ikm_sender = KERNEL_SECURITY_ID_VALUE;
114:
115: /*
116: * Initialize reply message.
117: */
118: {
119: #define InP ((mach_msg_header_t *) &request->ikm_header)
120: #define OutP ((mig_reply_header_t *) &reply->ikm_header)
121:
122: static mach_msg_type_t RetCodeType = {
123: /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
124: /* msgt_size = */ 32,
125: /* msgt_number = */ 1,
126: /* msgt_inline = */ TRUE,
127: /* msgt_longform = */ FALSE,
128: /* msgt_unused = */ 0
129: };
130: OutP->Head.msgh_bits =
131: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0) |
132: MACH_MSGH_BITS_OLD_FORMAT;
133: OutP->Head.msgh_size = sizeof(mig_reply_header_t);
134: OutP->Head.msgh_remote_port = InP->msgh_local_port;
135: OutP->Head.msgh_local_port = MACH_PORT_NULL;
136: OutP->Head.msgh_reserved = 0;
137: OutP->Head.msgh_id = InP->msgh_id + 100;
138:
139: OutP->RetCodeType = RetCodeType;
140:
141: #undef InP
142: #undef OutP
143: }
144:
145: /*
146: * Find the server routine to call, and call it
147: * to perform the kernel function
148: */
149: #if MACH_NET
150: if (netipc_msg_send(request))
151: ((mig_reply_header_t *)
152: &reply->ikm_header)->RetCode = MIG_NO_REPLY;
153: else
154: #endif
155: {
156: extern mig_routine_t mach_server_routine(),
157: mach_port_server_routine(),
158: mach_host_server_routine();
159: #if DRIVERKIT
160: extern mig_routine_t driverServer_server_routine();
161: #endif
162:
163: #if MACH_MACHINE_ROUTINES
164: extern mig_routine_t MACHINE_SERVER_ROUTINE();
165: #endif
166:
167: if ((routine =
168: mach_server_routine(&request->ikm_header)) != 0
169: || (routine =
170: mach_host_server_routine(&request->ikm_header)) != 0
171: #if DRIVERKIT
172: || (routine =
173: driverServer_server_routine(&request->ikm_header)) != 0
174: #endif DRIVERKIT
175: #if MACH_MACHINE_ROUTINES
176: || (routine =
177: MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0
178: #endif MACH_MACHINE_ROUTINES
179: ) {
180: (*routine)(&request->ikm_header, &reply->ikm_header);
181: }
182: else
183: if (!ipc_kobject_notify(
184: &request->ikm_header,&reply->ikm_header)) {
185: ((mig_reply_header_t *)
186: &reply->ikm_header)->RetCode = MIG_BAD_ID;
187: #if MACH_IPC_TEST
188: printf("ipc_kobject_server: bogus kernel message, id=%d\n",
189: request->ikm_header.msgh_id);
190: #endif MACH_IPC_TEST
191: }
192: }
193:
194: kr = ((mig_reply_header_t *) &reply->ikm_header)->RetCode;
195: }
196: else {
197: reply_size = ikm_less_overhead(2048);
198: reply = ikm_alloc(reply_size);
199: if (reply == IKM_NULL) {
200: printf("ipc_kobject_server: dropping request\n");
201: ipc_kmsg_destroy(request);
202: return IKM_NULL;
203: }
204: ikm_init(reply, reply_size);
205:
206: reply->ikm_sender = KERNEL_SECURITY_ID_VALUE;
207:
208: /*
209: * Initialize reply message.
210: */
211: {
212: #define InP ((mach_msg_header_t *) &request->ikm_header)
213: #define OutP ((mig_reply_error_t *) &reply->ikm_header)
214:
215: OutP->NDR = NDR_record;
216: OutP->Head.msgh_size = sizeof(mig_reply_error_t);
217:
218: OutP->Head.msgh_bits =
219: MACH_MSGH_BITS(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0);
220: OutP->Head.msgh_remote_port = InP->msgh_local_port;
221: OutP->Head.msgh_local_port = MACH_PORT_NULL;
222: OutP->Head.msgh_reserved = 0;
223: OutP->Head.msgh_id = InP->msgh_id + 100;
224:
225: #undef InP
226: #undef OutP
227: }
228:
229: /*
230: * Find the server routine to call, and call it
231: * to perform the kernel function
232: */
233: {
234: extern mig_routine_t mach_port_server_routine();
235: #if MACH_DEBUG
236: extern mig_routine_t mach_debug_server_routine();
237: #endif
238:
239: if ((routine =
240: mach_port_server_routine(&request->ikm_header)) != 0
241: #if MACH_DEBUG
242: || (routine =
243: mach_debug_server_routine(&request->ikm_header)) != 0
244: #endif MACH_DEBUG
245: ) {
246: (*routine)(&request->ikm_header, &reply->ikm_header);
247: }
248: else
249: if (!ipc_kobject_notify(
250: &request->ikm_header,&reply->ikm_header)) {
251: ((mig_reply_error_t *)
252: &reply->ikm_header)->RetCode = MIG_BAD_ID;
253: #if MACH_IPC_TEST
254: printf("ipc_kobject_server: bogus kernel message, id=%d\n",
255: request->ikm_header.msgh_id);
256: #endif MACH_IPC_TEST
257: }
258: }
259:
260: if (!(reply->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX))
261: kr = ((mig_reply_error_t *) &reply->ikm_header)->RetCode;
262: else
263: kr = KERN_SUCCESS;
264: }
265:
266: /*
267: * Destroy destination. The following code differs from
268: * ipc_object_destroy in that we release the send-once
269: * right instead of generating a send-once notification
270: * (which would bring us here again, creating a loop).
271: * It also differs in that we only expect send or
272: * send-once rights, never receive rights.
273: *
274: * We set msgh_remote_port to IP_NULL so that the kmsg
275: * destroy routines don't try to destroy the port twice.
276: */
277: destp = (ipc_port_t *) &request->ikm_header.msgh_remote_port;
278: switch (MACH_MSGH_BITS_REMOTE(request->ikm_header.msgh_bits)) {
279: case MACH_MSG_TYPE_PORT_SEND:
280: ipc_port_release_send(*destp);
281: break;
282:
283: case MACH_MSG_TYPE_PORT_SEND_ONCE:
284: ipc_port_release_sonce(*destp);
285: break;
286:
287: default:
288: panic("ipc_object_destroy: strange destination rights");
289: }
290: *destp = IP_NULL;
291:
292: if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) {
293: /*
294: * The server function is responsible for the contents
295: * of the message. The reply port right is moved
296: * to the reply message, and we have deallocated
297: * the destination port right, so we just need
298: * to free the kmsg.
299: */
300:
301: /* like ipc_kmsg_put, but without the copyout */
302:
303: ikm_check_initialized(request, request->ikm_size);
304: if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
305: (ikm_cache() == IKM_NULL))
306: ikm_cache() = request;
307: else
308: ikm_free(request);
309: } else {
310: /*
311: * The message contents of the request are intact.
312: * Destroy everthing except the reply port right,
313: * which is needed in the reply message.
314: */
315:
316: request->ikm_header.msgh_local_port = MACH_PORT_NULL;
317: ipc_kmsg_destroy(request);
318: }
319:
320: if (kr == MIG_NO_REPLY) {
321: /*
322: * The server function will send a reply message
323: * using the reply port right, which it has saved.
324: */
325:
326: ikm_free(reply);
327: return IKM_NULL;
328: } else if (!IP_VALID((ipc_port_t)reply->ikm_header.msgh_remote_port)) {
329: /*
330: * Can't queue the reply message if the destination
331: * (the reply port) isn't valid.
332: */
333:
334: ipc_kmsg_destroy(reply);
335: return IKM_NULL;
336: }
337:
338: return reply;
339: }
340:
341: /*
342: * Routine: ipc_kobject_set
343: * Purpose:
344: * Make a port represent a kernel object of the given type.
345: * The caller is responsible for handling refs for the
346: * kernel object, if necessary.
347: * Conditions:
348: * Nothing locked. The port must be active.
349: */
350:
351: void
352: ipc_kobject_set(
353: ipc_port_t port,
354: ipc_kobject_t kobject,
355: ipc_kobject_type_t type)
356: {
357: ip_lock(port);
358: assert(ip_active(port));
359: port->ip_bits = (port->ip_bits &~ IO_BITS_KOTYPE) | type;
360: port->ip_kobject = kobject;
361: ip_unlock(port);
362: }
363:
364: /*
365: * Routine: ipc_kobject_destroy
366: * Purpose:
367: * Release any kernel object resources associated
368: * with the port, which is being destroyed.
369: *
370: * This should only be needed when resources are
371: * associated with a user's port. In the normal case,
372: * when the kernel is the receiver, the code calling
373: * ipc_port_dealloc_kernel should clean up the resources.
374: * Conditions:
375: * The port is not locked, but it is dead.
376: */
377:
378: void
379: ipc_kobject_destroy(port)
380: ipc_port_t port;
381: {
382: switch (ip_kotype(port)) {
383: #if MACH_NET
384: case IKOT_NETIPC:
385: netipc_ignore(IP_NULL, port);
386: break;
387: #endif
388:
389: default:
390: #if MACH_ASSERT
391: printf("ipc_kobject_destroy: port 0x%x, kobj 0x%x, type %d\n",
392: port, port->ip_kobject, ip_kotype(port));
393: #endif MACH_ASSERT
394: break;
395: }
396: }
397:
398: /*
399: * Routine: ipc_kobject_notify
400: * Purpose:
401: * Deliver notifications to kobjects that care about them.
402: */
403:
404: boolean_t
405: ipc_kobject_notify(request_header, reply_header)
406: mach_msg_header_t *request_header;
407: mach_msg_header_t *reply_header;
408: {
409: ipc_port_t port = (ipc_port_t) request_header->msgh_remote_port;
410:
411: ((mig_reply_header_t *) reply_header)->RetCode = MIG_NO_REPLY;
412: switch (request_header->msgh_id) {
413: case MACH_NOTIFY_PORT_DELETED:
414: case MACH_NOTIFY_MSG_ACCEPTED:
415: case MACH_NOTIFY_PORT_DESTROYED:
416: case MACH_NOTIFY_NO_SENDERS:
417: case MACH_NOTIFY_SEND_ONCE:
418: case MACH_NOTIFY_DEAD_NAME:
419: break;
420:
421: default:
422: return FALSE;
423: }
424: switch (ip_kotype(port)) {
425: default:
426: return FALSE;
427: }
428: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.