Arp Table을 알게되었습니다. (개념을 모르시다면, 검색해보아용)
Arp Table은 CMD 창에서 간단하게 arp -a ,-s , -d 등등 여러가지 명령어로 수정하거나 추가하거나 지우거나 할 수 있습니다.
하지만, 저는 개발자;; 소스로 어떻게 할 수 없나 찾아봤습니다 .그래서 밑에 코드프로젝트에서 찾았습니다!! (감동 ㅠ_ㅠ!!)
원본 및 출처 : http://www.codeproject.com/KB/IP/ARPTables.aspx
원본에 있는 주석들은 싸그리 지웠기 때문에 원본을 꼭!! 참고하시고 보시길 바랍니다
(주석 안보시면 이해 안될거에요)
참!! 전 콘솔로 프로젝트를 생성하였습니다.
- 추가시켜줘야 할 SNMP 헤더파일
#pragma comment(lib, "snmpapi.lib")
- Arp Table Structure
{
unsigned long Type; // Type: 3:Dynamic, 4:Static
unsigned char IPAddress[4]; // IP Address
unsigned char MACAddress[6]; // MAC Address
} arpTable;
- CARP Class .h
{
private:
HMODULE hMIBLibrary;
PFNSNMPEXTENSIONINIT pfnSnmpExtensionInit;
PFNSNMPEXTENSIONQUERY pfnSnmpExtensionQuery;
BOOL 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 하는 함수 입니다. 복잡하고 길죠? 차근차근 원작자의 설명과 주석을 보면서 이해하시길 ....
{
// 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;
SVBList[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를 수정하였습니다.
#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;
}
설명이 무척 짧습니다. 댓글로 질문 주시면 답변드리겠습니다.
'programming > MFC' 카테고리의 다른 글
[MFC] CString 에 있는 파일경로 char 로 가져오기 wcstombs_s 함수 (0) | 2011.10.20 |
---|---|
MultiByteToWideChar(), WideCharToMultiByte() 함수 (0) | 2011.09.21 |
SendMessage & PostMessage (0) | 2011.02.23 |
visual 2008에서 ClassWiard 따라하기(?) (1) | 2010.12.23 |
MFC List 클래스 (0) | 2010.12.21 |