|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
add2strt.h
Abstract:
Code for IP address-to-string translation routines.
Author:
Dave Thaler (dthaler) 3-28-2001
Revision History:
IPv6 conversion code originally by Rich Draves (richdr)
--*/
struct in6_addr { union { UCHAR Byte[16]; USHORT Word[8]; } u; }; #define s6_bytes u.Byte
#define s6_words u.Word
struct in_addr { union { struct { UCHAR s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { USHORT s_w1,s_w2; } S_un_w; ULONG S_addr; } S_un; }; #define s_addr S_un.S_addr
LPTSTR RtlIpv6AddressToStringT( IN const struct in6_addr *Addr, OUT LPTSTR S )
/*++
Routine Description:
Generates an IPv6 string literal corresponding to the address Addr. The shortened canonical forms are used (RFC 1884 etc). The basic string representation consists of 8 hex numbers separated by colons, with a couple embellishments: - a string of zero numbers (at most one) is replaced with a double-colon. - the last 32 bits are represented in IPv4-style dotted-octet notation if the address is a v4-compatible or ISATAP address.
For example, :: ::1 ::157.56.138.30 ::ffff:156.56.136.75 ff01:: ff02::2 0:1:2:3:4:5:6:7
Arguments:
S - Receives a pointer to the buffer in which to place the string literal.
Addr - Receives the IPv6 address.
Return Value:
Pointer to the null byte at the end of the string inserted. This can be used by the caller to easily append more information.
--*/
{ int maxFirst, maxLast; int curFirst, curLast; int i; int endHex = 8;
// Check for IPv6-compatible, IPv4-mapped, and IPv4-translated
// addresses
if ((Addr->s6_words[0] == 0) && (Addr->s6_words[1] == 0) && (Addr->s6_words[2] == 0) && (Addr->s6_words[3] == 0) && (Addr->s6_words[6] != 0)) { if ((Addr->s6_words[4] == 0) && ((Addr->s6_words[5] == 0) || (Addr->s6_words[5] == 0xffff))) { // compatible or mapped
S += _stprintf(S, _T("::%hs%u.%u.%u.%u"), Addr->s6_words[5] == 0 ? "" : "ffff:", Addr->s6_bytes[12], Addr->s6_bytes[13], Addr->s6_bytes[14], Addr->s6_bytes[15]); return S; } else if ((Addr->s6_words[4] == 0xffff) && (Addr->s6_words[5] == 0)) { // translated
S += _stprintf(S, _T("::ffff:0:%u.%u.%u.%u"), Addr->s6_bytes[12], Addr->s6_bytes[13], Addr->s6_bytes[14], Addr->s6_bytes[15]); return S; } }
// Find largest contiguous substring of zeroes
// A substring is [First, Last), so it's empty if First == Last.
maxFirst = maxLast = 0; curFirst = curLast = 0;
// ISATAP EUI64 starts with 00005EFE (or 02005EFE)...
if (((Addr->s6_words[4] & 0xfffd) == 0) && (Addr->s6_words[5] == 0xfe5e)) { endHex = 6; }
for (i = 0; i < endHex; i++) {
if (Addr->s6_words[i] == 0) { // Extend current substring
curLast = i+1;
// Check if current is now largest
if (curLast - curFirst > maxLast - maxFirst) {
maxFirst = curFirst; maxLast = curLast; } } else { // Start a new substring
curFirst = curLast = i+1; } }
// Ignore a substring of length 1.
if (maxLast - maxFirst <= 1) maxFirst = maxLast = 0;
// Write colon-separated words.
// A double-colon takes the place of the longest string of zeroes.
// All zeroes is just "::".
for (i = 0; i < endHex; i++) {
// Skip over string of zeroes
if ((maxFirst <= i) && (i < maxLast)) {
S += _stprintf(S, _T("::")); i = maxLast-1; continue; }
// Need colon separator if not at beginning
if ((i != 0) && (i != maxLast)) S += _stprintf(S, _T(":"));
S += _stprintf(S, _T("%x"), RtlUshortByteSwap(Addr->s6_words[i])); }
if (endHex < 8) { S += _stprintf(S, _T(":%u.%u.%u.%u"), Addr->s6_bytes[12], Addr->s6_bytes[13], Addr->s6_bytes[14], Addr->s6_bytes[15]); }
return S; }
LPTSTR RtlIpv4AddressToStringT( IN const struct in_addr *Addr, OUT LPTSTR S )
/*++
Routine Description:
Generates an IPv4 string literal corresponding to the address Addr.
Arguments:
S - Receives a pointer to the buffer in which to place the string literal.
Addr - Receives the IPv4 address.
Return Value:
Pointer to the null byte at the end of the string inserted. This can be used by the caller to easily append more information.
--*/
{ S += _stprintf(S, _T("%u.%u.%u.%u"), ( Addr->s_addr >> 0 ) & 0xFF, ( Addr->s_addr >> 8 ) & 0xFF, ( Addr->s_addr >> 16 ) & 0xFF, ( Addr->s_addr >> 24 ) & 0xFF );
return S; }
|