int sys_recvfrom(struct lwp *l, const struct sys_recvfrom_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(void *) buf; syscallarg(size_t) len; syscallarg(int) flags; syscallarg(struct sockaddr *) from; syscallarg(unsigned int *) fromlenaddr; } */ struct msghdr msg; struct iovec aiov; int error; struct mbuf *from; msg.msg_name = NULL; msg.msg_iov = &aiov; msg.msg_iovlen = 1; aiov.iov_base = SCARG(uap, buf); aiov.iov_len = SCARG(uap, len); msg.msg_control = NULL; msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval); if (error != 0) return error; error = copyout_sockname(SCARG(uap, from), SCARG(uap, fromlenaddr), MSG_LENUSRSPACE, from); if (from != NULL) m_free(from); return error; }
int sys_recvmsg(struct lwp *l, const struct sys_recvmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(struct msghdr *) msg; syscallarg(int) flags; } */ struct msghdr msg; int error; struct mbuf *from, *control; error = copyin(SCARG(uap, msg), &msg, sizeof(msg)); if (error) return error; msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, msg.msg_control != NULL ? &control : NULL, retval); if (error != 0) return error; if (msg.msg_control != NULL) error = copyout_msg_control(l, &msg, control); if (error == 0) error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0, from); if (from != NULL) m_free(from); if (error == 0) { ktrkuser("msghdr", &msg, sizeof msg); error = copyout(&msg, SCARG(uap, msg), sizeof(msg)); } return error; }
/* * This is a brutal clone of compat_43_sys_recvmsg(). */ int compat_43_netbsd32_orecvmsg(struct lwp *l, const struct compat_43_netbsd32_orecvmsg_args *uap, register_t *retval) { /* { syscallarg(int) s; syscallarg(netbsd32_omsghdrp_t) msg; syscallarg(int) flags; } */ struct netbsd32_omsghdr omsg; struct msghdr msg; struct mbuf *from, *control; struct iovec *iov, aiov[UIO_SMALLIOV]; int error; error = copyin(SCARG_P32(uap, msg), &omsg, sizeof (struct omsghdr)); if (error) return (error); if (NETBSD32PTR64(omsg.msg_accrights) == NULL) omsg.msg_accrightslen = 0; /* it was this way in 4.4BSD */ if (omsg.msg_accrightslen > MLEN) return EINVAL; iov = netbsd32_get_iov(NETBSD32PTR64(omsg.msg_iov), omsg.msg_iovlen, aiov, __arraycount(aiov)); if (iov == NULL) return EFAULT; msg.msg_name = NETBSD32PTR64(omsg.msg_name); msg.msg_namelen = omsg.msg_namelen; msg.msg_iovlen = omsg.msg_iovlen; msg.msg_iov = iov; msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS; error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NETBSD32PTR64(omsg.msg_accrights) != NULL ? &control : NULL, retval); if (error != 0) return error; /* * If there is any control information and it's SCM_RIGHTS, * pass it back to the program. * XXX: maybe there can be more than one chunk of control data? */ if (NETBSD32PTR64(omsg.msg_accrights) != NULL && control != NULL) { struct cmsghdr *cmsg = mtod(control, void *); if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS && cmsg->cmsg_len < omsg.msg_accrightslen && copyout(CMSG_DATA(cmsg), NETBSD32PTR64(omsg.msg_accrights), cmsg->cmsg_len) == 0) { omsg.msg_accrightslen = cmsg->cmsg_len; free_control_mbuf(l, control, control->m_next); } else { omsg.msg_accrightslen = 0; free_control_mbuf(l, control, control); } } else