Remove building with NOCRYPTO option
[minix.git] / minix / lib / libc / sys / sendmsg.c
blob846d67dc6484eec58063e3097bc09f9e42b2498b
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/ioctl.h>
9 #include <sys/ioc_net.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <sys/un.h>
14 #define DEBUG 0
16 static ssize_t _uds_sendmsg_conn(int sock, const struct msghdr *msg,
17 int flags);
18 static ssize_t _uds_sendmsg_dgram(int sock, const struct msghdr *msg,
19 int flags);
22 * Send a message on a socket using a message structure.
24 static ssize_t
25 __sendmsg(int fd, const struct msghdr * msg, int flags)
27 struct iovec iov;
28 const struct msghdr *msgp;
29 struct msghdr msg2;
30 char *ptr;
31 message m;
32 ssize_t r;
35 * Currently, MINIX3 does not support vector I/O operations. Like in
36 * the readv and writev implementations, we coalesce the data vector
37 * into a single buffer used for I/O. For future ABI compatibility, we
38 * then supply this buffer as a single vector element. This involves
39 * supplying a modified copy of the message header, as well as extra
40 * pre-checks. Once true vector I/O support has been added, the checks
41 * and vector I/O coalescing can be removed from here, leaving just the
42 * system call. Nothing will change at the system call ABI level.
44 if (msg == NULL || (msg->msg_iovlen > 1 && msg->msg_iov == NULL)) {
45 errno = EFAULT;
46 return -1;
49 if (msg->msg_iovlen < 0 || msg->msg_iovlen > IOV_MAX) {
50 errno = EMSGSIZE; /* different from readv/writev */
51 return -1;
54 if (msg->msg_iovlen > 1) {
55 if ((r = _vectorio_setup(msg->msg_iov, msg->msg_iovlen, &ptr,
56 _VECTORIO_WRITE)) < 0)
57 return -1;
59 iov.iov_base = ptr;
60 iov.iov_len = r;
62 memcpy(&msg2, msg, sizeof(msg2));
63 msg2.msg_iov = &iov;
64 msg2.msg_iovlen = 1;
65 msgp = &msg2;
66 } else
67 msgp = msg;
69 memset(&m, 0, sizeof(m));
70 m.m_lc_vfs_sockmsg.fd = fd;
71 m.m_lc_vfs_sockmsg.msgbuf = (vir_bytes)msgp;
72 m.m_lc_vfs_sockmsg.flags = flags;
74 r = _syscall(VFS_PROC_NR, VFS_SENDMSG, &m);
76 /* If we coalesced the vector, clean up. */
77 if (msgp != msg) {
78 _vectorio_cleanup(msg->msg_iov, msg->msg_iovlen, ptr, r,
79 _VECTORIO_WRITE);
82 return r;
85 ssize_t sendmsg(int sock, const struct msghdr *msg, int flags)
87 int r;
88 int uds_sotype;
90 r = __sendmsg(sock, msg, flags);
91 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
92 return r;
94 if (msg == NULL) {
95 errno= EFAULT;
96 return -1;
99 /* For old socket driver implementations, this flag is the default. */
100 flags &= ~MSG_NOSIGNAL;
102 r= ioctl(sock, NWIOGUDSSOTYPE, &uds_sotype);
103 if (r != -1 || errno != ENOTTY) {
104 if (r == -1) {
105 return r;
108 if (uds_sotype == SOCK_DGRAM) {
109 return _uds_sendmsg_dgram(sock, msg, flags);
110 } else {
111 return _uds_sendmsg_conn(sock, msg, flags);
116 errno = ENOTSOCK;
117 return -1;
120 static ssize_t _uds_sendmsg_conn(int sock, const struct msghdr *msg,
121 int flags)
123 struct msg_control msg_ctrl;
124 int r;
126 if (flags != 0) {
127 #if DEBUG
128 fprintf(stderr, "sendmsg(uds): flags not implemented\n");
129 #endif
130 errno= ENOSYS;
131 return -1;
135 /* grab the control data */
136 memset(&msg_ctrl, '\0', sizeof(struct msg_control));
137 if (msg->msg_controllen > MSG_CONTROL_MAX) {
138 errno = ENOMEM;
139 return -1;
140 } else if (msg->msg_controllen > 0) {
141 memcpy(&msg_ctrl.msg_control, msg->msg_control,
142 msg->msg_controllen);
144 msg_ctrl.msg_controllen = msg->msg_controllen;
146 /* send the control data to PFS */
147 r= ioctl(sock, NWIOSUDSCTRL, (void *) &msg_ctrl);
148 if (r == -1) {
149 return r;
152 /* Silently ignore destination, if given. */
154 return writev(sock, msg->msg_iov, msg->msg_iovlen);
157 static ssize_t _uds_sendmsg_dgram(int sock, const struct msghdr *msg,
158 int flags)
160 struct msg_control msg_ctrl;
161 struct sockaddr_un *dest_addr;
162 int r;
164 if (flags != 0) {
165 #if DEBUG
166 fprintf(stderr, "sendmsg(uds): flags not implemented\n");
167 #endif
168 errno= ENOSYS;
169 return -1;
173 dest_addr = msg->msg_name;
174 if (dest_addr == NULL) {
175 errno= EFAULT;
176 return -1;
179 /* set the target address */
180 r= ioctl(sock, NWIOSUDSTADDR, (void *) dest_addr);
181 if (r == -1) {
182 return r;
185 /* grab the control data */
186 memset(&msg_ctrl, '\0', sizeof(struct msg_control));
187 if (msg->msg_controllen > MSG_CONTROL_MAX) {
188 errno = ENOMEM;
189 return -1;
190 } else if (msg->msg_controllen > 0) {
191 memcpy(&msg_ctrl.msg_control, msg->msg_control,
192 msg->msg_controllen);
194 msg_ctrl.msg_controllen = msg->msg_controllen;
196 /* send the control data to PFS */
197 r= ioctl(sock, NWIOSUDSCTRL, (void *) &msg_ctrl);
198 if (r == -1) {
199 return r;
202 /* do the send */
203 return writev(sock, msg->msg_iov, msg->msg_iovlen);