1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
49 *  School of Computer Science
50 *  Carnegie Mellon University
51 *  Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
58 * support for mandatory and extensible security protections.  This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
60 * Version 2.0.
61 * Copyright (c) 2005 SPARTA, Inc.
62 */
63/*
64 */
65/*
66 *	File:	ipc/ipc_kmsg.h
67 *	Author:	Rich Draves
68 *	Date:	1989
69 *
70 *	Definitions for kernel messages.
71 */
72
73#ifndef	_IPC_IPC_KMSG_H_
74#define _IPC_IPC_KMSG_H_
75
76#include <mach/vm_types.h>
77#include <mach/message.h>
78#include <kern/kern_types.h>
79#include <kern/assert.h>
80#include <kern/macro_help.h>
81#include <ipc/ipc_types.h>
82#include <ipc/ipc_object.h>
83
84/*
85 *	This structure is only the header for a kmsg buffer;
86 *	the actual buffer is normally larger.  The rest of the buffer
87 *	holds the body of the message.
88 *
89 *	In a kmsg, the port fields hold pointers to ports instead
90 *	of port names.  These pointers hold references.
91 *
92 *	The ikm_header.msgh_remote_port field is the destination
93 *	of the message.
94 */
95
96struct ipc_labelh;
97
98struct ipc_kmsg {
99	struct ipc_kmsg *ikm_next;
100	struct ipc_kmsg *ikm_prev;
101	ipc_port_t ikm_prealloc;	/* port we were preallocated from */
102	mach_msg_size_t ikm_size;
103	struct ipc_labelh *ikm_sender;
104	mach_msg_header_t *ikm_header;
105};
106
107
108#define	IKM_OVERHEAD		(sizeof(struct ipc_kmsg))
109
110#define	ikm_plus_overhead(size)	((mach_msg_size_t)((size) + IKM_OVERHEAD))
111#define	ikm_less_overhead(size)	((mach_msg_size_t)((size) - IKM_OVERHEAD))
112
113/*
114 * XXX	For debugging.
115 */
116#define IKM_BOGUS		((ipc_kmsg_t) 0xffffff10)
117
118/*
119 *	The size of the kernel message buffers that will be cached.
120 *	IKM_SAVED_KMSG_SIZE includes overhead; IKM_SAVED_MSG_SIZE doesn't.
121 */
122extern zone_t ipc_kmsg_zone;
123#define	IKM_SAVED_KMSG_SIZE	256
124#define	IKM_SAVED_MSG_SIZE	ikm_less_overhead(IKM_SAVED_KMSG_SIZE)
125
126#define	ikm_prealloc_inuse_port(kmsg)					\
127	((kmsg)->ikm_prealloc)
128
129#define	ikm_prealloc_inuse(kmsg)					\
130	((kmsg)->ikm_prealloc != IP_NULL)
131
132#define	ikm_prealloc_set_inuse(kmsg, port)				\
133MACRO_BEGIN								\
134	assert((port) != IP_NULL);					\
135	(kmsg)->ikm_prealloc = (port);					\
136	ip_reference(port);						\
137MACRO_END
138
139#define ikm_prealloc_clear_inuse(kmsg, port)				\
140MACRO_BEGIN								\
141	(kmsg)->ikm_prealloc = IP_NULL;					\
142	ip_release(port);						\
143MACRO_END
144
145#define	ikm_init(kmsg, size)						\
146MACRO_BEGIN								\
147	(kmsg)->ikm_size = (size);					\
148	(kmsg)->ikm_prealloc = IP_NULL;					\
149        (kmsg)->ikm_sender = NULL;					\
150	assert((kmsg)->ikm_prev = (kmsg)->ikm_next = IKM_BOGUS);	\
151MACRO_END
152
153#define	ikm_check_init(kmsg, size)					\
154MACRO_BEGIN								\
155	assert((kmsg)->ikm_size == (size));				\
156	assert((kmsg)->ikm_prev == IKM_BOGUS);				\
157	assert((kmsg)->ikm_next == IKM_BOGUS);				\
158MACRO_END
159
160struct ipc_kmsg_queue {
161	struct ipc_kmsg *ikmq_base;
162};
163
164typedef struct ipc_kmsg_queue *ipc_kmsg_queue_t;
165
166#define	IKMQ_NULL		((ipc_kmsg_queue_t) 0)
167
168
169/*
170 * Exported interfaces
171 */
172
173#define	ipc_kmsg_queue_init(queue)		\
174MACRO_BEGIN					\
175	(queue)->ikmq_base = IKM_NULL;		\
176MACRO_END
177
178#define	ipc_kmsg_queue_empty(queue)	((queue)->ikmq_base == IKM_NULL)
179
180/* Enqueue a kmsg */
181extern void ipc_kmsg_enqueue(
182	ipc_kmsg_queue_t	queue,
183	ipc_kmsg_t		kmsg);
184
185/* Dequeue and return a kmsg */
186extern ipc_kmsg_t ipc_kmsg_dequeue(
187	ipc_kmsg_queue_t        queue);
188
189/* Pull a kmsg out of a queue */
190extern void ipc_kmsg_rmqueue(
191	ipc_kmsg_queue_t	queue,
192	ipc_kmsg_t		kmsg);
193
194#define	ipc_kmsg_queue_first(queue)		((queue)->ikmq_base)
195
196/* Return the kmsg following the given kmsg */
197extern ipc_kmsg_t ipc_kmsg_queue_next(
198	ipc_kmsg_queue_t	queue,
199	ipc_kmsg_t		kmsg);
200
201#define	ipc_kmsg_rmqueue_first_macro(queue, kmsg)			\
202MACRO_BEGIN								\
203	register ipc_kmsg_t _next;					\
204									\
205	assert((queue)->ikmq_base == (kmsg));				\
206									\
207	_next = (kmsg)->ikm_next;					\
208	if (_next == (kmsg)) {						\
209		assert((kmsg)->ikm_prev == (kmsg));			\
210		(queue)->ikmq_base = IKM_NULL;				\
211	} else {							\
212		register ipc_kmsg_t _prev = (kmsg)->ikm_prev;		\
213									\
214		(queue)->ikmq_base = _next;				\
215		_next->ikm_prev = _prev;				\
216		_prev->ikm_next = _next;				\
217	}								\
218  	/* XXX Debug paranoia ASSIGNMENTS */				\
219  	assert(kmsg->ikm_next = IKM_BOGUS);				\
220  	assert(kmsg->ikm_prev = IKM_BOGUS);				\
221MACRO_END
222
223#define	ipc_kmsg_enqueue_macro(queue, kmsg)				\
224MACRO_BEGIN								\
225	register ipc_kmsg_t _first = (queue)->ikmq_base;		\
226									\
227	if (_first == IKM_NULL) {					\
228		(queue)->ikmq_base = (kmsg);				\
229		(kmsg)->ikm_next = (kmsg);				\
230		(kmsg)->ikm_prev = (kmsg);				\
231	} else {							\
232		register ipc_kmsg_t _last = _first->ikm_prev;		\
233									\
234		(kmsg)->ikm_next = _first;				\
235		(kmsg)->ikm_prev = _last;				\
236		_first->ikm_prev = (kmsg);				\
237		_last->ikm_next = (kmsg);				\
238	}								\
239MACRO_END
240
241/*
242 *	extern void
243 *	ipc_kmsg_send_always(ipc_kmsg_t);
244 */
245#define	ipc_kmsg_send_always(kmsg)					\
246	ipc_kmsg_send((kmsg), MACH_SEND_ALWAYS, MACH_MSG_TIMEOUT_NONE)
247
248
249/* Allocate a kernel message */
250extern ipc_kmsg_t ipc_kmsg_alloc(
251        mach_msg_size_t size);
252
253/* Free a kernel message buffer */
254extern void ipc_kmsg_free(
255	ipc_kmsg_t	kmsg);
256
257/* Destroy kernel message */
258extern void ipc_kmsg_destroy(
259	ipc_kmsg_t	kmsg);
260
261/* destroy kernel message and a reference on the dest */
262extern void ipc_kmsg_destroy_dest(
263	ipc_kmsg_t	kmsg);
264
265
266/* Preallocate a kernel message buffer */
267extern void ipc_kmsg_set_prealloc(
268	ipc_kmsg_t	kmsg,
269	ipc_port_t	port);
270
271/* Clear a kernel message buffer */
272extern void ipc_kmsg_clear_prealloc(
273	ipc_kmsg_t	kmsg,
274	ipc_port_t	port);
275
276/* Allocate a kernel message buffer and copy a user message to the buffer */
277extern mach_msg_return_t ipc_kmsg_get(
278	mach_vm_address_t	msg_addr,
279	mach_msg_size_t		size,
280	ipc_kmsg_t		*kmsgp);
281
282/* Allocate a kernel message buffer and copy a kernel message to the buffer */
283extern mach_msg_return_t ipc_kmsg_get_from_kernel(
284	mach_msg_header_t	*msg,
285	mach_msg_size_t		size,
286	ipc_kmsg_t		*kmsgp);
287
288/* Send a message to a port */
289extern mach_msg_return_t ipc_kmsg_send(
290	ipc_kmsg_t		kmsg,
291	mach_msg_option_t	option,
292	mach_msg_timeout_t	timeout_val);
293
294/* Copy a kernel message buffer to a user message */
295extern mach_msg_return_t ipc_kmsg_put(
296	mach_vm_address_t	msg_addr,
297	ipc_kmsg_t		kmsg,
298	mach_msg_size_t		size);
299
300/* Copy a kernel message buffer to a kernel message */
301extern void ipc_kmsg_put_to_kernel(
302	mach_msg_header_t	*msg,
303	ipc_kmsg_t		kmsg,
304	mach_msg_size_t		size);
305
306/* Copyin port rights in the header of a message */
307extern mach_msg_return_t ipc_kmsg_copyin_header(
308	mach_msg_header_t	*msg,
309	ipc_space_t		space,
310	mach_port_name_t	notify);
311
312/* Copyin port rights and out-of-line memory from a user message */
313extern mach_msg_return_t ipc_kmsg_copyin(
314	ipc_kmsg_t		kmsg,
315	ipc_space_t		space,
316	vm_map_t		map,
317	mach_port_name_t	notify);
318
319/* Copyin port rights and out-of-line memory from a kernel message */
320extern void ipc_kmsg_copyin_from_kernel(
321	ipc_kmsg_t		kmsg);
322
323/* Copyout port rights in the header of a message */
324extern mach_msg_return_t ipc_kmsg_copyout_header(
325	mach_msg_header_t	*msg,
326	ipc_space_t		space,
327	mach_port_name_t	notify);
328
329/* Copyout a port right returning a name */
330extern mach_msg_return_t ipc_kmsg_copyout_object(
331	ipc_space_t		space,
332	ipc_object_t		object,
333	mach_msg_type_name_t	msgt_name,
334	mach_port_name_t	*namep);
335
336/* Copyout the header and body to a user message */
337extern mach_msg_return_t ipc_kmsg_copyout(
338	ipc_kmsg_t		kmsg,
339	ipc_space_t		space,
340	vm_map_t		map,
341	mach_port_name_t	notify,
342	mach_msg_body_t		*slist);
343
344/* Copyout port rights and out-of-line memory from the body of a message */
345extern mach_msg_return_t ipc_kmsg_copyout_body(
346    	ipc_kmsg_t		kmsg,
347	ipc_space_t		space,
348	vm_map_t		map,
349	mach_msg_body_t		*slist);
350
351/* Copyout port rights and out-of-line memory to a user message,
352   not reversing the ports in the header */
353extern mach_msg_return_t ipc_kmsg_copyout_pseudo(
354	ipc_kmsg_t		kmsg,
355	ipc_space_t		space,
356	vm_map_t		map,
357	mach_msg_body_t		*slist);
358
359/* Compute size of message as copied out to the specified space/map */
360extern mach_msg_size_t ipc_kmsg_copyout_size(
361	ipc_kmsg_t		kmsg,
362	vm_map_t		map);
363
364/* Copyout the destination port in the message */
365extern void ipc_kmsg_copyout_dest(
366	ipc_kmsg_t		kmsg,
367	ipc_space_t		space);
368
369/* kernel's version of ipc_kmsg_copyout_dest */
370extern void ipc_kmsg_copyout_to_kernel(
371	ipc_kmsg_t		kmsg,
372	ipc_space_t		space);
373
374/* get a scatter list and check consistency */
375extern mach_msg_body_t *ipc_kmsg_get_scatter(
376        mach_vm_address_t       msg_addr,
377        mach_msg_size_t         slist_size,
378        ipc_kmsg_t              kmsg);
379
380/* free a scatter list */
381extern void ipc_kmsg_free_scatter(
382        mach_msg_body_t 	*slist,
383        mach_msg_size_t		slist_size);
384
385#endif	/* _IPC_IPC_KMSG_H_ */
386
387