解析IP

/************************************************************
 * IP实验													*
 * 2016年3月26日											*
 * 130342132												*
 ************************************************************/

#include "pcap.h"

typedef unsigned char u8_t;  // 无符号8bit长度类型
typedef unsigned short u16_t; // 无符号16 bit长度类型
typedef unsigned long u32_t; // 无符号32 bit长度类型

// 以太网头部
struct ether_header
{
	u8_t ether_dhost[6]; // 目的以太网地址6B
	u8_t ether_shost[6]; // 源以太网地址6B
	u16_t ether_type; // 以太网类型字段2B
};
// IP格式
struct ip_header
{
	u8_t	ver_HeadLen;		// Version (4 bits) + Internet header length (4 bits)
	u8_t	serType;			// Type of service 
	u16_t	lenSum;				// Total length 
	u16_t	identification;		// Identification 标识
	u16_t	flags_Offset;		// Flags (3 bits) + Fragment offset (13 bits) 标志+分片偏移
	u8_t	_TTL;				// Time to live
	u8_t	proto;				// Protocol
	u16_t	checksum;			// Header checksum
	u8_t	s_ipAddr[4];		// 源IP	4B
	u8_t	d_ipAddr[4];		// 目的IP	4B
};
struct ip_packet {
	struct ether_header eth;		// Ethernet头部
	struct ip_header ip;				// ip报文首部
};

void packet_handler(u_char *user_data, const struct pcap_pkthdr *header, const u_char *pkt_content);

int main()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum;
	int i=0;
	pcap_t *adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];
	
	//	u8_t *send_buff;   // 待发送的数据帧
	//	int packet_len;
	
	// 创建以太网帧的首部结构
	//	struct ip_packet ip_pkt;	// 包
	
    // 获取本机设备列表
    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 WinPcap 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");
        // 释放设备列表
        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,            // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
		1,    // 混杂模式
		1000,             // 读取超时时间
		//    NULL,             // 远程机器验证
		errbuf            // 错误缓冲池
		) ) == NULL)
    {
        fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
        // 释放设备列表
        pcap_freealldevs(alldevs);
        return -1;
    }
	
	
	// 释放设备列表
    pcap_freealldevs(alldevs);
    pcap_loop(adhandle, 0, packet_handler, NULL);
    pcap_close(adhandle);
    return 0;
}

void packet_handler(u_char *user_data, const struct pcap_pkthdr *header, const u_char *pkt_content)
{
	u_short ethernet_type;			// 以太网类型
	struct ip_packet *sip_pkt;
	// struct ether_header *ethernet_protocol;	// 以太网首部协议
	u_char *mac_addr;
	u8_t version;
	u8_t headLen;
	u16_t f_o;
	u8_t DF, MF;
	u16_t offset;
	u8_t proto;

	u_char *ip_addr;
	static int packet_number = 1;	// 统计捕获报文个数

	sip_pkt = (struct ip_packet*)pkt_content;	// 获得帧首部信息
	ethernet_type = ntohs(sip_pkt->eth.ether_type);	// ethernet_protocol->ether_type);

	if (ethernet_type == 0x0800)
	{
		printf("*********************************************\n");
		printf("第%d个数据包\n%s\n", packet_number, ctime((const time_t*)&header->ts.tv_sec));	// 捕获时间
	
		// MAC首部
		printf("\tMAC首部\n");
		// printf("源MAC\t\t");
		mac_addr = sip_pkt->eth.ether_shost;
		printf("源MAC\t\t%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_addr, *(mac_addr + 1),
			*(mac_addr + 2), *(mac_addr + 3), *(mac_addr + 4), *(mac_addr + 5));
		// printf("目的MAC\t");
		mac_addr = sip_pkt->eth.ether_dhost;
		printf("目的MAC\t\t%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_addr, *(mac_addr + 1),
			*(mac_addr + 2), *(mac_addr + 3), *(mac_addr + 4), *(mac_addr + 5));
		printf("协议类型\tIP协议\n");

		// IP首部
		printf("\n\tIP首部\n");
		version = sip_pkt->ip.ver_HeadLen >> 4;
		printf("版本\t\t%d\n", version);
		// 头部长度
		headLen = (sip_pkt->ip.ver_HeadLen & 0x0f) *4;
		printf("头部长度\t%d\n", headLen);
		// 总长度
		printf("总长度\t\t%d\n", ntohs(sip_pkt->ip.lenSum));
		// 标识符
		printf("标识\t\t%d\n", ntohs(sip_pkt->ip.identification));
		f_o = ntohs(sip_pkt->ip.flags_Offset);
		// 标志位
		DF = (f_o >> 14) & 0x03;
		MF = (f_o >> 13) & 0x01;
		printf("标志位\t\tDF = %d, MF = %d\n", DF, MF);
		// IP片偏移
		offset = f_o & 0x1fff;
		printf("片偏移\t\t%d\n", offset);
		// TTL
		printf("TTL\t\t%d\n", sip_pkt->ip._TTL);
		// IP协议类型
		proto = sip_pkt->ip.proto;
		printf("协议类型\t%d,", proto);
		switch (proto)
		{
		case 1:
			printf("ICMP\n");
			break;
		case 2:
			printf("IGMP\n");
			break;
		case 4:
			printf("IP\n");
			break;
		case 6:
			printf("TCP\n");
			break;
		case 8:
			printf("EGP\n");
			break;
		case 9:
			printf("IGP\n");
			break;
		case 17:
			printf("UDP\n");
			break;
		case 41:
			printf("IPv6\n");
			break;
		case 50:
			printf("ESP\n");
			break;
		case 89:
			printf("OSPF\n");
			break;
		default:
			printf("其他类型\n");
			break;
		}
		// 首部校验和
		printf("首部校验和\t0x%0x\n", ntohs(sip_pkt->ip.checksum));
		// printf("源IP\t\t");
		ip_addr = sip_pkt->ip.s_ipAddr;
		printf("源IP\t\t%i.%i.%i.%i\n", *ip_addr, *(ip_addr + 1), *(ip_addr + 2), *(ip_addr + 3));
		// printf("目的IP\t\t");
		ip_addr = sip_pkt->ip.d_ipAddr;
		printf("目的IP\t\t%i.%i.%i.%i\n", *ip_addr, *(ip_addr + 1), *(ip_addr + 2), *(ip_addr + 3));

		packet_number++;
		system("pause");
	}
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注