背景
我有兴趣使用定义一组字段的位数组/位图。具体来说,我想解析radiotap标题,但我遇到了一些概念上的问题(或者,更可能的是,我只是错过了一些关于这一切是如何工作的)。
位数组描述的字段radiotap标头在上面的链接中定义。
问题:(已编辑)
例如,当我的数据是u_char流时,我将如何读取位图和字段中的值?我如何访问一个特定的字段,因为我知道它的存在是由位图指示的?
我认为这里的解决方案与位移/屏蔽有关,但这是我第一次尝试低级别编程,我不知道如何开始解决这个问题。
修改
目前我的问题是我正在从u_char指针读取802.11帧,但是我一直在以编程方式从这里开始访问我所知道的标题和字段,首先是radiotap标题。
//defined by library I'm using
struct packet_header {
struct timeval ts; /*timestamp*/
bpf_u_int32 caplen; /*number of stored bytes*/
bpf_u_int32 length; /*total length of packet*/
}
struct packet_header hdr; //see above, basic info
u_char *packet //the data
for(int i = 0; i < hdr->length; i++){
//parse/analyse data contained in the frame/packet (1st radiotap)
packet[i] //do something with u_char here, but what exactly?
}
答案 0 :(得分:2)
我建议你仔细研究这个页面:http://www.radiotap.org/Radiotap
标题的it_present
字段表示标题后面的字段。并且存在的字段按其位数顺序排列,从最低到最高。因此,例如,如果it_present
中的第一个非零位是第3位,则标头后面的第一个字段将是通道。
这个协议非常复杂,必须遵循许多规则。例如,如果设置了it_present
的第31位,则不是紧跟在标题之后的字段,而是首先存在更多的存在位。您还必须了解字段的对齐方式。字段之间可能存在填充,因此32位字段在4字节边界上对齐,64位字段在8字节边界上对齐,依此类推。
编辑:我们假设packet
指向radiotap标头的开头,pkt_len
是字节数。你可以像这样开始:
pkt_len = hdr.length;
if ( pkt_len >= sizeof(ieee80211_radiotap_header) )
{
u_int16_t it_len;
u_int32_t it_present;
u_int32_t tmpMask;
u_int32_t* pExtraMask;
u_int32_t* pNextMask;
u_int32_t uMask;
int iFldNum;
ieee80211_radiotap_header* pPktHdr = (ieee80211_radiotap_header*) packet;
pkt_len -= sizeof(ieee80211_radiotap_header);
packet += sizeof(ieee80211_radiotap_header);
it_len = le16_to_cpu(pPktHdr->it_len); // Get radiotap packet length from header
it_present = le32_to_cpu(pPktHdr->it_present); // Get present field bitmask
// Find end of radiotap header
tmpMask = it_present;
pExtraMask = pNextMask = (u_int32_t*) packet;
while ( (tmpMask & 0x80000000) && (pkt_len >= sizeof(u_int32_t)) )
{
tmpMask = le32_to_cpu(*pNextMask++);
pkt_len -= sizeof(u_int32_t);
packet += sizeof(u_int32_t);
}
// packet should now point to the first field
for ( iFldNum = 0, uMask = 1; (iFldNum < 31) && pkt_len; ++iFldNum, uMask <<= 1 )
{
if ( (it_present & uMask) )
{
u_int16_t uFldLen;
// We have a non-zero bit in the mask, iFldNum is the field number
// Call function to extract the field at packet and return number of bytes used
// process_field() is responsible for data alignment and preventing buffer overrun
uFldLen = process_field(packet, pkt_len, iFldNum);
pkt_len -= uFldLen;
packet += uFldLen;
}
}
// Here you would check if it_present had bit 31 set
// If so, process additional masks starting at pExtraMask
}
正如你所看到的,它可能会有点毛茸茸。
答案 1 :(得分:0)
我不确定我的问题是否正确。我假设你在询问如何在第3位读取一些值。
因此,您可以正常读取值并将其左移3个位置。
x = 1; x = x&lt;&lt; 3;