day7 原始套接字

这两段代码展示了如何在Linux环境下使用原始套接字分别在链路层和网络层捕获并解析IP数据报,特别是针对TCP协议的数据。程序会打印出源IP、目的IP、TCP源端口和目的端口,以及数据段的内容。
摘要由CSDN通过智能技术生成

链路层原始套接字

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/ethernet.h>

#define MTU 1500

int main()
{
	/* 定义变量 */
	int sockfd, len;
	uint8_t buf[MTU]={};
	uint16_t ether_type;

	struct iphdr *iph;  //IP包头
	struct tcphdr *tcph;//TCP包头
	struct ether_header *eth;

	/* 创建一个链路层原始套接字 */
	if( (sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) ) < 0){
		perror("socket");
		return 0;
	}
	printf("sockfd = %d\n", sockfd);

	/* 接收(只接收TCP数据协议)并处理IP数据报 */
	while(1)
	{
		/* 接收包含TCP协议的IP数据报 */
		len = recvfrom(sockfd, buf, sizeof(buf),0,NULL,NULL);

		eth = (struct ether_header *)buf;
		ether_type = htons(eth->ether_type);
		switch(ether_type){
		case ETHERTYPE_IP:
			printf("IP协议\n");
			break;
		case ETHERTYPE_ARP:
			printf("ARP协议\n");
			break;
		case ETHERTYPE_LOOPBACK:
			printf("loop back\n");
			break;
		default:
			printf("其他协议 %x\n",eth->ether_type);
		}
		if(ether_type != ETHERTYPE_IP)
			continue;

		/* 打印源IP和目的IP */
		iph = (struct iphdr *)(buf+14);
		if(iph->protocol != IPPROTO_TCP)
			continue;
		printf("源IP:%s\n",inet_ntoa(*(struct in_addr *)&iph->saddr) );
		printf("目的IP%s\n",inet_ntoa(*(struct in_addr *)&iph->daddr) );

		/* 打印TCP包头的源端口号和目的端口号 */
		tcph = (struct tcphdr *)(buf+14+iph->ihl*4);
		printf("%hu--->", ntohs(tcph->source));
		printf("%hu\n", ntohs(tcph->dest));

		/* 打印TCP数据段的长度 */
		printf("TCP首部长度:%d\n", tcph->doff*4);
	}
	//关闭套接字
	close(sockfd);
	return 0;
}

网络层原始套接字

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/ioctl.h>

#define MTU 1500

int main()
{
	/* 定义变量 */
	int sockfd = -1, len, datalen, i;
	uint8_t buf[MTU]={}, *data;

	struct iphdr *iph;  //IP包头
	struct tcphdr *tcph;//TCP包头
	struct winsize size;

	/* 创建一个原始套接字 */
	if( (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP) ) < 0)
	{
		perror("socket");
		return 0;
	}
	printf("sockfd = %d\n", sockfd);

	/* 接收(只接收TCP数据协议)并处理IP数据报 */
	while(1)
	{
		/* 接收包含TCP协议的IP数据报 */
		len = recvfrom(sockfd, buf, sizeof(buf),0,NULL,NULL);
		printf("IP数据报长度 = %d\n", len);

		/* 打印源IP和目的IP */
		iph = (struct iphdr *)buf;
		printf("源IP:%s",inet_ntoa(*(struct in_addr *)&iph->saddr) );
		printf("目的IP%s\n",inet_ntoa(*(struct in_addr *)&iph->daddr) );

		/* 打印TCP包头的源端口号和目的端口号 */
		tcph = (struct tcphdr *)(buf+iph->ihl*4);
		printf("%hu--->", ntohs(tcph->source));
		printf("%hu\n", ntohs(tcph->dest));

		/* 打印TCP数据段的长度 */
		printf("TCP首部长度:%d\n", tcph->doff*4);
		if(iph->ihl*4+tcph->doff*4 < len) {
			data = buf + iph->ihl*4 + tcph->doff*4;
			datalen = len - iph->ihl*4 + tcph->doff*4;
			ioctl(STDIN_FILENO,TIOCGWINSZ,&size); //terminal 结构体
			for(i = 0; i < size.ws_col; i++) //显示一行 = 
				putchar('=');
			putchar('\n');
			printf("TCP数据字符:\n");
			for(i = 0; i < size.ws_col; i++)
				putchar('=');
			putchar('\n');
			for(i = 0; i < datalen-1; i++) {
				printf("%c", data[i]);
			}
			for(i = 0; i < size.ws_col; i++)
				putchar('=');
			putchar('\n');
			printf("TCP数据16进制:\n");
			for(i = 0; i < size.ws_col; i++)
				putchar('=');
			putchar('\n');
			for(i = 0; i < datalen-1; i++){
				printf("%x ", data[i]);
			}
			putchar('\n');
			for(i = 0; i < size.ws_col; i++)
				putchar('=');
			putchar('\n');
		}
	}
	//关闭套接字
	close(sockfd);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值