lib/libc/sys-minix/recvfrom.c

http://www.minix3.org/ · C · 296 lines · 247 code · 44 blank · 5 comment · 62 complexity · c6741835dd0d0096c7e8505a9a73730a MD5 · raw file

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