패킷은 패킷 헤더 24바이트를 제외하고는 다음과 같은 구조로 이루어져 있다.

그리고 IP Header는 다음과 같은 구조로 이루어져 있다. 따라서 형식에 맞는 구조체를 선언하여 패킷을 읽는 방식을 사용했다.

Ping 옵션을 사용하여 [-l size]송신 버퍼 크기를 변경했을 때 패킷을 잡은 모습이다.
송신 패킷이 분할 되었고 마지막 fragment에는 ICMP가 붙어있다.




#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef struct _PFHeader //패킷 파일 헤더
{
unsigned int magic;
unsigned short major;
unsigned short minor;
unsigned int gmt_to_local;
unsigned int timestamp;
unsigned int max_caplen;
unsigned int linktype;
} PFHeader;
typedef struct _pcap_pkthdr //패킷 파일 헤더
{
unsigned int sec;
unsigned int usec;
unsigned int caplen;
unsigned int len;
} pcap_pkthdr;
typedef struct _ether_header //패킷 파일 헤더
{
unsigned char DMac[6];
unsigned char SMac[6];
unsigned char Ether_type[2];
} ether_header;
typedef struct _ip_header {
unsigned char hlen;
unsigned char type_of_service;
unsigned short total_length;
//
unsigned char id[2];
unsigned char fragmentation_offset[2];
//
unsigned char time_to_live;
unsigned char protocol;
unsigned short header_checksum;
//
unsigned char src_ip_address[4];
unsigned char dest_ip_address[4];
} ip_header;
int num_of_packet = 0;
void print_pcap_pkthdr(pcap_pkthdr* pcap_p) {
printf("sec:%d\n", pcap_p->sec);
printf("usec:%d\n", pcap_p->usec);
printf("caplen:%d\n", pcap_p->caplen);
printf("len:%d\n", pcap_p->len);
}
void print_local_time(pcap_pkthdr* pcap_p) {
time_t timer = pcap_p->sec;
struct tm* t = localtime(&timer);
printf("Local time: %d %02d:%02d:%02d.%06d\n", t->tm_year + 1900, t->tm_hour, t->tm_min, t->tm_sec, pcap_p->usec);
}
void print_cap_len(pcap_pkthdr* pcap_p) {
printf("captured length: %d, actual length: %d \n", pcap_p->caplen, pcap_p->len);
}
void print_ipheader_len(ip_header* ipheader) {
printf("The length in the IP header: %d\n", (ipheader->hlen & 0xF) * 4);
}
void print_ether_header(ether_header* eheader) {
printf("Source MAC address %02X", eheader->SMac[0]);
for (int i = 1; i < 6; i++) {
printf(":%02X", eheader->SMac[i]);
}
printf(" -> ");
printf("Destination MAC address %02X", eheader->DMac[0]);
for (int i = 1; i < 6; i++) {
printf(":%02X", eheader->DMac[i]);
}
printf("\n");
}
void print_protocol(int protocol) {
printf("protocol: ");
switch (protocol) {
case 1:
printf("ICMP");
break;
case 2:
printf("IGMP");
break;
case 6:
printf("TCP");
break;
case 9:
printf("IGRP");
break;
case 17:
printf("UDP");
break;
case 47:
printf("GRE");
break;
case 50:
printf("ESP");
break;
case 51:
printf("AH");
break;
case 57:
printf("SKIP");
break;
case 88:
printf("EIGRP");
break;
case 89:
printf("OSPF");
break;
case 115:
printf("L2TP");
break;
default:
printf("ERROR");
break;
}
printf("\n");
}
void print_id_and_flags(ip_header* ipheader) {
unsigned int id = (ipheader->id[0] << 8) + ipheader->id[1];
bool DF = ipheader->fragmentation_offset[0] & (1 << 6);
bool MF = ipheader->fragmentation_offset[0] & (1 << 5);
printf("ID: %d\n", id);
printf("DF: %d\n", DF);
printf("MF: %d\n", MF);
}
void print_TTL(int ttl) {
printf("TTL: %d\n", ttl);
}
void print_TOS(int tos) {
printf("Type of service: %d\n", tos);
}
void print_ip_header(ip_header* ipheader) {
printf("Source IP address %d", ipheader->src_ip_address[0]);
for (int i = 1; i < 4; i++) {
printf(".%d", ipheader->src_ip_address[i]);
}
printf(" -> ");
printf("Destination IP address %d", ipheader->dest_ip_address[0]);
for (int i = 1; i < 4; i++) {
printf(".%d", ipheader->dest_ip_address[i]);
}
printf("\n");
print_protocol(ipheader->protocol);
print_id_and_flags(ipheader);
print_TTL(ipheader->time_to_live);
}
void print_ip_address(ip_header* ipheader) {
printf("Source IP address %d", ipheader->src_ip_address[0]);
for (int i = 1; i < 4; i++) {
printf(".%d", ipheader->src_ip_address[i]);
}
printf(" -> ");
printf("Destination IP address %d", ipheader->dest_ip_address[0]);
for (int i = 1; i < 4; i++) {
printf(".%d", ipheader->dest_ip_address[i]);
}
printf("\n");
}
void print_one_packet(FILE* fp) {
printf("============PACKET %d=============\n", ++num_of_packet);
char buffer[70000];
pcap_pkthdr pcap_p;
ether_header eheader;
ip_header ipheader;
fread(&pcap_p, sizeof(pcap_pkthdr), 1, fp);
print_local_time(&pcap_p); // 7번
print_cap_len(&pcap_p); // 8번 caplen,actlen
fread(&eheader, sizeof(ether_header), 1, fp);
if (eheader.Ether_type[0] == 0x8) {
fread(&ipheader, sizeof(ip_header), 1, fp);
// print_ipheader_len(&ipheader); // 8번 ip header len
print_ether_header(&eheader); // 9번
print_ip_address(&ipheader); // 10번
print_protocol(ipheader.protocol); // 11번
print_id_and_flags(&ipheader); // 12번
print_TTL(ipheader.time_to_live); // 13번
print_TOS(ipheader.type_of_service);
fread(buffer, pcap_p.caplen - sizeof(ether_header) - sizeof(ip_header), 1, fp);
} else {
fread(buffer, pcap_p.caplen - sizeof(ether_header), 1, fp);
}
printf("=============+++++++++============\n", ++num_of_packet);
}
int main(int argc, char* argv[]) {
FILE* fp;
char buffer[100];
PFHeader h;
pcap_pkthdr pcap_p;
ether_header eheader;
ip_header ipheader;
fp = fopen(argv[1], "rb");
if (fp == NULL) {
perror("error: no file");
exit(0);
}
fread(&h, sizeof(PFHeader), 1, fp);
while (1) {
if (feof(fp) != 0) break;
print_one_packet(fp);
}
printf("\n\n");
return 0;
}