Changeset 1761

Show
Ignore:
Timestamp:
10/23/06 11:10:31 (2 years ago)
Author:
kelmo
Message:

This patch adds radiotap header parsing capability to ieee80211_monitor_encap.
It allows userspace applications to send frames encapsulated in radiotap
header containing any arbitrary subset of fields (from the set of known ones)
instead of the fixed ath_tx_radiotap_header. It properly handles extended
field presence bitmaps and removes FCS from the end of the frame if it is
present according to an apropriate radiotap header flag. Parsing stops after
encountering unknown field.

Signed-off-by: Michal Wrobel <xmxwx@asn.pl>

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/net80211/ieee80211_monitor.c

    r1728 r1761  
    166166                break; 
    167167        } 
     168        case ARPHRD_IEEE80211_RADIOTAP: { 
     169                struct ieee80211_frame *wh = NULL; 
     170                struct ieee80211_radiotap_header *rh = 
     171                        (struct ieee80211_radiotap_header *)skb->data; 
     172                u_int32_t present, present_ext; 
     173                u_int16_t len; 
     174                u_int8_t *start = skb->data + sizeof(struct ieee80211_radiotap_header); 
     175                u_int8_t *p = start; 
     176                u_int8_t *end = skb->data + skb->len; 
     177                u_int8_t bit, flags = 0; 
     178 
     179                if (skb->len < sizeof(*rh) || rh->it_version != 0) 
     180                        break; 
     181 
     182                present_ext = present = le32_to_cpu(rh->it_present); 
     183                len = le16_to_cpu(rh->it_len); 
     184 
     185                if (skb->len < len) 
     186                        break; 
     187 
     188                /* skip the chain of additional bitmaps following it_present */ 
     189                while (present_ext & (1 << IEEE80211_RADIOTAP_EXT)) { 
     190                        if (p+4 > end) { 
     191                                /* An extended bitmap would now follow, but there is  
     192                                 * no place for it. Stop parsing. */ 
     193                                present = 0; 
     194                                break; 
     195                        } 
     196                        present_ext = le32_to_cpu(*(u_int32_t*)p); 
     197                        p += 4; 
     198                } 
     199 
     200                for (bit = 0; present && p < end; present >>= 1, bit++) { 
     201                        if ((present & 1) == 0) 
     202                                continue; 
     203                        switch (bit) { 
     204                                case IEEE80211_RADIOTAP_RATE: 
     205                                        ph->rate0 = *p; 
     206                                        p++; 
     207                                        break; 
     208 
     209                                case IEEE80211_RADIOTAP_DBM_TX_POWER: 
     210                                        ph->power = *p; 
     211                                        p++; 
     212                                        break; 
     213 
     214                                case IEEE80211_RADIOTAP_FLAGS: 
     215                                        flags = *p; 
     216                                        p++; 
     217                                        break; 
     218 
     219                                case IEEE80211_RADIOTAP_DB_ANTSIGNAL: 
     220                                case IEEE80211_RADIOTAP_DB_ANTNOISE: 
     221                                case IEEE80211_RADIOTAP_ANTENNA: 
     222                                case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: 
     223                                case IEEE80211_RADIOTAP_DBM_ANTNOISE: 
     224                                        /* 8-bit */ 
     225                                        p++; 
     226                                        break; 
     227 
     228                                case IEEE80211_RADIOTAP_FHSS: 
     229                                        /* 2 x 8-bit */ 
     230                                        p += 2; 
     231                                        break; 
     232 
     233                                case IEEE80211_RADIOTAP_LOCK_QUALITY: 
     234                                case IEEE80211_RADIOTAP_TX_ATTENUATION: 
     235                                case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: 
     236                                        /* 16-bit */ 
     237                                        p = start + roundup(p - start, 2) + 2; 
     238                                        break; 
     239 
     240                                case IEEE80211_RADIOTAP_CHANNEL: 
     241                                        /* 2 x 16-bit */ 
     242                                        p = start + roundup(p - start, 2) + 4; 
     243                                        break; 
     244 
     245                                case IEEE80211_RADIOTAP_FCS: 
     246                                        /* 32-bit */ 
     247                                        p = start + roundup(p - start, 4) + 4; 
     248                                        break; 
     249 
     250                                case IEEE80211_RADIOTAP_TSFT: 
     251                                        /* 64-bit */ 
     252                                        p = start + roundup(p - start, 8) + 8; 
     253                                        break; 
     254 
     255                                default: 
     256                                        present = 0; 
     257                                        break; 
     258                        } 
     259                } 
     260                skb_pull(skb, len); 
     261                if (flags & IEEE80211_RADIOTAP_F_FCS) 
     262                        /* Remove FCS from the end of frames to transmit */ 
     263                        skb_trim(skb, skb->len - IEEE80211_CRC_LEN); 
     264                wh = (struct ieee80211_frame *)skb->data; 
     265                if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)  
     266                        ph->try0 = 1; 
     267                break; 
     268        } 
    168269        case ARPHRD_IEEE80211_ATHDESC: { 
    169270                if (skb->len > ATHDESC_HEADER_SIZE) { 
     
    183284                break; 
    184285        }        
    185         case ARPHRD_IEEE80211_RADIOTAP: { 
    186                 if(skb->len >  sizeof(struct ath_tx_radiotap_header)) { 
    187                         struct ath_tx_radiotap_header *wh = (struct ath_tx_radiotap_header *) skb->data; 
    188                         ph->power = wh->wt_txpower; 
    189                         ph->rate0 = wh->wt_rate; 
    190                         ph->try0 = 1; 
    191                         skb_pull(skb, sizeof(struct ath_tx_radiotap_header)); 
    192                 } 
    193                 break; 
    194         } 
    195286        default: 
    196287                break; 
  • trunk/net80211/ieee80211_radiotap.h

    r1484 r1761  
    217217                                                 * with fragmentation 
    218218                                                 */ 
     219#define IEEE80211_RADIOTAP_F_FCS        0x10    /* frame includes FCS */ 
     220#define IEEE80211_RADIOTAP_F_DATAPAD    0x20    /* frame has padding between 
     221                                                 * 802.11 header and payload 
     222                                                 * (to 32-bit boundary) 
     223                                                 */ 
     224#define IEEE80211_RADIOTAP_F_BADFCS     0x40    /* does not pass FCS check */ 
    219225 
    220226#endif /* _NET_IF_IEEE80211RADIOTAP_H_ */