본문 바로가기

programming/C++

Windows7에서 Arp Table을 수정 ( CMD 명령어를 이용한 방법)

저번 포스트보다 Arp를 간단히 다뤄보고, CMD 명령어를 이용한 수정방법에 대해 알아보도록 하겠습니다. (동적을 정적으로)

일단 주소 결정 프로토콜 (Address Resolution Protocol, ARP)이란 IP 주소를 물리적 네트워크 주소로 대응시키기 위해 사용되는 프로토콜. 사용자는 IP 주소를 이용하여 인터넷과 연결하지만 이더넷상에서는 이더넷 주소를 이용하게 된다. 이를 위하여 IP 주소를 이더넷 주소로 변환시켜 주어야 하는데 이와 같이 IP 주소를 물리적 주소로 변환시키는 프로토콜을 ARP 이라 한다.  - 네이버 용어사전  펌

말로 이렇게 표현한 것보다 CMD 창에서 보도록 하겠습니다.


CMD 창에서 "arp -a" 명령어를 실행한 모습니다. 보시다시피, 명령어를 이용하면 [ 인터넷주소 : IP ]와 [물리적 주소 : MAC ] 그리고 [유형]이 보입니다.
그리고 [0xB] 저건 Adapter를 나타냅니다. Adapter란..저도 확실히 이거다 라고 설명을 못드리겠습니다. ( 저도 대충알고있어서;;) - 일단 IP와 MAC이 있는 한 공간(?)
저 Adapter가 한개 일수도, 여러개일 수도 있습니다. 따라서 Adapter 갯수가 몇개인지 알아야 됩니다. 전 일단 한개이군요.

 - ARP에 대해 좀 더 자세한 사항은 검색해보세요 ㅎㅎ (퍽!)

그럼 이제부터 Windows7 에서 저기 보이는 [유형]을 동적에서 정적으로 바꾸는 방법을 살펴보겠습니다. 제 포스트중에서 보면, 소스로 해결하는 방법이 있는데,
왜 그런지 몰라도, 윈도우7에서는 잘 작동이 안되더군요; 그래서 모색해서 명령어를 이용하는 방법을 선택했습니다 ㅠ_ㅠ;

http://www.codeproject.com/KB/IP/ARPTables.aspx 일단 여기서 CARP 클래스를 사용하도록 하겠습니다. (살색(?) 테투리안에 있는 CARP 소스만 사용하세요)

이 CARP 클래스는 ARP Table의 Entry들을 가져오거나 수정할 수 있는 함수로 구성되어 있습니다. (자세한 사항은 원본 사이트에서 보셔야됩니다.^^;)
암튼, 그래서 이 함수를 이용하여 수정하도록 시도하였지만..안되더군요;; 그래서 이 클래스의 힘(?)을 조금 빌려서 CMD 명령어와 같이 사용하였습니다.
 

일단, Static으로 바꿔주는 명렁어입니다. 참고하세요 - Windows7 용

netsh -c "interface ipv4" set neighbors "로컬 영역 연결" (혹은 인덱스번호)  "000.000.000.000" (IP) "00-00-00-00-00-00" (MAC)
  "로컬 영역 연결" 항목에는 String 값만이 아니라, 해당 인덱스번호도 들어갌 수 있습니다.
 그래서 저는 항상 로컬만 들어가기만 하는게 아니라서 인덱스번호를 이용하여 사용하였습니다.

Windows7 이외에 버전
arp -s "000.000.000.000" "00-00-00-00-00-00"



이제 소스입니다. 주석을 참고하세요 간단합니다.

Include 해야 될 것들 입니다.

#include <atlstr.h>

//
// SNMP HEADER
//
#include <snmp.h>                           
#pragma comment(lib, "snmpapi.lib")
//
// IPHLPAPI HEADER
//
#pragma comment(lib, "IPHLPAPI.lib")
#include <iphlpapi.h>
#include <iptypes.h>
// - ip help api 입니다. 이 라이브러리를 사용하면 , " /ipconfig /al " 에 대한 항목들을 가져올수있습니다. 이 라이브러리에 대해 공부하시는걸 강추합니다.
// 여러가지 좋은것들(?)이 많습니다
//
// SEHLLAPI HEADER // - cmd 명렁어를 날리기 위한 것.
//
#include <shellapi.h>



본문 소스입니니다.

