利用libpcap抓包(三)----------数据包解析函数的实现

下面是对抓取到的数据包进行解析,分2层以太网的解析,3层ip,icmp的解析,4层tcp,udp的解析

注:print是我自定义的宏,相当于printf

/******************************************************************************
  文 件 名   : callback.c
  版 本 号   : V1.1
  负 责 人   : Sophisticated
  生成日期   : 2018年9月28日
  最近修改   :
  文件描述   : 解析数据包的回调函数
  函数列表   :
              arp_callback
              ethernet_callback
              icmp_callback
              ip_callback
              pppoe_callback
              tcp_callback
              tcp_flag
              udp_callback
  修改历史   :
  1.日    期   : 2018年9月28日
    作    者   : Sophisticated
    修改内容   : 创建文件

******************************************************************************/
#include
#include
#include
#include
#include
#include

#include"head.h"
#include"callback.h"


char *tcp_flag(const u_char tcp_flags);
void pppoe_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet);


/*过滤条件*/
extern char filter_exp[128];

/*抓包设备名称*/
extern char *dev;

/*****************************************************************************
 函 数 名  : ethernet_callback
 功能描述  : 以太网数据包头分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月28日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void ethernet_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
	struct ethernet *ethheader;
	struct ip *ipptr;
	u_short protocol;
	u_int *id = (u_int *)arg;
	u_char *time = ctime((const time_t*)&pcap_pkt->ts.tv_sec);

    print("---------------Device : %s--------------\n",dev);
	print("---------------Filter: %s---------------\n",filter_exp);
	print("-----------------Analyze Info---------------\n");
	print("Id: %d\n",++(*id));
	print("Packet length: %d\n",pcap_pkt->len);
	print("Number of bytes: %d\n",pcap_pkt->caplen);
	print("Receive time: %s\n",time);
   
	int k;
	for (k = 0; k < pcap_pkt->len; k++)
	{
		/*表示以16进制的格式输出整数类型的数值,
		输出域宽为2,右对齐,不足的用字符0替代*/
		print(" %02x",packet[k]);
		if ((k + 1) % 16 == 0)
		{
			print("\n");
		}
	}

	print("\n\n");
	
	ethheader = (struct ethernet*)packet;
	print("---------------Data Link Layer-----------\n");

	print("Mac Src Address: ");
	int i;
	for (i = 0; i < ETHERNET_ADDR_LEN; i++)
	{
		if (ETHERNET_ADDR_LEN - 1 == i)
		{
			print("%02x\n",ethheader->ether_shost[i]);
		}
		else
		{
		print("%02x:",ethheader->ether_shost[i]);
		}
	}

	print("Mac Dst Address: ");
	int j;
	for (j = 0; j < ETHERNET_ADDR_LEN; j++)
	{
		if (ETHERNET_ADDR_LEN - 1 == j)
		{
			print("%02x\n",ethheader->ether_dhost[j]);
		}
		else
		{
		print("%02x:",ethheader->ether_dhost[j]);
		}
	}

	protocol = ntohs(ethheader->ether_type);

    /*对pppoe报文的处理*/
    if (0x8863 == protocol)
    {
        print("PPPOE Discovery");
        pppoe_callback(arg, pcap_pkt, packet);
    }
    if (0x8864 == protocol)
    {
        print("PPPOE Session");
        pppoe_callback(arg, pcap_pkt, packet);
    }
	
	print("----------------Network Layer-------------\n");
	switch (protocol)
	{
		case 0x0800: 
			print("IPv4 protocol!\n");
			ip_callback(arg, pcap_pkt, packet);
			break;
		case 0x0806:
			print("ARP protocol!\n");
			arp_callback(arg, pcap_pkt, packet);
			break;
		case 0x8035:
			print("RARP protocol!\n");
			break;
		case 0x86DD:
			print("IPv6 protocol!\n");
			break;
		case 0x880B:
			print("PPP protocol!\n");
			print("There is no function to process PPP packet!!!");
			break;
		default:
			print("Other Network Layer protocol is used!\n");
			break;	
	}	
	print("---------------------Done--------------------\n\n\n");
}

