int ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *sent, struct cred *cr) { int error; ssize_t len; int i; struct uio auio; /* All Solaris components should pass a cred for this operation. */ ASSERT(cr != NULL); if (!KSOCKET_VALID(ks)) { if (sent != NULL) *sent = 0; return (ENOTSOCK); } bzero(&auio, sizeof (struct uio)); auio.uio_loffset = 0; auio.uio_iov = msg->msg_iov; auio.uio_iovcnt = msg->msg_iovlen; if (flags & MSG_USERSPACE) auio.uio_segflg = UIO_USERSPACE; else auio.uio_segflg = UIO_SYSSPACE; auio.uio_extflg = UIO_COPY_DEFAULT; auio.uio_limit = 0; auio.uio_fmode = KSOCKET_FMODE(ks); len = 0; for (i = 0; i < msg->msg_iovlen; i++) { ssize_t iovlen; iovlen = (msg->msg_iov)[i].iov_len; len += iovlen; if (len < 0 || iovlen < 0) return (EINVAL); } auio.uio_resid = len; msg->msg_flags = flags | MSG_EOR; error = socket_sendmsg(KSTOSO(ks), msg, &auio, cr); if (error != 0) { if (sent != NULL) *sent = 0; return (error); } if (sent != NULL) *sent = len - auio.uio_resid; return (0); }
int ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags, struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr) { int error; struct nmsghdr msghdr; struct uio auio; struct iovec iov; /* All Solaris components should pass a cred for this operation. */ ASSERT(cr != NULL); if (!KSOCKET_VALID(ks)) { if (sent != NULL) *sent = 0; return (ENOTSOCK); } iov.iov_base = msg; iov.iov_len = msglen; bzero(&auio, sizeof (struct uio)); auio.uio_loffset = 0; auio.uio_iov = &iov; auio.uio_iovcnt = 1; auio.uio_resid = msglen; if (flags & MSG_USERSPACE) auio.uio_segflg = UIO_USERSPACE; else auio.uio_segflg = UIO_SYSSPACE; auio.uio_extflg = UIO_COPY_DEFAULT; auio.uio_limit = 0; auio.uio_fmode = KSOCKET_FMODE(ks); msghdr.msg_iov = &iov; msghdr.msg_iovlen = 1; msghdr.msg_name = (char *)name; msghdr.msg_namelen = namelen; msghdr.msg_control = NULL; msghdr.msg_controllen = 0; msghdr.msg_flags = flags | MSG_EOR; error = socket_sendmsg(KSTOSO(ks), &msghdr, &auio, cr); if (error != 0) { if (sent != NULL) *sent = 0; return (error); } if (sent != NULL) *sent = msglen - auio.uio_resid; return (0); }
DEFINE_SYSCALL(sendmsg, int, sockfd, const struct msghdr *, msg, int, flags) { log_info("sendmsg(%d, %p, %x)", sockfd, msg, flags); if (!mm_check_read_msghdr(msg)) return -L_EFAULT; struct file *f = vfs_get(sockfd); if (!f) return -L_EBADF; int r; if (!f->op_vtable->sendmsg) { log_error("sendmsg() not implemented."); r = -L_ENOTSOCK; } else r = socket_sendmsg(f, msg, flags); vfs_release(f); return r; }
/*ARGSUSED2*/ static int socket_vop_write(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *cr, caller_context_t *ct) { struct sonode *so = VTOSO(vp); struct nmsghdr lmsg; ASSERT(vp->v_type == VSOCK); bzero((void *)&lmsg, sizeof (lmsg)); if (!(so->so_mode & SM_BYTESTREAM)) { /* * If the socket is not byte stream set MSG_EOR */ lmsg.msg_flags = MSG_EOR; } return (socket_sendmsg(so, &lmsg, uiop, cr)); }