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