1 /*        $NetBSD: netbsd32_socket.c,v 1.56 2021/01/19 03:41:22 simonb 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.56 2021/01/19 03:41:22 simonb 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 struct sockaddr is compatible.
53  */
54 
55 #define   CMSG32_ALIGN(n)     (((n) + ALIGNBYTES32) & ~ALIGNBYTES32)
56 #define CMSG32_ASIZE          CMSG32_ALIGN(sizeof(struct cmsghdr))
57 #define   CMSG32_DATA(cmsg) (__CASTV(u_char *, cmsg) + CMSG32_ASIZE)
58 #define CMSG32_MSGNEXT(ucmsg, kcmsg) \
59     (__CASTV(char *, kcmsg) + CMSG32_ALIGN((ucmsg)->cmsg_len))
60 #define CMSG32_MSGEND(mhdr) \
61     (__CASTV(char *, (mhdr)->msg_control) + (mhdr)->msg_controllen)
62 
63 #define   CMSG32_NXTHDR(mhdr, ucmsg, kcmsg)       \
64     __CASTV(struct cmsghdr *,  \
65           CMSG32_MSGNEXT(ucmsg, kcmsg) + \
66           CMSG32_ASIZE > CMSG32_MSGEND(mhdr) ? 0 : \
67           CMSG32_MSGNEXT(ucmsg, kcmsg))
68 #define   CMSG32_FIRSTHDR(mhdr) \
69     __CASTV(struct cmsghdr *, \
70           (mhdr)->msg_controllen < sizeof(struct cmsghdr) ? 0 : \
71           (mhdr)->msg_control)
72 
73 #define CMSG32_SPACE(l)       (CMSG32_ALIGN(sizeof(struct cmsghdr)) + CMSG32_ALIGN(l))
74 #define CMSG32_LEN(l)         (CMSG32_ALIGN(sizeof(struct cmsghdr)) + (l))
75 
76 static int
copyout32_msg_control_mbuf(struct lwp * l,struct msghdr * mp,u_int * len,struct mbuf * m,char ** q,bool * truncated)77 copyout32_msg_control_mbuf(struct lwp *l, struct msghdr *mp, u_int *len,
78     struct mbuf *m, char **q, bool *truncated)
79 {
80           struct cmsghdr *cmsg, cmsg32;
81           size_t i, j;
82           int error;
83 
84           *truncated = false;
85           cmsg = mtod(m, struct cmsghdr *);
86           do {
87                     if ((char *)cmsg == mtod(m, char *) + m->m_len)
88                               break;
89                     if ((char *)cmsg > mtod(m, char *) + m->m_len - sizeof(*cmsg))
90                               return EINVAL;
91                     cmsg32 = *cmsg;
92                     j = cmsg->cmsg_len - CMSG_LEN(0);
93                     i = cmsg32.cmsg_len = CMSG32_LEN(j);
94                     if (i > *len) {
95                               mp->msg_flags |= MSG_CTRUNC;
96                               if (cmsg->cmsg_level == SOL_SOCKET
97                                   && cmsg->cmsg_type == SCM_RIGHTS) {
98                                         *truncated = true;
99                                         return 0;
100                               }
101                               j -= i - *len;
102                               i = *len;
103                     }
104 
105                     ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
106                     error = copyout(&cmsg32, *q, MIN(i, sizeof(cmsg32)));
107                     if (error)
108                               return error;
109                     if (i > CMSG32_LEN(0)) {
110                               error = copyout(CMSG_DATA(cmsg), *q + CMSG32_LEN(0),
111                                   i - CMSG32_LEN(0));
112                               if (error)
113                                         return error;
114                     }
115                     j = CMSG32_SPACE(cmsg->cmsg_len - CMSG_LEN(0));
116                     if (*len >= j) {
117                               *len -= j;
118                               *q += j;
119                     } else {
120                               *q += i;
121                               *len = 0;
122                     }
123                     cmsg = (void *)((char *)cmsg + CMSG_ALIGN(cmsg->cmsg_len));
124           } while (*len > 0);
125 
126           return 0;
127 }
128 
129 static int
copyout32_msg_control(struct lwp * l,struct msghdr * mp,struct mbuf * control)130 copyout32_msg_control(struct lwp *l, struct msghdr *mp, struct mbuf *control)
131 {
132           int len, error = 0;
133           struct mbuf *m;
134           char *q;
135           bool truncated;
136 
137           len = mp->msg_controllen;
138           if (len <= 0 || control == 0) {
139                     mp->msg_controllen = 0;
140                     free_control_mbuf(l, control, control);
141                     return 0;
142           }
143 
144           q = (char *)mp->msg_control;
145 
146           for (m = control; len > 0 && m != NULL; m = m->m_next) {
147                     error = copyout32_msg_control_mbuf(l, mp, &len, m, &q,
148                         &truncated);
149                     if (truncated) {
150                               m = control;
151                               break;
152                     }
153                     if (error)
154                               break;
155           }
156 
157           free_control_mbuf(l, control, m);
158 
159           mp->msg_controllen = q - (char *)mp->msg_control;
160           return error;
161 }
162 
163 static int
msg_recv_copyin(struct lwp * l,const struct netbsd32_msghdr * msg32,struct msghdr * msg,struct iovec * aiov)164 msg_recv_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
165     struct msghdr *msg, struct iovec *aiov)
166 {
167           int error;
168           size_t iovsz;
169           struct iovec *iov = aiov;
170 
171           iovsz = msg32->msg_iovlen * sizeof(struct iovec);
172           if (msg32->msg_iovlen > UIO_SMALLIOV) {
173                     if (msg32->msg_iovlen > IOV_MAX)
174                               return EMSGSIZE;
175                     iov = kmem_alloc(iovsz, KM_SLEEP);
176           }
177 
178           error = netbsd32_to_iovecin(NETBSD32PTR64(msg32->msg_iov), iov,
179               msg32->msg_iovlen);
180           if (error)
181                     goto out;
182 
183           netbsd32_to_msghdr(msg32, msg);
184           msg->msg_iov = iov;
185 out:
186           if (iov != aiov)
187                     kmem_free(iov, iovsz);
188           return error;
189 }
190 
191 static int
msg_recv_copyout(struct lwp * l,struct netbsd32_msghdr * msg32,struct msghdr * msg,struct netbsd32_msghdr * arg,struct mbuf * from,struct mbuf * control)192 msg_recv_copyout(struct lwp *l, struct netbsd32_msghdr *msg32,
193     struct msghdr *msg, struct netbsd32_msghdr *arg,
194     struct mbuf *from, struct mbuf *control)
195 {
196           int error = 0;
197 
198           if (msg->msg_control != NULL)
199                     error = copyout32_msg_control(l, msg, control);
200 
201           if (error == 0)
202                     error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
203                               from);
204 
205           if (from != NULL)
206                     m_free(from);
207           if (error)
208                     return error;
209 
210           msg32->msg_namelen = msg->msg_namelen;
211           msg32->msg_controllen = msg->msg_controllen;
212           msg32->msg_flags = msg->msg_flags;
213           ktrkuser("msghdr", msg, sizeof(*msg));
214           if (arg == NULL)
215                     return 0;
216           return copyout(msg32, arg, sizeof(*arg));
217 }
218 
219 int
netbsd32_recvmsg(struct lwp * l,const struct netbsd32_recvmsg_args * uap,register_t * retval)220 netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap,
221     register_t *retval)
222 {
223           /* {
224                     syscallarg(int) s;
225                     syscallarg(netbsd32_msghdrp_t) msg;
226                     syscallarg(int) flags;
227           } */
228           struct netbsd32_msghdr        msg32;
229           struct iovec aiov[UIO_SMALLIOV];
230           struct msghdr       msg;
231           int                 error;
232           struct mbuf         *from, *control;
233 
234           error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
235           if (error)
236                     return error;
237 
238           if ((error = msg_recv_copyin(l, &msg32, &msg, aiov)) != 0)
239                     return error;
240 
241           msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
242           error = do_sys_recvmsg(l, SCARG(uap, s), &msg,
243               &from, msg.msg_control != NULL ? &control : NULL, retval);
244           if (error != 0)
245                     goto out;
246 
247           error = msg_recv_copyout(l, &msg32, &msg, SCARG_P32(uap, msg),
248               from, control);
249 out:
250           if (msg.msg_iov != aiov)
251                     kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
252           return error;
253 }
254 
255 int
netbsd32_recvmmsg(struct lwp * l,const struct netbsd32_recvmmsg_args * uap,register_t * retval)256 netbsd32_recvmmsg(struct lwp *l, const struct netbsd32_recvmmsg_args *uap,
257     register_t *retval)
258 {
259           /* {
260                     syscallarg(int)                                   s;
261                     syscallarg(netbsd32_mmsghdr_t)                    mmsg;
262                     syscallarg(unsigned int)                vlen;
263                     syscallarg(unsigned int)                flags;
264                     syscallarg(netbsd32_timespecp_t)        timeout;
265           } */
266           struct mmsghdr mmsg;
267           struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
268           struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
269           struct socket *so;
270           struct msghdr *msg = &mmsg.msg_hdr;
271           int error, s;
272           struct mbuf *from, *control;
273           struct timespec ts, now;
274           struct netbsd32_timespec ts32;
275           unsigned int vlen, flags, dg;
276           struct iovec aiov[UIO_SMALLIOV];
277 
278           ts.tv_sec = 0;      // XXX: gcc
279           ts.tv_nsec = 0;
280           if (SCARG_P32(uap, timeout)) {
281                     if ((error = copyin(SCARG_P32(uap, timeout), &ts32,
282                         sizeof(ts32))) != 0)
283                               return error;
284                     getnanotime(&now);
285                     netbsd32_to_timespec(&ts32, &ts);
286                     timespecadd(&now, &ts, &ts);
287           }
288 
289           s = SCARG(uap, s);
290           if ((error = fd_getsock(s, &so)) != 0)
291                     return error;
292 
293           /*
294            * If so->so_rerror holds a deferred error return it now.
295            */
296           if (so->so_rerror) {
297                     error = so->so_rerror;
298                     so->so_rerror = 0;
299                     fd_putfile(s);
300                     return error;
301           }
302 
303           vlen = SCARG(uap, vlen);
304           if (vlen > 1024)
305                     vlen = 1024;
306 
307           from = NULL;
308           flags = SCARG(uap, flags) & MSG_USERFLAGS;
309 
310           for (dg = 0; dg < vlen;) {
311                     error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
312                     if (error)
313                               break;
314 
315                     if ((error = msg_recv_copyin(l, msg32, msg, aiov)) != 0)
316                               return error;
317 
318                     msg->msg_flags = flags & ~MSG_WAITFORONE;
319 
320                     if (from != NULL) {
321                               m_free(from);
322                               from = NULL;
323                     }
324 
325                     error = do_sys_recvmsg_so(l, s, so, msg, &from,
326                         msg->msg_control != NULL ? &control : NULL, retval);
327                     if (error) {
328                               if (error == EAGAIN && dg > 0)
329                                         error = 0;
330                               break;
331                     }
332                     error = msg_recv_copyout(l, msg32, msg, NULL,
333                         from, control);
334                     from = NULL;
335                     if (error)
336                               break;
337 
338                     mmsg32.msg_len = *retval;
339 
340                     error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
341                     if (error)
342                               break;
343 
344                     dg++;
345                     if (msg->msg_flags & MSG_OOB)
346                               break;
347 
348                     if (SCARG_P32(uap, timeout)) {
349                               getnanotime(&now);
350                               timespecsub(&now, &ts, &now);
351                               if (now.tv_sec > 0)
352                                         break;
353                     }
354 
355                     if (flags & MSG_WAITFORONE)
356                               flags |= MSG_DONTWAIT;
357 
358           }
359 
360           if (from != NULL)
361                     m_free(from);
362 
363           *retval = dg;
364 
365           /*
366            * If we succeeded at least once, return 0, hopefully so->so_rerror
367            * will catch it next time.
368            */
369           if (error && dg > 0) {
370                     so->so_rerror = error;
371                     error = 0;
372           }
373 
374           fd_putfile(s);
375 
376           return error;
377 }
378 
379 static int
copyin32_msg_control(struct lwp * l,struct msghdr * mp)380 copyin32_msg_control(struct lwp *l, struct msghdr *mp)
381 {
382           /*
383            * Handle cmsg if there is any.
384            */
385           struct cmsghdr *cmsg, cmsg32, *cc;
386           struct mbuf *ctl_mbuf;
387           ssize_t resid = mp->msg_controllen;
388           size_t clen, cidx = 0, cspace;
389           uint8_t *control;
390           int error;
391 
392           ctl_mbuf = m_get(M_WAIT, MT_CONTROL);
393           clen = MLEN;
394           control = mtod(ctl_mbuf, void *);
395           memset(control, 0, clen);
396 
397           for (cc = CMSG32_FIRSTHDR(mp); cc; cc = CMSG32_NXTHDR(mp, &cmsg32, cc))
398           {
399                     error = copyin(cc, &cmsg32, sizeof(cmsg32));
400                     if (error)
401                               goto failure;
402 
403                     /*
404                      * Sanity check the control message length.
405                      */
406                     if (resid < 0 ||
407                         cmsg32.cmsg_len > (size_t)resid ||
408                         cmsg32.cmsg_len < sizeof(cmsg32)) {
409                               error = EINVAL;
410                               goto failure;
411                     }
412 
413                     cspace = CMSG_SPACE(cmsg32.cmsg_len - CMSG32_LEN(0));
414 
415                     /* Check the buffer is big enough */
416                     if (__predict_false(cidx + cspace > clen)) {
417                               uint8_t *nc;
418                               size_t nclen;
419 
420                               nclen = cidx + cspace;
421                               if (nclen >= (size_t)PAGE_SIZE) {
422                                         error = EINVAL;
423                                         goto failure;
424                               }
425                               nc = realloc(clen <= MLEN ? NULL : control,
426                                              nclen, M_TEMP, M_WAITOK);
427                               if (!nc) {
428                                         error = ENOMEM;
429                                         goto failure;
430                               }
431                               if (cidx <= MLEN) {
432                                         /* Old buffer was in mbuf... */
433                                         memcpy(nc, control, cidx);
434                                         memset(nc + cidx, 0, nclen - cidx);
435                               } else {
436                                         memset(nc + nclen, 0, nclen - clen);
437                               }
438                               control = nc;
439                               clen = nclen;
440                     }
441 
442                     /* Copy header */
443                     cmsg = (void *)&control[cidx];
444                     cmsg->cmsg_len = CMSG_LEN(cmsg32.cmsg_len - CMSG32_LEN(0));
445                     cmsg->cmsg_level = cmsg32.cmsg_level;
446                     cmsg->cmsg_type = cmsg32.cmsg_type;
447 
448                     /* Copyin the data */
449                     error = copyin(CMSG32_DATA(cc), CMSG_DATA(cmsg),
450                         cmsg32.cmsg_len - CMSG32_LEN(0));
451                     if (error)
452                               goto failure;
453                     ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
454 
455                     resid -= CMSG32_ALIGN(cmsg32.cmsg_len);
456                     cidx += CMSG_ALIGN(cmsg->cmsg_len);
457           }
458 
459           /* If we allocated a buffer, attach to mbuf */
460           if (cidx > MLEN) {
461                     MEXTADD(ctl_mbuf, control, clen, M_MBUF, NULL, NULL);
462                     ctl_mbuf->m_flags |= M_EXT_RW;
463           }
464           control = NULL;
465           mp->msg_controllen = ctl_mbuf->m_len = CMSG_ALIGN(cidx);
466 
467           mp->msg_control = ctl_mbuf;
468           mp->msg_flags |= MSG_CONTROLMBUF;
469 
470 
471           return 0;
472 
473 failure:
474           if (control != mtod(ctl_mbuf, void *))
475                     free(control, M_MBUF);
476           m_free(ctl_mbuf);
477           return error;
478 }
479 
480 static int
msg_send_copyin(struct lwp * l,const struct netbsd32_msghdr * msg32,struct msghdr * msg,struct iovec * aiov)481 msg_send_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
482     struct msghdr *msg, struct iovec *aiov)
483 {
484           int error;
485           struct iovec *iov = aiov;
486           struct netbsd32_iovec *iov32;
487           size_t iovsz;
488 
489           netbsd32_to_msghdr(msg32, msg);
490           msg->msg_flags = 0;
491 
492           if (CMSG32_FIRSTHDR(msg)) {
493                     error = copyin32_msg_control(l, msg);
494                     if (error)
495                               return error;
496                     /* From here on, msg->msg_control is allocated */
497           } else {
498                     msg->msg_control = NULL;
499                     msg->msg_controllen = 0;
500           }
501 
502           iovsz = msg->msg_iovlen * sizeof(struct iovec);
503           if ((u_int)msg->msg_iovlen > UIO_SMALLIOV) {
504                     if ((u_int)msg->msg_iovlen > IOV_MAX) {
505                               error = EMSGSIZE;
506                               goto out;
507                     }
508                     iov = kmem_alloc(iovsz, KM_SLEEP);
509           }
510 
511           iov32 = NETBSD32PTR64(msg32->msg_iov);
512           error = netbsd32_to_iovecin(iov32, iov, msg->msg_iovlen);
513           if (error)
514                     goto out;
515           msg->msg_iov = iov;
516           return 0;
517 out:
518           if (msg->msg_control)
519                     m_free(msg->msg_control);
520           if (iov != aiov)
521                     kmem_free(iov, iovsz);
522           return error;
523 }
524 
525 int
netbsd32_sendmsg(struct lwp * l,const struct netbsd32_sendmsg_args * uap,register_t * retval)526 netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap,
527     register_t *retval)
528 {
529           /* {
530                     syscallarg(int) s;
531                     syscallarg(const netbsd32_msghdrp_t) msg;
532                     syscallarg(int) flags;
533           } */
534           struct msghdr msg;
535           struct netbsd32_msghdr msg32;
536           struct iovec aiov[UIO_SMALLIOV];
537           int error;
538 
539           error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
540           if (error)
541                     return error;
542 
543           if ((error = msg_send_copyin(l, &msg32, &msg, aiov)) != 0)
544                     return error;
545 
546           error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
547               retval);
548           /* msg.msg_control freed by do_sys_sendmsg() */
549 
550           if (msg.msg_iov != aiov)
551                     kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
552           return error;
553 }
554 
555 int
netbsd32_sendmmsg(struct lwp * l,const struct netbsd32_sendmmsg_args * uap,register_t * retval)556 netbsd32_sendmmsg(struct lwp *l, const struct netbsd32_sendmmsg_args *uap,
557     register_t *retval)
558 {
559           /* {
560                     syscallarg(int)                         s;
561                     syscallarg(const netbsd32_mmsghdr_t)    mmsg;
562                     syscallarg(unsigned int)      vlen;
563                     syscallarg(unsigned int)      flags;
564           } */
565           struct mmsghdr mmsg;
566           struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
567           struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
568           struct socket *so;
569           file_t *fp;
570           struct msghdr *msg = &mmsg.msg_hdr;
571           int error, s;
572           unsigned int vlen, flags, dg;
573           struct iovec aiov[UIO_SMALLIOV];
574 
575           s = SCARG(uap, s);
576           if ((error = fd_getsock1(s, &so, &fp)) != 0)
577                     return error;
578 
579           vlen = SCARG(uap, vlen);
580           if (vlen > 1024)
581                     vlen = 1024;
582 
583           flags = SCARG(uap, flags) & MSG_USERFLAGS;
584 
585           for (dg = 0; dg < vlen;) {
586                     error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
587                     if (error)
588                               break;
589                     if ((error = msg_send_copyin(l, msg32, msg, aiov)) != 0)
590                               break;
591 
592                     msg->msg_flags = flags;
593 
594                     error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
595                     if (msg->msg_iov != aiov) {
596                               kmem_free(msg->msg_iov,
597                                   msg->msg_iovlen * sizeof(struct iovec));
598                     }
599                     if (error)
600                               break;
601 
602                     ktrkuser("msghdr", msg, sizeof(*msg));
603                     mmsg.msg_len = *retval;
604                     netbsd32_from_mmsghdr(&mmsg32, &mmsg);
605                     error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
606                     if (error)
607                               break;
608                     dg++;
609           }
610 
611           *retval = dg;
612 
613           fd_putfile(s);
614 
615           /*
616            * If we succeeded at least once, return 0.
617            */
618           if (dg)
619                     return 0;
620           return error;
621 }
622 
623 int
netbsd32_recvfrom(struct lwp * l,const struct netbsd32_recvfrom_args * uap,register_t * retval)624 netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap,
625     register_t *retval)
626 {
627           /* {
628                     syscallarg(int) s;
629                     syscallarg(netbsd32_voidp) buf;
630                     syscallarg(netbsd32_size_t) len;
631                     syscallarg(int) flags;
632                     syscallarg(netbsd32_sockaddrp_t) from;
633                     syscallarg(netbsd32_intp) fromlenaddr;
634           } */
635           struct msghdr       msg;
636           struct iovec        aiov;
637           int                 error;
638           struct mbuf         *from;
639 
640           if (SCARG(uap, len) > NETBSD32_SSIZE_MAX)
641                     return EINVAL;
642 
643           msg.msg_name = NULL;
644           msg.msg_iov = &aiov;
645           msg.msg_iovlen = 1;
646           aiov.iov_base = SCARG_P32(uap, buf);
647           aiov.iov_len = SCARG(uap, len);
648           msg.msg_control = NULL;
649           msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
650 
651           error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
652           if (error != 0)
653                     return error;
654 
655           error = copyout_sockname(SCARG_P32(uap, from),
656               SCARG_P32(uap, fromlenaddr), MSG_LENUSRSPACE, from);
657           if (from != NULL)
658                     m_free(from);
659           return error;
660 }
661 
662 int
netbsd32_sendto(struct lwp * l,const struct netbsd32_sendto_args * uap,register_t * retval)663 netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap,
664     register_t *retval)
665 {
666           /* {
667                     syscallarg(int) s;
668                     syscallarg(const netbsd32_voidp) buf;
669                     syscallarg(netbsd32_size_t) len;
670                     syscallarg(int) flags;
671                     syscallarg(const netbsd32_sockaddrp_t) to;
672                     syscallarg(int) tolen;
673           } */
674           struct msghdr msg;
675           struct iovec aiov;
676 
677           if (SCARG(uap, len) > NETBSD32_SSIZE_MAX)
678                     return EINVAL;
679 
680           msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */
681           msg.msg_namelen = SCARG(uap, tolen);
682           msg.msg_iov = &aiov;
683           msg.msg_iovlen = 1;
684           msg.msg_control = 0;
685           aiov.iov_base = SCARG_P32(uap, buf);    /* XXX kills const */
686           aiov.iov_len = SCARG(uap, len);
687           msg.msg_flags = 0;
688           return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
689               retval);
690 }
691