使用raw socket编程抓取goose报文

编写源文件goose.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<net/if.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <time.h>

#define BUFFSIZE 8024

struct goose_pkt{
	uint8_t dest[6];
	uint8_t src[6];
	uint16_t type;
	//uint32_t vlan;
	uint16_t app_id;
	uint16_t length;
	uint8_t reserve[6 * 16 + 2];
	uint16_t sq_num;
}__attribute__((packed));


struct session {
	time_t time;
	uint16_t seq_num;
	uint32_t cnt;
	uint32_t time_diff;
};

#define MAX_APP_ID 0x1200
struct session map[MAX_APP_ID];

/*
 * return:
 * 0 success
 * 1 timeout
 * -1 fail
 */
int get_goose_massage(int sockfd, uint8_t *buff, uint32_t *length)
{
	struct timeval timeout;
	int ret = 0;
	fd_set rfds;

	FD_ZERO(&rfds);//清空描述符集合 
	FD_SET(0, &rfds);//将标准输入(stdin)添加到集合中
	FD_SET(sockfd, &rfds);//将我们的套接字描述符添加到集合中
	/*设置超时时间*/
	timeout.tv_sec = 10;   
	timeout.tv_usec = 0;

	/*监听套接字是否为可读*/
	ret = select(sockfd+1, &rfds, NULL, NULL, &timeout);
	//printf("ret:%d\n", ret);
	if(ret == -1) {//select 连接失败
		perror("select failure ");
		return -1;
	}   
	else if(ret == 0) {//超时(timeout)
		return 1;
	}   

	if(FD_ISSET(sockfd, &rfds)) {//如果可读
		*length = recvfrom(sockfd,buff,BUFFSIZE,0,NULL,NULL);
		if(*length<0){
			printf("receive error!\n");
			return -1;
		}
	} else {
		printf("select failed!\n");
		return -1;
	}

	return 0; 
}

int main(){

	int rawsock;
	uint8_t buff[BUFFSIZE];
	int n;
	int count = 0;


	memset(&map, 0, sizeof(map));
	rawsock = socket(PF_PACKET,SOCK_RAW,htons(0x88b8));
	//rawsock = socket(PF_PACKET,SOCK_RAW,htons(0x8100));
	//rawsock = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
	if(rawsock < 0){
		printf("raw socket error!\n");
		exit(1);
	}

#if 0
	struct ifreq ifr;
	strncpy( ifr.ifr_name, "eth3", IFNAMSIZ );
	if( ioctl( rawsock, SIOCGIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCGIFFLAGS" );
		exit(EXIT_FAILURE);
	}
	ifr.ifr_flags |= ( IFF_PROMISC | IFF_UP );
	if( ioctl( rawsock, SIOCSIFFLAGS, &ifr ) == -1 )
	{
		perror( "SIOCSIFFLAGS" );
		exit(EXIT_FAILURE);
	}
#endif

	printf("sizeof: %d\n", sizeof(struct goose_pkt));
	while(1){	
		int ret = get_goose_massage(rawsock, buff, &n);
		if (ret == 1) {
			printf("timeout\n");
			continue;
		} else if (ret == -1) {
			printf("receive message failed!\n");
			continue;
		}


		struct goose_pkt *pkt = (struct goose_pkt *)buff;
		if (ntohs(pkt->type) != 0x88b8) {
			continue;
		}

		//count++;
		//printf("%5d	recv:%d",count, n);
		//printf("\n");
#if 0
		int i;
		for (i = 0; i < n; i++) {
			printf("%02x ", buff[i]);
			if ((i % 8) == 7) 
				printf("  ");
			if ((i % 16) == 15)
				printf("\n");
		}
		printf("\n");
#endif


		uint16_t app_id = ntohs(pkt->app_id);
		//uint16_t seq_num = *(uint16_t *)(buff + 116);
		uint16_t seq_num = ntohs(pkt->sq_num);
		if (app_id >= MAX_APP_ID) {
			printf("error app_id: %04x\n", app_id);
			continue;
		}

		time_t now = time(NULL);
		struct session *p_node = &map[app_id];
		if (p_node->time != 0) {
			if ((now - p_node->time) >= 10) {
				printf("node, app_id: %04x timeout!\n", app_id);
			}
			if (seq_num != (p_node->seq_num + 1)) {
				//printf("node, app_id: %04x drop packet!\n", app_id);
			}
		}
		p_node->time_diff = now - p_node->time;
		p_node->time = now;
		p_node->seq_num = seq_num;
		p_node->cnt++;

		printf("app_id:%04x, time:%ld, time_diff:%u, sqNum:%5d, cnt:%u\n", app_id, now, p_node->time_diff, seq_num, p_node->cnt);
	}
}	

编写Makefile

all: goose
    echo complete
goose: goose.c
    ${CC} -o goose goose.c

clean:
    rm goose

测试

make
./goose
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值