#include "pcap.h"
#include "stdio.h"
/*下边是以太网的协议格式 */
struct ethernet_header
{
u_int8_t ether_dhost[6]; /*目的以太地址*/
u_int8_t ether_shost[6]; /*源以太网地址*/
u_int16_t ether_type; /*以太网类型*/
};
/*ip地址格式*/
typedef u_int32_t in_addr_t;
//struct in_addr
//{
// in_addr_t s_addr;
//};
struct ip_header
{
#ifdef WORKS_BIGENDIAN
u_int8_t ip_version:4, /*version:4*/
ip_header_length:4; /*IP协议首部长度*/
#else
u_int8_t ip_header_length:4,
ip_version:4;
#endif
u_int8_t ip_tos; /*TOS服务质量*/
u_int16_t ip_length; /*总长度*/
u_int16_t ip_id; /*标识*/
u_int16_t ip_off; /*偏移*/
u_int8_t ip_ttl; /*生存时间*/
u_int8_t ip_protocol; /*协议类型*/
u_int16_t ip_checksum; /*校验和*/
struct in_addr ip_source_address; /*源IP*/
struct in_addr ip_destination_address; /*目的IP*/
};
/*关于tcp头部的定义*/
struct tcp_header
{
u_int16_t tcp_source_port;
u_int16_t tcp_destination_port;
u_int32_t tcp_acknowledgement;
u_int32_t tcp_ack;
#ifdef WORDS_BIGENDIAN
u_int8_t tcp_offset:4 ,
tcp_reserved:4;
#else
u_int8_t tcp_reserved:4,
tcp_offset:4;
#endif
u_int8_t tcp_flags;
u_int16_t tcp_windows;
u_int16_t tcp_checksum;
u_int16_t tcp_urgent_pointer;
};
/*下边实现tcp数据包分析的函数定义tcp_protocol_packet_callback*/
void tcp_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
packet_header,const u_char* packet_content)
{
struct tcp_header *tcp_protocol ; /*tcp协议变量*/
u_char flags; /*标记*/
int header_length; /*头长度*/
u_short source_port; /*源端口*/
u_short destination_port; /*目的端口*/
u_short windows; /*窗口大小*/
u_short urgent_pointer; /*紧急指针*/
u_int sequence; /*序列号*/
u_int acknowledgement; /*确认号*/
u_int16_t checksum; /*检验和*/
tcp_protocol=(struct tcp_header *) (packet_content+14+20); /*获得tcp首部内容*/
source_port =ntohs(tcp_protocol->tcp_source_port); /*获得源端口号*/
destination_port =ntohs(tcp_protocol->tcp_destination_port); /*获得目的端口号*/
header_length =tcp_protocol->tcp_offset *4; /*获得首部长度*/
sequence =ntohl(tcp_protocol->tcp_acknowledgement);
/*获得序列号*/
acknowledgement =ntohl(tcp_protocol->tcp_ack);
windows = ntohs(tcp_protocol->tcp_windows);
urgent_pointer = ntohs(tcp_protocol->tcp_urgent_pointer);
flags = tcp_protocol->tcp_flags;
checksum =ntohs (tcp_protocol->tcp_checksum);
printf("***************TCP Protocol (Transprot Layer )***************/n");
printf("Source Port %d/n",source_port);
printf("Destination Port %d/n",destination_port);
switch (destination_port)
{
case 80:printf("Protocol is http ");break;
case 21:printf("Protocol is ftp");break;
case 23:printf("Protocol is telnet ");break;
case 25:printf("Protocol is smtp");break;
case 110:printf("Protocol is pop3");break;
default :break;
}
printf("Sequence Number %u /n",sequence);
printf("Acknowledgement Number %u /n",acknowledgement);
printf("Header Length %d /n",header_length);
printf("Reserved %d /n",tcp_protocol->tcp_reserved);
printf("Flags:");
if (flags & 0x08) printf("PSH");
if (flags & 0x10) printf("ACK");
if (flags & 0x02) printf("SYN");
if (flags & 0x20) printf("URG");
if (flags & 0x01) printf("FIN");
if (flags & 0x04) printf("RST");
printf("/n");
printf("Windows Size :%d /n",windows);
printf("Checksum :%d/n",checksum);
printf("Urgent pointer :%d/n",urgent_pointer);
}
/*下边实现IP数据包分析的函数定义ethernet_protocol_packet_callback*/
void ip_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
packet_header,const u_char* packet_content)
{
struct ip_header *ip_protocol; /*ip协议变量*/
u_int header_length; /*长度*/
u_int offset; /*偏移*/
u_char tos; /*服务质量*/
u_int16_t checksum; /*校验和*/
ip_protocol=(struct ip_header*) (packet_content+14);
/*获得ip数据包的内容去掉以太头部*/
checksum=ntohs(ip_protocol->ip_checksum); /*获得校验和*/
header_length=ip_protocol->ip_header_length*4; /*获得长度*/
tos=ip_protocol->ip_tos; /*获得tos*/
offset=ntohs(ip_protocol->ip_off); /*获得偏移量*/
printf("***************IP Protocol network layer***************/n /n");
printf("IP Version :%d/n",ip_protocol->ip_version);
printf("Header length :%d/n",header_length);
printf("Tos :%d/n",tos);
printf("Total length:%d/n",ntohs(ip_protocol->ip_length));/*获得总长度*/
printf("Identification:%d/n",ntohs(ip_protocol->ip_id)); /*获得标识*/
printf("Offset:%d/n",(offset&0x1fff)*8); /**/
printf("TTL:%d/n",ip_protocol->ip_ttl); /*获得ttl*/
printf("protocol:%d/n",ip_protocol->ip_protocol); /*获得协议类型*/
printf("Header checksum:%d/n",checksum);
printf("Source address:%s/n",inet_ntoa(ip_protocol->ip_source_address)); /*
获得源ip地址*/
printf("Destinastion address :%s/n",inet_ntoa(ip_protocol->ip_destination_address));
/*获得目的ip地址*/
switch(ip_protocol->ip_protocol)
{
case 6 :printf("The Transport Layer Protocol is TCP#####################################/n");
tcp_protocol_packet_callback(argument,packet_header,packet_content);
break; /*协议类型是6代表TCP*/
case 17:printf("The Transport Layer Protocol is UDP/n");break;/*17代表UDP*/
case 1:printf("The Transport Layer Protocol is ICMP/n");break;/*代表ICMP*/
case 2:printf("The Transport Layer Protocol is IGMP/n");break;/*代表IGMP*/
default :break;
}
}
void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr *packet_header,const u_char* packet_content)
{
u_short ethernet_type; /*以太网协议类型*/
struct ethernet_header *ethernet_protocol; /*以太网协议变量*/
u_char *mac_string;
static int packet_number=1;
printf("*******************************************************************************/n");
printf("The %d ip packet is captured,/n",packet_number);
printf("**********ethernet protocol (link Layer)*******************/n");
ethernet_protocol =(struct ethernet_header *) packet_content; /*获得一太网协议数据内容*/
printf("Ethernet type is :/n");
ethernet_type=ntohs(ethernet_protocol->ether_type);
/*获得以太网类型*/
printf("%04x/n",ethernet_type);
switch(ethernet_type) /*判断以太网类型的值*/
{
case 0x0800 : printf("The network layer is ip protocol/n");break;
case 0x0806 : printf("The network layer is ARP protocol/n");break;
case 0x8035 : printf("The network layer is RARP protocol/n");break;
default: break;
}
printf("Mac souce address is :/n");
mac_string=ethernet_protocol->ether_shost;
printf("%02x:%02x:%02x:%02x:%02x:%02x:/n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
/*获得以太网地址*/
printf("Mac Destination Address is :/n");
mac_string=ethernet_protocol->ether_dhost;
printf("%02x:%02x:%02x:%02x:%02x:%02x:/n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
/*获得目的端口地址*/
switch (ethernet_type)
{case 0x0800: ip_protocol_packet_callback(argument,packet_header,packet_content);break;
/*如果上层是ip协议,就调用分析ip协议的函数对ip包进行贩治*/
default :break;
}
packet_number++;
}
main()
{
pcap_if_t *alldevs;
pcap_if_t *d;
int inum=0;
int i=0;
pcap_t *adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
/* 获得网卡的列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s/n", errbuf);
exit(1);
}
/* 打印网卡信息 */
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)/n", d->description);
else
printf(" (No description available)/n");
}
if(i==0)
{
printf("/nNo interfaces found! Make sure LibPcap is installed./n");
return -1;
}
printf("Enter the interface number (1-%d):",i);
scanf("%d", &inum); //输入要选择打开的网卡号
if(inum < 1 || inum > i) //判断号的合法性
{
printf("/nInterface number out of range./n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
/* 找到要选择的网卡结构 */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
/* 打开选择的网卡 */
if ( (adhandle= pcap_open_live(d->name, /* 设备名称*/
65536, /* portion of the packet to capture.*/
/* 65536 grants that the whole packet will be captured on allthe MACs.*/
1, /* 混杂模式*/
1000, /* 读超时为1秒*/
errbuf /* error buffer*/
) ) == NULL)
{
fprintf(stderr,"/nUnable to open the adapter. %s is not supported by LibPcap/n");
/* Free the device list */
pcap_freealldevs(alldevs);
return -1;
}
printf("/nlistening on %s.../n", d->description);
/* At this point, we don't need any more the device list. Free it */
pcap_freealldevs(alldevs);
/* 开始捕获包 */
pcap_loop(adhandle, 0, ethernet_protocol_packet_callback, NULL);
return 0;
}