]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_notify.c
e00829214b1e4dc34b898dfd081149c697ab9357
[apple/xnu.git] / osfmk / ipc / ipc_notify.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
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
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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 */
78 void ipc_notify_init_port_deleted(
79 mach_port_deleted_notification_t *n);
80
81 void ipc_notify_init_port_destroyed(
82 mach_port_destroyed_notification_t *n);
83
84 void ipc_notify_init_no_senders(
85 mach_no_senders_notification_t *n);
86
87 void ipc_notify_init_send_once(
88 mach_send_once_notification_t *n);
89
90 void ipc_notify_init_dead_name(
91 mach_dead_name_notification_t *n);
92
93 mach_port_deleted_notification_t ipc_notify_port_deleted_template;
94 mach_port_destroyed_notification_t ipc_notify_port_destroyed_template;
95 mach_no_senders_notification_t ipc_notify_no_senders_template;
96 mach_send_once_notification_t ipc_notify_send_once_template;
97 mach_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
105 void
106 ipc_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
131 void
132 ipc_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
160 void
161 ipc_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
186 void
187 ipc_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
209 void
210 ipc_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
235 void
236 ipc_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
254 void
255 ipc_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
290 void
291 ipc_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
325 void
326 ipc_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
358 void
359 ipc_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
389 void
390 ipc_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 }