libpcap包的使用

1. 示例程序

此示例程序捕获本地包,即发往127.0.0.1的包,若要捕获外地包,之需要修改device的值为eth0或使用pcap_lookupdev函数查找可用网卡。

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h> 
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

typedef unsigned char UCHAR;
typedef unsigned short USHORT;

void pcap_handle(u_char *user,const struct pcap_pkthdr *header, const u_char *pkt_data);

typedef struct{    //以太网帧首部
	UCHAR DestMac[6];
	UCHAR SrcMac[6];
	UCHAR Etype[2];   
}ETHHEADER;
typedef struct  {   //IP头部
        UCHAR  header_len:4;
        UCHAR  version:4;   
        UCHAR  tos:8;            // type of service
        USHORT  total_len:16;      // length of the packet
        USHORT  ident:16;          // unique identifier
        USHORT  flags:16;          
        UCHAR  ttl:8;            
        UCHAR  proto:8;          // protocol ( IP , TCP, UDP etc)
        USHORT  checksum:16;       
        UCHAR  sourceIP[4];
        UCHAR  destIP[4];
		        
}IPHEADER;
typedef struct {	//TCP头部
		USHORT srcPort:16;
		USHORT decPort:16;
		UCHAR id[4];
		UCHAR ackId[4];
		UCHAR unused1:4;
		UCHAR header_len:4;
		UCHAR unused2:2;
		UCHAR flag:6;
}TCPHEADER;
typedef struct {	//端口号
	USHORT srcPort;
	USHORT decPort;
}PORT;
char *Proto[] = {"Reserved", "ICMP", "IGMP", "GGP", "IP", "ST", "TCP",
 "UCL", "EGP", "IGP", "BBN-RCC-MON", "NVP-II", "PUP",
 "ARGUS", "EMCON", "XNET", "CHAOS", "UDP", "MUX", 
 "DCN-MEAS", "HMP", "PRM", "XNS-IDP", "TRUNK-1", 
"TRUNK-2", "LEAF-1", "LEAF-2", "RDP", "IRTP", "ISO-TP4", "NETBLT","MFE-NSP", 
"MERIT-INP", "SEP", "3PC", "IDPR", "XTP", "DDP", "IDPR-CMTP", "TP++", "IL", "SIP", 
"SDRP", "SIP-SR", "SIP-FRAG", "IDRP", "RSVP", "GRE", "MHRP", "BNA", "SIPP-ESP",  
"SIPP-AH", "I-NLSP", "SWIPE", "NHRP", "unassigned", "unassigned","unassigned", 
"unassigned", "unassigned", "unassigned","any host internal protocol", "CFTP", "any local network", "SAT-EXPAK", "KRYPTOLAN", "RVD", "IPPC", "any distributed file system",  
"SAT-MON", "VISA", "IPCV", "CPNX", "CPHB", "WSN", "PVP", "BR-SAT-MON", "SUN-ND", 
"WB-MON", "WB-EXPAK", "ISO-IP",  "VMTP", "SECURE-VMTP", "VINES", "TTP", 
"NSFNET-IGP", "DGP", "TCF", "IGRP", "OSPFIGP", "Sprite-RPC", "LARP", "MTP", "AX.25", 
"IPIP", "MICP", "SCC-SP", "ETHERIP", "ENCAP", "any private encryption scheme", "GMTP"};

int npacketnum;
int main(void)
{
        char *device = "lo";
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *phandle;
        bpf_u_int32 ipaddress, ipmask;
        struct bpf_program fcode;
        int datalink;
/*        if ((device = pcap_lookupdev(errbuf)) == NULL)
		{
			perror(errbuf);
			return 0;
		}
        else
		{
			printf("device: %s\n", device);
		}
*/
        phandle = pcap_open_live(device, 200, 0, 500, errbuf);
        if (phandle == NULL)
        {
			perror(errbuf);
			return 0;
		}

        if (pcap_lookupnet(device, &ipaddress, &ipmask, errbuf) == -1)
		{
			perror(errbuf);
			return 0;
		}
        else 
		{                                         
            char net[INET_ADDRSTRLEN], mask[INET_ADDRSTRLEN];
            if (inet_ntop(AF_INET, &ipaddress, net, sizeof(net)) == NULL)
			{
				perror("inet_ntop");
			}
            else if (inet_ntop(AF_INET, &ipmask, mask, sizeof(net)) == NULL)
            {
				perror("inet_ntop");
			}
            printf("NET Address: %s, Network Mask: %s\n", net, mask);
        }

		int bflag = 1;
		while(bflag)
		{
			printf("Input Packet Filter:>");
			char filterString[1024];
			fgets(filterString, 1024, stdin);
			//编译过滤规则
			if (pcap_compile(phandle, &fcode, filterString, 0, ipmask) == -1) {
                fprintf(stderr, "pcap_compile: %s,please input again......\n", pcap_geterr(phandle));                
			}
			else
				bflag = 0;
		}
		//设定过滤规则
        if (pcap_setfilter(phandle, &fcode) == -1) 
		{
                fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(phandle));
				return 0;
        }

        if ((datalink = pcap_datalink(phandle)) == -1)
		{
                fprintf(stderr, "pcap_datalink: %s\n", pcap_geterr(phandle));
                return 0;
        }
        printf("datalink = %d\n", datalink);

		npacketnum = 0;
		//捕获并处理数据包,使用pcap_handle函数处理数据包
		pcap_loop(phandle, 0, pcap_handle, NULL);// 
        return 1;
}

