10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <sys/ucred.h>
13 #include <netinet/tcp.h>
15 #include <net/gen/in.h>
16 #include <net/gen/tcp.h>
17 #include <net/gen/tcp_io.h>
18 #include <net/gen/udp.h>
19 #include <net/gen/udp_io.h>
21 #include <minix/type.h>
25 static int _tcp_getsockopt(int sock
, int level
, int option_name
,
26 void *__restrict option_value
, socklen_t
*__restrict option_len
);
27 static int _udp_getsockopt(int sock
, int level
, int option_name
,
28 void *__restrict option_value
, socklen_t
*__restrict option_len
);
29 static int _uds_getsockopt(int sock
, int level
, int option_name
,
30 void *__restrict option_value
, socklen_t
*__restrict option_len
);
31 static void getsockopt_copy(void *return_value
, size_t return_len
,
32 void *__restrict option_value
, socklen_t
*__restrict option_len
);
38 __getsockopt(int fd
, int level
, int option_name
,
39 void * __restrict option_value
, socklen_t
* __restrict option_len
)
43 if (option_len
== NULL
) {
48 memset(&m
, 0, sizeof(m
));
49 m
.m_lc_vfs_sockopt
.fd
= fd
;
50 m
.m_lc_vfs_sockopt
.level
= level
;
51 m
.m_lc_vfs_sockopt
.name
= option_name
;
52 m
.m_lc_vfs_sockopt
.buf
= (vir_bytes
)option_value
;
53 m
.m_lc_vfs_sockopt
.len
= *option_len
;
55 if (_syscall(VFS_PROC_NR
, VFS_GETSOCKOPT
, &m
) < 0)
58 *option_len
= m
.m_vfs_lc_socklen
.len
;
62 int getsockopt(int sock
, int level
, int option_name
,
63 void *__restrict option_value
, socklen_t
*__restrict option_len
)
68 struct sockaddr_un uds_addr
;
70 r
= __getsockopt(sock
, level
, option_name
, option_value
, option_len
);
71 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
74 r
= ioctl(sock
, NWIOGTCPOPT
, &tcpopt
);
75 if (r
!= -1 || errno
!= ENOTTY
)
79 /* Bad file descriptor */
82 return _tcp_getsockopt(sock
, level
, option_name
,
83 option_value
, option_len
);
86 r
= ioctl(sock
, NWIOGUDPOPT
, &udpopt
);
87 if (r
!= -1 || errno
!= ENOTTY
)
91 /* Bad file descriptor */
94 return _udp_getsockopt(sock
, level
, option_name
,
95 option_value
, option_len
);
98 r
= ioctl(sock
, NWIOGUDSADDR
, &uds_addr
);
99 if (r
!= -1 || errno
!= ENOTTY
)
103 /* Bad file descriptor */
106 return _uds_getsockopt(sock
, level
, option_name
,
107 option_value
, option_len
);
114 static void getsockopt_copy(void *return_value
, size_t return_len
,
115 void *__restrict option_value
, socklen_t
*__restrict option_len
)
117 /* copy as much data as possible */
118 if (*option_len
< return_len
)
119 memcpy(option_value
, return_value
, *option_len
);
121 memcpy(option_value
, return_value
, return_len
);
124 *option_len
= return_len
;
127 static int _tcp_getsockopt(int sock
, int level
, int option_name
,
128 void *__restrict option_value
, socklen_t
*__restrict option_len
)
132 if (level
== SOL_SOCKET
&& option_name
== SO_REUSEADDR
)
134 i
= 1; /* Binds to TIME_WAIT sockets never cause errors */
135 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
138 if (level
== SOL_SOCKET
&& option_name
== SO_KEEPALIVE
)
140 i
= 1; /* Keepalive is always on */
141 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
144 if (level
== SOL_SOCKET
&& option_name
== SO_ERROR
)
146 r
= ioctl(sock
, NWIOTCPGERROR
, &err
);
150 getsockopt_copy(&err
, sizeof(err
), option_value
, option_len
);
153 if (level
== SOL_SOCKET
&& option_name
== SO_RCVBUF
)
155 i
= 32 * 1024; /* Receive buffer in the current
158 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
161 if (level
== SOL_SOCKET
&& option_name
== SO_SNDBUF
)
163 i
= 32 * 1024; /* Send buffer in the current implementation */
164 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
167 if (level
== SOL_SOCKET
&& option_name
== SO_TYPE
)
169 i
= SOCK_STREAM
; /* this is a TCP socket */
170 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
173 if (level
== IPPROTO_TCP
&& option_name
== TCP_NODELAY
)
175 i
= 0; /* nodelay is always off */
176 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
180 fprintf(stderr
, "_tcp_getsocketopt: level %d, name %d\n",
188 static int _udp_getsockopt(int sock
, int level
, int option_name
,
189 void *__restrict option_value
, socklen_t
*__restrict option_len
)
193 if (level
== SOL_SOCKET
&& option_name
== SO_TYPE
)
195 i
= SOCK_DGRAM
; /* this is a UDP socket */
196 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
200 fprintf(stderr
, "_udp_getsocketopt: level %d, name %d\n",
208 static int _uds_getsockopt(int sock
, int level
, int option_name
,
209 void *__restrict option_value
, socklen_t
*__restrict option_len
)
214 if (level
== SOL_SOCKET
&& option_name
== SO_RCVBUF
)
216 r
= ioctl(sock
, NWIOGUDSRCVBUF
, &size
);
221 getsockopt_copy(&size
, sizeof(size
), option_value
, option_len
);
225 if (level
== SOL_SOCKET
&& option_name
== SO_SNDBUF
)
227 r
= ioctl(sock
, NWIOGUDSSNDBUF
, &size
);
232 getsockopt_copy(&size
, sizeof(size
), option_value
, option_len
);
236 if (level
== SOL_SOCKET
&& option_name
== SO_TYPE
)
238 r
= ioctl(sock
, NWIOGUDSSOTYPE
, &i
);
243 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
248 if (level
== SOL_SOCKET
&& option_name
== SO_PEERCRED
)
252 r
= ioctl(sock
, NWIOGUDSPEERCRED
, &cred
);
257 getsockopt_copy(&cred
, sizeof(struct uucred
), option_value
,
264 if (level
== SOL_SOCKET
&& option_name
== SO_REUSEADDR
)
266 i
= 1; /* as long as nobody is listen()ing on the address,
267 * it can be reused without waiting for a
270 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
275 if (level
== SOL_SOCKET
&& option_name
== SO_PASSCRED
)
277 i
= 1; /* option is always 'on' */
278 getsockopt_copy(&i
, sizeof(i
), option_value
, option_len
);
284 fprintf(stderr
, "_uds_getsocketopt: level %d, name %d\n",