xref: /NextBSD/sys/compat/mach/ipc/ipc_notify.c (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright 1991-1998 by Open Software Foundation, Inc.
3  *              All Rights Reserved
4  *
5  * Permission to use, copy, modify, and distribute this software and
6  * its documentation for any purpose and without fee is hereby granted,
7  * provided that the above copyright notice appears in all copies and
8  * that both the copyright notice and this permission notice appear in
9  * supporting documentation.
10  *
11  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
12  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13  * FOR A PARTICULAR PURPOSE.
14  *
15  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
16  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
18  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
19  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  */
21 /*
22  * MkLinux
23  */
24 /* CMU_HIST */
25 /*
26  * Revision 2.5.2.2  92/03/28  10:09:23  jeffreyh
27  * 	NORMA_IPC: Don't send send_once notification if port is dead.
28  * 	[92/03/25            dlb]
29  *
30  * Revision 2.5.2.1  92/01/03  16:35:29  jsb
31  * 	Did I say ndproxy? I meant to say nsproxy.
32  * 	[91/12/31  21:40:41  jsb]
33  *
34  * 	Changes for IP_NORMA_REQUEST macros being renamed to ip_ndproxy{,m,p}.
35  * 	[91/12/30  07:57:26  jsb]
36  *
37  * 	Use IP_IS_NORMA_NSREQUEST macro.
38  * 	[91/12/28  17:05:21  jsb]
39  *
40  * 	Added norma_ipc_notify_no_senders hook in ipc_notify_no_senders.
41  * 	[91/12/24  14:37:56  jsb]
42  *
43  * Revision 2.5  91/08/28  11:13:41  jsb
44  * 	Changed msgh_kind to msgh_seqno.
45  * 	[91/08/09            rpd]
46  *
47  * Revision 2.4  91/05/14  16:34:24  mrt
48  * 	Correcting copyright
49  *
50  * Revision 2.3  91/02/05  17:22:33  mrt
51  * 	Changed to new Mach copyright
52  * 	[91/02/01  15:46:58  mrt]
53  *
54  * Revision 2.2  90/06/02  14:50:50  rpd
55  * 	Created for new IPC.
56  * 	[90/03/26  20:57:58  rpd]
57  *
58  */
59 /* CMU_ENDHIST */
60 /*
61  * Mach Operating System
62  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
63  * All Rights Reserved.
64  *
65  * Permission to use, copy, modify and distribute this software and its
66  * documentation is hereby granted, provided that both the copyright
67  * notice and this permission notice appear in all copies of the
68  * software, derivative works or modified versions, and any portions
69  * thereof, and that both notices appear in supporting documentation.
70  *
71  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
72  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
73  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
74  *
75  * Carnegie Mellon requests users of this software to return to
76  *
77  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
78  *  School of Computer Science
79  *  Carnegie Mellon University
80  *  Pittsburgh PA 15213-3890
81  *
82  * any improvements or extensions that they make and grant Carnegie Mellon
83  * the rights to redistribute these changes.
84  */
85 /*
86  */
87 /*
88  *	File:	ipc/ipc_notify.c
89  *	Author:	Rich Draves
90  *	Date:	1989
91  *
92  *	Notification-sending functions.
93  */
94 
95 
96 #include <sys/mach/port.h>
97 #include <sys/mach/message.h>
98 #include <sys/mach/notify.h>
99 #if 0
100 #include <kern/assert.h>
101 #include <kern/misc_protos.h>
102 #endif
103 #include <sys/mach/ipc/ipc_kmsg.h>
104 #include <sys/mach/ipc/ipc_mqueue.h>
105 #include <sys/mach/ipc/ipc_notify.h>
106 #include <sys/mach/ipc/ipc_port.h>
107 
108 /*
109  * Forward declarations
110  */
111 void ipc_notify_init_port_deleted(
112 	mach_port_deleted_notification_t	*n);
113 
114 void ipc_notify_init_port_destroyed(
115 	mach_port_destroyed_notification_t	*n);
116 
117 void ipc_notify_init_no_senders(
118 	mach_no_senders_notification_t		*n);
119 
120 void ipc_notify_init_send_once(
121 	mach_send_once_notification_t		*n);
122 
123 void ipc_notify_init_dead_name(
124 	mach_dead_name_notification_t		*n);
125 
126 mach_port_deleted_notification_t	ipc_notify_port_deleted_template;
127 mach_port_destroyed_notification_t	ipc_notify_port_destroyed_template;
128 mach_no_senders_notification_t		ipc_notify_no_senders_template;
129 mach_send_once_notification_t		ipc_notify_send_once_template;
130 mach_dead_name_notification_t		ipc_notify_dead_name_template;
131 
132 /*
133  *	Routine:	ipc_notify_init_port_deleted
134  *	Purpose:
135  *		Initialize a template for port-deleted notifications.
136  */
137 
138 void
ipc_notify_init_port_deleted(mach_port_deleted_notification_t * n)139 ipc_notify_init_port_deleted(
140 	mach_port_deleted_notification_t	*n)
141 {
142 	mach_msg_header_t *m = &n->not_header;
143 
144 	m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
145 	m->msgh_local_port = MACH_PORT_NULL;
146 	m->msgh_remote_port = MACH_PORT_NULL;
147 	m->msgh_id = MACH_NOTIFY_PORT_DELETED;
148 	m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
149 
150 	n->not_port = MACH_PORT_NAME_NULL;
151 	n->NDR = NDR_record;
152 	n->trailer.msgh_seqno = 0;
153 	n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
154 	n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
155 	n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
156 }
157 
158 /*
159  *	Routine:	ipc_notify_init_port_destroyed
160  *	Purpose:
161  *		Initialize a template for port-destroyed notifications.
162  */
163 
164 void
ipc_notify_init_port_destroyed(mach_port_destroyed_notification_t * n)165 ipc_notify_init_port_destroyed(
166 	mach_port_destroyed_notification_t	*n)
167 {
168 	mach_msg_header_t *m = &n->not_header;
169 
170 	m->msgh_bits = MACH_MSGH_BITS_COMPLEX |
171 		MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
172 	m->msgh_local_port = MACH_PORT_NULL;
173 	m->msgh_remote_port = MACH_PORT_NULL;
174 	m->msgh_id = MACH_NOTIFY_PORT_DESTROYED;
175 	m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
176 
177 	n->not_body.msgh_descriptor_count = 1;
178 	n->not_port.disposition = MACH_MSG_TYPE_PORT_RECEIVE;
179 	n->not_port.name = MACH_PORT_NULL;
180 	n->not_port.type = MACH_MSG_PORT_DESCRIPTOR;
181 	n->trailer.msgh_seqno = 0;
182 	n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
183 	n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
184 	n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
185 }
186 
187 /*
188  *	Routine:	ipc_notify_init_no_senders
189  *	Purpose:
190  *		Initialize a template for no-senders notifications.
191  */
192 
193 void
ipc_notify_init_no_senders(mach_no_senders_notification_t * n)194 ipc_notify_init_no_senders(
195 	mach_no_senders_notification_t	*n)
196 {
197 	mach_msg_header_t *m = &n->not_header;
198 
199 	m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
200 	m->msgh_local_port = MACH_PORT_NULL;
201 	m->msgh_remote_port = MACH_PORT_NULL;
202 	m->msgh_id = MACH_NOTIFY_NO_SENDERS;
203 	m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
204 
205 	n->NDR = NDR_record;
206 	n->trailer.msgh_seqno = 0;
207 	n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
208 	n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
209 	n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
210 	n->not_count = 0;
211 }
212 
213 /*
214  *	Routine:	ipc_notify_init_send_once
215  *	Purpose:
216  *		Initialize a template for send-once notifications.
217  */
218 
219 void
ipc_notify_init_send_once(mach_send_once_notification_t * n)220 ipc_notify_init_send_once(
221 	mach_send_once_notification_t	*n)
222 {
223 	mach_msg_header_t *m = &n->not_header;
224 
225 	m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
226 	m->msgh_local_port = MACH_PORT_NULL;
227 	m->msgh_remote_port = MACH_PORT_NULL;
228 	m->msgh_id = MACH_NOTIFY_SEND_ONCE;
229 	m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
230 	n->trailer.msgh_seqno = 0;
231 	n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
232 	n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
233 	n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
234 }
235 
236 /*
237  *	Routine:	ipc_notify_init_dead_name
238  *	Purpose:
239  *		Initialize a template for dead-name notifications.
240  */
241 
242 void
ipc_notify_init_dead_name(mach_dead_name_notification_t * n)243 ipc_notify_init_dead_name(
244 	mach_dead_name_notification_t	*n)
245 {
246 	mach_msg_header_t *m = &n->not_header;
247 
248 	m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, 0);
249 	m->msgh_local_port = MACH_PORT_NULL;
250 	m->msgh_remote_port = MACH_PORT_NULL;
251 	m->msgh_id = MACH_NOTIFY_DEAD_NAME;
252 	m->msgh_size = ((int)sizeof *n) - sizeof(mach_msg_format_0_trailer_t);
253 
254 	n->not_port = MACH_PORT_NAME_NULL;
255 	n->NDR = NDR_record;
256 	n->trailer.msgh_seqno = 0;
257 	n->trailer.msgh_sender = KERNEL_SECURITY_TOKEN;
258 	n->trailer.msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0;
259 	n->trailer.msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE;
260 }
261 
262 /*
263  *	Routine:	ipc_notify_init
264  *	Purpose:
265  *		Initialize the notification subsystem.
266  */
267 
268 void
ipc_notify_init(void)269 ipc_notify_init(void)
270 {
271 	ipc_notify_init_port_deleted(&ipc_notify_port_deleted_template);
272 	ipc_notify_init_port_destroyed(&ipc_notify_port_destroyed_template);
273 	ipc_notify_init_no_senders(&ipc_notify_no_senders_template);
274 	ipc_notify_init_send_once(&ipc_notify_send_once_template);
275 	ipc_notify_init_dead_name(&ipc_notify_dead_name_template);
276 }
277 
278 /*
279  *	Routine:	ipc_notify_port_deleted
280  *	Purpose:
281  *		Send a port-deleted notification.
282  *	Conditions:
283  *		Nothing locked.
284  *		Consumes a ref/soright for port.
285  */
286 
287 void
ipc_notify_port_deleted(ipc_port_t port,mach_port_name_t name)288 ipc_notify_port_deleted(
289 	ipc_port_t	port,
290 	mach_port_name_t	name)
291 {
292 	ipc_kmsg_t kmsg;
293 	mach_port_deleted_notification_t *n;
294 
295 		kmsg = ikm_alloc(sizeof *n);
296 	if (kmsg == IKM_NULL) {
297 		printf("dropped port-deleted (%p, 0x%x)\n", port, name);
298 		ipc_port_release_sonce(port);
299 		return;
300 	}
301 
302 	ikm_init(kmsg, sizeof *n);
303 	n = (mach_port_deleted_notification_t *) kmsg->ikm_header;
304 	*n = ipc_notify_port_deleted_template;
305 
306 	n->not_header.msgh_remote_port = (mach_port_t) port;
307 	n->not_port = name;
308 
309 	ipc_mqueue_send_always(kmsg);
310 }
311 
312 /*
313  *	Routine:	ipc_notify_port_destroyed
314  *	Purpose:
315  *		Send a port-destroyed notification.
316  *	Conditions:
317  *		Nothing locked.
318  *		Consumes a ref/soright for port.
319  *		Consumes a ref for right, which should be a receive right
320  *		prepped for placement into a message.  (In-transit,
321  *		or in-limbo if a circularity was detected.)
322  */
323 
324 void
ipc_notify_port_destroyed(ipc_port_t port,ipc_port_t right)325 ipc_notify_port_destroyed(
326 	ipc_port_t	port,
327 	ipc_port_t	right)
328 {
329 	ipc_kmsg_t kmsg;
330 	mach_port_destroyed_notification_t *n;
331 
332 		kmsg = ikm_alloc(sizeof *n);
333 	if (kmsg == IKM_NULL) {
334 		printf("dropped port-destroyed (%p, %p)\n",
335 		       port, right);
336 		ipc_port_release_sonce(port);
337 		ipc_port_release_receive(right);
338 		return;
339 	}
340 
341 	ikm_init(kmsg, sizeof *n);
342 	n = (mach_port_destroyed_notification_t *) kmsg->ikm_header;
343 	*n = ipc_notify_port_destroyed_template;
344 
345 	n->not_header.msgh_remote_port = (mach_port_t) port;
346 	n->not_port.name = (mach_port_t)right;
347 
348 	ipc_mqueue_send_always(kmsg);
349 }
350 
351 /*
352  *	Routine:	ipc_notify_no_senders
353  *	Purpose:
354  *		Send a no-senders notification.
355  *	Conditions:
356  *		Nothing locked.
357  *		Consumes a ref/soright for port.
358  */
359 
360 void
ipc_notify_no_senders(ipc_port_t port,mach_port_mscount_t mscount)361 ipc_notify_no_senders(
362 	ipc_port_t		port,
363 	mach_port_mscount_t	mscount)
364 {
365 	ipc_kmsg_t kmsg;
366 	mach_no_senders_notification_t *n;
367 
368 		kmsg = ikm_alloc(sizeof *n);
369 	if (kmsg == IKM_NULL) {
370 		printf("dropped no-senders (%p, %u)\n", port, mscount);
371 		ipc_port_release_sonce(port);
372 		return;
373 	}
374 
375 	ikm_init(kmsg, sizeof *n);
376 	n = (mach_no_senders_notification_t *) kmsg->ikm_header;
377 	*n = ipc_notify_no_senders_template;
378 
379 	n->not_header.msgh_remote_port = (mach_port_t) port;
380 	n->not_count = mscount;
381 
382 	ipc_mqueue_send_always(kmsg);
383 }
384 
385 /*
386  *	Routine:	ipc_notify_send_once
387  *	Purpose:
388  *		Send a send-once notification.
389  *	Conditions:
390  *		Nothing locked.
391  *		Consumes a ref/soright for port.
392  */
393 
394 void
ipc_notify_send_once(ipc_port_t port)395 ipc_notify_send_once(
396 	ipc_port_t	port)
397 {
398 	ipc_kmsg_t kmsg;
399 	mach_send_once_notification_t *n;
400 
401 	kmsg = ikm_alloc(sizeof *n);
402 	if (kmsg == IKM_NULL) {
403 		printf("dropped send-once (%p)\n", port);
404 		ipc_port_release_sonce(port);
405 		return;
406 	}
407 
408 	ikm_init(kmsg, sizeof *n);
409 	n = (mach_send_once_notification_t *) kmsg->ikm_header;
410 	*n = ipc_notify_send_once_template;
411 
412 	n->not_header.msgh_remote_port = (mach_port_t) port;
413 
414 	ipc_mqueue_send_always(kmsg);
415 }
416 
417 /*
418  *	Routine:	ipc_notify_dead_name
419  *	Purpose:
420  *		Send a dead-name notification.
421  *	Conditions:
422  *		Nothing locked.
423  *		Consumes a ref/soright for port.
424  */
425 
426 void
ipc_notify_dead_name(ipc_port_t port,mach_port_name_t name)427 ipc_notify_dead_name(
428 	ipc_port_t	port,
429 	mach_port_name_t	name)
430 {
431 	ipc_kmsg_t kmsg;
432 	mach_dead_name_notification_t *n;
433 
434 		kmsg = ikm_alloc(sizeof *n);
435 	if (kmsg == IKM_NULL) {
436 		printf("dropped dead-name (%p, 0x%x)\n", port, name);
437 		ipc_port_release_sonce(port);
438 		return;
439 	}
440 
441 	ikm_init(kmsg, sizeof *n);
442 	n = (mach_dead_name_notification_t *) kmsg->ikm_header;
443 	*n = ipc_notify_dead_name_template;
444 
445 	n->not_header.msgh_remote_port = (mach_port_t) port;
446 	n->not_port = name;
447 
448 	ipc_mqueue_send_always(kmsg);
449 }
450