10 #include <sys/ioc_net.h>
11 #include <sys/socket.h>
12 #include <sys/types.h>
17 static ssize_t
_uds_recvmsg_conn(int sock
, struct msghdr
*msg
, int flags
);
18 static ssize_t
_uds_recvmsg_dgram(int sock
, struct msghdr
*msg
, int flags
);
21 * Receive a message from a socket using a message structure.
24 __recvmsg(int fd
, struct msghdr
* msg
, int flags
)
27 struct msghdr msg2
, *msgp
;
33 * Currently, MINIX3 does not support vector I/O operations. Like in
34 * the readv and writev implementations, we coalesce the data vector
35 * into a single buffer used for I/O. For future ABI compatibility, we
36 * then supply this buffer as a single vector element. This involves
37 * supplying a modified copy of the message header, as well as extra
38 * pre-checks. Once true vector I/O support has been added, the checks
39 * and vector I/O coalescing can be removed from here, leaving just the
40 * system call. Nothing will change at the system call ABI level.
42 if (msg
== NULL
|| (msg
->msg_iovlen
> 1 && msg
->msg_iov
== NULL
)) {
47 if (msg
->msg_iovlen
< 0 || msg
->msg_iovlen
> IOV_MAX
) {
48 errno
= EMSGSIZE
; /* different from readv/writev */
52 if (msg
->msg_iovlen
> 1) {
53 if ((r
= _vectorio_setup(msg
->msg_iov
, msg
->msg_iovlen
, &ptr
,
60 memcpy(&msg2
, msg
, sizeof(msg2
));
67 /* Issue the actual system call. */
68 memset(&m
, 0, sizeof(m
));
69 m
.m_lc_vfs_sockmsg
.fd
= fd
;
70 m
.m_lc_vfs_sockmsg
.msgbuf
= (vir_bytes
)msgp
;
71 m
.m_lc_vfs_sockmsg
.flags
= flags
;
73 r
= _syscall(VFS_PROC_NR
, VFS_RECVMSG
, &m
);
75 /* If we coalesced the vector, clean up and copy back the results. */
77 _vectorio_cleanup(msg
->msg_iov
, msg
->msg_iovlen
, ptr
, r
,
81 memcpy(msg
, &msg2
, sizeof(msg2
));
87 ssize_t
recvmsg(int sock
, struct msghdr
*msg
, int flags
)
92 r
= __recvmsg(sock
, msg
, flags
);
93 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
101 r
= ioctl(sock
, NWIOGUDSSOTYPE
, &uds_sotype
);
102 if (r
!= -1 || errno
!= ENOTTY
) {
107 if (uds_sotype
== SOCK_DGRAM
) {
108 return _uds_recvmsg_dgram(sock
, msg
, flags
);
110 return _uds_recvmsg_conn(sock
, msg
, flags
);
118 static ssize_t
_uds_recvmsg_conn(int sock
, struct msghdr
*msg
, int flags
)
124 fprintf(stderr
, "recvmsg(uds): flags not implemented\n");
130 r
= readv(sock
, msg
->msg_iov
, msg
->msg_iovlen
);
132 if (r
>= 0 && msg
->msg_name
&& msg
->msg_namelen
> 0) {
133 getpeername(sock
, msg
->msg_name
, &msg
->msg_namelen
);
136 /* get control data */
137 if (r
>= 0 && msg
->msg_control
&& msg
->msg_controllen
> 0) {
138 struct msg_control msg_ctrl
;
140 memset(&msg_ctrl
, '\0', sizeof(struct msg_control
));
141 msg_ctrl
.msg_controllen
= msg
->msg_controllen
;
142 rc
= ioctl(sock
, NWIOGUDSCTRL
, &msg_ctrl
);
147 if (msg_ctrl
.msg_controllen
<= msg
->msg_controllen
) {
148 memcpy(msg
->msg_control
, msg_ctrl
.msg_control
,
149 msg_ctrl
.msg_controllen
);
150 msg
->msg_controllen
= msg_ctrl
.msg_controllen
;
159 static ssize_t
_uds_recvmsg_dgram(int sock
, struct msghdr
*msg
, int flags
)
165 fprintf(stderr
, "recvmsg(uds): flags not implemented\n");
171 r
= readv(sock
, msg
->msg_iov
, msg
->msg_iovlen
);
173 if (r
>= 0 && msg
->msg_name
&&
174 msg
->msg_namelen
>= sizeof(struct sockaddr_un
))
176 rc
= ioctl(sock
, NWIOGUDSFADDR
, msg
->msg_name
);
180 msg
->msg_namelen
= sizeof(struct sockaddr_un
);
183 /* get control data */
184 if (r
>= 0 && msg
->msg_control
&& msg
->msg_controllen
> 0) {
185 struct msg_control msg_ctrl
;
187 memset(&msg_ctrl
, '\0', sizeof(struct msg_control
));
188 msg_ctrl
.msg_controllen
= msg
->msg_controllen
;
189 rc
= ioctl(sock
, NWIOGUDSCTRL
, &msg_ctrl
);
194 if (msg_ctrl
.msg_controllen
<= msg
->msg_controllen
) {
195 memcpy(msg
->msg_control
, msg_ctrl
.msg_control
,
196 msg_ctrl
.msg_controllen
);
197 msg
->msg_controllen
= msg_ctrl
.msg_controllen
;