// Socket Data 를 recvfrom으로 데이터 수신후 분석 //
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <linux/if.h> #include <linux/if_ether.h> #include "HexaView.h" #include "Ethernet.h" #include "L2_IP.h"
typedef struct _L1_map { unsigned int uiType; int (*L1Func)(void *); }L1_map;
// 구조체를 L1_list[]에 각각 넣어줌. 2차원 배열 uiType <-> ETHERTYPE_? , int (*L1Func)(void *) <-> 함수주소 (ex: L2_IP) L1_map L1_list[] ={ {ETHERTYPE_PUP, 0}, {ETHERTYPE_IP, L2_IP}, {ETHERTYPE_ARP, 0}, {ETHERTYPE_REVARP, 0}, {0xFFFFFFFF, 0} };
int main() { int iSock; struct ifreq stIf; int iRet; struct sockaddr_in st_pktInfo; unsigned int ui_Len = sizeof(st_pktInfo); unsigned char uc_Buffer[1500]; // Packet의 용량제한범위. ethernet이니까! L1_map *stpL1; // stpL1은 L1_map 구조체를 가리키고있는 포인터. int iProto;
// SOCK_RAW 생소켓!, 가공되어있지않은 소켓. iSock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)); // usr/include <asm/socket.h> line56 <linux/if_ether.h> line74
// 윈도우에서 cls 와 비슷. write (1, "\033[1;1H\033[2J", 10);
if(0 > iSock) { printf("socket() failed\n"); return 0; } // 랜카드 정보를 Socket 하고 연결 시킴. strcpy(stIf.ifr_name, "eth0");
// 저수준 입출력 장치에 모두에 쓰임. iRet = ioctl(iSock, SIOCGIFFLAGS, &stIf); if( 0 > iRet ) { printf("ioclt() failed\n"); close(iSock); return 0; }
// 랜카드 플래그를 다 건져올리는 모드 PROMISC모드로 바꿈. stIf.ifr_flags = stIf.ifr_flags | IFF_PROMISC;
// PROMISC 모드로 랜카드 설정이 바꿈. iRet = ioctl(iSock, SIOCSIFFLAGS, &stIf); if( 0 > iRet ) { printf("ioclt() failed\n"); close(iSock); return 0; }
// 읽어들인 byte 수. iRet = recvfrom(iSock, uc_Buffer, 1500, 0, (struct sockaddr *)&st_pktInfo, &ui_Len); // Ethernet 장치번호, Packet type ID : Layer 1 // iProto에 Packet Type 을 반환받음. iProto = L1_Ethernet(uc_Buffer); // L1_map을 가리키고있는 stpL1에다가 // 전역변수로 지정해둔 L1_list[]의 주소, L1_list를 넣어줌. // stpL1은 현재 L1_list를 가리키고있음. stpL1 = L1_list; while(1) { // L1_Ethernet() 의 반환값(ETHERTYPE_?)이 무엇이든 있을때 반복문 나감. if(iProto == (stpL1->uiType)) { break; }
// 전역변수 L1_list의 끝까지 도달하면 반복문 나감. if(0xFFFFFFFF == (stpL1->uiType)) { break; } ++stpL1; // L1_list의 배열 한칸씩 옮겨감. }
// Packet Type 이 건져와지면 실행 if(NULL != (stpL1->L1Func)) { stpL1->L1Func(uc_Buffer+14); }
// 받은 데이터 uc_Buffer, recvfrom으로 수신받은 byte만큼 // HexaView에 보냄. HexaView(uc_Buffer, iRet);
close(iSock); return 0; }
void HexaView(unsigned char *ucP, unsigned int isize) { int iCnt; int iloop; printf("----------------------------------------" "----------------------------------\n"); printf("Address \t\t\tHexa\t\t\t ASCII\n"); printf("\t ");
for(iCnt=0 ; iCnt <= 15 ; iCnt++) { printf("%02X ", iCnt); }
putchar('\n');
printf("----------------------------------------" "----------------------------------\n"); if( 0 == isize%16 ) { isize = isize / 16; } else { isize = (isize/16) + 1; } for(iloop=0; iloop < isize; iloop++) { printf("%08X ", ucP); for( iCnt=0 ; iCnt <= 15 ; iCnt++) { printf("%02X ", *(ucP+iCnt)); }
for( iCnt=0 ; iCnt <= 15 ; iCnt++ ) { if(0 == *(ucP+iCnt)) { printf("."); } else if( 32 > *(ucP+iCnt)) { printf("."); } else if( 127 < *(ucP+iCnt)) { printf("."); } else { printf("%c", *(ucP+iCnt)); } } putchar('\n'); ucP = ucP + 16; } } |