본문 바로가기

programming/MFC

Arp Table Edit ( ADD/ Modify / Remove ) - C/C++

Arp Table을 알게되었습니다. (개념을 모르시다면, 검색해보아용)
Arp Table은 CMD 창에서 간단하게 arp -a ,-s , -d 등등 여러가지 명령어로 수정하거나 추가하거나 지우거나 할 수 있습니다.
하지만, 저는 개발자;; 소스로 어떻게 할 수 없나 찾아봤습니다 .그래서 밑에 코드프로젝트에서 찾았습니다!! (감동 ㅠ_ㅠ!!)

원본 및 출처 : http://www.codeproject.com/KB/IP/ARPTables.aspx
원본에 있는 주석들은 싸그리 지웠기 때문에 원본을 꼭!! 참고하시고 보시길 바랍니다
(주석 안보시면 이해 안될거에요)


참!! 전 콘솔로 프로젝트를 생성하였습니다.

- 추가시켜줘야 할 SNMP 헤더파일

 #include <snmp.h>
#
pragma comment(lib, "snmpapi.lib")

- Arp Table Structure
 typedef struct
{
unsigned long Type; // Type: 3:Dynamic, 4:Static
          unsigned char IPAddress[4]; // IP Address
          unsigned char MACAddress[6]; // MAC Address
} arpTable;
 
 - CARP Class .h

class CARP
{
private:
HMODULE hMIBLibrary;
PFNSNMPEXTENSIONINIT pfnSnmpExtensionInit;
PFNSNMPEXTENSIONQUERY pfnSnmpExtensionQuery;
B
OOL bInitialized;

public:
CARP();
virtual ~CARP();
intGetEntries(arpTable* pTable, int TableLength, int AdapterIndex);
BOOL EditEntry(unsigned char IPAddress[4], unsigned char MACAddress[6], unsigned long Type, int AdapterIndex);
};


- CARP Clss .cpp

   Arp Table의 항목에 대한 Get하거나  Set 하는 함수 입니다. 복잡하고 길죠? 차근차근 원작자의 설명과 주석을 보면서 이해하시길 ....

 CARP::CARP()
{
// Load dynamic library: inetmib1.dll
hMIBLibrary = LoadLibrary(TEXT("inetmib1.dll"));
// If library loaded, get addresses of (SnmpExtensionInit, pfnSnmpExtensionQuery) functions

if (hMIBLibrary)
{
pfnSnmpExtensionInit = (PFNSNMPEXTENSIONINIT) GetProcAddress(hMIBLibrary, "SnmpExtensionInit");
pfnSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY) GetProcAddress(hMIBLibrary, "SnmpExtensionQuery");

// If success get addresses and initialize SNMP, bInitialized = true
if (pfnSnmpExtensionInit && pfnSnmpExtensionQuery)
{
HANDLE hPollForTrapEvent;
AsnObjectIdentifier aoiSupportedView;

bInitialized = pfnSnmpExtensionInit(0, &hPollForTrapEvent, &aoiSupportedView);

}

}

else

{

// If fail to get addresses, bInitialized = false
bInitialized = FALSE;
// AfxMessageBox(_T("Load library fail"));

}


CARP::~CARP()

{

// If library loaded, free it

if (hMIBLibrary)

FreeLibrary(hMIBLibrary);

}

