linux c arp协议分析三 - 捕捉并分析tcp包

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <arpa/inet.h>

//以太网的最大传输单元为1500
#define MTU 1500

struct ethernet_header
{
	unsigned char mac_target[ETH_ALEN];
	unsigned char mac_source[ETH_ALEN];
	unsigned short ether_type;
};

struct ip_header
{
	//ip头部长度,及ip协议版本
	//说明首部有多少32位字长,如果是5则表示有5个32位字长,也就是20个字节
	unsigned char header_len:4,
	version:4;
	//服务类型
	unsigned char st_routine:3,
	st_nd:1,
	st_nt:1,
	st_nr:1,
	st_ectbit:1,
	st_ce:1;
	unsigned short total_len;
	unsigned short iden;
	unsigned short flags;
	unsigned char time_to_live;
	unsigned char protocal;
	unsigned short hc;
	unsigned char source_ip[4];
	unsigned char target_ip[4];
};

struct tcp_header
{
	unsigned short int source_port;
	unsigned short int target_port;
	unsigned int seqnum;
	unsigned int acknum;
	unsigned char reserve:4,
	//tcp头部的偏移,以4字节为单位,为8时表示偏移量是8*4=32个字节
	dataoffset:4;
	unsigned char flags;
	unsigned short int win;
	unsigned short int checksum;
	unsigned short int up;
};

void die(const char*pre);
void print_ethdr(struct ethernet_header **ppethdr);
void print_iphdr(struct ip_header **ppiphdr);
void print_tcphdr(struct tcp_header **pptcphdr);

int main(void)
{
	int sfd, len;
	struct sockaddr_ll sl;
	struct ethernet_header *pethdr;
	struct ip_header *piphdr = 0;
	struct tcp_header *ptcphdr = 0;
	char buf[MTU];
	
	sfd = socket(AF_PACKET, SOCK_RAW, htons(ETHERTYPE_IP));
	if(-1 == sfd)
	{
		die("socket");
	}

	memset(&sl, 0, sizeof(sl));
	sl.sll_family = AF_PACKET;
	//sl.sll_protocol = htons(ETH_P_ALL);
	//sl.sll_ifindex = IFF_BROADCAST;

	if(-1 == bind(sfd, (sockaddr*)&sl, sizeof(sl)))
	{
		die("bind");
	}

	
	while(1)
	{
		len = recv(sfd, buf, MTU, 0);
		if(!len)
		{
			perror("recv");
			continue;
		}
		
		//获得ethernet_header的指针
		ethernet_header *pethdr = (ethernet_header *)&buf;
		print_ethdr(&pethdr);

		//获得ip_header的指针
		piphdr = (ip_header*) ( (char*)pethdr + sizeof(ethernet_header) );
		print_iphdr(&piphdr);

		//检测是否为IP协议
		if(0x6 != piphdr->protocal)
			continue;

		//获得tcp_header的指针
		int optlen = piphdr->header_len > 5 ? 4 : 0;
		ptcphdr = (tcp_header*) ( (char*)piphdr + sizeof(ip_header) + optlen);
		print_tcphdr(&ptcphdr);

		//获取数据区指针
		//数据区长度
		int datalen = ntohs(piphdr->total_len) - piphdr->header_len * 4 - ptcphdr->dataoffset * 4;
		char *pbuf = new char[datalen];
		//数据区首字节指针
		char *pdata = (char*) ( (char*)ptcphdr + ptcphdr->dataoffset * 4);
		memcpy(pbuf, pdata, datalen);

		printf("---------------------------data begin----------------------------\n");
		printf("data = %s\n", pbuf);
		printf("---------------------------data end------------------------------\n");
	}
	
	return 0;
}

void die(const char*pre)
{
	perror(pre);
	exit(1);
}

void print_ethdr(struct ethernet_header **ppethdr)
{
	int i;

	struct ethernet_header *pethdr = *ppethdr;

	printf("---------------------------ethernet header begin------------------------------\n");
	
	for(i = 0; i < ETH_ALEN; i++)
	{
		printf(i == 0 ? "mac_target =  %.2x" : ":%.2x", pethdr->mac_target[i]);
	}

	for(i = 0; i < ETH_ALEN; i++)
	{
		printf(i == 0 ? "\nmac_source = %.2x" : ":%.2x", pethdr->mac_source[i]);
	}

	printf("\nether_type = %x\n", ntohs(pethdr->ether_type));
}

void print_iphdr(struct ip_header **ppiphdr)
{
	struct ip_header *piphdr = *ppiphdr;

	printf("---------------------------ip header begin------------------------------\n");
	printf("version    = %d\n", piphdr->version);
	printf("header_len = %d\n", piphdr->header_len);
	printf("source_ip  = %s\n", inet_ntoa(*(struct in_addr*)(piphdr->source_ip)));
	printf("target_ip  = %s\n", inet_ntoa(*(struct in_addr*)(piphdr->target_ip)));
	printf("total_len  = %d\n", ntohs(piphdr->total_len));
	printf("protocal   = %d\n", piphdr->protocal);
}

void print_tcphdr(struct tcp_header **pptcphdr)
{
	tcp_header *ptcphdr = *pptcphdr;
	printf("---------------------------tcp header begin------------------------------\n");
	printf("source_port     = %d\n", ntohs(ptcphdr->source_port));
	printf("target_port     = %d\n", ntohs(ptcphdr->target_port));
	printf("seqnum          = %d\n", ntohs(ptcphdr->seqnum));
	printf("acknum          = %d\n", ntohs(ptcphdr->acknum));
	printf("dataoffset      = %d\n", ptcphdr->dataoffset);
}

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值