9 #include <sys/ioc_net.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
16 static ssize_t
_uds_sendmsg_conn(int sock
, const struct msghdr
*msg
,
18 static ssize_t
_uds_sendmsg_dgram(int sock
, const struct msghdr
*msg
,
22 * Send a message on a socket using a message structure.
25 __sendmsg(int fd
, const struct msghdr
* msg
, int flags
)
28 const struct msghdr
*msgp
;
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
)) {
49 if (msg
->msg_iovlen
< 0 || msg
->msg_iovlen
> IOV_MAX
) {
50 errno
= EMSGSIZE
; /* different from readv/writev */
54 if (msg
->msg_iovlen
> 1) {
55 if ((r
= _vectorio_setup(msg
->msg_iov
, msg
->msg_iovlen
, &ptr
,
56 _VECTORIO_WRITE
)) < 0)
62 memcpy(&msg2
, msg
, sizeof(msg2
));
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. */
78 _vectorio_cleanup(msg
->msg_iov
, msg
->msg_iovlen
, ptr
, r
,
85 ssize_t
sendmsg(int sock
, const struct msghdr
*msg
, int flags
)
90 r
= __sendmsg(sock
, msg
, flags
);
91 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
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
) {
108 if (uds_sotype
== SOCK_DGRAM
) {
109 return _uds_sendmsg_dgram(sock
, msg
, flags
);
111 return _uds_sendmsg_conn(sock
, msg
, flags
);
120 static ssize_t
_uds_sendmsg_conn(int sock
, const struct msghdr
*msg
,
123 struct msg_control msg_ctrl
;
128 fprintf(stderr
, "sendmsg(uds): flags not implemented\n");
135 /* grab the control data */
136 memset(&msg_ctrl
, '\0', sizeof(struct msg_control
));
137 if (msg
->msg_controllen
> MSG_CONTROL_MAX
) {
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
);
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
,
160 struct msg_control msg_ctrl
;
161 struct sockaddr_un
*dest_addr
;
166 fprintf(stderr
, "sendmsg(uds): flags not implemented\n");
173 dest_addr
= msg
->msg_name
;
174 if (dest_addr
== NULL
) {
179 /* set the target address */
180 r
= ioctl(sock
, NWIOSUDSTADDR
, (void *) dest_addr
);
185 /* grab the control data */
186 memset(&msg_ctrl
, '\0', sizeof(struct msg_control
));
187 if (msg
->msg_controllen
> MSG_CONTROL_MAX
) {
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
);
203 return writev(sock
, msg
->msg_iov
, msg
->msg_iovlen
);