→ Opcode : ARP에는 두가지 타입이 있다. 그 타입을 나타낸다. (2 byte)
0X0001 = ARP Request
0X0002 = ARP Reply
0X0003 = RARP request
0X0004 = RARP reply
→ Sender MAC address : 송신지 MAC 주소 ( 6 byte)
→ Sender IP address : 송신지 IP 주소 (4 byte)
→ Target MAC address : 수신지 MAC 주소 (6 byte)
→ Target IP address : 수신지 IP 주소 (4 byte)
※ IP 주소 형식으로 출력하는 방법에 대해 잠시 살펴보면
unsigned int A = 0x70 00 12 13;
이라고 생각했을 때 이를 70.00.12.1으로 출력한다.
이를 위해서 캐스팅을 하면 *((unsigned char *)&A)로 캐스팅 하여 출력 하였을 때 13이 출력된다.(little endian이기 때문)
이것을 한번 출력해 보면 아래와 같다.
#include<stdio.h>
int main()
{
int A = 0x70001213;
printf("%02X.%02X.%02X.%02X\n", *((unsigned char *)&A+3), *((unsigned char *)&A+2),
*((unsigned char *)&A+1), *((unsigned char *)&A));
return 0;#include < stdio.h >
int main()
{
int A = 0x70001213 ;
printf("%02X.%02X.%02X.%02X\n" , *((unsigned char *)& A+3 ), *((unsigned char *)& A+2 ),
*((unsigned char *)& A+1 ), *((unsigned char *)& A));
return 0 ;
}
접기
// L2_ARP.c
#include "L2_ARP.h"
const void * L2_ARP(const void * vpData, unsigned int * uipNext)
{
const struct ether_arp *stpARP = vpData;
printf("┌─────────────────────────────────────────┐\n" );
printf("│ ARP information │\n" );
printf("├─────────────────────────────────────────┤\n" );
// ARP protocol HARDWARE identifiers
switch (ntohs(stpARP-> arp_hrd))
{
/* ARP protocol HARDWARE identifiers. */
case ARPHRD_NETROM:
printf("│ HARDWARE identifiers : from KA9Q: NET/ROM pseudo │\n" );
break ;
case ARPHRD_ETHER:
printf("│ HARDWARE identifiers : Ethernet 10Mbps │\n" );
break ;
case ARPHRD_EETHER:
printf("│ HARDWARE identifiers : Experimental Ethernet │\n" );
break ;
case ARPHRD_AX25:
printf("│ HARDWARE identifiers : AX.25 Level 2 │\n" );
break ;
case ARPHRD_PRONET:
printf("│ HARDWARE identifiers : PROnet token ring │\n" );
break ;
case ARPHRD_CHAOS:
printf("│ HARDWARE identifiers : Chaosnet │\n" );
break ;
case ARPHRD_IEEE802:
printf("│ HARDWARE identifiers : IEEE 802.2 Ethernet/TR/TB │\n" );
break ;
case ARPHRD_ARCNET:
printf("│ HARDWARE identifiers : ARCnet │\n" );
break ;
case ARPHRD_APPLETLK:
printf("│ HARDWARE identifiers : APPLEtalk │\n" );
break ;
case ARPHRD_DLCI:
printf("│ HARDWARE identifiers : Frame Relay DLCI │\n" );
break ;
case ARPHRD_ATM:
printf("│ HARDWARE identifiers : ATM │\n" );
break ;
case ARPHRD_METRICOM:
printf("│ HARDWARE identifiers : Metricom STRIP (new IANA id) │\n" );
break ;
/* Dummy types for non ARP hardware */
case ARPHRD_SLIP:
break ;
case ARPHRD_CSLIP:
break ;
case ARPHRD_SLIP6:
break ;
case ARPHRD_CSLIP6:
break ;
case ARPHRD_RSRVD:
printf("│ HARDWARE identifiers : Notional KISS type │\n" );
break ;
case ARPHRD_ADAPT:
break ;
case ARPHRD_ROSE:
break ;
case ARPHRD_X25:
printf("│ HARDWARE identifiers : CCITT X.25 │\n" );
break ;
case ARPHDR_HWX25:
printf("│ HARDWARE identifiers : Boards with X.25 in firmware │\n" );
break ;
case ARPHRD_PPP:
break ;
case ARPHRD_HDLC:
printf("│ HARDWARE identifiers : (Cisco) HDLC │\n" );
break ;
case ARPHRD_LAPB:
printf("│ HARDWARE identifiers : LAPB │\n" );
break ;
case ARPHRD_DDCMP:
printf("│ HARDWARE identifiers : Digital's DDCMP protocol │\n" );
break ;
case ARPHRD_TUNNEL:
printf("│ HARDWARE identifiers : IPIP tunnel │\n" );
case ARPHRD_TUNNEL6:
printf("│ HARDWARE identifiers : IPIP6 tunnel │\n" );
break ;
case ARPHRD_FRAD:
printf("│ HARDWARE identifiers : Frame Relay Access Device │\n" );
break ;
case ARPHRD_SKIP:
printf("│ HARDWARE identifiers : SKIP vif │\n" );
break ;
case ARPHRD_LOOPBACK:
printf("│ HARDWARE identifiers : Loopback device │\n" );
break ;
case ARPHRD_LOCALTLK:
printf("│ HARDWARE identifiers : Localtalk device │\n" );
break ;
case ARPHRD_FDDI:
printf("│ HARDWARE identifiers : Fiber Distributed Data Interface │\n" );
break ;
case ARPHRD_BIF:
printf("│ HARDWARE identifiers : AP1000 BIF │\n" );
break ;
case ARPHRD_SIT:
printf("│ HARDWARE identifiers : sit0 device - IPv6-in-IPv4 │\n" );
break ;
case ARPHRD_IPDDP:
printf("│ HARDWARE identifiers : IP over DDP tunneller │\n" );
break ;
case ARPHRD_IPGRE:
printf("│ HARDWARE identifiers : GRE over IP │\n" );
break ;
case ARPHRD_PIMREG:
printf("│ HARDWARE identifiers : PIMSM register interface │\n" );
break ;
case ARPHRD_HIPPI:
printf("│ HARDWARE identifiers : High Performance Parallel Interface │\n" );
break ;
case ARPHRD_ASH:
printf("│ HARDWARE identifiers : Nexus 64Mbps Ash │\n" );
break ;
case ARPHRD_ECONET:
printf("│ HARDWARE identifiers : Acorn Econet │\n" );
break ;
case ARPHRD_IRDA:
printf("│ HARDWARE identifiers : Linux-IrDA │\n" );
break ;
/* ARP works differently on different FC media .. so */
case ARPHRD_FCPP:
printf("│ HARDWARE identifiers : Point to point fibrechanel │\n" );
break ;
case ARPHRD_FCAL:
printf("│ HARDWARE identifiers : Fibrechannel arbitrated loop │\n" );
break ;
case ARPHRD_FCPL:
printf("│ HARDWARE identifiers : Fibrechannel public loop │\n" );
break ;
case ARPHRD_FCPFABRIC:
printf("│ HARDWARE identifiers : Fibrechannel fabric │\n" );
break ;
/* 787-> 799 reserved for fibrechannel media types */
case ARPHRD_IEEE802_TR:
printf("│ HARDWARE identifiers : Magic type ident for TR │\n" );
break ;
default :
break ;
}
printf("├─────────────────────────────────────────┤\n" );
// protocol ID's
switch (ntohs(stpARP-> arp_pro))
{
case IPTOS_LOWDELAY:
printf("%-84s" , "│ IPTOS_LOWDELAY" );
break ;
case IPTOS_THROUGHPUT:
printf("%-84s" , "│ IPTOS_THROUGHPUT" );
break ;
case IPTOS_RELIABILITY:
printf("%-84s" , "│ IPTOS_RELIABILITY" );
break ;
case IPTOS_LOWCOST:
printf("%-84s" , "│ IPTOS_LOWCOST" );
break ;
default :
printf("%-84s" , "│ Type of service : unknown" );
break ;
}
printf("│\n" );
printf("├─────────────────────────────────────────┤\n" );
// Hardware length
printf("│ Hardware Length %-65d│ \n" , stpARP-> arp_hln);
printf("├─────────────────────────────────────────┤\n" );
// Protocol Length/size
printf("│ Protocol Length : %-63d│ \n" , stpARP-> arp_pln);
printf("├─────────────────────────────────────────┤\n" );
// ARP protocol opcodes
switch (ntohs(stpARP-> arp_op))
{
case ARPOP_REQUEST:
printf("%-84s" , "│ ARP protocol opcodes : ARP request" );
break ;
case ARPOP_REPLY:
printf("%-84s" , "│ ARP protocol opcodes : ARP reply" );
case ARPOP_RREQUEST:
printf("%-84s" , "│ ARP protocol opcodes : RARP request" );
break ;
case ARPOP_RREPLY:
printf("%-84s" , "│ ARP protocol opcodes : RARP reply" );
break ;
case ARPOP_InREQUEST:
printf("%-84s" , "│ ARP protocol opcodes : InARP request" );
break ;
case ARPOP_InREPLY:
printf("%-84s" , "│ ARP protocol opcodes : InARP reply" );
break ;
case ARPOP_NAK:
printf("%-84s" , "│ ARP protocol opcodes : (ATM)ARP NAK" );
break ;
default :
printf("%-84s" , "│ ARP protocol opcodes : default" );
break ;
}
printf("│\n" );
printf("├─────────────────────────────────────────┤\n" );
// MAC Address
printf("│ MAC [%02X:%02X:%02X:%02X:%02X:%02X] -> "
"[%02X:%02X:%02X:%02X:%02X:%02X] │\n"
, stpARP-> arp_sha[0 ]
, stpARP-> arp_sha[1 ]
, stpARP-> arp_sha[2 ]
, stpARP-> arp_sha[3 ]
, stpARP-> arp_sha[4 ]
, stpARP-> arp_sha[5 ]
, stpARP-> arp_tha[0 ]
, stpARP-> arp_tha[1 ]
, stpARP-> arp_tha[2 ]
, stpARP-> arp_tha[3 ]
, stpARP-> arp_tha[4 ]
, stpARP-> arp_tha[5 ]);
printf("├─────────────────────────────────────────┤\n" );
// IP Address
printf("│ IP : [%d.%d.%d.%d] -> "
"[%d.%d.%d.%d] │\n"
, stpARP-> arp_spa[0 ]
, stpARP-> arp_spa[1 ]
, stpARP-> arp_spa[2 ]
, stpARP-> arp_spa[3 ]
, stpARP-> arp_tpa[0 ]
, stpARP-> arp_tpa[1 ]
, stpARP-> arp_tpa[2 ]
, stpARP-> arp_tpa[3 ]);
printf("└─────────────────────────────────────────┘\n" );
return vpData;
}
접기 접기
// main.c
#include < stdio.h>
#include < pcap/pcap.h>
#include "hexaview.h"
#include "L1_Ethernet.h"
#include "L2_IP.h"
#include "L2_ARP.h"
int main()
{
char *cpNIC_Name;
char errbuf[PCAP_ERRBUF_SIZE]; // 에러 발생시 원인 저장
pcap_t *stpNIC;
const u_char *ucpData;
struct pcap_pkthdr stInfo;
unsigned int uiNext;
cpNIC_Name= pcap_lookupdev(errbuf); // 패킷 캡처 할 수 있는 디바이스 찾기
if (0 = = cpNIC_Name)
{
printf(errbuf);
putchar('\n' ); // 개행한다.
return 0 ;
}
printf(cpNIC_Name); // 성공한 디바이스 이름 반환
putchar('\n' );
stpNIC= pcap_open_live(cpNIC_Name, 1500 , 1 , 0 , errbuf); // 네트워크 디바이스 열기
if (0 = = stpNIC)
{
printf(errbuf);
putchar('\n' ); // 개행한다.
return 0 ;
}
printf("Packet Capture Open Successful!!\n" );
ucpData = pcap_next(stpNIC, & stInfo); // 패킷 캡쳐
hexaview(ucpData, 160 );
// IP에다 ucpData를 넘겨 주기 위해서
ucpData = L1_Ethernet(ucpData, & uiNext); // 반환형은 void, 인자로 제일 초기의 시작 주소를 넘겨 ㅑ論었다.
switch (uiNext)
{
case ETHERTYPE_PUP:
break ;
case ETHERTYPE_IP:
ucpData = L2_IP(ucpData, & uiNext);
break ;
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
ucpData = L2_ARP(ucpData, & uiNext);
break ;
default :
break ;
}
switch (uiNext)
{
case IPPROTO_IP:
break ;
/* case IPPROTO_HOPOPTS:
break;*/
case IPPROTO_ICMP:
break ;
case IPPROTO_IGMP:
break ;
case IPPROTO_IPIP:
break ;
case IPPROTO_TCP:
break ;
case IPPROTO_EGP:
break ;
case IPPROTO_PUP:
break ;
case IPPROTO_IDP:
break ;
case IPPROTO_TP:
break ;
case IPPROTO_IPV6:
break ;
case IPPROTO_ROUTING:
break ;
case IPPROTO_FRAGMENT:
break ;
case IPPROTO_RSVP:
break ;
case IPPROTO_GRE:
break ;
case IPPROTO_ESP:
break ;
case IPPROTO_AH:
break ;
case IPPROTO_ICMPV6:
break ;
case IPPROTO_NONE:
break ;
case IPPROTO_DSTOPTS:
break ;
case IPPROTO_MTP:
break ;
case IPPROTO_ENCAP:
break ;
case IPPROTO_PIM:
break ;
case IPPROTO_COMP:
break ;
case IPPROTO_RAW:
break ;
default :
break ;
}
pcap_close(stpNIC);
return 0 ;
}
접기
- 이전에 만든 SimplePaint 예제의 그리기 옵션인 색상과 굵기값 선택 컨트롤들을 대화상자로 옮겨본다.
- 메인 윈도우는 흰색 바탕의 컨버스로만 구성하고 옵션은 오른쪽 마우스 버튼을 누를 때 대화상자를 열어 선택 받는다.
- 화면을 지우는 기능은 옵션이 아니라 명령이므로 대화상자로 옮기는 것은 부적절 하며 공백키가 입력 되었을 때 지우는 것으로 한다.
접기
#include "MsgProc.h"
HDC hdc;
static int x;
static int y;
static BOOL bNowDraw = FALSE;
int Width = 0 ; // 초기 굵기는 0
COLORREF Color = RGB(0 , 0 , 0 ); // 초기 색상은 BLACK
LRESULT OnCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) // 프로그램 실행시 가장 먼저 실행
{
return 0 ;
}
LRESULT OnCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
return 0 ;
}
LRESULT OnKeyDown(HWND hWnd, WPARAM wParam, LPARAM lParam) // 키보드 입력 값을 윈도우로 받는다.(특수문자 포함)
{
switch (wParam)
{
case VK_SPACE: // space 키를 입력받으면
{
InvalidateRect(hWnd, NULL, TRUE); // 화면을 클리어 한다.
}
}
return 0 ;
}
LRESULT OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
x = LOWORD(lParam);
y = HIWORD(lParam);
bNowDraw = TRUE;
return 0 ;
}
LRESULT OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HPEN MyPen, OldPen;
if (bNowDraw = = TRUE)
{
hdc = GetDC(hWnd);
MyPen = CreatePen(PS_SOLID, Width, Color); // 펜의 굵기와 색상을 변수로 받아 적용
OldPen = (HPEN)SelectObject(hdc, MyPen);
MoveToEx(hdc, x, y, NULL);
x = LOWORD(lParam);
y = HIWORD(lParam);
LineTo(hdc, x, y);
ReleaseDC(hWnd, hdc);
SelectObject(hdc, OldPen);
DeleteObject(MyPen);
}
return 0 ;
}
LRESULT OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
bNowDraw= FALSE;
return 0 ;
}
LRESULT OnRButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, RadioDlgProc);
return 0 ;
}
LRESULT OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, & ps);
EndPaint(hWnd, & ps);
return 0 ;
}
LRESULT OnDestroy(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
PostQuitMessage(0 );
return 0 ;
}
/////////////////////////////////////////////////////////////////////
BOOL OnInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
CheckRadioButton(hDlg, IDC_RADIO1, IDC_RADIO4, IDC_RADIO1);
return TRUE;
}
BOOL OnDlgCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case IDOK:
if (IsDlgButtonChecked(hDlg, IDC_RADIO1)= = BST_CHECKED)
{
Color = RGB(0 , 0 , 0 ); // Black
}
if (IsDlgButtonChecked(hDlg, IDC_RADIO2)= = BST_CHECKED)
{
Color = RGB(255 , 0 , 0 ); // RED
}
if (IsDlgButtonChecked(hDlg, IDC_RADIO3)= = BST_CHECKED)
{
Color = RGB(0 , 0 , 255 ); // Blue
}
if (IsDlgButtonChecked(hDlg, IDC_RADIO4)= = BST_CHECKED)
{
Color = RGB(255 , 255 , 0 ); // Yellow
}
if (IsDlgButtonChecked(hDlg, IDC_CHECK1)= = BST_CHECKED)
{
Width = 2 ; // 굵기 2
}
if (IsDlgButtonChecked(hDlg, IDC_CHECK2)= = BST_CHECKED)
{
Width = 4 ; // 굵기 4
}
if (IsDlgButtonChecked(hDlg, IDC_CHECK3)= = BST_CHECKED)
{
Width = 6 ; // 굵기 6
}
EndDialog(hDlg, IDOK);
return TRUE;
case IDCANCEL:
EndDialog(hDlg, IDCANCEL);
return TRUE;
}
return FALSE;
}
접기