1 /* $NetBSD: netbsd32_socket.c,v 1.35 2009/06/15 22:59:53 njoly Exp $ */
4 * Copyright (c) 1998, 2001 Matthew R. Green
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.35 2009/06/15 22:59:53 njoly Exp $");
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #define msg __msg /* Don't ask me! */
35 #include <sys/malloc.h>
36 #include <sys/mount.h>
37 #include <sys/socket.h>
38 #include <sys/sockio.h>
39 #include <sys/socketvar.h>
41 #include <sys/ktrace.h>
43 #include <sys/filedesc.h>
44 #include <sys/syscallargs.h>
46 #include <sys/dirent.h>
48 #include <compat/netbsd32/netbsd32.h>
49 #include <compat/netbsd32/netbsd32_syscallargs.h>
50 #include <compat/netbsd32/netbsd32_conv.h>
52 /* note that the netbsd32_msghdr's iov really points to a struct iovec, not a netbsd32_iovec. */
53 static int recvit32(struct lwp
*, int, struct netbsd32_msghdr
*, struct iovec
*, void *,
57 netbsd32_recvmsg(struct lwp
*l
, const struct netbsd32_recvmsg_args
*uap
, register_t
*retval
)
61 syscallarg(netbsd32_msghdrp_t) msg;
62 syscallarg(int) flags;
64 struct netbsd32_msghdr msg
;
65 struct iovec aiov
[UIO_SMALLIOV
], *iov
;
66 struct netbsd32_iovec
*iov32
;
69 error
= copyin(SCARG_P32(uap
, msg
), &msg
, sizeof(msg
));
70 /* netbsd32_msghdr needs the iov pre-allocated */
73 if ((u_int
)msg
.msg_iovlen
> UIO_SMALLIOV
) {
74 if ((u_int
)msg
.msg_iovlen
> IOV_MAX
)
76 iov
= (struct iovec
*)malloc(
77 sizeof(struct iovec
) * (u_int
)msg
.msg_iovlen
, M_IOV
,
81 msg
.msg_flags
= SCARG(uap
, flags
);
82 iov32
= NETBSD32PTR64(msg
.msg_iov
);
83 error
= netbsd32_to_iovecin(iov32
, iov
, msg
.msg_iovlen
);
86 if ((error
= recvit32(l
, SCARG(uap
, s
), &msg
, iov
, (void *)0,
88 error
= copyout(&msg
, SCARG_P32(uap
, msg
), sizeof(msg
));
97 recvit32(struct lwp
*l
, int s
, struct netbsd32_msghdr
*mp
, struct iovec
*iov
, void *namelenp
, register_t
*retsize
)
100 int i
, len
, error
, iovlen
;
101 struct mbuf
*from
= 0, *control
= 0;
104 struct iovec
*ktriov
= NULL
;
107 /* fd_getsock() will use the descriptor for us */
108 if ((error
= fd_getsock(s
, &so
)) != 0)
111 auio
.uio_iovcnt
= mp
->msg_iovlen
;
112 auio
.uio_rw
= UIO_READ
;
113 auio
.uio_vmspace
= l
->l_proc
->p_vmspace
;
114 auio
.uio_offset
= 0; /* XXX */
116 for (i
= 0; i
< mp
->msg_iovlen
; i
++, iov
++) {
118 /* cannot happen iov_len is unsigned */
119 if (iov
->iov_len
< 0) {
125 * Reads return ssize_t because -1 is returned on error.
126 * Therefore we must restrict the length to SSIZE_MAX to
127 * avoid garbage return values.
129 auio
.uio_resid
+= iov
->iov_len
;
130 if (iov
->iov_len
> SSIZE_MAX
|| auio
.uio_resid
> SSIZE_MAX
) {
136 if (ktrpoint(KTR_GENIO
)) {
137 iovlen
= auio
.uio_iovcnt
* sizeof(struct iovec
);
138 ktriov
= (struct iovec
*)malloc(iovlen
, M_TEMP
, M_WAITOK
);
139 memcpy((void *)ktriov
, (void *)auio
.uio_iov
, iovlen
);
142 len
= auio
.uio_resid
;
143 error
= (*so
->so_receive
)(so
, &from
, &auio
, NULL
,
144 NETBSD32PTR64(mp
->msg_control
) ? &control
: NULL
,
147 if (auio
.uio_resid
!= len
&& (error
== ERESTART
||
148 error
== EINTR
|| error
== EWOULDBLOCK
))
152 if (ktriov
!= NULL
) {
153 ktrgeniov(s
, UIO_READ
, ktriov
, len
- auio
.uio_resid
, error
);
154 free(ktriov
, M_TEMP
);
159 *retsize
= len
- auio
.uio_resid
;
160 if (NETBSD32PTR64(mp
->msg_name
)) {
161 len
= mp
->msg_namelen
;
162 if (len
<= 0 || from
== 0)
165 if (len
> from
->m_len
)
167 /* else if len < from->m_len ??? */
168 error
= copyout(mtod(from
, void *),
169 (void *)NETBSD32PTR64(mp
->msg_name
),
174 mp
->msg_namelen
= len
;
176 (error
= copyout((void *)&len
, namelenp
, sizeof(int))))
179 if (NETBSD32PTR64(mp
->msg_control
)) {
180 len
= mp
->msg_controllen
;
181 if (len
<= 0 || control
== 0)
184 struct mbuf
*m
= control
;
185 void *cp
= (void *)NETBSD32PTR64(mp
->msg_control
);
190 mp
->msg_flags
|= MSG_CTRUNC
;
193 error
= copyout(mtod(m
, void *), cp
,
199 if (error
!= 0 || len
<= 0)
201 } while ((m
= m
->m_next
) != NULL
);
202 len
= (char *)cp
- (char *)NETBSD32PTR64(mp
->msg_control
);
204 mp
->msg_controllen
= len
;
217 netbsd32_sendmsg(struct lwp
*l
, const struct netbsd32_sendmsg_args
*uap
, register_t
*retval
)
221 syscallarg(const netbsd32_msghdrp_t) msg;
222 syscallarg(int) flags;
225 struct netbsd32_msghdr msg32
;
226 struct iovec aiov
[UIO_SMALLIOV
], *iov
;
227 struct netbsd32_iovec
*iov32
;
230 error
= copyin(SCARG_P32(uap
, msg
), &msg32
, sizeof(msg32
));
233 netbsd32_to_msghdr(&msg32
, &msg
);
235 if ((u_int
)msg
.msg_iovlen
> UIO_SMALLIOV
) {
236 if ((u_int
)msg
.msg_iovlen
> IOV_MAX
)
238 iov
= (struct iovec
*)malloc(
239 sizeof(struct iovec
) * (u_int
)msg
.msg_iovlen
, M_IOV
,
244 iov32
= NETBSD32PTR64(msg32
.msg_iov
);
245 error
= netbsd32_to_iovecin(iov32
, iov
, msg
.msg_iovlen
);
251 /* Luckily we can use this directly */
252 /* XXX: dsl (June'07) The cmsg alignment rules differ ! */
253 error
= do_sys_sendmsg(l
, SCARG(uap
, s
), &msg
, SCARG(uap
, flags
), retval
);
261 netbsd32_recvfrom(struct lwp
*l
, const struct netbsd32_recvfrom_args
*uap
, register_t
*retval
)
265 syscallarg(netbsd32_voidp) buf;
266 syscallarg(netbsd32_size_t) len;
267 syscallarg(int) flags;
268 syscallarg(netbsd32_sockaddrp_t) from;
269 syscallarg(netbsd32_intp) fromlenaddr;
271 struct netbsd32_msghdr msg
;
275 if (SCARG_P32(uap
, fromlenaddr
)) {
276 error
= copyin(SCARG_P32(uap
, fromlenaddr
),
277 &msg
.msg_namelen
, sizeof(msg
.msg_namelen
));
282 msg
.msg_name
= SCARG(uap
, from
);
283 NETBSD32PTR32(msg
.msg_iov
, 0); /* ignored in recvit32(), uses iov */
285 aiov
.iov_base
= SCARG_P32(uap
, buf
);
286 aiov
.iov_len
= (u_long
)SCARG(uap
, len
);
287 NETBSD32PTR32(msg
.msg_control
, 0);
288 msg
.msg_flags
= SCARG(uap
, flags
);
289 return (recvit32(l
, SCARG(uap
, s
), &msg
, &aiov
,
290 SCARG_P32(uap
, fromlenaddr
), retval
));
294 netbsd32_sendto(struct lwp
*l
, const struct netbsd32_sendto_args
*uap
, register_t
*retval
)
298 syscallarg(const netbsd32_voidp) buf;
299 syscallarg(netbsd32_size_t) len;
300 syscallarg(int) flags;
301 syscallarg(const netbsd32_sockaddrp_t) to;
302 syscallarg(int) tolen;
307 msg
.msg_name
= SCARG_P32(uap
, to
); /* XXX kills const */
308 msg
.msg_namelen
= SCARG(uap
, tolen
);
312 aiov
.iov_base
= SCARG_P32(uap
, buf
); /* XXX kills const */
313 aiov
.iov_len
= SCARG(uap
, len
);
315 return do_sys_sendmsg(l
, SCARG(uap
, s
), &msg
, SCARG(uap
, flags
), retval
);