Order of sending “Frame Control field”data of an 802.11 frame?

独自空忆成欢 提交于 2019-12-05 01:53:59

问题


Below is bit format for FC field for QoS Data:

00|01|0001  01000010

The first 2 bits represent version, the next 2 bits type, the next 4 bits subtype, with ToDS=0, FromDS=1,Protection bit=1.

So, in what order is the above data sent through the interface on the air? (i.e left to right or right to left )

I see the wireshark catching the data as "8842"(in the last segment where it shows raw packet data).

But, if I write the following code to print FC field data:

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);
}

The output is:

FC = 4288

So my secondary question is, shouldn't it print 8842 instead of 4288?

Update: I am updating the question so as to be more clear about what my doubt is.

Say, I want to send a QoS Data packet whose FC field is in the format below:

00|01|0001  01000010

So, should I have to write:

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

Or

mac_header->fc = 0x4211

Or

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

Or

mac_header->fc = 0x8842

Mine is a little endian machine.


回答1:


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.




回答2:


This is a byte ordering bug. You can't do (unsigned short int)(*(packet+2)) unless you know that your platform has the same byte order as the packet's contents. In your case, they differ which is why you're seeing the bytes swap places.

See this Wikipedia article for more on byte order, or endianness as it's also called.




回答3:


FC is printed as 4288 because your system uses little-endian format to store data in memory. Where as network communications follows big-endian format.

Ensure with the following program

#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;
}

if it prints 0x78563412 then your machine is little-endian. else if it prints 0x12345678 then it is big-endian.

EDIT:
I hope follwing links will be helpful.

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



来源:https://stackoverflow.com/questions/11562036/order-of-sending-frame-control-fielddata-of-an-802-11-frame

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!