+ u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
+ if (u.u_error)
+ return;
+ if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
+ u.u_error = EMSGSIZE;
+ return;
+ }
+ msg.msg_flags = uap->flags;
+ u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
+ (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
+ if (u.u_error)
+ return;
+ uiov = msg.msg_iov;
+ msg.msg_iov = aiov;
+ if (msg.msg_accrights)
+ if (useracc((caddr_t)msg.msg_accrights,
+ (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ if (msg.msg_control)
+ if (useracc((caddr_t)msg.msg_control,
+ (unsigned)msg.msg_controllen, B_WRITE) == 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
+ msg.msg_iov = uiov;
+ u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
+}
+
+recvit(s, mp, namelenp, rightslenp, compat_43)
+ int s, compat_43;
+ register struct msghdr *mp;
+ caddr_t namelenp, rightslenp;
+{
+ register struct file *fp;
+ struct uio auio;
+ register struct iovec *iov;
+ register int i;
+ int len;
+ struct mbuf *from = 0, *rights = 0, *control = 0;
+
+ fp = getsock(s);
+ if (fp == 0)
+ return;
+ auio.uio_iov = mp->msg_iov;
+ auio.uio_iovcnt = mp->msg_iovlen;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_offset = 0; /* XXX */
+ auio.uio_resid = 0;
+ iov = mp->msg_iov;
+ for (i = 0; i < mp->msg_iovlen; i++, iov++) {
+ if (iov->iov_len < 0) {
+ u.u_error = EINVAL;
+ return;
+ }
+ if (iov->iov_len == 0)
+ continue;
+ if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
+ u.u_error = EFAULT;
+ return;
+ }
+ auio.uio_resid += iov->iov_len;
+ }
+ len = auio.uio_resid;
+ if (setjmp(&u.u_qsave)) { /* XXX */
+ if (auio.uio_resid == len) {
+ if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+ u.u_error = EINTR;
+ else
+ u.u_eosys = RESTARTSYS;
+ }
+ } else
+ u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
+ &mp->msg_flags, &rights, &control);
+ u.u_r.r_val1 = len - auio.uio_resid;
+ if (mp->msg_name) {
+ len = mp->msg_namelen;
+ if (len <= 0 || from == 0)
+ len = 0;
+ else {
+#ifdef COMPAT_43
+ if (compat_43)
+ mtod(from, struct osockaddr *)->sa_family =
+ mtod(from, struct sockaddr *)->sa_family;
+#endif
+ if (len > from->m_len) /* ??? */
+ len = from->m_len;
+ (void) copyout(mtod(from, caddr_t),
+ (caddr_t)mp->msg_name, (unsigned)len);
+ }
+ mp->msg_namelen = len;
+ if (namelenp)
+ (void) copyout((caddr_t)&len, namelenp, sizeof (int));
+ }
+ if (mp->msg_accrights) {
+ len = mp->msg_accrightslen;
+ if (len <= 0 || rights == 0)
+ len = 0;
+ else {
+ if (len > rights->m_len)
+ len = rights->m_len;
+ (void) copyout((caddr_t)mtod(rights, caddr_t),
+ (caddr_t)mp->msg_accrights, (unsigned)len);
+ }
+ mp->msg_accrightslen = len;
+ if (rightslenp)
+ (void) copyout((caddr_t)&len, rightslenp, sizeof (int));
+ }
+ if (mp->msg_control) {
+ len = mp->msg_controllen;
+ if (len <= 0 || control == 0)
+ len = 0;
+ else {
+ if (len >= control->m_len)
+ len = control->m_len;
+ else
+ mp->msg_flags |= MSG_CTRUNC;
+ (void) copyout((caddr_t)mtod(control, caddr_t),
+ (caddr_t)mp->msg_control, (unsigned)len);
+ }
+ mp->msg_controllen = len;
+ }
+ if (rights)
+ m_freem(rights);
+ if (from)
+ m_freem(from);
+ if (control)
+ m_freem(control);