]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/mach++.h
Security-29.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / mach++.h
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // mach++ - C++ bindings for useful Mach primitives
21 //
22 #ifndef _H_MACHPP
23 #define _H_MACHPP
24
25 #include <Security/utilities.h>
26 #include <Security/threading.h>
27 #include <Security/globalizer.h>
28 #include <mach/mach.h>
29 #include <servers/bootstrap.h>
30
31 // yes, we use some UNIX (non-mach) headers...
32 #include <sys/types.h>
33 #include <unistd.h>
34
35 namespace Security {
36 namespace MachPlusPlus {
37
38
39 //
40 // Exceptions thrown by the mach++ interface.
41 //
42 class Error : public CssmCommonError {
43 protected:
44 // actually, kern_return_t can be just about any subsystem type return code
45 Error(kern_return_t err);
46 public:
47 virtual ~Error();
48
49 virtual CSSM_RETURN cssmError() const;
50 virtual OSStatus osStatus() const;
51
52 const kern_return_t error;
53
54 static void check(kern_return_t err);
55 static void throwMe(kern_return_t err) __attribute__((noreturn));
56 };
57
58 // generic return code checker
59 inline void check(kern_return_t status)
60 { Error::check(status); }
61
62
63 //
64 // An encapsulation of a Mach 3 port
65 //
66 class Port {
67 protected:
68 static mach_port_t self() { return mach_task_self(); }
69
70 public:
71 Port() { mPort = 0; }
72 Port(mach_port_t port) { mPort = port; }
73
74 // devolve to Mach primitive type
75 operator mach_port_t () const { return mPort; }
76
77 // access reference (for primitives storing into &mach_port_t)
78 mach_port_t &port () { return mPort; }
79 const mach_port_t &port () const { return mPort; }
80
81 // status checks
82 mach_port_type_t type() const
83 { mach_port_type_t typ; check(mach_port_type(self(), mPort, &typ)); return typ; }
84
85 bool isType(mach_port_type_t typ) const { return type() & typ; }
86 bool isDead() const { return isType(MACH_PORT_TYPE_DEAD_NAME); }
87
88 // port allocation and management
89 void allocate(mach_port_right_t right = MACH_PORT_RIGHT_RECEIVE)
90 { check(mach_port_allocate(self(), right, &mPort)); }
91 void deallocate() { check(mach_port_deallocate(self(), mPort)); }
92 void destroy() { check(mach_port_destroy(self(), mPort)); }
93
94 void insertRight(mach_msg_type_name_t type)
95 { check(mach_port_insert_right(self(), mPort, mPort, type)); }
96
97 void modRefs(mach_port_right_t right, mach_port_delta_t delta = 1)
98 { check(mach_port_mod_refs(self(), mPort, right, delta)); }
99
100 mach_port_urefs_t getRefs(mach_port_right_t right);
101
102 // port notification interface
103 mach_port_t requestNotify(mach_port_t notify, mach_msg_id_t type, mach_port_mscount_t sync = 1)
104 {
105 mach_port_t previous;
106 check(mach_port_request_notification(self(), mPort, type, sync, notify,
107 MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous));
108 return previous;
109 }
110
111 IFDUMP(void dump(const char *name = NULL));
112
113 protected:
114 mach_port_t mPort;
115 };
116
117
118 //
119 // Ports representing PortSets
120 //
121 class PortSet : public Port {
122 public:
123 PortSet() { allocate(MACH_PORT_RIGHT_PORT_SET); }
124 ~PortSet() { destroy(); }
125
126 void operator += (const Port &port)
127 { check(mach_port_move_member(self(), port, mPort)); }
128
129 void operator -= (const Port &port)
130 { check(mach_port_move_member(self(), port, MACH_PORT_NULL)); }
131 };
132
133
134 //
135 // Ports that are bootstrap ports
136 //
137 class Bootstrap : public Port {
138 public:
139 Bootstrap() { check(task_get_bootstrap_port(mach_task_self(), &mPort)); }
140 Bootstrap(mach_port_t bootp) : Port(bootp) { }
141
142 mach_port_t checkIn(const char *name) const;
143 mach_port_t checkInOptional(const char *name) const;
144
145 void registerAs(mach_port_t port, const char *name) const;
146
147 mach_port_t lookup(const char *name) const;
148 mach_port_t lookupOptional(const char *name) const;
149
150 Bootstrap subset(Port requestor);
151
152 IFDUMP(void dump());
153
154 private:
155 // officially, the register/lookup IPCs take an array of 128 characters (not a zero-end string)
156 mutable char nameBuffer[BOOTSTRAP_MAX_NAME_LEN];
157
158 protected:
159 char *Bootstrap::makeName(const char *s) const
160 { return strncpy(nameBuffer, s, BOOTSTRAP_MAX_NAME_LEN); }
161 };
162
163
164 //
165 // Ports that are Task Ports
166 //
167 class TaskPort : public Port {
168 public:
169 TaskPort() { mPort = self(); }
170 TaskPort(const Port &p) { mPort = p; }
171
172 Bootstrap bootstrap() const
173 { mach_port_t boot; check(task_get_bootstrap_port(mPort, &boot)); return boot; }
174 void bootstrap(Bootstrap boot)
175 { check(task_set_bootstrap_port(mPort, boot)); }
176
177 pid_t pid() const;
178 static TaskPort forPid(pid_t pid);
179 };
180
181
182 //
183 // Ports that are are self-allocated and have receive rights
184 //
185 class ReceivePort : public Port {
186 public:
187 ReceivePort() { allocate(); }
188 ReceivePort(const char *name, const Bootstrap &bootstrap);
189 ~ReceivePort() { destroy(); }
190 };
191
192
193 //
194 // A little stack utility for temporarily switching your bootstrap around.
195 // Essentially, it restores your bootstrap port when it dies. Since the
196 // "current bootstrap port" is a process-global item, this uses a global
197 // zone of exclusion (aka critical region). There's no protection against
198 // someone else calling the underlying system service, of course.
199 //
200 class StBootstrap {
201 public:
202 StBootstrap(const Bootstrap &boot, const TaskPort &task = TaskPort());
203 ~StBootstrap();
204
205 private:
206 Bootstrap mOldBoot;
207 TaskPort mTask;
208 StLock<Mutex> locker;
209 static ModuleNexus<Mutex> critical; // critical region guard (of a sort)
210 };
211
212
213 //
214 // Message buffers for Mach messages.
215 // This class is for relatively simple uses.
216 //
217 class Message {
218 public:
219 Message(void *buffer, size_t size);
220 Message(size_t size);
221 virtual ~Message();
222
223 operator mig_reply_error_t & () const { return *mBuffer; }
224 operator mach_msg_header_t & () const { return mBuffer->Head; }
225 operator mig_reply_error_t * () const { return mBuffer; }
226 operator mach_msg_header_t * () const { return &mBuffer->Head; }
227 operator NDR_record_t & () const { return mBuffer->NDR; }
228
229 void *data() const { return mBuffer; }
230 size_t length() const { return mBuffer->Head.msgh_size; }
231 Port localPort() const { return mBuffer->Head.msgh_local_port; }
232 Port remotePort() const { return mBuffer->Head.msgh_remote_port; }
233 mach_msg_id_t msgId() const { return mBuffer->Head.msgh_id; }
234 mach_msg_bits_t bits() const { return mBuffer->Head.msgh_bits; }
235 kern_return_t returnCode() const { return mBuffer->RetCode; }
236
237 void localPort(mach_port_t p) { mBuffer->Head.msgh_local_port = p; }
238 void remotePort(mach_port_t p) { mBuffer->Head.msgh_remote_port = p; }
239
240 public:
241 void send(mach_msg_option_t options = 0,
242 mach_msg_timeout_t timeout = MACH_MSG_TIMEOUT_NONE,
243 mach_port_name_t notify = MACH_PORT_NULL);
244 void receive(mach_port_t receivePort,
245 mach_msg_option_t options = 0,
246 mach_msg_timeout_t timeout = MACH_MSG_TIMEOUT_NONE,
247 mach_port_name_t notify = MACH_PORT_NULL);
248 void sendReceive(mach_port_t receivePort,
249 mach_msg_option_t options = 0,
250 mach_msg_timeout_t timeout = MACH_MSG_TIMEOUT_NONE,
251 mach_port_name_t notify = MACH_PORT_NULL);
252
253 void destroy() { mach_msg_destroy(*this); }
254
255 private:
256 mig_reply_error_t *mBuffer;
257 size_t mSize;
258 bool mRelease;
259 };
260
261
262 } // end namespace MachPlusPlus
263 } // end namespace Security
264
265 #endif //_H_MACHPP