PageRenderTime 32ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

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

http://www.minix3.org/
C | 236 lines | 190 code | 36 blank | 10 comment | 52 complexity | 00d5051351b98bb893b93589d0848ab8 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 <stdio.h>
  7. #include <stdlib.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_sendto(int sock, const void *message, size_t length,
  21. int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
  22. static ssize_t _udp_sendto(int sock, const void *message, size_t length,
  23. int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
  24. nwio_udpopt_t *udpoptp);
  25. static ssize_t _uds_sendto_conn(int sock, const void *message, size_t length,
  26. int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
  27. static ssize_t _uds_sendto_dgram(int sock, const void *message, size_t length,
  28. int flags, const struct sockaddr *dest_addr, socklen_t dest_len);
  29. ssize_t sendto(int sock, const void *message, size_t length, int flags,
  30. const struct sockaddr *dest_addr, socklen_t dest_len)
  31. {
  32. int r;
  33. nwio_tcpopt_t tcpopt;
  34. nwio_udpopt_t udpopt;
  35. int uds_sotype = -1;
  36. r= ioctl(sock, NWIOGTCPOPT, &tcpopt);
  37. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  38. {
  39. if (r == -1)
  40. return r;
  41. return _tcp_sendto(sock, message, length, flags,
  42. dest_addr, dest_len);
  43. }
  44. r= ioctl(sock, NWIOGUDPOPT, &udpopt);
  45. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  46. {
  47. if (r == -1)
  48. return r;
  49. return _udp_sendto(sock, message, length, flags,
  50. dest_addr, dest_len, &udpopt);
  51. }
  52. r= ioctl(sock, NWIOGUDSSOTYPE, &uds_sotype);
  53. if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
  54. {
  55. if (r == -1) {
  56. return r;
  57. }
  58. if (uds_sotype == SOCK_DGRAM) {
  59. return _uds_sendto_dgram(sock, message,
  60. length, flags,dest_addr, dest_len);
  61. } else {
  62. return _uds_sendto_conn(sock, message,
  63. length, flags, dest_addr, dest_len);
  64. }
  65. }
  66. #if DEBUG
  67. fprintf(stderr, "sendto: not implemented for fd %d\n", sock);
  68. #endif
  69. errno= ENOSYS;
  70. return -1;
  71. }
  72. static ssize_t _tcp_sendto(int sock, const void *message, size_t length,
  73. int flags, const struct sockaddr *dest_addr, socklen_t dest_len)
  74. {
  75. if (flags != 0) {
  76. #if DEBUG
  77. fprintf(stderr, "sendto(tcp): flags not implemented\n");
  78. #endif
  79. errno= ENOSYS;
  80. return -1;
  81. }
  82. /* Silently ignore destination, if given. */
  83. return write(sock, message, length);
  84. }
  85. static ssize_t _udp_sendto(int sock, const void *message, size_t length,
  86. int flags, const struct sockaddr *dest_addr, socklen_t dest_len,
  87. nwio_udpopt_t *udpoptp)
  88. {
  89. int r, t_errno;
  90. size_t buflen;
  91. void *buf;
  92. struct sockaddr_in *sinp;
  93. udp_io_hdr_t *io_hdrp;
  94. if (flags)
  95. {
  96. #if DEBUG
  97. fprintf(stderr, "sendto(udp): flags not implemented\n");
  98. #endif
  99. errno= ENOSYS;
  100. return -1;
  101. }
  102. if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
  103. return write(sock, message, length);
  104. if ((udpoptp->nwuo_flags & NWUO_RP_ANY) ||
  105. (udpoptp->nwuo_flags & NWUO_RA_ANY))
  106. {
  107. if (!dest_addr)
  108. {
  109. errno= ENOTCONN;
  110. return -1;
  111. }
  112. /* Check destination address */
  113. if (dest_len < sizeof(*sinp))
  114. {
  115. errno= EINVAL;
  116. return -1;
  117. }
  118. sinp= (struct sockaddr_in *) __UNCONST(dest_addr);
  119. if (sinp->sin_family != AF_INET)
  120. {
  121. errno= EAFNOSUPPORT;
  122. return -1;
  123. }
  124. }
  125. buflen= sizeof(*io_hdrp) + length;
  126. if (buflen < length)
  127. {
  128. /* Overflow */
  129. errno= EMSGSIZE;
  130. return -1;
  131. }
  132. buf= malloc(buflen);
  133. if (buf == NULL)
  134. return -1;
  135. io_hdrp= buf;
  136. io_hdrp->uih_src_addr= 0; /* Unused */
  137. io_hdrp->uih_src_port= 0; /* Will cause error if NWUO_LP_ANY */
  138. if (udpoptp->nwuo_flags & NWUO_RA_ANY)
  139. io_hdrp->uih_dst_addr= sinp->sin_addr.s_addr;
  140. else
  141. io_hdrp->uih_dst_addr= 0;
  142. if (udpoptp->nwuo_flags & NWUO_RP_ANY)
  143. io_hdrp->uih_dst_port= sinp->sin_port;
  144. else
  145. io_hdrp->uih_dst_port= 0;
  146. io_hdrp->uih_ip_opt_len= 0;
  147. io_hdrp->uih_data_len= 0;
  148. memcpy(&io_hdrp[1], message, length);
  149. r= write(sock, buf, buflen);
  150. if (r == -1)
  151. {
  152. t_errno= errno;
  153. free(buf);
  154. errno= t_errno;
  155. return -1;
  156. }
  157. assert(r == buflen);
  158. free(buf);
  159. return length;
  160. }
  161. static ssize_t _uds_sendto_conn(int sock, const void *message, size_t length,
  162. int flags, const struct sockaddr *dest_addr, socklen_t dest_len)
  163. {
  164. /* for connection oriented unix domain sockets (SOCK_STREAM /
  165. * SOCK_SEQPACKET)
  166. */
  167. if (flags != 0) {
  168. #if DEBUG
  169. fprintf(stderr, "sendto(uds): flags not implemented\n");
  170. #endif
  171. errno= ENOSYS;
  172. return -1;
  173. }
  174. /* Silently ignore destination, if given. */
  175. return write(sock, message, length);
  176. }
  177. static ssize_t _uds_sendto_dgram(int sock, const void *message, size_t length,
  178. int flags, const struct sockaddr *dest_addr, socklen_t dest_len)
  179. {
  180. int r;
  181. /* for connectionless unix domain sockets (SOCK_DGRAM) */
  182. if (flags != 0) {
  183. #if DEBUG
  184. fprintf(stderr, "sendto(uds): flags not implemented\n");
  185. #endif
  186. errno= ENOSYS;
  187. return -1;
  188. }
  189. if (dest_addr == NULL) {
  190. errno = EFAULT;
  191. return -1;
  192. }
  193. /* set the target address */
  194. r= ioctl(sock, NWIOSUDSTADDR, (void *) __UNCONST(dest_addr));
  195. if (r == -1) {
  196. return r;
  197. }
  198. /* do the send */
  199. return write(sock, message, length);
  200. }