// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// in_addr.cpp - IPv6/IPv4 socket library
//
#include <in_sock.h>
#include "in6_opt.h"
//
// DLL entry point
//
const TInt KIPv4AddressPartCount = 4;
//
//
// *************************************
// Primitive methods on raw IPv6 Address
// *************************************
// (some could be inlined later)
//
EXPORT_C TBool TIp6Addr::IsUnicast() const
/**
* Tests if the address is IPv6 unicast.
* @return
* ETrue, if the address is unicast (not IPv6 unspecified or multicast);
* EFalse, otherwise.
* @since 7.0
*/
{
return !(IsMulticast() || IsUnspecified());
}
EXPORT_C TBool TIp6Addr::IsMulticast() const
/**
* Tests if the IPv6 address is multicast.
* @return
* ETrue, if the IP address value is IPv6 multicast (<tt>ff00::/8</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
return u.iAddr8[0] == 0xFF;
}
EXPORT_C TBool TIp6Addr::IsLoopback() const
/**
* Tests if the address is IPv6 loopback.
* @return
* ETrue, if the address is loopback (<tt>::1</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
const union {TUint8 a[4]; TUint32 b;} one = { {0, 0, 0, 1} };
return
u.iAddr32[0] == 0 &&
u.iAddr32[1] == 0 &&
u.iAddr32[2] == 0 &&
u.iAddr32[3] == one.b;
}
EXPORT_C TBool TIp6Addr::IsUnspecified() const
/**
* Tests if the address is IPv6 unspecified.
* @return
* ETrue, if the IP address value is zero (= <tt>::</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
return
u.iAddr32[0] == 0 &&
u.iAddr32[1] == 0 &&
u.iAddr32[2] == 0 &&
u.iAddr32[3] == 0;
}
EXPORT_C TBool TIp6Addr::IsLinkLocal() const
/**
* Tests if the address is an IPv6 link-local address.
* @return
* ETrue, if this address is an IPv6 link-local address (<tt>fe80::/10</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
return u.iAddr8[0] == 0xFE && (u.iAddr8[1] & 0xC0) == 0x80;
}
EXPORT_C TBool TIp6Addr::IsSiteLocal() const
/**
* Tests if this address is an IPv6 site-local address (fec0::/10).
* @return
* ETrue, if this is an IPv6 site-local address (<tt>fec0::/10</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
return u.iAddr8[0] == 0xFE && (u.iAddr8[1] & 0xC0) == 0xC0;
}
EXPORT_C TBool TIp6Addr::IsV4Compat() const
/**
* Tests if this address is an IPv4-compatible address.
*
* @note
* returns EFalse for <tt>::0.0.0.0</tt> (= <tt>::</tt>) and
* <tt>::0.0.0.1</tt> (= <tt>::1</tt>).
*
* @return
* ETrue, if this is a IPv4-compatible address (<tt>::x.x.x.x</tt>);
* EFalse, otherwise.
* @deprecated
* @since 7.0
*/
{
// Note: This must return false for true IPv6 "::" and "::1".
const union {TUint8 a[4]; TUint32 b;} one = { {0, 0, 0, 1} };
return
u.iAddr32[0] == 0 &&
u.iAddr32[1] == 0 &&
u.iAddr32[2] == 0 &&
u.iAddr32[3] != 0 &&
u.iAddr32[3] != one.b;
}
EXPORT_C TBool TIp6Addr::IsV4Mapped() const
/**
* Tests if this address is an IPv4-mapped address.
* @return
* ETrue, if this address is an IPv4-mapped address (<tt>::ffff:x.x.x.x</tt>);
* EFalse, otherwise.
* @since 7.0
*/
{
const union {TUint8 a[4]; TUint32 b;} v4Prefix = { {0, 0, 0xff, 0xff} };
return
u.iAddr32[0] == 0 &&
u.iAddr32[1] == 0 &&
u.iAddr32[2] == v4Prefix.b;
}
EXPORT_C TBool TIp6Addr::IsEqual(const TIp6Addr &aAddr) const
/**
* Tests if two addresses are equal.
*
* @param aAddr
* Address to compare with
* @return
* ETrue, if the addresses are equal;
* EFalse, otherwise.
* @since 7.0
*/
{
return
u.iAddr32[3] == aAddr.u.iAddr32[3] &&
u.iAddr32[2] == aAddr.u.iAddr32[2] &&
u.iAddr32[1] == aAddr.u.iAddr32[1] &&
u.iAddr32[0] == aAddr.u.iAddr32[0];
}
EXPORT_C TInt TIp6Addr::Match(const TIp6Addr &aAddr) const
/**
* Compares two raw IPv6 addresses from left to right and returns
* the number of bits that match.
*
* @param aAddr
* Address to compare with
* @return
* The number of bits that match (the common prefix length).
* @since 7.0
*/
{
TInt i = 0;
while (u.iAddr32[i] == aAddr.u.iAddr32[i])
if (++i == 4)
return 128;
i <<= 1;
if (u.iAddr16[i] == aAddr.u.iAddr16[i])
i++;
i <<= 1;
if (u.iAddr8[i] == aAddr.u.iAddr8[i])
i++;
TUint8 diff = (TUint8)(u.iAddr8[i] ^ aAddr.u.iAddr8[i]);
for (i <<= 3; !(diff & 0x80); diff <<= 1)
i++;
return i;
}
EXPORT_C TInt TIp6Addr::Scope() const
/**
* Return the scope level of the addres.
*
* All IP addresses (IPv4 and IPv6) have a scope level as defined by
* this function. The scope level is a positive integer in range [1..16].
*
* This function may also return 0, which is an invalid level. This can
* happen only, because IPv6 multicast addresses specify their scope
* level explicitly.
*
* The scope level determines the interpretation of the scope identifier
* in TInetAddr (see TInetAddr::Scope(), TInetAddr::SetScope()).
*
* Each network interface has a vector of 16 scope identifiers. The scope
* identifier in the destination address selects a subset of the possible
* interfaces: only the interfaces which have the correct matching scope
* identifier in the vector entry matching the scope level, are valid
* destinations for that address.
*
* The scope level of an IP address is computed as follows:
*
* @li <tt>ffyz::/10</tt>
* -- IPv6 multicast addressess, the scope level is extracted from the address (= z)
* @li <tt>fe80::/10</tt>
* -- IPv6 link local addresses, return KIp6AddrScopeLinkLocal
* @li <tt>fec0::/10</tt>
* -- IPv6 site local addresses, return KIp6AddrScopeSiteLocal
* @li <tt>::1/128</tt>
* -- IPv6 loopback address, return KIp6AddrScopeNodeLocal
* @li <tt>::/128</tt>
* -- IPv6 unspecified address, return KIp6AddrScopeNodeLocal
* @li <tt> ::ffff:0.0.0.0</tt>
* -- IPv4 unspecified address, return KIp6AddrScopeNodeLocal
* @li <tt>::ffff:169.254.x.x/112</tt>
* -- IPv4 link local range, return KIp6AddrScopeLinkLocal
* @li <tt>::ffff:224.0.0.x/120</tt>
* -- IPv4 link local multicast range, return KIp6AddrScopeLinkLocal
* @li <tt>::ffff:127.x.x.x/104</tt>
* -- IPv4 loopback addresses, return KIp6AddrScopeNodeLocal
* @li <tt>::ffff:0.0.0.0/96</tt>
* -- all other IPv4 addresses, return KIp6AddrScopeNetwork
* @li None of the above
* -- assume global IPv6 addresses, return KIp6AddrScopeGlobal
*
* @return
* The scope value of the address (e.g. #KIp6AddrScopeNodeLocal,
* #KIp6AddrScopeLinkLocal, #KIp6AddrScopeSiteLocal,
* #KIp6AddrScopeOrganization, #KIp6AddrScopeGlobal or
* #KIp6AddrScopeNetwork).
* @since 7.0
*/
{
if (u.iAddr8[0] == 0xFF)
return u.iAddr8[1] & 0x0F; // Multicast scope is explicit in the address.
//
// Other addresses must be mapped "by hand"
//
if (u.iAddr8[0] == 0x00)
{
const union {TUint8 a[2]; TUint16 b;} ipv4_linklocal = { {169, 254} };
const union {TUint8 a[4]; TUint32 b;} ipv4_linklocal_mc = { {224, 0, 0, 0} };
const union {TUint8 a[4]; TUint32 b;} ipv4_linklocal_mc_mask = { {255, 255, 255, 0} };
if (IsLoopback())
return KIp6AddrScopeNodeLocal;// Loopback ==> Node Local Scope
if (IsUnspecified())
return KIp6AddrScopeNodeLocal;// Return Node Local for unspecified address
if (IsV4Mapped())
{
if (u.iAddr16[6] == ipv4_linklocal.b)
return KIp6AddrScopeLinkLocal;// IPv4 Link local (169.254/16)
else if ((u.iAddr32[3] & ipv4_linklocal_mc_mask.b) == ipv4_linklocal_mc.b)
return KIp6AddrScopeLinkLocal;
else if (u.iAddr8[12] == 127 || u.iAddr32[3] == 0)
return KIp6AddrScopeNodeLocal;// IPv4 Loopback (127.0/8) and 0.0.0.0
return KIp6AddrScopeNetwork;// all other IPv4 addresses
}
}
else if (u.iAddr8[0] == 0xFE)
{
if ((u.iAddr8[1] & 0xC0) == 0x80)
return KIp6AddrScopeLinkLocal;// Link Local ==> Link Local Scope
else if ((u.iAddr8[1] & 0xC0) == 0xC0)
return KIp6AddrScopeSiteLocal;// Site Local ==> Site Local Scope
// Fall through to global scope
}
//
// All rest and unassigned ranges are treated as Global Scope
//
return KIp6AddrScopeGlobal;
}
//
//
// ********************************
// Actual TInetAddr implementation
// ********************************
//
EXPORT_C void TInetAddr::Init(TUint aFamily)
/**
* Initialises the object properly according to the address family
* passed in.
*
* @param aFamily The address family. Valid values are
* @li #KAfInet,
* plain IPv4 address format
* @li #KAfInet6,
* combined IPv4 and IPv6 format, including fields for the scope id and
* flow label.
* @li anything else,
* initialized to KAFUnspec, with empty content.
*
* @post
* In all above cases, IsUnspecified() returns ETrue after
* this function.
* @since 7.0
*/
{
if (aFamily == KAfInet)
SetUserLen(sizeof(SInetAddr));
else if (aFamily == KAfInet6)
SetUserLen(sizeof(SInet6Addr));
else
{
SetUserLen(0);
aFamily = KAFUnspec;
}
SetFamily(aFamily);
// Always clear the IPv6 address variant, it is also
// sufficient for IPv4 (even though a bit overkill).
// For IPv6 this means that Scope and Flow Label
// are zeroed.
Mem::FillZ(UserPtr(), sizeof(SInet6Addr));
}
EXPORT_C TInetAddr::TInetAddr()
: TSockAddr(KAFUnspec)
/**
* Constructs a basic TInetAddr object.
*
* The port is initialised to 0, and the IP address is unspecified.
* The resulting address family is KAFUnspec.
*/
{
SetPort(KInetPortNone);
}
EXPORT_C TInetAddr::TInetAddr(const TSockAddr &aAddr) : TSockAddr(aAddr)
/**
* Constructs a TInetAddr from a TSockAddr.
*
* The port and IP address values are copied from aAddr.
* The resulting address family is same as that of aAddr.
*
* The function does a raw copy operation of the TSockAddr.
* No checks are made at this point.
*
* @param aAddr TSockAddr to be used as initial content.
*/
{
}
EXPORT_C TInetAddr::TInetAddr(TUint aPort)
: TSockAddr(KAFUnspec)
/**
* Constructs a TInetAddr and initialises the port to the specified value,
* and the IP address is unspecified.
*
* The resulting address family is KAFUnspec.
*
* @param aPort Value to which to set the port.
*/
{
SetPort(aPort);
}
EXPORT_C TInetAddr::TInetAddr(TUint32 aAddr, TUint aPort)
/**
* Constructs a TInetAddr and initialise the specified port value
* to aPort and the IP address to aAddr.
*
* The resulting address family is #KAfInet
*
* @param aAddr Value to which to set the IP address.
* @param aPort Value to which to set the port.
*/
{
Init(KAfInet);
SetPort(aPort);
Addr4Ptr()->iAddr = aAddr;
}
EXPORT_C TInetAddr::TInetAddr(const TIp6Addr& aAddr, TUint aPort)
/**
* Constructs a TInetAddr and initialises the port to the
* specified value, and the IPv6 address to aAddr.
*
* The resulting address family is #KAfInet6.
*
* @param aAddr Value to which to set the IPv6 address.
* @param aPort Value to which to set the port.
* @since 7.0
*/
{
Init(KAfInet6);
AddrPtr()->iAddr = aAddr;
SetPort(aPort);
}
EXPORT_C void TInetAddr::SetAddress(TUint32 aAddr)
/**
* Sets the IPv4 address value.
*
* @note
* An IP address in dotted-decimal form can be converted into
* a TUint32 by the INET_ADDR macro.
*
* The resulting address family is #KAfInet.
*
* @param aAddr Value to which to set the IPv4 address.
*/
{
Init(KAfInet);
Addr4Ptr()->iAddr = aAddr;
}
EXPORT_C void TInetAddr::SetAddress(const TIp6Addr &aAddr)
/**
* Sets the IPv6 address value.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
*
* @param aAddr Value to which to set the IPv6 address.
* @since 7.0
*/
{
Init(KAfInet6);
AddrPtr()->iAddr = aAddr;
}
EXPORT_C void TInetAddr::SetV4CompatAddress(TUint32 aAddr)
/**
* Creates an IPv4-compatible IPv6 address.
*
* The <em>IPv4-compatible format</em> is <tt>::x.x.x.x</tt>.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
*
* @param aAddr IPv4 address from which the IPv6 address is generated.
*
* @deprecated This address format is deprecated and should not be used.
* @since 7.0
*/
{
Init(KAfInet6);
struct SInet6Addr *const a = AddrPtr();
a->iAddr.u.iAddr32[0] = 0;
a->iAddr.u.iAddr32[1] = 0;
a->iAddr.u.iAddr32[2] = 0;
a->iAddr.u.iAddr8[12] = (TUint8)(aAddr >> 24);
a->iAddr.u.iAddr8[13] = (TUint8)(aAddr >> 16);
a->iAddr.u.iAddr8[14] = (TUint8)(aAddr >> 8);
a->iAddr.u.iAddr8[15] = (TUint8)aAddr;
}
EXPORT_C void TInetAddr::SetV4MappedAddress(TUint32 aAddr)
/**
* Creates an IPv4-mapped IPv6 address.
*
* The <em>IPv4-mapped format</em> is <tt>::ffff:x.x.x.x</tt>. Internally, all
* IPv4 addresses are stored in this format.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
*
* @param aAddr IPv4 address from which the IPv6 address is generated.
* @since 7.0
*/
{
Init(KAfInet6);
const union {TUint8 a[4]; TUint32 b;} cpatPrefix = { {0, 0, 0xff, 0xff} };
struct SInet6Addr *const a = AddrPtr();
a->iAddr.u.iAddr32[0] = 0;
a->iAddr.u.iAddr32[1] = 0;
a->iAddr.u.iAddr32[2] = cpatPrefix.b;
a->iAddr.u.iAddr8[12] = (TUint8)(aAddr >> 24);
a->iAddr.u.iAddr8[13] = (TUint8)(aAddr >> 16);
a->iAddr.u.iAddr8[14] = (TUint8)(aAddr >> 8);
a->iAddr.u.iAddr8[15] = (TUint8)aAddr;
}
EXPORT_C void TInetAddr::ConvertToV4Compat()
/**
* Converts an IPv4 address to an IPv4-compatible IPv6 address.
*
* The function assumes that the previous content is IPv4 address and
* accesses this using TInetAddr::Address() function. If the previous
* content was not IPv4 address (in any format), function acts as if
* the old content was <tt>0.0.0.0</tt>.
*
* The <em>IPv4-compatible format</em> is <tt>::x.x.x.x</tt>.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
*
* @deprecated This address format is deprecated and should not be used.
* @since 7.0
*/
{
SetV4CompatAddress(Address());
}
EXPORT_C void TInetAddr::ConvertToV4Mapped()
/**
* Converts an IPv4 address to an IPv4-mapped IPv6 address.
*
* The function assumes that the previous content is IPv4 address and
* accesses this using TInetAddr::Address() function. If the previous
* content was not IPv4 address (in any format), function acts as if
* the old content was "0.0.0.0".
*
* The <em>IPv4-mapped format</em> is <tt>::ffff:x.x.x.x</tt>. Internally, all
* IPv4 addresses are stored in this format.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
* @since 7.0
*/
{
SetV4MappedAddress(Address());
}
EXPORT_C void TInetAddr::ConvertToV4()
/**
* Converts an IPv4-mapped or IPv4-comptatible address to IPv4.
*
* The function assumes that the previous content is IPv4 address
* and accesses this using TInetAddr::Address()
* function. If the previous content was not IPv4 address (in any format),
* function acts as if the old content was <tt>0.0.0.0</tt>.
*
* The address family is set to #KAfInet.
* @since 7.0
*/
{
SetAddress(Address());
}
EXPORT_C const TIp6Addr &TInetAddr::Ip6Address() const
/**
* Gets the IPv6 address
*
* Only for #KAfInet6, undefined for #KAfInet.
*
* This function returns a reference to a location where IPv6
* address would be stored.
* No check on family is made, and
* using this function for any other address family except KAfInet6
* does not cause an error, but returned reference does not point
* to valid IPv6 address (unless content is converted to KAfInet6).
*
* @return The IPv6 address
* @since 7.0
*/
{
return AddrPtr()->iAddr;
}
EXPORT_C void TInetAddr::SetFlowLabel(TInt aLabel)
/**
* Sets the Flow Label.
*
* Only for #KAfInet6, undefined (ignored) for #KAfInet.
*
* @param aLabel The flow label (only low 20 bits used)
* @since 7.0
*/
{
// Family not checked, but if it is not KAfInet6, the stored
// value has no significance.
AddrPtr()->iFlow = aLabel & 0xFFFFF;
}
EXPORT_C TInt TInetAddr::FlowLabel() const
/**
* Gets the Flow Label.
*
* Only for #KAfInet6, return zero for #KAfInet.
*
* @return The flow label
* @since 7.0
*/
{
return Family() == KAfInet6 ? AddrPtr()->iFlow : 0;
}
EXPORT_C void TInetAddr::SetScope(TUint32 aScope)
/**
* Sets the scope id value
*
* Only for #KAfInet6, undefined (ignored) for #KAfInet.
*
* When an IPv4 address is stored in IPv4-mapped format (KAfInet6),
* then non-zero scopes are also possible for IPv4 (and needed for
* proper handling of overlapping private address ranges or for
* IPv4 link local addresses).
*
* @param aScope The scope id of the address.
* @since 7.0
*/
{
// Family not checked, but if it is not KAfInet6, the stored
// value has no significance.
AddrPtr()->iScope = aScope;
}
EXPORT_C TUint32 TInetAddr::Scope() const
/**
* Gets the scope id value
*
* Only for #KAfInet6, return zero for #KAfInet.
*
* When an IPv4 address is stored in IPv4-mapped format (KAfInet6),
* then non-zero scopes are also possible for IPv4 (and needed for
* proper handling of overlapping private address ranges or for
* IPv4 link local addresses).
*
* @return The scope id of the address.
* @since 7.0
*/
{
return Family() == KAfInet6 ? AddrPtr()->iScope : 0;
}
EXPORT_C TBool TInetAddr::IsUnicast() const
/**
* Tests if address is unicast address.
*
* This is just a "shorthand" notation for a test
* that none of the following is true
*
* @li TInetAddr::IsMulticast()
* @li TInetAddr::IsBroadcast()
* @li TInetAddr::IsUnspecified()
*
* For exact semantics of IsUnicast, see the descriptions
* of the above functions.
*
* Caution: the test is based purely on the address, and it should be
* kept in mind that this test has no way of detecting IPv4 net
* broadcast addresses (because the netmask is not known).
*
* @return
* ETrue if the address is unicast:
* EFalse, otherwise
* @since 7.0
*/
{
return !(IsMulticast() || IsBroadcast() || IsUnspecified());
}
EXPORT_C TBool TInetAddr::IsMulticast() const
/**
* Tests if the IP address is a multicast address.
*
* For IPv4 addresses this returns true, if address
* is Class D (multicast). IPv4 address can be in
* #KAfInet or #KAfInet6 (<em>IPv4-mapped</em> or
* <em>IPv4-compatible</em>) formats.
*
* For IPv6 addresses this returns true, if address
* is IPv6 multicast address (start with <tt>0xff</tt> byte).
*
* @return
* ETrue if the IP address value is multicast;
* EFalse, otherwise
* @since 7.0
*/
{
return (Family() == KAfInet6 && AddrPtr()->iAddr.IsMulticast()) ||
(Address() & KInetAddrIdMaskD) == KInetAddrIdValD;
}
EXPORT_C TBool TInetAddr::IsUnspecified() const
/**
* Tests if the IP address is unspecified.
*
* The address is unspecified if the
* @li family is KAFUnspec
* @li family is #KAfInet6 and address is <tt>::</tt>
* @li family is #KAfInet6 and address is IPv4-mapped <tt>0.0.0.0</tt>
* @li family is #KAfInet and address is <tt>0.0.0.0</tt>
*
* @return
* ETrue if the IP address is unspecified;
* EFalse, otherwise
* @since 7.0
*/
{
return Family() == KAfInet6 ?
AddrPtr()->iAddr.IsUnspecified() || (AddrPtr()->iAddr.IsV4Mapped() && Address() == KInetAddrNone) :
Address() == KInetAddrNone;
}
EXPORT_C TBool TInetAddr::IsLoopback() const
/**
* Tests if the IP address is a loopback address.
*
* For IPv4 addresses this returns true, if address
* belongs to the loopback net (<tt>127.x.x.x</tt>). IPv4 address
* can be in KAfInet or in IPv4-mapped/compatible
* formats.
*
* For IPv6 address this returns true for IPv6 loopback
* address (= <tt>::1</tt>).
*
* @return
* ETrue, if the address is loopback;
* EFalse, otherwise
* @since 7.0
*/
{
return (Family() == KAfInet6 && AddrPtr()->iAddr.IsLoopback()) ||
(Address() & INET_ADDR(255,0,0,0)) == INET_ADDR(127,0,0,0);
}
EXPORT_C TBool TInetAddr::IsLinkLocal() const
/**
* Tests if IP address is link-local address
*
* For IPv4 this returns true, if the address belongs to the
* link-local net (<tt>169.254.x.x</tt>).
*
* For IPv6 this returns true, if the address is IPv6 link-local
* address (<tt>fe80:..</tt>).
*
* @note
* Does not return true for multicast addresses
* which are in the link-local scope.
*
* @return
* ETrue, if this address is a link-local address;
* EFalse, otherwise
* @since 7.0
*/
{
return (Family() == KAfInet6 && AddrPtr()->iAddr.IsLinkLocal()) ||
(Address() & KInetAddrLinkLocalNetMask) == KInetAddrLinkLocalNet;
}
EXPORT_C TBool TInetAddr::IsSiteLocal() const
/**
* Tests if IP address is site-local address.
*
* Always false for IPv4 addressess.
*
* For IPv6 this returns true, if the address is IPv6 site-local
* address (<tt>fec0:...</tt>)
*
* @note
* Does not return true for multicast addresses
* which are in the site-local scope.
*
* @return
* ETrue, if this is a site-local address;
* EFalse, otherwise
* @since 7.0
*/
{
return Family() == KAfInet6 && AddrPtr()->iAddr.IsSiteLocal();
}
EXPORT_C TBool TInetAddr::IsV4Compat() const
/**
* Tests if this address is an IPv4-compatible address.
*
* This is always false, if address is in #KAfInet format.
*
* @return
* ETrue, if this is a IPv4 compatible address;
* EFalse, otherwise.
*
* @deprecated IPv4-compatible addresses should not be used.
* @since 7.0
*/
{
return Family() == KAfInet6 && AddrPtr()->iAddr.IsV4Compat();
}
EXPORT_C TBool TInetAddr::IsV4Mapped() const
/**
* Tests if this address is an IPv4-mapped address.
*
* This is always false, if address is in #KAfInet format.
*
* @return
* ETrue, if this address is an IPv4-mapped address;
* EFalse, otherwise.
* @since 7.0
*/
{
return Family() == KAfInet6 && AddrPtr()->iAddr.IsV4Mapped();
}
EXPORT_C TUint32 TInetAddr::Address() const
/**
* Gets the IPv4 address value.
*
* If the stored address is not an IPv4 address, the returned
* value is ZERO.
*
* This works also for IPv4 addresses which
* are stored in <em>IPv4-mapped</em> or <em>IPv4-compatible</em>
* format. (since 7.0).
*
* @return The IP address value.
*/
{
if (Family() == KAfInet)
return Addr4Ptr()->iAddr;
if (Family() == KAfInet6 && (IsV4Mapped() || IsV4Compat()))
{
const struct SInet6Addr *a = AddrPtr();
return
(a->iAddr.u.iAddr8[12] << 24) |
(a->iAddr.u.iAddr8[13] << 16) |
(a->iAddr.u.iAddr8[14] << 8) |
a->iAddr.u.iAddr8[15];
}
// Note: This is returned for KAFUnspec and any unknown family
return KInetAddrNone;
}
EXPORT_C TBool TInetAddr::CmpAddr(const TInetAddr &aAddr) const
/**
* Compares IP address and port values with
* those in another TInetAddr.
*
* @param aAddr
* TInetAddr with which to compare
* @return
* ETrue if IP address and port values are the same;
* EFalse, otherwise.
*/
{
return Match(aAddr) && CmpPort(aAddr);
}
EXPORT_C TBool TInetAddr::Match(const TInetAddr &aHost) const
/**
* Tests the IP address value with that in another TInetAddr.
*
* @note
* The function matches IPv4 addresses even if they are
* stored in different formats (#KAfInet or #KAfInet6 using
* <em>IPv4-mapped</em> format) (since Symbian OS 7.0s).
*
* @param aHost TInetAddr with which to compare
* @return
* ETrue if IP address value is the same as this,
* EFalse, otherwise.
*/
{
const struct SInet6Addr *a = AddrPtr();
const struct SInet6Addr *b = aHost.AddrPtr();
if (Family() != aHost.Family())
{
//
// Do some heavier testing, to return true for
// equal IPv4 addresses, when one is in KAfInet
// format and other presented as IPv4 mapped (KAfInet6)
// format.
if ((Family() == KAfInet && aHost.IsV4Mapped()) ||
(IsV4Mapped() && aHost.Family() == KAfInet))
return Address() == aHost.Address();
else
return EFalse;
}
if (Family() == KAfInet)
return Addr4Ptr()->iAddr == aHost.Addr4Ptr()->iAddr;
else if (Family() == KAfInet6)
return
a->iAddr.u.iAddr32[3] == b->iAddr.u.iAddr32[3] &&
a->iAddr.u.iAddr32[2] == b->iAddr.u.iAddr32[2] &&
a->iAddr.u.iAddr32[1] == b->iAddr.u.iAddr32[1] &&
a->iAddr.u.iAddr32[0] == b->iAddr.u.iAddr32[0];
// Any other than KAfInet, KAfInet6 or KAFUnspec is always FALSE
return Family() == KAFUnspec;
}
EXPORT_C TBool TInetAddr::Match(const TInetAddr &aNet, const TInetAddr &aMask) const
/**
* Tests if another TInetAddr is in the same subnet.
*
* The function applies the subnet mask passed through aMask to the IP
* address and to the IP address in aNet. If the resulting values are
* the same, this indicates that the addresses are part of the same subnet,
* and ETrue is returned.
*
* @note
* The function matches IPv4 addresses even if they are
* stored in different formats (#KAfInet or #KAfInet6 using
* <em>IPv4-mapped</em> format). (since Symbian OS 7.0s).
*
* @param aNet
* TInetAddr with which to compare.
* @param aMask
* TInetAddr object with the IP address set to the relevant subnet mask.
* @return
* ETrue if both IP address values are the members of the same subnet;
* EFalse, otherwise.
*/
{
const struct SInet6Addr *a = AddrPtr();
const struct SInet6Addr *b = aNet.AddrPtr();
const struct SInet6Addr *m = aMask.AddrPtr();
if (Family() != aNet.Family() || Family() != aMask.Family())
{
// Mixed address families, only case that could return true
// is some combination of KAfInet and IPv4 mapped formats.
if (!(Family() == KAfInet || IsV4Mapped()))
return EFalse;
if (!(aNet.Family() == KAfInet || aNet.IsV4Mapped()))
return EFalse;
if (!(aMask.Family() == KAfInet || aMask.IsV4Mapped()))
return EFalse;
return !(aMask.Address() & (Address() ^ aNet.Address()));
}
if (Family() == KAfInet)
return !(aMask.Addr4Ptr()->iAddr & (Addr4Ptr()->iAddr ^ aNet.Addr4Ptr()->iAddr));
else if (Family() == KAfInet6)
return
!((m->iAddr.u.iAddr32[0] & (a->iAddr.u.iAddr32[0] ^ b->iAddr.u.iAddr32[0])) ||
(m->iAddr.u.iAddr32[1] & (a->iAddr.u.iAddr32[1] ^ b->iAddr.u.iAddr32[1])) ||
(m->iAddr.u.iAddr32[2] & (a->iAddr.u.iAddr32[2] ^ b->iAddr.u.iAddr32[2])) ||
(m->iAddr.u.iAddr32[3] & (a->iAddr.u.iAddr32[3] ^ b->iAddr.u.iAddr32[3])));
// Any other than KAfInet, KAfInet6 or KAFUnspec is always FALSE
return Family() == KAFUnspec;
}
EXPORT_C TBool TInetAddr::Match(const TInetAddr &aNet, TInt aPrefixLen) const
/**
* Tests if the specified number of left-most bits on addresses are same.
*
* Return ETrue if leftmost aPrefixLen bits on addresses are same (both
* families must be the same).
*
* @param aNet
* TInetAddr with which to compare.
* @param aPrefixLen
* Number of left-most bits to compare.
* @return
* ETrue, if the bits match;
* EFalse, otherwise.
* @since 7.0
*/
{
if (aPrefixLen > 127)
{
// If the prefix length is 128 or larger, then this
// is just simple address match..
return Match(aNet);
}
else if (aPrefixLen <= 0)
{
// If prefix is 0 (or < 0 for sanity), then match
// result is implicitly true.
return ETrue;
}
const struct SInet6Addr *a = AddrPtr();
const struct SInet6Addr *b = aNet.AddrPtr();
TInt i;
if (Family() != aNet.Family())
{
if (!(Family() == KAfInet || IsV4Mapped()))
return EFalse;
if (aNet.IsV4Mapped())
aPrefixLen -= 96;
else if (aNet.Family() != KAfInet)
return EFalse;
return !(~(~0UL >> (aPrefixLen & 31)) & (Address() ^ aNet.Address()));
}
if (Family() != KAfInet6)
return !(~(~0UL >> (aPrefixLen & 31)) & (Addr4Ptr()->iAddr ^ aNet.Addr4Ptr()->iAddr));
for (i = 0; i < (aPrefixLen >> 5); i++)
if (a->iAddr.u.iAddr32[i] != b->iAddr.u.iAddr32[i])
return EFalse;
for (i <<= 2; i < (aPrefixLen >> 3); i++)
if (a->iAddr.u.iAddr8[i] != b->iAddr.u.iAddr8[i])
return EFalse;
if (~(0xff >> (aPrefixLen & 7)) & (a->iAddr.u.iAddr8[i] ^ b->iAddr.u.iAddr8[i]))
return EFalse;
return ETrue;
}
EXPORT_C void TInetAddr::PrefixMask(TInt aPrefixLen)
/**
* Creates an IPv6 address with the specified number of left-most bits set to
* 1, and the rest set to 0.
*
* The previous content does not matter, and is overwritten.
*
* @param aPrefixLen
* Number of left-most bits to set to 1.
* @since 7.0
*/
{
Init(KAfInet6);
__ASSERT_ALWAYS(aPrefixLen >= 0 && aPrefixLen <= 128, User::Panic(_L("INSOCK"), aPrefixLen));
struct SInet6Addr *const a = AddrPtr();
const TUint32 m = ~(~0UL >> (aPrefixLen & 31));
TInt i;
aPrefixLen >>= 5;
for (i = 0; i < aPrefixLen; i++)
a->iAddr.u.iAddr32[i] = ~0UL;
i <<= 2;
a->iAddr.u.iAddr8[i++] = (TUint8)(m >> 24);
a->iAddr.u.iAddr8[i++] = (TUint8)(m >> 16);
a->iAddr.u.iAddr8[i++] = (TUint8)(m >> 8);
a->iAddr.u.iAddr8[i++] = (TUint8)m;
i >>= 2;
while (i < 4)
a->iAddr.u.iAddr32[i++] = 0;
}
EXPORT_C void TInetAddr::Prefix(const TInetAddr& aAddr, TInt aPrefixLen)
/**
* Creates an IPv6 address with the specified number of left-most bits
* copied from another address, and remaining bits set to 0.
*
* The function does not check the family of the aAddr, and for anything
* else but KAfInet6 the resulting prefix value is undefined.
*
* The resulting address family is #KAfInet6.
* The scope id and flow label are zeroed.
*
* @param aAddr
* The address to copy the prefix from.
* @param aPrefixLen
* Number of left-most bits to set to copy from aAddr.
* @since 7.0
*/
{
Init(KAfInet6);
__ASSERT_ALWAYS(aPrefixLen >= 0 && aPrefixLen <= 128, User::Panic(_L("INSOCK"), aPrefixLen));
struct SInet6Addr *const a = AddrPtr();
const struct SInet6Addr *const b = aAddr.AddrPtr();
TUint32 m = ~(~0UL >> (aPrefixLen & 31));
TInt i;
aPrefixLen >>= 5;
for (i = 0; i < aPrefixLen; i++)
a->iAddr.u.iAddr32[i] = b->iAddr.u.iAddr32[i];
i <<= 2;
a->iAddr.u.iAddr8[i] = (TUint8)(b->iAddr.u.iAddr8[i] & (m >> 24)); i++;
a->iAddr.u.iAddr8[i] = (TUint8)(b->iAddr.u.iAddr8[i] & (m >> 16)); i++;
a->iAddr.u.iAddr8[i] = (TUint8)(b->iAddr.u.iAddr8[i] & (m >> 8)); i++;
a->iAddr.u.iAddr8[i] = (TUint8)(b->iAddr.u.iAddr8[i] & m); i++;
i >>= 2;
while (i < 4)
a->iAddr.u.iAddr32[i++] = 0;
}
//
EXPORT_C void TInetAddr::Output(TDes &aBuf) const
/**
* Writes the IP address into a string.
*
* For an IPv4 address, the format is <tt>d.d.d.d</tt>, where "d" is an 8-bit
* decimal number. (An example IPv4 address: <tt>127.0.0.1</tt>).
*
* For an IPv6 address, the format is <tt>h:h:h:h:h:h:h:h</tt>,
* where "h" is a 16-bit hexadecimal number.
* (An example IPv6 address: <tt>2001:618:40C:20:2C0:4FFF:FE24:AA79</tt>).
*
* If address family is not #KAfInet or #KAfInet6, then empty
* string is returned (aBuf.Length() == 0).
*
* If the family is KAfInet6, the output buffer must be at least
* 39 characters. If less, the buffer is filled with '*' characters.
*
* @retval aBuf
* contains a string representation of the IP address.
* @since 7.0 (IPv6 support)
*/
{
aBuf.SetLength(0);
if (Family() != KAfInet && Family() != KAfInet6)
return;
TUint32 a = Address();
if (Family() == KAfInet)
{
aBuf.Format(_L("%d.%d.%d.%d"), a>>24, (a>>16)&0xff, (a>>8)&0xff, a&0xff);
return;
}
// Address family is IPv6. At worst case, the output buffer must be large
// enough for full IPv6 address = 39 (8 * 4 + 7). To catch errors, require
// the output to be at least this long, even though the current output might
// fit. However, just fill the output with *'s in release environment, so
// that existing IPv4 binaries do not crash, if they get IPv6 addresses.
// Remember to update the magic 39, if you change the output format!
//__ASSERT_DEBUG(aBuf.MaxLength() >= 39, User::Panic(_L("DEBUG"), aBuf.MaxLength()));
if (aBuf.MaxLength() < 39)
{
aBuf.Fill('*', aBuf.MaxLength());
return;
}
if (IsV4Compat())
aBuf.Format(_L("::%d.%d.%d.%d"), a>>24, (a>>16)&0xff, (a>>8)&0xff, a&0xff);
else if (IsV4Mapped())
aBuf.Format(_L("%d.%d.%d.%d"), a>>24, (a>>16)&0xff, (a>>8)&0xff, a&0xff);
else
{
TPtrC16 i6addr(AddrPtr()->iAddr.u.iAddr16, 8);
TInt start = 0, count = 0, longest_count = 0, longest_start = 0;
TInt i;
for (i = 0; i < 8; i++)
{
if (i6addr[i])
{
if (count > longest_count)
{
longest_count = count;
longest_start = start;
}
start = i + 1;
count = 0;
}
else
count++;
}
if (count > longest_count)
{
longest_count = count;
longest_start = start;
}
i = 0;
if (longest_count > 1)
{
if (longest_start == 0)
aBuf.Append(':');
else while (i < longest_start)
{
aBuf.AppendNum(TUint(BigEndian::Get16((TUint8 *)&i6addr[i++])), EHex);
aBuf.Append(':');
}
aBuf.Append(':');
i += longest_count;
}
if (i < 8)
for (;;)
{
aBuf.AppendNum(TUint(BigEndian::Get16((TUint8 *)&i6addr[i++])), EHex);
if (i == 8)
break;
aBuf.Append(':');
}
}
}
EXPORT_C void TInetAddr::OutputWithScope(TDes &aBuf) const
/**
* Writes the IP address into a string and appends the scope id.
*
* The IP address is formatted with as with the standard
* Output.
*
* If the scope id has non-zero value and if there is
* room in the output buffer, the scope id is appended to the address
* using the "%scope-id"-notation.
*
* @retval aBuf
* contains a string representation of the address.
* @since after 7.0s
*/
{
Output(aBuf);
if (Scope() && aBuf.MaxLength() - aBuf.Length() > 11)
aBuf.AppendFormat(_L("%%%d"), Scope());
}
//
// IPv6address = hexpart [ ":" IPv4address ]
// IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT
// IPv6prefix = hexpart "/" 1*2DIGIT
//
// hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
// hexseq = hex4 *( ":" hex4)
// hex4 = 1*4HEXDIG
typedef enum
{
EInvalid, // Invalid address characters detected
EColon, // Plain ':'
EHexColon, // Hex sequence ending with ':'
EDecPeriod, // Decimal sequence ending with '.'
ELast // Last sequence at end of string
} TAddressToken;
class TInetAddrParser : public TLex
{
friend class TInetAddr;
TInetAddrParser(const TDesC &anInput, TIp6Addr &aAddr);
TAddressToken NextComponent(); // Extract the next component of the address
TInt GetHexValue(TUint16 &aComp);
TAddressToken HeadPart();
TBool TailPart(TAddressToken);
TBool Ipv4address();
TInt iFill; // Number of filled components in i6addr (0..8)
TPtr16 i6addr; // Collects IPv6 address components (max 8)
};
#ifdef __VC32__
#pragma warning(disable : 4097) // typedef-name used as synonym for class-name
#endif
//
// TInetAddrParser::TInetAddrParser
//
TInetAddrParser::TInetAddrParser(const TDesC &anInput, TIp6Addr &aAddr) :
TLex(anInput), iFill(0), i6addr(aAddr.u.iAddr16, 8, 8)
{
}
//
// TInetAddrParser::GetHexValue
// Extract hexadecimal value terminated by ':' or Eos (any other
// termination is considered as invalid syntax). The resulting
// value must fit into unsigned 16 bits (checked by the Val()).
//
// On input, the Mark on TLex must point to the beginning
// of the number!
//
// Returns
// = KErrNone and value in 'comp', if no errors detected
// The current point is left after the number or
// terminator, if present.
// != KErrNone, otherwise. 'comp' and current point
// may have indeterminate values.
//
TInt TInetAddrParser::GetHexValue(TUint16 &comp)
{
TInt err, ch;
UnGetToMark();
err = Val(comp, EHex);
BigEndian::Put16((TUint8 *)&comp, comp);
if (err == KErrNone && !Eos() && (ch = Get(), (ch != ':')))
err = KErrArgument;
return err;
}
//
// TInetAddrParser::NextComponent
// Mark the beginning and determine the type of the next component
// by looking how the sequence is terminated.
//
// 1*<hexdigit> ":" -> EHexColon
// 1*<hexdigit> "." -> EDecPeriod
// 1*<hexdigit> <EOS> -> ELast
// ":" -> EColon
// anything else -> EInvalid
//
// Note that this not check the lengths of the sequences,
// nor any validity within context (like only decimal digits before
// period. There is no point in checking such issues here, as they
// must be noted later in any case (in TLex Val() function in part)
//
TAddressToken TInetAddrParser::NextComponent()
{
TAddressToken type = EInvalid;
Mark();
while (!Eos())
{
TChar ch = Get();
if (ch.IsHexDigit())
type = ELast; // Have digits!
else if (ch == '.')
if (type == ELast) // we have digits?
return EDecPeriod;
else
return EInvalid; // Component just can't start with "."
else if (ch == ':')
{
if (type == EInvalid) // Any preceding digits?
return EColon;
else
return EHexColon;
}
else
return EInvalid;
}
return type;
}
//
// TInetAddrParser::HeadPart
// Parse the beginning part of a IPv6 address, up to the "::",
// first IPv4 component or last component. Parse a sequence of
// components (EHexColon)
// 0*7(<hexseq> ":")
// and fills the i6addr with the converted results. Returns the
// type of the first address component that is not EHexColon.
//
TAddressToken TInetAddrParser::HeadPart()
{
TAddressToken t = EInvalid;
while (iFill < i6addr.Length() && (t = NextComponent()) == EHexColon)
if (GetHexValue(i6addr[iFill++]))
return EInvalid;
return t;
}
//
// TInetAddrParser::TailPart
// Parse the tail part of a IPv6 address. The tail part is
// *(<hexseq> ":") (<hexseq>| <ivp4address>)
//
// Returns ETrue on correct input, and EFalse otherwise
//
TBool TInetAddrParser::TailPart(TAddressToken t)
{
for (;;)
{
if (t == EDecPeriod)
return Ipv4address();
else if (iFill == i6addr.Length() || GetHexValue(i6addr[iFill++]) != KErrNone)
return EFalse;
else if (t == ELast)
return ETrue;
else if (t != EHexColon)
return EFalse;
t = NextComponent();
}
}
//
// TInetAddrParser::Ipv4address
// Parse the IPv4 address as a part of IPv6 address (must be at end)
// <decseq> "." <decseq> "." <decseq> "." <decseq>
// ^
// Should only be called when the current Mark points to this!
//
// Returns ETrue, on correct input and EFalse on any error.
//
TBool TInetAddrParser::Ipv4address()
{
TPtr8 i4addr((TUint8 *)(&i6addr[iFill]), 4, 4);
iFill += 2;
if (iFill > 8)
return EFalse; // No room for the IPv4 address!
UnGetToMark();
for (TInt i = 0;;)
{
if (Val(i4addr[i++], EDecimal) != KErrNone)
return EFalse; // Overflow or some other number error
if (i == 4)
return Eos(); // Ok, if all parsed.
if (Eos() || Get() != '.')
return EFalse; // Premature end or number not '.'-terminated
}
}
EXPORT_C TInt TInetAddr::Input(const TDesC& aDes)
/**
* Sets the IP address from a string containing a representation of an
* IP address, such as might be entered in a dialog.
*
* The string must contain an ASCII representation of the address.
* The format may be one of the following examples:
* @li Four 8-bit decimal numbers separated by '.' (eg. <tt>192.168.40.4</tt>)
* @li Two 8-bit decimal numbers and a 16 bit decimal (eg. <tt>192.168.10244</tt>)
* @li One 8-bit decimal number and a 24-bit decimal (eg. <tt>192.11020292</tt>)
* @li One 32 decimal number (eg. <tt>3232245764</tt>)
* @li Eight 16-bit hex numbers separated by ':' (eg.<tt>2001:618:400:6a:0:0:0:abc</tt>)
*
* Use at most one '<tt>::</tt>' to denote consecutive zeroes
* (eg. <tt>2001:618:400:6a::abc</tt>),
* IPv4-compatible address (eg. <tt>::192.168.40.4</tt>), and
* IPv4-mapped address (eg. <tt>::ffff:192.168.40.4</tt>)
*
* Any of the address notations above can be followed by "%scope-id" and
* the scope id of the TInetAddress is also set accordingly. If a dotted
* IPv4 address is associated with scope id, the address is stored as
* IPv4-mapped. If scope is not specified, the value defaults to zero.
* The flow label is set to zero.
*
* The hexadecimal numbers may be either upper or lower case.
*
* @param aDes
* Descriptor containing a string representation of an IP address
* @return
* KErrNone, if address syntax was correct and input succeeded;
* otherwise, one of the system-wide error codes.
* @since 7.0 (IPv6 support)
*/
{
TInt32 scope_id = 0;
TPtrC ptr(aDes);
//
// recognize "%<numeric-scopeid>" notation
// (for non-numeric "%<interface-name>" notation, the
// RHostResolver must be used).
//
const TInt i = ptr.LocateReverse('%');
if (i >= 0)
{
TLex num(ptr.Right(ptr.Length() - i - 1));
if (num.Val(scope_id) != KErrNone)
return KErrArgument; // aDes is not directly convertible.
ptr.Set(ptr.Left(i));
}
TInt ret = Ipv4Input(ptr);
if (ret != KErrNone)
ret = Ipv6Input(ptr);
if (ret == KErrNone && scope_id != 0)
{
// Augment returned address with the scope id
if (Family() != KAfInet6)
ConvertToV4Mapped();
SetScope(scope_id);
}
return ret;
}
TInt TInetAddr::Ipv4Input(const TDesC& aDes)
/**
* Parse string as IPv4 address.
*/
{
TUint32 addr[KIPv4AddressPartCount];
TInt current;
TRadix radix;
TChar ch;
TInt err;
TLex lex(aDes);
// skip leading white spaces
lex.SkipSpaceAndMark();
// Extract upto 4 dot separated parts
current = 0;
do
{
// Get radix prefix if any
radix = EDecimal;
ch = lex.Peek();
if (ch=='0') // might be "0x" for hex
{
lex.Mark();
lex.Inc();
ch = lex.Get();
if (ch=='x' || ch=='X')
radix = EHex;
else
lex.UnGetToMark();
}
// Get value of part
if (err = lex.Val(addr[current++], radix), err!=KErrNone)
return err;
if (current == KIPv4AddressPartCount)
{
// skip trailing white spaces
lex.SkipSpaceAndMark();
}
// Next char will be '.' if another part
if (!lex.Eos())
{
ch = lex.Get();
if(ch!='.')
return KErrArgument;
}
}
while (!lex.Eos() && ch=='.' && current<KIPv4AddressPartCount);
if (ch=='.' && current>=KIPv4AddressPartCount)
return KErrOverflow;
// Assemble the address according to the
// number of parts
switch (current)
{
case 0: // Nothing could be extracted
// lex.GotoMark();
return KErrArgument;
case 1: // a - 32 bits
SetAddress(addr[0]);
break;
case 2: // a.b - 8.24 bits
if (addr[0]>0xff || addr[1]>0xffffff)
return KErrOverflow;
SetAddress((addr[0]<<24) | addr[1]);
break;
case 3: // a.b.c - 8.8.16 bits
if (addr[0]>0xff || addr[1]>0xff || addr[2]>0xffff)
return KErrOverflow;
SetAddress((addr[0]<<24) | (addr[1]<<16) | addr[2]);
break;
case 4: // a.b.c.d - 8.8.8.8 bits
if (addr[0]>0xff || addr[1]>0xff || addr[2]>0xff || addr[3]>0xff)
return KErrOverflow;
SetAddress((addr[0]<<24) | (addr[1]<<16) | (addr[2]<<8) | addr[3]);
break;
default: // Too many parts
return KErrOverflow;
}
return KErrNone;
}
TInt TInetAddr::Ipv6Input(const TDesC& aDes)
/**
* Parse string as IPv6 address.
*/
{
TUint32 addr;
TInt head;
TInetAddrParser lex(aDes, AddrPtr()->iAddr);
lex.SkipSpaceAndMark();
//
// The first address token determines whether this is to be
// parsed as IPv4 address (KAfInet) or IPv6 address (KAfInet6).
//
// If the first token is plain decimal number or a decimal number
// terminating with a period, then assume this is a request to
// return plain old KAfInet type address.
switch (lex.HeadPart())
{
case ELast: // IPv4 as single integer?
if (lex.iFill == 0)
{
// The input "address" is specified as a single string of
// hex or decimal digits. This is not valid IPv6 address,
// and even dubious as IPv4, but accept it as IPv4 if it
// is decimal number and fits into 32 bits.
// Or, should things like "f", "ffe" be accepted as IPv6
// addresses??
lex.UnGetToMark();
if (lex.Val(addr, EDecimal) == KErrNone && lex.Eos())
{
// All decimal digits and full string accepted by Val
SetAddress(addr);
return KErrNone;
}
}
else if (lex.TailPart(ELast) && lex.iFill == 8)
//
// Now the address is given as "XX:XX:XX... :XX".
//
break;
return KErrArgument;
case EDecPeriod:
if (lex.Ipv4address())
if (lex.iFill == 2) // == 4 bytes!
{
// The input cannot be IPv6 address, it was a plain
// IPv4 address.
SetAddress(ByteOrder::Swap32(AddrPtr()->iAddr.u.iAddr32[0]));
return KErrNone;
}
else if (lex.iFill == 8)
// The were some IPv6 components followed by an IPv4. For
// acceptable input, all components must be defined!
break;
return KErrArgument;
case EColon:
// IPv6 address with zerofill part. A special kludge: if the
// address begins with "::", we must check the other colon
// here, because HeadPart has not skipped it.
//
if (lex.iFill == 0 && lex.NextComponent() != EColon)
return KErrArgument; // Not a valid address format
head = lex.iFill;
if (!lex.Eos() && !lex.TailPart(lex.NextComponent()))
return KErrArgument;
// The [head,iTail] portion must be moved to the end of the
// address and the middle part (if any) needs to be filled
// with zeroes.
if (lex.iFill < 8)
{
TInt i = 8;
while (head < lex.iFill)
lex.i6addr[--i] = lex.i6addr[--lex.iFill];
while (head < i)
lex.i6addr[--i] = 0;
}
break;
default:
return KErrArgument; // Not a valid address format
}
SetFamily(KAfInet6);
SetUserLen(sizeof(SInet6Addr));
SetScope(0);
SetFlowLabel(0);
return KErrNone;
}
//
// IPv4 compatibility stuff
//
EXPORT_C void TInetAddr::NetMask(const TInetAddr& aAddr)
/**
* Sets the IP address to a mask suitable for extracting the network number
* part of the IP address (deprecated).
*
* This function assumes the IPv4 address classes (A, B, C). Applications
* using this function may not work properly in the current internet
* environment.
*
* The function tests whether the IP
* address in aAddr is a Class A, B, C, or other address. It then sets
* the IP address to suitable mask values as follows:
*
* @li Class A addresses: mask 255.0.0.0
* @li Class B addresses: mask 255.255.0.0
* @li Class C addresses: mask 255.255.255.0
* @li other addresses: mask 255.255.255.255
*
* The resulting address family is #KAfInet.
*
* @param aAddr
* TInetAddr from which to obtain IP address
*
* @deprecated
* Works only for IPv4. The length of the network prefix needs to be
* aqcuired by other means. When prefix length is known, PrefixMask()
* function can be used.
*/
{
TUint32 mask = 0;
TUint32 addr = aAddr.Address();
if ((addr & KInetAddrIdMaskA) == KInetAddrIdValA)
mask = KInetAddrNetMaskA;
else if ((addr & KInetAddrIdMaskB) == KInetAddrIdValB)
mask = KInetAddrNetMaskB;
else if ((addr & KInetAddrIdMaskC) == KInetAddrIdValC)
mask = KInetAddrNetMaskC;
else
mask = KInetAddrMaskHost;
SetAddress(mask);
}
EXPORT_C void TInetAddr::Net(const TInetAddr& aAddr)
/**
* Obtains a network mask corresponding to the class of the IP address,
* using the NetMask() function, and then applies this mask to the current
* IP address (deprecated).
*
* The resulting address family is #KAfInet
*
* @param aAddr
* TInetAddr from which to obtain IP address for creating the
* network mask.
*
* @deprecated
* Works only for IPv4. Prefix() should be used instead.
*/
{
NetMask(aAddr);
SetAddress(aAddr.Address() & Address());
}
EXPORT_C void TInetAddr::SubNet(const TInetAddr& aAddr, const TInetAddr& aMask)
/**
* Sets the IP address to the network number and subnet parts of the IP
* address (that is, the original IP address with the host number part
* cleared).
*
* This is obtained by applying the mask value in aMask to the
* IP address in aAddr. The result is undefined if address and
* mask have different address family.
*
* @param aAddr
* TInetAddr from which to obtain IP address
* @param aMask
* TInetAddr object with the IP address set to the relevant subnet mask.
*/
{
if (aAddr.Family() != KAfInet6)
SetAddress(aAddr.Address() & aMask.Address());
else
{
Init(KAfInet6);
struct SInet6Addr *const a = AddrPtr();
const struct SInet6Addr *const b = aAddr.AddrPtr();
const struct SInet6Addr *const m = aMask.AddrPtr();
a->iAddr.u.iAddr32[0] = m->iAddr.u.iAddr32[0] & b->iAddr.u.iAddr32[0];
a->iAddr.u.iAddr32[1] = m->iAddr.u.iAddr32[1] & b->iAddr.u.iAddr32[1];
a->iAddr.u.iAddr32[2] = m->iAddr.u.iAddr32[2] & b->iAddr.u.iAddr32[2];
a->iAddr.u.iAddr32[3] = m->iAddr.u.iAddr32[3] & b->iAddr.u.iAddr32[3];
}
}
EXPORT_C void TInetAddr::SubNetBroadcast(const TInetAddr& aAddr, const TInetAddr& aMask)
/**
* Sets the IP address to be suitable for a subnet-directed broadcast
* address.
*
* To achieve this, the subnet mask value in aMask is applied to the IP
* address in aAddr. The mask is then used again to set all host number
* bits to 1 (which signifies, broadcast to all hosts on the subnet).
*
* Only for IPv4. The function does not have a sensible interpretation in
* IPv6. An application that uses this needs to code separate branches for
* IPv4 and IPv6 cases.
*
* @param aAddr
* TInetAddr from which to obtain IP address
* @param aMask
* TInetAddr object with the IP address set to the relevant subnet mask.
*
* @deprecated
* Works only for IPv4. IPv6 has all-nodes link local multicast
* address (ff02::1) for this purpose.
*/
{
const TUint32 addr = aAddr.Address();
const TUint32 mask = aMask.Address();
SetAddress((addr & mask) | (KInetAddrBroadcast & ~mask));
}
EXPORT_C void TInetAddr::NetBroadcast(const TInetAddr& aAddr)
/**
* Sets the IP address to be suitable for a network-directed broadcast
* address (deprecated).
*
* The function obtains a network mask corresponding to the class of
* the IP address in aAddr, using the NetMask() function. It then
* applies this mask to the current IP address to separate the network
* number part of the address. The mask is then used again to set all
* host number bits to 1 (which signifies, broadcast to all hosts on
* the network).
*
* The resulting address family is #KAfInet
*
* @param aAddr
* TInetAddr from which to obtain IP address for creating the network mask.
*
* @deprecated Works only for IPv4.
* @deprecated
* This function works only for IPv4. It assumes the old
* IPv4 address classes (A, B, C). Applications using this
* function may not work properly in the current internet environment.
*/
{
TInetAddr netmask;
netmask.NetMask(aAddr);
const TUint32 addr = aAddr.Address();
const TUint32 mask = netmask.Address();
SetAddress((addr & mask) | (KInetAddrBroadcast & ~mask));
}
EXPORT_C TInt TSoInetRouteInfo::GetLinkAddr( TLinkAddr &aInfo ) const
{
/**
* Checks to make sure the gateway member is actually a link layer
* address and not the IP address of a gateway
* If the function is successful, the link layer address
* of the neighbour is stored in the parameter and KErrNone is
* returned. If the function is unsuccessful because
* the link layer address cannot be obtained, KErrNotFound is
* returned and the parameter is not modified.
*
* @param aInfo parameter to store link layer address if found
* @return KErrNone if link layer address found else KErrNotFound
*/
TInt len = const_cast<TSoInetRouteInfo*>( this )->iGateway.GetUserLen();
if(len < 1)
{
return KErrNotFound;
}
TInt family = iGateway.Family();
if ((family != KAFUnspec) && (family != KAfInet) && (family != KAfInet6))
{
aInfo = TLinkAddr::Cast( iGateway );
return KErrNone;
}
return KErrNotFound;
}
EXPORT_C TLinkAddr::TLinkAddr()
/**
* Default constructor initialises the address to be zero-filled.
*/
{;}
EXPORT_C void TLinkAddr::SetAddress(const TDesC8 &aAddr)
/**
* Assigns a string of octets as the address.
* @param aAddr The link layer address.
*/
{
const TInt len = aAddr.Length();
SetUserLen(len);
TPtr8((TUint8 *)UserPtr(), len).Copy(aAddr);
}
EXPORT_C TPtrC8 TLinkAddr::Address() const
/**
* Returns the current stored address as a pointer to string of octets.
* @return The link layer address.
*/
{
return TPtrC8((TUint8 *)UserPtr(), ((TSockAddr *)this)->GetUserLen());
}
EXPORT_C const TLinkAddr& TLinkAddr::Cast(const TSockAddr& aAddr)
/**
* This function will cast the address to a TLinkAddr.
* This function has no way of verifying that the source address is actually a link layer address and should
* not be passed an IP address.
* @param address to be cast
* @return link layer cast of passed parameter
*/
{
return *((TLinkAddr *)&aAddr);
}
EXPORT_C TLinkAddr& TLinkAddr::Cast(TSockAddr& aAddr)
/**
* This function will cast the address to a TLinkAddr.
* This function has no way of verifying that the source address is actually a link layer address and should
* not be passed an IP address.
* @param address to be cast
* @return link layer cast of passed parameter
*/
{
return *((TLinkAddr *)&aAddr);
}
EXPORT_C const TLinkAddr* TLinkAddr::Cast(const TSockAddr* aAddr)
/**
* This function will cast the address to a TLinkAddr.
* This function has no way of verifying that the source address is actually a link layer address and should
. * not be passed an IP address.
*/
{
return (TLinkAddr *)aAddr;
}
EXPORT_C TLinkAddr* TLinkAddr::Cast(TSockAddr* aAddr)
/**
* This function will cast the address to a TLinkAddr.
* This function has no way of verifying that the source address is actually a link layer address and should
. * not be passed an IP address.
*/
{
return (TLinkAddr *)aAddr;
}