From 2edf81d6945ea100d69f9132aecc1e8e1a67d74f Mon Sep 17 00:00:00 2001 From: correy <112426112@qq.com> Date: Thu, 1 Feb 2024 09:19:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0SDK=E7=9A=84ARP=E4=BE=8B?= =?UTF-8?q?=E5=AD=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NetTool/IPArp.Cpp | 547 ++++++++++++++++++++++++++++++++ NetTool/IPArp.h | 38 +++ NetTool/NetTool.cpp | 5 + NetTool/NetTool.vcxproj | 2 + NetTool/NetTool.vcxproj.filters | 6 + NetTool/NetTool.vcxproj.user | 2 +- 6 files changed, 599 insertions(+), 1 deletion(-) create mode 100644 NetTool/IPArp.Cpp create mode 100644 NetTool/IPArp.h diff --git a/NetTool/IPArp.Cpp b/NetTool/IPArp.Cpp new file mode 100644 index 0000000..622ba30 --- /dev/null +++ b/NetTool/IPArp.Cpp @@ -0,0 +1,547 @@ +/*--------------------------------------------------------------------------- + Copyright (c) 1998 - 2000 Microsoft Corporation + Module Name: IpArp.exe + File : IpArp.cpp + Description: This file demonstrates the use of IP Helper APIs to + manipulate ARP cache. + Author: + Frank Li April 16, 1998 + + + Revision History: + Who Wen What + -------- -------- ---------------------------------- + Frank Li 04-16-98 created +---------------------------------------------------------------------------*/ + +#include "IpArp.h" + +#define IPADDR_BUF_SIZE 128 +#define IPTYPE_BUF_SIZE 128 +#define PHYSADDR_BUF_SIZE 256 + +#pragma warning(disable:4996) + +void Usage(const char * pszProgramName) +{ + printf("%s -s inet_addr eth_addr [if_addr]\n", pszProgramName); + printf("%s -d inet_addr [if_addr]\n", pszProgramName); + printf("%s -a\n", pszProgramName); + + printf("-a Displays current ARP entries by interrogating the current\n"); + printf(" protocol data.\n"); + printf("-d Deletes the host specified by inet_addr.\n"); + printf("-s Adds the host and associates the Internet address inet_addr\n"); + printf(" with the Physical address eth_addr. The Physical address is\n"); + printf(" given as 6 hexadecimal bytes separated by hyphens. The entry\n"); + printf(" is permanent.\n"); + printf("eth_addr Specifies a physical address.\n"); + printf("if_addr If present, this specifies the Internet address of the\n"); + printf(" interface whose address translation table should be modified.\n"); + printf(" If not present, the first applicable interface will be used.\n"); + printf("Example:\n"); + printf(" >IpArp -s 157.55.85.212 00-aa-bb-cc-dd-ee 0x2000003 .... Add a static\n"); + printf(" arp entry on interface number 0x2000003.\n"); + printf(" >IpArp -a ....Displays the arp table.\n"); + printf(" >IpArp -d 157.55.85.212 ....Delete an entry.\n"); + WSACleanup(); + exit(1); +} + + +void _cdecl IpArp(int argc, char **argv) +//\Windows-classic-samples\Samples\Win7Samples\netds\iphelp\iparp\IPArp.Cpp +{ + WORD wVersionRequested = MAKEWORD(1,1); + WSADATA wsaData; + int nRet; + + nRet = WSAStartup(wVersionRequested, &wsaData); + if (wsaData.wVersion != wVersionRequested) + { + fprintf(stderr,"\n Wrong version\n"); + return; + } + + + if ((argc < 2) || (argv[1][0] != '-')) + Usage("IpArp"); + if (strlen(argv[1]) > 2) + Usage("IpArp"); + + switch(argv[1][1]) + { + case 'a': + // Print arp table + DoGetIpNetTable(); + break; + case 's': + //Update or add an ARP Internet/Ethernet Address entry + if (argc == 4) + DoSetIpNetEntry(argv[2], argv[3]); + else if (argc == 5) + DoSetIpNetEntry(argv[2], argv[3], argv[4]); + else + Usage("IpArp"); + break; + case 'd': + //Delete an Internet/Ethernet Address pair from the ARP table + if (argc == 3) + DoDeleteIpNetEntry(argv[2]); + else if (argc == 4) + DoDeleteIpNetEntry(argv[2], argv[3]); + else + Usage("IpArp"); + break; + default: + // help + Usage("IpArp"); + break; + } + WSACleanup(); +} + + +void DoGetIpNetTable() +{ + DWORD dwStatus; + PMIB_IPNETTABLE pIpArpTab = NULL; + + + if ( (dwStatus = MyGetIpNetTable(pIpArpTab, TRUE)) == NO_ERROR) + { + PrintIpNetTable(pIpArpTab); + free(pIpArpTab); + return; + } + else if ( dwStatus == ERROR_NO_DATA) + { + printf("No entries in arp cache.\n"); + if (pIpArpTab) + free (pIpArpTab); + return; + } + else + { + if (pIpArpTab) + free (pIpArpTab); + printf("IpArp returned 0x%x\n", dwStatus); + return; + } + +} + +//---------------------------------------------------------------------------- +// Add an arp entry with ip dotted decimal address of "pszDottedInetAddr" and +// physical address of "pszPhysAddr" in 00-aa-bb-cc-dd-ee format on interface +// index of "pszInterface" in hex form. +//---------------------------------------------------------------------------- +void DoSetIpNetEntry(char* pszDottedInetAddr, char* pszPhysAddr, char* pszInterface) +{ + DWORD dwInetAddr = 0; // ip address + DWORD dwStatus; + BYTE bPhysAddr[MAXLEN_PHYSADDR]; + + if (pszDottedInetAddr == NULL || pszPhysAddr == NULL) + { + printf("IpArp: Bad Argument\n"); + return; + } + + dwInetAddr = inet_addr(pszDottedInetAddr); // convert dotted ip addr. to ip addr. + if (dwInetAddr == INADDR_NONE) + { + printf("IpArp: Bad Argument %s\n", pszDottedInetAddr); + return; + } + + if (StringToPhysAddr(pszPhysAddr, (char*)bPhysAddr ) != 0) + { + printf("IpArp: Bad Argument %s\n", pszPhysAddr); + return; + } + MIB_IPNETROW arpEntry; // an arp entry + if (pszInterface) + { + // User provides a interface index number + sscanf_s(pszInterface, "%X",&(arpEntry.dwIndex)); + } + else + { + // add this to the first available interface + PMIB_IPADDRTABLE pIpAddrTable = NULL; + if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR) + { + printf("IpArp: Couldn't find a interface number to add your arp entry\n"); + return; + } + arpEntry.dwIndex = pIpAddrTable->table[0].dwIndex; + free(pIpAddrTable); + } + arpEntry.dwPhysAddrLen = 6; + memcpy(arpEntry.bPhysAddr, bPhysAddr, 6); + arpEntry.dwAddr = dwInetAddr; + arpEntry.dwType = MIB_IPNET_TYPE_STATIC; //static arp entry + dwStatus = SetIpNetEntry(&arpEntry); + if (dwStatus != NO_ERROR) + { + printf("IpArp: couldn't add (%s, %s), dwStatus = %lu.\n", + pszDottedInetAddr, pszPhysAddr, dwStatus); + } +} +//---------------------------------------------------------------------------- +// Delete an arp entry with ip dotted decimal address of "pszDottedInetAddr" +// and interface index of "pszInterface" in hex form. +//---------------------------------------------------------------------------- +void DoDeleteIpNetEntry(char* pszDottedInetAddr, char* pszInterface) +{ + DWORD dwInetAddr = 0; // ip address + DWORD dwStatus; + + if (pszDottedInetAddr == NULL) + { + printf("IpArp: Bad Argument\n"); + return; + } + dwInetAddr = inet_addr(pszDottedInetAddr); // convert dotted ip addr. to ip addr. + if (dwInetAddr == INADDR_NONE) + { + printf("IpArp: Bad Argument %s\n", pszDottedInetAddr); + return; + } + + MIB_IPNETROW arpEntry; // an arp entry + if (pszInterface) + { + // User provides a interface index number + sscanf_s(pszInterface, "%X",&(arpEntry.dwIndex)); + } + else + { + // try to delete this from first available interface + PMIB_IPADDRTABLE pIpAddrTable = NULL; + if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR) + { + printf("IpArp: Couldn't find a interface number to add your arp entry\n"); + return; + } + arpEntry.dwIndex = pIpAddrTable->table[0].dwIndex; + free(pIpAddrTable); + } + + arpEntry.dwAddr = dwInetAddr; + dwStatus = DeleteIpNetEntry(&arpEntry); + if (dwStatus != NO_ERROR) + { + printf("IpArp: couldn't delete (%s), dwStatus = %lu.\n", + pszDottedInetAddr, dwStatus); + } + + +} +//---------------------------------------------------------------------------- +// Inputs: pIpAddrTable is the IP address table +// dwIndex is the Interface Number +// Output: If it returns TRUE, str contains the ip address of the interface +//---------------------------------------------------------------------------- +bool InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[]) +{ + struct in_addr inadTmp; + char* szIpAddr; + + if (pIpAddrTable == NULL || str == NULL) + return FALSE; + str[0] = '\0'; + for (DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++) + { + if (dwIndex == pIpAddrTable->table[dwIdx].dwIndex) + { + inadTmp.s_addr = pIpAddrTable->table[dwIdx].dwAddr; + szIpAddr = inet_ntoa(inadTmp); + if (szIpAddr) + { + strcpy_s(str, IPADDR_BUF_SIZE, szIpAddr); + return TRUE; + } + else + return FALSE; + } + } + return FALSE; + +} + +//------------------------------------------------------------------------- +// Input: str points to an ethernet address of the form 00-aa-bb-cc-dd-ee +// If it returns 0, ret contains the 6 bytes ethernet address. +//------------------------------------------------------------------------- + +int StringToPhysAddr(char* szInEther, char* szOutEther) +{ + const char DASH = '-'; + register char c; + register int val; + + // check szInEther for the correct format + if (strlen(szInEther) != 17) + return (-1); + if (szInEther[2] != DASH || szInEther[5] != DASH || szInEther[8] != DASH || + szInEther[8] != DASH || szInEther[14] != DASH) + return (-1); + if (!isxdigit(szInEther[0]) || !isxdigit(szInEther[1]) || + !isxdigit(szInEther[3]) || !isxdigit(szInEther[4]) || + !isxdigit(szInEther[6]) || !isxdigit(szInEther[7]) || + !isxdigit(szInEther[9]) || !isxdigit(szInEther[10]) || + !isxdigit(szInEther[12]) || !isxdigit(szInEther[13]) || + !isxdigit(szInEther[15]) || !isxdigit(szInEther[16])) + return (-1); + // convert the 12 hex decimals back to 6 digit decimals + for (int i = 0; i < 6; i++) + { + val = 0; + c = toupper(szInEther[i*3]); + c = c - (isdigit(c) ? '0' : ('A' - 10)); //offset adjustment + val += c; + val = (val << 4); // val * 16 + c = toupper(szInEther[i*3 + 1]); + c = c - (isdigit(c) ? '0' : ('A' - 10)); // offset adjustement + val += c; + szOutEther[i] = val; + } + return (0); +} + +//---------------------------------------------------------------------------- +// Inputs: PhysAddr is the hardware address in bytes +// PhysAddrLen is the length of the PhysAddr +// Outputs: if it returns TRUE, str is the hex formated string of the hardware +// address. +// NOTE: make sure str is TRIPLE as big as PhysAddrLen +//---------------------------------------------------------------------------- +bool PhysAddrToString(BYTE PhysAddr[], DWORD PhysAddrLen, char str[]) +{ + if (PhysAddr == NULL || PhysAddrLen == 0 || str == NULL) + return FALSE; + str[0] = '\0'; + for (DWORD dwIdx = 0; dwIdx < PhysAddrLen; dwIdx++) + { + if (dwIdx == PhysAddrLen-1) + sprintf_s(str+(dwIdx*3), IPADDR_BUF_SIZE-(dwIdx*3), "%02X", ((int)PhysAddr[dwIdx])&0xff); + else + sprintf_s(str+(dwIdx*3), IPADDR_BUF_SIZE-(dwIdx*3), "%02X-", ((int)PhysAddr[dwIdx])&0xff); + + } + return TRUE; +} +//---------------------------------------------------------------------------- +// arp table format to be printed: +// Interface: 157.61.239.34 on Interface 2 +// Internet Address Physical Address Type +// 159.61.230.39 00-aa-00-61-5d-a4 dynamic +// +// Interface: 157.54.178.219 on Interface 3 +// Internet Address Physical Address Type +// 159.54.170.1 00-10-54-42-c0-88 dynamic +// 159.54.170.113 00-aa-00-c0-80-2e dynamic +//---------------------------------------------------------------------------- +void PrintIpNetTable(PMIB_IPNETTABLE pIpNetTable) +{ + DWORD i, dwStatus, dwCurrIndex; + struct in_addr inadTmp; + char szPrintablePhysAddr[PHYSADDR_BUF_SIZE]; + char szType[IPTYPE_BUF_SIZE]; + char szIpAddr[IPADDR_BUF_SIZE]; + PMIB_IPADDRTABLE pIpAddrTable = NULL; + + if (pIpNetTable == NULL) + { + printf( "pIpNetTable == NULL in line %d\n", __LINE__); + return; + } + // get IP Address Table for mapping interface index number to ip address + if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR) + { + printf("GetIpAddrTable returned 0x%x\n", dwStatus); + if (pIpAddrTable) + free(pIpAddrTable); + return; + } + assert(pIpAddrTable); + // Note: the ARP table should be sorted in interface index + dwCurrIndex = pIpNetTable->table[0].dwIndex; + if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr)) + { + printf("\nInterface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex); + printf(" Internet Address Physical Address Type\n"); + } + else + { + printf("Error: Could not convert Interface number 0x%X to IP address.\n", + pIpNetTable->table[0].dwIndex); + return; + } + + + for (i = 0; i < pIpNetTable->dwNumEntries; ++i) + { + if (pIpNetTable->table[i].dwIndex != dwCurrIndex) + { + dwCurrIndex = pIpNetTable->table[i].dwIndex; + if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr)) + { + printf("Interface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex); + printf(" Internet Address Physical Address Type\n"); + } + else + { + printf("Error: Could not convert Interface number 0x%X to IP address.\n", + pIpNetTable->table[0].dwIndex); + return; + } + } + PhysAddrToString(pIpNetTable->table[i].bPhysAddr, pIpNetTable->table[i].dwPhysAddrLen, szPrintablePhysAddr); + inadTmp.s_addr = pIpNetTable->table[i].dwAddr; + switch (pIpNetTable->table[i].dwType) + { + case 1: + strcpy_s(szType, IPTYPE_BUF_SIZE, "other"); + break; + case 2: + strcpy_s(szType, IPTYPE_BUF_SIZE, "invalidated"); + break; + case 3: + strcpy_s(szType, IPTYPE_BUF_SIZE, "dynamic"); + break; + case 4: + strcpy_s(szType, IPTYPE_BUF_SIZE, "static"); + break; + default: + strcpy_s(szType, IPTYPE_BUF_SIZE, "invalidType"); + } + printf(" %-16s %-17s %-11s\n", inet_ntoa(inadTmp), szPrintablePhysAddr, szType); + + } + if (pIpAddrTable) + free(pIpAddrTable); +} + + +//---------------------------------------------------------------------------- +// Format of IP Address Table: +// ipAdEntAddr ifAdEntIfIndex ipAdEntNetMask ipAdEntBcastAddr ipAdEntReasmMaxSize +//---------------------------------------------------------------------------- +void PrintIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable) +{ + DWORD i; + struct in_addr inadTmp1; + struct in_addr inadTmp2; + char szAddr[IPADDR_BUF_SIZE]; + char szMask[IPADDR_BUF_SIZE]; + + if (pIpAddrTable == NULL) + { + printf( "pIpAddrTable == NULL in line %d\n", __LINE__); + return; + } + printf("ipAdEntAddr\t ifAdEntIfIndex\t ipAdEntNetMask\t ipAdEntBcastAddr\t ipAdEntReasmMaxSize\n"); + for (i = 0; i < pIpAddrTable->dwNumEntries; ++i) + { + inadTmp1.s_addr = pIpAddrTable->table[i].dwAddr; + strcpy_s(szAddr, IPADDR_BUF_SIZE, inet_ntoa(inadTmp1)); + inadTmp2.s_addr = pIpAddrTable->table[i].dwMask; + strcpy_s(szMask, IPADDR_BUF_SIZE, inet_ntoa(inadTmp2)); + printf(" %s\t 0x%X\t %s\t %s\t %u\n", + szAddr, + pIpAddrTable->table[i].dwIndex, + szMask, + (pIpAddrTable->table[i].dwBCastAddr ? "255.255.255.255" : "0.0.0.0"), + pIpAddrTable->table[i].dwReasmSize); + + } +} + +//---------------------------------------------------------------------------- +// Input : fOrder -- sorts the output IP Addr Table +// Output: If it returns NO_ERROR, pIpAddrTable points to the IP Addr Table +//---------------------------------------------------------------------------- +DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE& pIpAddrTable, bool fOrder) +{ + DWORD status = NO_ERROR; + DWORD statusRetry = NO_ERROR; + DWORD dwActualSize = 0; + + + // query for buffer size needed + status = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder); + + if (status == NO_ERROR) + { + printf("No error\n"); + return status; + } + else if (status == ERROR_INSUFFICIENT_BUFFER) + { + // need more space + + pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwActualSize); + assert(pIpAddrTable); + + statusRetry = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder); + return statusRetry; + } + else + { + return status; + } +} + +//---------------------------------------------------------------------------- +// Input : fOrder -- sorts the output IP Net Table +// Output: If it returns NO_ERROR, pIpNetTable points to the IP Net Table +//---------------------------------------------------------------------------- +DWORD MyGetIpNetTable(PMIB_IPNETTABLE& pIpNetTable, bool fOrder) +{ + DWORD status = NO_ERROR; + DWORD statusRetry = NO_ERROR; + DWORD dwActualSize = 0; + + // query for buffer size needed + dwActualSize = 0; + status = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder); + + if (status == NO_ERROR) + { + return status; + } + else if (status == ERROR_INSUFFICIENT_BUFFER) + { + // need more space + + pIpNetTable = (PMIB_IPNETTABLE) malloc(dwActualSize); + assert(pIpNetTable); + + statusRetry = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder); + + if (statusRetry != NO_ERROR) + { +#ifdef _DEBUG + printf("Retry failed.\n"); +#endif + return statusRetry; + } + else + { + return statusRetry; + } + } + else + { +#ifdef _DEBUG + printf("first getipnettable call failed\n"); +#endif + return status; + } +} + + + diff --git a/NetTool/IPArp.h b/NetTool/IPArp.h new file mode 100644 index 0000000..8a41daa --- /dev/null +++ b/NetTool/IPArp.h @@ -0,0 +1,38 @@ +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// +// Copyright (C) Microsoft Corporation, 2008-2009 +// +// File: iparp.h +// +//-------------------------------------------------------------------------- + +#ifndef HEADER_IPARP +#define HEADER_IPARP + +#include +#include +#include +#include +#include +#include + +#ifndef WIN_SUCCESS +#define WIN_SUCCESS(x) ((x) == NO_ERROR) +#endif //WIN_SUCCESS + +// +// Forward declarations +// +void DoGetIpNetTable(); +void DoSetIpNetEntry(char* pszDottedInetAddr, char* pszPhysAddr, char* pszInterface = NULL); +void DoDeleteIpNetEntry(char* pszDottedInetAddr, char* pszInterface = NULL); +DWORD MyGetIpNetTable(PMIB_IPNETTABLE& pIpNetTable, bool fOrder = TRUE); +void PrintIpNetTable(PMIB_IPNETTABLE pIpNetTable); +int StringToPhysAddr(char* szInEther, char* szOutEther); +DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE& pIpAddrTable, bool fOrder = TRUE); + +void _cdecl IpArp(int argc, char ** argv); + +#endif diff --git a/NetTool/NetTool.cpp b/NetTool/NetTool.cpp index 7223488..de72f17 100644 --- a/NetTool/NetTool.cpp +++ b/NetTool/NetTool.cpp @@ -3,6 +3,7 @@ #include "..\inc\libnet.h" #include "pch.h" +#include "IPArp.h" #ifdef _WIN64 @@ -95,6 +96,10 @@ int _cdecl main(_In_ int argc, _In_reads_(argc) CHAR * argv[]) whois(--argc, ++argv); } + else if (_wcsicmp(Arglist[1], L"Arp") == 0) { + IpArp(--argc, ++argv); + } + else { Usage(Arglist[0]); } diff --git a/NetTool/NetTool.vcxproj b/NetTool/NetTool.vcxproj index 1f50814..c87ece4 100644 --- a/NetTool/NetTool.vcxproj +++ b/NetTool/NetTool.vcxproj @@ -147,9 +147,11 @@ + + diff --git a/NetTool/NetTool.vcxproj.filters b/NetTool/NetTool.vcxproj.filters index c6022b2..b3a69de 100644 --- a/NetTool/NetTool.vcxproj.filters +++ b/NetTool/NetTool.vcxproj.filters @@ -18,10 +18,16 @@ 源文件 + + 源文件 + 头文件 + + 头文件 + \ No newline at end of file diff --git a/NetTool/NetTool.vcxproj.user b/NetTool/NetTool.vcxproj.user index 7ff49db..0c05183 100644 --- a/NetTool/NetTool.vcxproj.user +++ b/NetTool/NetTool.vcxproj.user @@ -1,7 +1,7 @@  - whois baidu.com + Arp -a WindowsLocalDebugger \ No newline at end of file