发送802.11帧的"帧控制字段"数据的顺序?

ben*_*iga 4 c wlan libpcap

以下是QoS数据的FC字段的位格式:

00|01|0001  01000010
Run Code Online (Sandbox Code Playgroud)

前2位表示版本,下2位表示类型,下4位子类型,ToDS = 0,FromDS = 1,保护位= 1.

那么,上面的数据以什么顺序通过界面发送?(即从左到右或从右到左)

我看到wireshark将数据捕获为" 8842 "(在显示原始数据包数据的最后一段).

但是,如果我编写以下代码来打印FC字段数据:

struct mgmt_header_t {
    u_int16_t    fc;          /* 2 bytes */
    u_int16_t    duration;    /* 2 bytes */
    u_int8_t     addr1[6];    /* 6 bytes */  
    u_int8_t     addr2[6];    /* 6 bytes */  
    u_int8_t     addr3[6];    /* 6 bytes */  
    u_int16_t    seq_ctrl;    /* 2 bytes */
};
void my_callback(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
    int radiotapheader_length = (unsigned short int)(*(packet+2));
    struct mgmt_header_t *mac_header = (struct mgmt_header_t *)  (packet+radiotapheader_length);
    printf("FC = %X\n", mac_header->fc);
}
Run Code Online (Sandbox Code Playgroud)

输出是:

FC = 4288
Run Code Online (Sandbox Code Playgroud)

所以我的第二个问题是,它不应该打印8842而不是4288吗?

更新: 我正在更新问题,以便更清楚我怀疑的是什么.

比如,我想发送一个QoS数据包,其FC字段的格式如下:

00|01|0001  01000010
Run Code Online (Sandbox Code Playgroud)

那么,我应该写:

mac_header->fc = 0x1142 /* value if read from left to right */
Run Code Online (Sandbox Code Playgroud)

要么

mac_header->fc = 0x4211
Run Code Online (Sandbox Code Playgroud)

要么

mac_header->fc = 0x4288 /* value if read from right to left */
Run Code Online (Sandbox Code Playgroud)

要么

mac_header->fc = 0x8842
Run Code Online (Sandbox Code Playgroud)

我的是一个小端机器.

小智 8

IEEE 802.11标准(遗憾的是,IEEE Get程序目前无法提供)标准:

MAC子层中的MPDU或帧被描述为特定顺序的字段序列.第7章中的每个图描绘了它们出现在MAC帧中的字段/子字段,以及它们从左到右传递到物理层会聚过程(PLCP)的顺序.

在图中,字段内的所有位都被编号,从0到k,其中字段的长度是k + 1位.字段内的八位字节边界可以通过取模数字8的位数来获得.数字字段中比单个八位字节长的八位字节以重要性的递增顺序描绘,从最低编号位到最高编号位.长度超过单个八位字节的字段中的八位字节按从包含最低编号位的八位字节到包含最高编号位的八位字节的顺序发送到PLCP.

因此,发送到PLCP的帧控制字段的第一个八位字节是包含B0的字节,即包含协议版本,类型和子类型字段的八位字节.之后是包含To DS,From DS,More Frag等的八位字节.的00|01|0001八位位组,因此,第一个八位组被发送.在内存中的一个字节中变为10001000,从高位到低位而不是低位到高位,因此为0x88.下一个八位字节是01000010一个,因此是0x42.

因此,00010001随后会越过线路01000010,并且将在内存中显示为0x88,然后是0x42.(顺便说一句,这意味着FC字段与802.11中的所有其他多字节组合字段一样,以little-endian字节顺序传输,而不是以big-endian字节顺序传输."网络字节顺序" 很大 -字节序字节顺序;并非所有通过网络传输的数据都是"网络字节顺序" - 互联网协议标准(如IPv4,IPv6,TCP和UDP)中的字段是"网络字节顺序",但其他协议,包括其中的一些IP传输,一些通过TCP或UDP传输,可能使用little-endian字节顺序.)

由小端机器接收,并被视为16位整数量,即0x4288 - 在小端机器上,具有多个八位字节的积分量,内存中的第一个八位字节是低阶八位字节数量.因此,您的代码在您的little-endian机器上打印为0x4288; 如果它在大端机器上运行,它会将其打印为0x8842.

将其打印为0x4288是打印它的"正确"方式,因为它是"在线上"的小端(或者更确切地说,"在空中",因为这是802.11 :-)).Wireshark在"数据包详细信息"窗格(默认情况下为中间窗格)中将数据包的帧控制字段显示为0x4288; 它在"十六进制转储"窗格(默认情况下为底部窗格)中显示为88 42,因为它只是按照它们在内存中出现的顺序显示每个单独的八位字节.

如果您希望它在big-endian和little-endian机器上打印为0x4288,则需要将它从little-endian字节顺序转换为主机字节顺序.最简单的方法是使用pletohs()Wireshark中的宏:

#define pletohs(p) ((unsigned short)                       \
                    ((unsigned short)*((const unsigned char *)(p)+1)<<8|  \
                     (unsigned short)*((const unsigned char *)(p)+0)<<0))
Run Code Online (Sandbox Code Playgroud)

并做一些事情

printf("FC = %X\n", pletohs(&mac_header->fc));
Run Code Online (Sandbox Code Playgroud)

至于发射该值,最简单的方法来做到在在你的机器的字节顺序,无论是使用的东西,如一种方式phtoles()从Wireshark的宏:

#define phtoles(p, v) \
    {                 \
        (p)[0] = (unsigned char)((v) >> 0);    \
        (p)[1] = (unsigned char)((v) >> 8);    \
    }
Run Code Online (Sandbox Code Playgroud)

并做

pletohs(&mac_header->fc, 0x4288);
Run Code Online (Sandbox Code Playgroud)

设定mac_header->fc.