PageRenderTime 22ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://www.minix3.org/
C | 295 lines | 246 code | 44 blank | 5 comment | 62 complexity | 4d24ed6413add6ad30e08eacde6777f3 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. #undef NDEBUG
  4. #include <assert.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/ioctl.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <net/gen/in.h>
  14. #include <net/gen/tcp.h>
  15. #include <net/gen/tcp_io.h>
  16. #include <net/gen/udp.h>
  17. #include <net/gen/udp_hdr.h>
  18. #include <net/gen/udp_io.h>
  19. #define DEBUG 0
  20. static ssize_t _tcp_recvfrom(int sock, void *__restrict buffer, size_t length,
  21. int flags, struct sockaddr *__restrict address,
  22. socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp);
  23. static ssize_t _udp_recvfrom(int sock, void *__restrict buffer, size_t length,
  24. int flags, struct sockaddr *__restrict address,
  25. socklen_t *__restrict address_len, nwio_udpopt_t *udpoptp);
  26. static ssize_t _uds_recvfrom_conn(int sock, void *__restrict buffer,
  27. size_t length, int flags, struct sockaddr *__restrict address,
  28. socklen_t *__restrict address_len, struct sockaddr_un *uds_addr);
  29. static ssize_t _uds_recvfrom_dgram(int sock, void *__restrict buffer,
  30. size_t length, int flags, struct sockaddr *__restrict address,
  31. socklen_t *__restrict address_len);
  32. ssize_t recvfrom(int sock, void *__restrict buffer, size_t length,
  33. int flags, struct sockaddr *__restrict address,
  34. socklen_t *__restrict address_len)
  35. {
  36. int r;
  37. nwio_tcpconf_t tcpconf;
  38. nwio_udpopt_t udpopt;
  39. struct sockaddr_un uds_addr;
  40. int uds_sotype = -1;
  41. #if DEBUG
  42. fprintf(stderr, "recvfrom: for fd %d\n", sock);
  43. #endif
  44. r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
  45. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  46. {
  47. if (r == -1)
  48. return r;
  49. return _tcp_recvfrom(sock, buffer, length, flags,
  50. address, address_len, &tcpconf);
  51. }
  52. r= ioctl(sock, NWIOGUDPOPT, &udpopt);
  53. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  54. {
  55. if (r == -1)
  56. return r;
  57. return _udp_recvfrom(sock, buffer, length, flags,
  58. address, address_len, &udpopt);
  59. }
  60. r= ioctl(sock, NWIOGUDSSOTYPE, &uds_sotype);
  61. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  62. {
  63. if (r == -1) {
  64. return r;
  65. }
  66. if (uds_sotype == SOCK_DGRAM) {
  67. return _uds_recvfrom_dgram(sock, buffer,
  68. length, flags, address, address_len);
  69. } else {
  70. return _uds_recvfrom_conn(sock, buffer,
  71. length, flags, address, address_len,
  72. &uds_addr);
  73. }
  74. }
  75. #if DEBUG
  76. fprintf(stderr, "recvfrom: not implemented for fd %d\n", sock);
  77. #endif
  78. errno= ENOSYS;
  79. assert(0);
  80. return -1;
  81. }
  82. static ssize_t _tcp_recvfrom(int sock, void *__restrict buffer, size_t length,
  83. int flags, struct sockaddr *__restrict address,
  84. socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp)
  85. {
  86. int r;
  87. size_t len;
  88. struct sockaddr_in sin;
  89. if (flags != 0)
  90. {
  91. #if DEBUG
  92. fprintf(stderr, "recvfrom(tcp): flags not implemented\n");
  93. #endif
  94. errno= ENOSYS;
  95. return -1;
  96. }
  97. r = read(sock, buffer, length);
  98. if (r >= 0 && address != NULL)
  99. {
  100. sin.sin_family= AF_INET;
  101. sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr;
  102. sin.sin_port= tcpconfp->nwtc_remport;
  103. len= *address_len;
  104. if (len > sizeof(sin))
  105. len= sizeof(sin);
  106. memcpy(address, &sin, len);
  107. *address_len= sizeof(sin);
  108. }
  109. return r;
  110. }
  111. static ssize_t _udp_recvfrom(int sock, void *__restrict buffer, size_t length,
  112. int flags, struct sockaddr *__restrict address,
  113. socklen_t *__restrict address_len, nwio_udpopt_t *udpoptp)
  114. {
  115. int r, t_errno;
  116. size_t buflen, len;
  117. void *buf;
  118. udp_io_hdr_t *io_hdrp;
  119. struct sockaddr_in sin;
  120. if (flags)
  121. {
  122. #if DEBUG
  123. fprintf(stderr, "recvfrom(udp): flags not implemented\n");
  124. #endif
  125. errno= ENOSYS;
  126. return -1;
  127. }
  128. if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
  129. {
  130. if (address != NULL &&
  131. (udpoptp->nwuo_flags & (NWUO_RA_SET | NWUO_RP_SET)) !=
  132. (NWUO_RA_SET | NWUO_RP_SET))
  133. {
  134. #if DEBUG
  135. fprintf(stderr,
  136. "recvfrom(udp): RWDATONLY on unconnected socket\n");
  137. #endif
  138. errno= ENOTCONN;
  139. return -1;
  140. }
  141. r= read(sock, buffer, length);
  142. if (r == -1)
  143. return r;
  144. if (address != NULL)
  145. {
  146. sin.sin_family= AF_INET;
  147. sin.sin_addr.s_addr= udpoptp->nwuo_remaddr;
  148. sin.sin_port= udpoptp->nwuo_remport;
  149. len= *address_len;
  150. if (len > sizeof(sin))
  151. len= sizeof(sin);
  152. memcpy(address, &sin, len);
  153. *address_len= sizeof(sin);
  154. }
  155. return r;
  156. }
  157. buflen= sizeof(*io_hdrp) + length;
  158. if (buflen < length)
  159. {
  160. /* Overflow */
  161. errno= EMSGSIZE;
  162. return -1;
  163. }
  164. buf= malloc(buflen);
  165. if (buf == NULL)
  166. return -1;
  167. r= read(sock, buf, buflen);
  168. if (r == -1)
  169. {
  170. t_errno= errno;
  171. #if DEBUG
  172. fprintf(stderr, "recvfrom(udp): read failed: %s\n",
  173. strerror(errno));
  174. fprintf(stderr, "udp opt flags = 0x%x\n", udpoptp->nwuo_flags);
  175. #endif
  176. free(buf);
  177. errno= t_errno;
  178. return -1;
  179. }
  180. assert(r >= sizeof(*io_hdrp));
  181. length= r-sizeof(*io_hdrp);
  182. io_hdrp= buf;
  183. memcpy(buffer, &io_hdrp[1], length);
  184. if (address != NULL)
  185. {
  186. sin.sin_family= AF_INET;
  187. sin.sin_addr.s_addr= io_hdrp->uih_src_addr;
  188. sin.sin_port= io_hdrp->uih_src_port;
  189. len= *address_len;
  190. if (len > sizeof(sin))
  191. len= sizeof(sin);
  192. memcpy(address, &sin, len);
  193. *address_len= sizeof(sin);
  194. }
  195. free(buf);
  196. return length;
  197. }
  198. static ssize_t _uds_recvfrom_conn(int sock, void *__restrict buffer,
  199. size_t length, int flags, struct sockaddr *__restrict address,
  200. socklen_t *__restrict address_len, struct sockaddr_un *uds_addr)
  201. {
  202. int r;
  203. size_t len;
  204. /* for connection oriented unix domain sockets (SOCK_STREAM /
  205. * SOCK_SEQPACKET)
  206. */
  207. if (flags != 0)
  208. {
  209. #if DEBUG
  210. fprintf(stderr, "recvfrom(uds): flags not implemented\n");
  211. #endif
  212. errno= ENOSYS;
  213. return -1;
  214. }
  215. r = read(sock, buffer, length);
  216. if (r >= 0 && address != NULL)
  217. {
  218. len= *address_len;
  219. if (len > sizeof(struct sockaddr_un))
  220. len= sizeof(struct sockaddr_un);
  221. memcpy(address, uds_addr, len);
  222. *address_len= sizeof(struct sockaddr_un);
  223. }
  224. return r;
  225. }
  226. static ssize_t _uds_recvfrom_dgram(int sock, void *__restrict buffer,
  227. size_t length, int flags, struct sockaddr *__restrict address,
  228. socklen_t *__restrict address_len)
  229. {
  230. int r;
  231. size_t len;
  232. /* for connectionless unix domain sockets (SOCK_DGRAM) */
  233. if (flags != 0)
  234. {
  235. #if DEBUG
  236. fprintf(stderr, "recvfrom(uds): flags not implemented\n");
  237. #endif
  238. errno= ENOSYS;
  239. return -1;
  240. }
  241. r = read(sock, buffer, length);
  242. if (r >= 0 && address != NULL)
  243. {
  244. len= *address_len;
  245. if (len > sizeof(struct sockaddr_un))
  246. len= sizeof(struct sockaddr_un);
  247. ioctl(sock, NWIOGUDSFADDR, address);
  248. *address_len= sizeof(struct sockaddr_un);
  249. }
  250. return r;
  251. }