QT协议终端调出ARP

#include<stdio.h>  // 引入标准输入输出库
#include<pcap.h>   // 引入pcap库,用于网络数据包捕获
#include<time.h>   // 引入时间处理库
#ifndef ETHERTYPE_ARP
#define ETHERTYPE_ARP 0x0806
#endif

// ARP头部结构定义
struct arphdr {
    unsigned short ar_hrd;      /* 格式/协议类型 */
    unsigned short ar_pro;      /* 协议类型 */
    unsigned char  ar_hln;      /* 硬件地址长度 */
    unsigned char  ar_pln;      /* 协议地址长度 */
    unsigned short ar_op;       /* ARP操作码 */

    /* ARP数据字段 */
    // 这里可以添加源硬件地址、源协议地址、目的硬件地址和目的协议地址的字段
    // 但为了简洁,我们将直接在解析时从数据包中读取
};
struct ether_header
{
    u_int8_t ether_dhost[6];//目的MAC地址
    u_int8_t ether_shost[6];//源MAC地址
    u_int16_t e_type;//以太网类型
};

// 定义回调函数,当捕获到数据包时,pcap库会调用这个函数
void call_back(u_char *argument, const struct pcap_pkthdr *pkt_hdr, const u_char *pktdata)
{
    unsigned int packet_length = pkt_hdr->len; // 数据包的长度
    long timestamp_seconds = pkt_hdr->ts.tv_sec; // 数据包的时间戳(秒)
    long timestamp_microseconds = pkt_hdr->ts.tv_usec; // 数据包的时间戳(微秒)

    time_t rawtime = timestamp_seconds; // 将秒转换为time_t类型
    struct tm *timeinfo; // 定义一个指向tm结构体的指针,用于存储本地时间
    char time[20]; // 定义一个字符数组,用于存储格式化后的时间字符串

    // 获取本地时间
    timeinfo = localtime(&rawtime);

    // 格式化时间字符串
    strftime(time, sizeof(time), "%Y-%m-%d %H:%M:%S", timeinfo);
    struct ether_header *eth_header = (struct ether_header*)pktdata;

        // 输出以太网目的地址
        printf("目的MAC地址: ");
        for (int i = 0; i < 6; i++) {
            printf("%02x", eth_header->ether_dhost[i]);
            if (i < 5) {
                printf(":");
            }
        }
        printf("\n");

        // 输出以太网源地址
        printf("源MAC地址: ");
        for (int i = 0; i < 6; i++) {
            printf("%02x", eth_header->ether_shost[i]);
            if (i < 5) {
                printf(":");
            }
        }
        printf("\n");

        // 输出以太网类型(注意这里是以网络字节序,可能需要转换为主机字节序)
        printf("以太网类型: %04x\n", ntohs(eth_header->e_type));
        // 检查以太网类型是否为ARP
        if (ntohs(eth_header->e_type) == ETHERTYPE_ARP) {
                struct arphdr *arp_header = (struct arphdr*)(pktdata + sizeof(struct ether_header));

            // 输出硬件类型(通常是1,代表以太网)
            printf("硬件类型: %hu\n", ntohs(arp_header->ar_hrd));

                // 输出协议类型(通常是0x0800,代表IPv4)
            printf("协议类型: %hu\n", ntohs(arp_header->ar_pro));

                // 输出硬件地址长度和协议地址长度
            printf("硬件地址长度: %hu\n", arp_header->ar_hln);
            printf("协议地址长度: %hu\n", arp_header->ar_pln);

                // 输出操作码(1为ARP请求,2为ARP响应)
            printf("操作码: %hu\n", ntohs(arp_header->ar_op));

                // 输出发送方MAC地址(已经在以太网头部中给出)
                printf("发送方MAC地址: ");
                for (int i = 0; i < 6; i++) {
                    printf("%02x", eth_header->ether_shost[i]);
                    if (i < 5) {
                        printf(":");
                    }
                }
                printf("\n");

                // 跳过ARP头部到发送方IP地址
                struct in_addr sender_ip;
                memcpy(&sender_ip, pktdata + sizeof(struct ether_header) + sizeof(struct arphdr) +
                       arp_header->ar_hln, sizeof(sender_ip));
                printf("发送方IP地址: %s\n", inet_ntoa(sender_ip));

                // 输出目的MAC地址(已经在以太网头部中给出)
                printf("目的MAC地址: ");
                for (int i = 0; i < 6; i++) {
                    printf("%02x", eth_header->ether_dhost[i]);
                    if (i < 5) {
                        printf(":");
                    }
                }
                printf("\n");

                // 跳过ARP头部到目的IP地址
                struct in_addr target_ip;
                memcpy(&target_ip, pktdata + sizeof(struct ether_header) + sizeof(struct arphdr) +
                       2 * arp_header->ar_hln + arp_header->ar_pln, sizeof(target_ip));
                printf("目的IP地址: %s\n", inet_ntoa(target_ip));
            }

    // 输出数据包长度和时间
    printf("数据包长度:%u\n", packet_length);
    printf("时间:%s.%06ld\n\n", time, timestamp_microseconds);
}

int main()
{
    char *device = "ens33"; // 定义网络接口名称
    printf("%s\n", device); // 输出网络接口名称

    char err_content[PCAP_ERRBUF_SIZE]; // 定义一个字符数组,用于存储错误消息
    char* filepath = "./input/bingyanglife.pcap"; // 定义pcapng文件的路径
    pcap_t *handle = NULL; // 定义pcap句柄
    int method = 0; // 定义方法选择变量,0表示从文件读取,1表示从网络接口捕获

    // 根据method的值选择打开网络接口或pcapng文件
    if (1 == method)
    {
        handle = pcap_open_live(device, BUFSIZ, 1, 0, err_content); // 打开网络接口进行实时捕获
    }
    else
    {
        handle = pcap_open_offline(filepath, err_content); // 打开pcapng文件进行读取
    }

    // 检查是否成功打开
    if (handle == NULL)
    {
        printf("无法打开文件:%s", err_content); // 输出错误信息
        return 1; // 返回错误代码
    }
 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值