int CARP::GetEntries(arpTable* pTable, int TableLength, int AdapterIndex)
{
// Be sure initialize SNMP true
if (!bInitialized)

return 0;


SnmpVarBindList SVBList[3];

SnmpVarBind SVBVars[3];

UINT OID[3][10];

AsnInteger32 aiErrorStatus[3], aiErrorIndex[3];

AsnObjectIdentifier AsnOID0 = {sizeof(OID[0])/sizeof(UINT), OID[0]};

AsnObjectIdentifier AsnOID1 = {sizeof(OID[1])/sizeof(UINT), OID[1]};

AsnObjectIdentifier AsnOID2 = {sizeof(OID[2])/sizeof(UINT), OID[2]};

unsigned long pIPAddress;

unsigned long pMACAddress;

int iEntries;


for (int count=0; count<3; count++)

{

OID[count][0] = 1;

OID[count][1] = 3;

OID[count][2] = 6;

OID[count][3] = 1;

OID[count][4] = 2;

OID[count][5] = 1;

OID[count][6] = 4;

OID[count][7] = 22;

OID[count][8] = 1;


switch(count)

{

case 0:

// Adapter interface

OID[count][9] = 1;

break;


case 1:

// MAC address

OID[count][9] = 2;

break;


case 2:

// Entry Type

OID[count][9] = 4;

break;

}

}

ZeroMemory(pTable, sizeof(arpTable)*TableLength);
SVBList[0].len = 1;
SVBList[0].list = &SVBVars[0];
SnmpUtilOidCpy(&SVBVars[0].name, &AsnOID0);
SVBList[1].len = 1;
S
VBList[1].list = &SVBVars[1];
SnmpUtilOidCpy(&SVBVars[1].name, &AsnOID1);
SVBList[2].len = 1;
SVBList[2].list = &SVBVars[2];
SnmpUtilOidCpy(&SVBVars[2].name, &AsnOID2);
iEntries = 0;

do

{

aiErrorStatus[0] = 0;

aiErrorIndex[0] = 0;

aiErrorStatus[1] = 0;

aiErrorIndex[1] = 0;

aiErrorStatus[2] = 0;

aiErrorIndex[2] = 0;


// Query information of 3 OIDs

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[0], &aiErrorStatus[0], &aiErrorIndex[0]))

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[1], &aiErrorStatus[1], &aiErrorIndex[1]))

if (pfnSnmpExtensionQuery(SNMP_PDU_GETNEXT, &SVBList[2], &aiErrorStatus[2], &aiErrorIndex[2]))

if (aiErrorStatus[0] == SNMP_ERRORSTATUS_NOERROR &&

aiErrorStatus[1] == SNMP_ERRORSTATUS_NOERROR &&

aiErrorStatus[2] == SNMP_ERRORSTATUS_NOERROR) // Check for error

{


if(SnmpUtilOidNCmp(&SVBVars[0].name, &AsnOID0, AsnOID0.idLength))

break;

if(SnmpUtilOidNCmp(&SVBVars[1].name, &AsnOID1, AsnOID1.idLength))

break;

if(SnmpUtilOidNCmp(&SVBVars[2].name, &AsnOID2, AsnOID2.idLength))

break;


// Verify selected Adapter interface

if (AdapterIndex == SVBList[0].list->value.asnValue.number)

{

// pIPAddress get pointer ro IP Address

pIPAddress = (unsigned long)SVBList[1].list->name.ids;

pTable[iEntries].IPAddress[0] = *(unsigned char *)(pIPAddress + 44);

pTable[iEntries].IPAddress[1] = *(unsigned char *)(pIPAddress + 48);

pTable[iEntries].IPAddress[2] = *(unsigned char *)(pIPAddress + 52);

pTable[iEntries].IPAddress[3] = *(unsigned char *)(pIPAddress + 56);


// pIPAddress get pointer ro MAC Address

pMACAddress = (unsigned long)SVBList[1].list->value.asnValue.string.stream;

if (pMACAddress)

{

pTable[iEntries].MACAddress[0] = *(unsigned char *)(pMACAddress + 0);

pTable[iEntries].MACAddress[1] = *(unsigned char *)(pMACAddress + 1);

pTable[iEntries].MACAddress[2] = *(unsigned char *)(pMACAddress + 2);

pTable[iEntries].MACAddress[3] = *(unsigned char *)(pMACAddress + 3);

pTable[iEntries].MACAddress[4] = *(unsigned char *)(pMACAddress + 4);

pTable[iEntries].MACAddress[5] = *(unsigned char *)(pMACAddress + 5);

}


// Entry Type

pTable[iEntries].Type = (unsigned long)SVBList[2].list->value.asnValue.number;


// Type must be one of (1, 2, 3, 4)

if (pTable[iEntries].Type>=1 && pTable[iEntries].Type<=4)

iEntries++; // Move to next array position

}

}

