diff --git a/router/net_task_thread.c b/router/net_task_thread.c new file mode 100644 index 0000000..5db158f --- /dev/null +++ b/router/net_task_thread.c @@ -0,0 +1,158 @@ +#include "net_task_thread.h" + +void *net_task(void *arg) +{ + printf("net_task\n"); + + // 1. 获取可用的网络设备名称 + char errbuf[PCAP_ERRBUF_SIZE]; // 错误信息 + pcap_if_t *alldevs; + if (pcap_findalldevs(&alldevs, errbuf) == -1) + { + printf("pcap_findalldevs error: %s\n", errbuf); + return 1; + } + + // 2. 打印网络设备名称 + pcap_if_t *d; + for (d = alldevs; d != NULL; d = d->next) + { + printf("%s\n", d->name); + } + + // 3. 获取第一个网络设备的IP地址 + pcap_addr_t *a; + for (a = alldevs->addresses; a != NULL; a = a->next) + { + if (a->addr->sa_family == AF_INET) + { + // ntoa 将网络字节序的IP地址转换为点分十进制的字符串 + printf("%s\n", inet_ntoa(((struct sockaddr_in *)a->addr)->sin_addr)); + } + } + + // 获取网卡的网络号和网络掩码 + bpf_u_int32 netip, netmask; + if (pcap_lookupnet(alldevs->name, &netip, &netmask, NULL) != 0) + { + printf("网络号和网络掩码获取错误\n"); + return -1; + } + unsigned char ip[INET_ADDRSTRLEN] = ""; + unsigned char mask[INET_ADDRSTRLEN] = ""; + // ntop 将网络字节序的IP地址转换为点分十进制的字符串 + inet_ntop(AF_INET, &netip, ip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &netmask, mask, INET_ADDRSTRLEN); + printf("网络号: %s 网络掩码: %s\n", ip, mask); + + // 获取网卡的MAC地址 + struct ifreq ifr; + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); + strcpy(ifr.ifr_name, alldevs->name); + if (ioctl(sockfd, SIOCGIFHWADDR, &ifr) < 0) + { + printf("MAC地址获取失败\n"); + return -1; + } + unsigned char mac[6]; + memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); + printf("MAC地址: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + // 打开网络设备,开始抓包(捕获数据包) + pcap_t *pcap_handle = pcap_open_live(alldevs->name, 65535, 1, 0, errbuf); // 65535 最大捕获的字节数 1 混杂模式 0 不超时 errbuf 错误信息 + if (pcap_handle == NULL) + { + printf("pcap_open_live error: %s\n", errbuf); + return 1; + } + + // 4. 抓包 + struct pcap_pkthdr pcap_header; // 数据包头 + bzero(&pcap_header, sizeof(pcap_header)); // 清空 + const u_char *packet; // 数据包数据 + while (1) + { + packet = pcap_next(pcap_handle, &pcap_header); // 抓包 + if (packet == NULL) + { + printf("pcap_next error\n"); + return 1; + } + printf("数据包长度: %d\n", pcap_header.len); + printf("捕获的数据长度: %d\n", pcap_header.caplen); + // printf("数据包时间: %s", ctime((const time_t *)&pcap_header.ts.tv_sec)); + // printf("数据包内容: "); + // for (int i = 0; i < pcap_header.len; i++) + // { + // printf("%02x ", packet[i]); + // } + + // 5. 解析数据包 + struct ether_header *eth_header = (struct ether_header *)packet; // 以太网帧头 + unsigned char src_mac[18] = ""; + unsigned char dst_mac[18] = ""; + sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", eth_header->ether_shost[0], eth_header->ether_shost[1], eth_header->ether_shost[2], eth_header->ether_shost[3], eth_header->ether_shost[4], eth_header->ether_shost[5]); // 将MAC地址转换为点分十进制的字符串 + sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", eth_header->ether_dhost[0], eth_header->ether_dhost[1], eth_header->ether_dhost[2], eth_header->ether_dhost[3], eth_header->ether_dhost[4], eth_header->ether_dhost[5]); + unsigned short eth_type = ntohs(eth_header->ether_type); // type 字段是网络字节序,需要转换为主机字节序 + printf("以太网帧类型: %04x\n", eth_type); // 0x080 IP协议 0x0806 ARP协议 0x8035 RARP协议 0x86dd IPv6协议 + printf("目的MAC地址: %s\n", dst_mac); + printf("源MAC地址: %s\n", src_mac); + + // 如果是ARP协议 + if (eth_type == 0x0806) + { + // // 分析 arp 报文 + // struct ether_arp *arp_header = (struct ether_arp *)(packet + sizeof(struct ether_header)); // arp 报文 + // unsigned short this_arp_op = ntohs(arp_header->arp_op); // 操作码 + // printf("ARP操作码: %d\n", this_arp_op); // 1 ARP请求 2 ARP应答 3 RARP请求 4 RARP应答 + // if (this_arp_op == 1 || this_arp_op == 2) + // { + // unsigned char src_ip[INET_ADDRSTRLEN] = ""; + // unsigned char dst_ip[INET_ADDRSTRLEN] = ""; + // inet_ntop(AF_INET, arp_header->arp_spa, src_ip, INET_ADDRSTRLEN); // 将网络字节序的IP地址转换为点分十进制的字符串 + // inet_ntop(AF_INET, arp_header->arp_tpa, dst_ip, INET_ADDRSTRLEN); + // printf("源IP地址: %s\n", src_ip); + // printf("目的IP地址: %s\n", dst_ip); + // } + + // 发送 ARP 请求,用于广播获取网段内的所有已连接设备的mac地址,并存入 ip_mac 映射表 + } + + // 如果是IP协议 + if (eth_type == 0x800) + { + // 分析 ip 报文 + struct iphdr *ip_header = (struct iphdr *)(packet + sizeof(struct ether_header)); // ip 报文 (sizeof(struct ether_header) = 14 (MAC)以太网帧头长度) + unsigned char src_ip[INET_ADDRSTRLEN] = ""; + unsigned char dst_ip[INET_ADDRSTRLEN] = ""; + unsigned char ip_protocol[INET_ADDRSTRLEN] = ""; // 协议类型 + inet_ntop(AF_INET, &ip_header->saddr, src_ip, INET_ADDRSTRLEN); // 将网络字节序的IP地址转换为点分十进制的字符串 + inet_ntop(AF_INET, &ip_header->daddr, dst_ip, INET_ADDRSTRLEN); + printf("IP协议类型: %d\n", ip_header->protocol); // ICMP(1),IGMP(2),TCP(6),UDP(17),IPv6(41) + printf("源IP地址: %s\n", src_ip); + printf("目的IP地址: %s\n", dst_ip); + + // 如果是黑名单IP,则跳过本次循环,即屏蔽本ip的数据 + if (is_blocked_ip(src_ip) == 0 || is_blocked_ip(dst_ip) == 0) + { + printf("数据报已被过滤\n"); + continue; + } + // is_blocked_ip(src_ip); + printf("数据报正常\n"); + + // 不在黑名单时,进行数据报中ip和mac地址的转换和转发 + + // 先检查ip对应的mac地址是否存在(mysql->ip_mac表查询),存在时进行下一步;不存在时,调用三次循环,来进行ARP广播,获取最新的设备ip--mac + } + + printf("\n"); + sleep(1); + } + + // 3. 释放资源 + pcap_close(pcap_handle); // 关闭网络设备 + pcap_freealldevs(alldevs); // 释放资源 + + return NULL; +} \ No newline at end of file diff --git a/router/net_task_thread.h b/router/net_task_thread.h new file mode 100644 index 0000000..f6cf01d --- /dev/null +++ b/router/net_task_thread.h @@ -0,0 +1,8 @@ +#ifndef __NET_TASK_THREAD_H__ +#define __NET_TASK_THREAD_H__ + +#include "router.h" + +void *net_task(void *arg); + +#endif \ No newline at end of file diff --git a/router/router.c b/router/router.c index 242b6ea..3d499cc 100644 --- a/router/router.c +++ b/router/router.c @@ -102,7 +102,7 @@ void net_init() parmas[0].is_null = 0; parmas[0].length = &parmas[0].buffer_length; const char *delete_ip_fw_sql = "delete from ip_fw where ip = ?"; - int result = delete(delete_ip_fw_sql, parmas); + int result = delete (delete_ip_fw_sql, parmas); if (result > 0) { printf("黑名单删除成功\n"); @@ -154,7 +154,7 @@ void printResult(MYSQL_ROW row, char (*columns)[30], int cols) for (int i = 0; i < cols; i++) { - printf("%s", row[i]); + printf("%s: %s \t", columns[i], row[i]); } printf("\n"); }