router模块: libnet 换网卡转发遇到 bug; 先处理 ARP 相关

This commit is contained in:
flykhan 2023-09-21 11:26:50 +08:00
parent 80d9ba5f9e
commit a8937b0c7e
2 changed files with 116 additions and 6 deletions

View File

@ -8,8 +8,9 @@ void *net_task(void *arg)
char *dev2 = "ens38"; // 第二个网卡
// 打开网卡设备
open_device(&device1, dev1);
open_device(&device2, dev2);
// libnet_context1 使用 open_device 函数打开网卡设备1 后返回的 libnet 上下文
libnet_context1 = open_device(&device1, dev1);
libnet_context2 = open_device(&device2, dev2);
// 开始捕获数据包:
// pcap_loop: 网卡设备、捕获的数据包个数、回调函数、传递给回调函数的参数
@ -20,7 +21,8 @@ void *net_task(void *arg)
}
// 打开网卡设备
void open_device(pcap_t **device, char *dev_name)
// 如果成功打开网卡设备,就返回 libnet 上下文
libnet_t *open_device(pcap_t **device, char *dev_name)
{
// 打开网卡设备: 设备名、最大字节数、混杂模式、超时时间、错误信息缓冲区
*device = pcap_open_live(dev_name, MAX_BYTE, 1, 512, errbuf);
@ -31,16 +33,124 @@ void open_device(pcap_t **device, char *dev_name)
}
// 处理数据包
libnet_context1 = libnet_init(LIBNET_LINK, dev_name, errbuf); // 初始化 libnet
if (libnet_context1 == NULL)
libnet_t *libnet = libnet_init(LIBNET_LINK, dev_name, errbuf); // 初始化 libnet
if (libnet == NULL)
{
perror("libnet_init");
exit(-1);
}
return libnet; // 返回 libnet 上下文
}
// 处理数据包
// 参数: 传递给回调函数的参数、数据包头部、数据包
void process_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet)
{
// 将数据包从一个网卡发送到另一个网卡
// 实际路由中,需要根据路由表进行路由选择
printf("process_packet\n");
/*
libnet_ptag_t t; // libnet 标签: 用于标识数据包中的某一部分
libnet_t *libnet; // libnet 上下文: 用于发送数据包
// 根据网卡设备选择 libnet 上下文,以便发送数据包
// 规则是: 如果是从网卡1接收到的数据包就从网卡2发送出去
if (arg == (u_char *)device1)
{
libnet = libnet_context2;
}
else if (arg == (u_char *)device2)
{
libnet = libnet_context1;
}
t = libnet_build_ethernet(
((struct libnet_ethernet_hdr *)packet)->ether_dhost, // 目的MAC地址
((struct libnet_ethernet_hdr *)packet)->ether_shost, // 源MAC地址
((struct libnet_ethernet_hdr *)packet)->ether_type, // 以太网类型
packet + LIBNET_ETH_H, // 负载数据(携带的数据)
pkthdr->len - LIBNET_ETH_H, // 以太网数据包的数据部分
libnet, // libnet 上下文
0 // 标记
);
if (t == -1)
{
perror("libnet_build_ethernet");
exit(-1);
}
// 发送数据包
int res = libnet_write(libnet);
if (res == -1)
{
perror("libnet_write");
exit(-1);
} */
struct libnet_ethernet_hdr *eth_hdr = (struct libnet_ethernet_hdr *)packet;
// 如果是IP数据包就打印源IP地址和目的IP地址
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP)
{
struct libnet_ipv4_hdr *ip_hdr = (struct libnet_ipv4_hdr *)(packet + LIBNET_ETH_H);
if (ip_hdr->ip_p == IPPROTO_TCP)
{
struct libnet_tcp_hdr *tcp_hdr = (struct libnet_tcp_hdr *)(packet + LIBNET_ETH_H + LIBNET_IPV4_H);
printf("TCP: %s:%d -> %s:%d\n", inet_ntoa(ip_hdr->ip_src), ntohs(tcp_hdr->th_sport), inet_ntoa(ip_hdr->ip_dst), ntohs(tcp_hdr->th_dport));
}
else if (ip_hdr->ip_p == IPPROTO_UDP)
{
struct libnet_udp_hdr *udp_hdr = (struct libnet_udp_hdr *)(packet + LIBNET_ETH_H + LIBNET_IPV4_H);
printf("UDP: %s:%d -> %s:%d\n", inet_ntoa(ip_hdr->ip_src), ntohs(udp_hdr->uh_sport), inet_ntoa(ip_hdr->ip_dst), ntohs(udp_hdr->uh_dport));
}
libnet_t *libnet;
if (arg == (u_char *)device1)
{
libnet = libnet_context2;
}
else if (arg == (u_char *)device2)
{
libnet = libnet_context1;
}
libnet_ptag_t t = libnet_build_ethernet(
eth_hdr->ether_dhost,
eth_hdr->ether_shost,
ETHERTYPE_IP,
packet + LIBNET_ETH_H,
pkthdr->len - LIBNET_ETH_H,
libnet,
0);
if (t == -1)
{
perror("libnet_build_ethernet");
exit(-1);
}
int res = libnet_write(libnet);
if (res == -1)
{
perror("libnet_write");
exit(-1);
}
}
// 如果是ARP数据包就打印源IP地址和目的IP地址
if (ntohs(eth_hdr->ether_type) == ETHERTYPE_ARP)
{
struct libnet_arp_hdr *arp_hdr = (struct libnet_arp_hdr *)(packet + LIBNET_ETH_H);
// printf("ARP: %s -> %s\n", inet_ntoa(*(struct in_addr *)arp_hdr->arp_spa), inet_ntoa(*(struct in_addr *)arp_hdr->arp_tpa));
}
}
// ARP 数据报处理函数
void process_arp_packet(const u_char *packet)
{
struct ether_header *eth_hdr = (struct ether_header *)packet;
}

View File

@ -13,7 +13,7 @@ libnet_t *libnet_context1; // libnet1 上下文
libnet_t *libnet_context2; // libnet2 上下文
// libpcap 相关函数
void open_device(pcap_t **device, char *dev_name); // 打开网卡设备
libnet_t *open_device(pcap_t **device, char *dev_name); // 打开网卡设备
void process_packet(u_char *arg, const struct pcap_pkthdr *pkthdr, const u_char *packet); // 处理数据包
void *net_task(void *arg);