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