0

背景:

我对使用定义一组字段的位数组/位图感兴趣。具体来说,我想解析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?


}
4

2 回答 2

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
}

如您所见,它可能会有点毛茸茸。

于 2013-10-29T04:44:44.570 回答
0

我不确定我的问题是否正确。我假设你在问如何在第 3 位读取一些值。

因此,您可以正常读取值并将其左移 3 位。

x = 1 ; x = x << 3 ;

于 2013-10-29T05:31:34.137 回答