]>
Commit | Line | Data |
---|---|---|
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 | */ | |
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 | } |