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.
471 lines
7.8 KiB
471 lines
7.8 KiB
/*++
|
|
|
|
Copyright (c) 2000-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
addr.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
IP address routines
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) June 2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
#include "ws2atm.h" // ATM addressing
|
|
|
|
|
|
//
|
|
// Address info table
|
|
//
|
|
|
|
FAMILY_INFO AddrFamilyTable[] =
|
|
{
|
|
AF_INET,
|
|
DNS_TYPE_A,
|
|
sizeof(IP4_ADDRESS),
|
|
sizeof(SOCKADDR_IN),
|
|
(DWORD) FIELD_OFFSET( SOCKADDR_IN, sin_addr ),
|
|
|
|
AF_INET6,
|
|
DNS_TYPE_AAAA,
|
|
sizeof(IP6_ADDRESS),
|
|
sizeof(SOCKADDR_IN6),
|
|
(DWORD) FIELD_OFFSET( SOCKADDR_IN6, sin6_addr ),
|
|
|
|
AF_ATM,
|
|
DNS_TYPE_ATMA,
|
|
sizeof(ATM_ADDRESS),
|
|
sizeof(SOCKADDR_ATM),
|
|
sizeof(DWORD),
|
|
(DWORD) FIELD_OFFSET( SOCKADDR_ATM, satm_number ),
|
|
};
|
|
|
|
|
|
|
|
PFAMILY_INFO
|
|
FamilyInfo_GetForFamily(
|
|
IN DWORD Family
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get address family info for family.
|
|
|
|
Arguments:
|
|
|
|
Family -- address family
|
|
|
|
Return Value:
|
|
|
|
Ptr to address family info for family.
|
|
NULL if family is unknown.
|
|
|
|
--*/
|
|
{
|
|
PFAMILY_INFO pinfo = NULL;
|
|
|
|
// switch on type
|
|
|
|
if ( Family == AF_INET )
|
|
{
|
|
pinfo = pFamilyInfoIp4;
|
|
}
|
|
else if ( Family == AF_INET6 )
|
|
{
|
|
pinfo = pFamilyInfoIp6;
|
|
}
|
|
else if ( Family == AF_ATM )
|
|
{
|
|
pinfo = pFamilyInfoAtm;
|
|
}
|
|
|
|
return pinfo;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
Family_SockaddrLength(
|
|
IN WORD Family
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extract info for family.
|
|
|
|
Arguments:
|
|
|
|
Family -- address family
|
|
|
|
Return Value:
|
|
|
|
Length of sockaddr for address family.
|
|
Zero if unknown family.
|
|
|
|
--*/
|
|
{
|
|
PFAMILY_INFO pinfo;
|
|
|
|
// get family -- extract info
|
|
|
|
pinfo = FamilyInfo_GetForFamily( Family );
|
|
if ( pinfo )
|
|
{
|
|
return pinfo->LengthSockaddr;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
WORD
|
|
Family_DnsType(
|
|
IN WORD Family
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extract info for family.
|
|
|
|
Arguments:
|
|
|
|
Family -- address family
|
|
|
|
Return Value:
|
|
|
|
Length of sockaddr for address family.
|
|
Zero if unknown family.
|
|
|
|
--*/
|
|
{
|
|
PFAMILY_INFO pinfo;
|
|
|
|
// get family -- extract info
|
|
|
|
pinfo = FamilyInfo_GetForFamily( Family );
|
|
if ( pinfo )
|
|
{
|
|
return pinfo->DnsType;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
Family_GetFromDnsType(
|
|
IN WORD wType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get address family for a given DNS type.
|
|
|
|
Arguments:
|
|
|
|
wType -- DNS type
|
|
|
|
Return Value:
|
|
|
|
Address family if found.
|
|
Zero if wType doesn't map to known family.
|
|
|
|
--*/
|
|
{
|
|
// switch on type
|
|
|
|
if ( wType == DNS_TYPE_A )
|
|
{
|
|
return AF_INET;
|
|
}
|
|
if ( wType == DNS_TYPE_AAAA )
|
|
{
|
|
return AF_INET6;
|
|
}
|
|
if ( wType == DNS_TYPE_ATMA )
|
|
{
|
|
return AF_ATM;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Sockaddr
|
|
//
|
|
|
|
DWORD
|
|
Sockaddr_Length(
|
|
IN PSOCKADDR pSockaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get length of sockaddr.
|
|
|
|
Arguments:
|
|
|
|
pSockaddr -- sockaddr buffer to recv address
|
|
|
|
Return Value:
|
|
|
|
Length of sockaddr for address family.
|
|
Zero if unknown family.
|
|
|
|
--*/
|
|
{
|
|
return Family_SockaddrLength( pSockaddr->sa_family );
|
|
}
|
|
|
|
|
|
|
|
IP6_ADDRESS
|
|
Sockaddr_GetIp6(
|
|
IN PSOCKADDR pSockaddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get IP6 address from sockaddr.
|
|
|
|
If IP4 sockaddr, IP6 address is mapped.
|
|
|
|
Arguments:
|
|
|
|
pSockaddr -- any kind of sockaddr
|
|
must have actual length for sockaddr family
|
|
|
|
Return Value:
|
|
|
|
IP6 address corresponding to sockaddr.
|
|
If IP4 sockaddr it's IP4_MAPPED address.
|
|
If not IP4 or IP6 sockaddr IP6 addresss is zero.
|
|
|
|
--*/
|
|
{
|
|
IP6_ADDRESS ip6;
|
|
|
|
//
|
|
// switch on family
|
|
// - IP6 gets copy
|
|
// - IP4 gets IP4_MAPPED
|
|
// - bogus gets zero
|
|
//
|
|
|
|
switch ( pSockaddr->sa_family )
|
|
{
|
|
case AF_INET:
|
|
|
|
IP6_SET_ADDR_V4MAPPED(
|
|
& ip6,
|
|
((PSOCKADDR_IN)pSockaddr)->sin_addr.s_addr );
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
RtlCopyMemory(
|
|
&ip6,
|
|
& ((PSOCKADDR_IN6)pSockaddr)->sin6_addr,
|
|
sizeof(IP6_ADDRESS) );
|
|
break;
|
|
|
|
default:
|
|
|
|
RtlZeroMemory(
|
|
&ip6,
|
|
sizeof(IP6_ADDRESS) );
|
|
break;
|
|
}
|
|
|
|
return ip6;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
Sockaddr_BuildFromIp6(
|
|
OUT PSOCKADDR pSockaddr,
|
|
IN IP6_ADDRESS Ip6Addr,
|
|
IN WORD Port
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write IP6 address (straight 6 or v4 mapped) to sockaddr.
|
|
|
|
Arguments:
|
|
|
|
pSockaddr -- ptr to sockaddr to write to;
|
|
must be at least size of SOCKADDR_IN6
|
|
|
|
Ip6Addr -- IP6 addresss being written
|
|
|
|
Port -- port in net byte order
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
// zero
|
|
|
|
RtlZeroMemory(
|
|
pSockaddr,
|
|
sizeof(SOCKADDR_IN6) );
|
|
|
|
//
|
|
// determine whether IP6 or IP4
|
|
//
|
|
|
|
if ( IP6_IS_ADDR_V4MAPPED( &Ip6Addr ) )
|
|
{
|
|
PSOCKADDR_IN psa = (PSOCKADDR_IN) pSockaddr;
|
|
|
|
psa->sin_family = AF_INET;
|
|
psa->sin_port = Port;
|
|
|
|
psa->sin_addr.s_addr = IP6_GET_V4_ADDR( &Ip6Addr );
|
|
}
|
|
else // IP6
|
|
{
|
|
PSOCKADDR_IN6 psa = (PSOCKADDR_IN6) pSockaddr;
|
|
|
|
psa->sin6_family = AF_INET6;
|
|
psa->sin6_port = Port;
|
|
|
|
RtlCopyMemory(
|
|
&psa->sin6_addr,
|
|
&Ip6Addr,
|
|
sizeof(IP6_ADDRESS) );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
Sockaddr_BuildFromFlatAddr(
|
|
OUT PSOCKADDR pSockaddr,
|
|
IN OUT PDWORD pSockaddrLength,
|
|
IN BOOL fClearSockaddr,
|
|
IN PBYTE pAddr,
|
|
IN DWORD AddrLength,
|
|
IN DWORD AddrFamily
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert address in ptr\family\length to sockaddr.
|
|
|
|
Arguments:
|
|
|
|
pSockaddr -- sockaddr buffer to recv address
|
|
|
|
pSockaddrLength -- addr with length of sockaddr buffer
|
|
receives the actual sockaddr length
|
|
|
|
fClearSockaddr -- start with zero buffer
|
|
|
|
pAddr -- ptr to address
|
|
|
|
AddrLength -- address length
|
|
|
|
AddrFamily -- address family (AF_INET, AF_INET6)
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR if successful.
|
|
ERROR_INSUFFICIENT_BUFFER -- if buffer too small
|
|
WSAEAFNOSUPPORT -- if invalid family
|
|
|
|
--*/
|
|
{
|
|
PFAMILY_INFO pinfo;
|
|
DWORD lengthIn = *pSockaddrLength;
|
|
DWORD lengthSockAddr;
|
|
|
|
|
|
// clear to start
|
|
|
|
if ( fClearSockaddr )
|
|
{
|
|
RtlZeroMemory(
|
|
pSockaddr,
|
|
lengthIn );
|
|
}
|
|
|
|
// switch on type
|
|
|
|
if ( AddrFamily == AF_INET )
|
|
{
|
|
pinfo = pFamilyInfoIp4;
|
|
}
|
|
else if ( AddrFamily == AF_INET6 )
|
|
{
|
|
pinfo = pFamilyInfoIp6;
|
|
}
|
|
else if ( AddrFamily == AF_ATM )
|
|
{
|
|
pinfo = pFamilyInfoAtm;
|
|
}
|
|
else
|
|
{
|
|
return WSAEAFNOSUPPORT;
|
|
}
|
|
|
|
// validate lengths
|
|
|
|
if ( AddrLength != pinfo->LengthAddr )
|
|
{
|
|
return DNS_ERROR_INVALID_IP_ADDRESS;
|
|
}
|
|
|
|
lengthSockAddr = pinfo->LengthSockaddr;
|
|
*pSockaddrLength = lengthSockAddr;
|
|
|
|
if ( lengthIn < lengthSockAddr )
|
|
{
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
//
|
|
// fill out sockaddr
|
|
// - set family
|
|
// - copy address to sockaddr
|
|
// - return length was set above
|
|
//
|
|
|
|
RtlCopyMemory(
|
|
(PBYTE)pSockaddr + pinfo->OffsetToAddrInSockaddr,
|
|
pAddr,
|
|
AddrLength );
|
|
|
|
pSockaddr->sa_family = (WORD)AddrFamily;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
//
|
|
// End addr.c
|
|
//
|