etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / setsockopt.c
blobcbe29ed03d54c98049ba3366d29a5ca806d5d008
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <string.h>
6 #include <assert.h>
7 #include <errno.h>
8 #include <stdio.h>
9 #include <sys/ioctl.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <netinet/tcp.h>
14 #include <net/gen/in.h>
15 #include <net/gen/tcp.h>
16 #include <net/gen/tcp_io.h>
17 #include <net/gen/udp.h>
18 #include <net/gen/udp_io.h>
20 #define DEBUG 0
22 static int _tcp_setsockopt(int sock, int level, int option_name,
23 const void *option_value, socklen_t option_len);
25 static int _udp_setsockopt(int sock, int level, int option_name,
26 const void *option_value, socklen_t option_len);
28 static int _uds_setsockopt(int sock, int level, int option_name,
29 const void *option_value, socklen_t option_len);
32 * Set socket options.
34 static int
35 __setsockopt(int fd, int level, int option_name, const void * option_value,
36 socklen_t option_len)
38 message m;
40 memset(&m, 0, sizeof(m));
41 m.m_lc_vfs_sockopt.fd = fd;
42 m.m_lc_vfs_sockopt.level = level;
43 m.m_lc_vfs_sockopt.name = option_name;
44 m.m_lc_vfs_sockopt.buf = (vir_bytes)option_value;
45 m.m_lc_vfs_sockopt.len = option_len;
47 return _syscall(VFS_PROC_NR, VFS_SETSOCKOPT, &m);
50 int setsockopt(int sock, int level, int option_name,
51 const void *option_value, socklen_t option_len)
53 int r;
54 nwio_tcpopt_t tcpopt;
55 nwio_udpopt_t udpopt;
56 struct sockaddr_un uds_addr;
58 r = __setsockopt(sock, level, option_name, option_value, option_len);
59 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
60 return r;
62 r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
63 if (r != -1 || errno != ENOTTY)
65 if (r == -1)
67 /* Bad file descriptor */
68 return -1;
70 return _tcp_setsockopt(sock, level, option_name,
71 option_value, option_len);
74 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
75 if (r != -1 || errno != ENOTTY)
77 if (r == -1)
79 /* Bad file descriptor */
80 return -1;
82 return _udp_setsockopt(sock, level, option_name,
83 option_value, option_len);
86 r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
87 if (r != -1 || errno != ENOTTY)
89 if (r == -1)
91 /* Bad file descriptor */
92 return -1;
94 return _uds_setsockopt(sock, level, option_name,
95 option_value, option_len);
98 errno = ENOTSOCK;
99 return -1;
102 static int _tcp_setsockopt(int sock, int level, int option_name,
103 const void *option_value, socklen_t option_len)
105 int i;
107 if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
109 if (option_len != sizeof(i))
111 errno= EINVAL;
112 return -1;
114 i= *(const int *)option_value;
115 if (!i)
117 /* At the moment there is no way to turn off
118 * reusing addresses.
120 errno= ENOSYS;
121 return -1;
123 return 0;
125 if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
127 if (option_len != sizeof(i))
129 errno= EINVAL;
130 return -1;
132 i= *(const int *)option_value;
133 if (!i)
135 /* At the moment there is no way to turn off
136 * keepalives.
138 errno= ENOSYS;
139 return -1;
141 return 0;
143 if (level == SOL_SOCKET && option_name == SO_RCVBUF)
145 if (option_len != sizeof(i))
147 errno= EINVAL;
148 return -1;
150 i= *(const int *)option_value;
151 if (i > 32*1024)
153 /* The receive buffer is limited to 32K at the moment.
155 errno= ENOSYS;
156 return -1;
158 /* There is no way to reduce the receive buffer, do we have to
159 * let this call fail for smaller buffers?
161 return 0;
163 if (level == SOL_SOCKET && option_name == SO_SNDBUF)
165 if (option_len != sizeof(i))
167 errno= EINVAL;
168 return -1;
170 i= *(const int *)option_value;
171 if (i > 32*1024)
173 /* The send buffer is limited to 32K at the moment.
175 errno= ENOSYS;
176 return -1;
178 /* There is no way to reduce the send buffer, do we have to
179 * let this call fail for smaller buffers?
181 return 0;
183 if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
185 if (option_len != sizeof(i))
187 errno= EINVAL;
188 return -1;
190 i= *(const int *)option_value;
191 if (i)
193 /* At the moment there is no way to turn on
194 * nodelay.
196 errno= ENOSYS;
197 return -1;
199 return 0;
201 #if DEBUG
202 fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
203 level, option_name);
204 #endif
206 errno= ENOSYS;
207 return -1;
210 static int _udp_setsockopt(int sock, int level, int option_name,
211 const void *option_value, socklen_t option_len)
213 #if DEBUG
214 fprintf(stderr, "_udp_setsocketopt: level %d, name %d\n",
215 level, option_name);
216 #endif
218 errno= ENOSYS;
219 return -1;
223 static int _uds_setsockopt(int sock, int level, int option_name,
224 const void *option_value, socklen_t option_len)
226 int i;
227 size_t size;
229 if (level == SOL_SOCKET && option_name == SO_RCVBUF)
231 if (option_len != sizeof(size))
233 errno= EINVAL;
234 return -1;
236 size= *(const size_t *)option_value;
237 return ioctl(sock, NWIOSUDSRCVBUF, &size);
240 if (level == SOL_SOCKET && option_name == SO_SNDBUF)
242 if (option_len != sizeof(size))
244 errno= EINVAL;
245 return -1;
247 size= *(const size_t *)option_value;
248 return ioctl(sock, NWIOSUDSSNDBUF, &size);
251 if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
253 if (option_len != sizeof(i))
255 errno= EINVAL;
256 return -1;
258 i= *(const int *)option_value;
259 if (!i)
261 /* At the moment there is no way to turn off
262 * reusing addresses.
264 errno= ENOSYS;
265 return -1;
267 return 0;
270 #ifdef SO_PASSCRED
271 if (level == SOL_SOCKET && option_name == SO_PASSCRED)
273 if (option_len != sizeof(i))
275 errno= EINVAL;
276 return -1;
278 i= *(const int *)option_value;
279 if (!i)
281 /* credentials can always be received. */
282 errno= ENOSYS;
283 return -1;
285 return 0;
287 #endif
289 #if DEBUG
290 fprintf(stderr, "_uds_setsocketopt: level %d, name %d\n",
291 level, option_name);
292 #endif
294 errno= ENOSYS;
295 return -1;