xref: /minix3/minix/lib/libc/sys/setsockopt.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc #include <sys/cdefs.h>
2*433d6423SLionel Sambuc #include "namespace.h"
3*433d6423SLionel Sambuc 
4*433d6423SLionel Sambuc #include <assert.h>
5*433d6423SLionel Sambuc #include <errno.h>
6*433d6423SLionel Sambuc #include <stdio.h>
7*433d6423SLionel Sambuc #include <sys/ioctl.h>
8*433d6423SLionel Sambuc #include <sys/socket.h>
9*433d6423SLionel Sambuc #include <sys/types.h>
10*433d6423SLionel Sambuc #include <netinet/tcp.h>
11*433d6423SLionel Sambuc 
12*433d6423SLionel Sambuc #include <net/gen/in.h>
13*433d6423SLionel Sambuc #include <net/gen/tcp.h>
14*433d6423SLionel Sambuc #include <net/gen/tcp_io.h>
15*433d6423SLionel Sambuc #include <net/gen/udp.h>
16*433d6423SLionel Sambuc #include <net/gen/udp_io.h>
17*433d6423SLionel Sambuc 
18*433d6423SLionel Sambuc #define DEBUG 0
19*433d6423SLionel Sambuc 
20*433d6423SLionel Sambuc static int _tcp_setsockopt(int sock, int level, int option_name,
21*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len);
22*433d6423SLionel Sambuc 
23*433d6423SLionel Sambuc static int _udp_setsockopt(int sock, int level, int option_name,
24*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len);
25*433d6423SLionel Sambuc 
26*433d6423SLionel Sambuc static int _uds_setsockopt(int sock, int level, int option_name,
27*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len);
28*433d6423SLionel Sambuc 
29*433d6423SLionel Sambuc int setsockopt(int sock, int level, int option_name,
30*433d6423SLionel Sambuc         const void *option_value, socklen_t option_len)
31*433d6423SLionel Sambuc {
32*433d6423SLionel Sambuc 	int r;
33*433d6423SLionel Sambuc 	nwio_tcpopt_t tcpopt;
34*433d6423SLionel Sambuc 	nwio_udpopt_t udpopt;
35*433d6423SLionel Sambuc 	struct sockaddr_un uds_addr;
36*433d6423SLionel Sambuc 
37*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
38*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
39*433d6423SLionel Sambuc 	{
40*433d6423SLionel Sambuc 		if (r == -1)
41*433d6423SLionel Sambuc 		{
42*433d6423SLionel Sambuc 			/* Bad file descriptor */
43*433d6423SLionel Sambuc 			return -1;
44*433d6423SLionel Sambuc 		}
45*433d6423SLionel Sambuc 		return _tcp_setsockopt(sock, level, option_name,
46*433d6423SLionel Sambuc 			option_value, option_len);
47*433d6423SLionel Sambuc 	}
48*433d6423SLionel Sambuc 
49*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGUDPOPT, &udpopt);
50*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
51*433d6423SLionel Sambuc 	{
52*433d6423SLionel Sambuc 		if (r == -1)
53*433d6423SLionel Sambuc 		{
54*433d6423SLionel Sambuc 			/* Bad file descriptor */
55*433d6423SLionel Sambuc 			return -1;
56*433d6423SLionel Sambuc 		}
57*433d6423SLionel Sambuc 		return _udp_setsockopt(sock, level, option_name,
58*433d6423SLionel Sambuc 			option_value, option_len);
59*433d6423SLionel Sambuc 	}
60*433d6423SLionel Sambuc 
61*433d6423SLionel Sambuc 	r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
62*433d6423SLionel Sambuc 	if (r != -1 || errno != ENOTTY)
63*433d6423SLionel Sambuc 	{
64*433d6423SLionel Sambuc 		if (r == -1)
65*433d6423SLionel Sambuc 		{
66*433d6423SLionel Sambuc 			/* Bad file descriptor */
67*433d6423SLionel Sambuc 			return -1;
68*433d6423SLionel Sambuc 		}
69*433d6423SLionel Sambuc 		return _uds_setsockopt(sock, level, option_name,
70*433d6423SLionel Sambuc 			option_value, option_len);
71*433d6423SLionel Sambuc 	}
72*433d6423SLionel Sambuc 
73*433d6423SLionel Sambuc 
74*433d6423SLionel Sambuc #if DEBUG
75*433d6423SLionel Sambuc 	fprintf(stderr, "setsockopt: not implemented for fd %d\n", sock);
76*433d6423SLionel Sambuc #endif
77*433d6423SLionel Sambuc 	errno= ENOTSOCK;
78*433d6423SLionel Sambuc 	return -1;
79*433d6423SLionel Sambuc }
80*433d6423SLionel Sambuc 
81*433d6423SLionel Sambuc static int _tcp_setsockopt(int sock, int level, int option_name,
82*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len)
83*433d6423SLionel Sambuc {
84*433d6423SLionel Sambuc 	int i;
85*433d6423SLionel Sambuc 
86*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
87*433d6423SLionel Sambuc 	{
88*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
89*433d6423SLionel Sambuc 		{
90*433d6423SLionel Sambuc 			errno= EINVAL;
91*433d6423SLionel Sambuc 			return -1;
92*433d6423SLionel Sambuc 		}
93*433d6423SLionel Sambuc 		i= *(const int *)option_value;
94*433d6423SLionel Sambuc 		if (!i)
95*433d6423SLionel Sambuc 		{
96*433d6423SLionel Sambuc 			/* At the moment there is no way to turn off
97*433d6423SLionel Sambuc 			 * reusing addresses.
98*433d6423SLionel Sambuc 			 */
99*433d6423SLionel Sambuc 			errno= ENOSYS;
100*433d6423SLionel Sambuc 			return -1;
101*433d6423SLionel Sambuc 		}
102*433d6423SLionel Sambuc 		return 0;
103*433d6423SLionel Sambuc 	}
104*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
105*433d6423SLionel Sambuc 	{
106*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
107*433d6423SLionel Sambuc 		{
108*433d6423SLionel Sambuc 			errno= EINVAL;
109*433d6423SLionel Sambuc 			return -1;
110*433d6423SLionel Sambuc 		}
111*433d6423SLionel Sambuc 		i= *(const int *)option_value;
112*433d6423SLionel Sambuc 		if (!i)
113*433d6423SLionel Sambuc 		{
114*433d6423SLionel Sambuc 			/* At the moment there is no way to turn off
115*433d6423SLionel Sambuc 			 * keepalives.
116*433d6423SLionel Sambuc 			 */
117*433d6423SLionel Sambuc 			errno= ENOSYS;
118*433d6423SLionel Sambuc 			return -1;
119*433d6423SLionel Sambuc 		}
120*433d6423SLionel Sambuc 		return 0;
121*433d6423SLionel Sambuc 	}
122*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_RCVBUF)
123*433d6423SLionel Sambuc 	{
124*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
125*433d6423SLionel Sambuc 		{
126*433d6423SLionel Sambuc 			errno= EINVAL;
127*433d6423SLionel Sambuc 			return -1;
128*433d6423SLionel Sambuc 		}
129*433d6423SLionel Sambuc 		i= *(const int *)option_value;
130*433d6423SLionel Sambuc 		if (i > 32*1024)
131*433d6423SLionel Sambuc 		{
132*433d6423SLionel Sambuc 			/* The receive buffer is limited to 32K at the moment.
133*433d6423SLionel Sambuc 			 */
134*433d6423SLionel Sambuc 			errno= ENOSYS;
135*433d6423SLionel Sambuc 			return -1;
136*433d6423SLionel Sambuc 		}
137*433d6423SLionel Sambuc 		/* There is no way to reduce the receive buffer, do we have to
138*433d6423SLionel Sambuc 		 * let this call fail for smaller buffers?
139*433d6423SLionel Sambuc 		 */
140*433d6423SLionel Sambuc 		return 0;
141*433d6423SLionel Sambuc 	}
142*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_SNDBUF)
143*433d6423SLionel Sambuc 	{
144*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
145*433d6423SLionel Sambuc 		{
146*433d6423SLionel Sambuc 			errno= EINVAL;
147*433d6423SLionel Sambuc 			return -1;
148*433d6423SLionel Sambuc 		}
149*433d6423SLionel Sambuc 		i= *(const int *)option_value;
150*433d6423SLionel Sambuc 		if (i > 32*1024)
151*433d6423SLionel Sambuc 		{
152*433d6423SLionel Sambuc 			/* The send buffer is limited to 32K at the moment.
153*433d6423SLionel Sambuc 			 */
154*433d6423SLionel Sambuc 			errno= ENOSYS;
155*433d6423SLionel Sambuc 			return -1;
156*433d6423SLionel Sambuc 		}
157*433d6423SLionel Sambuc 		/* There is no way to reduce the send buffer, do we have to
158*433d6423SLionel Sambuc 		 * let this call fail for smaller buffers?
159*433d6423SLionel Sambuc 		 */
160*433d6423SLionel Sambuc 		return 0;
161*433d6423SLionel Sambuc 	}
162*433d6423SLionel Sambuc 	if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
163*433d6423SLionel Sambuc 	{
164*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
165*433d6423SLionel Sambuc 		{
166*433d6423SLionel Sambuc 			errno= EINVAL;
167*433d6423SLionel Sambuc 			return -1;
168*433d6423SLionel Sambuc 		}
169*433d6423SLionel Sambuc 		i= *(const int *)option_value;
170*433d6423SLionel Sambuc 		if (i)
171*433d6423SLionel Sambuc 		{
172*433d6423SLionel Sambuc 			/* At the moment there is no way to turn on
173*433d6423SLionel Sambuc 			 * nodelay.
174*433d6423SLionel Sambuc 			 */
175*433d6423SLionel Sambuc 			errno= ENOSYS;
176*433d6423SLionel Sambuc 			return -1;
177*433d6423SLionel Sambuc 		}
178*433d6423SLionel Sambuc 		return 0;
179*433d6423SLionel Sambuc 	}
180*433d6423SLionel Sambuc #if DEBUG
181*433d6423SLionel Sambuc 	fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
182*433d6423SLionel Sambuc 		level, option_name);
183*433d6423SLionel Sambuc #endif
184*433d6423SLionel Sambuc 
185*433d6423SLionel Sambuc 	errno= ENOSYS;
186*433d6423SLionel Sambuc 	return -1;
187*433d6423SLionel Sambuc }
188*433d6423SLionel Sambuc 
189*433d6423SLionel Sambuc static int _udp_setsockopt(int sock, int level, int option_name,
190*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len)
191*433d6423SLionel Sambuc {
192*433d6423SLionel Sambuc #if DEBUG
193*433d6423SLionel Sambuc 	fprintf(stderr, "_udp_setsocketopt: level %d, name %d\n",
194*433d6423SLionel Sambuc 		level, option_name);
195*433d6423SLionel Sambuc #endif
196*433d6423SLionel Sambuc 
197*433d6423SLionel Sambuc 	errno= ENOSYS;
198*433d6423SLionel Sambuc 	return -1;
199*433d6423SLionel Sambuc }
200*433d6423SLionel Sambuc 
201*433d6423SLionel Sambuc 
202*433d6423SLionel Sambuc static int _uds_setsockopt(int sock, int level, int option_name,
203*433d6423SLionel Sambuc 	const void *option_value, socklen_t option_len)
204*433d6423SLionel Sambuc {
205*433d6423SLionel Sambuc 	int i;
206*433d6423SLionel Sambuc 	size_t size;
207*433d6423SLionel Sambuc 
208*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_RCVBUF)
209*433d6423SLionel Sambuc 	{
210*433d6423SLionel Sambuc 		if (option_len != sizeof(size))
211*433d6423SLionel Sambuc 		{
212*433d6423SLionel Sambuc 			errno= EINVAL;
213*433d6423SLionel Sambuc 			return -1;
214*433d6423SLionel Sambuc 		}
215*433d6423SLionel Sambuc 		size= *(const size_t *)option_value;
216*433d6423SLionel Sambuc 		return ioctl(sock, NWIOSUDSRCVBUF, &size);
217*433d6423SLionel Sambuc 	}
218*433d6423SLionel Sambuc 
219*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_SNDBUF)
220*433d6423SLionel Sambuc 	{
221*433d6423SLionel Sambuc 		if (option_len != sizeof(size))
222*433d6423SLionel Sambuc 		{
223*433d6423SLionel Sambuc 			errno= EINVAL;
224*433d6423SLionel Sambuc 			return -1;
225*433d6423SLionel Sambuc 		}
226*433d6423SLionel Sambuc 		size= *(const size_t *)option_value;
227*433d6423SLionel Sambuc 		return ioctl(sock, NWIOSUDSSNDBUF, &size);
228*433d6423SLionel Sambuc 	}
229*433d6423SLionel Sambuc 
230*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
231*433d6423SLionel Sambuc 	{
232*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
233*433d6423SLionel Sambuc 		{
234*433d6423SLionel Sambuc 			errno= EINVAL;
235*433d6423SLionel Sambuc 			return -1;
236*433d6423SLionel Sambuc 		}
237*433d6423SLionel Sambuc 		i= *(const int *)option_value;
238*433d6423SLionel Sambuc 		if (!i)
239*433d6423SLionel Sambuc 		{
240*433d6423SLionel Sambuc 			/* At the moment there is no way to turn off
241*433d6423SLionel Sambuc 			 * reusing addresses.
242*433d6423SLionel Sambuc 			 */
243*433d6423SLionel Sambuc 			errno= ENOSYS;
244*433d6423SLionel Sambuc 			return -1;
245*433d6423SLionel Sambuc 		}
246*433d6423SLionel Sambuc 		return 0;
247*433d6423SLionel Sambuc 	}
248*433d6423SLionel Sambuc 
249*433d6423SLionel Sambuc 	if (level == SOL_SOCKET && option_name == SO_PASSCRED)
250*433d6423SLionel Sambuc 	{
251*433d6423SLionel Sambuc 		if (option_len != sizeof(i))
252*433d6423SLionel Sambuc 		{
253*433d6423SLionel Sambuc 			errno= EINVAL;
254*433d6423SLionel Sambuc 			return -1;
255*433d6423SLionel Sambuc 		}
256*433d6423SLionel Sambuc 		i= *(const int *)option_value;
257*433d6423SLionel Sambuc 		if (!i)
258*433d6423SLionel Sambuc 		{
259*433d6423SLionel Sambuc 			/* credentials can always be received. */
260*433d6423SLionel Sambuc 			errno= ENOSYS;
261*433d6423SLionel Sambuc 			return -1;
262*433d6423SLionel Sambuc 		}
263*433d6423SLionel Sambuc 		return 0;
264*433d6423SLionel Sambuc 	}
265*433d6423SLionel Sambuc 
266*433d6423SLionel Sambuc #if DEBUG
267*433d6423SLionel Sambuc 	fprintf(stderr, "_uds_setsocketopt: level %d, name %d\n",
268*433d6423SLionel Sambuc 		level, option_name);
269*433d6423SLionel Sambuc #endif
270*433d6423SLionel Sambuc 
271*433d6423SLionel Sambuc 	errno= ENOSYS;
272*433d6423SLionel Sambuc 	return -1;
273*433d6423SLionel Sambuc }
274