162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci=========================== 462306a36Sopenharmony_ciHow to use radiotap headers 562306a36Sopenharmony_ci=========================== 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciPointer to the radiotap include file 862306a36Sopenharmony_ci------------------------------------ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciRadiotap headers are variable-length and extensible, you can get most of the 1162306a36Sopenharmony_ciinformation you need to know on them from:: 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci ./include/net/ieee80211_radiotap.h 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ciThis document gives an overview and warns on some corner cases. 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciStructure of the header 1962306a36Sopenharmony_ci----------------------- 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciThere is a fixed portion at the start which contains a u32 bitmap that defines 2262306a36Sopenharmony_ciif the possible argument associated with that bit is present or not. So if b0 2362306a36Sopenharmony_ciof the it_present member of ieee80211_radiotap_header is set, it means that 2462306a36Sopenharmony_cithe header for argument index 0 (IEEE80211_RADIOTAP_TSFT) is present in the 2562306a36Sopenharmony_ciargument area. 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci:: 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci < 8-byte ieee80211_radiotap_header > 3062306a36Sopenharmony_ci [ <possible argument bitmap extensions ... > ] 3162306a36Sopenharmony_ci [ <argument> ... ] 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciAt the moment there are only 13 possible argument indexes defined, but in case 3462306a36Sopenharmony_ciwe run out of space in the u32 it_present member, it is defined that b31 set 3562306a36Sopenharmony_ciindicates that there is another u32 bitmap following (shown as "possible 3662306a36Sopenharmony_ciargument bitmap extensions..." above), and the start of the arguments is moved 3762306a36Sopenharmony_ciforward 4 bytes each time. 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciNote also that the it_len member __le16 is set to the total number of bytes 4062306a36Sopenharmony_cicovered by the ieee80211_radiotap_header and any arguments following. 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciRequirements for arguments 4462306a36Sopenharmony_ci-------------------------- 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ciAfter the fixed part of the header, the arguments follow for each argument 4762306a36Sopenharmony_ciindex whose matching bit is set in the it_present member of 4862306a36Sopenharmony_ciieee80211_radiotap_header. 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci - the arguments are all stored little-endian! 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci - the argument payload for a given argument index has a fixed size. So 5362306a36Sopenharmony_ci IEEE80211_RADIOTAP_TSFT being present always indicates an 8-byte argument is 5462306a36Sopenharmony_ci present. See the comments in ./include/net/ieee80211_radiotap.h for a nice 5562306a36Sopenharmony_ci breakdown of all the argument sizes 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci - the arguments must be aligned to a boundary of the argument size using 5862306a36Sopenharmony_ci padding. So a u16 argument must start on the next u16 boundary if it isn't 5962306a36Sopenharmony_ci already on one, a u32 must start on the next u32 boundary and so on. 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci - "alignment" is relative to the start of the ieee80211_radiotap_header, ie, 6262306a36Sopenharmony_ci the first byte of the radiotap header. The absolute alignment of that first 6362306a36Sopenharmony_ci byte isn't defined. So even if the whole radiotap header is starting at, eg, 6462306a36Sopenharmony_ci address 0x00000003, still the first byte of the radiotap header is treated as 6562306a36Sopenharmony_ci 0 for alignment purposes. 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci - the above point that there may be no absolute alignment for multibyte 6862306a36Sopenharmony_ci entities in the fixed radiotap header or the argument region means that you 6962306a36Sopenharmony_ci have to take special evasive action when trying to access these multibyte 7062306a36Sopenharmony_ci entities. Some arches like Blackfin cannot deal with an attempt to 7162306a36Sopenharmony_ci dereference, eg, a u16 pointer that is pointing to an odd address. Instead 7262306a36Sopenharmony_ci you have to use a kernel API get_unaligned() to dereference the pointer, 7362306a36Sopenharmony_ci which will do it bytewise on the arches that require that. 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci - The arguments for a given argument index can be a compound of multiple types 7662306a36Sopenharmony_ci together. For example IEEE80211_RADIOTAP_CHANNEL has an argument payload 7762306a36Sopenharmony_ci consisting of two u16s of total length 4. When this happens, the padding 7862306a36Sopenharmony_ci rule is applied dealing with a u16, NOT dealing with a 4-byte single entity. 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ciExample valid radiotap header 8262306a36Sopenharmony_ci----------------------------- 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci:: 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci 0x00, 0x00, // <-- radiotap version + pad byte 8762306a36Sopenharmony_ci 0x0b, 0x00, // <- radiotap header length 8862306a36Sopenharmony_ci 0x04, 0x0c, 0x00, 0x00, // <-- bitmap 8962306a36Sopenharmony_ci 0x6c, // <-- rate (in 500kHz units) 9062306a36Sopenharmony_ci 0x0c, //<-- tx power 9162306a36Sopenharmony_ci 0x01 //<-- antenna 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciUsing the Radiotap Parser 9562306a36Sopenharmony_ci------------------------- 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ciIf you are having to parse a radiotap struct, you can radically simplify the 9862306a36Sopenharmony_cijob by using the radiotap parser that lives in net/wireless/radiotap.c and has 9962306a36Sopenharmony_ciits prototypes available in include/net/cfg80211.h. You use it like this:: 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci #include <net/cfg80211.h> 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* buf points to the start of the radiotap header part */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci int MyFunction(u8 * buf, int buflen) 10662306a36Sopenharmony_ci { 10762306a36Sopenharmony_ci int pkt_rate_100kHz = 0, antenna = 0, pwr = 0; 10862306a36Sopenharmony_ci struct ieee80211_radiotap_iterator iterator; 10962306a36Sopenharmony_ci int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buflen); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci while (!ret) { 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ret = ieee80211_radiotap_iterator_next(&iterator); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci if (ret) 11662306a36Sopenharmony_ci continue; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci /* see if this argument is something we can use */ 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci switch (iterator.this_arg_index) { 12162306a36Sopenharmony_ci /* 12262306a36Sopenharmony_ci * You must take care when dereferencing iterator.this_arg 12362306a36Sopenharmony_ci * for multibyte types... the pointer is not aligned. Use 12462306a36Sopenharmony_ci * get_unaligned((type *)iterator.this_arg) to dereference 12562306a36Sopenharmony_ci * iterator.this_arg for type "type" safely on all arches. 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci case IEEE80211_RADIOTAP_RATE: 12862306a36Sopenharmony_ci /* radiotap "rate" u8 is in 12962306a36Sopenharmony_ci * 500kbps units, eg, 0x02=1Mbps 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci pkt_rate_100kHz = (*iterator.this_arg) * 5; 13262306a36Sopenharmony_ci break; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci case IEEE80211_RADIOTAP_ANTENNA: 13562306a36Sopenharmony_ci /* radiotap uses 0 for 1st ant */ 13662306a36Sopenharmony_ci antenna = *iterator.this_arg); 13762306a36Sopenharmony_ci break; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci case IEEE80211_RADIOTAP_DBM_TX_POWER: 14062306a36Sopenharmony_ci pwr = *iterator.this_arg; 14162306a36Sopenharmony_ci break; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci default: 14462306a36Sopenharmony_ci break; 14562306a36Sopenharmony_ci } 14662306a36Sopenharmony_ci } /* while more rt headers */ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (ret != -ENOENT) 14962306a36Sopenharmony_ci return TXRX_DROP; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci /* discard the radiotap header part */ 15262306a36Sopenharmony_ci buf += iterator.max_length; 15362306a36Sopenharmony_ci buflen -= iterator.max_length; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ... 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ciAndy Green <andy@warmcat.com> 160