void pcap_handle(u_char *user,const struct pcap_pkthdr *header, const u_char *pkt_data)
{

	ETHHEADER *eth_header = (ETHHEADER *)pkt_data;//以太网帧头部
	printf("================Begin Analysis [%d] Packet ====================\n",npacketnum++);
	printf("packet length:%ld \n",header->len);
	if (header->len >= 14)// IP数据报头部
	{
	
		IPHEADER *ip_header=(IPHEADER *)(pkt_data+14);
		int iph_len = ip_header->header_len;
		iph_len <<= 2;//IP首部大小,单位4字节

		char strtype[100];
		if (ip_header->proto > 99)
			strcpy(strtype ,"IP/UNKNOWN");
	    else
			strcpy(strtype, Proto[ip_header->proto]);

		printf("Source MAC:%02X-%02X-%02X-%02X-%02X-%02X ==>", eth_header->SrcMac[0],
			eth_header->SrcMac[1], eth_header->SrcMac[2], eth_header->SrcMac[3],
			eth_header->SrcMac[4], eth_header->SrcMac[5]);// ÌáÈ¡ÔŽMACµØÖ·
        printf("Dest MAC:%02X-%02X-%02X-%02X-%02X-%02X \n", eth_header->DestMac[0],
			eth_header->DestMac[1], eth_header->DestMac[2], eth_header->DestMac[3],
			eth_header->DestMac[4], eth_header->DestMac[5]);//ÌáÈ¡Ä¿µÄMACµØÖ·

		printf("Source IP:%d.%d.%d.%d==>",ip_header->sourceIP[0] ,ip_header->sourceIP[1],ip_header->sourceIP[2],
			ip_header->sourceIP[3]);

		printf("Dest IP:%d.%d.%d.%d\n",ip_header->destIP[0] ,ip_header->destIP[1],ip_header->destIP[2],
			ip_header->destIP[3]);
		

		printf("Protocol:%s\n",strtype);
		if((strcmp("TCP",strtype)==0)
			||(strcmp("UDP",strtype)==0))
		{
			PORT *port=(PORT *)(pkt_data+14+iph_len);
			printf("Source Port:%d==>",ntohs(port->srcPort));
			printf("Dest Port:%d\n",ntohs(port->decPort ));
		}

		if(!(strcmp("TCP",strtype)==0))
			return;
		TCPHEADER *tcp_header = (TCPHEADER*)(pkt_data+14+iph_len);
		int tcph_len = tcp_header->header_len;
		tcph_len <<= 2;

		u_char *p = pkt_data;
		int i;
		printf("\r\nheader YiTaiWang:\r\n");
		for( i= 0; i < 14; i++)
		{
			printf("%02X ", *p++);			
			if( (i + 1) % 25== 0)
				printf("\r\n");
		}
		printf("\r\nheader IP:(%d bytes)\r\n", iph_len);
		for( i= 14; i < 14+iph_len; i++)
		{
			printf("%02X ", *p++);			
			if( (i + 1 -14) % 25== 0)
				printf("\r\n");
		}
		printf("\r\nheader TCP:(%d bytes)\r\n", tcph_len);
		for( i= 14+iph_len; i < 14+iph_len+tcph_len; i++)
		{
			printf("%02X ", *p++);			
			if( (i + 1 - 14 -iph_len) % 25== 0)
				printf("\r\n");
		}
		printf("\r\nData:\r\n");
		for( i= 14+iph_len+tcph_len; i < (int)header->len; i++)
		{
			printf("%02X ", *p++);			
			if( (i + 1 - 14 -iph_len - tcph_len) % 25== 0)
				printf("\r\n");
		}
		printf("\n================END Analysis Packet ====================\n");
	}
}

2. 编译

gcc -o ltest libpcaptest.c -lpcap


3. 运行结果

客户端给服务器发送了2个整数,服务器端返回了其和。

root@ubuntu:~/下载/Linux_C/chp16/libpcap# ./lpacket
NET Address: 127.0.0.0, Network Mask: 255.0.0.0
Input Packet Filter:>tcp
datalink = 1
================Begin Analysis [0] Packet ====================
packet length:74 
Source MAC:00-00-00-00-00-00 ==>Dest MAC:00-00-00-00-00-00 
Source IP:211.69.205.233==>Dest IP:211.69.205.233
Protocol:TCP
Source Port:60842==>Dest Port:9877

header YiTaiWang:
00 00 00 00 00 00 00 00 00 00 00 00 08 00 
header IP:(20 bytes)
45 00 00 3C 79 4C 40 00 40 06 7F 11 D3 45 CD E9 D3 45 CD E9 
header TCP:(32 bytes)
ED AA 26 95 C8 5C 06 FB 5D 79 AE 29 80 18 02 01 42 8D 00 00 01 01 08 0A 00 
2E EC 83 00 2C 66 F2 
Data:
01 00 00 00 02 00 00 00 
================END Analysis Packet ====================
================Begin Analysis [1] Packet ====================
packet length:70 
Source MAC:00-00-00-00-00-00 ==>Dest MAC:00-00-00-00-00-00 
Source IP:211.69.205.233==>Dest IP:211.69.205.233
Protocol:TCP
Source Port:9877==>Dest Port:60842

header YiTaiWang:
00 00 00 00 00 00 00 00 00 00 00 00 08 00 
header IP:(20 bytes)
45 00 00 38 D1 90 40 00 40 06 26 D1 D3 45 CD E9 D3 45 CD E9 
header TCP:(32 bytes)
26 95 ED AA 5D 79 AE 29 C8 5C 07 03 80 18 02 00 42 89 00 00 01 01 08 0A 00 
2E EC 83 00 2E EC 83 
Data:
03 00 00 00 
================END Analysis Packet ====================


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值