netbsd32_socket.c revision 1.38 1 /* $NetBSD: netbsd32_socket.c,v 1.38 2012/01/13 21:02:03 joerg Exp $ */
2
3 /*
4 * Copyright (c) 1998, 2001 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.38 2012/01/13 21:02:03 joerg Exp $");
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #define msg __msg /* Don't ask me! */
35 #include <sys/mount.h>
36 #include <sys/socket.h>
37 #include <sys/sockio.h>
38 #include <sys/socketvar.h>
39 #include <sys/mbuf.h>
40 #include <sys/ktrace.h>
41 #include <sys/file.h>
42 #include <sys/filedesc.h>
43 #include <sys/syscallargs.h>
44 #include <sys/proc.h>
45 #include <sys/dirent.h>
46
47 #include <compat/netbsd32/netbsd32.h>
48 #include <compat/netbsd32/netbsd32_syscallargs.h>
49 #include <compat/netbsd32/netbsd32_conv.h>
50
51 /*
52 * XXX Assumes that sockaddr is compatible.
53 * XXX Assumes that copyout_msg_control uses identical alignment.
54 */
55 int
56 netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap, register_t *retval)
57 {
58 /* {
59 syscallarg(int) s;
60 syscallarg(netbsd32_msghdrp_t) msg;
61 syscallarg(int) flags;
62 } */
63 struct netbsd32_msghdr msg32;
64 struct iovec aiov[UIO_SMALLIOV], *iov;
65 struct msghdr msg;
66 int error;
67 struct mbuf *from, *control;
68 size_t iovsz;
69
70 error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
71 if (error)
72 return (error);
73
74 iovsz = msg32.msg_iovlen * sizeof(struct iovec);
75 if (msg32.msg_iovlen > UIO_SMALLIOV) {
76 if (msg32.msg_iovlen > IOV_MAX)
77 return (EMSGSIZE);
78 iov = kmem_alloc(iovsz, KM_SLEEP);
79 } else
80 iov = aiov;
81 error = netbsd32_to_iovecin(NETBSD32PTR64(msg32.msg_iov), iov,
82 msg32.msg_iovlen);
83 if (error)
84 goto done;
85
86 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
87 msg.msg_name = NETBSD32PTR64(msg32.msg_name);
88 msg.msg_namelen = msg32.msg_namelen;
89 msg.msg_control = NETBSD32PTR64(msg32.msg_control);
90 msg.msg_controllen = msg32.msg_controllen;
91 msg.msg_iov = iov;
92 msg.msg_iovlen = msg32.msg_iovlen;
93
94 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
95 msg.msg_control != NULL ? &control : NULL, retval);
96 if (error != 0)
97 goto done;
98
99 if (msg.msg_control != NULL)
100 error = copyout_msg_control(l, &msg, control);
101
102 if (error == 0)
103 error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
104 from);
105 if (from != NULL)
106 m_free(from);
107 if (error == 0) {
108 ktrkuser("msghdr", &msg, sizeof msg);
109 msg32.msg_namelen = msg.msg_namelen;
110 msg32.msg_controllen = msg.msg_controllen;
111 msg32.msg_flags = msg.msg_flags;
112 error = copyout(&msg32, SCARG_P32(uap, msg), sizeof(msg32));
113 }
114
115 done:
116 if (iov != aiov)
117 kmem_free(iov, iovsz);
118 return (error);
119 }
120
121 int
122 netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap, register_t *retval)
123 {
124 /* {
125 syscallarg(int) s;
126 syscallarg(const netbsd32_msghdrp_t) msg;
127 syscallarg(int) flags;
128 } */
129 struct msghdr msg;
130 struct netbsd32_msghdr msg32;
131 struct iovec aiov[UIO_SMALLIOV], *iov;
132 struct netbsd32_iovec *iov32;
133 size_t iovsz;
134 int error;
135
136 error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
137 if (error)
138 return (error);
139 netbsd32_to_msghdr(&msg32, &msg);
140
141 iovsz = msg.msg_iovlen * sizeof(struct iovec);
142 if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
143 if ((u_int)msg.msg_iovlen > IOV_MAX)
144 return (EMSGSIZE);
145 iov = kmem_alloc(iovsz, KM_SLEEP);
146 } else
147 iov = aiov;
148
149 iov32 = NETBSD32PTR64(msg32.msg_iov);
150 error = netbsd32_to_iovecin(iov32, iov, msg.msg_iovlen);
151 if (error)
152 goto done;
153 msg.msg_iov = iov;
154 msg.msg_flags = 0;
155
156 /* Luckily we can use this directly */
157 /* XXX: dsl (June'07) The cmsg alignment rules differ ! */
158 error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
159 done:
160 if (iov != aiov)
161 kmem_free(iov, iovsz);
162 return (error);
163 }
164
165 int
166 netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap, register_t *retval)
167 {
168 /* {
169 syscallarg(int) s;
170 syscallarg(netbsd32_voidp) buf;
171 syscallarg(netbsd32_size_t) len;
172 syscallarg(int) flags;
173 syscallarg(netbsd32_sockaddrp_t) from;
174 syscallarg(netbsd32_intp) fromlenaddr;
175 } */
176 struct msghdr msg;
177 struct iovec aiov;
178 int error;
179 struct mbuf *from;
180
181 msg.msg_name = NULL;
182 msg.msg_iov = &aiov;
183 msg.msg_iovlen = 1;
184 aiov.iov_base = SCARG_P32(uap, buf);
185 aiov.iov_len = SCARG(uap, len);
186 msg.msg_control = NULL;
187 msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
188
189 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
190 if (error != 0)
191 return error;
192
193 error = copyout_sockname(SCARG_P32(uap, from), SCARG_P32(uap, fromlenaddr),
194 MSG_LENUSRSPACE, from);
195 if (from != NULL)
196 m_free(from);
197 return error;
198 }
199
200 int
201 netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap, register_t *retval)
202 {
203 /* {
204 syscallarg(int) s;
205 syscallarg(const netbsd32_voidp) buf;
206 syscallarg(netbsd32_size_t) len;
207 syscallarg(int) flags;
208 syscallarg(const netbsd32_sockaddrp_t) to;
209 syscallarg(int) tolen;
210 } */
211 struct msghdr msg;
212 struct iovec aiov;
213
214 msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */
215 msg.msg_namelen = SCARG(uap, tolen);
216 msg.msg_iov = &aiov;
217 msg.msg_iovlen = 1;
218 msg.msg_control = 0;
219 aiov.iov_base = SCARG_P32(uap, buf); /* XXX kills const */
220 aiov.iov_len = SCARG(uap, len);
221 msg.msg_flags = 0;
222 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
223 }
224