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.

212 lines
5.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. LPTSTR
  29. RtlIpv6AddressToStringT(
  30. IN const struct in6_addr *Addr,
  31. OUT LPTSTR S
  32. )
  33. /*++
  34. Routine Description:
  35. Generates an IPv6 string literal corresponding to the address Addr.
  36. The shortened canonical forms are used (RFC 1884 etc).
  37. The basic string representation consists of 8 hex numbers
  38. separated by colons, with a couple embellishments:
  39. - a string of zero numbers (at most one) is replaced
  40. with a double-colon.
  41. - the last 32 bits are represented in IPv4-style dotted-octet notation
  42. if the address is a v4-compatible or ISATAP address.
  43. For example,
  44. ::
  45. ::1
  46. ::157.56.138.30
  47. ::ffff:156.56.136.75
  48. ff01::
  49. ff02::2
  50. 0:1:2:3:4:5:6:7
  51. Arguments:
  52. S - Receives a pointer to the buffer in which to place the
  53. string literal.
  54. Addr - Receives the IPv6 address.
  55. Return Value:
  56. Pointer to the null byte at the end of the string inserted.
  57. This can be used by the caller to easily append more information.
  58. --*/
  59. {
  60. int maxFirst, maxLast;
  61. int curFirst, curLast;
  62. int i;
  63. int endHex = 8;
  64. // Check for IPv6-compatible, IPv4-mapped, and IPv4-translated
  65. // addresses
  66. if ((Addr->s6_words[0] == 0) && (Addr->s6_words[1] == 0) &&
  67. (Addr->s6_words[2] == 0) && (Addr->s6_words[3] == 0) &&
  68. (Addr->s6_words[6] != 0)) {
  69. if ((Addr->s6_words[4] == 0) &&
  70. ((Addr->s6_words[5] == 0) || (Addr->s6_words[5] == 0xffff)))
  71. {
  72. // compatible or mapped
  73. S += _stprintf(S, _T("::%hs%u.%u.%u.%u"),
  74. Addr->s6_words[5] == 0 ? "" : "ffff:",
  75. Addr->s6_bytes[12], Addr->s6_bytes[13],
  76. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  77. return S;
  78. }
  79. else if ((Addr->s6_words[4] == 0xffff) && (Addr->s6_words[5] == 0)) {
  80. // translated
  81. S += _stprintf(S, _T("::ffff:0:%u.%u.%u.%u"),
  82. Addr->s6_bytes[12], Addr->s6_bytes[13],
  83. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  84. return S;
  85. }
  86. }
  87. // Find largest contiguous substring of zeroes
  88. // A substring is [First, Last), so it's empty if First == Last.
  89. maxFirst = maxLast = 0;
  90. curFirst = curLast = 0;
  91. // ISATAP EUI64 starts with 00005EFE (or 02005EFE)...
  92. if (((Addr->s6_words[4] & 0xfffd) == 0) && (Addr->s6_words[5] == 0xfe5e)) {
  93. endHex = 6;
  94. }
  95. for (i = 0; i < endHex; i++) {
  96. if (Addr->s6_words[i] == 0) {
  97. // Extend current substring
  98. curLast = i+1;
  99. // Check if current is now largest
  100. if (curLast - curFirst > maxLast - maxFirst) {
  101. maxFirst = curFirst;
  102. maxLast = curLast;
  103. }
  104. }
  105. else {
  106. // Start a new substring
  107. curFirst = curLast = i+1;
  108. }
  109. }
  110. // Ignore a substring of length 1.
  111. if (maxLast - maxFirst <= 1)
  112. maxFirst = maxLast = 0;
  113. // Write colon-separated words.
  114. // A double-colon takes the place of the longest string of zeroes.
  115. // All zeroes is just "::".
  116. for (i = 0; i < endHex; i++) {
  117. // Skip over string of zeroes
  118. if ((maxFirst <= i) && (i < maxLast)) {
  119. S += _stprintf(S, _T("::"));
  120. i = maxLast-1;
  121. continue;
  122. }
  123. // Need colon separator if not at beginning
  124. if ((i != 0) && (i != maxLast))
  125. S += _stprintf(S, _T(":"));
  126. S += _stprintf(S, _T("%x"), RtlUshortByteSwap(Addr->s6_words[i]));
  127. }
  128. if (endHex < 8) {
  129. S += _stprintf(S, _T(":%u.%u.%u.%u"),
  130. Addr->s6_bytes[12], Addr->s6_bytes[13],
  131. Addr->s6_bytes[14], Addr->s6_bytes[15]);
  132. }
  133. return S;
  134. }
  135. LPTSTR
  136. RtlIpv4AddressToStringT(
  137. IN const struct in_addr *Addr,
  138. OUT LPTSTR S
  139. )
  140. /*++
  141. Routine Description:
  142. Generates an IPv4 string literal corresponding to the address Addr.
  143. Arguments:
  144. S - Receives a pointer to the buffer in which to place the
  145. string literal.
  146. Addr - Receives the IPv4 address.
  147. Return Value:
  148. Pointer to the null byte at the end of the string inserted.
  149. This can be used by the caller to easily append more information.
  150. --*/
  151. {
  152. S += _stprintf(S, _T("%u.%u.%u.%u"),
  153. ( Addr->s_addr >> 0 ) & 0xFF,
  154. ( Addr->s_addr >> 8 ) & 0xFF,
  155. ( Addr->s_addr >> 16 ) & 0xFF,
  156. ( Addr->s_addr >> 24 ) & 0xFF );
  157. return S;
  158. }