else

break; // If error exit do-while

}

while(iEntries<TableLength);


// Frees the memory allocated for the specified object identifiers

SnmpUtilOidFree(&SVBVars[2].name);

SnmpUtilOidFree(&SVBVars[1].name);

SnmpUtilOidFree(&SVBVars[0].name);


return iEntries; // Return number of Entries

}


BOOL CARP::EditEntry(unsigned char IPAddress[4], unsigned char MACAddress[6], unsigned long Type, int AdapterIndex)

{

if (!bInitialized)

return 0;


SnmpVarBindList SVBList;

SnmpVarBind SVBVars[4];

UINT OID[4][10];

AsnInteger32 aiErrorStatus, aiErrorIndex;

BOOL bReturn = FALSE;


for (int count=0; count<4; count++)

{

OID[count][0] = 1;

OID[count][1] = 3;

OID[count][2] = 6;

OID[count][3] = 1;

OID[count][4] = 2;

OID[count][5] = 1;

OID[count][6] = 4;

OID[count][7] = 22;

OID[count][8] = 1;

OID[count][9] = 1 + count;


switch(count)

{

case 0:

// OID[0] : "1.3.6.1.2.1.4.22.1.1", ipNetToMediaIfIndex

// The interface on which this entry's equivalence is effective

SVBVars[count].value.asnType = ASN_INTEGER;

SVBVars[count].value.asnValue.number = AdapterIndex;

break;


case 1:

// OID[1] : "1.3.6.1.2.1.4.22.1.2", ipNetToMediaPhysAddress

// The media-dependent 'physical' address

SVBVars[count].value.asnType = ASN_OCTETSTRING;

SVBVars[count].value.asnValue.string.stream = MACAddress;

SVBVars[count].value.asnValue.string.length = 6; // MAC Address length

SVBVars[count].value.asnValue.string.dynamic= FALSE;

break;


case 2:

// OID[2] : "1.3.6.1.2.1.4.22.1.3", ipNetToMediaNetAddress

// The IpAddress corresponding to the media-dependent 'physical' address

SVBVars[count].value.asnType = ASN_IPADDRESS;

SVBVars[count].value.asnValue.string.stream = IPAddress;

SVBVars[count].value.asnValue.string.length = 4; // IP Address length

SVBVars[count].value.asnValue.string.dynamic= FALSE;

break;


case 3:

// OID[3] : "1.3.6.1.2.1.4.22.1.4", ipNetToMediaType

// Entry type: 2:Remove, 3:Dynamic, 4:Static

SVBVars[count].value.asnType = ASN_INTEGER;

SVBVars[count].value.asnValue.number = Type;

break;

}

AsnObjectIdentifier AsnOID = {sizeof(OID[count])/sizeof(UINT), OID[count]};

SnmpUtilOidCpy(&SVBVars[count].name, &AsnOID);

}


SVBList.len = 4;

SVBList.list = SVBVars;


aiErrorStatus = 0;

aiErrorIndex = 0;


// Set information of entry (4 OIDs)

if (pfnSnmpExtensionQuery(SNMP_PDU_SET, &SVBList, &aiErrorStatus, &aiErrorIndex))

if (aiErrorStatus == SNMP_ERRORSTATUS_NOERROR)

bReturn = TRUE; // If success set bReturn = true


// Frees the memory allocated for the specified object identifiers

SnmpUtilOidFree(&SVBVars[3].name);

SnmpUtilOidFree(&SVBVars[2].name);

SnmpUtilOidFree(&SVBVars[1].name);

SnmpUtilOidFree(&SVBVars[0].name);


return bReturn; // TRUE if set successfully, FALSE otherwise.

}



- 전 윈도우7에서 Arp Table은 바로 Static(정적)으로 바뀌지가 않더군요. 그래서 이 소스를 찾게되었구요.
 그래서 밑에 방법으로 삭제후, Static으로 추가를 시켰습니다.
