PageRenderTime 24ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libc/sys-minix/getsockopt.c

http://www.minix3.org/
C | 257 lines | 212 code | 35 blank | 10 comment | 91 complexity | a8313e1e7639f2849d7c9417c4202dfc MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. #include <sys/cdefs.h>
  2. #include "namespace.h"
  3. #include <assert.h>
  4. #include <errno.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <sys/ioctl.h>
  8. #include <sys/socket.h>
  9. #include <sys/types.h>
  10. #include <sys/ucred.h>
  11. #include <netinet/tcp.h>
  12. #include <net/gen/in.h>
  13. #include <net/gen/tcp.h>
  14. #include <net/gen/tcp_io.h>
  15. #include <net/gen/udp.h>
  16. #include <net/gen/udp_io.h>
  17. #include <minix/type.h>
  18. #define DEBUG 0
  19. static int _tcp_getsockopt(int sock, int level, int option_name,
  20. void *__restrict option_value, socklen_t *__restrict option_len);
  21. static int _udp_getsockopt(int sock, int level, int option_name,
  22. void *__restrict option_value, socklen_t *__restrict option_len);
  23. static int _uds_getsockopt(int sock, int level, int option_name,
  24. void *__restrict option_value, socklen_t *__restrict option_len);
  25. static void getsockopt_copy(void *return_value, size_t return_len,
  26. void *__restrict option_value, socklen_t *__restrict option_len);
  27. int getsockopt(int sock, int level, int option_name,
  28. void *__restrict option_value, socklen_t *__restrict option_len)
  29. {
  30. int r;
  31. nwio_tcpopt_t tcpopt;
  32. nwio_udpopt_t udpopt;
  33. struct sockaddr_un uds_addr;
  34. r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
  35. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  36. {
  37. if (r == -1)
  38. {
  39. /* Bad file descriptor */
  40. return -1;
  41. }
  42. return _tcp_getsockopt(sock, level, option_name,
  43. option_value, option_len);
  44. }
  45. r= ioctl(sock, NWIOGUDPOPT, &udpopt);
  46. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  47. {
  48. if (r == -1)
  49. {
  50. /* Bad file descriptor */
  51. return -1;
  52. }
  53. return _udp_getsockopt(sock, level, option_name,
  54. option_value, option_len);
  55. }
  56. r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
  57. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  58. {
  59. if (r == -1)
  60. {
  61. /* Bad file descriptor */
  62. return -1;
  63. }
  64. return _uds_getsockopt(sock, level, option_name,
  65. option_value, option_len);
  66. }
  67. #if DEBUG
  68. fprintf(stderr, "getsockopt: not implemented for fd %d\n", sock);
  69. #endif
  70. errno= ENOTSOCK;
  71. return -1;
  72. }
  73. static void getsockopt_copy(void *return_value, size_t return_len,
  74. void *__restrict option_value, socklen_t *__restrict option_len)
  75. {
  76. /* copy as much data as possible */
  77. if (*option_len < return_len)
  78. memcpy(option_value, return_value, *option_len);
  79. else
  80. memcpy(option_value, return_value, return_len);
  81. /* return length */
  82. *option_len = return_len;
  83. }
  84. static int _tcp_getsockopt(int sock, int level, int option_name,
  85. void *__restrict option_value, socklen_t *__restrict option_len)
  86. {
  87. int i, r, err;
  88. if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
  89. {
  90. i = 1; /* Binds to TIME_WAIT sockets never cause errors */
  91. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  92. return 0;
  93. }
  94. if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
  95. {
  96. i = 1; /* Keepalive is always on */
  97. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  98. return 0;
  99. }
  100. if (level == SOL_SOCKET && option_name == SO_ERROR)
  101. {
  102. r = ioctl(sock, NWIOTCPGERROR, &err);
  103. if (r != 0)
  104. return r;
  105. getsockopt_copy(&err, sizeof(err), option_value, option_len);
  106. return 0;
  107. }
  108. if (level == SOL_SOCKET && option_name == SO_RCVBUF)
  109. {
  110. i = 32 * 1024; /* Receive buffer in the current
  111. * implementation
  112. */
  113. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  114. return 0;
  115. }
  116. if (level == SOL_SOCKET && option_name == SO_SNDBUF)
  117. {
  118. i = 32 * 1024; /* Send buffer in the current implementation */
  119. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  120. return 0;
  121. }
  122. if (level == SOL_SOCKET && option_name == SO_TYPE)
  123. {
  124. i = SOCK_STREAM; /* this is a TCP socket */
  125. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  126. return 0;
  127. }
  128. if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
  129. {
  130. i = 0; /* nodelay is always off */
  131. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  132. return 0;
  133. }
  134. #if DEBUG
  135. fprintf(stderr, "_tcp_getsocketopt: level %d, name %d\n",
  136. level, option_name);
  137. #endif
  138. errno= ENOPROTOOPT;
  139. return -1;
  140. }
  141. static int _udp_getsockopt(int sock, int level, int option_name,
  142. void *__restrict option_value, socklen_t *__restrict option_len)
  143. {
  144. int i;
  145. if (level == SOL_SOCKET && option_name == SO_TYPE)
  146. {
  147. i = SOCK_DGRAM; /* this is a UDP socket */
  148. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  149. return 0;
  150. }
  151. #if DEBUG
  152. fprintf(stderr, "_udp_getsocketopt: level %d, name %d\n",
  153. level, option_name);
  154. #endif
  155. errno= ENOSYS;
  156. return -1;
  157. }
  158. static int _uds_getsockopt(int sock, int level, int option_name,
  159. void *__restrict option_value, socklen_t *__restrict option_len)
  160. {
  161. int i, r;
  162. size_t size;
  163. if (level == SOL_SOCKET && option_name == SO_RCVBUF)
  164. {
  165. r= ioctl(sock, NWIOGUDSRCVBUF, &size);
  166. if (r == -1) {
  167. return r;
  168. }
  169. getsockopt_copy(&size, sizeof(size), option_value, option_len);
  170. return 0;
  171. }
  172. if (level == SOL_SOCKET && option_name == SO_SNDBUF)
  173. {
  174. r= ioctl(sock, NWIOGUDSSNDBUF, &size);
  175. if (r == -1) {
  176. return r;
  177. }
  178. getsockopt_copy(&size, sizeof(size), option_value, option_len);
  179. return 0;
  180. }
  181. if (level == SOL_SOCKET && option_name == SO_TYPE)
  182. {
  183. r= ioctl(sock, NWIOGUDSSOTYPE, &i);
  184. if (r == -1) {
  185. return r;
  186. }
  187. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  188. return 0;
  189. }
  190. if (level == SOL_SOCKET && option_name == SO_PEERCRED)
  191. {
  192. struct ucred cred;
  193. r= ioctl(sock, NWIOGUDSPEERCRED, &cred);
  194. if (r == -1) {
  195. return -1;
  196. }
  197. getsockopt_copy(&cred, sizeof(struct ucred), option_value,
  198. option_len);
  199. return 0;
  200. }
  201. if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
  202. {
  203. i = 1; /* as long as nobody is listen()ing on the address,
  204. * it can be reused without waiting for a
  205. * timeout to expire.
  206. */
  207. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  208. return 0;
  209. }
  210. if (level == SOL_SOCKET && option_name == SO_PASSCRED)
  211. {
  212. i = 1; /* option is always 'on' */
  213. getsockopt_copy(&i, sizeof(i), option_value, option_len);
  214. return 0;
  215. }
  216. #if DEBUG
  217. fprintf(stderr, "_uds_getsocketopt: level %d, name %d\n",
  218. level, option_name);
  219. #endif
  220. errno= ENOSYS;
  221. return -1;
  222. }