xref: /minix3/minix/lib/libc/sys/recvmsg.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 
4 #include <errno.h>
5 #include <stdio.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>
13 
14 #define DEBUG 0
15 
16 static ssize_t _uds_recvmsg_conn(int sock, struct msghdr *msg, int flags);
17 static ssize_t _uds_recvmsg_dgram(int sock, struct msghdr *msg, int flags);
18 
19 ssize_t recvmsg(int sock, struct msghdr *msg, int flags)
20 {
21 	int r;
22 	int uds_sotype;
23 
24 	if (msg == NULL) {
25 		errno= EFAULT;
26 		return -1;
27 	}
28 
29 	r= ioctl(sock, NWIOGUDSSOTYPE, &uds_sotype);
30 	if (r != -1 || errno != ENOTTY) {
31 		if (r == -1) {
32 			return r;
33 		}
34 
35 		if (uds_sotype == SOCK_DGRAM) {
36 			return _uds_recvmsg_dgram(sock, msg, flags);
37 		} else {
38 			return _uds_recvmsg_conn(sock, msg, flags);
39 		}
40 	}
41 
42 #if DEBUG
43 	fprintf(stderr, "recvmsg: not implemented for fd %d\n", sock);
44 #endif
45 
46 	errno= ENOSYS;
47 	return -1;
48 }
49 
50 static ssize_t _uds_recvmsg_conn(int sock, struct msghdr *msg, int flags)
51 {
52 	int r, rc;
53 
54 	if (flags != 0) {
55 #if DEBUG
56 		fprintf(stderr, "recvmsg(uds): flags not implemented\n");
57 #endif
58 		errno= ENOSYS;
59 		return -1;
60 	}
61 
62 	r= readv(sock, msg->msg_iov, msg->msg_iovlen);
63 
64 	if (r >= 0 && msg->msg_name && msg->msg_namelen > 0) {
65 		getpeername(sock, msg->msg_name, &msg->msg_namelen);
66 	}
67 
68 	/* get control data */
69 	if (r >= 0 && msg->msg_control && msg->msg_controllen > 0) {
70 		struct msg_control msg_ctrl;
71 
72 		memset(&msg_ctrl, '\0', sizeof(struct msg_control));
73 		msg_ctrl.msg_controllen = msg->msg_controllen;
74 		rc = ioctl(sock, NWIOGUDSCTRL, &msg_ctrl);
75 		if (rc == -1) {
76 			return rc;
77 		}
78 
79 		if (msg_ctrl.msg_controllen <= msg->msg_controllen) {
80 			memcpy(msg->msg_control, msg_ctrl.msg_control,
81 						msg_ctrl.msg_controllen);
82 			msg->msg_controllen = msg_ctrl.msg_controllen;
83 		}
84 	}
85 
86 	msg->msg_flags = 0;
87 
88 	return r;
89 }
90 
91 static ssize_t _uds_recvmsg_dgram(int sock, struct msghdr *msg, int flags)
92 {
93 	int r, rc;
94 
95 	if (flags != 0) {
96 #if DEBUG
97 		fprintf(stderr, "recvmsg(uds): flags not implemented\n");
98 #endif
99 		errno= ENOSYS;
100 		return -1;
101 	}
102 
103 	r= readv(sock, msg->msg_iov, msg->msg_iovlen);
104 
105 	if (r >= 0 && msg->msg_name &&
106 				msg->msg_namelen >= sizeof(struct sockaddr_un))
107 	{
108 		rc= ioctl(sock, NWIOGUDSFADDR, msg->msg_name);
109 		if (rc == -1) {
110 			return rc;
111 		}
112 		msg->msg_namelen= sizeof(struct sockaddr_un);
113 	}
114 
115 	/* get control data */
116 	if (r >= 0 && msg->msg_control && msg->msg_controllen > 0) {
117 		struct msg_control msg_ctrl;
118 
119 		memset(&msg_ctrl, '\0', sizeof(struct msg_control));
120 		msg_ctrl.msg_controllen = msg->msg_controllen;
121 		rc = ioctl(sock, NWIOGUDSCTRL, &msg_ctrl);
122 		if (rc == -1) {
123 			return rc;
124 		}
125 
126 		if (msg_ctrl.msg_controllen <= msg->msg_controllen) {
127 			memcpy(msg->msg_control, msg_ctrl.msg_control,
128 						msg_ctrl.msg_controllen);
129 			msg->msg_controllen = msg_ctrl.msg_controllen;
130 		}
131 	}
132 
133 	msg->msg_flags = 0;
134 
135 	return r;
136 }
137