简体   繁体   中英

reading fields from bit array/bitmap in c++

Background:

I'm interested in working with a bit array/bitmap that defines a set of fields. Specifically, I'd like to parse the radiotap header but I'm having something of a conceptual problem (or, more likely, am just missing something about how this all works).

The fields described by the bit array, the radiotap header, are defined in the link above.

Question: (edited)

For instance then, how would I go about reading the values in the bitmap and in the fields when my data is a u_char stream? How do I access a field specifically given that I know its presence is indicated by the bitmap?

I figure that the solution here will have something to do with bit shifting/masking but this is my first foray into low-ish level programming and I don't know quite how to begin solving this problem.

Edit:

Currently for my problem I'm reading in 802.11 frames from a u_char pointer, but I'm stuck on where to go from here programatically to access the header and fields of what I know to be, first, the radiotap header.

//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?


}

I would suggest that you study this page very carefully: http://www.radiotap.org/Radiotap

The it_present field of the header indicates what fields follow the header. And the fields that are present are in order by their bit number, lowest to highest. So for example, if the first non-zero bit in it_present is bit 3, the first field following the header will be the channel.

This protocol is quite complicated and there are a lot of rules that must be followed. For instance, if bit 31 of it_present is set, then instead of fields immediately following the header, there are more presence bits first. You must also be aware of alignment of fields. There may be padding between fields so that 32-bit fields are aligned on 4-byte boundaries and 64-bit fields are aligned on 8-byte boundaries and so on.

Edit: Let's assume that packet points to the beginning of the radiotap header and that pkt_len is the number of bytes. You could get started like this:

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
}

As you can see, it can get a bit hairy.

I am not sure if i got your question right. I am assuming you are asking how to read some value at bit 3.

So you can read value normally and left shift it by 3 places.

x = 1 ; x = x << 3 ;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM