netbsd32_socket.c revision 1.45 1 1.45 christos /* $NetBSD: netbsd32_socket.c,v 1.45 2018/05/03 21:43:33 christos Exp $ */
2 1.1 mrg
3 1.1 mrg /*
4 1.1 mrg * Copyright (c) 1998, 2001 Matthew R. Green
5 1.1 mrg * All rights reserved.
6 1.1 mrg *
7 1.1 mrg * Redistribution and use in source and binary forms, with or without
8 1.1 mrg * modification, are permitted provided that the following conditions
9 1.1 mrg * are met:
10 1.1 mrg * 1. Redistributions of source code must retain the above copyright
11 1.1 mrg * notice, this list of conditions and the following disclaimer.
12 1.1 mrg * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 mrg * notice, this list of conditions and the following disclaimer in the
14 1.1 mrg * documentation and/or other materials provided with the distribution.
15 1.1 mrg *
16 1.1 mrg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 mrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 mrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 mrg * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 mrg * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.1 mrg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.1 mrg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.1 mrg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.1 mrg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.1 mrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.1 mrg * SUCH DAMAGE.
27 1.1 mrg */
28 1.6 lukem
29 1.6 lukem #include <sys/cdefs.h>
30 1.45 christos __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.45 2018/05/03 21:43:33 christos Exp $");
31 1.1 mrg
32 1.1 mrg #include <sys/param.h>
33 1.1 mrg #include <sys/systm.h>
34 1.1 mrg #define msg __msg /* Don't ask me! */
35 1.1 mrg #include <sys/mount.h>
36 1.1 mrg #include <sys/socket.h>
37 1.1 mrg #include <sys/sockio.h>
38 1.1 mrg #include <sys/socketvar.h>
39 1.1 mrg #include <sys/mbuf.h>
40 1.1 mrg #include <sys/ktrace.h>
41 1.1 mrg #include <sys/file.h>
42 1.1 mrg #include <sys/filedesc.h>
43 1.1 mrg #include <sys/syscallargs.h>
44 1.1 mrg #include <sys/proc.h>
45 1.15 christos #include <sys/dirent.h>
46 1.1 mrg
47 1.1 mrg #include <compat/netbsd32/netbsd32.h>
48 1.1 mrg #include <compat/netbsd32/netbsd32_syscallargs.h>
49 1.1 mrg #include <compat/netbsd32/netbsd32_conv.h>
50 1.1 mrg
51 1.37 rmind /*
52 1.39 joerg * XXX Assumes that struct sockaddr is compatible.
53 1.37 rmind */
54 1.39 joerg
55 1.39 joerg #define CMSG32_ALIGN(n) (((n) + ALIGNBYTES32) & ~ALIGNBYTES32)
56 1.45 christos #define CMSG32_ASIZE CMSG32_ALIGN(sizeof(struct cmsghdr))
57 1.45 christos #define CMSG32_DATA(cmsg) (__CASTV(u_char *, cmsg) + CMSG32_ASIZE)
58 1.45 christos #define CMSG32_MSGNEXT(ucmsg, kcmsg) \
59 1.45 christos (__CASTV(char *, kcmsg) + CMSG32_ALIGN((ucmsg)->cmsg_len))
60 1.45 christos #define CMSG32_MSGEND(mhdr) \
61 1.45 christos (__CASTV(char *, (mhdr)->msg_control) + (mhdr)->msg_controllen)
62 1.45 christos
63 1.45 christos #define CMSG32_NXTHDR(mhdr, ucmsg, kcmsg) \
64 1.45 christos __CASTV(struct cmsghdr *, \
65 1.45 christos CMSG32_MSGNEXT(ucmsg, kcmsg) + \
66 1.45 christos CMSG32_ASIZE > CMSG32_MSGEND(mhdr) ? 0 : \
67 1.45 christos CMSG32_MSGNEXT(ucmsg, kcmsg))
68 1.39 joerg #define CMSG32_FIRSTHDR(mhdr) \
69 1.45 christos __CASTV(struct cmsghdr *, \
70 1.45 christos (mhdr)->msg_controllen < sizeof(struct cmsghdr) ? 0 : \
71 1.45 christos (mhdr)->msg_control)
72 1.39 joerg
73 1.39 joerg #define CMSG32_SPACE(l) (CMSG32_ALIGN(sizeof(struct cmsghdr)) + CMSG32_ALIGN(l))
74 1.39 joerg #define CMSG32_LEN(l) (CMSG32_ALIGN(sizeof(struct cmsghdr)) + (l))
75 1.39 joerg
76 1.39 joerg static int
77 1.45 christos copyout32_msg_control_mbuf(struct lwp *l, struct msghdr *mp, int *len,
78 1.45 christos struct mbuf *m, char **q, bool *truncated)
79 1.39 joerg {
80 1.39 joerg struct cmsghdr *cmsg, cmsg32;
81 1.39 joerg int i, j, error;
82 1.39 joerg
83 1.39 joerg *truncated = false;
84 1.39 joerg cmsg = mtod(m, struct cmsghdr *);
85 1.39 joerg do {
86 1.39 joerg if ((char *)cmsg == mtod(m, char *) + m->m_len)
87 1.39 joerg break;
88 1.39 joerg if ((char *)cmsg > mtod(m, char *) + m->m_len - sizeof(*cmsg))
89 1.39 joerg return EINVAL;
90 1.39 joerg cmsg32 = *cmsg;
91 1.39 joerg j = cmsg->cmsg_len - CMSG_LEN(0);
92 1.39 joerg i = cmsg32.cmsg_len = CMSG32_LEN(j);
93 1.39 joerg if (i > *len) {
94 1.39 joerg mp->msg_flags |= MSG_CTRUNC;
95 1.39 joerg if (cmsg->cmsg_level == SOL_SOCKET
96 1.39 joerg && cmsg->cmsg_type == SCM_RIGHTS) {
97 1.39 joerg *truncated = true;
98 1.39 joerg return 0;
99 1.39 joerg }
100 1.39 joerg j -= i - *len;
101 1.39 joerg i = *len;
102 1.39 joerg }
103 1.39 joerg
104 1.45 christos ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
105 1.39 joerg error = copyout(&cmsg32, *q, MAX(i, sizeof(cmsg32)));
106 1.39 joerg if (error)
107 1.39 joerg return (error);
108 1.39 joerg if (i > CMSG32_LEN(0)) {
109 1.45 christos error = copyout(CMSG_DATA(cmsg), *q + CMSG32_LEN(0),
110 1.45 christos i - CMSG32_LEN(0));
111 1.39 joerg if (error)
112 1.39 joerg return (error);
113 1.39 joerg }
114 1.39 joerg j = CMSG32_SPACE(cmsg->cmsg_len - CMSG_LEN(0));
115 1.39 joerg if (*len >= j) {
116 1.39 joerg *len -= j;
117 1.39 joerg *q += j;
118 1.39 joerg } else {
119 1.39 joerg *q += i;
120 1.39 joerg *len = 0;
121 1.39 joerg }
122 1.39 joerg cmsg = (void *)((char *)cmsg + CMSG_ALIGN(cmsg->cmsg_len));
123 1.39 joerg } while (*len > 0);
124 1.39 joerg
125 1.39 joerg return 0;
126 1.39 joerg }
127 1.39 joerg
128 1.39 joerg static int
129 1.39 joerg copyout32_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
130 1.39 joerg {
131 1.39 joerg int len, error = 0;
132 1.39 joerg struct mbuf *m;
133 1.39 joerg char *q;
134 1.39 joerg bool truncated;
135 1.39 joerg
136 1.39 joerg len = mp->msg_controllen;
137 1.39 joerg if (len <= 0 || control == 0) {
138 1.39 joerg mp->msg_controllen = 0;
139 1.39 joerg free_control_mbuf(l, control, control);
140 1.39 joerg return 0;
141 1.39 joerg }
142 1.39 joerg
143 1.39 joerg q = (char *)mp->msg_control;
144 1.39 joerg
145 1.40 matt for (m = control; len > 0 && m != NULL; m = m->m_next) {
146 1.45 christos error = copyout32_msg_control_mbuf(l, mp, &len, m, &q,
147 1.45 christos &truncated);
148 1.39 joerg if (truncated) {
149 1.39 joerg m = control;
150 1.39 joerg break;
151 1.39 joerg }
152 1.39 joerg if (error)
153 1.39 joerg break;
154 1.39 joerg }
155 1.39 joerg
156 1.39 joerg free_control_mbuf(l, control, m);
157 1.39 joerg
158 1.39 joerg mp->msg_controllen = q - (char *)mp->msg_control;
159 1.39 joerg return error;
160 1.39 joerg }
161 1.39 joerg
162 1.1 mrg int
163 1.45 christos netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap,
164 1.45 christos register_t *retval)
165 1.1 mrg {
166 1.30 dsl /* {
167 1.1 mrg syscallarg(int) s;
168 1.1 mrg syscallarg(netbsd32_msghdrp_t) msg;
169 1.1 mrg syscallarg(int) flags;
170 1.30 dsl } */
171 1.38 joerg struct netbsd32_msghdr msg32;
172 1.35 njoly struct iovec aiov[UIO_SMALLIOV], *iov;
173 1.38 joerg struct msghdr msg;
174 1.38 joerg int error;
175 1.38 joerg struct mbuf *from, *control;
176 1.37 rmind size_t iovsz;
177 1.1 mrg
178 1.38 joerg error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
179 1.1 mrg if (error)
180 1.1 mrg return (error);
181 1.38 joerg
182 1.38 joerg iovsz = msg32.msg_iovlen * sizeof(struct iovec);
183 1.38 joerg if (msg32.msg_iovlen > UIO_SMALLIOV) {
184 1.38 joerg if (msg32.msg_iovlen > IOV_MAX)
185 1.1 mrg return (EMSGSIZE);
186 1.37 rmind iov = kmem_alloc(iovsz, KM_SLEEP);
187 1.25 christos } else
188 1.1 mrg iov = aiov;
189 1.38 joerg error = netbsd32_to_iovecin(NETBSD32PTR64(msg32.msg_iov), iov,
190 1.38 joerg msg32.msg_iovlen);
191 1.1 mrg if (error)
192 1.1 mrg goto done;
193 1.1 mrg
194 1.38 joerg msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
195 1.38 joerg msg.msg_name = NETBSD32PTR64(msg32.msg_name);
196 1.38 joerg msg.msg_namelen = msg32.msg_namelen;
197 1.38 joerg msg.msg_control = NETBSD32PTR64(msg32.msg_control);
198 1.38 joerg msg.msg_controllen = msg32.msg_controllen;
199 1.38 joerg msg.msg_iov = iov;
200 1.38 joerg msg.msg_iovlen = msg32.msg_iovlen;
201 1.13 perry
202 1.45 christos error = do_sys_recvmsg(l, SCARG(uap, s), &msg,
203 1.44 martin &from, msg.msg_control != NULL ? &control : NULL, retval);
204 1.38 joerg if (error != 0)
205 1.38 joerg goto done;
206 1.1 mrg
207 1.38 joerg if (msg.msg_control != NULL)
208 1.39 joerg error = copyout32_msg_control(l, &msg, control);
209 1.27 ad
210 1.38 joerg if (error == 0)
211 1.38 joerg error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
212 1.38 joerg from);
213 1.38 joerg if (from != NULL)
214 1.38 joerg m_free(from);
215 1.38 joerg if (error == 0) {
216 1.38 joerg msg32.msg_namelen = msg.msg_namelen;
217 1.38 joerg msg32.msg_controllen = msg.msg_controllen;
218 1.38 joerg msg32.msg_flags = msg.msg_flags;
219 1.45 christos ktrkuser("msghdr", &msg, sizeof msg);
220 1.38 joerg error = copyout(&msg32, SCARG_P32(uap, msg), sizeof(msg32));
221 1.1 mrg }
222 1.27 ad
223 1.38 joerg done:
224 1.38 joerg if (iov != aiov)
225 1.38 joerg kmem_free(iov, iovsz);
226 1.1 mrg return (error);
227 1.1 mrg }
228 1.1 mrg
229 1.39 joerg static int
230 1.39 joerg copyin32_msg_control(struct lwp *l, struct msghdr *mp)
231 1.39 joerg {
232 1.39 joerg /*
233 1.39 joerg * Handle cmsg if there is any.
234 1.39 joerg */
235 1.39 joerg struct cmsghdr *cmsg, cmsg32, *cc;
236 1.39 joerg struct mbuf *ctl_mbuf;
237 1.39 joerg ssize_t resid = mp->msg_controllen;
238 1.39 joerg size_t clen, cidx = 0, cspace;
239 1.39 joerg u_int8_t *control;
240 1.39 joerg int error;
241 1.39 joerg
242 1.39 joerg ctl_mbuf = m_get(M_WAIT, MT_CONTROL);
243 1.39 joerg clen = MLEN;
244 1.39 joerg control = mtod(ctl_mbuf, void *);
245 1.39 joerg memset(control, 0, clen);
246 1.39 joerg
247 1.45 christos for (cc = CMSG32_FIRSTHDR(mp); cc; cc = CMSG32_NXTHDR(mp, &cmsg32, cc))
248 1.45 christos {
249 1.39 joerg error = copyin(cc, &cmsg32, sizeof(cmsg32));
250 1.39 joerg if (error)
251 1.39 joerg goto failure;
252 1.39 joerg
253 1.39 joerg /*
254 1.39 joerg * Sanity check the control message length.
255 1.39 joerg */
256 1.39 joerg if (cmsg32.cmsg_len > resid ||
257 1.39 joerg cmsg32.cmsg_len < sizeof(cmsg32)) {
258 1.39 joerg error = EINVAL;
259 1.39 joerg goto failure;
260 1.39 joerg }
261 1.39 joerg
262 1.39 joerg cspace = CMSG_SPACE(cmsg32.cmsg_len - CMSG32_LEN(0));
263 1.39 joerg
264 1.39 joerg /* Check the buffer is big enough */
265 1.39 joerg if (__predict_false(cidx + cspace > clen)) {
266 1.39 joerg u_int8_t *nc;
267 1.39 joerg size_t nclen;
268 1.39 joerg
269 1.39 joerg nclen = cidx + cspace;
270 1.39 joerg if (nclen >= PAGE_SIZE) {
271 1.39 joerg error = EINVAL;
272 1.39 joerg goto failure;
273 1.39 joerg }
274 1.39 joerg nc = realloc(clen <= MLEN ? NULL : control,
275 1.39 joerg nclen, M_TEMP, M_WAITOK);
276 1.39 joerg if (!nc) {
277 1.39 joerg error = ENOMEM;
278 1.39 joerg goto failure;
279 1.39 joerg }
280 1.39 joerg if (cidx <= MLEN) {
281 1.39 joerg /* Old buffer was in mbuf... */
282 1.39 joerg memcpy(nc, control, cidx);
283 1.39 joerg memset(nc + cidx, 0, nclen - cidx);
284 1.39 joerg } else {
285 1.39 joerg memset(nc + nclen, 0, nclen - clen);
286 1.39 joerg }
287 1.39 joerg control = nc;
288 1.39 joerg clen = nclen;
289 1.39 joerg }
290 1.39 joerg
291 1.39 joerg /* Copy header */
292 1.39 joerg cmsg = (void *)&control[cidx];
293 1.39 joerg cmsg->cmsg_len = CMSG_LEN(cmsg32.cmsg_len - CMSG32_LEN(0));
294 1.39 joerg cmsg->cmsg_level = cmsg32.cmsg_level;
295 1.39 joerg cmsg->cmsg_type = cmsg32.cmsg_type;
296 1.39 joerg
297 1.39 joerg /* Copyin the data */
298 1.39 joerg error = copyin(CMSG32_DATA(cc), CMSG_DATA(cmsg),
299 1.39 joerg cmsg32.cmsg_len - CMSG32_LEN(0));
300 1.39 joerg if (error)
301 1.39 joerg goto failure;
302 1.45 christos ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
303 1.39 joerg
304 1.39 joerg resid -= CMSG32_ALIGN(cmsg32.cmsg_len);
305 1.45 christos cidx += CMSG_ALIGN(cmsg->cmsg_len);
306 1.45 christos }
307 1.39 joerg
308 1.39 joerg /* If we allocated a buffer, attach to mbuf */
309 1.39 joerg if (cidx > MLEN) {
310 1.39 joerg MEXTADD(ctl_mbuf, control, clen, M_MBUF, NULL, NULL);
311 1.39 joerg ctl_mbuf->m_flags |= M_EXT_RW;
312 1.39 joerg }
313 1.39 joerg control = NULL;
314 1.39 joerg mp->msg_controllen = ctl_mbuf->m_len = CMSG_ALIGN(cidx);
315 1.39 joerg
316 1.39 joerg mp->msg_control = ctl_mbuf;
317 1.39 joerg mp->msg_flags |= MSG_CONTROLMBUF;
318 1.39 joerg
319 1.39 joerg
320 1.39 joerg return 0;
321 1.39 joerg
322 1.39 joerg failure:
323 1.39 joerg if (control != mtod(ctl_mbuf, void *))
324 1.39 joerg free(control, M_MBUF);
325 1.39 joerg m_free(ctl_mbuf);
326 1.39 joerg return error;
327 1.39 joerg }
328 1.39 joerg
329 1.1 mrg int
330 1.45 christos netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap,
331 1.45 christos register_t *retval)
332 1.1 mrg {
333 1.30 dsl /* {
334 1.1 mrg syscallarg(int) s;
335 1.1 mrg syscallarg(const netbsd32_msghdrp_t) msg;
336 1.1 mrg syscallarg(int) flags;
337 1.30 dsl } */
338 1.1 mrg struct msghdr msg;
339 1.1 mrg struct netbsd32_msghdr msg32;
340 1.42 maxv struct iovec aiov[UIO_SMALLIOV], *iov = aiov;
341 1.35 njoly struct netbsd32_iovec *iov32;
342 1.37 rmind size_t iovsz;
343 1.1 mrg int error;
344 1.1 mrg
345 1.24 dsl error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
346 1.1 mrg if (error)
347 1.1 mrg return (error);
348 1.1 mrg netbsd32_to_msghdr(&msg32, &msg);
349 1.39 joerg msg.msg_flags = 0;
350 1.39 joerg
351 1.39 joerg if (CMSG32_FIRSTHDR(&msg)) {
352 1.39 joerg error = copyin32_msg_control(l, &msg);
353 1.39 joerg if (error)
354 1.39 joerg return (error);
355 1.42 maxv /* From here on, msg.msg_control is allocated */
356 1.39 joerg } else {
357 1.39 joerg msg.msg_control = NULL;
358 1.39 joerg msg.msg_controllen = 0;
359 1.39 joerg }
360 1.26 dsl
361 1.37 rmind iovsz = msg.msg_iovlen * sizeof(struct iovec);
362 1.1 mrg if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
363 1.42 maxv if ((u_int)msg.msg_iovlen > IOV_MAX) {
364 1.42 maxv error = EMSGSIZE;
365 1.42 maxv goto out;
366 1.42 maxv }
367 1.37 rmind iov = kmem_alloc(iovsz, KM_SLEEP);
368 1.42 maxv }
369 1.26 dsl
370 1.35 njoly iov32 = NETBSD32PTR64(msg32.msg_iov);
371 1.35 njoly error = netbsd32_to_iovecin(iov32, iov, msg.msg_iovlen);
372 1.1 mrg if (error)
373 1.42 maxv goto out;
374 1.1 mrg msg.msg_iov = iov;
375 1.26 dsl
376 1.44 martin error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
377 1.45 christos retval);
378 1.42 maxv /* msg.msg_control freed by do_sys_sendmsg() */
379 1.42 maxv
380 1.1 mrg if (iov != aiov)
381 1.37 rmind kmem_free(iov, iovsz);
382 1.1 mrg return (error);
383 1.42 maxv
384 1.42 maxv out:
385 1.42 maxv if (iov != aiov)
386 1.42 maxv kmem_free(iov, iovsz);
387 1.42 maxv if (msg.msg_control)
388 1.42 maxv m_free(msg.msg_control);
389 1.42 maxv return error;
390 1.1 mrg }
391 1.1 mrg
392 1.1 mrg int
393 1.45 christos netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap,
394 1.45 christos register_t *retval)
395 1.1 mrg {
396 1.30 dsl /* {
397 1.1 mrg syscallarg(int) s;
398 1.1 mrg syscallarg(netbsd32_voidp) buf;
399 1.1 mrg syscallarg(netbsd32_size_t) len;
400 1.1 mrg syscallarg(int) flags;
401 1.1 mrg syscallarg(netbsd32_sockaddrp_t) from;
402 1.1 mrg syscallarg(netbsd32_intp) fromlenaddr;
403 1.30 dsl } */
404 1.38 joerg struct msghdr msg;
405 1.38 joerg struct iovec aiov;
406 1.38 joerg int error;
407 1.38 joerg struct mbuf *from;
408 1.1 mrg
409 1.38 joerg msg.msg_name = NULL;
410 1.38 joerg msg.msg_iov = &aiov;
411 1.1 mrg msg.msg_iovlen = 1;
412 1.24 dsl aiov.iov_base = SCARG_P32(uap, buf);
413 1.38 joerg aiov.iov_len = SCARG(uap, len);
414 1.38 joerg msg.msg_control = NULL;
415 1.38 joerg msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
416 1.38 joerg
417 1.45 christos error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
418 1.38 joerg if (error != 0)
419 1.38 joerg return error;
420 1.38 joerg
421 1.45 christos error = copyout_sockname(SCARG_P32(uap, from),
422 1.45 christos SCARG_P32(uap, fromlenaddr), MSG_LENUSRSPACE, from);
423 1.38 joerg if (from != NULL)
424 1.38 joerg m_free(from);
425 1.38 joerg return error;
426 1.1 mrg }
427 1.1 mrg
428 1.1 mrg int
429 1.45 christos netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap,
430 1.45 christos register_t *retval)
431 1.1 mrg {
432 1.30 dsl /* {
433 1.1 mrg syscallarg(int) s;
434 1.1 mrg syscallarg(const netbsd32_voidp) buf;
435 1.1 mrg syscallarg(netbsd32_size_t) len;
436 1.1 mrg syscallarg(int) flags;
437 1.1 mrg syscallarg(const netbsd32_sockaddrp_t) to;
438 1.1 mrg syscallarg(int) tolen;
439 1.30 dsl } */
440 1.1 mrg struct msghdr msg;
441 1.1 mrg struct iovec aiov;
442 1.1 mrg
443 1.24 dsl msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */
444 1.1 mrg msg.msg_namelen = SCARG(uap, tolen);
445 1.1 mrg msg.msg_iov = &aiov;
446 1.1 mrg msg.msg_iovlen = 1;
447 1.1 mrg msg.msg_control = 0;
448 1.24 dsl aiov.iov_base = SCARG_P32(uap, buf); /* XXX kills const */
449 1.1 mrg aiov.iov_len = SCARG(uap, len);
450 1.26 dsl msg.msg_flags = 0;
451 1.44 martin return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
452 1.45 christos retval);
453 1.1 mrg }
454