1219 lines
28 KiB
C
1219 lines
28 KiB
C
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ipconfig.c
|
|
|
|
Abstract:
|
|
|
|
updated clean version of ipconfig.
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
#include <shellapi.h>
|
|
#include <dhcpcapi.h>
|
|
#include <locale.h>
|
|
#include <dnslib.h>
|
|
|
|
int InitLogger(const char *fname);
|
|
void DoneLogger(void);
|
|
|
|
DWORD
|
|
WriteOutput(
|
|
IN HANDLE hOut,
|
|
IN LPWSTR String
|
|
)
|
|
{
|
|
DWORD Error = NO_ERROR, Unused;
|
|
INT StringLen;
|
|
|
|
StringLen = wcslen(String);
|
|
if( GetFileType(hOut) == FILE_TYPE_CHAR )
|
|
{
|
|
if (StringLen < 0)
|
|
{
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
while (StringLen > 0)
|
|
{
|
|
if (!WriteConsoleW(hOut, String, min(StringLen, 1024), &Unused, 0 ))
|
|
{
|
|
Error = GetLastError();
|
|
break;
|
|
}
|
|
String += 1024;
|
|
StringLen -= 1024;
|
|
}
|
|
}
|
|
|
|
if( ERROR_INVALID_HANDLE != Error ) return Error;
|
|
}
|
|
|
|
//
|
|
// If it is not a console, this is good enough
|
|
//
|
|
|
|
printf("%ws", String );
|
|
return NO_ERROR;
|
|
}
|
|
|
|
BOOL
|
|
StringIsSame(
|
|
IN LPWSTR Str1,
|
|
IN LPWSTR Str2
|
|
)
|
|
{
|
|
return CSTR_EQUAL == CompareString(
|
|
LOCALE_USER_DEFAULT, NORM_IGNORECASE |
|
|
NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH,
|
|
Str1, -1, Str2, -2 );
|
|
}
|
|
|
|
DWORD
|
|
ParseCommandLine(
|
|
IN OUT PCMD_ARGS Args,
|
|
IN OUT LPWSTR *Argv,
|
|
IN DWORD Argc,
|
|
OUT LPWSTR *AdapterName,
|
|
OUT LPWSTR *ClassId
|
|
)
|
|
{
|
|
Argc --; Argv ++;
|
|
|
|
if( Argc == 0 ) return NO_ERROR;
|
|
|
|
if( **Argv != L'/' && **Argv != L'-' ) {
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
(*Argv)++;
|
|
|
|
if( StringIsSame(Args->Debug, *Argv) ) {
|
|
LocalFree( Args->Debug );
|
|
Args->Debug = NULL;
|
|
Argv ++;
|
|
Argc --;
|
|
|
|
if( **Argv != L'/' && **Argv != L'-' ) {
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
(*Argv)++;
|
|
}
|
|
|
|
if( Argc == 0 ) return NO_ERROR;
|
|
|
|
if( Argc >= 2 ) (*AdapterName) = Argv[1];
|
|
if( Argc == 3 ) (*ClassId) = Argv[2];
|
|
|
|
if( **Argv == L'?' ) {
|
|
return ERROR_INVALID_COMMAND_LINE;
|
|
}
|
|
|
|
if( StringIsSame(Args->All, *Argv) ) {
|
|
if( Argc != 1 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->All );
|
|
Args->All = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->FlushDns, *Argv) ) {
|
|
if( Argc != 1 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->FlushDns );
|
|
Args->FlushDns = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->Register, *Argv) ) {
|
|
if( Argc != 1 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->Register );
|
|
Args->Register = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->DisplayDns, *Argv) ) {
|
|
if( Argc != 1 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->DisplayDns );
|
|
Args->DisplayDns = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->Renew, *Argv) ) {
|
|
if( Argc > 2 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->Renew );
|
|
Args->Renew = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->Release, *Argv) ) {
|
|
if( Argc > 2 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->Release );
|
|
Args->Release = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->ShowClassId, *Argv) ) {
|
|
if( Argc != 2 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->ShowClassId );
|
|
Args->ShowClassId = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if( StringIsSame(Args->SetClassId, *Argv) ) {
|
|
if( Argc != 3 && Argc != 2 ) return ERROR_INVALID_DATA;
|
|
LocalFree( Args->SetClassId );
|
|
Args->SetClassId = NULL;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
return ERROR_INVALID_DATA;
|
|
}
|
|
|
|
BOOL
|
|
StringMatch(
|
|
IN LPWSTR Str1,
|
|
IN LPWSTR Str2,
|
|
IN BOOL fCase
|
|
)
|
|
{
|
|
switch( *Str1 ){
|
|
case L'\0' : return ! *Str2 ;
|
|
case L'*' : return StringMatch( Str1+1, Str2, fCase ) || *Str2 && StringMatch( Str1, Str2+1, fCase );
|
|
case L'?' : return *Str2 && StringMatch( Str1+1, Str2+1, fCase );
|
|
default : return (fCase ? *Str1 == *Str2 : toupper(*Str1) == toupper(*Str2)) && StringMatch( Str1+1, Str2+1, fCase );
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
InterfaceMatch(
|
|
IN PINTERFACE_NETWORK_INFO IfInfo,
|
|
IN LPWSTR AdapterName
|
|
)
|
|
{
|
|
if( NULL == AdapterName ) return TRUE;
|
|
|
|
if( IfInfo->ConnectionName != NULL ) {
|
|
return StringMatch( AdapterName, IfInfo->ConnectionName, FALSE );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD
|
|
DoRenew(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo,
|
|
IN LPWSTR AdapterName
|
|
)
|
|
{
|
|
DWORD i, FindCount, Error, LastError;
|
|
PINTERFACE_NETWORK_INFO IfInfo;
|
|
BOOL fSucceeded;
|
|
|
|
fSucceeded = FALSE;
|
|
FindCount = 0;
|
|
LastError = ERROR_INTERNAL_ERROR;
|
|
|
|
for( i = 0; i < NetInfo->nInterfaces; i ++ ) {
|
|
IfInfo = NetInfo->IfInfo[i];
|
|
|
|
if( !InterfaceMatch(IfInfo, AdapterName) ) continue;
|
|
|
|
FindCount ++;
|
|
|
|
if( !IfInfo->EnableDhcp || 0 == IfInfo->nIpAddresses ) {
|
|
if( NULL != AdapterName ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_OPERATION_ON_NONDHCP,
|
|
IfInfo->ConnectionName );
|
|
} else FindCount --;
|
|
} else if( IfInfo->MediaDisconnected ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_MEDIA_SENSE,
|
|
IfInfo->ConnectionName );
|
|
} else {
|
|
Error = DhcpAcquireParameters(IfInfo->DeviceGuidName);
|
|
|
|
if( NO_ERROR == Error ) {
|
|
fSucceeded = TRUE;
|
|
} else if (ERROR_SEM_TIMEOUT == Error) {
|
|
LastError = Error;
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_RENEW_FAILED_UNREACHABLE_DHCP,
|
|
IfInfo->ConnectionName );
|
|
} else {
|
|
LastError = Error;
|
|
DumpMessageError(
|
|
Buffer, BufSize, MSG_RENEW_FAILED, Error,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( fSucceeded ) return NO_ERROR;
|
|
if( FindCount == 0 ) {
|
|
DumpMessage( Buffer, BufSize, MSG_NO_MATCH );
|
|
}
|
|
|
|
return LastError;
|
|
}
|
|
|
|
DWORD
|
|
DoRelease(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo,
|
|
IN LPWSTR AdapterName
|
|
)
|
|
{
|
|
DWORD i, FindCount, Error, LastError;
|
|
PINTERFACE_NETWORK_INFO IfInfo;
|
|
BOOL fSucceeded;
|
|
|
|
fSucceeded = FALSE;
|
|
FindCount = 0;
|
|
LastError = ERROR_INTERNAL_ERROR;
|
|
|
|
for( i = 0; i < NetInfo->nInterfaces; i ++ ) {
|
|
IfInfo = NetInfo->IfInfo[i];
|
|
|
|
if( !InterfaceMatch(IfInfo, AdapterName) ) continue;
|
|
|
|
FindCount ++;
|
|
|
|
if( !IfInfo->EnableDhcp || 0 == IfInfo->nIpAddresses ) {
|
|
if( NULL != AdapterName ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_OPERATION_ON_NONDHCP,
|
|
IfInfo->ConnectionName );
|
|
} else FindCount --;
|
|
} else if( IfInfo->MediaDisconnected ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_MEDIA_SENSE,
|
|
IfInfo->ConnectionName );
|
|
} else if( IfInfo->IpAddress[0] == INADDR_ANY ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_ZERO_ADDRESS,
|
|
IfInfo->ConnectionName );
|
|
} else {
|
|
Error = DhcpReleaseParameters(IfInfo->DeviceGuidName);
|
|
|
|
if( NO_ERROR == Error ) {
|
|
fSucceeded = TRUE;
|
|
} else {
|
|
LastError = Error;
|
|
DumpMessageError(
|
|
Buffer, BufSize, MSG_RELEASE_FAILED, Error,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( fSucceeded ) return NO_ERROR;
|
|
if( FindCount == 0 ) {
|
|
DumpMessage( Buffer, BufSize, MSG_NO_MATCH );
|
|
}
|
|
|
|
return LastError;
|
|
}
|
|
|
|
DWORD
|
|
DoFlushDns(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo
|
|
)
|
|
{
|
|
DWORD Error;
|
|
|
|
UNREFERENCED_PARAMETER( NetInfo);
|
|
|
|
Error = DnsFlushResolverCache();
|
|
if( FALSE == Error ) {
|
|
Error = ERROR_FUNCTION_FAILED;
|
|
DumpMessageError(
|
|
Buffer, BufSize, MSG_FLUSHDNS_FAILED, Error, NULL );
|
|
} else {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_FLUSHDNS_SUCCEEDED );
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
extern DWORD DhcpStaticRefreshParams(IN LPWSTR Adapter);
|
|
|
|
DWORD
|
|
DoRegisterDns(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo
|
|
)
|
|
{
|
|
DWORD Error;
|
|
extern DWORD RegisterIPv6Dns(VOID);
|
|
|
|
//
|
|
// Since IPv6 call is asynchronous, no error doesn't necessarily
|
|
// mean the success of DNS registration. So ignore it.
|
|
//
|
|
Error = RegisterIPv6Dns();
|
|
|
|
Error = DhcpStaticRefreshParams(NULL);
|
|
if( NO_ERROR != Error ) {
|
|
DumpMessageError(
|
|
Buffer, BufSize, MSG_REGISTERDNS_FAILED, Error, NULL );
|
|
} else {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_REGISTERDNS_SUCCEEDED );
|
|
}
|
|
|
|
UNREFERENCED_PARAMETER( NetInfo );
|
|
return Error;
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintARecord (
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR IpAddr[20];
|
|
|
|
swprintf(
|
|
IpAddr,
|
|
L"%d.%d.%d.%d",
|
|
((BYTE *) &DnsRecord->Data.A.IpAddress)[0],
|
|
((BYTE *) &DnsRecord->Data.A.IpAddress)[1],
|
|
((BYTE *) &DnsRecord->Data.A.IpAddress)[2],
|
|
((BYTE *) &DnsRecord->Data.A.IpAddress)[3] );
|
|
|
|
DumpMessage( Buffer, BufSize, MSG_DNS_A_RECORD, IpAddr );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintSOARecord (
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR SerialNo[20], Refresh[20], Retry[20];
|
|
WCHAR Expire[20], Ttl[20];
|
|
|
|
swprintf( SerialNo, L"%d", DnsRecord->Data.SOA.dwSerialNo );
|
|
swprintf( Refresh, L"%d", DnsRecord->Data.SOA.dwRefresh );
|
|
swprintf( Retry, L"%d", DnsRecord->Data.SOA.dwRetry );
|
|
swprintf( Expire, L"%d", DnsRecord->Data.SOA.dwExpire );
|
|
swprintf( Ttl, L"%d", DnsRecord->Data.SOA.dwDefaultTtl );
|
|
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_SOA_RECORD,
|
|
DnsRecord->Data.SOA.pNamePrimaryServer,
|
|
DnsRecord->Data.SOA.pNameAdministrator,
|
|
SerialNo,
|
|
Refresh,
|
|
Retry,
|
|
Expire,
|
|
Ttl );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintPTRRecord (
|
|
IN ULONG MsgId,
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
DumpMessage(
|
|
Buffer,
|
|
BufSize,
|
|
MsgId,
|
|
DnsRecord->Data.PTR.pNameHost );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintMXRecord (
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR Pref[20], Pad[20];
|
|
|
|
swprintf( Pref, L"%d", DnsRecord->Data.MX.wPreference );
|
|
swprintf( Pad, L"%d", DnsRecord->Data.MX.Pad );
|
|
|
|
DumpMessage(
|
|
Buffer,
|
|
BufSize,
|
|
MSG_DNS_MX_RECORD,
|
|
DnsRecord->Data.MX.pNameExchange,
|
|
Pref,
|
|
Pad );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintAAAARecord(
|
|
IN OUT PWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR stringIp6[IP6_ADDRESS_STRING_BUFFER_LENGTH];
|
|
|
|
Dns_Ip6AddressToString_W(
|
|
stringIp6,
|
|
& DnsRecord->Data.AAAA.Ip6Address );
|
|
|
|
DumpMessage(
|
|
Buffer,
|
|
BufSize,
|
|
MSG_DNS_AAAA_RECORD,
|
|
stringIp6 );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintSRVRecord (
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR Priority[20], Weight[20], Port[20];
|
|
|
|
swprintf( Priority, L"%d", DnsRecord->Data.SRV.wPriority );
|
|
swprintf( Weight, L"%d", DnsRecord->Data.SRV.wWeight );
|
|
swprintf( Port, L"%d", DnsRecord->Data.SRV.wPort );
|
|
|
|
DumpMessage(
|
|
Buffer,
|
|
BufSize,
|
|
MSG_DNS_SRV_RECORD,
|
|
DnsRecord->Data.SRV.pNameTarget,
|
|
Priority,
|
|
Weight,
|
|
Port );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintATMARecord (
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR Type[20], Address[300];
|
|
|
|
swprintf( Type, L"%d", DnsRecord->Data.ATMA.AddressType );
|
|
|
|
if ( DnsRecord->Data.ATMA.Address &&
|
|
DnsRecord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 ) {
|
|
|
|
swprintf(
|
|
Address,
|
|
L"%S",
|
|
DnsRecord->Data.ATMA.Address );
|
|
|
|
} else {
|
|
DWORD iter;
|
|
|
|
for ( iter = 0; iter < DnsRecord->wDataLength; iter++ ) {
|
|
|
|
swprintf(
|
|
&Address[iter*2],
|
|
L"%02x",
|
|
DnsRecord->Data.ATMA.Address[iter]
|
|
);
|
|
}
|
|
}
|
|
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_ATMA_RECORD, Type, Address );
|
|
|
|
}
|
|
|
|
VOID
|
|
PrintDnsRecord(
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
WCHAR Type[20], Ttl[20], DataLen[20];
|
|
DWORD MsgId;
|
|
|
|
if ( ! DnsRecord ) return;
|
|
|
|
swprintf( Type, L"%d", DnsRecord->wType );
|
|
swprintf( Ttl, L"%d", DnsRecord->dwTtl );
|
|
swprintf( DataLen, L"%d", DnsRecord->wDataLength );
|
|
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_RECORD_HEADER,
|
|
DnsRecord->pName, (LPWSTR)Type, (LPWSTR)Ttl,
|
|
(LPWSTR)DataLen );
|
|
|
|
if ( DnsRecord->Flags.S.Section == DNSREC_QUESTION ) {
|
|
MsgId = MSG_DNS_QUESTION_SECTION;
|
|
} else if ( DnsRecord->Flags.S.Section == DNSREC_ANSWER ) {
|
|
MsgId = MSG_DNS_ANSWER_SECTION;
|
|
} else if ( DnsRecord->Flags.S.Section == DNSREC_AUTHORITY ) {
|
|
MsgId = MSG_DNS_AUTHORITY_SECTION;
|
|
} else {
|
|
MsgId = MSG_DNS_ADDITIONAL_SECTION;
|
|
}
|
|
|
|
DumpMessage( Buffer, BufSize, MsgId );
|
|
|
|
switch( DnsRecord->wType )
|
|
{
|
|
case DNS_TYPE_A :
|
|
PrintARecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_SOA :
|
|
PrintSOARecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_PTR :
|
|
PrintPTRRecord(
|
|
MSG_DNS_PTR_RECORD, Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_NS :
|
|
PrintPTRRecord(
|
|
MSG_DNS_NS_RECORD, Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_CNAME :
|
|
PrintPTRRecord(
|
|
MSG_DNS_CNAME_RECORD, Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_MX :
|
|
PrintMXRecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_AAAA :
|
|
PrintAAAARecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_SRV :
|
|
PrintSRVRecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
case DNS_TYPE_ATMA :
|
|
PrintATMARecord( Buffer, BufSize, DnsRecord );
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PrintDnsRecords(
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PDNS_RECORD DnsRecord
|
|
)
|
|
{
|
|
PDNS_RECORD Tmp = DnsRecord;
|
|
|
|
while( Tmp ) {
|
|
PrintDnsRecord( Buffer, BufSize, Tmp );
|
|
Tmp = Tmp->pNext;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetDnsCachedData(
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN LPWSTR Name,
|
|
IN WORD Type
|
|
)
|
|
{
|
|
PDNS_RECORD DnsRecord = NULL;
|
|
DNS_STATUS DnsStatus;
|
|
|
|
DnsStatus = DnsQuery_W(
|
|
Name,
|
|
Type,
|
|
DNS_QUERY_CACHE_ONLY,
|
|
NULL,
|
|
& DnsRecord,
|
|
NULL );
|
|
|
|
if ( DnsStatus != NO_ERROR ) {
|
|
|
|
if ( DnsStatus == DNS_INFO_NO_RECORDS ) {
|
|
|
|
WCHAR wsTypeName[ 20 ];
|
|
|
|
Dns_WriteStringForType_W(
|
|
wsTypeName,
|
|
Type );
|
|
|
|
DumpMessage(
|
|
Buffer,
|
|
BufSize,
|
|
MSG_DNS_ERR_NO_RECORDS,
|
|
Name,
|
|
wsTypeName );
|
|
|
|
} else if ( DnsStatus == DNS_ERROR_RCODE_NAME_ERROR ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_ERR_NAME_ERROR, Name );
|
|
|
|
} else if ( DnsStatus == DNS_ERROR_RECORD_DOES_NOT_EXIST ) {
|
|
//
|
|
// Don't print?
|
|
//
|
|
} else {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_ERR_UNABLE_TO_DISPLAY,
|
|
Name );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if ( DnsRecord ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DNS_RECORD_PREAMBLE, Name );
|
|
|
|
PrintDnsRecords( Buffer, BufSize, DnsRecord );
|
|
DnsRecordListFree( DnsRecord, TRUE );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
DisplayDnsCacheData(
|
|
IN OUT LPWSTR Buffer,
|
|
IN ULONG BufSize
|
|
)
|
|
{
|
|
PDNS_CACHE_TABLE pDNSCacheTable = NULL;
|
|
PDNS_CACHE_TABLE pTempDNSCacheTable = NULL;
|
|
|
|
if( !DnsGetCacheDataTable( &pDNSCacheTable ) ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_DISPLAYDNS_FAILED );
|
|
return;
|
|
}
|
|
|
|
pTempDNSCacheTable = pDNSCacheTable;
|
|
|
|
while( pTempDNSCacheTable ) {
|
|
PDNS_CACHE_TABLE pNext = pTempDNSCacheTable->pNext;
|
|
|
|
if( pTempDNSCacheTable->Type1 != DNS_TYPE_ZERO ) {
|
|
GetDnsCachedData(
|
|
Buffer, BufSize, pTempDNSCacheTable->Name,
|
|
pTempDNSCacheTable->Type1 );
|
|
}
|
|
|
|
if( pTempDNSCacheTable->Type2 != DNS_TYPE_ZERO ) {
|
|
GetDnsCachedData(
|
|
Buffer, BufSize, pTempDNSCacheTable->Name,
|
|
pTempDNSCacheTable->Type2 );
|
|
}
|
|
|
|
if( pTempDNSCacheTable->Type3 != DNS_TYPE_ZERO ) {
|
|
GetDnsCachedData(
|
|
Buffer, BufSize, pTempDNSCacheTable->Name,
|
|
pTempDNSCacheTable->Type3 );
|
|
}
|
|
|
|
if( pTempDNSCacheTable->Name ) {
|
|
LocalFree( pTempDNSCacheTable->Name );
|
|
}
|
|
|
|
LocalFree( pTempDNSCacheTable );
|
|
|
|
pTempDNSCacheTable = pNext;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
DoDisplayDns(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER( NetInfo);
|
|
|
|
DisplayDnsCacheData( Buffer, BufSize );
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
DoShowClassId(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo,
|
|
IN LPWSTR AdapterName
|
|
)
|
|
{
|
|
DWORD i, Error, Size, nClassesPrinted;
|
|
PINTERFACE_NETWORK_INFO IfInfo;
|
|
DHCP_CLASS_INFO *pClasses;
|
|
|
|
IfInfo = NULL;
|
|
for( i = 0; i < NetInfo->nInterfaces; i ++ ) {
|
|
IfInfo = NetInfo->IfInfo[i];
|
|
|
|
if( !InterfaceMatch(IfInfo, AdapterName) ) continue;
|
|
|
|
if( !IfInfo->DeviceGuidName ) continue;
|
|
|
|
break;
|
|
}
|
|
|
|
if( i == NetInfo->nInterfaces ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_NO_MATCH );
|
|
return ERROR_NOT_FOUND;
|
|
}
|
|
|
|
do {
|
|
Size = 0; pClasses = NULL;
|
|
Error = DhcpEnumClasses(
|
|
0, IfInfo->DeviceGuidName, &Size, pClasses
|
|
);
|
|
|
|
if( ERROR_MORE_DATA != Error ) {
|
|
if( NO_ERROR == Error ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_NO_CLASSES,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
pClasses = LocalAlloc(LMEM_FIXED, Size);
|
|
if( NULL == pClasses ) {
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
Error = DhcpEnumClasses(
|
|
0, IfInfo->DeviceGuidName, &Size, pClasses
|
|
);
|
|
|
|
if( NO_ERROR != Error ) {
|
|
LocalFree(pClasses);
|
|
break;
|
|
}
|
|
|
|
nClassesPrinted = Size;
|
|
|
|
if( nClassesPrinted ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_CLASSES_LIST_HEADER,
|
|
IfInfo->ConnectionName );
|
|
|
|
for( i = 0; i < nClassesPrinted ; i ++ ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_CLASSID,
|
|
pClasses[i].ClassName, pClasses[i].ClassDescr );
|
|
}
|
|
} else {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_NO_CLASSES,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
|
|
LocalFree(pClasses);
|
|
} while ( 0 );
|
|
|
|
if( NO_ERROR != Error ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_CLASSID_FAILED, Error,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
DWORD
|
|
DoSetClassId(
|
|
IN LPWSTR Buffer,
|
|
IN ULONG BufSize,
|
|
IN PNETWORK_INFO NetInfo,
|
|
IN LPWSTR AdapterName,
|
|
IN LPWSTR ClassId
|
|
)
|
|
{
|
|
DWORD i, Error;
|
|
PINTERFACE_NETWORK_INFO IfInfo;
|
|
HKEY hKey;
|
|
DHCP_PNP_CHANGE Changes;
|
|
|
|
IfInfo = NULL;
|
|
for( i = 0; i < NetInfo->nInterfaces; i ++ ) {
|
|
IfInfo = NetInfo->IfInfo[i];
|
|
|
|
if( !InterfaceMatch(IfInfo, AdapterName) ) continue;
|
|
|
|
if( !IfInfo->DeviceGuidName ) continue;
|
|
|
|
break;
|
|
}
|
|
|
|
if( i == NetInfo->nInterfaces ) {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_NO_MATCH );
|
|
return ERROR_NOT_FOUND;
|
|
}
|
|
|
|
Error = OpenRegKey(
|
|
IfInfo->DeviceGuidName, OpenTcpipKey, OpenKeyForWrite,
|
|
&hKey );
|
|
if( NO_ERROR != Error ) {
|
|
DumpErrorMessage(
|
|
Buffer, BufSize, InterfaceOpenTcpipKeyReadFailure,
|
|
Error );
|
|
return Error;
|
|
}
|
|
|
|
|
|
if( NULL == ClassId ) ClassId = (LPWSTR)L"";
|
|
|
|
RegSetValueExW(
|
|
hKey, (LPWSTR) L"DhcpClassId", 0, REG_SZ,
|
|
(LPBYTE)ClassId, sizeof(WCHAR)*(1+wcslen(ClassId)) );
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
ZeroMemory(&Changes, sizeof(Changes));
|
|
Changes.ClassIdChanged = TRUE;
|
|
|
|
Error = DhcpHandlePnPEvent(
|
|
0, DHCP_CALLER_TCPUI, IfInfo->DeviceGuidName, &Changes,
|
|
NULL );
|
|
|
|
if( NO_ERROR != Error ) {
|
|
DumpMessageError(
|
|
Buffer, BufSize, MSG_SETCLASSID_FAILED, Error,
|
|
IfInfo->ConnectionName );
|
|
} else {
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_SETCLASSID_SUCCEEDED,
|
|
IfInfo->ConnectionName );
|
|
}
|
|
|
|
return Error;
|
|
}
|
|
|
|
void _cdecl main(void)
|
|
{
|
|
WCHAR TmpBuffer[8000];
|
|
WCHAR *Buffer;
|
|
DWORD LocalError, Error, InternalError, BufSize = 512;
|
|
PNETWORK_INFO NetInfo;
|
|
LPWSTR *Argv, CommandLine, AdapterName, ClassId;
|
|
int Argc;
|
|
CMD_ARGS Args;
|
|
BOOL fVerbose;
|
|
BOOL fDebug;
|
|
BOOL fDisplay;
|
|
|
|
UNREFERENCED_PARAMETER(InternalError);
|
|
UNREFERENCED_PARAMETER(NetInfo);
|
|
|
|
//
|
|
// bug 211927: set the locale to the system default
|
|
//
|
|
setlocale ( LC_ALL, "" );
|
|
|
|
InitLogger("ipconfig.log");
|
|
|
|
CommandLine = GetCommandLineW();
|
|
if( NULL == CommandLine ) {
|
|
DbgPrint("GetCommandLineW: 0x%x\n", GetLastError());
|
|
DoneLogger();
|
|
exit(1);
|
|
}
|
|
|
|
Argv = CommandLineToArgvW(CommandLine, &Argc );
|
|
if( NULL == Argv ) {
|
|
DbgPrint("CommandLineToArgvW: 0x%x\n", GetLastError());
|
|
DoneLogger();
|
|
exit(1);
|
|
}
|
|
|
|
Error = GetCommandArgConstants( &Args );
|
|
if( NO_ERROR != Error ) {
|
|
DbgPrint("GetCommandArgConstants: 0x%lx\n", Error );
|
|
DoneLogger();
|
|
exit(1);
|
|
}
|
|
|
|
AdapterName = NULL; ClassId = NULL;
|
|
|
|
//
|
|
// The ParseCommandLine routine NULLs out the field in Args
|
|
// that was supplied by teh user... i.e ipconfig /renew would
|
|
// cause Args.Renew to be NULL on return
|
|
//
|
|
|
|
Error = ParseCommandLine(
|
|
&Args, Argv, Argc, &AdapterName, &ClassId );
|
|
if( ERROR_INVALID_COMMAND_LINE == Error ) {
|
|
WriteOutput( GetStdHandle( STD_OUTPUT_HANDLE), Args.Usage );
|
|
DoneLogger();
|
|
exit(1);
|
|
}
|
|
|
|
if( NO_ERROR != Error ) {
|
|
WriteOutput( GetStdHandle( STD_OUTPUT_HANDLE), Args.UsageErr );
|
|
WriteOutput( GetStdHandle( STD_OUTPUT_HANDLE), Args.Usage );
|
|
DoneLogger();
|
|
exit(1);
|
|
}
|
|
|
|
fVerbose = (Args.All == NULL);
|
|
fDebug = (Args.Debug == NULL);
|
|
fDisplay = FALSE;
|
|
|
|
NetInfo = NULL;
|
|
|
|
Error = GetNetworkInformation(
|
|
&NetInfo, &InternalError );
|
|
|
|
//
|
|
// Calculate how much space it would take to display a full display..
|
|
//
|
|
|
|
do {
|
|
Buffer = LocalAlloc( LPTR, sizeof(WCHAR)*BufSize );
|
|
if( Buffer == NULL ) break;
|
|
|
|
LocalError = FormatNetworkInfo(
|
|
Buffer, BufSize, NetInfo,
|
|
Error,InternalError,TRUE,fDebug);
|
|
|
|
LocalFree(Buffer);
|
|
BufSize *= 2;
|
|
} while( NO_ERROR != LocalError );
|
|
|
|
if( NULL != Buffer ) {
|
|
Buffer = LocalAlloc( LPTR, sizeof(WCHAR)*BufSize );
|
|
}
|
|
|
|
if( NULL == Buffer ) {
|
|
Buffer = (LPWSTR)TmpBuffer;
|
|
BufSize = sizeof(TmpBuffer)/sizeof(WCHAR);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
DumpMessage(
|
|
Buffer, BufSize, MSG_TITLE );
|
|
|
|
if( NO_ERROR != Error || Args.All == NULL ) {
|
|
fDisplay = TRUE;
|
|
} else if( Args.Renew == NULL ) {
|
|
//
|
|
// Attempt to renew
|
|
//
|
|
|
|
Error = DoRenew( Buffer, BufSize, NetInfo, AdapterName);
|
|
fDisplay = (NO_ERROR == Error);
|
|
|
|
if( fDisplay ) {
|
|
FreeNetworkInfo( NetInfo );
|
|
Error = GetNetworkInformation(
|
|
&NetInfo, &InternalError );
|
|
}
|
|
|
|
} else if( Args.Release == NULL ) {
|
|
//
|
|
// Attempt to renew
|
|
//
|
|
|
|
Error = DoRelease( Buffer, BufSize, NetInfo, AdapterName);
|
|
fDisplay = (NO_ERROR == Error);
|
|
|
|
if( fDisplay ) {
|
|
FreeNetworkInfo( NetInfo );
|
|
Error = GetNetworkInformation(
|
|
&NetInfo, &InternalError );
|
|
}
|
|
} else if( Args.FlushDns == NULL ) {
|
|
|
|
DoFlushDns( Buffer, BufSize, NetInfo );
|
|
} else if( Args.Register == NULL ) {
|
|
|
|
DoRegisterDns( Buffer, BufSize, NetInfo );
|
|
} else if( Args.DisplayDns == NULL ) {
|
|
|
|
DoDisplayDns( Buffer, BufSize, NetInfo );
|
|
} else if( Args.ShowClassId == NULL ) {
|
|
|
|
DoShowClassId( Buffer, BufSize, NetInfo, AdapterName );
|
|
} else if( Args.SetClassId == NULL ) {
|
|
|
|
DoSetClassId( Buffer, BufSize, NetInfo, AdapterName, ClassId );
|
|
} else {
|
|
fDisplay = TRUE;
|
|
}
|
|
|
|
if( fDisplay ) {
|
|
FormatNetworkInfo(
|
|
Buffer, BufSize, NetInfo,
|
|
Error, InternalError, fVerbose, fDebug );
|
|
}
|
|
|
|
Error = WriteOutput( GetStdHandle( STD_OUTPUT_HANDLE), Buffer );
|
|
if (Error != NO_ERROR)
|
|
{
|
|
Buffer[0] = L'\0';
|
|
DumpMessage(Buffer, BufSize, MSG_TITLE );
|
|
DumpErrorMessage(Buffer, BufSize, NoSpecificError, Error);
|
|
WriteOutput( GetStdHandle( STD_OUTPUT_HANDLE ), Buffer );
|
|
}
|
|
|
|
FreeNetworkInfo(NetInfo);
|
|
GlobalFree( Argv );
|
|
LocalFree( Args.All );
|
|
LocalFree( Args.Renew );
|
|
LocalFree( Args.Release );
|
|
LocalFree( Args.FlushDns );
|
|
LocalFree( Args.Register );
|
|
LocalFree( Args.DisplayDns );
|
|
LocalFree( Args.ShowClassId );
|
|
LocalFree( Args.SetClassId );
|
|
LocalFree( Args.Debug );
|
|
LocalFree( Args.Usage );
|
|
|
|
DoneLogger();
|
|
exit(0);
|
|
}
|
|
|
|
|
|
DWORD
|
|
RegisterIPv6Dns(VOID)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
SC_HANDLE hcm = NULL;
|
|
SC_HANDLE hSvc = NULL;
|
|
SERVICE_STATUS status = {0};
|
|
#define SERVICE_CONTROL_6TO4_REGISER_DNS 128
|
|
|
|
do
|
|
{
|
|
hcm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
|
if (NULL == hcm)
|
|
{
|
|
dwErr = GetLastError();
|
|
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("OpenSCManager returns 0x%lx (%d)\n", dwErr, dwErr));
|
|
break;
|
|
}
|
|
|
|
hSvc = OpenService(hcm, L"6to4", SERVICE_USER_DEFINED_CONTROL);
|
|
if (NULL == hSvc)
|
|
{
|
|
dwErr = GetLastError();
|
|
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("OpenService returns 0x%lx (%d)\n", dwErr, dwErr));
|
|
break;
|
|
}
|
|
|
|
|
|
if (!ControlService(hSvc, SERVICE_CONTROL_6TO4_REGISER_DNS, &status))
|
|
{
|
|
dwErr = GetLastError();
|
|
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("ControlService returns 0x%lx (%d)\n", dwErr, dwErr));
|
|
break;
|
|
}
|
|
} while (FALSE);
|
|
|
|
if (hSvc)
|
|
{
|
|
CloseServiceHandle(hSvc);
|
|
}
|
|
|
|
if (hcm)
|
|
{
|
|
CloseServiceHandle(hcm);
|
|
}
|
|
|
|
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("RegisterIPv6Dns returns 0x%lx (%d)\n", dwErr, dwErr));
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
#ifdef __IPCFG_ENABLE_LOG__
|
|
DWORD dwTraceFlag = 0xffffffffU;
|
|
static FILE *hLogger = NULL;
|
|
int
|
|
InitLogger(const char *fname)
|
|
{
|
|
if (hLogger) {
|
|
fclose(hLogger);
|
|
}
|
|
hLogger = fopen(fname, "w+");
|
|
return (hLogger == NULL)? (-1): 0;
|
|
}
|
|
|
|
void
|
|
DoneLogger(void)
|
|
{
|
|
if (hLogger) {
|
|
fclose(hLogger);
|
|
hLogger = NULL;
|
|
}
|
|
}
|
|
|
|
int
|
|
TraceFunc(const char* fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (hLogger != NULL) {
|
|
va_start(ap, fmt);
|
|
vfprintf(hLogger, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
return 0;
|
|
}
|
|
#else
|
|
int InitLogger(const char *fname)
|
|
{
|
|
UNREFERENCED_PARAMETER(fname);
|
|
return 0;
|
|
}
|
|
|
|
void DoneLogger(void) {}
|
|
|
|
int TraceFunc(const char* fmt, ...)
|
|
{
|
|
UNREFERENCED_PARAMETER(fmt);
|
|
return 0;
|
|
}
|
|
#endif
|