From a8937b0c7ed3e96805be1a05cdc24bd1622045ef Mon Sep 17 00:00:00 2001 From: flykhan Date: Thu, 21 Sep 2023 11:26:50 +0800 Subject: [PATCH] =?UTF-8?q?router=E6=A8=A1=E5=9D=97:=20libnet=20=E6=8D=A2?= =?UTF-8?q?=E7=BD=91=E5=8D=A1=E8=BD=AC=E5=8F=91=E9=81=87=E5=88=B0=20bug;?= =?UTF-8?q?=20=E5=85=88=E5=A4=84=E7=90=86=20ARP=20=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/net_task_thread.c | 120 +++++++++++++++++++++++++++++++++++++-- router/net_task_thread.h | 2 +- 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/router/net_task_thread.c b/router/net_task_thread.c index 47b9d27..5a36577 100644 --- a/router/net_task_thread.c +++ b/router/net_task_thread.c @@ -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; + } \ No newline at end of file diff --git a/router/net_task_thread.h b/router/net_task_thread.h index e0b169a..c50c2c4 100644 --- a/router/net_task_thread.h +++ b/router/net_task_thread.h @@ -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);