00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "radiotap_iter.h"
00017 #include "platform.h"
00018
00019
00020
00021 static const struct radiotap_align_size rtap_namespace_sizes[] = {
00022 [IEEE80211_RADIOTAP_TSFT] = { .align = 8, .size = 8, },
00023 [IEEE80211_RADIOTAP_FLAGS] = { .align = 1, .size = 1, },
00024 [IEEE80211_RADIOTAP_RATE] = { .align = 1, .size = 1, },
00025 [IEEE80211_RADIOTAP_CHANNEL] = { .align = 2, .size = 4, },
00026 [IEEE80211_RADIOTAP_FHSS] = { .align = 2, .size = 2, },
00027 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = { .align = 1, .size = 1, },
00028 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = { .align = 1, .size = 1, },
00029 [IEEE80211_RADIOTAP_LOCK_QUALITY] = { .align = 2, .size = 2, },
00030 [IEEE80211_RADIOTAP_TX_ATTENUATION] = { .align = 2, .size = 2, },
00031 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = { .align = 2, .size = 2, },
00032 [IEEE80211_RADIOTAP_DBM_TX_POWER] = { .align = 1, .size = 1, },
00033 [IEEE80211_RADIOTAP_ANTENNA] = { .align = 1, .size = 1, },
00034 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = { .align = 1, .size = 1, },
00035 [IEEE80211_RADIOTAP_DB_ANTNOISE] = { .align = 1, .size = 1, },
00036 [IEEE80211_RADIOTAP_RX_FLAGS] = { .align = 2, .size = 2, },
00037 [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, },
00038 [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, },
00039 [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
00040
00041
00042
00043 };
00044
00045 static const struct ieee80211_radiotap_namespace radiotap_ns = {
00046 .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
00047 .align_size = rtap_namespace_sizes,
00048 };
00049
00088 int ieee80211_radiotap_iterator_init(
00089 struct ieee80211_radiotap_iterator *iterator,
00090 struct ieee80211_radiotap_header *radiotap_header,
00091 int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
00092 {
00093
00094 if (radiotap_header->it_version)
00095 return -EINVAL;
00096
00097
00098 if (max_length < get_unaligned_le16(&radiotap_header->it_len))
00099 return -EINVAL;
00100
00101 iterator->_rtheader = radiotap_header;
00102 iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
00103 iterator->_arg_index = 0;
00104 iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
00105 iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
00106 iterator->_reset_on_ext = 0;
00107 iterator->_next_bitmap = &radiotap_header->it_present;
00108 iterator->_next_bitmap++;
00109 iterator->_vns = vns;
00110 iterator->current_namespace = &radiotap_ns;
00111 iterator->is_radiotap_ns = 1;
00112 #ifdef RADIOTAP_SUPPORT_OVERRIDES
00113 iterator->n_overrides = 0;
00114 iterator->overrides = NULL;
00115 #endif
00116
00117
00118
00119 if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
00120 while (get_unaligned_le32(iterator->_arg) &
00121 (1 << IEEE80211_RADIOTAP_EXT)) {
00122 iterator->_arg += sizeof(uint32_t);
00123
00124
00125
00126
00127
00128
00129
00130 if ((unsigned long)iterator->_arg -
00131 (unsigned long)iterator->_rtheader >
00132 (unsigned long)iterator->_max_length)
00133 return -EINVAL;
00134 }
00135
00136 iterator->_arg += sizeof(uint32_t);
00137
00138
00139
00140
00141
00142
00143 }
00144
00145 iterator->this_arg = iterator->_arg;
00146
00147
00148
00149 return 0;
00150 }
00151
00152 static void find_ns(struct ieee80211_radiotap_iterator *iterator,
00153 uint32_t oui, uint8_t subns)
00154 {
00155 int i;
00156
00157 iterator->current_namespace = NULL;
00158
00159 if (!iterator->_vns)
00160 return;
00161
00162 for (i = 0; i < iterator->_vns->n_ns; i++) {
00163 if (iterator->_vns->ns[i].oui != oui)
00164 continue;
00165 if (iterator->_vns->ns[i].subns != subns)
00166 continue;
00167
00168 iterator->current_namespace = &iterator->_vns->ns[i];
00169 break;
00170 }
00171 }
00172
00173 #ifdef RADIOTAP_SUPPORT_OVERRIDES
00174 static int find_override(struct ieee80211_radiotap_iterator *iterator,
00175 int *align, int *size)
00176 {
00177 int i;
00178
00179 if (!iterator->overrides)
00180 return 0;
00181
00182 for (i = 0; i < iterator->n_overrides; i++) {
00183 if (iterator->_arg_index == iterator->overrides[i].field) {
00184 *align = iterator->overrides[i].align;
00185 *size = iterator->overrides[i].size;
00186 if (!*align)
00187 return 0;
00188 return 1;
00189 }
00190 }
00191
00192 return 0;
00193 }
00194 #endif
00195
00196
00220 int ieee80211_radiotap_iterator_next(
00221 struct ieee80211_radiotap_iterator *iterator)
00222 {
00223 while (1) {
00224 int hit = 0;
00225 int pad, align, size, subns, vnslen;
00226 uint32_t oui;
00227
00228
00229 if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT &&
00230 !(iterator->_bitmap_shifter & 1))
00231 return -ENOENT;
00232
00233 if (!(iterator->_bitmap_shifter & 1))
00234 goto next_entry;
00235
00236
00237 switch (iterator->_arg_index % 32) {
00238 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
00239 case IEEE80211_RADIOTAP_EXT:
00240 align = 1;
00241 size = 0;
00242 break;
00243 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
00244 align = 2;
00245 size = 6;
00246 break;
00247 default:
00248 #ifdef RADIOTAP_SUPPORT_OVERRIDES
00249 if (find_override(iterator, &align, &size)) {
00250
00251 } else
00252 #endif
00253 if (!iterator->current_namespace ||
00254 iterator->_arg_index >= iterator->current_namespace->n_bits) {
00255 if (iterator->current_namespace == &radiotap_ns)
00256 return -ENOENT;
00257 align = 0;
00258 } else {
00259 align = iterator->current_namespace->align_size[iterator->_arg_index].align;
00260 size = iterator->current_namespace->align_size[iterator->_arg_index].size;
00261 }
00262 if (!align) {
00263
00264 iterator->_arg = iterator->_next_ns_data;
00265
00266 iterator->current_namespace = NULL;
00267 goto next_entry;
00268 }
00269 break;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 pad = ((unsigned long)iterator->_arg -
00285 (unsigned long)iterator->_rtheader) & (align - 1);
00286
00287 if (pad)
00288 iterator->_arg += align - pad;
00289
00290
00291
00292
00293
00294 iterator->this_arg_index = iterator->_arg_index;
00295 iterator->this_arg = iterator->_arg;
00296 iterator->this_arg_size = size;
00297
00298
00299 iterator->_arg += size;
00300
00301
00302
00303
00304
00305
00306
00307
00308 if ((unsigned long)iterator->_arg -
00309 (unsigned long)iterator->_rtheader >
00310 (unsigned long)iterator->_max_length)
00311 return -EINVAL;
00312
00313
00314 switch (iterator->_arg_index % 32) {
00315 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
00316 iterator->_bitmap_shifter >>= 1;
00317 iterator->_arg_index++;
00318
00319 iterator->_reset_on_ext = 1;
00320
00321 vnslen = get_unaligned_le16(iterator->this_arg + 4);
00322 iterator->_next_ns_data = iterator->_arg + vnslen;
00323 oui = (*iterator->this_arg << 16) |
00324 (*(iterator->this_arg + 1) << 8) |
00325 *(iterator->this_arg + 2);
00326 subns = *(iterator->this_arg + 3);
00327
00328 find_ns(iterator, oui, subns);
00329
00330 iterator->is_radiotap_ns = 0;
00331
00332 iterator->this_arg_index =
00333 IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
00334 iterator->this_arg_size += vnslen;
00335 if ((unsigned long)iterator->this_arg +
00336 iterator->this_arg_size -
00337 (unsigned long)iterator->_rtheader >
00338 (unsigned long)(unsigned long)iterator->_max_length)
00339 return -EINVAL;
00340 hit = 1;
00341 break;
00342 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
00343 iterator->_bitmap_shifter >>= 1;
00344 iterator->_arg_index++;
00345
00346 iterator->_reset_on_ext = 1;
00347 iterator->current_namespace = &radiotap_ns;
00348 iterator->is_radiotap_ns = 1;
00349 break;
00350 case IEEE80211_RADIOTAP_EXT:
00351
00352
00353
00354
00355 iterator->_bitmap_shifter =
00356 get_unaligned_le32(iterator->_next_bitmap);
00357 iterator->_next_bitmap++;
00358 if (iterator->_reset_on_ext)
00359 iterator->_arg_index = 0;
00360 else
00361 iterator->_arg_index++;
00362 iterator->_reset_on_ext = 0;
00363 break;
00364 default:
00365
00366 hit = 1;
00367 next_entry:
00368 iterator->_bitmap_shifter >>= 1;
00369 iterator->_arg_index++;
00370 }
00371
00372
00373 if (hit)
00374 return 0;
00375 }
00376 }