Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_socket.c revision 1.44.14.2
      1  1.44.14.2  pgoyette /*	$NetBSD: netbsd32_socket.c,v 1.44.14.2 2018/11/26 01:52:29 pgoyette 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.44.14.2  pgoyette __KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.44.14.2 2018/11/26 01:52:29 pgoyette 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.44.14.1  pgoyette #define CMSG32_ASIZE	CMSG32_ALIGN(sizeof(struct cmsghdr))
     57  1.44.14.1  pgoyette #define	CMSG32_DATA(cmsg) (__CASTV(u_char *, cmsg) + CMSG32_ASIZE)
     58  1.44.14.1  pgoyette #define CMSG32_MSGNEXT(ucmsg, kcmsg) \
     59  1.44.14.1  pgoyette     (__CASTV(char *, kcmsg) + CMSG32_ALIGN((ucmsg)->cmsg_len))
     60  1.44.14.1  pgoyette #define CMSG32_MSGEND(mhdr) \
     61  1.44.14.1  pgoyette     (__CASTV(char *, (mhdr)->msg_control) + (mhdr)->msg_controllen)
     62  1.44.14.1  pgoyette 
     63  1.44.14.1  pgoyette #define	CMSG32_NXTHDR(mhdr, ucmsg, kcmsg)	\
     64  1.44.14.1  pgoyette     __CASTV(struct cmsghdr *,  \
     65  1.44.14.1  pgoyette 	CMSG32_MSGNEXT(ucmsg, kcmsg) + \
     66  1.44.14.1  pgoyette 	CMSG32_ASIZE > CMSG32_MSGEND(mhdr) ? 0 : \
     67  1.44.14.1  pgoyette 	CMSG32_MSGNEXT(ucmsg, kcmsg))
     68       1.39     joerg #define	CMSG32_FIRSTHDR(mhdr) \
     69  1.44.14.1  pgoyette     __CASTV(struct cmsghdr *, \
     70  1.44.14.1  pgoyette 	(mhdr)->msg_controllen < sizeof(struct cmsghdr) ? 0 : \
     71  1.44.14.1  pgoyette 	(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.44.14.1  pgoyette copyout32_msg_control_mbuf(struct lwp *l, struct msghdr *mp, int *len,
     78  1.44.14.1  pgoyette     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.44.14.1  pgoyette 		ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
    105  1.44.14.2  pgoyette 		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.44.14.1  pgoyette 			error = copyout(CMSG_DATA(cmsg), *q + CMSG32_LEN(0),
    110  1.44.14.1  pgoyette 			    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.44.14.1  pgoyette 		error = copyout32_msg_control_mbuf(l, mp, &len, m, &q,
    147  1.44.14.1  pgoyette 		    &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.44.14.1  pgoyette static int
    163  1.44.14.1  pgoyette msg_recv_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
    164  1.44.14.1  pgoyette     struct msghdr *msg, struct iovec *aiov)
    165  1.44.14.1  pgoyette {
    166  1.44.14.1  pgoyette 	int error;
    167  1.44.14.1  pgoyette 	size_t iovsz;
    168  1.44.14.1  pgoyette 	struct iovec *iov = aiov;
    169  1.44.14.1  pgoyette 
    170  1.44.14.1  pgoyette 	iovsz = msg32->msg_iovlen * sizeof(struct iovec);
    171  1.44.14.1  pgoyette 	if (msg32->msg_iovlen > UIO_SMALLIOV) {
    172  1.44.14.1  pgoyette 		if (msg32->msg_iovlen > IOV_MAX)
    173  1.44.14.1  pgoyette 			return EMSGSIZE;
    174  1.44.14.1  pgoyette 		iov = kmem_alloc(iovsz, KM_SLEEP);
    175  1.44.14.1  pgoyette 	}
    176  1.44.14.1  pgoyette 
    177  1.44.14.1  pgoyette 	error = netbsd32_to_iovecin(NETBSD32PTR64(msg32->msg_iov), iov,
    178  1.44.14.1  pgoyette 	    msg32->msg_iovlen);
    179  1.44.14.1  pgoyette 	if (error)
    180  1.44.14.1  pgoyette 		goto out;
    181  1.44.14.1  pgoyette 
    182  1.44.14.1  pgoyette 	netbsd32_to_msghdr(msg32, msg);
    183  1.44.14.1  pgoyette 	msg->msg_iov = iov;
    184  1.44.14.1  pgoyette out:
    185  1.44.14.1  pgoyette 	if (iov != aiov)
    186  1.44.14.1  pgoyette 		kmem_free(iov, iovsz);
    187  1.44.14.1  pgoyette 	return error;
    188  1.44.14.1  pgoyette }
    189  1.44.14.1  pgoyette 
    190  1.44.14.1  pgoyette static int
    191  1.44.14.1  pgoyette msg_recv_copyout(struct lwp *l, struct netbsd32_msghdr *msg32,
    192  1.44.14.1  pgoyette     struct msghdr *msg, struct netbsd32_msghdr *arg,
    193  1.44.14.1  pgoyette     struct mbuf *from, struct mbuf *control)
    194  1.44.14.1  pgoyette {
    195  1.44.14.1  pgoyette 	int error = 0;
    196  1.44.14.1  pgoyette 
    197  1.44.14.1  pgoyette 	if (msg->msg_control != NULL)
    198  1.44.14.1  pgoyette 		error = copyout32_msg_control(l, msg, control);
    199  1.44.14.1  pgoyette 
    200  1.44.14.1  pgoyette 	if (error == 0)
    201  1.44.14.1  pgoyette 		error = copyout_sockname(msg->msg_name, &msg->msg_namelen, 0,
    202  1.44.14.1  pgoyette 			from);
    203  1.44.14.1  pgoyette 
    204  1.44.14.1  pgoyette 	if (from != NULL)
    205  1.44.14.1  pgoyette 		m_free(from);
    206  1.44.14.1  pgoyette 	if (error)
    207  1.44.14.1  pgoyette 		return error;
    208  1.44.14.1  pgoyette 
    209  1.44.14.1  pgoyette 	msg32->msg_namelen = msg->msg_namelen;
    210  1.44.14.1  pgoyette 	msg32->msg_controllen = msg->msg_controllen;
    211  1.44.14.1  pgoyette 	msg32->msg_flags = msg->msg_flags;
    212  1.44.14.1  pgoyette 	ktrkuser("msghdr", msg, sizeof(*msg));
    213  1.44.14.1  pgoyette 	if (arg == NULL)
    214  1.44.14.1  pgoyette 		return 0;
    215  1.44.14.1  pgoyette 	return copyout(msg32, arg, sizeof(*arg));
    216  1.44.14.1  pgoyette }
    217  1.44.14.1  pgoyette 
    218        1.1       mrg int
    219  1.44.14.1  pgoyette netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap,
    220  1.44.14.1  pgoyette     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.44.14.1  pgoyette 	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.44.14.1  pgoyette 	if ((error = msg_recv_copyin(l, &msg32, &msg, aiov)) != 0)
    238  1.44.14.1  pgoyette 		return error;
    239        1.1       mrg 
    240       1.38     joerg 	msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
    241  1.44.14.1  pgoyette 	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.44.14.1  pgoyette 		goto out;
    245  1.44.14.1  pgoyette 
    246  1.44.14.1  pgoyette 	error = msg_recv_copyout(l, &msg32, &msg, SCARG_P32(uap, msg),
    247  1.44.14.1  pgoyette 	    from, control);
    248  1.44.14.1  pgoyette out:
    249  1.44.14.1  pgoyette 	if (msg.msg_iov != aiov)
    250  1.44.14.1  pgoyette 		kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
    251  1.44.14.1  pgoyette 	return error;
    252  1.44.14.1  pgoyette }
    253        1.1       mrg 
    254  1.44.14.1  pgoyette int
    255  1.44.14.1  pgoyette netbsd32_recvmmsg(struct lwp *l, const struct netbsd32_recvmmsg_args *uap,
    256  1.44.14.1  pgoyette     register_t *retval)
    257  1.44.14.1  pgoyette {
    258  1.44.14.1  pgoyette 	/* {
    259  1.44.14.1  pgoyette 		syscallarg(int)				s;
    260  1.44.14.1  pgoyette 		syscallarg(netbsd32_mmsghdr_t)		mmsg;
    261  1.44.14.1  pgoyette 		syscallarg(unsigned int)		vlen;
    262  1.44.14.1  pgoyette 		syscallarg(unsigned int)		flags;
    263  1.44.14.1  pgoyette 		syscallarg(netbsd32_timespecp_t)	timeout;
    264  1.44.14.1  pgoyette 	} */
    265  1.44.14.1  pgoyette 	struct mmsghdr mmsg;
    266  1.44.14.1  pgoyette 	struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
    267  1.44.14.1  pgoyette 	struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
    268  1.44.14.1  pgoyette 	struct socket *so;
    269  1.44.14.1  pgoyette 	struct msghdr *msg = &mmsg.msg_hdr;
    270  1.44.14.1  pgoyette 	int error, s;
    271  1.44.14.1  pgoyette 	struct mbuf *from, *control;
    272  1.44.14.1  pgoyette 	struct timespec ts, now;
    273  1.44.14.1  pgoyette 	struct netbsd32_timespec ts32;
    274  1.44.14.1  pgoyette 	unsigned int vlen, flags, dg;
    275  1.44.14.1  pgoyette 	struct iovec aiov[UIO_SMALLIOV];
    276  1.44.14.1  pgoyette 
    277  1.44.14.1  pgoyette 	ts.tv_sec = 0;	// XXX: gcc
    278  1.44.14.1  pgoyette 	ts.tv_nsec = 0;
    279  1.44.14.1  pgoyette 	if (SCARG_P32(uap, timeout)) {
    280  1.44.14.1  pgoyette 		if ((error = copyin(SCARG_P32(uap, timeout), &ts32,
    281  1.44.14.1  pgoyette 		    sizeof(ts32))) != 0)
    282  1.44.14.1  pgoyette 			return error;
    283  1.44.14.1  pgoyette 		getnanotime(&now);
    284  1.44.14.1  pgoyette 		netbsd32_to_timespec(&ts32, &ts);
    285  1.44.14.1  pgoyette 		timespecadd(&now, &ts, &ts);
    286  1.44.14.1  pgoyette 	}
    287  1.44.14.1  pgoyette 
    288  1.44.14.1  pgoyette 	s = SCARG(uap, s);
    289  1.44.14.1  pgoyette 	if ((error = fd_getsock(s, &so)) != 0)
    290  1.44.14.1  pgoyette 		return error;
    291  1.44.14.1  pgoyette 
    292  1.44.14.2  pgoyette 	/*
    293  1.44.14.2  pgoyette 	 * If so->so_rerror holds a deferred error return it now.
    294  1.44.14.2  pgoyette 	 */
    295  1.44.14.2  pgoyette 	if (so->so_rerror) {
    296  1.44.14.2  pgoyette 		error = so->so_rerror;
    297  1.44.14.2  pgoyette 		so->so_rerror = 0;
    298  1.44.14.2  pgoyette 		fd_putfile(s);
    299  1.44.14.2  pgoyette 		return error;
    300  1.44.14.2  pgoyette 	}
    301  1.44.14.2  pgoyette 
    302  1.44.14.1  pgoyette 	vlen = SCARG(uap, vlen);
    303  1.44.14.1  pgoyette 	if (vlen > 1024)
    304  1.44.14.1  pgoyette 		vlen = 1024;
    305  1.44.14.1  pgoyette 
    306  1.44.14.1  pgoyette 	from = NULL;
    307  1.44.14.1  pgoyette 	flags = SCARG(uap, flags) & MSG_USERFLAGS;
    308  1.44.14.1  pgoyette 
    309  1.44.14.1  pgoyette 	for (dg = 0; dg < vlen;) {
    310  1.44.14.1  pgoyette 		error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
    311  1.44.14.1  pgoyette 		if (error)
    312  1.44.14.1  pgoyette 			break;
    313  1.44.14.1  pgoyette 
    314  1.44.14.1  pgoyette 		if ((error = msg_recv_copyin(l, msg32, msg, aiov)) != 0)
    315  1.44.14.1  pgoyette 			return error;
    316  1.44.14.1  pgoyette 
    317  1.44.14.1  pgoyette 		msg->msg_flags = flags & ~MSG_WAITFORONE;
    318  1.44.14.1  pgoyette 
    319  1.44.14.1  pgoyette 		if (from != NULL) {
    320  1.44.14.1  pgoyette 			m_free(from);
    321  1.44.14.1  pgoyette 			from = NULL;
    322  1.44.14.1  pgoyette 		}
    323  1.44.14.1  pgoyette 
    324  1.44.14.1  pgoyette 		error = do_sys_recvmsg_so(l, s, so, msg, &from,
    325  1.44.14.1  pgoyette 		    msg->msg_control != NULL ? &control : NULL, retval);
    326  1.44.14.1  pgoyette 		if (error) {
    327  1.44.14.1  pgoyette 			if (error == EAGAIN && dg > 0)
    328  1.44.14.1  pgoyette 				error = 0;
    329  1.44.14.1  pgoyette 			break;
    330  1.44.14.1  pgoyette 		}
    331  1.44.14.1  pgoyette 		error = msg_recv_copyout(l, msg32, msg, NULL,
    332  1.44.14.1  pgoyette 		    from, control);
    333  1.44.14.1  pgoyette 		from = NULL;
    334  1.44.14.1  pgoyette 		if (error)
    335  1.44.14.1  pgoyette 			break;
    336  1.44.14.1  pgoyette 
    337  1.44.14.1  pgoyette 		mmsg32.msg_len = *retval;
    338  1.44.14.1  pgoyette 
    339  1.44.14.1  pgoyette 		error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
    340  1.44.14.1  pgoyette 		if (error)
    341  1.44.14.1  pgoyette 			break;
    342  1.44.14.1  pgoyette 
    343  1.44.14.1  pgoyette 		dg++;
    344  1.44.14.1  pgoyette 		if (msg->msg_flags & MSG_OOB)
    345  1.44.14.1  pgoyette 			break;
    346  1.44.14.1  pgoyette 
    347  1.44.14.1  pgoyette 		if (SCARG_P32(uap, timeout)) {
    348  1.44.14.1  pgoyette 			getnanotime(&now);
    349  1.44.14.1  pgoyette 			timespecsub(&now, &ts, &now);
    350  1.44.14.1  pgoyette 			if (now.tv_sec > 0)
    351  1.44.14.1  pgoyette 				break;
    352  1.44.14.1  pgoyette 		}
    353  1.44.14.1  pgoyette 
    354  1.44.14.1  pgoyette 		if (flags & MSG_WAITFORONE)
    355  1.44.14.1  pgoyette 			flags |= MSG_DONTWAIT;
    356  1.44.14.1  pgoyette 
    357  1.44.14.1  pgoyette 	}
    358       1.27        ad 
    359       1.38     joerg 	if (from != NULL)
    360       1.38     joerg 		m_free(from);
    361       1.27        ad 
    362  1.44.14.1  pgoyette 	*retval = dg;
    363  1.44.14.1  pgoyette 
    364  1.44.14.1  pgoyette 	/*
    365  1.44.14.2  pgoyette 	 * If we succeeded at least once, return 0, hopefully so->so_rerror
    366  1.44.14.1  pgoyette 	 * will catch it next time.
    367  1.44.14.1  pgoyette 	 */
    368  1.44.14.2  pgoyette 	if (error && dg > 0) {
    369  1.44.14.2  pgoyette 		so->so_rerror = error;
    370  1.44.14.2  pgoyette 		error = 0;
    371  1.44.14.2  pgoyette 	}
    372  1.44.14.2  pgoyette 
    373  1.44.14.2  pgoyette 	fd_putfile(s);
    374  1.44.14.1  pgoyette 
    375  1.44.14.1  pgoyette 	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.44.14.1  pgoyette 	for (cc = CMSG32_FIRSTHDR(mp); cc; cc = CMSG32_NXTHDR(mp, &cmsg32, cc))
    397  1.44.14.1  pgoyette 	{
    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.44.14.1  pgoyette 		ktrkuser(mbuftypes[MT_CONTROL], cmsg, cmsg->cmsg_len);
    452       1.39     joerg 
    453       1.39     joerg 		resid -= CMSG32_ALIGN(cmsg32.cmsg_len);
    454  1.44.14.1  pgoyette 		cidx += CMSG_ALIGN(cmsg->cmsg_len);
    455  1.44.14.1  pgoyette 	}
    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.44.14.1  pgoyette static int
    479  1.44.14.1  pgoyette msg_send_copyin(struct lwp *l, const struct netbsd32_msghdr *msg32,
    480  1.44.14.1  pgoyette     struct msghdr *msg, struct iovec *aiov)
    481        1.1       mrg {
    482  1.44.14.1  pgoyette 	int error;
    483  1.44.14.1  pgoyette 	struct iovec *iov = aiov;
    484       1.35     njoly 	struct netbsd32_iovec *iov32;
    485       1.37     rmind 	size_t iovsz;
    486        1.1       mrg 
    487  1.44.14.1  pgoyette 	netbsd32_to_msghdr(msg32, msg);
    488  1.44.14.1  pgoyette 	msg->msg_flags = 0;
    489       1.39     joerg 
    490  1.44.14.1  pgoyette 	if (CMSG32_FIRSTHDR(msg)) {
    491  1.44.14.1  pgoyette 		error = copyin32_msg_control(l, msg);
    492       1.39     joerg 		if (error)
    493  1.44.14.1  pgoyette 			return error;
    494  1.44.14.1  pgoyette 		/* From here on, msg->msg_control is allocated */
    495       1.39     joerg 	} else {
    496  1.44.14.1  pgoyette 		msg->msg_control = NULL;
    497  1.44.14.1  pgoyette 		msg->msg_controllen = 0;
    498       1.39     joerg 	}
    499       1.26       dsl 
    500  1.44.14.1  pgoyette 	iovsz = msg->msg_iovlen * sizeof(struct iovec);
    501  1.44.14.1  pgoyette 	if ((u_int)msg->msg_iovlen > UIO_SMALLIOV) {
    502  1.44.14.1  pgoyette 		if ((u_int)msg->msg_iovlen > IOV_MAX) {
    503       1.42      maxv 			error = EMSGSIZE;
    504       1.42      maxv 			goto out;
    505       1.42      maxv 		}
    506       1.37     rmind 		iov = kmem_alloc(iovsz, KM_SLEEP);
    507       1.42      maxv 	}
    508       1.26       dsl 
    509  1.44.14.1  pgoyette 	iov32 = NETBSD32PTR64(msg32->msg_iov);
    510  1.44.14.1  pgoyette 	error = netbsd32_to_iovecin(iov32, iov, msg->msg_iovlen);
    511        1.1       mrg 	if (error)
    512       1.42      maxv 		goto out;
    513  1.44.14.1  pgoyette 	msg->msg_iov = iov;
    514  1.44.14.1  pgoyette 	return 0;
    515  1.44.14.1  pgoyette out:
    516  1.44.14.1  pgoyette 	if (msg->msg_control)
    517  1.44.14.1  pgoyette 		m_free(msg->msg_control);
    518  1.44.14.1  pgoyette 	if (iov != aiov)
    519  1.44.14.1  pgoyette 		kmem_free(iov, iovsz);
    520  1.44.14.1  pgoyette 	return error;
    521  1.44.14.1  pgoyette }
    522  1.44.14.1  pgoyette 
    523  1.44.14.1  pgoyette int
    524  1.44.14.1  pgoyette netbsd32_sendmsg(struct lwp *l, const struct netbsd32_sendmsg_args *uap,
    525  1.44.14.1  pgoyette     register_t *retval)
    526  1.44.14.1  pgoyette {
    527  1.44.14.1  pgoyette 	/* {
    528  1.44.14.1  pgoyette 		syscallarg(int) s;
    529  1.44.14.1  pgoyette 		syscallarg(const netbsd32_msghdrp_t) msg;
    530  1.44.14.1  pgoyette 		syscallarg(int) flags;
    531  1.44.14.1  pgoyette 	} */
    532  1.44.14.1  pgoyette 	struct msghdr msg;
    533  1.44.14.1  pgoyette 	struct netbsd32_msghdr msg32;
    534  1.44.14.1  pgoyette 	struct iovec aiov[UIO_SMALLIOV];
    535  1.44.14.1  pgoyette 	int error;
    536  1.44.14.1  pgoyette 
    537  1.44.14.1  pgoyette 	error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
    538  1.44.14.1  pgoyette 	if (error)
    539  1.44.14.1  pgoyette 		return error;
    540  1.44.14.1  pgoyette 
    541  1.44.14.1  pgoyette 	if ((error = msg_send_copyin(l, &msg32, &msg, aiov)) != 0)
    542  1.44.14.1  pgoyette 		return error;
    543       1.26       dsl 
    544       1.44    martin 	error = do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
    545  1.44.14.1  pgoyette 	    retval);
    546       1.42      maxv 	/* msg.msg_control freed by do_sys_sendmsg() */
    547       1.42      maxv 
    548  1.44.14.1  pgoyette 	if (msg.msg_iov != aiov)
    549  1.44.14.1  pgoyette 		kmem_free(msg.msg_iov, msg.msg_iovlen * sizeof(struct iovec));
    550  1.44.14.1  pgoyette 	return error;
    551  1.44.14.1  pgoyette }
    552       1.42      maxv 
    553  1.44.14.1  pgoyette int
    554  1.44.14.1  pgoyette netbsd32_sendmmsg(struct lwp *l, const struct netbsd32_sendmmsg_args *uap,
    555  1.44.14.1  pgoyette     register_t *retval)
    556  1.44.14.1  pgoyette {
    557  1.44.14.1  pgoyette 	/* {
    558  1.44.14.1  pgoyette 		syscallarg(int)			s;
    559  1.44.14.1  pgoyette 		syscallarg(const netbsd32_mmsghdr_t)	mmsg;
    560  1.44.14.1  pgoyette 		syscallarg(unsigned int)	vlen;
    561  1.44.14.1  pgoyette 		syscallarg(unsigned int)	flags;
    562  1.44.14.1  pgoyette 	} */
    563  1.44.14.1  pgoyette 	struct mmsghdr mmsg;
    564  1.44.14.1  pgoyette 	struct netbsd32_mmsghdr mmsg32, *mmsg32p = SCARG_P32(uap, mmsg);
    565  1.44.14.1  pgoyette 	struct netbsd32_msghdr *msg32 = &mmsg32.msg_hdr;
    566  1.44.14.1  pgoyette 	struct socket *so;
    567  1.44.14.1  pgoyette 	file_t *fp;
    568  1.44.14.1  pgoyette 	struct msghdr *msg = &mmsg.msg_hdr;
    569  1.44.14.1  pgoyette 	int error, s;
    570  1.44.14.1  pgoyette 	unsigned int vlen, flags, dg;
    571  1.44.14.1  pgoyette 	struct iovec aiov[UIO_SMALLIOV];
    572  1.44.14.1  pgoyette 
    573  1.44.14.1  pgoyette 	s = SCARG(uap, s);
    574  1.44.14.1  pgoyette 	if ((error = fd_getsock1(s, &so, &fp)) != 0)
    575  1.44.14.1  pgoyette 		return error;
    576  1.44.14.1  pgoyette 
    577  1.44.14.1  pgoyette 	vlen = SCARG(uap, vlen);
    578  1.44.14.1  pgoyette 	if (vlen > 1024)
    579  1.44.14.1  pgoyette 		vlen = 1024;
    580  1.44.14.1  pgoyette 
    581  1.44.14.1  pgoyette 	flags = SCARG(uap, flags) & MSG_USERFLAGS;
    582  1.44.14.1  pgoyette 
    583  1.44.14.1  pgoyette 	for (dg = 0; dg < vlen;) {
    584  1.44.14.1  pgoyette 		error = copyin(mmsg32p + dg, &mmsg32, sizeof(mmsg32));
    585  1.44.14.1  pgoyette 		if (error)
    586  1.44.14.1  pgoyette 			break;
    587  1.44.14.1  pgoyette 		if ((error = msg_send_copyin(l, msg32, msg, aiov)) != 0)
    588  1.44.14.1  pgoyette 			break;
    589  1.44.14.1  pgoyette 
    590  1.44.14.1  pgoyette 		msg->msg_flags = flags;
    591  1.44.14.1  pgoyette 
    592  1.44.14.1  pgoyette 		error = do_sys_sendmsg_so(l, s, so, fp, msg, flags, retval);
    593  1.44.14.1  pgoyette 		if (msg->msg_iov != aiov) {
    594  1.44.14.1  pgoyette 			kmem_free(msg->msg_iov,
    595  1.44.14.1  pgoyette 			    msg->msg_iovlen * sizeof(struct iovec));
    596  1.44.14.1  pgoyette 		}
    597  1.44.14.1  pgoyette 		if (error)
    598  1.44.14.1  pgoyette 			break;
    599  1.44.14.1  pgoyette 
    600  1.44.14.1  pgoyette 		ktrkuser("msghdr", msg, sizeof(*msg));
    601  1.44.14.1  pgoyette 		mmsg.msg_len = *retval;
    602  1.44.14.1  pgoyette 		netbsd32_from_mmsghdr(&mmsg32, &mmsg);
    603  1.44.14.1  pgoyette 		error = copyout(&mmsg32, mmsg32p + dg, sizeof(mmsg32));
    604  1.44.14.1  pgoyette 		if (error)
    605  1.44.14.1  pgoyette 			break;
    606  1.44.14.1  pgoyette 		dg++;
    607  1.44.14.1  pgoyette 	}
    608  1.44.14.1  pgoyette 
    609  1.44.14.1  pgoyette 	*retval = dg;
    610  1.44.14.1  pgoyette 
    611  1.44.14.1  pgoyette 	fd_putfile(s);
    612  1.44.14.1  pgoyette 
    613  1.44.14.1  pgoyette 	/*
    614  1.44.14.2  pgoyette 	 * If we succeeded at least once, return 0.
    615  1.44.14.1  pgoyette 	 */
    616  1.44.14.1  pgoyette 	if (dg)
    617  1.44.14.1  pgoyette 		return 0;
    618       1.42      maxv 	return error;
    619        1.1       mrg }
    620        1.1       mrg 
    621        1.1       mrg int
    622  1.44.14.1  pgoyette netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap,
    623  1.44.14.1  pgoyette     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.44.14.1  pgoyette 	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.44.14.1  pgoyette 	error = copyout_sockname(SCARG_P32(uap, from),
    651  1.44.14.1  pgoyette 	    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.44.14.1  pgoyette netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap,
    659  1.44.14.1  pgoyette     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.44.14.1  pgoyette 	    retval);
    682        1.1       mrg }
    683