4

以下は、QoS データの FC フィールドのビット形式です。

00|01|0001  01000010

最初の 2 ビットはバージョン、次の 2 ビットはタイプ、次の 4 ビットはサブタイプを表し、ToDS=0、FromDS=1、Protection ビット=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);
}

出力は次のとおりです。

FC = 4288

私の二次的な質問は、4288の代わりに8842を出力すべきではないということです。

更新: 私の疑問が何であるかをより明確にするために、質問を更新しています。

たとえば、FC フィールドが次の形式の QoS データ パケットを送信したいとします。

00|01|0001  01000010

だから、私は書く必要があります:

mac_header->fc = 0x1142 /* value if read from left to right */

または

mac_header->fc = 0x4211

または

mac_header->fc = 0x4288 /* value if read from right to left */

または

mac_header->fc = 0x8842

私のはリトルエンディアンマシンです。

4

3 に答える 3

8

The IEEE 802.11 standard (which, unfortunately, is not currently available from the IEEE Get program) says:

The MPDUs or frames in the MAC sublayer are described as a sequence of fields in specific order. Each figure in Clause 7 depicts the fields/subfields as they appear in the MAC frame and in the order in which they are passed to the physical layer convergence procedure (PLCP), from left to right.

In figures, all bits within fields are numbered, from 0 to k, where the length of the field is k + 1 bits. The octet boundaries within a field can be obtained by taking the bit numbers of the field modulo 8. Octets within numeric fields that are longer than a single octet are depicted in increasing order of significance, from lowest numbered bit to highest numbered bit. The octets in fields longer than a single octet are sent to the PLCP in order from the octet containing the lowest numbered bits to the octet containing the highest numbered bits.

So the first octet of the Frame Control field sent to the PLCP is the one containing B0, i.e. the octet containing the protocol version, type, and subtype fields. After that comes the octet containing To DS, From DS, More Frag, and so on. The 00|01|0001 octet is, therefore, the first octet transmitted. That turns into 10001000 in a byte in memory, from high-order bit to low-order bit rather than low-order bit to high-order bit, hence 0x88. The next octet is the 01000010 one, hence 0x42.

So that goes over the wire as 00010001 followed by 01000010, and would appear in memory as 0x88 followed by 0x42. (This, by the way, means that the FC field, like all other multi-octet integral fields in 802.11, is transmitted in little-endian byte order, rather than in big-endian byte order. "Network byte order" is big-endian byte order; not all data transmitted over a network is in "network byte order" - fields in Internet protocol standards such as IPv4, IPv6, TCP, and UDP are in "network byte order", but other protocols, including some over which IP is transmitted and some that are transmitted over TCP or UDP, may use little-endian byte order.)

As received by a little-endian machine, and treated as a 16-bit integral quantity, that would be 0x4288 - on a little-endian machine, with a multiple-octet integral quantity, the first octet in memory is the low-order octet of the quantity. Therefore, your code prints it as 0x4288 on your little-endian machine; if it were running on a big-endian machine, it would print it as 0x8842.

Printing it as 0x4288 is the "correct" way to print it, as it's little-endian "on the wire" (or, rather, "on the air", as this is 802.11 :-)). Wireshark shows the Frame Control field for your packet as 0x4288 in the "packet details" pane (the middle pane, by default); it shows up as 88 42 in the "hex dump" pane (the bottom pane, by default) because it's just showing each individual octet in the order in which they appear in memory.

You would need to convert it from little-endian byte order to host byte order if you want it to print as 0x4288 on both big-endian and little-endian machines. The easiest way to do that would be to use something such as the pletohs() macro from Wireshark:

#define pletohs(p) ((unsigned short)                       \
                    ((unsigned short)*((const unsigned char *)(p)+1)<<8|  \
                     (unsigned short)*((const unsigned char *)(p)+0)<<0))

and do something such as

printf("FC = %X\n", pletohs(&mac_header->fc));

As for transmitting that value, the easiest way to do that in a way that works regardless of the byte order of your machine would be to use something such as the phtoles() macro from Wireshark:

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

and do

pletohs(&mac_header->fc, 0x4288);

to set mac_header->fc.

于 2012-07-19T18:31:36.860 に答える
1

FC は4288、システムがリトル エンディアン形式を使用してデータをメモリに格納するため、次のように出力されます。ネットワーク通信はビッグエンディアン形式に従います。

次のプログラムで確認します

#include <stdio.h>
int main()
{

int a = 0x12345678, j = 0;
char *b =(char*)&a;
printf("\n0x");
for(j=0; j < sizeof(int); j++)
        printf("%x", *b++);

printf("\n");

return 0;
}

0x78563412 が出力される場合、マシンはリトル エンディアンです。それ以外の場合、0x12345678 が出力される場合は、ビッグエンディアンです。

編集:
次のリンクが役立つことを願っています。

1. http://www.cs.odu.edu/~cs476/fall03/lectures/sockets.htm 2.
http://www.ccplusplus.com/2011/10/htons-example-in-c.html

于 2012-07-19T14:20:40.840 に答える
1

これはバイト順のバグです。(unsigned short int)(*(packet+2))プラットフォームのバイト順がパケットの内容と同じであることがわかっていない限り、これを行うことはできません。あなたの場合、それらは異なるため、バイトスワップの場所が表示されます。

バイトオーダー、またはエンディアンとも呼ばれるエンディアンの詳細については、このウィキペディアの記事を参照してください。

于 2012-07-19T14:07:04.613 に答える