(추가가 아닌 수정이지만요, 헷갈리지 마세요)  
     밑에 소스는 Adapter의 정보를 가져와서 Arp Table에서 지우고, 추가하는 소스입니다.
     arp.EditEntry(pIp,mac,2,AdapterIndex);  // Remove
     arp.EditEntry(pIp,mac,4,AdapterIndex);  // Static Add
원본을 보신분은 아시겠지만, 위 2개 함수의 3번째 매개변수 중 2는 삭제, 3은 동적(Dynamic)으로 수정, 4는 정적(Static)으로 수정하는 함수입니다.
위 2개의 함수를 가지고, 삭제후, Static으로 추가(수정) 했습니다.

- UDP 방식으로 생각했기 때문에, IP 주소는 알고 있다고 가정했습니다. 그래서 IP주소를 입력하게 되면, 그에 따른 Adapter와 Adapter 안에 있는 MAC주소를 가져와서, (Adapter 안에 MAC 주소의 정보가 다 들어있습니다) ARP Table를 수정하였습니다.

 #pragma comment(lib, "IPHLPAPI.lib") //이것도 추가시켜줘야 됩니당.
#include <iphlpapi.h>
#include <iptypes.h>

bool FindMacInfo(unsigned char* pIp, int AdapterCount, int AdapterIndexList[]); //MAC 주소를 가져오는 함수
void SetArpStatic(unsigned char* pIp)  // Adapter 정보를 가져오는 함수
{

int iAdapters = 0;

ULONG ulBufferSize = 0;

PIP_ADAPTER_INFO pAdapter, pAdapterInfo = NULL;

int AdapterIndexList[256] = {0,};
int AdapterCount;
int AdapterListIndex = 0;

if (GetAdaptersInfo(NULL, &ulBufferSize) == ERROR_BUFFER_OVERFLOW)
{
pAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[ulBufferSize];
if (pAdapterInfo)
{
if (GetAdaptersInfo(pAdapterInfo, &ulBufferSize) == ERROR_SUCCESS)
{
pAdapter = pAdapterInfo;
AdapterCount = 0;
while(pAdapter)
{
AdapterIndexList[AdapterCount] = pAdapter->Index;
pAdapter = pAdapter->Next;
AdapterCount++;
}

}
delete[] pAdapterInfo;
}
}

FindMacInfo(pIp,AdapterCount,AdapterIndexList); // Find about : MAC id, Adapter index;

}
bool FindMacInfo(unsigned char* pIp, int AdapterCount, int AdapterIndexList[])

{
// Find about : MAC id, Adapter index;


int AdapterIndex = 0;

int i;

bool bFind = false;

unsigned char mac[6] = {0,};


for(i = 0; i<AdapterCount; i++)

{

CARP arp;

arpTable Table[256];

int Counter;

int TableLength = sizeof(Table)/sizeof(arpTable);


Counter = arp.GetEntries(Table, TableLength, AdapterIndexList[i]);

for(int j=0; j<Counter; j++)

{

if( (Table[j].IPAddress[0] == pIp[0]) && (Table[j].IPAddress[1] == pIp[1]) &&

(Table[j].IPAddress[2] == pIp[2]) && (Table[j].IPAddress[3] == pIp[3]) )

{


memcpy(mac, Table[j].MACAddress, sizeof(char)*6);

AdapterIndex = AdapterIndexList[i];

bFind = true;


arp.EditEntry(pIp,mac,2,AdapterIndex); // Remove

arp.EditEntry(pIp,mac,4,AdapterIndex); // Static Add

break;

}

}

if(bFind) break;

}


if(!bFind)

return false;

}


int _tmain(int argc, _TCHAR* argv[])

{

unsigned char ip[4] = {192,168,0,62};

SetArpStatic(&ip[0]);

return 0;

}




설명이 무척 짧습니다. 댓글로 질문 주시면 답변드리겠습니다.