]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ipc/ipc_notify.c
xnu-344.21.73.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_notify.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
d7e50217 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
d7e50217
A
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
d7e50217
A
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
26 * @OSF_COPYRIGHT@
27 */
28/*
29 * Mach Operating System
30 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
31 * All Rights Reserved.
32 *
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
38 *
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
42 *
43 * Carnegie Mellon requests users of this software to return to
44 *
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
49 *
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
52 */
53/*
54 */
55/*
56 * File: ipc/ipc_notify.c
57 * Author: Rich Draves
58 * Date: 1989
59 *
60 * Notification-sending functions.
61 */
62
63#include <mach_rt.h>
64
65#include <mach/port.h>
66#include <mach/message.h>
67#include <mach/notify.h>
68#include <kern/assert.h>
69#include <kern/misc_protos.h>
70#include <ipc/ipc_kmsg.h>
71#include <ipc/ipc_mqueue.h>
72#include <ipc/ipc_notify.h>
73#include <ipc/ipc_port.h>
74
75/*
76 * Forward declarations
77 */
78void ipc_notify_init_port_deleted(
79 mach_port_deleted_notification_t *n);
80
81void ipc_notify_init_port_destroyed(
82 mach_port_destroyed_notification_t *n);
83
84void ipc_notify_init_no_senders(
85 mach_no_senders_notification_t *n);
86
87void ipc_notify_init_send_once(
88 mach_send_once_notification_t *n);
89
90void ipc_notify_init_dead_name(
91 mach_dead_name_notification_t *n);
92
93mach_port_deleted_notification_t ipc_notify_port_deleted_template;
94mach_port_destroyed_notification_t ipc_notify_port_destroyed_template;
95mach_no_senders_notification_t ipc_notify_no_senders_template;
96mach_send_once_notification_t ipc_notify_send_once_template;
97mach_dead_name_notification_t ipc_notify_dead_name_template;
98
99/*
100 * Routine: ipc_notify_init_port_deleted
101 * Purpose:
102 * Initialize a template for port-deleted notifications.
103 */
104
105void
106ipc_notify_init_port_deleted(
107 mach_port_deleted_notification_t *n)
108{
109 mach_msg_header_t *m = &n->not_header;
110
111 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
112 m->msgh_local_port = MACH_PORT_NULL;
113 m->msgh_remote_port = MACH_PORT_NULL;
114 m->msgh_id = MACH_NOTIFY_PORT_DELETED;
115 m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
116
117 n->not_port = MACH_PORT_NULL;
118 n->NDR = NDR_record;
119 n->trailer.msgh_seqno = 0;
120 n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
121 n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
122 n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
123}
124
125/*
126 * Routine: ipc_notify_init_port_destroyed
127 * Purpose:
128 * Initialize a template for port-destroyed notifications.
129 */
130
131void
132ipc_notify_init_port_destroyed(
133 mach_port_destroyed_notification_t *n)
134{
135 mach_msg_header_t *m = &n->not_header;
136
137 m->msgh_bits = MACH_MSGH_BITS_COMPLEX |
138 MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
139 m->msgh_local_port = MACH_PORT_NULL;
140 m->msgh_remote_port = MACH_PORT_NULL;
141 m->msgh_id = MACH_NOTIFY_PORT_DESTROYED;
142 m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
143
144 n->not_body.msgh_descriptor_count = 1;
145 n->not_port.disposition = MACH_MSG_TYPE_PORT_RECEIVE;
146 n->not_port.name = MACH_PORT_NULL;
147 n->not_port.type = MACH_MSG_PORT_DESCRIPTOR;
148 n->trailer.msgh_seqno = 0;
149 n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
150 n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
151 n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
152}
153
154/*
155 * Routine: ipc_notify_init_no_senders
156 * Purpose:
157 * Initialize a template for no-senders notifications.
158 */
159
160void
161ipc_notify_init_no_senders(
162 mach_no_senders_notification_t *n)
163{
164 mach_msg_header_t *m = &n->not_header;
165
166 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
167 m->msgh_local_port = MACH_PORT_NULL;
168 m->msgh_remote_port = MACH_PORT_NULL;
169 m->msgh_id = MACH_NOTIFY_NO_SENDERS;
170 m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
171
172 n->NDR = NDR_record;
173 n->trailer.msgh_seqno = 0;
174 n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
175 n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
176 n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
177 n->not_count = 0;
178}
179
180/*
181 * Routine: ipc_notify_init_send_once
182 * Purpose:
183 * Initialize a template for send-once notifications.
184 */
185
186void
187ipc_notify_init_send_once(
188 mach_send_once_notification_t *n)
189{
190 mach_msg_header_t *m = &n->not_header;
191
192 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
193 m->msgh_local_port = MACH_PORT_NULL;
194 m->msgh_remote_port = MACH_PORT_NULL;
195 m->msgh_id = MACH_NOTIFY_SEND_ONCE;
196 m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
197 n->trailer.msgh_seqno = 0;
198 n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
199 n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
200 n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
201}
202
203/*
204 * Routine: ipc_notify_init_dead_name
205 * Purpose:
206 * Initialize a template for dead-name notifications.
207 */
208
209void
210ipc_notify_init_dead_name(
211 mach_dead_name_notification_t *n)
212{
213 mach_msg_header_t *m = &n->not_header;
214
215 m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
216 m->msgh_local_port = MACH_PORT_NULL;
217 m->msgh_remote_port = MACH_PORT_NULL;
218 m->msgh_id = MACH_NOTIFY_DEAD_NAME;
219 m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
220
221 n->not_port = MACH_PORT_NULL;
222 n->NDR = NDR_record;
223 n->trailer.msgh_seqno = 0;
224 n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
225 n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
226 n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
227}
228
229/*
230 * Routine: ipc_notify_init
231 * Purpose:
232 * Initialize the notification subsystem.
233 */
234
235void
236ipc_notify_init(void)
237{
238 ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template);
239 ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template);
240 ipc_notify_init_no_senders(&ipc_notify_no_senders_template);
241 ipc_notify_init_send_once(&ipc_notify_send_once_template);
242 ipc_notify_init_dead_name(&ipc_notify_dead_name_template);
243}
244
245/*
246 * Routine: ipc_notify_port_deleted
247 * Purpose:
248 * Send a port-deleted notification.
249 * Conditions:
250 * Nothing locked.
251 * Consumes a ref/soright for port.
252 */
253
254void
255ipc_notify_port_deleted(
256 ipc_port_t port,
257 mach_port_name_t name)
258{
259 ipc_kmsg_t kmsg;
260 mach_port_deleted_notification_t *n;
261
262 kmsg = ipc_kmsg_alloc(sizeof *n);
263 if (kmsg == IKM_NULL) {
264 printf("dropped port-deleted (0x%08x, 0x%x)\n", port, name);
265 ipc_port_release_sonce(port);
266 return;
267 }
268
269 n = (mach_port_deleted_notification_t *) &kmsg->ikm_header;
270 *n = ipc_notify_port_deleted_template;
271
272 n->not_header.msgh_remote_port = port;
273 n->not_port = name;
274
275 ipc_kmsg_send_always(kmsg);
276}
277
278/*
279 * Routine: ipc_notify_port_destroyed
280 * Purpose:
281 * Send a port-destroyed notification.
282 * Conditions:
283 * Nothing locked.
284 * Consumes a ref/soright for port.
285 * Consumes a ref for right, which should be a receive right
286 * prepped for placement into a message. (In-transit,
287 * or in-limbo if a circularity was detected.)
288 */
289
290void
291ipc_notify_port_destroyed(
292 ipc_port_t port,
293 ipc_port_t right)
294{
295 ipc_kmsg_t kmsg;
296 mach_port_destroyed_notification_t *n;
297
298 kmsg = ipc_kmsg_alloc(sizeof *n);
299 if (kmsg == IKM_NULL) {
300 printf("dropped port-destroyed (0x%08x, 0x%08x)\n",
301 port, right);
302 ipc_port_release_sonce(port);
303 ipc_port_release_receive(right);
304 return;
305 }
306
307 n = (mach_port_destroyed_notification_t *) &kmsg->ikm_header;
308 *n = ipc_notify_port_destroyed_template;
309
310 n->not_header.msgh_remote_port = port;
311 n->not_port.name = right;
312
313 ipc_kmsg_send_always(kmsg);
314}
315
316/*
317 * Routine: ipc_notify_no_senders
318 * Purpose:
319 * Send a no-senders notification.
320 * Conditions:
321 * Nothing locked.
322 * Consumes a ref/soright for port.
323 */
324
325void
326ipc_notify_no_senders(
327 ipc_port_t port,
328 mach_port_mscount_t mscount)
329{
330 ipc_kmsg_t kmsg;
331 mach_no_senders_notification_t *n;
332
333 kmsg = ipc_kmsg_alloc(sizeof *n);
334 if (kmsg == IKM_NULL) {
335 printf("dropped no-senders (0x%08x, %u)\n", port, mscount);
336 ipc_port_release_sonce(port);
337 return;
338 }
339
340 n = (mach_no_senders_notification_t *) &kmsg->ikm_header;
341 *n = ipc_notify_no_senders_template;
342
343 n->not_header.msgh_remote_port = port;
344 n->not_count = mscount;
345
346 ipc_kmsg_send_always(kmsg);
347}
348
349/*
350 * Routine: ipc_notify_send_once
351 * Purpose:
352 * Send a send-once notification.
353 * Conditions:
354 * Nothing locked.
355 * Consumes a ref/soright for port.
356 */
357
358void
359ipc_notify_send_once(
360 ipc_port_t port)
361{
362 ipc_kmsg_t kmsg;
363 mach_send_once_notification_t *n;
364
365 kmsg = ipc_kmsg_alloc(sizeof *n);
366 if (kmsg == IKM_NULL) {
367 printf("dropped send-once (0x%08x)\n", port);
368 ipc_port_release_sonce(port);
369 return;
370 }
371
372 n = (mach_send_once_notification_t *) &kmsg->ikm_header;
373 *n = ipc_notify_send_once_template;
374
375 n->not_header.msgh_remote_port = port;
376
377 ipc_kmsg_send_always(kmsg);
378}
379
380/*
381 * Routine: ipc_notify_dead_name
382 * Purpose:
383 * Send a dead-name notification.
384 * Conditions:
385 * Nothing locked.
386 * Consumes a ref/soright for port.
387 */
388
389void
390ipc_notify_dead_name(
391 ipc_port_t port,
392 mach_port_name_t name)
393{
394 ipc_kmsg_t kmsg;
395 mach_dead_name_notification_t *n;
396
397 kmsg = ipc_kmsg_alloc(sizeof *n);
398 if (kmsg == IKM_NULL) {
399 printf("dropped dead-name (0x%08x, 0x%x)\n", port, name);
400 ipc_port_release_sonce(port);
401 return;
402 }
403
404 n = (mach_dead_name_notification_t *) &kmsg->ikm_header;
405 *n = ipc_notify_dead_name_template;
406
407 n->not_header.msgh_remote_port = port;
408 n->not_port = name;
409
410 ipc_kmsg_send_always(kmsg);
411}