在Linux终端中需要构造一个测试程序,完成在L2层发送原始数据包任务。如下图示,Talker组中的app发送原始网络报文到网络总线上,Listener从网络接收该报文。
App应用程序代码如下,
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
char buf[1024] = {0};
const char *ifname = "ens33";
int32_t raw_interface_idx_get(int32_t fd, const char *ifname)
{
struct ifreq ifreq;
memset(&ifreq, 0, sizeof(ifreq));
strncpy(ifreq.ifr_name, ifname, sizeof(ifreq.ifr_name) - 1);
if (ioctl(fd, SIOCGIFINDEX, &ifreq) < 0)
{
return -1;
}
return ifreq.ifr_ifindex;
}
int main(int argc, char *argv[])
{
int size;
int ret;
int fd;
struct sockaddr_ll addr;
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (-1 == fd)
{
perror("socket");
return -1;
}
ret = raw_interface_idx_get(fd, ifname);
if (ret < 0)
{
printf("get ifname idx fail\n");
goto out;
}
memset(&addr, 0, sizeof(addr));
addr.sll_ifindex = ret;
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
if (ret < 0)
{
perror("bind");
goto out;
}
//00:0c:29:96:35:37
/*dst mac*/
buf[0] = 0xFF;
buf[1] = 0xFF;
buf[2] = 0xFF;
buf[3] = 0xFF;
buf[4] = 0xFF;
buf[5] = 0xFF;
size = 6;
/*src mac*/
buf[6] = 0x00;
buf[7] = 0x0c;
buf[8] = 0x29;
buf[9] = 0x96;
buf[10] = 0x35;
buf[11] = 0x37;
size += 6;
/*vlan tpid*/
buf[size] = 0x81;
size += 1;
buf[size] = 0x00;
size += 1;
/*vlan tag*/
buf[size] = 0x00;
buf[size] |= 1 << 6; //vlan pri = 2
size += 1;
buf[size] = 0x01; //vlan id = 1
size += 1;
/*packet protocl*/
buf[size] = 0x22;
size += 1;
buf[size] = 0xFF;
size += 1;
/*payload*/
buf[size] = 'A';
size += 1;
/*cycle send L2 packet*/
while (1)
{
ret = send(fd, buf, size, 0);
if (ret <= 0)
{
perror("send");
break;
}
sleep(1);
}
out:
close(fd);
return 0;
}