Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
6.5 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. str2addt.h
  5. Abstract:
  6. Code file for IP string-to-address translation routines.
  7. Author:
  8. Dave Thaler (dthaler) 3-28-2001
  9. Revision History:
  10. IPv4 conversion code originally from old winsock code
  11. IPv6 conversion code originally by Rich Draves (richdr)
  12. --*/
  13. //
  14. // Define some versions of crt functions which are not affected by locale.
  15. //
  16. #define ISDIGIT(c) (_istascii(c) && _istdigit(c))
  17. #define ISLOWER(c) (_istascii(c) && _istlower(c))
  18. #define ISXDIGIT(c) (_istascii(c) && _istxdigit(c))
  19. NTSTATUS
  20. RtlIpv6StringToAddressExT (
  21. IN LPCTSTR AddressString,
  22. OUT struct in6_addr *Address,
  23. OUT PULONG ScopeId,
  24. OUT PUSHORT Port
  25. )
  26. /*++
  27. Routine Description:
  28. Parsing a human-readable string to Address, port number and scope id.
  29. The syntax is address%scope-id or [address%scope-id]:port, where
  30. the scope-id and port are optional.
  31. Note that since the IPv6 address format uses a varying number
  32. of ':' characters, the IPv4 convention of address:port cannot
  33. be supported without the braces.
  34. Arguments:
  35. AddressString - Points to the zero-terminated human-readable string.
  36. Address - Receive address part (in6_addr) of this address.
  37. ScopeId - Receive scopeid of this address. If there is no scope id in
  38. the address string, 0 is returned.
  39. Port - Receive port number of this address. If there is no port number
  40. in the string, 0 is returned. Port is returned in network byte order.
  41. Return Value:
  42. NT_STATUS - STATUS_SUCCESS if successful, NT error code if not.
  43. --*/
  44. {
  45. LPTSTR Terminator;
  46. ULONG TempScopeId;
  47. USHORT TempPort;
  48. TCHAR Ch;
  49. BOOLEAN ExpectBrace;
  50. //
  51. // Quick sanity checks.
  52. //
  53. if ((AddressString == NULL) ||
  54. (Address == NULL) ||
  55. (ScopeId == NULL) ||
  56. (Port == NULL)) {
  57. return STATUS_INVALID_PARAMETER;
  58. }
  59. TempPort = 0;
  60. TempScopeId = 0;
  61. ExpectBrace = FALSE;
  62. if (*AddressString == _T('[')) {
  63. ExpectBrace = TRUE;
  64. AddressString++;
  65. }
  66. if (!NT_SUCCESS(RtlIpv6StringToAddressT(AddressString,
  67. &Terminator,
  68. Address))) {
  69. return STATUS_INVALID_PARAMETER;
  70. }
  71. //
  72. // We have parsed the address, check for a scope-id.
  73. //
  74. if (*Terminator == _T('%')) {
  75. Terminator++;
  76. Ch = *Terminator;
  77. if (!ISDIGIT(Ch)) {
  78. return STATUS_INVALID_PARAMETER;
  79. }
  80. while ((Ch != 0) && (Ch != _T(']'))) {
  81. if (!ISDIGIT(Ch)) {
  82. return STATUS_INVALID_PARAMETER;
  83. }
  84. TempScopeId = 10*TempScopeId + (Ch - _T('0'));
  85. Terminator++;
  86. Ch = *Terminator;
  87. }
  88. }
  89. //
  90. // When we come here, the current char should either be the
  91. // end of the string or ']' if expectbrace is true.
  92. //
  93. if (*Terminator == _T(']')) {
  94. if (!ExpectBrace) {
  95. return STATUS_INVALID_PARAMETER;
  96. }
  97. ExpectBrace = FALSE;
  98. Terminator++;
  99. //
  100. // See if we have a port to parse.
  101. //
  102. if (*Terminator == _T(':')) {
  103. USHORT Base;
  104. Terminator++;
  105. Base = 10;
  106. if (*Terminator == _T('0')) {
  107. Base = 8;
  108. Terminator++;
  109. if (*Terminator == _T('x')) {
  110. Base = 16;
  111. Terminator++;
  112. }
  113. }
  114. Ch = *Terminator;
  115. while (Ch != 0) {
  116. if (ISDIGIT(Ch) && (Ch - _T('0')) < Base) {
  117. TempPort = (TempPort * Base) + (Ch - _T('0'));
  118. } else if (Base == 16 && ISXDIGIT(Ch)) {
  119. TempPort = (TempPort << 4);
  120. TempPort += Ch + 10 - (ISLOWER(Ch)? _T('a') : _T('A'));
  121. } else {
  122. return STATUS_INVALID_PARAMETER;
  123. }
  124. Terminator++;
  125. Ch = *Terminator;
  126. }
  127. }
  128. }
  129. //
  130. // We finished parsing address, scope id and port number. We are expecting the
  131. // end of the string.
  132. //
  133. if ((*Terminator != 0) || ExpectBrace) {
  134. return STATUS_INVALID_PARAMETER;
  135. }
  136. //
  137. // Now construct the address.
  138. //
  139. *Port = RtlUshortByteSwap(TempPort);
  140. *ScopeId = TempScopeId;
  141. return STATUS_SUCCESS;
  142. }
  143. NTSTATUS
  144. RtlIpv4StringToAddressExT (
  145. IN LPCTSTR AddressString,
  146. OUT struct in_addr *Address,
  147. OUT PUSHORT Port
  148. )
  149. /*++
  150. Routine Description:
  151. Parsing a human-readable string to in_addr and port number.
  152. Arguments:
  153. AddressString - Points to the zero-terminated human-readable string.
  154. Address - Receives the address (in_addr) itself.
  155. Port - Receives port number. 0 is returned if there is no port number.
  156. Port is returned in network byte order.
  157. Return Value:
  158. NTSTATUS - STATUS_SUCCESS if successful, error code if not.
  159. --*/
  160. {
  161. LPTSTR Terminator;
  162. USHORT TempPort;
  163. if ((AddressString == NULL) ||
  164. (Address == NULL) ||
  165. (Port == NULL)) {
  166. return STATUS_INVALID_PARAMETER;
  167. }
  168. if (!NT_SUCCESS(RtlIpv4StringToAddressT(AddressString,
  169. FALSE,
  170. &Terminator,
  171. Address))) {
  172. return STATUS_INVALID_PARAMETER;
  173. }
  174. if (*((ULONG*)Address) == INADDR_NONE) {
  175. return STATUS_INVALID_PARAMETER;
  176. }
  177. if (*Terminator == _T(':')) {
  178. TCHAR Ch;
  179. USHORT Base;
  180. Terminator++;
  181. TempPort = 0;
  182. Base = 10;
  183. if (*Terminator == _T('0')) {
  184. Base = 8;
  185. Terminator++;
  186. if (*Terminator == _T('x')) {
  187. Base = 16;
  188. Terminator++;
  189. }
  190. }
  191. while (Ch = *Terminator++) {
  192. if (ISDIGIT(Ch) && (USHORT)(Ch-_T('0')) < Base) {
  193. TempPort = (TempPort * Base) + (Ch - _T('0'));
  194. } else if (Base == 16 && ISXDIGIT(Ch)) {
  195. TempPort = TempPort << 4;
  196. TempPort += Ch + 10 - (ISLOWER(Ch) ? _T('a') : _T('A'));
  197. } else {
  198. return STATUS_INVALID_PARAMETER;
  199. }
  200. }
  201. } else if (*Terminator == 0) {
  202. TempPort = 0;
  203. } else {
  204. return STATUS_INVALID_PARAMETER;
  205. }
  206. *Port = RtlUshortByteSwap(TempPort);
  207. return STATUS_SUCCESS;
  208. }