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