diff --git a/day7/pcap1.c b/day7/pcap1.c new file mode 100644 index 0000000..a816634 --- /dev/null +++ b/day7/pcap1.c @@ -0,0 +1,42 @@ +// libpcap 开发 +/* + libpcap是一个用于捕获网络数据包的库,它提供了一组函数和工具,用于在计算机网络上进行数据包捕获、过滤和分析。 + 在使用libpcap时,你需要在编译和链接你的程序时指定-lpcap选项,以告诉编译器和链接器使用libpcap库。这个选项通常用于Unix-like系统的编译环境,例如在使用GCC编译器时。 +*/ +#include // libpcap头文件 +#include +#include +#include // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式 + +int main(int argc, char const *argv[]) +{ + // 1. 获取可用的网络设备名称 + char err_buf[PCAP_ERRBUF_SIZE]; // 错误信息缓冲区 + char *dev = pcap_lookupdev(err_buf); // 获取网络设备名称: err_buf用于存储错误信息 + // char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备 + if (dev != NULL) + { + printf("网络设备名称: %s\n", dev); + } + else + { + printf("获取网络设备名称失败: %s\n", err_buf); + return 1; + } + + // 2. 获取网卡的网络号和子网掩码 + bpf_u_int32 netip; + bpf_u_int32 netmask; + if ((pcap_lookupnet(dev, &netip, &netmask, NULL)) == 0) + { + unsigned char ip[16] = ""; + unsigned char mask[16] = ""; + + inet_ntop(AF_INET, &netip, ip, 16); // inet_ntop()将网络地址转换成“.”点隔的字符串格式 + inet_ntop(AF_INET, &netmask, mask, 16); + + printf("网卡网络号: %s 子网掩码: %s\n", ip, mask); + } + + return 0; +} diff --git a/day7/pcap2.c b/day7/pcap2.c new file mode 100644 index 0000000..c0355ec --- /dev/null +++ b/day7/pcap2.c @@ -0,0 +1,83 @@ +// pcap_next 接收下一条数据 +#include // libpcap头文件 +#include +#include +#include +#include +#include // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式 +#include +#include + +int main(int argc, char const *argv[]) +{ + // 1. 获取可用的网络设备名称 + char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备 + if (dev != NULL) + { + printf("网络设备名称: %s\n", dev); + } + + // 2. 打开网络设备, 开始捕获数据 + char err_buf[PCAP_ERRBUF_SIZE] = ""; + pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf); + if (cap == NULL) + { + printf("open pcap fail: %s\n", err_buf); + return -1; + } + + // 3. 开始捕获数据 + while (1) + { + struct pcap_pkthdr cap_hdr; + bzero(&cap_hdr, sizeof(cap_hdr)); + const u_char *data = pcap_next(cap, &cap_hdr); + if (cap_hdr.len > 0) + { + printf("数据包长度: %d, 实际长度: %d\n", cap_hdr.caplen, cap_hdr.len); + } + + // 分析 mac 报文的数据 + struct ether_header *mac_hdr = (struct ether_header *)data; + unsigned char src_mac[18] = ""; + unsigned char dst_mac[18] = ""; + + sprintf(dst_mac, "%02x:%02x:%02x:%02x:%02x:%02x", + mac_hdr->ether_dhost[0], + mac_hdr->ether_dhost[1], + mac_hdr->ether_dhost[2], + mac_hdr->ether_dhost[3], + mac_hdr->ether_dhost[4], + mac_hdr->ether_dhost[5]); + + sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x", + mac_hdr->ether_shost[0], + mac_hdr->ether_shost[1], + mac_hdr->ether_dhost[2], + mac_hdr->ether_shost[3], + mac_hdr->ether_shost[4], + mac_hdr->ether_shost[5]); + + unsigned short mac_type = ntohs(mac_hdr->ether_type); + + printf("type(%#x) src mac: %s, dst mac: %s\n", mac_type, src_mac, dst_mac); + if (mac_type == 0x0800) + { + // 分析 ip 报文的数据 + struct iphdr *ip_hdr = (struct iphdr *)(data + sizeof(struct ether_header)); + u_char src_ip[INET_ADDRSTRLEN] = ""; + u_char dst_ip[INET_ADDRSTRLEN] = ""; + inet_ntop(AF_INET, &ip_hdr->saddr, src_ip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &ip_hdr->daddr, dst_ip, INET_ADDRSTRLEN); + + printf("ip type(%d) %s->%s\n", ip_hdr->protocol, src_ip, dst_ip); + } + + sleep(1); + } + + // 关闭网卡设备 + pcap_close(cap); + + return 0; +} diff --git a/day7/pcap3.c b/day7/pcap3.c new file mode 100644 index 0000000..cd22eec --- /dev/null +++ b/day7/pcap3.c @@ -0,0 +1,48 @@ +// pcap_loop 循环接收数据 +#include // libpcap头文件 +#include +#include +#include +#include +#include // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式 +#include +#include + +void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data); + +int main(int argc, char const *argv[]) +{ + // 1. 获取可用的网络设备名称 + char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备 + if (dev != NULL) + { + printf("网络设备名称: %s\n", dev); + } + + // 2. 打开网络设备, 开始捕获数据 + char err_buf[PCAP_ERRBUF_SIZE] = ""; + pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf); + if (cap == NULL) + { + printf("open pcap fail: %s\n", err_buf); + return -1; + } + + // 循环捕获数据 + pcap_loop(cap, -1, recv_data_handler, NULL); + + // 关闭网卡设备 + pcap_close(cap); + + return 0; +} + +void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data) +{ + if (cap_hdr->caplen > 0) + { + printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len); + } + + sleep(1); +} \ No newline at end of file diff --git a/day7/pcap4.c b/day7/pcap4.c new file mode 100644 index 0000000..d8400d9 --- /dev/null +++ b/day7/pcap4.c @@ -0,0 +1,56 @@ +// pcap_loop 循环接收数据 +#include // libpcap头文件 +#include +#include +#include +#include +#include // 网络地址转换函数,如inet_ntoa()->将网络地址转换成“.”点隔的字符串格式 +#include +#include + +void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *caphdr, const u_char *data); + +int main(int argc, char const *argv[]) +{ + // 1. 获取可用的网络设备名称 + char *dev = pcap_lookupdev(NULL); // NULL表示获取默认网络设备 + if (dev != NULL) + { + printf("网络设备名称: %s\n", dev); + } + + // 2. 打开网络设备, 开始捕获数据 + char err_buf[PCAP_ERRBUF_SIZE] = ""; + pcap_t *cap = pcap_open_live(dev, 128, 0, 0, err_buf); + if (cap == NULL) + { + printf("open pcap fail: %s\n", err_buf); + return -1; + } + + // 编译过滤规则, 成功则设置过滤规则 + char filter[] = "udp dst port 8001"; + struct bpf_program program; // 过滤器程序结构体,采用bpf(伯克利包过滤器) + if (pcap_compile(cap, &program, filter, 0, 0xffffff00) == 0) + { + pcap_setfilter(cap, &program); + } + + // 循环捕获数据 + pcap_loop(cap, -1, recv_data_handler, NULL); + + // 关闭网卡设备 + pcap_close(cap); + + return 0; +} + +void recv_data_handler(u_char *user_arg, const struct pcap_pkthdr *cap_hdr, const u_char *data) +{ + if (cap_hdr->caplen > 0) + { + printf("数据包长度: %d, 实际长度: %d\n", cap_hdr->caplen, cap_hdr->len); + } + + sleep(1); +} \ No newline at end of file