]> git.saurik.com Git - apple/libc.git/blob - mach.subproj/mach_msg_destroy.c
008ee99e917285bf5a6eb40593beaac67c621c7a
[apple/libc.git] / mach.subproj / mach_msg_destroy.c
1 /*
2 * @OSF_COPYRIGHT@
3 */
4
5 /*
6 * Mach Operating System
7 * Copyright (c) 1991,1990 Carnegie Mellon University
8 * All Rights Reserved.
9 *
10 * Permission to use, copy, modify and distribute this software and its
11 * documentation is hereby granted, provided that both the copyright
12 * notice and this permission notice appear in all copies of the
13 * software, derivative works or modified versions, and any portions
14 * thereof, and that both notices appear in supporting documentation.
15 *
16 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
17 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
18 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
19 *
20 * Carnegie Mellon requests users of this software to return to
21 *
22 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
23 * School of Computer Science
24 * Carnegie Mellon University
25 * Pittsburgh PA 15213-3890
26 *
27 * any improvements or extensions that they make and grant Carnegie Mellon
28 * the rights to redistribute these changes.
29 */
30
31 #include <mach/mach.h>
32 #include <mach/message.h>
33 #include <mach/mach_init.h>
34
35 static void mach_msg_destroy_port(mach_port_t, mach_msg_type_name_t);
36 static void mach_msg_destroy_memory(vm_offset_t, vm_size_t);
37
38 /*
39 * Routine: mach_msg_destroy
40 * Purpose:
41 * mach_msg_destroy is useful in two contexts.
42 *
43 * First, it can deallocate all port rights and
44 * out-of-line memory in a received message.
45 * When a server receives a request it doesn't want,
46 * it needs this functionality.
47 *
48 * Second, it can mimic the side-effects of a msg-send
49 * operation. The effect is as if the message were sent
50 * and then destroyed inside the kernel. When a server
51 * can't send a reply (because the client died),
52 * it needs this functionality.
53 */
54 void
55 mach_msg_destroy(mach_msg_header_t *msg)
56 {
57 mach_msg_bits_t mbits = msg->msgh_bits;
58
59 /*
60 * The msgh_local_port field doesn't hold a port right.
61 * The receive operation consumes the destination port right.
62 */
63
64 mach_msg_destroy_port(msg->msgh_remote_port, MACH_MSGH_BITS_REMOTE(mbits));
65
66 if (mbits & MACH_MSGH_BITS_COMPLEX) {
67 mach_msg_body_t *body;
68 mach_msg_descriptor_t *saddr, *eaddr;
69
70 body = (mach_msg_body_t *) (msg + 1);
71 saddr = (mach_msg_descriptor_t *)
72 ((mach_msg_base_t *) msg + 1);
73 eaddr = saddr + body->msgh_descriptor_count;
74
75 for ( ; saddr < eaddr; saddr++) {
76 switch (saddr->type.type) {
77
78 case MACH_MSG_PORT_DESCRIPTOR: {
79 mach_msg_port_descriptor_t *dsc;
80
81 /*
82 * Destroy port rights carried in the message
83 */
84 dsc = &saddr->port;
85 mach_msg_destroy_port(dsc->name, dsc->disposition);
86 break;
87 }
88
89 case MACH_MSG_OOL_DESCRIPTOR : {
90 mach_msg_ool_descriptor_t *dsc;
91
92 /*
93 * Destroy memory carried in the message
94 */
95 dsc = &saddr->out_of_line;
96 if (dsc->deallocate) {
97 mach_msg_destroy_memory((vm_offset_t)dsc->address,
98 dsc->size);
99 }
100 break;
101 }
102
103 case MACH_MSG_OOL_PORTS_DESCRIPTOR : {
104 mach_port_t *ports;
105 mach_msg_ool_ports_descriptor_t *dsc;
106 mach_msg_type_number_t j;
107
108 /*
109 * Destroy port rights carried in the message
110 */
111 dsc = &saddr->ool_ports;
112 ports = (mach_port_t *) dsc->address;
113 for (j = 0; j < dsc->count; j++, ports++) {
114 mach_msg_destroy_port(*ports, dsc->disposition);
115 }
116
117 /*
118 * Destroy memory carried in the message
119 */
120 if (dsc->deallocate) {
121 mach_msg_destroy_memory((vm_offset_t)dsc->address,
122 dsc->count * sizeof(mach_port_t));
123 }
124 break;
125 }
126 }
127 }
128 }
129 }
130
131 static void
132 mach_msg_destroy_port(mach_port_t port, mach_msg_type_name_t type)
133 {
134 if (MACH_PORT_VALID(port)) switch (type) {
135 case MACH_MSG_TYPE_MOVE_SEND:
136 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
137 /* destroy the send/send-once right */
138 (void) mach_port_deallocate(mach_task_self(), port);
139 break;
140
141 case MACH_MSG_TYPE_MOVE_RECEIVE:
142 /* destroy the receive right */
143 (void) mach_port_mod_refs(mach_task_self(), port,
144 MACH_PORT_RIGHT_RECEIVE, -1);
145 break;
146
147 case MACH_MSG_TYPE_MAKE_SEND:
148 /* create a send right and then destroy it */
149 (void) mach_port_insert_right(mach_task_self(), port,
150 port, MACH_MSG_TYPE_MAKE_SEND);
151 (void) mach_port_deallocate(mach_task_self(), port);
152 break;
153
154 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
155 /* create a send-once right and then destroy it */
156 (void) mach_port_extract_right(mach_task_self(), port,
157 MACH_MSG_TYPE_MAKE_SEND_ONCE,
158 &port, &type);
159 (void) mach_port_deallocate(mach_task_self(), port);
160 break;
161 }
162 }
163
164 static void
165 mach_msg_destroy_memory(vm_offset_t addr, vm_size_t size)
166 {
167 if (size != 0)
168 (void) vm_deallocate(mach_task_self(), addr, size);
169 }