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>
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
)
39 struct sockaddr_un uds_addr
;
41 r
= ioctl(sock
, NWIOGTCPOPT
, &tcpopt
);
42 if (r
!= -1 || (errno
!= ENOTTY
&& errno
!= EBADIOCTL
))
46 /* Bad file descriptor */
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
))
58 /* Bad file descriptor */
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
))
70 /* Bad file descriptor */
73 return _uds_getsockopt(sock
, level
, option_name
,
74 option_value
, option_len
);
79 fprintf(stderr
, "getsockopt: not implemented for fd %d\n", sock
);
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
);
92 memcpy(option_value
, return_value
, return_len
);
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
)
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
);
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
);
115 if (level
== SOL_SOCKET
&& option_name
== SO_ERROR
)
117 r
= ioctl(sock
, NWIOTCPGERROR
, &err
);
121 getsockopt_copy(&err
, sizeof(err
), option_value
, option_len
);
124 if (level
== SOL_SOCKET
&& option_name
== SO_RCVBUF
)
126 i
= 32 * 1024; /* Receive buffer in the current
129 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
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
);
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
);
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
);
151 fprintf(stderr
, "_tcp_getsocketopt: level %d, name %d\n",
159 static int _udp_getsockopt(int sock
, int level
, int option_name
,
160 void *__restrict option_value
, socklen_t
*__restrict option_len
)
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
);
171 fprintf(stderr
, "_udp_getsocketopt: level %d, name %d\n",
179 static int _uds_getsockopt(int sock
, int level
, int option_name
,
180 void *__restrict option_value
, socklen_t
*__restrict option_len
)
185 if (level
== SOL_SOCKET
&& option_name
== SO_RCVBUF
)
187 r
= ioctl(sock
, NWIOGUDSRCVBUF
, &size
);
192 getsockopt_copy(&size
, sizeof(size
), option_value
, option_len
);
196 if (level
== SOL_SOCKET
&& option_name
== SO_SNDBUF
)
198 r
= ioctl(sock
, NWIOGUDSSNDBUF
, &size
);
203 getsockopt_copy(&size
, sizeof(size
), option_value
, option_len
);
207 if (level
== SOL_SOCKET
&& option_name
== SO_TYPE
)
209 r
= ioctl(sock
, NWIOGUDSSOTYPE
, &i
);
214 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
218 if (level
== SOL_SOCKET
&& option_name
== SO_PEERCRED
)
222 r
= ioctl(sock
, NWIOGUDSPEERCRED
, &cred
);
227 getsockopt_copy(&cred
, sizeof(struct ucred
), option_value
,
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
239 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
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
);
251 fprintf(stderr
, "_uds_getsocketopt: level %d, name %d\n",