#include "ethernet.h" #include "hexaview.h"
// write (1, "\033[1;1H\033[2J", 10);//화면 지우는 것.
void hexaview(unsigned char *ucP, unsigned int isize);
typedef struct _L1_map { unsigned int uiType; int (*L1func)(void *); }L1_map; //전역변수로 typedef struct 구조체 정의.
L1_map L1list[]={ {ETHERTYPE_PUP, 0}, {ETHERTYPE_IP, L2_IP}, {ETHERTYPE_ARP, 0}, {ETHERTYPE_REVARP, 0}, {0xFFFFFFFF , 0} }; // 전역변수로 구조체 L1list선언.
int main() { int iSock; int iRet; struct ifreq stIF; // unsigned char ucBuff[1500]; struct sockaddr_in stPkat_Info; unsigned int uiLen=sizeof(stPkat_Info); L1_map *stpL1; int ipProto; iSock=socket(AF_INET, SOCK_PACKET, ntohs(ETH_P_ALL));//소켓 생성. if(0>iSock) { fprintf(stderr, "error"); return 0; } //위 if문은 에러시 화면에 error를 찍고 프로그램 종료.
strcpy(stIF.ifr_name, "eth0" );//문자열 eth0를 stIF.ifr_name에 대입.(랜카드, 랜번호) iRet=ioctl(iSock, SIOCGIFFLAGS, &stIF); //ioctl()함수 사용. //첫 번째 인자는 소켓번호, 두번재 인자는 , 3번째 인자는 크기. if(0>iRet)//에러처리 { fprintf(stderr, "error"); close(iSock); return 0; } stIF.ifr_flags= stIF.ifr_flags|IFF_PROMISC;//IFF_PROMISC는 랜카드를 PROMISC모드로 설정한다.
iRet=ioctl(iSock, SIOCSIFFLAGS, &stIF); //소켓을 설정한다.
if(0>iRet) { fprintf(stderr, "error"); close(iSock); return 0; }
iRet=recvfrom(iSock, ucBuff, 1500, 0, (struct sockaddr *)&stPkat_Info , &uiLen); /* 데이터를 수신하는 함수 1.소켓 2.데이터를 저장하는 버퍼 3.데이터를 저장하는 버퍼의 크기를 지정. 4.제어 플래그, 대부분의 경우 0으로 설정한다. 5.송신자의 주소, 구조체. 이 구조체의 반환영에 따라 struct sockaddr형으로 캐스팅한다. 포인터이기 때문에 인자에 주소를 넣어야 한다. 6. 자료형이 포인터이기 때문에 주소로 받아야하며, 송신자 주소의 크기가 되겠다. */
ipProto=L1_ethernet(ucBuff);//L1_ethernet(ucBuff)함수를 호출한다. 반환형은 int형. ipProto에 넣는다. //함수의 설명은 아래 소스를 참조. 인자는 void형 포인터. 송신된 데이터가 들어있는 // ucBuff를 인자로 넣는다.
stpL1=L1list; //전역변수 구조체형 L1list배열을 구조체형 포인터에 대입. 배열이름은 주소이기때문에 //포인터에 대입이 가능한다. //아래 while문이 실행됨으로서 L1list안에 내용들이 출력이 된다.
while(1) { if(iProto==(stpL1->uiType)) //iProto와 stpL1->uiType과 같으면, 정지. uiType은 전역변수 unsigned int형 구조체의 멤버. { break; } if(0xFFFFFFFF==(stpL1->uiType))//L1list의 배열의 끝으로 마찬가지로 while문에 종료조건이다. { break;
} ++stpL1; //포인터를 한 칸 이동시키면, 가르키는 주소도 한 칸 이동된다. 처음에는 L1list[0]을 가르키다 // 1증가하면 다음주소인 L1list[1]을 가르킨다.
}
if(0!=stpL1->L1func) { (stpL1->L1func)(ucBuff+14);//
}
hexaview(ucBuff,iRet); //헥사뷰 함수 호출.
close(iSock); return 0; }
void hexaview(unsigned char *ucP, unsigned int isize) { int iCnt; int iLoop;
printf("---------------------------------------" "----------------------------------\n"); printf("address Hexa ASCII\n"); printf(" "); for(iCnt=0; iCnt<=15; iCnt= iCnt +1) { 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= iLoop+1) { printf("%08X ", ucP);
for(iCnt=0;iCnt<=15;iCnt=iCnt +1) { printf("%02X ", *(ucP+iCnt)); }
for(iCnt=0; iCnt<=15; iCnt= iCnt +1) {
if(0==*(ucP+iCnt)) { printf("."); } else if(*(ucP+iCnt)<32) { printf("."); } else if(*(ucP+iCnt)>127) { printf("."); } else { printf("%c", *(ucP+iCnt)); } } putchar('\n'); ucP= ucP+16; }
return;
}
L1_ethernet.c 함수
//패킷을 건져올리는 함수.
#include "ethernet.h"
int L1_ethernet(void *vp) { struct ether_header *stEth=(struct ether_header *)vp; //printf("-----%02s\n", ether_ntoa ((struct ether_addr *)stEth->ether_shost)); // printf("mac address: [%02X %02X %02X %02X %02X %02X]->"stEth->ether_shost[0], stEth->ether_shost[1],stEth->ether_shost[2], stEth->ether_shost[3],stEth->ether_shost[4],stEth->ether_shost[5]);
printf("[%02X %02X %02X %02X %02X %02X]\n", stEth->ether_dhost[0],stEth->ether_dhost[1],stEth->ether_dhost[2], stEth->ether_dhost[3],stEth->ether_dhost[4],stEth->ether_dhost[5]);
printf("packet type : "); switch(ntohs(stEth->ether_type))//big endian으로 바꾸는 함수를 스위치문 인자. { case ETHERTYPE_IP: printf("IP\n"); //L2_IP(ucdata+14); break; case ETHERTYPE_ARP: printf("Address resolution\n"); break; case ETHERTYPE_REVARP: printf("Reverse ARP\n"); break; default: printf("unknown: %04X\n", ntohs(stEth->ether_type)); break;
} //스위치문에서 해당패킷이 선택되어 지면, 해당 printf()문을 출력한다. return (ntohs(stEth->ether_type));스위치문에서 선택된 ether타입을 반환한다. }
|
L2ip.c 함수 각종 ip, tcp와 같은 패키지를 화면에 출력하는 함수. ip헤더부분을 나타낸다.

