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

http://www.minix3.org/ · C · 273 lines · 222 code · 25 blank · 26 comment · 85 complexity · 316ee25a9a7e6129df603381b98238e2 MD5 · raw file

  1. #include <sys/cdefs.h>
  2. #include "namespace.h"
  3. #include <assert.h>
  4. #include <errno.h>
  5. #include <stdio.h>
  6. #include <sys/ioctl.h>
  7. #include <sys/socket.h>
  8. #include <sys/types.h>
  9. #include <netinet/tcp.h>
  10. #include <net/gen/in.h>
  11. #include <net/gen/tcp.h>
  12. #include <net/gen/tcp_io.h>
  13. #include <net/gen/udp.h>
  14. #include <net/gen/udp_io.h>
  15. #define DEBUG 0
  16. static int _tcp_setsockopt(int sock, int level, int option_name,
  17. const void *option_value, socklen_t option_len);
  18. static int _udp_setsockopt(int sock, int level, int option_name,
  19. const void *option_value, socklen_t option_len);
  20. static int _uds_setsockopt(int sock, int level, int option_name,
  21. const void *option_value, socklen_t option_len);
  22. int setsockopt(int sock, int level, int option_name,
  23. const void *option_value, socklen_t option_len)
  24. {
  25. int r;
  26. nwio_tcpopt_t tcpopt;
  27. nwio_udpopt_t udpopt;
  28. struct sockaddr_un uds_addr;
  29. r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
  30. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  31. {
  32. if (r == -1)
  33. {
  34. /* Bad file descriptor */
  35. return -1;
  36. }
  37. return _tcp_setsockopt(sock, level, option_name,
  38. option_value, option_len);
  39. }
  40. r= ioctl(sock, NWIOGUDPOPT, &udpopt);
  41. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  42. {
  43. if (r == -1)
  44. {
  45. /* Bad file descriptor */
  46. return -1;
  47. }
  48. return _udp_setsockopt(sock, level, option_name,
  49. option_value, option_len);
  50. }
  51. r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
  52. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  53. {
  54. if (r == -1)
  55. {
  56. /* Bad file descriptor */
  57. return -1;
  58. }
  59. return _uds_setsockopt(sock, level, option_name,
  60. option_value, option_len);
  61. }
  62. #if DEBUG
  63. fprintf(stderr, "setsockopt: not implemented for fd %d\n", sock);
  64. #endif
  65. errno= ENOTSOCK;
  66. return -1;
  67. }
  68. static int _tcp_setsockopt(int sock, int level, int option_name,
  69. const void *option_value, socklen_t option_len)
  70. {
  71. int i;
  72. if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
  73. {
  74. if (option_len != sizeof(i))
  75. {
  76. errno= EINVAL;
  77. return -1;
  78. }
  79. i= *(const int *)option_value;
  80. if (!i)
  81. {
  82. /* At the moment there is no way to turn off
  83. * reusing addresses.
  84. */
  85. errno= ENOSYS;
  86. return -1;
  87. }
  88. return 0;
  89. }
  90. if (level == SOL_SOCKET && option_name == SO_KEEPALIVE)
  91. {
  92. if (option_len != sizeof(i))
  93. {
  94. errno= EINVAL;
  95. return -1;
  96. }
  97. i= *(const int *)option_value;
  98. if (!i)
  99. {
  100. /* At the moment there is no way to turn off
  101. * keepalives.
  102. */
  103. errno= ENOSYS;
  104. return -1;
  105. }
  106. return 0;
  107. }
  108. if (level == SOL_SOCKET && option_name == SO_RCVBUF)
  109. {
  110. if (option_len != sizeof(i))
  111. {
  112. errno= EINVAL;
  113. return -1;
  114. }
  115. i= *(const int *)option_value;
  116. if (i > 32*1024)
  117. {
  118. /* The receive buffer is limited to 32K at the moment.
  119. */
  120. errno= ENOSYS;
  121. return -1;
  122. }
  123. /* There is no way to reduce the receive buffer, do we have to
  124. * let this call fail for smaller buffers?
  125. */
  126. return 0;
  127. }
  128. if (level == SOL_SOCKET && option_name == SO_SNDBUF)
  129. {
  130. if (option_len != sizeof(i))
  131. {
  132. errno= EINVAL;
  133. return -1;
  134. }
  135. i= *(const int *)option_value;
  136. if (i > 32*1024)
  137. {
  138. /* The send buffer is limited to 32K at the moment.
  139. */
  140. errno= ENOSYS;
  141. return -1;
  142. }
  143. /* There is no way to reduce the send buffer, do we have to
  144. * let this call fail for smaller buffers?
  145. */
  146. return 0;
  147. }
  148. if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
  149. {
  150. if (option_len != sizeof(i))
  151. {
  152. errno= EINVAL;
  153. return -1;
  154. }
  155. i= *(const int *)option_value;
  156. if (i)
  157. {
  158. /* At the moment there is no way to turn on
  159. * nodelay.
  160. */
  161. errno= ENOSYS;
  162. return -1;
  163. }
  164. return 0;
  165. }
  166. #if DEBUG
  167. fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
  168. level, option_name);
  169. #endif
  170. errno= ENOSYS;
  171. return -1;
  172. }
  173. static int _udp_setsockopt(int sock, int level, int option_name,
  174. const void *option_value, socklen_t option_len)
  175. {
  176. #if DEBUG
  177. fprintf(stderr, "_udp_setsocketopt: level %d, name %d\n",
  178. level, option_name);
  179. #endif
  180. errno= ENOSYS;
  181. return -1;
  182. }
  183. static int _uds_setsockopt(int sock, int level, int option_name,
  184. const void *option_value, socklen_t option_len)
  185. {
  186. int i;
  187. size_t size;
  188. if (level == SOL_SOCKET && option_name == SO_RCVBUF)
  189. {
  190. if (option_len != sizeof(size))
  191. {
  192. errno= EINVAL;
  193. return -1;
  194. }
  195. size= *(const size_t *)option_value;
  196. return ioctl(sock, NWIOSUDSRCVBUF, &size);
  197. }
  198. if (level == SOL_SOCKET && option_name == SO_SNDBUF)
  199. {
  200. if (option_len != sizeof(size))
  201. {
  202. errno= EINVAL;
  203. return -1;
  204. }
  205. size= *(const size_t *)option_value;
  206. return ioctl(sock, NWIOSUDSSNDBUF, &size);
  207. }
  208. if (level == SOL_SOCKET && option_name == SO_REUSEADDR)
  209. {
  210. if (option_len != sizeof(i))
  211. {
  212. errno= EINVAL;
  213. return -1;
  214. }
  215. i= *(const int *)option_value;
  216. if (!i)
  217. {
  218. /* At the moment there is no way to turn off
  219. * reusing addresses.
  220. */
  221. errno= ENOSYS;
  222. return -1;
  223. }
  224. return 0;
  225. }
  226. if (level == SOL_SOCKET && option_name == SO_PASSCRED)
  227. {
  228. if (option_len != sizeof(i))
  229. {
  230. errno= EINVAL;
  231. return -1;
  232. }
  233. i= *(const int *)option_value;
  234. if (!i)
  235. {
  236. /* credentials can always be received. */
  237. errno= ENOSYS;
  238. return -1;
  239. }
  240. return 0;
  241. }
  242. #if DEBUG
  243. fprintf(stderr, "_uds_setsocketopt: level %d, name %d\n",
  244. level, option_name);
  245. #endif
  246. errno= ENOSYS;
  247. return -1;
  248. }