1433d6423SLionel Sambuc #include <sys/cdefs.h> 2433d6423SLionel Sambuc #include "namespace.h" 3*c38dbb97SDavid van Moolenbroek #include <lib.h> 4433d6423SLionel Sambuc 5433d6423SLionel Sambuc #include <errno.h> 6433d6423SLionel Sambuc #include <stdio.h> 7433d6423SLionel Sambuc #include <stdlib.h> 8433d6423SLionel Sambuc #include <string.h> 9433d6423SLionel Sambuc #include <sys/ioctl.h> 10433d6423SLionel Sambuc #include <sys/ioc_net.h> 11433d6423SLionel Sambuc #include <sys/socket.h> 12433d6423SLionel Sambuc #include <sys/types.h> 13433d6423SLionel Sambuc #include <sys/un.h> 14433d6423SLionel Sambuc 15433d6423SLionel Sambuc #define DEBUG 0 16433d6423SLionel Sambuc 17433d6423SLionel Sambuc static ssize_t _uds_recvmsg_conn(int sock, struct msghdr *msg, int flags); 18433d6423SLionel Sambuc static ssize_t _uds_recvmsg_dgram(int sock, struct msghdr *msg, int flags); 19433d6423SLionel Sambuc 20*c38dbb97SDavid van Moolenbroek /* 21*c38dbb97SDavid van Moolenbroek * Receive a message from a socket using a message structure. 22*c38dbb97SDavid van Moolenbroek */ 23*c38dbb97SDavid van Moolenbroek static ssize_t 24*c38dbb97SDavid van Moolenbroek __recvmsg(int fd, struct msghdr * msg, int flags) 25*c38dbb97SDavid van Moolenbroek { 26*c38dbb97SDavid van Moolenbroek struct iovec iov; 27*c38dbb97SDavid van Moolenbroek struct msghdr msg2, *msgp; 28*c38dbb97SDavid van Moolenbroek char *ptr; 29*c38dbb97SDavid van Moolenbroek message m; 30*c38dbb97SDavid van Moolenbroek ssize_t r; 31*c38dbb97SDavid van Moolenbroek 32*c38dbb97SDavid van Moolenbroek /* 33*c38dbb97SDavid van Moolenbroek * Currently, MINIX3 does not support vector I/O operations. Like in 34*c38dbb97SDavid van Moolenbroek * the readv and writev implementations, we coalesce the data vector 35*c38dbb97SDavid van Moolenbroek * into a single buffer used for I/O. For future ABI compatibility, we 36*c38dbb97SDavid van Moolenbroek * then supply this buffer as a single vector element. This involves 37*c38dbb97SDavid van Moolenbroek * supplying a modified copy of the message header, as well as extra 38*c38dbb97SDavid van Moolenbroek * pre-checks. Once true vector I/O support has been added, the checks 39*c38dbb97SDavid van Moolenbroek * and vector I/O coalescing can be removed from here, leaving just the 40*c38dbb97SDavid van Moolenbroek * system call. Nothing will change at the system call ABI level. 41*c38dbb97SDavid van Moolenbroek */ 42*c38dbb97SDavid van Moolenbroek if (msg == NULL || (msg->msg_iovlen > 1 && msg->msg_iov == NULL)) { 43*c38dbb97SDavid van Moolenbroek errno = EFAULT; 44*c38dbb97SDavid van Moolenbroek return -1; 45*c38dbb97SDavid van Moolenbroek } 46*c38dbb97SDavid van Moolenbroek 47*c38dbb97SDavid van Moolenbroek if (msg->msg_iovlen < 0 || msg->msg_iovlen > IOV_MAX) { 48*c38dbb97SDavid van Moolenbroek errno = EMSGSIZE; /* different from readv/writev */ 49*c38dbb97SDavid van Moolenbroek return -1; 50*c38dbb97SDavid van Moolenbroek } 51*c38dbb97SDavid van Moolenbroek 52*c38dbb97SDavid van Moolenbroek if (msg->msg_iovlen > 1) { 53*c38dbb97SDavid van Moolenbroek if ((r = _vectorio_setup(msg->msg_iov, msg->msg_iovlen, &ptr, 54*c38dbb97SDavid van Moolenbroek _VECTORIO_READ)) < 0) 55*c38dbb97SDavid van Moolenbroek return -1; 56*c38dbb97SDavid van Moolenbroek 57*c38dbb97SDavid van Moolenbroek iov.iov_base = ptr; 58*c38dbb97SDavid van Moolenbroek iov.iov_len = r; 59*c38dbb97SDavid van Moolenbroek 60*c38dbb97SDavid van Moolenbroek memcpy(&msg2, msg, sizeof(msg2)); 61*c38dbb97SDavid van Moolenbroek msg2.msg_iov = &iov; 62*c38dbb97SDavid van Moolenbroek msg2.msg_iovlen = 1; 63*c38dbb97SDavid van Moolenbroek msgp = &msg2; 64*c38dbb97SDavid van Moolenbroek } else 65*c38dbb97SDavid van Moolenbroek msgp = msg; 66*c38dbb97SDavid van Moolenbroek 67*c38dbb97SDavid van Moolenbroek /* Issue the actual system call. */ 68*c38dbb97SDavid van Moolenbroek memset(&m, 0, sizeof(m)); 69*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockmsg.fd = fd; 70*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockmsg.msgbuf = (vir_bytes)msgp; 71*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockmsg.flags = flags; 72*c38dbb97SDavid van Moolenbroek 73*c38dbb97SDavid van Moolenbroek r = _syscall(VFS_PROC_NR, VFS_RECVMSG, &m); 74*c38dbb97SDavid van Moolenbroek 75*c38dbb97SDavid van Moolenbroek /* If we coalesced the vector, clean up and copy back the results. */ 76*c38dbb97SDavid van Moolenbroek if (msgp != msg) { 77*c38dbb97SDavid van Moolenbroek _vectorio_cleanup(msg->msg_iov, msg->msg_iovlen, ptr, r, 78*c38dbb97SDavid van Moolenbroek _VECTORIO_READ); 79*c38dbb97SDavid van Moolenbroek 80*c38dbb97SDavid van Moolenbroek if (r >= 0) 81*c38dbb97SDavid van Moolenbroek memcpy(msg, &msg2, sizeof(msg2)); 82*c38dbb97SDavid van Moolenbroek } 83*c38dbb97SDavid van Moolenbroek 84*c38dbb97SDavid van Moolenbroek return r; 85*c38dbb97SDavid van Moolenbroek } 86*c38dbb97SDavid van Moolenbroek 87433d6423SLionel Sambuc ssize_t recvmsg(int sock, struct msghdr *msg, int flags) 88433d6423SLionel Sambuc { 89433d6423SLionel Sambuc int r; 90433d6423SLionel Sambuc int uds_sotype; 91433d6423SLionel Sambuc 92*c38dbb97SDavid van Moolenbroek r = __recvmsg(sock, msg, flags); 93*c38dbb97SDavid van Moolenbroek if (r != -1 || errno != ENOTSOCK) 94*c38dbb97SDavid van Moolenbroek return r; 95*c38dbb97SDavid van Moolenbroek 96433d6423SLionel Sambuc if (msg == NULL) { 97433d6423SLionel Sambuc errno= EFAULT; 98433d6423SLionel Sambuc return -1; 99433d6423SLionel Sambuc } 100433d6423SLionel Sambuc 101433d6423SLionel Sambuc r= ioctl(sock, NWIOGUDSSOTYPE, &uds_sotype); 102433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) { 103433d6423SLionel Sambuc if (r == -1) { 104433d6423SLionel Sambuc return r; 105433d6423SLionel Sambuc } 106433d6423SLionel Sambuc 107433d6423SLionel Sambuc if (uds_sotype == SOCK_DGRAM) { 108433d6423SLionel Sambuc return _uds_recvmsg_dgram(sock, msg, flags); 109433d6423SLionel Sambuc } else { 110433d6423SLionel Sambuc return _uds_recvmsg_conn(sock, msg, flags); 111433d6423SLionel Sambuc } 112433d6423SLionel Sambuc } 113433d6423SLionel Sambuc 114*c38dbb97SDavid van Moolenbroek errno = ENOTSOCK; 115433d6423SLionel Sambuc return -1; 116433d6423SLionel Sambuc } 117433d6423SLionel Sambuc 118433d6423SLionel Sambuc static ssize_t _uds_recvmsg_conn(int sock, struct msghdr *msg, int flags) 119433d6423SLionel Sambuc { 120433d6423SLionel Sambuc int r, rc; 121433d6423SLionel Sambuc 122433d6423SLionel Sambuc if (flags != 0) { 123433d6423SLionel Sambuc #if DEBUG 124433d6423SLionel Sambuc fprintf(stderr, "recvmsg(uds): flags not implemented\n"); 125433d6423SLionel Sambuc #endif 126433d6423SLionel Sambuc errno= ENOSYS; 127433d6423SLionel Sambuc return -1; 128433d6423SLionel Sambuc } 129433d6423SLionel Sambuc 130433d6423SLionel Sambuc r= readv(sock, msg->msg_iov, msg->msg_iovlen); 131433d6423SLionel Sambuc 132433d6423SLionel Sambuc if (r >= 0 && msg->msg_name && msg->msg_namelen > 0) { 133433d6423SLionel Sambuc getpeername(sock, msg->msg_name, &msg->msg_namelen); 134433d6423SLionel Sambuc } 135433d6423SLionel Sambuc 136433d6423SLionel Sambuc /* get control data */ 137433d6423SLionel Sambuc if (r >= 0 && msg->msg_control && msg->msg_controllen > 0) { 138433d6423SLionel Sambuc struct msg_control msg_ctrl; 139433d6423SLionel Sambuc 140433d6423SLionel Sambuc memset(&msg_ctrl, '\0', sizeof(struct msg_control)); 141433d6423SLionel Sambuc msg_ctrl.msg_controllen = msg->msg_controllen; 142433d6423SLionel Sambuc rc = ioctl(sock, NWIOGUDSCTRL, &msg_ctrl); 143433d6423SLionel Sambuc if (rc == -1) { 144433d6423SLionel Sambuc return rc; 145433d6423SLionel Sambuc } 146433d6423SLionel Sambuc 147433d6423SLionel Sambuc if (msg_ctrl.msg_controllen <= msg->msg_controllen) { 148433d6423SLionel Sambuc memcpy(msg->msg_control, msg_ctrl.msg_control, 149433d6423SLionel Sambuc msg_ctrl.msg_controllen); 150433d6423SLionel Sambuc msg->msg_controllen = msg_ctrl.msg_controllen; 151433d6423SLionel Sambuc } 152433d6423SLionel Sambuc } 153433d6423SLionel Sambuc 154433d6423SLionel Sambuc msg->msg_flags = 0; 155433d6423SLionel Sambuc 156433d6423SLionel Sambuc return r; 157433d6423SLionel Sambuc } 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc static ssize_t _uds_recvmsg_dgram(int sock, struct msghdr *msg, int flags) 160433d6423SLionel Sambuc { 161433d6423SLionel Sambuc int r, rc; 162433d6423SLionel Sambuc 163433d6423SLionel Sambuc if (flags != 0) { 164433d6423SLionel Sambuc #if DEBUG 165433d6423SLionel Sambuc fprintf(stderr, "recvmsg(uds): flags not implemented\n"); 166433d6423SLionel Sambuc #endif 167433d6423SLionel Sambuc errno= ENOSYS; 168433d6423SLionel Sambuc return -1; 169433d6423SLionel Sambuc } 170433d6423SLionel Sambuc 171433d6423SLionel Sambuc r= readv(sock, msg->msg_iov, msg->msg_iovlen); 172433d6423SLionel Sambuc 173433d6423SLionel Sambuc if (r >= 0 && msg->msg_name && 174433d6423SLionel Sambuc msg->msg_namelen >= sizeof(struct sockaddr_un)) 175433d6423SLionel Sambuc { 176433d6423SLionel Sambuc rc= ioctl(sock, NWIOGUDSFADDR, msg->msg_name); 177433d6423SLionel Sambuc if (rc == -1) { 178433d6423SLionel Sambuc return rc; 179433d6423SLionel Sambuc } 180433d6423SLionel Sambuc msg->msg_namelen= sizeof(struct sockaddr_un); 181433d6423SLionel Sambuc } 182433d6423SLionel Sambuc 183433d6423SLionel Sambuc /* get control data */ 184433d6423SLionel Sambuc if (r >= 0 && msg->msg_control && msg->msg_controllen > 0) { 185433d6423SLionel Sambuc struct msg_control msg_ctrl; 186433d6423SLionel Sambuc 187433d6423SLionel Sambuc memset(&msg_ctrl, '\0', sizeof(struct msg_control)); 188433d6423SLionel Sambuc msg_ctrl.msg_controllen = msg->msg_controllen; 189433d6423SLionel Sambuc rc = ioctl(sock, NWIOGUDSCTRL, &msg_ctrl); 190433d6423SLionel Sambuc if (rc == -1) { 191433d6423SLionel Sambuc return rc; 192433d6423SLionel Sambuc } 193433d6423SLionel Sambuc 194433d6423SLionel Sambuc if (msg_ctrl.msg_controllen <= msg->msg_controllen) { 195433d6423SLionel Sambuc memcpy(msg->msg_control, msg_ctrl.msg_control, 196433d6423SLionel Sambuc msg_ctrl.msg_controllen); 197433d6423SLionel Sambuc msg->msg_controllen = msg_ctrl.msg_controllen; 198433d6423SLionel Sambuc } 199433d6423SLionel Sambuc } 200433d6423SLionel Sambuc 201433d6423SLionel Sambuc msg->msg_flags = 0; 202433d6423SLionel Sambuc 203433d6423SLionel Sambuc return r; 204433d6423SLionel Sambuc } 205