Leaked source code of windows server 2003
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.

364 lines
9.1 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. add2strt.h
  5. Abstract:
  6. Code for IP address-to-string translation routines.
  7. Author:
  8. Dave Thaler (dthaler) 3-28-2001
  9. Revision History:
  10. IPv6 conversion code originally by Rich Draves (richdr)
  11. --*/
  12. struct in6_addr {
  13. union {
  14. UCHAR Byte[16];
  15. USHORT Word[8];
  16. } u;
  17. };
  18. #define s6_bytes u.Byte
  19. #define s6_words u.Word
  20. struct in_addr {
  21. union {
  22. struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b;
  23. struct { USHORT s_w1,s_w2; } S_un_w;
  24. ULONG S_addr;
  25. } S_un;
  26. };
  27. #define s_addr S_un.S_addr
  28. #define AF_INET 2
  29. #define AF_INET6 23
  30. #define INET_ADDRSTRLEN 22
  31. #define INET6_ADDRSTRLEN 65
  32. LPTSTR
  33. RtlIpv6AddressToStringT(
  34. IN const struct in6_addr *Addr,
  35. OUT LPTSTR S
  36. )
  37. /*++
  38. Routine Description:
  39. Generates an IPv6 string literal corresponding to the address Addr.
  40. The shortened canonical forms are used (RFC 1884 etc).
  41. The basic string representation consists of 8 hex numbers
  42. separated by colons, with a couple embellishments:
  43. - a string of zero numbers (at most one) is replaced
  44. with a double-colon.
  45. - the last 32 bits are represented in IPv4-style dotted-octet notation
  46. if the address is a v4-compatible or ISATAP address.
  47. For example,
  48. ::
  49. ::1
  50. ::157.56.138.30
  51. ::ffff:156.56.136.75
  52. ff01::
  53. ff02::2
  54. 0:1:2:3:4:5:6:7
  55. Arguments:
  56. S - Receives a pointer to the buffer in which to place the
  57. string literal.
  58. Addr - Receives the IPv6 address.
  59. Return Value:
  60. Pointer to the null byte at the end of the string inserted.
  61. This can be used by the caller to easily append more information.
  62. --*/
  63. {
  64. int maxFirst, maxLast;
  65. int curFirst, curLast;
  66. int i;
  67. int endHex = 8;
  68. // Check for IPv6-compatible, IPv4-mapped, and IPv4-translated
  69. // addresses
  70. if ((Addr->s6_words[0] == 0) && (Addr->s6_words[1] == 0) &&
  71. (Addr->s6_words[2] == 0) && (Addr->s6_words[3] == 0) &&
  72. (Addr->s6_words[6] != 0)) {
  73. if ((Addr->s6_words[4] == 0) &&
  74. ((Addr->s6_words[5] == 0) || (Addr->s6_words[5] == 0xffff)))
  75. {
  76. // compatible or mapped
  77. S += _stprintf(S, _T("::%hs%u.%u.%u.%u"),
  78. Addr->s6_words[5] == 0 ? "" : "ffff:",
  79. Addr->s6_bytes[12], Addr->s6_bytes[13],
  80. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  81. return S;
  82. }
  83. else if ((Addr->s6_words[4] == 0xffff) && (Addr->s6_words[5] == 0)) {
  84. // translated
  85. S += _stprintf(S, _T("::ffff:0:%u.%u.%u.%u"),
  86. Addr->s6_bytes[12], Addr->s6_bytes[13],
  87. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  88. return S;
  89. }
  90. }
  91. // Find largest contiguous substring of zeroes
  92. // A substring is [First, Last), so it's empty if First == Last.
  93. maxFirst = maxLast = 0;
  94. curFirst = curLast = 0;
  95. // ISATAP EUI64 starts with 00005EFE (or 02005EFE)...
  96. if (((Addr->s6_words[4] & 0xfffd) == 0) && (Addr->s6_words[5] == 0xfe5e)) {
  97. endHex = 6;
  98. }
  99. for (i = 0; i < endHex; i++) {
  100. if (Addr->s6_words[i] == 0) {
  101. // Extend current substring
  102. curLast = i+1;
  103. // Check if current is now largest
  104. if (curLast - curFirst > maxLast - maxFirst) {
  105. maxFirst = curFirst;
  106. maxLast = curLast;
  107. }
  108. }
  109. else {
  110. // Start a new substring
  111. curFirst = curLast = i+1;
  112. }
  113. }
  114. // Ignore a substring of length 1.
  115. if (maxLast - maxFirst <= 1)
  116. maxFirst = maxLast = 0;
  117. // Write colon-separated words.
  118. // A double-colon takes the place of the longest string of zeroes.
  119. // All zeroes is just "::".
  120. for (i = 0; i < endHex; i++) {
  121. // Skip over string of zeroes
  122. if ((maxFirst <= i) && (i < maxLast)) {
  123. S += _stprintf(S, _T("::"));
  124. i = maxLast-1;
  125. continue;
  126. }
  127. // Need colon separator if not at beginning
  128. if ((i != 0) && (i != maxLast))
  129. S += _stprintf(S, _T(":"));
  130. S += _stprintf(S, _T("%x"), RtlUshortByteSwap(Addr->s6_words[i]));
  131. }
  132. if (endHex < 8) {
  133. S += _stprintf(S, _T(":%u.%u.%u.%u"),
  134. Addr->s6_bytes[12], Addr->s6_bytes[13],
  135. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  136. }
  137. return S;
  138. }
  139. NTSTATUS
  140. RtlIpv6AddressToStringExT(
  141. IN const struct in6_addr *Address,
  142. IN ULONG ScopeId,
  143. IN USHORT Port,
  144. OUT LPTSTR AddressString,
  145. IN OUT PULONG AddressStringLength
  146. )
  147. /*++
  148. Routine Description:
  149. This is the extension routine which handles a full address conversion
  150. including address, scopeid and port (scopeid and port are optional).
  151. Arguments:
  152. Address - The address part to be translated.
  153. ScopeId - The Scope ID of the address (optional).
  154. Port - The port number of the address (optional).
  155. Port is in network byte order.
  156. AddressString - Pointer to output buffer where we will fill in address string.
  157. AddressStringLength - For input, it is the length of the input buffer; for
  158. output it is the length we actual returned.
  159. Return Value:
  160. STATUS_SUCCESS if the operation is successful, error code otherwise.
  161. --*/
  162. {
  163. TCHAR String[INET6_ADDRSTRLEN];
  164. LPTSTR S;
  165. ULONG Length;
  166. if ((Address == NULL) ||
  167. (AddressString == NULL) ||
  168. (AddressStringLength == NULL)) {
  169. return STATUS_INVALID_PARAMETER;
  170. }
  171. S = String;
  172. if (Port) {
  173. S += _stprintf(S, _T("["));
  174. }
  175. //
  176. // Now translate this address.
  177. //
  178. S = RtlIpv6AddressToStringT(Address, S);
  179. if (ScopeId != 0) {
  180. S += _stprintf(S, _T("%%%u"), ScopeId);
  181. }
  182. if (Port != 0) {
  183. S += _stprintf(S, _T("]:%u"), RtlUshortByteSwap(Port));
  184. }
  185. Length = (ULONG)(S - String + 1);
  186. if (*AddressStringLength < Length) {
  187. //
  188. // Before return, tell the caller how big
  189. // the buffer we need.
  190. //
  191. *AddressStringLength = Length;
  192. return STATUS_INVALID_PARAMETER;
  193. }
  194. *AddressStringLength = Length;
  195. RtlCopyMemory(AddressString, String, Length * sizeof(TCHAR));
  196. return STATUS_SUCCESS;
  197. }
  198. LPTSTR
  199. RtlIpv4AddressToStringT(
  200. IN const struct in_addr *Addr,
  201. OUT LPTSTR S
  202. )
  203. /*++
  204. Routine Description:
  205. Generates an IPv4 string literal corresponding to the address Addr.
  206. Arguments:
  207. S - Receives a pointer to the buffer in which to place the
  208. string literal.
  209. Addr - Receives the IPv4 address.
  210. Return Value:
  211. Pointer to the null byte at the end of the string inserted.
  212. This can be used by the caller to easily append more information.
  213. --*/
  214. {
  215. S += _stprintf(S, _T("%u.%u.%u.%u"),
  216. ( Addr->s_addr >> 0 ) & 0xFF,
  217. ( Addr->s_addr >> 8 ) & 0xFF,
  218. ( Addr->s_addr >> 16 ) & 0xFF,
  219. ( Addr->s_addr >> 24 ) & 0xFF );
  220. return S;
  221. }
  222. NTSTATUS
  223. RtlIpv4AddressToStringExT(
  224. IN const struct in_addr *Address,
  225. IN USHORT Port,
  226. OUT LPTSTR AddressString,
  227. IN OUT PULONG AddressStringLength
  228. )
  229. /*++
  230. Routine Description:
  231. This is the extension routine which handles a full address conversion
  232. including address and port (port is optional).
  233. Arguments:
  234. Address - The address part to translate.
  235. Port - Port number if there is any, otherwise 0. Port is in network
  236. byte order.
  237. AddressString - Receives the formatted address string.
  238. AddressStringLength - On input, contains the length of AddressString.
  239. On output, contains the number of characters actually written
  240. to AddressString.
  241. Return Value:
  242. STATUS_SUCCESS if the operation is successful, error code otherwise.
  243. --*/
  244. {
  245. TCHAR String[INET_ADDRSTRLEN];
  246. LPTSTR S;
  247. ULONG Length;
  248. //
  249. // Quick sanity checks.
  250. //
  251. if ((Address == NULL) ||
  252. (AddressString == NULL) ||
  253. (AddressStringLength == NULL)) {
  254. return STATUS_INVALID_PARAMETER;
  255. }
  256. S = String;
  257. //
  258. // Now translate this address.
  259. //
  260. S = RtlIpv4AddressToStringT(Address, S);
  261. if (Port != 0) {
  262. S += _stprintf(S, _T(":%u"), RtlUshortByteSwap(Port));
  263. }
  264. Length = (ULONG)(S - String + 1);
  265. if (*AddressStringLength < Length) {
  266. //
  267. // Before return, tell the caller how big
  268. // the buffer we need.
  269. //
  270. *AddressStringLength = Length;
  271. return STATUS_INVALID_PARAMETER;
  272. }
  273. RtlCopyMemory(AddressString, String, Length * sizeof(TCHAR));
  274. *AddressStringLength = Length;
  275. return STATUS_SUCCESS;
  276. }