void SetArpStatic(unsigned char *pIp);                                                           // Static으로 변환 함수
void GetAdapterIndexList(int* AdapterCount, int* AdapterIndexList);                  // 사용가능한 Adapter 개수와 Index List를 가져옴
bool GetMacID(unsigned char* pIp, int AdapterCount, int* AdapterIndexList, unsigned char* mac, int* AdapterIndex);   
// IP 가 있는 Adapter에서 MAC ID를 얻어옴
void ResetStatic(unsigned char* pIp, unsigned char* mac, int AdapterIndex);    //Static으로 변환 함수
void ResetStaticOtehrVersion(unsigned char* pIp, unsigned char* mac);          //WIndows7 이외에 버전용 변환 함수
int _tmain(int argc, _TCHAR* argv[])
{
 unsigned char ip[4] = {000,000,0000,000};   //변환 하고자 하는 IP 함수 입력
 //
 // 해당 IP 를 Static으로 변환
 SetArpStatic(&ip[0]);
 return 0;
}
void SetArpStatic(unsigned char *pIp)
{
 OSVERSIONINFOEX OSvER = {sizeof(OSVERSIONINFOEX),};
 GetVersionEx((OSVERSIONINFO*)&OSvER);
 int AdapterCount = 0;
 int AdapterIndex = 0;
 int AdapterIndexList[256] = {0,};
 unsigned char mac[6] = {0,};
 if(OSvER.dwMajorVersion >=6)   // Windows 7 일 경우
 {
  //
  // 사용가능한 Adapter 개수와 Adapter index 리스트 를 가져옴
  GetAdapterIndexList(&AdapterCount, AdapterIndexList);
  //
  // IP 가 있는 Adapter에서 MAC ID를 얻어옴
  GetMacID(pIp, AdapterCount, AdapterIndexList, (unsigned char*)&mac, &AdapterIndex);
  //
  // Dynamic 유형을 Static 유형으로 수정함
  ResetStatic(pIp, mac, AdapterIndex);
 }
 else         // 그 외 버전인 경우
 {
  GetAdapterIndexList(&AdapterCount, AdapterIndexList);
  GetMacID(pIp, AdapterCount, AdapterIndexList, (unsigned char*)&mac, &AdapterIndex);
  //
  // 다른 버전일 경우, 해당 IP와 MAC 주소만으로 수정함
  ResetStaticOtehrVersion(pIp, mac);
 }
}
void GetAdapterIndexList(int* AdapterCount, int* AdapterIndexList)
{
 ULONG    ulBufferSize = 0;
 PIP_ADAPTER_INFO pAdapter, pAdapterInfo = NULL;
 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;
  }
 }
}
bool GetMacID(unsigned char* pIp, int AdapterCount, int* AdapterIndexList, unsigned char* mac, int* AdapterIndex)
{
 int i;
 bool bFind = false;
 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]);  //Arp Table 에 대한 항목 가져오기
  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]) )   //해당 IP 와 같다면...
   {
    memcpy(mac, Table[j].MACAddress, sizeof(char)*6);
    (*AdapterIndex) = AdapterIndexList[i];
    bFind = true;
    break;
   }
  }
  if(bFind)
  {
   break;
  }
 }
 return false;
}
void ResetStatic(unsigned char* pIp, unsigned char* mac, int AdapterIndex)
{
 SHELLEXECUTEINFO execinfo;   //CMD 명렁어를 날리기 위한 거..
 char strParam[256] = {0, };
 sprintf_s (strParam, 256, " -c \"interface ipv4\" set neighbors %d \"%u.%u.%u.%u\" %02X-%02X-%02X-%02X-%02X-%02X",
  AdapterIndex,                                                      // AdapterIndex
  pIp[0],pIp[1],pIp[2],pIp[3],                                  // IP
  mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);  // MAC
 ZeroMemory(&execinfo, sizeof(execinfo));
 execinfo.cbSize = sizeof(execinfo);
 execinfo.lpVerb = _T("open");
 execinfo.lpFile = _T("netsh");
 execinfo.lpParameters = strParam;   
 execinfo.nShow = SW_HIDE;
 ShellExecuteEx(&execinfo);   //쿼리 뿅~
}
void ResetStaticOtehrVersion(unsigned char* pIp, unsigned char* mac)
{
 SHELLEXECUTEINFO execinfo;
 char strParam[256]= {0,};
 sprintf_s (strParam, 256, " -s \"%u.%u.%u.%u\" %02X-%02X-%02X-%02X-%02X-%02X",
  pIp[0],pIp[1],pIp[2],pIp[3],     //IP
  mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);  //MAC 
 ZeroMemory(&execinfo, sizeof(execinfo));
 execinfo.cbSize = sizeof(execinfo);
 execinfo.lpVerb = _T("open");
 execinfo.lpFile = _T("arp");
 execinfo.lpParameters = strParam;   
 execinfo.nShow = SW_HIDE;
 ShellExecuteEx(&execinfo);  //쿼리 뿅
}


혹시 어쩌나 몰라 소스 첨부합니당.

/////
/////


P.s Windows7 에서는 관리자권한 모드가 필요합니다.

http://seolis.tistory.com/95 참고하세요.

'programming > C++' 카테고리의 다른 글

Log 파일 남기기.  (0) 2012.06.22
Release Mode vs Debug Mode  (0) 2011.08.10
[Visual Studio 6.0 - Workspace] 사용법 및 관리, 동적링크라이브러리  (0) 2011.03.31
Visual Studio 2010 C++ 단축키  (0) 2011.03.08
보간법  (0) 2010.06.10