/* * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A * PARTICULAR PURPOSE. * * Copyright © Microsoft Corporation. All Rights Reserved. * * Author: Yashlaxmi Gupta * Abstract: * Dump IPv4 leases across all the scopes configured on a DHCP server. * */ /* * Includes */ #include #include #include #include #include #include #define SERVERNAME_BUF_SIZE 255 #define IPADDR_BUF_SIZE 36 #define MAX_DATE_TIME_BUF_SIZE 64 #define DHCP_DATE_TIME_INFINITE_LOW 0xFFFFFFFF #define DHCP_DATE_TIME_INFINITE_HIGH 0x7FFFFFFF #define DHCP_DATE_TIME_ZERO_LOW 0 #define DHCP_DATE_TIME_ZERO_HIGH 0 WCHAR *ConvertIpAddtoWstr( __in DHCP_IP_ADDRESS addr ); WCHAR *GetHardwareAddress( __in DHCP_CLIENT_UID phyAdd ); WCHAR *GetDateTimeString( __in FILETIME ftTime ); DWORD __cdecl main(int argc, char* argv[]) { DHCP_RESUME_HANDLE ResumeHandleScope = 0; LPDHCP_IP_ARRAY EnumScopes = NULL; DWORD nRead = 0; DWORD nTotal = 0; DHCP_RESUME_HANDLE ResumeHandleClient = 0; LPDHCP_CLIENT_INFO_ARRAY_V5 Clients = NULL; DWORD nClientsRead = 0; DWORD nClientsTotal = 0; DWORD error1 = ERROR_SUCCESS, error2 = ERROR_SUCCESS; WCHAR *szDateTimeStr = NULL, *szClientIp = NULL, *szSubnetMask = NULL, *szHardwareAdd = NULL, *szScopeIp = NULL; WCHAR szServer[SERVERNAME_BUF_SIZE]={0}; if (2 != argc) { wprintf(L"Usage: DhcpServerShowLeasesV4.exe "); return ERROR_INVALID_PARAMETER; } MultiByteToWideChar(0, 0, argv[1], (int)strlen(argv[1]), szServer, SERVERNAME_BUF_SIZE); do { // enumerate all the IpV4 scopes on the server. error1 = DhcpEnumSubnets(szServer, &ResumeHandleScope, (DWORD)~0, &EnumScopes, &nRead, &nTotal); if (0 == nTotal) { wprintf(L"No scopes on this server.\n\n"); } if (ERROR_NO_MORE_ITEMS == error1) { break; } if (ERROR_SUCCESS != error1 && ERROR_MORE_DATA != error1) { wprintf(L"DhcpServerShowLeasesV4 returned with error: %d\n",error1); return error1; } // iterating over all the scopes one by one to get the clients for each scope. for (unsigned int count=0; count < EnumScopes->NumElements; count++) { // converting scope IP address from DWORD to LPWSTR szScopeIp = ConvertIpAddtoWstr(EnumScopes->Elements[count]); wprintf(L"\nScope : %s\n\n",szScopeIp ? szScopeIp : L" "); do { // enumerating the clients on a specific IpV4 scope error2 = DhcpEnumSubnetClientsV5(szServer, EnumScopes->Elements[count], &ResumeHandleClient, (DWORD)~0, &Clients, &nClientsRead, &nClientsTotal); if (0 == nClientsTotal) { wprintf(L"No clients on this scope.\n\n"); } if (ERROR_NO_MORE_ITEMS == error2) { break; } if (ERROR_SUCCESS != error2 && ERROR_MORE_DATA != error2) { wprintf(L"DhcpServerShowLeasesV4 returned with error: %d\n",error2); return error2; } //iterating over all the clients leases on a specified scope. //the leases shown include all the leases present and can be filtered out on the basic of Address State attribute of client. for (unsigned int count = 0; count < Clients->NumElements; count++) { //converting client Ip from DWORD to LPWSTR szClientIp = ConvertIpAddtoWstr(Clients->Clients[count]->ClientIpAddress); wprintf(L"Client Address : %s\n",szClientIp ? szClientIp : L" "); //converting scope subnet mask from DWORD to LPWSTR szSubnetMask = ConvertIpAddtoWstr(Clients->Clients[count]->SubnetMask); wprintf(L"Subnet Mask : %s\n",szSubnetMask ? szSubnetMask : L" "); //converting client hardware address from byte * to LPWSTR szHardwareAdd = GetHardwareAddress(Clients->Clients[count]->ClientHardwareAddress); wprintf(L"Hardware Address : %s\n",szHardwareAdd ? szHardwareAdd : L" "); // if lease duration is infinite then lease never expires. if (DHCP_DATE_TIME_INFINITE_LOW == Clients->Clients[count]->ClientLeaseExpires.dwLowDateTime && DHCP_DATE_TIME_INFINITE_HIGH == Clients->Clients[count]->ClientLeaseExpires.dwHighDateTime) { wprintf(L"Lease Expires : Never\n"); } // if lease duration is 0 the client is inactive. else if (DHCP_DATE_TIME_ZERO_LOW == Clients->Clients[count]->ClientLeaseExpires.dwLowDateTime && DHCP_DATE_TIME_ZERO_HIGH == Clients->Clients[count]->ClientLeaseExpires.dwHighDateTime) { wprintf(L"Lease Expires : Inactive\n"); } else { // converting the date time information from FILETIME * to LPWSTR. szDateTimeStr = GetDateTimeString(*(FILETIME *)(&Clients->Clients[count]->ClientLeaseExpires)); wprintf(L"Lease Expires : %s\n", szDateTimeStr ? szDateTimeStr : L" "); } wprintf(L"Client Name : %s\n",Clients->Clients[count]->ClientName ? Clients->Clients[count]->ClientName : L" "); wprintf(L"Client Comment : %s\n\n",Clients->Clients[count]->ClientComment ? Clients->Clients[count]->ClientComment : L" "); if (NULL != szClientIp) { free(szClientIp); szClientIp = NULL; } if (NULL != szSubnetMask) { free(szSubnetMask); szSubnetMask = NULL; } if (NULL != szHardwareAdd) { free(szHardwareAdd); szHardwareAdd = NULL; } if (NULL != szDateTimeStr) { free(szDateTimeStr); szDateTimeStr = NULL; } } if (NULL != Clients) { DhcpRpcFreeMemory(Clients); Clients = NULL; } nClientsRead = 0; nClientsTotal = 0; ResumeHandleClient = 0; } while (ERROR_MORE_DATA == error2); if (NULL != szScopeIp) { free(szScopeIp); szScopeIp = NULL; } } if (NULL != EnumScopes) { DhcpRpcFreeMemory(EnumScopes); EnumScopes = NULL; } nRead = 0; nTotal = 0; ResumeHandleScope = 0; } while (ERROR_MORE_DATA == error1); return 0; } WCHAR *ConvertIpAddtoWstr( __in DHCP_IP_ADDRESS addr ) { // getting the individual bytes of the IP Address. PUCHAR pAddress = (PUCHAR)&addr; // allocating memory to IP Address string. WCHAR *szIpAddress = (WCHAR *)malloc(IPADDR_BUF_SIZE); if (NULL == szIpAddress) { return NULL; } memset(szIpAddress, 0, IPADDR_BUF_SIZE); // creating the IP Address string HRESULT HRes = StringCchPrintfW(szIpAddress, IPADDR_BUF_SIZE, L"%ld.%ld.%ld.%ld",pAddress[3],pAddress[2],pAddress[1],pAddress[0]); if (FAILED(HRes)) { return NULL; } return szIpAddress; } WCHAR *GetHardwareAddress( __in DHCP_CLIENT_UID phyAdd ) { HRESULT HRes = S_OK; WCHAR *szPhysicalAddress = NULL; DWORD Size = 0; DWORD i=0, j=0, num0=0, num1=0, num2=0; if (NULL != phyAdd.Data && 0 < phyAdd.DataLength) { // calculating the ecount of the hardware address string. // corressponding to each byte in the original string, there would be a hyphen and a '\0' character for the last one. HRes = DWordMult(3, phyAdd.DataLength, &Size); if (FAILED(HRes)) { return NULL; } // calculating the bcount of the hardware address string. HRes = DWordMult(Size, sizeof(WCHAR), &Size); if (FAILED(HRes)) { return NULL; } // allocating the memory for the hardware address string. szPhysicalAddress = (WCHAR *)malloc(Size); if (NULL == szPhysicalAddress) { return NULL; } memset(szPhysicalAddress, 0, Size); for (i=0; i