原始套接字发送自定义协议的链路帧

server.c
===============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <netinet/ether.h>
#include <string.h>
#include <pthread.h>
void print_hex(unsigned char *buffer, int len){
	int i;
	printf("******************start code**********************************\n");
	for(i = 1; i <= len; i++){
		printf("0x%02X ",buffer[i-1]);					
		if(i % 16 == 0){
			printf("\n");
		}
	}
	printf("\n");
	printf("********************end code************************************\n");
}
int main()
{
	unsigned char buf[2048];
	int sock_raw_fd ;  
	sock_raw_fd = socket(PF_PACKET,SOCK_RAW,htons(0x3001));//ETH_P_ALL));
	printf("sock_raw_fd = %d\n",sock_raw_fd);

	int nread;
	while(1)
	{
		nread = recvfrom(sock_raw_fd,buf,2048,0,NULL,NULL);
		printf("nread = %d\n",nread);
		print_hex(buf,nread);
		
	}
	return 0;
}
//当socket函数的最后一个参数协议字段,填写ETH_P_ALL时,将收到所有类型的二层链路帧。
//比如这种情形,server运行在PC机上(ETH_P_ALL);client运行在同一台PC机上(0x3001),通过ens33网口向外发送自定义的二层链路帧,此时server能够接收到client的二层链路帧。
//server运行在PC机上(0x3001);client运行在同一台PC机上(0x3001),通过ens33网口向外发送自定义的二层链路帧,此时server不能接收到client的二层链路帧。
client.c
==============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <net/if_arp.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <netinet/ether.h>
#include <string.h>
#include <pthread.h>
void print_hex(unsigned char *buffer, int len){
	int i;
	printf("******************start code**********************************\n");
	for(i = 1; i <= len; i++){
		printf("0x%02X ",buffer[i-1]);					
		if(i % 16 == 0){
			printf("\n");
		}
	}
	printf("\n");
	printf("********************end code************************************\n");
}
int main()
{
//00:0c:29:de:a6:c5 目的MAC地址
//52:54:00:9b:38:7a 源MAC地址,这个可以随便填写,只关心目的MAC地址
	unsigned char buf[128]={0x0,0x0c,0x29,0xde,0xa6,0xc5,0x52,0x54,0,0x9b,0x38,0x7a,0x30,0x1};
	int sock_raw_fd ;
	sock_raw_fd = socket(PF_PACKET,SOCK_RAW,htons(0x3001));
	int nwrite;
	short type = htons(0x3001);
	memcpy(buf+12,&type,2);
	//memset(buf,0x01,128);
	struct sockaddr_ll sll;                 //原始套接字地址结构    
	struct ifreq ethreq;                    //网络接口地址    

	strncpy(ethreq.ifr_name, "ens33", IFNAMSIZ);         //指定网卡名称    
	if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &ethreq))    //获取网络接口    
	{    
	    perror("ioctl");    
	    close(sock_raw_fd);    
	    exit(-1);    
	}    
	 
	/*将网络接口赋值给原始套接字地址结构*/    
	bzero(&sll, sizeof(sll));    
	sll.sll_ifindex = ethreq.ifr_ifindex;    
	 
	// 发送数据        
	int len = sendto(sock_raw_fd, buf, 14, 0 , (struct sockaddr *)&sll, sizeof(sll));    
	if(len == -1)    
	{    
	    perror("sendto");    
	}   
	print_hex(buf,14);
	printf("len = %d\n",len);
}

server和client运行在不同的机器下:

1、client的目的MAC地址填写正确(server和client都是0x3001),在server是否为混杂模式下都可以收到数据。

2、client的目的MAC地址填写错误(server和client都是0x3001),server必须在混杂模式下才能收到数据。

3、server(ETH_P_ALL);client(0x3001),通过ens33网口向外发送自定义的二层链路帧,在目的MAC地址正确的情况下,此时server(无论是否为混杂模式)能接收到client的二层链路帧。

4、server(ETH_P_ALL);client(0x3001),通过ens33网口向外发送自定义的二层链路帧,在目的MAC地址错误的情况下,此时server(混杂模式)能接收到client的二层链路帧;此时server(非混杂模式)不能接收到client的二层链路帧。

设置混杂模式: ifconfig ens33 promisc

清除混杂模式:ifconfig ens33 -promisc

注:

  client发送大于等于14字节且小于60字节,server收到的都是60字节。大于60字节时,server收到的是client发送的实际字节数。  

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
套接字可以按不同的标准进行分类,以下是按照传输层协议和使用方式进行分类的套接字类型: 1. 流套接字(Stream Socket) 流套接字是一种基于TCP协议的套接字,它提供可靠的、面向连接的数据传输服务,数据传输的顺序不会发生变化,不会丢失数据,也不会出现重复数据。流套接字常用于需要可靠传输和按顺序接收数据的应用,如HTTP、FTP、SMTP等。 2. 数据报套接字(Datagram Socket) 数据报套接字是一种基于UDP协议的套接字,它提供不可靠的、无连接的数据传输服务,数据传输的顺序可能会发生变化,也可能会丢失数据或出现重复数据。数据报套接字常用于需要快速传输和不需要可靠传输的应用,如DNS、NTP等。 3. 原始套接字(Raw Socket) 原始套接字是一种可以直接访问网络层和链路层的套接字,它可以自定义协议头,实现对网络层和链路层的直接控制。原始套接字常用于网络监控、网络攻击与防御等应用。 4. Seqpacket套接字(Sequenced Packet Socket) Seqpacket套接字是一种顺序数据报套接字,它提供可靠的、面向连接的数据传输服务,并保证数据按顺序接收,不会出现重复数据。Seqpacket套接字常用于需要通过网络传输大量数据的应用,如多媒体、游戏等。 5. 网络锁套接字(Netlink Socket) 网络锁套接字是一种用于Linux内核和用户空间程序之间进行通信的套接字,它提供了一种高效的、可靠的、面向连接的通信机制,可以用于内核与用户空间程序之间的交互,如网络配置、路由表操作、网络状态监控等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值