You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助tcpdump与libpcap获取关联请求中的设备RSSI值

获取关联请求帧的RSSI值:tcpdump与libpcap实现方案

Got it, let's work through how to capture RSSI values for association requests using tcpdump and libpcap—since your current hex-printing approach isn't practical for ongoing use.

一、先用tcpdump快速验证与抓取

首先,你需要确保网卡处于监控模式(因为要捕获802.11管理帧,比如关联请求)。先开启监控模式:

iw dev wlan0 set type monitor
ifconfig wlan0mon up

然后用tcpdump捕获关联请求帧并输出RSSI:

tcpdump -i wlan0mon -e -s 256 -vv type mgt subtype assoc-req
  • -e:显示链路层信息(包括MAC地址和信号强度)
  • -vv:开启详细输出,会包含RSSI相关字段
  • type mgt subtype assoc-req:过滤仅抓取管理帧中的关联请求

输出示例里,你会看到类似这样的字段:

signal -52 dBm noise -92 dBm

这就是你要的RSSI值(这里是-52 dBm)。不同网卡/驱动的输出格式可能略有差异,但核心是找“signal”或“RSSI”相关的数值。

二、用libpcap集成到你的C程序中

既然你已经有C程序捕获MAC地址,我们可以扩展它来提取RSSI。关键是要正确解析radiotap头(802.11帧前的额外元数据,包含RSSI等信息),注意:不要用固定偏移(比如你之前的packet+58),因为radiotap头的长度是可变的,不同网卡的头长度可能不同。

核心步骤:

  1. 初始化libpcap并设置监控模式
  2. 设置过滤规则,仅捕获关联请求帧
  3. 解析radiotap头,提取RSSI
  4. 解析802.11帧头,提取设备与路由器的MAC地址

代码示例片段:

#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <net/ethernet.h>
#include <linux/if_ether.h>
#include <linux/ieee80211.h>
#include <linux/ieee80211_radiotap.h>

// 回调函数:处理捕获到的数据包
void packet_handler(u_char *user_data, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
    struct ieee80211_radiotap_header *radiotap = (struct ieee80211_radiotap_header *)packet;
    int radiotap_len = le16_to_cpu(radiotap->it_len); // 转换为主机字节序的radiotap长度

    // 跳过radiotap头,得到802.11帧起始位置
    const u_char *frame = packet + radiotap_len;
    struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)frame;

    // 验证是否是关联请求帧
    if ((hdr->frame_control & IEEE80211_FCTL_TYPE) != IEEE80211_FTYPE_MGMT ||
        (hdr->frame_control & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_ASSOC_REQ) {
        return;
    }

    // 提取RSSI:遍历radiotap字段(因为字段顺序不固定)
    int rssi = -1;
    u_char *ptr = (u_char *)(radiotap + 1);
    u_char *end = (u_char *)radiotap + radiotap_len;

    while (ptr < end) {
        uint8_t id = *ptr++;
        uint8_t len = *ptr++;

        if (id == IEEE80211_RADIOTAP_DB_ANTSIGNAL) { // 信号强度(dBm)
            if (len >= 1) {
                rssi = (int)*ptr;
                // 注意:这个值是无符号的,实际RSSI是负数,所以要转换
                rssi = -rssi;
            }
            break;
        }
        ptr += len;
    }

    // 提取MAC地址:关联请求中,源MAC是设备MAC,BSSID是路由器MAC
    u_char *device_mac = hdr->addr2;
    u_char *router_mac = hdr->addr1;

    // 输出结果
    printf("关联请求捕获:\n");
    printf("设备MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 
           device_mac[0], device_mac[1], device_mac[2], device_mac[3], device_mac[4], device_mac[5]);
    printf("路由器MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 
           router_mac[0], router_mac[1], router_mac[2], router_mac[3], router_mac[4], router_mac[5]);
    if (rssi != -1) {
        printf("RSSI值: %d dBm\n", rssi);
    } else {
        printf("无法获取RSSI(网卡/驱动不支持)\n");
    }
    printf("----------------------------------------\n");
}

int main() {
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *handle;
    struct bpf_program fp;
    char filter_exp[] = "type mgt subtype assoc-req";
    bpf_u_int32 mask;
    bpf_u_int32 net;

    // 获取网卡信息(这里用wlan0mon,根据你的实际网卡名修改)
    if (pcap_lookupnet("wlan0mon", &net, &mask, errbuf) == -1) {
        fprintf(stderr, "无法获取网卡信息: %s\n", errbuf);
        net = 0;
        mask = 0;
    }

    // 打开网卡(监控模式)
    handle = pcap_open_live("wlan0mon", BUFSIZ, 1, 1000, errbuf);
    if (handle == NULL) {
        fprintf(stderr, "无法打开网卡: %s\n", errbuf);
        return 1;
    }

    // 编译过滤规则
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
        fprintf(stderr, "无法编译过滤规则: %s\n", pcap_geterr(handle));
        return 1;
    }

    // 设置过滤规则
    if (pcap_setfilter(handle, &fp) == -1) {
        fprintf(stderr, "无法设置过滤规则: %s\n", pcap_geterr(handle));
        return 1;
    }

    // 开始捕获数据包
    printf("开始捕获关联请求帧...\n");
    pcap_loop(handle, 0, packet_handler, NULL);

    // 关闭handle
    pcap_close(handle);
    return 0;
}

注意事项:

  • 编译时需要链接libpcap库:gcc -o rssi_capture rssi_capture.c -lpcap
  • 确保你的网卡支持监控模式,并且驱动能够在radiotap头中提供RSSI数据(部分老旧网卡可能不支持)
  • 不要依赖固定偏移提取MAC地址:因为radiotap头长度可变,之前的packet+58仅在特定网卡下有效,用802.11帧头的addr1(BSSID/路由器MAC)和addr2(源设备MAC)才是可靠的方法

内容的提问来源于stack exchange,提问作者Conor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:39:48