/*****************************************************************************
 函 数 名  : pppoe_callback
 功能描述  : pppoe数据包处理函数
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年10月8日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void pppoe_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
    struct pppoe *pppoeheader = (struct pppoe *)(packet + ETHERNET_HEAD_SIZE);
    print("Version: %d\n",(pppoeheader->pppoe_vtype & 0xf0) >> 4);
    print("Type: %d\n",pppoeheader->pppoe_vtype & 0x0f);
    print("Code: %d\n",pppoeheader->pppoe_code);
    print("Session ID: %d\n",ntohs(pppoeheader->pppoe_s_id));
    print("Payload Length: %d\n",ntohs(pppoeheader->pppoe_len));
}

/*****************************************************************************
 函 数 名  : ip_callback
 功能描述  : ip数据包分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月29日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void ip_callback(u_char *arg, const struct,pcap_pkthdr *pcap_pkt,const u_char *packet)
{
	u_char protocol;
	struct ip *ipheader;
	ipheader = (struct ip *)(packet + ETHERNET_HEAD_SIZE);

	print("Version: %d\n", (ipheader->ip_hlv & 0xf0) >> 4); //取hlv高4位
	print("Header Length: %d\n",ipheader->ip_hlv & 0x0f);  //取hlv低4位
	print("Type of Service: %x\n",ipheader->ip_tos);
	print("Total Length: %d\n",ntohs(ipheader->ip_len));
	print("Indentification: %x\n",ntohs(ipheader->ip_id));
	print("Offset: %d\n",ntohs(ipheader->ip_off));
	print("TTL: %d\n",ipheader->ip_ttl);
	print("Protocol: %d\n",ipheader->ip_protocol);
	print("CheckSum: %d\n",ntohs(ipheader->ip_sum));
	int i = 0;
	print("IP Src Address: ");
	for (i = 0; i < IP_ADDR_LEN; i++)
	{
		print("%d.",ipheader->ip_src[i]);
	}
	print("\nIP Dst Address: ");
	for (i = 0; i < IP_ADDR_LEN; i++)
	{
		print("%d.",ipheader->ip_dst[i]);
	}
	print("\n");
	
    protocol = ipheader->ip_protocol;
    if (0x01 == protocol)
    {
        print("ICMP Protocol!\n");
		icmp_callback(arg, pcap_pkt, packet);
    }
    
	print("----------------Transport Layer--------------\n");
	switch (protocol)
	{
		case 0x06:
			print("TCP Protocol!\n");
			tcp_callback(arg, pcap_pkt, packet);
			break;
		case 0x11:
			print("UDP Protocol!\n");
			udp_callback(arg, pcap_pkt, packet);
			break;
		case 0x02:
			print("IGMP Protocol!\n");
			print("There is no function to process IGMP packet!!!");
			break;
		default:
			print("Other Transport Layer protocol is used!\n");
			break;
	}
}

/*****************************************************************************
 函 数 名  : tcp_callback
 功能描述  : TCP数据包分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月28日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void tcp_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
	struct tcp *tcpheader = (struct tcp *)(packet + ETHERNET_HEAD_SIZE + IP_HEAD_SIZE(packet));

	print("Src Port: %d\n",ntohs(tcpheader->tcp_sport));
	print("Dst Port: %d\n",ntohs(tcpheader->tcp_dport));
	print("Squence Number: %d\n",ntohs(tcpheader->tcp_seqe));
	print("ACK Number: %d\n",ntohs(tcpheader->tcp_ack));
	print("Header Length: %d\n",(tcpheader->tcp_hre & 0xf0) >> 4);
	print("FLAG: %d\n",tcpheader->tcp_flag);
	print("Flag: %s\n",tcp_flag(tcpheader->tcp_flag));
	print("Window Size: %d\n",ntohs(tcpheader->tcp_win));
	print("Checksum: %d\n",ntohs(tcpheader->tcp_sum));
	print("Urgent Pointer: %d\n",ntohs(tcpheader->tcp_urp));	
}


/*****************************************************************************
 函 数 名  : tcpflag
 功能描述  : 判断TCP协议的标志位
 输入参数  : const u_char tcp_flags  
 输出参数  : 无
 返 回 值  : u_char
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月29日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
char *tcp_flag(const u_char tcp_flags)
{
	char flags[100] = "-";
	if ((TCP_CWR & tcp_flags) == TCP_CWR)
	{
		strncat(flags, "CWR ", 100);
	}
	if ((TCP_ECE & tcp_flags) == TCP_ECE)
	{
		strncat(flags, "ECE ", 100);
	}
	if ((TCP_URG & tcp_flags) == TCP_URG)
	{
		strncat(flags, "URG ", 100);
	}
	if ((TCP_ACK & tcp_flags) == TCP_ACK)
	{
		strncat(flags, "ACK ", 100);
	}
	if ((TCP_PUSH & tcp_flags) == TCP_PUSH)
	{
		strncat(flags, "PUSH ", 100);
	}
	if ((TCP_RST & tcp_flags) == TCP_RST)
	{
		strncat(flags, "RST ", 100);
	}
	if ((TCP_SYN & tcp_flags) == TCP_SYN)
	{
		strncat(flags, "SYN ", 100);
	}
	if ((TCP_FIN & tcp_flags) == TCP_FIN)
	{
		strncat(flags, "FIN ", 100);
	}
	return flags;	
}


/*****************************************************************************
 函 数 名  : icmp_callback
 功能描述  : ICMP数据包分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月29日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void icmp_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
    struct icmp *icmpheader = (struct icmp *)(packet + ETHERNET_HEAD_SIZE + IP_HEAD_SIZE(packet));
    u_char icmp_type = icmpheader->icmp_type;

    print("ICMP Type: %d   ",icmpheader->icmp_type);
    switch (icmp_type)
    {
        case 0x08:
            print("(ICMP Request)\n");
            break;
        case 0x00:
            print("(ICMP Response)\n");
            break;
        case 0x11:
            print("(Timeout!!!)\n");
            break;
    }
    
    print("ICMP Code: %d\n",icmpheader->icmp_code);
    print("ICMP CheckSum: %d\n",icmpheader->icmp_sum);
}


/*****************************************************************************
 函 数 名  : udp_callback
 功能描述  : UDP数据包分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月28日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void udp_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
    struct udp *udpheader = (struct udp *)(packet + ETHERNET_HEAD_SIZE + IP_HEAD_SIZE(packet));

    print("Src Port: %d\n",ntohs(udpheader->udp_sport));
    print("Dst Port: %d\n",ntohs(udpheader->udp_dport));
    print("UDP Length: %d\n",ntohs(udpheader->udp_len));
    print("Checksum: %d\n",ntohs(udpheader->udp_sum));
}


/*****************************************************************************
 函 数 名  : arp_callback
 功能描述  : arp数据包分析
 输入参数  : u_char *arg                         
             const struct pcap_pkthdr *pcap_pkt  
             const u_char *packet                
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2018年9月28日
    作    者   : Sophisticated
    审 核 人   : #
    修改内容   : 新生成函数

*****************************************************************************/
void arp_callback(u_char *arg, const struct pcap_pkthdr *pcap_pkt,const u_char *packet)
{
	struct arp *arpheader;

	arpheader = (struct arp *)(packet + ETHERNET_HEAD_SIZE);
	print("Hardware type: %s\n",(ntohs(arpheader->arp_hrd) == 0x0001) ? "Ethernet" : "Unknow");
	print("Protocol type: %s\n",(ntohs(arpheader->arp_pro) == 0x0800) ? "IPv4" : "Unknow");
	print("Operation: %s\n",(ntohs(arpheader->arp_op) == ARP_REQUEST) ? "ARP_Request" : "ARP_Reply");
	int i = 0;
	print("Sender MAC:");
	for (i = 0; i < ETHERNET_ADDR_LEN; i++)
	{
		print("%02x:",arpheader->arp_shost[i]);
	}
	print("\nSender IP:");
	for (i = 0; i < IP_ADDR_LEN; i++)
	{
		print("%d.",arpheader->arp_sip[i]);
	}
	print("\nTarget Mac:");
	for (i = 0; i < ETHERNET_ADDR_LEN; i++)
	{
		print("%02x:",arpheader->arp_dhost[i]);
	}
	print("\nTarget IP:");
	for (i = 0; i < IP_ADDR_LEN; i++)
	{
		print("%d.",arpheader->arp_dip[i]);
	}
	print("\n\n");
}

在以太网解析中判断协议类型,即3层锁使用的协议,然后根据三层使用的协议使用相应的函数解析,然后在3层解析中判断4层使用协议类型。

你可能感兴趣的:(Linux网络)