#include "ethernet.h"
int L2_IP(void *vp) { struct ip * stIp=vp; unsigned short usChecksum; printf("ipversion : IPv%d\n", stIp->ip_v); //0~4 4bit version
printf("ipheader size : %dbytes\n", (stIp->ip_hl)*4); //0~4 4bit header length
printf("type of service : low delay %s\n", (0==((stIp->ip_tos)&IPTOS_LOWDELAY))? "NO": "yes"); //8bit type of service
printf(" throughput %s\n", (0==((stIp->ip_tos)&IPTOS_THROUGHPUT))? "NO": "yes"); //total packet length
printf(" relability %s\n", (0==((stIp->ip_tos)&IPTOS_RELIABILITY))? "NO": "yes"); // printf(" lowcost %s\n", (0==((stIp->ip_tos)&IPTOS_LOWCOST))? "NO": "yes");
printf("total length : %d\n", ntohs(stIp->ip_len));
printf("identification : %d\n", ntohs(stIp->ip_id));
printf("flag : More Fragment %s\n", (0==(ntohs(stIp->ip_off)&IP_MF))? "NO": "yes");
printf("flag : Don't Fragment %s\n", (0==(ntohs(stIp->ip_off)&IP_DF))? "NO": "yes"); printf("flagmentation off_set : %d\n", ntohs(stIp->ip_off)&IP_OFFMASK);
printf("time to live : %d\n", stIp->ip_ttl);
printf("프로토콜 : "); switch(stIp->ip_p) { case IPPROTO_IP: printf(" Dummy protocol for TCP\n"); break; /*case IPTOS_THROUGHPUT: printf(" IPv6 Hop-by-Hop options\n"); break;*/ case IPPROTO_ICMP : printf("Internet Control Message Protocol\n"); break; case IPPROTO_IGMP: printf("Internet Group Management Protocol\n"); break; case IPPROTO_IPIP: printf("IPIP tunnels (older KA9Q tunnels use 94)\n"); break; case IPPROTO_TCP : printf("Transmission Control Protocol\n"); break;
case IPPROTO_EGP : printf("Exterior Gateway Protocol\n"); break; case IPPROTO_PUP: printf("PUP protocol\n"); break; case IPPROTO_UDP: printf("User Datagram Protocol\n"); break; case IPPROTO_IDP : printf("XNS IDP protocol\n"); break; case IPPROTO_TP : printf("SO Transport Protocol Class 4\n"); break; case IPPROTO_IPV6: printf("IPv6 header\n"); break; case IPPROTO_ROUTING: printf("IPv6 routing header\n"); break; case IPPROTO_FRAGMENT: printf("IPv6 fragmentation header\n"); break; default: break;
}
printf("%04x\n",stIp->ip_sum); stIp->ip_sum=0x0000; printf("check sum :%04x\n", smart_cksum(stIp,20)); usChecksum=stIp->ip_sum; stIp->ip_sum=0x0000; printf("checksum check : %s\n", (usChecksum==smart_cksum(stIp,(stIp->ip_hl)*4))?"ok":"fail"); printf("IP Address : [%s]->",inet_ntoa(stIp->ip_src)); printf("[%s]\n", inet_ntoa(stIp->ip_dst)); printf("IP Address : [%s]->[%s]\n",inet_ntoa(stIp->ip_src),inet_ntoa(stIp->ip_dst));
return stIp->ip_p;//stIp->ip_p 스위치문조건을 만족하는 해당 타입을 반환한다. }
//체크 섬 함수. unsigned short smart_cksum(void *vpData, unsigned int uiLen) { unsigned long ulSum; for(ulSum =0;uiLen > 0;uiLen=uiLen-2) { ulSum = ulSum + *((unsigned short *)vpData); vpData= (unsigned short *)vpData +1; } ulSum = (ulSum>>16) + (ulSum&0xffff); ulSum = ulSum + (ulSum>>16); return ~ulSum; }
ethernet.h 헤더파일
#ifndef _ETHERNET_H_ #define _ETHERNET_H_
#include <stdio.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <unistd.h> #include <linux/if.h> #include <linux/if_ether.h> #include <pcap/pcap.h> #include <netinet/ether.h> #include <netinet/ip.h> #include <netinet/in.h>
int L1_ethernet(void *vp); int L2_IP(void *vp); unsigned short smart_cksum(void *vpData, unsigned int uiLen);
#endif//_ETHERNET_H_
|
| |