1 /* $NetBSD: darwin_socket.c,v 1.20 2008/04/28 20:23:41 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2004, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_socket.c,v 1.20 2008/04/28 20:23:41 martin Exp $");
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/socket.h>
38 #include <sys/signal.h>
39 #include <sys/lwp.h>
40 #include <sys/socketvar.h>
41 #include <sys/un.h>
42 #include <sys/mbuf.h>
43 #include <sys/filedesc.h>
44 #include <sys/protosw.h>
45 #include <sys/syscallargs.h>
46
47 #include <compat/sys/signal.h>
48
49 #include <compat/common/compat_util.h>
50
51 #include <compat/mach/mach_vm.h>
52
53 #include <compat/darwin/darwin_audit.h>
54 #include <compat/darwin/darwin_socket.h>
55 #include <compat/darwin/darwin_syscallargs.h>
56
57 unsigned char native_to_darwin_af[] = {
58 0,
59 DARWIN_AF_LOCAL,
60 DARWIN_AF_INET,
61 DARWIN_AF_IMPLINK,
62 DARWIN_AF_PUP,
63 DARWIN_AF_CHAOS, /* 5 */
64 DARWIN_AF_NS,
65 DARWIN_AF_ISO,
66 DARWIN_AF_ECMA,
67 DARWIN_AF_DATAKIT,
68 DARWIN_AF_CCITT, /* 10 */
69 DARWIN_AF_SNA,
70 DARWIN_AF_DECnet,
71 DARWIN_AF_DLI,
72 DARWIN_AF_LAT,
73 DARWIN_AF_HYLINK, /* 15 */
74 DARWIN_AF_APPLETALK,
75 DARWIN_AF_ROUTE,
76 DARWIN_AF_LINK,
77 DARWIN_AF_XTP,
78 DARWIN_AF_COIP, /* 20 */
79 DARWIN_AF_CNT,
80 DARWIN_AF_RTIP,
81 DARWIN_AF_IPX,
82 DARWIN_AF_INET6,
83 DARWIN_AF_PIP, /* 25 */
84 DARWIN_AF_ISDN,
85 DARWIN_AF_NATM,
86 0,
87 DARWIN_AF_KEY,
88 DARWIN_AF_HDRCMPLT, /* 30 */
89 0,
90 0,
91 0,
92 0,
93 0, /* 35 */
94 0,
95 };
96
97 unsigned char darwin_to_native_af[] = {
98 0,
99 AF_LOCAL,
100 AF_INET,
101 AF_IMPLINK,
102 AF_PUP,
103 AF_CHAOS, /* 5 */
104 AF_NS,
105 AF_ISO,
106 AF_ECMA,
107 AF_DATAKIT,
108 AF_CCITT, /* 10 */
109 AF_SNA,
110 AF_DECnet,
111 AF_DLI,
112 AF_LAT,
113 AF_HYLINK, /* 15 */
114 AF_APPLETALK,
115 AF_ROUTE,
116 AF_LINK,
117 0,
118 AF_COIP, /* 20 */
119 AF_CNT,
120 0,
121 AF_IPX,
122 0,
123 0, /* 25 */
124 0,
125 0,
126 AF_ISDN,
127 pseudo_AF_KEY,
128 AF_INET6, /* 30 */
129 AF_NATM,
130 0,
131 0,
132 0,
133 pseudo_AF_HDRCMPLT, /* 35 */
134 0,
135 };
136
137 static int
138 native_to_darwin_sockaddr(struct mbuf *nam)
139 {
140 struct sockaddr *sa = mtod(nam, void *);
141
142 /* We only need to translate the address family */
143 if ((unsigned)sa->sa_family >= __arraycount(native_to_darwin_af))
144 return EPROTONOSUPPORT;
145
146 sa->sa_family = native_to_darwin_af[sa->sa_family];
147 return 0;
148 }
149
150 static int
151 darwin_to_native_sockaddr(struct mbuf *nam)
152 {
153 struct sockaddr *sa = mtod(nam, void *);
154
155 if ((unsigned)sa->sa_family >= __arraycount(darwin_to_native_af)) {
156 m_free(nam);
157 return EPROTONOSUPPORT;
158 }
159 sa->sa_family = darwin_to_native_af[sa->sa_family];
160
161 /*
162 * sa_len is zero for AF_LOCAL sockets, believe size we copied in!
163 * The code used to strlen the filename, but that way lies madness!
164 */
165
166 if (sa->sa_len > nam->m_len || sa->sa_len == 0)
167 sa->sa_len = nam->m_len;
168 else
169 nam->m_len = sa->sa_len;
170
171 return 0;
172 }
173
174 int
175 darwin_sys_socket(struct lwp *l, const struct darwin_sys_socket_args *uap, register_t *retval)
176 {
177 /* {
178 syscallarg(int) domain;
179 syscallarg(int) type;
180 syscallarg(int) protocol;
181 } */
182 struct compat_30_sys_socket_args cup;
183
184 if ((unsigned)SCARG(uap, domain) >= __arraycount(darwin_to_native_af))
185 return (EPROTONOSUPPORT);
186
187 SCARG(&cup, domain) = darwin_to_native_af[SCARG(uap, domain)];
188 SCARG(&cup, type) = SCARG(uap, type);
189 SCARG(&cup, protocol) = SCARG(uap, protocol);
190
191 return compat_30_sys_socket(l, &cup, retval);
192 }
193
194 int
195 darwin_sys_recvfrom(struct lwp *l, const struct darwin_sys_recvfrom_args *uap, register_t *retval)
196 {
197 /* {
198 syscallarg(int) s;
199 syscallarg(void *) buf;
200 syscallarg(size_t) len;
201 syscallarg(int) flags;
202 syscallarg(struct sockaddr *) from;
203 syscallarg(unsigned int *) fromlenaddr;
204 } */
205 struct msghdr msg;
206 struct iovec aiov;
207 int error;
208 struct mbuf *from;
209
210 msg.msg_name = NULL;;
211 msg.msg_iov = &aiov;
212 msg.msg_iovlen = 1;
213 aiov.iov_base = SCARG(uap, buf);
214 aiov.iov_len = SCARG(uap, len);
215 msg.msg_control = NULL;
216 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
217
218 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
219 if (error != 0)
220 return error;
221
222 error = native_to_darwin_sockaddr(from);
223 if (error == 0)
224 error = copyout_sockname(SCARG(uap, from),
225 SCARG(uap, fromlenaddr), MSG_LENUSRSPACE, from);
226 if (from != NULL)
227 m_free(from);
228 return error;
229 }
230
231 int
232 darwin_sys_accept(struct lwp *l, const struct darwin_sys_accept_args *uap, register_t *retval)
233 {
234 /* {
235 syscallarg(int) s;
236 syscallarg(struct sockaddr *) name;
237 syscallarg(unsigned int *) anamelen;
238 } */
239 int error, fd;
240 struct mbuf *name;
241
242 error = do_sys_accept(l, SCARG(uap, s), &name, retval);
243 if (error != 0)
244 return error;
245
246 error = native_to_darwin_sockaddr(name);
247 if (error == 0)
248 error = copyout_sockname(SCARG(uap, name), SCARG(uap, anamelen),
249 MSG_LENUSRSPACE, name);
250 if (name != NULL)
251 m_free(name);
252 if (error != 0) {
253 fd = (int)*retval;
254 if (fd_getfile(fd) != NULL)
255 fd_close(fd);
256 }
257 return error;
258 }
259
260 int
261 darwin_sys_getpeername(struct lwp *l, const struct darwin_sys_getpeername_args *uap, register_t *retval)
262 {
263 /* {
264 syscallarg(int) fdes;
265 syscallarg(struct sockaddr *) asa;
266 syscallarg(unsigned int *) alen;
267 } */
268 struct mbuf *m;
269 int error;
270
271 error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_PEERADDR, &m);
272 if (error != 0)
273 return error;
274
275 error = native_to_darwin_sockaddr(m);
276 if (error != 0)
277 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
278 MSG_LENUSRSPACE, m);
279 if (m != NULL)
280 m_free(m);
281 return error;
282 }
283
284 int
285 darwin_sys_getsockname(struct lwp *l, const struct darwin_sys_getsockname_args *uap, register_t *retval)
286 {
287 /* {
288 syscallarg(int) fdes;
289 syscallarg(struct sockaddr *) asa;
290 syscallarg(unsigned int *) alen;
291 } */
292 struct mbuf *m;
293 int error;
294
295 error = do_sys_getsockname(l, SCARG(uap, fdes), PRU_SOCKADDR, &m);
296 if (error != 0)
297 return error;
298
299 error = native_to_darwin_sockaddr(m);
300 if (error != 0)
301 error = copyout_sockname(SCARG(uap, asa), SCARG(uap, alen),
302 MSG_LENUSRSPACE, m);
303 if (m != NULL)
304 m_free(m);
305 return error;
306 }
307
308 int
309 darwin_sys_connect(struct lwp *l, const struct darwin_sys_connect_args *uap, register_t *retval)
310 {
311 /* {
312 syscallarg(int) s;
313 syscallarg(struct sockaddr *) name;
314 syscallarg(unsigned int *) namelen;
315 } */
316 struct mbuf *nam;
317 int error;
318
319 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
320 MT_SONAME);
321 if (error == 0)
322 error = darwin_to_native_sockaddr(nam);
323 if (error == 0)
324 error = do_sys_connect(l, SCARG(uap, s), nam);
325
326 return error;
327 }
328
329 int
330 darwin_sys_bind(struct lwp *l, const struct darwin_sys_bind_args *uap, register_t *retval)
331 {
332 /* {
333 syscallarg(int) s;
334 syscallarg(struct sockaddr *) name;
335 syscallarg(unsigned int *) namelen;
336 } */
337 struct mbuf *nam;
338 int error;
339
340 error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
341 MT_SONAME);
342 if (error == 0)
343 error = darwin_to_native_sockaddr(nam);
344 if (error == 0)
345 error = do_sys_bind(l, SCARG(uap, s), nam);
346
347 return error;
348 }
349
350 int
351 darwin_sys_sendto(struct lwp *l, const struct darwin_sys_sendto_args *uap, register_t *retval)
352 {
353 /* {
354 syscallarg(int) s;
355 syscallarg(const void *) buf;
356 syscallarg(size_t) len;
357 syscallarg(int) flags;
358 syscallarg(struct sockaddr *) to;
359 syscallarg(unsigned int) tolen;
360 } */
361
362 struct msghdr msg;
363 struct iovec aiov;
364 struct mbuf *nam;
365 int error;
366
367 error = sockargs(&nam, SCARG(uap, to), SCARG(uap, tolen), MT_SONAME);
368 if (error != 0)
369 return error;
370 error = darwin_to_native_sockaddr(nam);
371 if (error != 0)
372 return error;
373
374 msg.msg_name = nam;
375 msg.msg_namelen = 0;
376 msg.msg_iov = &aiov;
377 msg.msg_iovlen = 1;
378 msg.msg_control = 0;
379 msg.msg_flags = MSG_NAMEMBUF;
380 aiov.iov_base = __UNCONST(SCARG(uap, buf)); /* XXXUNCONST kills const */
381 aiov.iov_len = SCARG(uap, len);
382 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
383 }
Cache object: 187979ce51eda07abd829a556f957be9
|