__aeabi_ldivmod: fix sign logic
[minix.git] / lib / libc / sys-minix / getsockopt.c
blobc37b5dc365158a70b5e2aa21f17247bf514f65c5
1 #include <sys/cdefs.h>
2 #include "namespace.h"
4 #include <assert.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <sys/ioctl.h>
9 #include <sys/socket.h>
10 #include <sys/types.h>
11 #include <sys/ucred.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 #include <minix/type.h>
22 #define DEBUG 0
24 static int _tcp_getsockopt(int sock, int level, int option_name,
25 void *__restrict option_value, socklen_t *__restrict option_len);
26 static int _udp_getsockopt(int sock, int level, int option_name,
27 void *__restrict option_value, socklen_t *__restrict option_len);
28 static int _uds_getsockopt(int sock, int level, int option_name,
29 void *__restrict option_value, socklen_t *__restrict option_len);
30 static void getsockopt_copy(void *return_value, size_t return_len,
31 void *__restrict option_value, socklen_t *__restrict option_len);
33 int getsockopt(int sock, int level, int option_name,
34 void *__restrict option_value, socklen_t *__restrict option_len)
36 int r;
37 nwio_tcpopt_t tcpopt;
38 nwio_udpopt_t udpopt;
39 struct sockaddr_un uds_addr;
41 r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
42 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
44 if (r == -1)
46 /* Bad file descriptor */
47 return -1;
49 return _tcp_getsockopt(sock, level, option_name,
50 option_value, option_len);
53 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
54 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
56 if (r == -1)
58 /* Bad file descriptor */
59 return -1;
61 return _udp_getsockopt(sock, level, option_name,
62 option_value, option_len);
65 r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
66 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
68 if (r == -1)
70 /* Bad file descriptor */
71 return -1;
73 return _uds_getsockopt(sock, level, option_name,
74 option_value, option_len);
78 #if DEBUG
79 fprintf(stderr, "getsockopt: not implemented for fd %d\n", sock);
80 #endif
81 errno= ENOTSOCK;
82 return -1;
85 static void getsockopt_copy(void *return_value, size_t return_len,
86 void *__restrict option_value, socklen_t *__restrict option_len)
88 /* copy as much data as possible */
89 if (*option_len < return_len)
90 memcpy(option_value, return_value, *option_len);
91 else
92 memcpy(option_value, return_value, return_len);
94 /* return length */
95 *option_len = return_len;
98 static int _tcp_getsockopt(int sock, int level, int option_name,
99 void *__restrict option_value, socklen_t *__restrict option_len)
101 int i, r, err;
103 if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
105 i = 1; /* Binds to TIME_WAIT sockets never cause errors */
106 getsockopt_copy(&i, sizeof(i), option_value, option_len);
107 return 0;
109 if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
111 i = 1; /* Keepalive is always on */
112 getsockopt_copy(&i, sizeof(i), option_value, option_len);
113 return 0;
115 if (level == SOL_SOCKET && option_name == SO_ERROR)
117 r = ioctl(sock, NWIOTCPGERROR, &err);
118 if (r != 0)
119 return r;
121 getsockopt_copy(&err, sizeof(err), option_value, option_len);
122 return 0;
124 if (level == SOL_SOCKET && option_name == SO_RCVBUF)
126 i = 32 * 1024; /* Receive buffer in the current
127 * implementation
129 getsockopt_copy(&i, sizeof(i), option_value, option_len);
130 return 0;
132 if (level == SOL_SOCKET && option_name == SO_SNDBUF)
134 i = 32 * 1024; /* Send buffer in the current implementation */
135 getsockopt_copy(&i, sizeof(i), option_value, option_len);
136 return 0;
138 if (level == SOL_SOCKET && option_name == SO_TYPE)
140 i = SOCK_STREAM; /* this is a TCP socket */
141 getsockopt_copy(&i, sizeof(i), option_value, option_len);
142 return 0;
144 if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
146 i = 0; /* nodelay is always off */
147 getsockopt_copy(&i, sizeof(i), option_value, option_len);
148 return 0;
150 #if DEBUG
151 fprintf(stderr, "_tcp_getsocketopt: level %d, name %d\n",
152 level, option_name);
153 #endif
155 errno= ENOPROTOOPT;
156 return -1;
159 static int _udp_getsockopt(int sock, int level, int option_name,
160 void *__restrict option_value, socklen_t *__restrict option_len)
162 int i;
164 if (level == SOL_SOCKET && option_name == SO_TYPE)
166 i = SOCK_DGRAM; /* this is a UDP socket */
167 getsockopt_copy(&i, sizeof(i), option_value, option_len);
168 return 0;
170 #if DEBUG
171 fprintf(stderr, "_udp_getsocketopt: level %d, name %d\n",
172 level, option_name);
173 #endif
175 errno= ENOSYS;
176 return -1;
179 static int _uds_getsockopt(int sock, int level, int option_name,
180 void *__restrict option_value, socklen_t *__restrict option_len)
182 int i, r;
183 size_t size;
185 if (level == SOL_SOCKET && option_name == SO_RCVBUF)
187 r= ioctl(sock, NWIOGUDSRCVBUF, &size);
188 if (r == -1) {
189 return r;
192 getsockopt_copy(&size, sizeof(size), option_value, option_len);
193 return 0;
196 if (level == SOL_SOCKET && option_name == SO_SNDBUF)
198 r= ioctl(sock, NWIOGUDSSNDBUF, &size);
199 if (r == -1) {
200 return r;
203 getsockopt_copy(&size, sizeof(size), option_value, option_len);
204 return 0;
207 if (level == SOL_SOCKET && option_name == SO_TYPE)
209 r= ioctl(sock, NWIOGUDSSOTYPE, &i);
210 if (r == -1) {
211 return r;
214 getsockopt_copy(&i, sizeof(i), option_value, option_len);
215 return 0;
218 if (level == SOL_SOCKET && option_name == SO_PEERCRED)
220 struct ucred cred;
222 r= ioctl(sock, NWIOGUDSPEERCRED, &cred);
223 if (r == -1) {
224 return -1;
227 getsockopt_copy(&cred, sizeof(struct ucred), option_value,
228 option_len);
229 return 0;
233 if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
235 i = 1; /* as long as nobody is listen()ing on the address,
236 * it can be reused without waiting for a
237 * timeout to expire.
239 getsockopt_copy(&i, sizeof(i), option_value, option_len);
240 return 0;
243 if (level == SOL_SOCKET && option_name == SO_PASSCRED)
245 i = 1; /* option is always 'on' */
246 getsockopt_copy(&i, sizeof(i), option_value, option_len);
247 return 0;
250 #if DEBUG
251 fprintf(stderr, "_uds_getsocketopt: level %d, name %d\n",
252 level, option_name);
253 #endif
255 errno= ENOSYS;
256 return -1;