PageRenderTime 78ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/libc/dynamic/socket.c

https://gitlab.com/vascocosta/os
C | 1873 lines | 902 code | 274 blank | 697 comment | 269 complexity | 1bcb9c54e2ea882e8b745e671b3326b7 MD5 | raw file
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. socket.c
  9. Abstract:
  10. This module implements support for socket-based communication in user mode.
  11. Author:
  12. Evan Green 3-May-2013
  13. Environment:
  14. User Mode
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <arpa/inet.h>
  22. #include <errno.h>
  23. #include <fcntl.h>
  24. #include <netinet/in.h>
  25. #include <netinet/tcp.h>
  26. #include <string.h>
  27. #include <sys/socket.h>
  28. #include <sys/time.h>
  29. #include <sys/un.h>
  30. #include <limits.h>
  31. //
  32. // --------------------------------------------------------------------- Macros
  33. //
  34. //
  35. // This macro asserts that the MSG_* flags are equal to the SOCKET_IO_* flags
  36. // and require no translation. It is basically a static assert that gets
  37. // compiled away.
  38. //
  39. #define ASSERT_SOCKET_IO_FLAGS_ARE_EQUIVALENT() \
  40. ASSERT((MSG_PEEK == SOCKET_IO_PEEK) && \
  41. (MSG_OOB == SOCKET_IO_OUT_OF_BAND) && \
  42. (MSG_WAITALL == SOCKET_IO_WAIT_ALL) && \
  43. (MSG_TRUNC == SOCKET_IO_DATA_TRUNCATED) && \
  44. (MSG_CTRUNC == SOCKET_IO_CONTROL_TRUNCATED) && \
  45. (MSG_NOSIGNAL == SOCKET_IO_NO_SIGNAL) && \
  46. (MSG_DONTWAIT == SOCKET_IO_NON_BLOCKING) && \
  47. (MSG_DONTROUTE == SOCKET_IO_DONT_ROUTE))
  48. #define ASSERT_SOCKET_TYPES_EQUIVALENT() \
  49. ASSERT((SOCK_DGRAM == NetSocketDatagram) && \
  50. (SOCK_RAW == NetSocketRaw) && \
  51. (SOCK_SEQPACKET == NetSocketSequencedPacket) && \
  52. (SOCK_STREAM == NetSocketStream))
  53. #define ASSERT_DOMAIN_TYPES_EQUIVALENT() \
  54. ASSERT((AF_UNIX == NetDomainLocal) && \
  55. (AF_LOCAL == NetDomainLocal) && \
  56. (AF_INET == NetDomainIp4) && \
  57. (AF_INET6 == NetDomainIp6))
  58. #define ASSERT_SOCKET_LEVELS_EQUIVALENT() \
  59. ASSERT((SOL_SOCKET == SocketInformationBasic) && \
  60. (IPPROTO_IP == SocketInformationIp4) && \
  61. (IPPROTO_IPV6 == SocketInformationIp6) && \
  62. (IPPROTO_TCP == SocketInformationTcp) && \
  63. (IPPROTO_UDP == SocketInformationUdp) && \
  64. (IPPROTO_RAW == SocketInformationRaw))
  65. #define ASSERT_SOCKET_BASIC_OPTIONS_EQUIVALENT() \
  66. ASSERT((SO_ACCEPTCONN == SocketBasicOptionAcceptConnections) && \
  67. (SO_BROADCAST == SocketBasicOptionBroadcastEnabled) && \
  68. (SO_DEBUG == SocketBasicOptionDebug) && \
  69. (SO_DONTROUTE == SocketBasicOptionRoutingDisabled) && \
  70. (SO_ERROR == SocketBasicOptionErrorStatus) && \
  71. (SO_KEEPALIVE == SocketBasicOptionKeepAlive) && \
  72. (SO_LINGER == SocketBasicOptionLinger) && \
  73. (SO_OOBINLINE == SocketBasicOptionInlineOutOfBand) && \
  74. (SO_RCVBUF == SocketBasicOptionReceiveBufferSize) && \
  75. (SO_RCVLOWAT == SocketBasicOptionReceiveMinimum) && \
  76. (SO_RCVTIMEO == SocketBasicOptionReceiveTimeout) && \
  77. (SO_SNDBUF == SocketBasicOptionSendBufferSize) && \
  78. (SO_SNDLOWAT == SocketBasicOptionSendMinimum) && \
  79. (SO_SNDTIMEO == SocketBasicOptionSendTimeout) && \
  80. (SO_TYPE == SocketBasicOptionType) && \
  81. (SO_PASSCRED == SocketBasicOptionPassCredentials) && \
  82. (SO_PEERCRED == SocketBasicOptionPeerCredentials))
  83. #define ASSERT_SOCKET_IPV4_OPTIONS_EQUIVALENT() \
  84. ASSERT((IP_HDRINCL == SocketIp4OptionHeaderIncluded) && \
  85. (IP_ADD_MEMBERSHIP == SocketIp4OptionJoinMulticastGroup) && \
  86. (IP_DROP_MEMBERSHIP == SocketIp4OptionLeaveMulticastGroup) && \
  87. (IP_MULTICAST_IF == SocketIp4OptionMulticastInterface) && \
  88. (IP_MULTICAST_TTL == SocketIp4OptionMulticastTimeToLive) && \
  89. (IP_MULTICAST_LOOP == SocketIp4OptionMulticastLoopback) && \
  90. (IP_TTL == SocketIp4OptionTimeToLive))
  91. #define ASSERT_SOCKET_IPV6_OPTIONS_EQUIVALENT() \
  92. ASSERT((IPV6_JOIN_GROUP == SocketIp6OptionJoinMulticastGroup) && \
  93. (IPV6_LEAVE_GROUP == SocketIp6OptionLeaveMulticastGroup) && \
  94. (IPV6_MULTICAST_HOPS == SocketIp6OptionMulticastHops) && \
  95. (IPV6_MULTICAST_IF == SocketIp6OptionMulticastInterface) && \
  96. (IPV6_MULTICAST_LOOP == SocketIp6OptionMulticastLoopback) && \
  97. (IPV6_UNICAST_HOPS == SocketIp6OptionUnicastHops) && \
  98. (IPV6_V6ONLY == SocketIp6OptionIpv6Only))
  99. #define ASSERT_SOCKET_TCP_OPTIONS_EQUIVALENT() \
  100. ASSERT((TCP_NODELAY == SocketTcpOptionNoDelay) && \
  101. (TCP_KEEPIDLE == SocketTcpOptionKeepAliveTimeout) && \
  102. (TCP_KEEPINTVL == SocketTcpOptionKeepAlivePeriod) && \
  103. (TCP_KEEPCNT == SocketTcpOptionKeepAliveProbeLimit))
  104. //
  105. // ---------------------------------------------------------------- Definitions
  106. //
  107. //
  108. // ------------------------------------------------------ Data Type Definitions
  109. //
  110. //
  111. // ----------------------------------------------- Internal Function Prototypes
  112. //
  113. int
  114. ClpGetSocketAddress (
  115. int Socket,
  116. SOCKET_BASIC_OPTION Option,
  117. struct sockaddr *SocketAddress,
  118. socklen_t *AddressLength
  119. );
  120. VOID
  121. ClpGetPathFromSocketAddress (
  122. struct sockaddr *Address,
  123. socklen_t *AddressLength,
  124. PSTR *Path,
  125. PUINTN PathSize
  126. );
  127. //
  128. // -------------------------------------------------------------------- Globals
  129. //
  130. //
  131. // ------------------------------------------------------------------ Functions
  132. //
  133. LIBC_API
  134. int
  135. socketpair (
  136. int Domain,
  137. int Type,
  138. int Protocol,
  139. int Sockets[2]
  140. )
  141. /*++
  142. Routine Description:
  143. This routine creates an unbound pair of connected sockets. The two sockets
  144. are identical.
  145. Arguments:
  146. Domain - Supplies the communicaion domain in which a sockets are to be
  147. created. Currently only AF_UNIX is supported for socket pairs.
  148. Type - Supplies the type of socket to be created. See the SOCK_*
  149. definitions. Common values include SOCK_STREAM and SOCK_DGRAM.
  150. Protocol - Supplies the particular protocol to use for the given domain
  151. and type. Supply 0 to use a default protocol appropriate for the
  152. specified type.
  153. Sockets - Supplies an array where the two connected sockets will be
  154. returned on success.
  155. Return Value:
  156. 0 on success.
  157. -1 on error, and the errno variable will be set to contain more information.
  158. --*/
  159. {
  160. HANDLE Handles[2];
  161. ULONG OpenFlags;
  162. KSTATUS Status;
  163. ASSERT_SOCKET_TYPES_EQUIVALENT();
  164. ASSERT_DOMAIN_TYPES_EQUIVALENT();
  165. OpenFlags = 0;
  166. if ((Type & SOCK_CLOEXEC) != 0) {
  167. OpenFlags |= SYS_OPEN_FLAG_CLOSE_ON_EXECUTE;
  168. }
  169. if ((Type & SOCK_NONBLOCK) != 0) {
  170. OpenFlags |= SYS_OPEN_FLAG_NON_BLOCKING;
  171. }
  172. Type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
  173. Status = OsSocketCreatePair(Domain, Type, Protocol, OpenFlags, Handles);
  174. Sockets[0] = (int)(UINTN)(Handles[0]);
  175. Sockets[1] = (int)(UINTN)(Handles[1]);
  176. if (!KSUCCESS(Status)) {
  177. errno = ClConvertKstatusToErrorNumber(Status);
  178. return -1;
  179. }
  180. return 0;
  181. }
  182. LIBC_API
  183. int
  184. socket (
  185. int Domain,
  186. int Type,
  187. int Protocol
  188. )
  189. /*++
  190. Routine Description:
  191. This routine creates a new socket for communication.
  192. Arguments:
  193. Domain - Supplies the communicaion domain in which a socket is to be
  194. created. See the AF_* or PF_* definitions. The most common values are
  195. AF_INET, AF_INET6, and AF_UNIX.
  196. Type - Supplies the type of socket to be created. See the SOCK_*
  197. definitions. Common values include SOCK_STREAM and SOCK_DGRAM.
  198. Protocol - Supplies the particular protocol to use for the given domain
  199. and type. Supply 0 to use a default protocol appropriate for the
  200. specified type.
  201. Return Value:
  202. Returns a non-negative integer representing the descriptor for the new
  203. socket.
  204. -1 on error, and the errno variable will be set to contain more information.
  205. --*/
  206. {
  207. ULONG OpenFlags;
  208. HANDLE Socket;
  209. KSTATUS Status;
  210. //
  211. // The network domains and socket types line up.
  212. //
  213. ASSERT_DOMAIN_TYPES_EQUIVALENT();
  214. ASSERT_SOCKET_TYPES_EQUIVALENT();
  215. OpenFlags = 0;
  216. if ((Type & SOCK_CLOEXEC) != 0) {
  217. OpenFlags |= SYS_OPEN_FLAG_CLOSE_ON_EXECUTE;
  218. }
  219. if ((Type & SOCK_NONBLOCK) != 0) {
  220. OpenFlags |= SYS_OPEN_FLAG_NON_BLOCKING;
  221. }
  222. Type &= ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
  223. //
  224. // Create the socket.
  225. //
  226. Status = OsSocketCreate(Domain, Type, Protocol, OpenFlags, &Socket);
  227. if (!KSUCCESS(Status)) {
  228. errno = ClConvertKstatusToErrorNumber(Status);
  229. return -1;
  230. }
  231. return (int)(UINTN)Socket;
  232. }
  233. LIBC_API
  234. int
  235. bind (
  236. int Socket,
  237. const struct sockaddr *Address,
  238. socklen_t AddressLength
  239. )
  240. /*++
  241. Routine Description:
  242. This routine assigns a local socket address to a socket that currently has
  243. no local address assigned.
  244. Arguments:
  245. Socket - Supplies the file descriptor of the socket to be bound.
  246. Address - Supplies a pointer to the address to bind the socket to. The
  247. length and format depend on the address family of the socket.
  248. AddressLength - Supplies the length of the address structure in bytes.
  249. Return Value:
  250. 0 on success.
  251. -1 on error, and the errno variable will be set to contain more information.
  252. --*/
  253. {
  254. NETWORK_ADDRESS NetworkAddress;
  255. PSTR Path;
  256. UINTN PathSize;
  257. KSTATUS Status;
  258. //
  259. // Convert the address structure into a network address that the kernel
  260. // understands.
  261. //
  262. Path = NULL;
  263. PathSize = 0;
  264. Status = ClConvertToNetworkAddress(Address,
  265. AddressLength,
  266. &NetworkAddress,
  267. &Path,
  268. &PathSize);
  269. if (!KSUCCESS(Status)) {
  270. errno = ClConvertKstatusToErrorNumber(Status);
  271. return -1;
  272. }
  273. Status = OsSocketBind((HANDLE)(UINTN)Socket,
  274. &NetworkAddress,
  275. Path,
  276. PathSize);
  277. if (!KSUCCESS(Status)) {
  278. if (Status == STATUS_NOT_SUPPORTED) {
  279. errno = EOPNOTSUPP;
  280. } else {
  281. errno = ClConvertKstatusToErrorNumber(Status);
  282. }
  283. return -1;
  284. }
  285. return 0;
  286. }
  287. LIBC_API
  288. int
  289. listen (
  290. int Socket,
  291. int Backlog
  292. )
  293. /*++
  294. Routine Description:
  295. This routine marks a connection-mode socket as ready to accept new
  296. incoming connections.
  297. Arguments:
  298. Socket - Supplies the file descriptor of the socket to be marked as
  299. listening.
  300. Backlog - Supplies a suggestion to the system as to the number of
  301. un-accepted connections to queue up before refusing additional
  302. incoming connection requests.
  303. Return Value:
  304. 0 on success.
  305. -1 on error, and the errno variable will be set to contain more information.
  306. --*/
  307. {
  308. KSTATUS Status;
  309. if (Backlog < 0) {
  310. Backlog = 0;
  311. }
  312. Status = OsSocketListen((HANDLE)(UINTN)Socket, Backlog);
  313. if (!KSUCCESS(Status)) {
  314. if (Status == STATUS_NOT_SUPPORTED) {
  315. errno = EOPNOTSUPP;
  316. } else {
  317. errno = ClConvertKstatusToErrorNumber(Status);
  318. }
  319. return -1;
  320. }
  321. return 0;
  322. }
  323. LIBC_API
  324. int
  325. accept (
  326. int Socket,
  327. struct sockaddr *Address,
  328. socklen_t *AddressLength
  329. )
  330. /*++
  331. Routine Description:
  332. This routine extracts the first pending incoming connection from the
  333. given listening socket, creates a new socket representing that connection,
  334. and allocates a file descriptor for that new socket. These newly created
  335. file descriptors are then ready for reading and writing.
  336. Arguments:
  337. Socket - Supplies the file descriptor of the listening socket to accept
  338. a connection on.
  339. Address - Supplies an optional pointer where the address of the connecting
  340. socket will be returned.
  341. AddressLength - Supplies a pointer that on input contains the length of the
  342. specified Address structure, and on output returns the length of the
  343. returned address.
  344. Return Value:
  345. Returns a non-negative file descriptor representing the new connection on
  346. success.
  347. -1 on error, and the errno variable will be set to contain more information.
  348. --*/
  349. {
  350. return accept4(Socket, Address, AddressLength, 0);
  351. }
  352. LIBC_API
  353. int
  354. accept4 (
  355. int Socket,
  356. struct sockaddr *Address,
  357. socklen_t *AddressLength,
  358. int Flags
  359. )
  360. /*++
  361. Routine Description:
  362. This routine extracts the first pending incoming connection from the
  363. given listening socket, creates a new socket representing that connection,
  364. and allocates a file descriptor for that new socket. These newly created
  365. file descriptors are then ready for reading and writing.
  366. Arguments:
  367. Socket - Supplies the file descriptor of the listening socket to accept
  368. a connection on.
  369. Address - Supplies an optional pointer where the address of the connecting
  370. socket will be returned.
  371. AddressLength - Supplies a pointer that on input contains the length of the
  372. specified Address structure, and on output returns the length of the
  373. returned address.
  374. Flags - Supplies an optional bitfield of flags governing the newly created
  375. file descriptor. Set SOCK_CLOEXEC to set the O_CLOEXEC flag on the new
  376. descriptor, and SOCK_NONBLOCK to set the O_NONBLOCK flag on the new
  377. descriptor.
  378. Return Value:
  379. Returns a non-negative file descriptor representing the new connection on
  380. success.
  381. -1 on error, and the errno variable will be set to contain more information.
  382. --*/
  383. {
  384. NETWORK_ADDRESS NetworkAddress;
  385. HANDLE NewSocket;
  386. ULONG OpenFlags;
  387. PSTR RemotePath;
  388. UINTN RemotePathSize;
  389. KSTATUS Status;
  390. assert((SOCK_CLOEXEC == O_CLOEXEC) && (SOCK_NONBLOCK == O_NONBLOCK));
  391. OpenFlags = 0;
  392. if (Flags != 0) {
  393. if ((Flags & SOCK_CLOEXEC) != 0) {
  394. OpenFlags |= SYS_OPEN_FLAG_CLOSE_ON_EXECUTE;
  395. }
  396. if ((Flags & SOCK_NONBLOCK) != 0) {
  397. OpenFlags |= SYS_OPEN_FLAG_NON_BLOCKING;
  398. }
  399. }
  400. ClpGetPathFromSocketAddress(Address,
  401. AddressLength,
  402. &RemotePath,
  403. &RemotePathSize);
  404. Status = OsSocketAccept((HANDLE)(UINTN)Socket,
  405. &NewSocket,
  406. &NetworkAddress,
  407. RemotePath,
  408. &RemotePathSize,
  409. OpenFlags);
  410. if (!KSUCCESS(Status)) {
  411. if (Status == STATUS_NOT_SUPPORTED) {
  412. errno = EOPNOTSUPP;
  413. } else {
  414. errno = ClConvertKstatusToErrorNumber(Status);
  415. }
  416. return -1;
  417. }
  418. //
  419. // Convert the network address returned by the kernel into the C library
  420. // sockaddr structure.
  421. //
  422. if ((Address != NULL) && (AddressLength != NULL)) {
  423. Status = ClConvertFromNetworkAddress(&NetworkAddress,
  424. Address,
  425. AddressLength,
  426. RemotePath,
  427. RemotePathSize);
  428. if (!KSUCCESS(Status)) {
  429. errno = EINVAL;
  430. return -1;
  431. }
  432. }
  433. return (int)(UINTN)NewSocket;
  434. }
  435. LIBC_API
  436. int
  437. connect (
  438. int Socket,
  439. const struct sockaddr *Address,
  440. socklen_t AddressLength
  441. )
  442. /*++
  443. Routine Description:
  444. This routine attempts to reach out and establish a connection with another
  445. socket.
  446. Arguments:
  447. Socket - Supplies the file descriptor of the socket to use for the
  448. connection.
  449. Address - Supplies a pointer to the address to connect to. The length and
  450. format depend on the address family of the socket.
  451. AddressLength - Supplies the length of the address structure in bytes.
  452. Return Value:
  453. 0 on success.
  454. -1 on error, and the errno variable will be set to contain more information.
  455. --*/
  456. {
  457. NETWORK_ADDRESS NetworkAddress;
  458. PSTR RemotePath;
  459. UINTN RemotePathSize;
  460. KSTATUS Status;
  461. //
  462. // Convert the address structure into a network address that the kernel
  463. // understands.
  464. //
  465. RemotePath = NULL;
  466. RemotePathSize = 0;
  467. Status = ClConvertToNetworkAddress(Address,
  468. AddressLength,
  469. &NetworkAddress,
  470. &RemotePath,
  471. &RemotePathSize);
  472. if (!KSUCCESS(Status)) {
  473. errno = EINVAL;
  474. return -1;
  475. }
  476. Status = OsSocketConnect((HANDLE)(UINTN)Socket,
  477. &NetworkAddress,
  478. RemotePath,
  479. RemotePathSize);
  480. if (!KSUCCESS(Status)) {
  481. if (Status == STATUS_NOT_SUPPORTED) {
  482. errno = EOPNOTSUPP;
  483. } else if (Status == STATUS_RESOURCE_IN_USE) {
  484. errno = EADDRNOTAVAIL;
  485. } else if (Status == STATUS_INVALID_ADDRESS) {
  486. errno = EPROTOTYPE;
  487. } else if (Status == STATUS_TIMEOUT) {
  488. errno = ETIMEDOUT;
  489. } else if (Status == STATUS_UNEXPECTED_TYPE) {
  490. errno = EAFNOSUPPORT;
  491. } else {
  492. errno = ClConvertKstatusToErrorNumber(Status);
  493. }
  494. return -1;
  495. }
  496. return 0;
  497. }
  498. LIBC_API
  499. ssize_t
  500. send (
  501. int Socket,
  502. const void *Data,
  503. size_t Length,
  504. int Flags
  505. )
  506. /*++
  507. Routine Description:
  508. This routine sends data out of a connected socket.
  509. Arguments:
  510. Socket - Supplies the file descriptor of the socket to send data out of.
  511. Data - Supplies the buffer of data to send.
  512. Length - Supplies the length of the data buffer, in bytes.
  513. Flags - Supplies a bitfield of flags governing the transmission of the data.
  514. See MSG_* definitions.
  515. Return Value:
  516. Returns the number of bytes sent on success.
  517. -1 on error, and the errno variable will be set to contain more information.
  518. --*/
  519. {
  520. return sendto(Socket, Data, Length, Flags, NULL, 0);
  521. }
  522. LIBC_API
  523. ssize_t
  524. sendto (
  525. int Socket,
  526. const void *Data,
  527. size_t Length,
  528. int Flags,
  529. const struct sockaddr *DestinationAddress,
  530. socklen_t DestinationAddressLength
  531. )
  532. /*++
  533. Routine Description:
  534. This routine sends data out of a socket, potentially to a specific
  535. destination address for connection-less sockets.
  536. Arguments:
  537. Socket - Supplies the file descriptor of the socket to send data out of.
  538. Data - Supplies the buffer of data to send.
  539. Length - Supplies the length of the data buffer, in bytes.
  540. Flags - Supplies a bitfield of flags governing the transmission of the data.
  541. See MSG_* definitions.
  542. DestinationAddress - Supplies an optional pointer to the destination
  543. address to send the data to.
  544. DestinationAddressLength - Supplies the length of the destination address
  545. structure.
  546. Return Value:
  547. Returns the number of bytes sent on success.
  548. -1 on error, and the errno variable will be set to contain more information.
  549. --*/
  550. {
  551. NETWORK_ADDRESS NetworkAddress;
  552. SOCKET_IO_PARAMETERS Parameters;
  553. KSTATUS Status;
  554. //
  555. // Truncate the byte count, so that it does not exceed the maximum number
  556. // of bytes that can be returned.
  557. //
  558. if (Length > (size_t)SSIZE_MAX) {
  559. Length = (size_t)SSIZE_MAX;
  560. }
  561. Parameters.Size = Length;
  562. Parameters.BytesCompleted = 0;
  563. Parameters.IoFlags = SYS_IO_FLAG_WRITE;
  564. Parameters.SocketIoFlags = Flags;
  565. Parameters.TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  566. Parameters.NetworkAddress = NULL;
  567. Parameters.RemotePath = NULL;
  568. Parameters.RemotePathSize = 0;
  569. Parameters.ControlData = NULL;
  570. Parameters.ControlDataSize = 0;
  571. ASSERT_SOCKET_IO_FLAGS_ARE_EQUIVALENT();
  572. //
  573. // A specific desination address was supplied, so it needs to be converted.
  574. //
  575. if (DestinationAddress != NULL) {
  576. Status = ClConvertToNetworkAddress(DestinationAddress,
  577. DestinationAddressLength,
  578. &NetworkAddress,
  579. &(Parameters.RemotePath),
  580. &(Parameters.RemotePathSize));
  581. if (!KSUCCESS(Status)) {
  582. errno = EINVAL;
  583. return -1;
  584. }
  585. Parameters.NetworkAddress = &NetworkAddress;
  586. }
  587. Status = OsSocketPerformIo((HANDLE)(UINTN)Socket, &Parameters, (PVOID)Data);
  588. if (!KSUCCESS(Status)) {
  589. if (Status == STATUS_NOT_SUPPORTED) {
  590. errno = EOPNOTSUPP;
  591. } else {
  592. errno = ClConvertKstatusToErrorNumber(Status);
  593. }
  594. return -1;
  595. }
  596. return (ssize_t)(Parameters.BytesCompleted);
  597. }
  598. LIBC_API
  599. ssize_t
  600. sendmsg (
  601. int Socket,
  602. const struct msghdr *Message,
  603. int Flags
  604. )
  605. /*++
  606. Routine Description:
  607. This routine sends a message out of a socket, potentially to a specific
  608. destination address for connection-less sockets. This version of the send
  609. function allows for vectored I/O and sending of ancillary data.
  610. Arguments:
  611. Socket - Supplies the file descriptor of the socket to send data out of.
  612. Message - Supplies a pointer to the message details to send.
  613. Flags - Supplies a bitfield of flags governing the transmission of the data.
  614. See MSG_* definitions.
  615. Return Value:
  616. Returns the number of bytes sent on success.
  617. -1 on error, and the errno variable will be set to contain more information.
  618. --*/
  619. {
  620. NETWORK_ADDRESS Address;
  621. SOCKET_IO_PARAMETERS Parameters;
  622. KSTATUS Status;
  623. UINTN VectorIndex;
  624. if (Message == NULL) {
  625. errno = EINVAL;
  626. return -1;
  627. }
  628. Parameters.Size = 0;
  629. for (VectorIndex = 0; VectorIndex < Message->msg_iovlen; VectorIndex += 1) {
  630. Parameters.Size += Message->msg_iov[VectorIndex].iov_len;
  631. }
  632. //
  633. // Truncate the byte count, so that it does not exceed the maximum number
  634. // of bytes that can be returned.
  635. //
  636. if (Parameters.Size > (UINTN)SSIZE_MAX) {
  637. Parameters.Size = (UINTN)SSIZE_MAX;
  638. }
  639. ASSERT_SOCKET_IO_FLAGS_ARE_EQUIVALENT();
  640. Parameters.BytesCompleted = 0;
  641. Parameters.IoFlags = SYS_IO_FLAG_WRITE;
  642. Parameters.SocketIoFlags = Flags;
  643. Parameters.TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  644. Parameters.NetworkAddress = NULL;
  645. Parameters.RemotePath = NULL;
  646. Parameters.RemotePathSize = 0;
  647. if ((Message->msg_name != NULL) && (Message->msg_namelen != 0)) {
  648. Status = ClConvertToNetworkAddress(Message->msg_name,
  649. Message->msg_namelen,
  650. &Address,
  651. &(Parameters.RemotePath),
  652. &(Parameters.RemotePathSize));
  653. if (!KSUCCESS(Status)) {
  654. errno = EINVAL;
  655. return -1;
  656. }
  657. Parameters.NetworkAddress = &Address;
  658. }
  659. Parameters.ControlData = Message->msg_control;
  660. Parameters.ControlDataSize = Message->msg_controllen;
  661. Status = OsSocketPerformVectoredIo((HANDLE)(UINTN)Socket,
  662. &Parameters,
  663. (PIO_VECTOR)(Message->msg_iov),
  664. Message->msg_iovlen);
  665. if (!KSUCCESS(Status)) {
  666. if (Status == STATUS_NOT_SUPPORTED) {
  667. errno = EOPNOTSUPP;
  668. } else {
  669. errno = ClConvertKstatusToErrorNumber(Status);
  670. }
  671. return -1;
  672. }
  673. return (ssize_t)(Parameters.BytesCompleted);
  674. }
  675. LIBC_API
  676. ssize_t
  677. recv (
  678. int Socket,
  679. void *Buffer,
  680. size_t Length,
  681. int Flags
  682. )
  683. /*++
  684. Routine Description:
  685. This routine receives data from a connected socket.
  686. Arguments:
  687. Socket - Supplies the file descriptor of the socket to receive data from.
  688. Buffer - Supplies a pointer to a buffer where the received data will be
  689. returned.
  690. Length - Supplies the length of the data buffer, in bytes.
  691. Flags - Supplies a bitfield of flags governing the reception of the data.
  692. See MSG_* definitions.
  693. Return Value:
  694. Returns the number of bytes received on success.
  695. -1 on error, and the errno variable will be set to contain more information.
  696. --*/
  697. {
  698. return recvfrom(Socket, Buffer, Length, Flags, NULL, NULL);
  699. }
  700. LIBC_API
  701. ssize_t
  702. recvfrom (
  703. int Socket,
  704. void *Buffer,
  705. size_t Length,
  706. int Flags,
  707. struct sockaddr *SourceAddress,
  708. socklen_t *SourceAddressLength
  709. )
  710. /*++
  711. Routine Description:
  712. This routine receives data from a socket, potentially receiving the
  713. source address for connection-less sockets.
  714. Arguments:
  715. Socket - Supplies the file descriptor of the socket to receive data from.
  716. Buffer - Supplies a pointer to a buffer where the received data will be
  717. returned.
  718. Length - Supplies the length of the data buffer, in bytes.
  719. Flags - Supplies a bitfield of flags governing the reception of the data.
  720. See MSG_* definitions.
  721. SourceAddress - Supplies an optional pointer where the source of the packet
  722. will be returned for connection-less sockets.
  723. SourceAddressLength - Supplies the length of the source address structure.
  724. Return Value:
  725. Returns the number of bytes received on success.
  726. -1 on error, and the errno variable will be set to contain more information.
  727. --*/
  728. {
  729. NETWORK_ADDRESS NetworkAddress;
  730. SOCKET_IO_PARAMETERS Parameters;
  731. KSTATUS Status;
  732. //
  733. // Truncate the byte count, so that it does not exceed the maximum number
  734. // of bytes that can be returned.
  735. //
  736. if (Length > (size_t)SSIZE_MAX) {
  737. Length = (size_t)SSIZE_MAX;
  738. }
  739. Parameters.Size = Length;
  740. Parameters.BytesCompleted = 0;
  741. Parameters.IoFlags = 0;
  742. Parameters.SocketIoFlags = Flags;
  743. Parameters.TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  744. Parameters.NetworkAddress = NULL;
  745. Parameters.RemotePath = NULL;
  746. Parameters.RemotePathSize = 0;
  747. Parameters.ControlData = NULL;
  748. Parameters.ControlDataSize = 0;
  749. ASSERT_SOCKET_IO_FLAGS_ARE_EQUIVALENT();
  750. if (SourceAddress != NULL) {
  751. NetworkAddress.Domain = NetDomainInvalid;
  752. ClpGetPathFromSocketAddress(SourceAddress,
  753. SourceAddressLength,
  754. &(Parameters.RemotePath),
  755. &(Parameters.RemotePathSize));
  756. Parameters.NetworkAddress = &NetworkAddress;
  757. }
  758. Status = OsSocketPerformIo((HANDLE)(UINTN)Socket, &Parameters, Buffer);
  759. if ((!KSUCCESS(Status)) && (Status != STATUS_END_OF_FILE)) {
  760. if (Status == STATUS_NOT_SUPPORTED) {
  761. errno = EOPNOTSUPP;
  762. } else {
  763. errno = ClConvertKstatusToErrorNumber(Status);
  764. }
  765. return -1;
  766. }
  767. //
  768. // If requested, attempt to translate the network address provided by the
  769. // kernel to a C library socket address.
  770. //
  771. if (SourceAddress != NULL) {
  772. Status = ClConvertFromNetworkAddress(&NetworkAddress,
  773. SourceAddress,
  774. SourceAddressLength,
  775. Parameters.RemotePath,
  776. Parameters.RemotePathSize);
  777. if (!KSUCCESS(Status)) {
  778. errno = EINVAL;
  779. return -1;
  780. }
  781. }
  782. return (ssize_t)(Parameters.BytesCompleted);
  783. }
  784. LIBC_API
  785. ssize_t
  786. recvmsg (
  787. int Socket,
  788. struct msghdr *Message,
  789. int Flags
  790. )
  791. /*++
  792. Routine Description:
  793. This routine receives data from a socket, potentially receiving the
  794. source address for connection-less sockets. This variation of the recv
  795. function has the ability to receive vectored I/O, as well as ancillary
  796. data.
  797. Arguments:
  798. Socket - Supplies the file descriptor of the socket to receive data from.
  799. Message - Supplies a pointer to an initialized structure where the message
  800. information will be returned. The caller must initialize the
  801. appropriate members to valid buffers if the remote network address or
  802. ancillary data is desired.
  803. Flags - Supplies a bitfield of flags governing the reception of the data.
  804. See MSG_* definitions.
  805. Return Value:
  806. Returns the number of bytes received on success.
  807. -1 on error, and the errno variable will be set to contain more information.
  808. --*/
  809. {
  810. NETWORK_ADDRESS Address;
  811. SOCKET_IO_PARAMETERS Parameters;
  812. KSTATUS Status;
  813. UINTN VectorIndex;
  814. if (Message == NULL) {
  815. errno = EINVAL;
  816. return -1;
  817. }
  818. Parameters.Size = 0;
  819. for (VectorIndex = 0; VectorIndex < Message->msg_iovlen; VectorIndex += 1) {
  820. Parameters.Size += Message->msg_iov[VectorIndex].iov_len;
  821. }
  822. //
  823. // Truncate the byte count, so that it does not exceed the maximum number
  824. // of bytes that can be returned.
  825. //
  826. if (Parameters.Size > (UINTN)SSIZE_MAX) {
  827. Parameters.Size = (UINTN)SSIZE_MAX;
  828. }
  829. ASSERT_SOCKET_IO_FLAGS_ARE_EQUIVALENT();
  830. Parameters.BytesCompleted = 0;
  831. Parameters.IoFlags = 0;
  832. Parameters.SocketIoFlags = Flags;
  833. Parameters.TimeoutInMilliseconds = SYS_WAIT_TIME_INDEFINITE;
  834. Parameters.NetworkAddress = NULL;
  835. Parameters.RemotePath = NULL;
  836. Parameters.RemotePathSize = 0;
  837. if ((Message->msg_name != NULL) && (Message->msg_namelen != 0)) {
  838. Address.Domain = NetDomainInvalid;
  839. ClpGetPathFromSocketAddress(Message->msg_name,
  840. &(Message->msg_namelen),
  841. &(Parameters.RemotePath),
  842. &(Parameters.RemotePathSize));
  843. Parameters.NetworkAddress = &Address;
  844. }
  845. Parameters.ControlData = Message->msg_control;
  846. Parameters.ControlDataSize = Message->msg_controllen;
  847. Status = OsSocketPerformVectoredIo((HANDLE)(UINTN)Socket,
  848. &Parameters,
  849. (PIO_VECTOR)(Message->msg_iov),
  850. Message->msg_iovlen);
  851. Message->msg_flags = Parameters.SocketIoFlags;
  852. Message->msg_controllen = Parameters.ControlDataSize;
  853. if ((!KSUCCESS(Status)) && (Status != STATUS_END_OF_FILE)) {
  854. if (Status == STATUS_NOT_SUPPORTED) {
  855. errno = EOPNOTSUPP;
  856. } else {
  857. errno = ClConvertKstatusToErrorNumber(Status);
  858. }
  859. return -1;
  860. }
  861. //
  862. // If requested, attempt to translate the network address provided by the
  863. // kernel to a C library socket address.
  864. //
  865. if ((Message->msg_name != NULL) && (Message->msg_namelen != 0)) {
  866. Status = ClConvertFromNetworkAddress(&Address,
  867. Message->msg_name,
  868. &(Message->msg_namelen),
  869. Parameters.RemotePath,
  870. Parameters.RemotePathSize);
  871. if (!KSUCCESS(Status)) {
  872. errno = EINVAL;
  873. return -1;
  874. }
  875. }
  876. return (ssize_t)(Parameters.BytesCompleted);
  877. }
  878. LIBC_API
  879. int
  880. shutdown (
  881. int Socket,
  882. int How
  883. )
  884. /*++
  885. Routine Description:
  886. This routine shuts down all or part of a full-duplex socket connection.
  887. Arguments:
  888. Socket - Supplies the socket to shut down.
  889. How - Supplies the type of shutdown. Valid values are SHUT_RD to disable
  890. further receive operations, SHUT_WR to disable further send operations,
  891. or SHUT_RDWR to disable further send and receive operations.
  892. Return Value:
  893. 0 on success.
  894. -1 on failure, and errno will be set to contain more information.
  895. --*/
  896. {
  897. ULONG ShutdownType;
  898. KSTATUS Status;
  899. switch (How) {
  900. case SHUT_RD:
  901. ShutdownType = SOCKET_SHUTDOWN_READ;
  902. break;
  903. case SHUT_WR:
  904. ShutdownType = SOCKET_SHUTDOWN_WRITE;
  905. break;
  906. case SHUT_RDWR:
  907. ShutdownType = SOCKET_SHUTDOWN_READ | SOCKET_SHUTDOWN_WRITE;
  908. break;
  909. default:
  910. errno = EINVAL;
  911. return -1;
  912. }
  913. Status = OsSocketShutdown((HANDLE)(UINTN)Socket, ShutdownType);
  914. if (!KSUCCESS(Status)) {
  915. errno = ClConvertKstatusToErrorNumber(Status);
  916. return -1;
  917. }
  918. return 0;
  919. }
  920. LIBC_API
  921. int
  922. setsockopt (
  923. int Socket,
  924. int Level,
  925. int OptionName,
  926. const void *OptionValue,
  927. socklen_t OptionLength
  928. )
  929. /*++
  930. Routine Description:
  931. This routine sets a socket option for the given socket.
  932. Arguments:
  933. Socket - Supplies the file descriptor of the socket to set options for.
  934. Level - Supplies the protocol level at which the option resides. To set
  935. options at the socket level, supply SOL_SOCKET. To set options at other
  936. levels, specify the identifier for the protocol controlling the option.
  937. For example, to indicate that an option is interpreted by the TCP
  938. protocol, set this parameter to IPPROTO_TCP.
  939. OptionName - Supplies the option name that is passed to the protocol module
  940. for interpretation. See SO_* definitions.
  941. OptionValue - Supplies a pointer to a buffer that is passed uninterpreted
  942. to the protocol module. The contents of the buffer are option-specific.
  943. OptionLength - Supplies the length of the option buffer in bytes.
  944. Return Value:
  945. 0 on success.
  946. -1 on failure, and errno will be set to contain more information.
  947. --*/
  948. {
  949. socklen_t LocalOptionLength;
  950. KSTATUS Status;
  951. ASSERT_SOCKET_TYPES_EQUIVALENT();
  952. ASSERT_SOCKET_LEVELS_EQUIVALENT();
  953. ASSERT_SOCKET_BASIC_OPTIONS_EQUIVALENT();
  954. ASSERT_SOCKET_IPV4_OPTIONS_EQUIVALENT();
  955. ASSERT_SOCKET_IPV6_OPTIONS_EQUIVALENT();
  956. ASSERT_SOCKET_TCP_OPTIONS_EQUIVALENT();
  957. LocalOptionLength = OptionLength;
  958. Status = OsSocketGetSetInformation((HANDLE)(UINTN)Socket,
  959. Level,
  960. OptionName,
  961. (PVOID)OptionValue,
  962. (PUINTN)&LocalOptionLength,
  963. TRUE);
  964. if (!KSUCCESS(Status)) {
  965. if (Status == STATUS_BUFFER_TOO_SMALL) {
  966. Status = STATUS_INVALID_PARAMETER;
  967. }
  968. errno = ClConvertKstatusToErrorNumber(Status);
  969. return -1;
  970. }
  971. return 0;
  972. }
  973. LIBC_API
  974. int
  975. getsockopt (
  976. int Socket,
  977. int Level,
  978. int OptionName,
  979. void *OptionValue,
  980. socklen_t *OptionLength
  981. )
  982. /*++
  983. Routine Description:
  984. This routine retrieves the current value of a given socket option.
  985. Arguments:
  986. Socket - Supplies the file descriptor of the socket.
  987. Level - Supplies the protocol level at which the option resides. To get
  988. options at the socket level, supply SOL_SOCKET. To get options at other
  989. levels, specify the identifier for the protocol controlling the option.
  990. For example, to indicate that an option is interpreted by the TCP
  991. protocol, set this parameter to IPPROTO_TCP.
  992. OptionName - Supplies the option name that is passed to the protocol module
  993. for interpretation. See SO_* definitions.
  994. OptionValue - Supplies a pointer to a buffer where the option value is
  995. returned on success.
  996. OptionLength - Supplies a pointer that on input contains the size of the
  997. option value buffer in bytes. If the supplied length is less than the
  998. actual size of the option value, then the option value will be silently
  999. truncated. On output, if the supplied length is greater than the actual
  1000. size of the value, this will contain the actual size of the value.
  1001. Return Value:
  1002. 0 on success.
  1003. -1 on failure, and errno will be set to contain more information.
  1004. --*/
  1005. {
  1006. socklen_t OriginalOptionLength;
  1007. KSTATUS Status;
  1008. ASSERT_SOCKET_TYPES_EQUIVALENT();
  1009. ASSERT_SOCKET_LEVELS_EQUIVALENT();
  1010. ASSERT_SOCKET_BASIC_OPTIONS_EQUIVALENT();
  1011. ASSERT_SOCKET_IPV4_OPTIONS_EQUIVALENT();
  1012. ASSERT_SOCKET_IPV6_OPTIONS_EQUIVALENT();
  1013. ASSERT_SOCKET_TCP_OPTIONS_EQUIVALENT();
  1014. //
  1015. // Get the converted socket option from the system.
  1016. //
  1017. OriginalOptionLength = *OptionLength;
  1018. Status = OsSocketGetSetInformation((HANDLE)(UINTN)Socket,
  1019. Level,
  1020. OptionName,
  1021. OptionValue,
  1022. (PUINTN)OptionLength,
  1023. FALSE);
  1024. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1025. Status = STATUS_SUCCESS;
  1026. *OptionLength = OriginalOptionLength;
  1027. }
  1028. if (!KSUCCESS(Status)) {
  1029. errno = ClConvertKstatusToErrorNumber(Status);
  1030. return -1;
  1031. }
  1032. return 0;
  1033. }
  1034. LIBC_API
  1035. int
  1036. getsockname (
  1037. int Socket,
  1038. struct sockaddr *SocketAddress,
  1039. socklen_t *AddressLength
  1040. )
  1041. /*++
  1042. Routine Description:
  1043. This routine returns the current address to which the given socket is bound.
  1044. Arguments:
  1045. Socket - Supplies the file descriptor of the socket.
  1046. SocketAddress - Supplies a pointer where the socket address will be
  1047. returned.
  1048. AddressLength - Supplies a pointer that on input supplies the size of the
  1049. socket address buffer. On output, this will contain the actual size of
  1050. the buffer. The buffer will have been truncated if the number returned
  1051. here is greater than the number supplied.
  1052. Return Value:
  1053. 0 on success.
  1054. -1 on failure, and errno will be set to contain more information.
  1055. --*/
  1056. {
  1057. int Result;
  1058. Result = ClpGetSocketAddress(Socket,
  1059. SocketBasicOptionLocalAddress,
  1060. SocketAddress,
  1061. AddressLength);
  1062. return Result;
  1063. }
  1064. LIBC_API
  1065. int
  1066. getpeername (
  1067. int Socket,
  1068. struct sockaddr *SocketAddress,
  1069. socklen_t *AddressLength
  1070. )
  1071. /*++
  1072. Routine Description:
  1073. This routine returns the peer address of the specified socket.
  1074. Arguments:
  1075. Socket - Supplies the file descriptor of the socket.
  1076. SocketAddress - Supplies a pointer where the socket's peer address will be
  1077. returned.
  1078. AddressLength - Supplies a pointer that on input supplies the size of the
  1079. socket address buffer. On output, this will contain the actual size of
  1080. the buffer. The buffer will have been truncated if the number returned
  1081. here is greater than the number supplied.
  1082. Return Value:
  1083. 0 on success.
  1084. -1 on failure, and errno will be set to contain more information.
  1085. --*/
  1086. {
  1087. int Result;
  1088. Result = ClpGetSocketAddress(Socket,
  1089. SocketBasicOptionRemoteAddress,
  1090. SocketAddress,
  1091. AddressLength);
  1092. return Result;
  1093. }
  1094. LIBC_API
  1095. KSTATUS
  1096. ClConvertToNetworkAddress (
  1097. const struct sockaddr *Address,
  1098. socklen_t AddressLength,
  1099. PNETWORK_ADDRESS NetworkAddress,
  1100. PSTR *Path,
  1101. PUINTN PathSize
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine converts a sockaddr address structure into a network address
  1106. structure.
  1107. Arguments:
  1108. Address - Supplies a pointer to the address structure.
  1109. AddressLength - Supplies the length of the address structure in bytes.
  1110. NetworkAddress - Supplies a pointer where the corresponding network address
  1111. will be returned.
  1112. Path - Supplies an optional pointer where a pointer to the path will be
  1113. returned if this is a Unix address.
  1114. PathSize - Supplies an optional pointer where the path size will be
  1115. returned if this is a Unix address.
  1116. Return Value:
  1117. STATUS_SUCCESS on success.
  1118. STATUS_INVALID_ADDRESS on failure.
  1119. --*/
  1120. {
  1121. PLIST_ENTRY CurrentEntry;
  1122. PCL_TYPE_CONVERSION_INTERFACE Entry;
  1123. struct sockaddr_in *Ip4SocketAddress;
  1124. struct sockaddr_in6 *Ip6SocketAddress;
  1125. KSTATUS Status;
  1126. UINTN StringSize;
  1127. struct sockaddr_un *UnixAddress;
  1128. RtlZeroMemory(NetworkAddress, sizeof(NETWORK_ADDRESS));
  1129. if (AddressLength < sizeof(sa_family_t)) {
  1130. return STATUS_INVALID_ADDRESS;
  1131. }
  1132. if (Address->sa_family == AF_INET) {
  1133. if (AddressLength < sizeof(struct sockaddr_in)) {
  1134. return STATUS_INVALID_ADDRESS;
  1135. }
  1136. Ip4SocketAddress = (struct sockaddr_in *)Address;
  1137. NetworkAddress->Domain = NetDomainIp4;
  1138. //
  1139. // The network address port is in host order, but the address is in
  1140. // network order.
  1141. //
  1142. NetworkAddress->Port = ntohs(Ip4SocketAddress->sin_port);
  1143. RtlCopyMemory(NetworkAddress->Address,
  1144. &(Ip4SocketAddress->sin_addr.s_addr),
  1145. sizeof(in_addr_t));
  1146. } else if (Address->sa_family == AF_INET6) {
  1147. if (AddressLength < sizeof(struct sockaddr_in6)) {
  1148. return STATUS_INVALID_ADDRESS;
  1149. }
  1150. Ip6SocketAddress = (struct sockaddr_in6 *)Address;
  1151. NetworkAddress->Domain = NetDomainIp6;
  1152. //
  1153. // The network address port is in host order, but the address is in
  1154. // network order.
  1155. //
  1156. NetworkAddress->Port = ntohs(Ip6SocketAddress->sin6_port);
  1157. RtlCopyMemory(NetworkAddress->Address,
  1158. &(Ip6SocketAddress->sin6_addr),
  1159. sizeof(struct in6_addr));
  1160. //
  1161. // TODO: Update NETWORK_ADDRESS for IPv6.
  1162. //
  1163. } else if (Address->sa_family == AF_UNIX) {
  1164. UnixAddress = (struct sockaddr_un *)Address;
  1165. NetworkAddress->Domain = NetDomainLocal;
  1166. if (Path != NULL) {
  1167. *Path = UnixAddress->sun_path;
  1168. }
  1169. //
  1170. // The address length is supposed to include a null terminator. If the
  1171. // last character isn't a null terminator, then append a null
  1172. // terminator and increase the size.
  1173. //
  1174. StringSize = AddressLength - FIELD_OFFSET(struct sockaddr_un, sun_path);
  1175. if ((StringSize + 1 < UNIX_PATH_MAX) &&
  1176. (StringSize != 0) &&
  1177. (UnixAddress->sun_path[0] != '\0') &&
  1178. (UnixAddress->sun_path[StringSize - 1] != '\0')) {
  1179. UnixAddress->sun_path[StringSize] = '\0';
  1180. StringSize += 1;
  1181. }
  1182. if (PathSize != NULL) {
  1183. *PathSize = StringSize;
  1184. }
  1185. } else {
  1186. Status = STATUS_INVALID_ADDRESS;
  1187. pthread_mutex_lock(&ClTypeConversionInterfaceLock);
  1188. CurrentEntry = ClTypeConversionInterfaceList.Next;
  1189. while (CurrentEntry != &ClTypeConversionInterfaceList) {
  1190. Entry = LIST_VALUE(CurrentEntry,
  1191. CL_TYPE_CONVERSION_INTERFACE,
  1192. ListEntry);
  1193. CurrentEntry = CurrentEntry->Next;
  1194. if ((Entry->Type != ClConversionNetworkAddress) ||
  1195. (Entry->Interface.Network->Version !=
  1196. CL_NETWORK_CONVERSION_INTERFACE_VERSION) ||
  1197. (Entry->Interface.Network->AddressFamily !=
  1198. Address->sa_family)) {
  1199. continue;
  1200. }
  1201. Status = Entry->Interface.Network->ToNetworkAddress(Address,
  1202. AddressLength,
  1203. NetworkAddress);
  1204. break;
  1205. }
  1206. pthread_mutex_unlock(&ClTypeConversionInterfaceLock);
  1207. return Status;
  1208. }
  1209. return STATUS_SUCCESS;
  1210. }
  1211. LIBC_API
  1212. KSTATUS
  1213. ClConvertFromNetworkAddress (
  1214. PNETWORK_ADDRESS NetworkAddress,
  1215. struct sockaddr *Address,
  1216. socklen_t *AddressLength,
  1217. PSTR Path,
  1218. UINTN PathSize
  1219. )
  1220. /*++
  1221. Routine Description:
  1222. This routine converts a network address structure into a sockaddr structure.
  1223. Arguments:
  1224. NetworkAddress - Supplies a pointer to the network address to convert.
  1225. Address - Supplies a pointer where the address structure will be returned.
  1226. AddressLength - Supplies a pointer that on input contains the length of the
  1227. specified Address structure, and on output returns the length of the
  1228. returned address. If the supplied buffer is not big enough to hold the
  1229. address, the address is truncated, and the larger needed buffer size
  1230. will be returned here.
  1231. Path - Supplies the path, if this is a local Unix address.
  1232. PathSize - Supplies the size of the path, if this is a local Unix address.
  1233. Return Value:
  1234. STATUS_SUCCESS on success.
  1235. STATUS_BUFFER_TOO_SMALL if the address buffer is not big enough.
  1236. STATUS_INVALID_ADDRESS on failure.
  1237. --*/
  1238. {
  1239. UINTN CopySize;
  1240. PLIST_ENTRY CurrentEntry;
  1241. PCL_TYPE_CONVERSION_INTERFACE Entry;
  1242. struct sockaddr_in Ip4Address;
  1243. struct sockaddr_in6 Ip6Address;
  1244. PVOID Source;
  1245. KSTATUS Status;
  1246. UINTN TotalSize;
  1247. struct sockaddr_un UnixAddress;
  1248. if (NetworkAddress->Domain == NetDomainIp4) {
  1249. Ip4Address.sin_family = AF_INET;
  1250. Ip4Address.sin_port = htons((USHORT)(NetworkAddress->Port));
  1251. Ip4Address.sin_addr.s_addr = *((PULONG)(NetworkAddress->Address));
  1252. TotalSize = sizeof(Ip4Address);
  1253. Source = &Ip4Address;
  1254. } else if (NetworkAddress->Domain == NetDomainIp6) {
  1255. Ip6Address.sin6_family = AF_INET6;
  1256. Ip6Address.sin6_port = htons((USHORT)(NetworkAddress->Port));
  1257. //
  1258. // TODO: Update NETWORK_ADDRESS for IPv6.
  1259. //
  1260. Ip6Address.sin6_flowinfo = 0;
  1261. Ip6Address.sin6_scope_id = 0;
  1262. RtlCopyMemory(&(Ip6Address.sin6_addr),
  1263. NetworkAddress->Address,
  1264. sizeof(struct in6_addr));
  1265. TotalSize = sizeof(Ip6Address);
  1266. Source = &Ip6Address;
  1267. } else if (NetworkAddress->Domain == NetDomainLocal) {
  1268. UnixAddress.sun_family = AF_UNIX;
  1269. if (PathSize > UNIX_PATH_MAX) {
  1270. PathSize = UNIX_PATH_MAX;
  1271. }
  1272. if ((Path == NULL) || (PathSize == 0)) {
  1273. PathSize = 1;
  1274. } else if (Path != NULL) {
  1275. memcpy(UnixAddress.sun_path, Path, PathSize);
  1276. }
  1277. UnixAddress.sun_path[PathSize - 1] = '\0';
  1278. TotalSize = FIELD_OFFSET(struct sockaddr_un, sun_path) + PathSize;
  1279. Source = &UnixAddress;
  1280. } else {
  1281. Status = STATUS_INVALID_ADDRESS;
  1282. pthread_mutex_lock(&ClTypeConversionInterfaceLock);
  1283. CurrentEntry = ClTypeConversionInterfaceList.Next;
  1284. while (CurrentEntry != &ClTypeConversionInterfaceList) {
  1285. Entry = LIST_VALUE(CurrentEntry,
  1286. CL_TYPE_CONVERSION_INTERFACE,
  1287. ListEntry);
  1288. CurrentEntry = CurrentEntry->Next;
  1289. if ((Entry->Type != ClConversionNetworkAddress) ||
  1290. (Entry->Interface.Network->Version !=
  1291. CL_NETWORK_CONVERSION_INTERFACE_VERSION) ||
  1292. (Entry->Interface.Network->AddressDomain !=
  1293. NetworkAddress->Domain)) {
  1294. continue;
  1295. }
  1296. Status = Entry->Interface.Network->FromNetworkAddress(
  1297. NetworkAddress,
  1298. Address,
  1299. AddressLength);
  1300. break;
  1301. }
  1302. pthread_mutex_unlock(&ClTypeConversionInterfaceLock);
  1303. return Status;
  1304. }
  1305. Status = STATUS_SUCCESS;
  1306. CopySize = TotalSize;
  1307. if (CopySize > *AddressLength) {
  1308. CopySize = *AddressLength;
  1309. Status = STATUS_BUFFER_TOO_SMALL;
  1310. }
  1311. RtlCopyMemory(Address, Source, CopySize);
  1312. *AddressLength = TotalSize;
  1313. return Status;
  1314. }
  1315. LIBC_API
  1316. struct cmsghdr *
  1317. __cmsg_nxthdr (
  1318. struct msghdr *Message,
  1319. struct cmsghdr *ControlMessage
  1320. )
  1321. /*++
  1322. Routine Description:
  1323. This routine gets the next control message in the buffer of ancillary data.
  1324. Arguments:
  1325. Message - Supplies a pointer to the beginning of the ancillary data.
  1326. ControlMessage - Supplies the previous control message. This routine
  1327. returns the next control message after this one.
  1328. Return Value:
  1329. Returns a pointer to the control message after the given control message.
  1330. NULL if there are no more messages or the buffer does not contain enough
  1331. space.
  1332. --*/
  1333. {
  1334. PUCHAR End;
  1335. struct cmsghdr *Result;
  1336. if (ControlMessage->cmsg_len < sizeof(struct cmsghdr)) {
  1337. return NULL;
  1338. }
  1339. Result = (struct cmsghdr *)((PUCHAR)ControlMessage +
  1340. CMSG_ALIGN(ControlMessage->cmsg_len));
  1341. End = (PUCHAR)(Message->msg_control) + Message->msg_controllen;
  1342. if (((PUCHAR)(Result + 1) > End) ||
  1343. ((PUCHAR)Result + CMSG_ALIGN(Result->cmsg_len) > End)) {
  1344. return NULL;
  1345. }
  1346. return Result;
  1347. }
  1348. //
  1349. // --------------------------------------------------------- Internal Functions
  1350. //
  1351. int
  1352. ClpGetSocketAddress (
  1353. int Socket,
  1354. SOCKET_BASIC_OPTION Option,
  1355. struct sockaddr *SocketAddress,
  1356. socklen_t *AddressLength
  1357. )
  1358. /*++
  1359. Routine Description:
  1360. This routine returns either the address of the socket itself or the so