source: lib/link_wireless.c @ 6df012d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 6df012d was 6df012d, checked in by Scott Raynel <smr26@…>, 15 years ago

Fix get_payload_from_link for prism and radiotap.
Make sure to use bswap when looking at radiotap length.
Tidy up exported API, don't export get_payload_from_prism or _from_radiotap.

  • Property mode set to 100644
File size: 13.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * link_wireless.c
5 * Implements the trace_get_wireless_* methods defined in libtrace.h
6 *
7 * Copyright (c) 2006 The University of Waikato, Hamilton, New Zealand.
8 * Authors: Scott Raynel
9 *          Perry Lorier
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 */
31
32#include "libtrace.h"
33#include "libtrace_int.h"
34
35/* Used for Radiotap fields which must be naturally aligned */
36#define ALIGN_NATURAL_64(_p,_s) \
37    while ( (_p - _s) % sizeof(uint64_t)) _p++
38#define ALIGN_NATURAL_32(_p,_s) \
39    while ( (_p - _s) % sizeof(uint32_t)) _p++
40#define ALIGN_NATURAL_16(_p,_s) \
41    while ( (_p - _s) % sizeof(uint16_t)) _p++
42
43/** Gets a field from a Radiotap header.
44 * @param link the radiotap header
45 * @param field the radiotap field we want to access
46 * @return a void pointer to the field. It is up to the caller to cast to the
47 * appropriate type.
48 * @note Radiotap fields are always little-endian
49 */
50static void *trace_get_radiotap_field(void *link, libtrace_radiotap_field_t field)
51{
52    struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t *)link;
53    uint8_t *p;
54    uint8_t *s;
55   
56    /* Check if the field exists in the radiotap header before proceeding
57     */
58    if ((rtap->it_present & (1 << field)) == 0) return NULL;
59
60    /* Skip over any extended bitmasks */
61    p = (uint8_t *) &(rtap->it_present);
62   
63    while ( *((uint32_t*)p) & (1 << TRACE_RADIOTAP_EXT) ) {
64        p += sizeof (uint32_t);
65    }
66
67    /* Point p at the first field of radiotap data and remember it for later
68     * when we're doing field alignment
69     */
70    p += sizeof(uint32_t);
71    s = p;
72   
73    if (field == TRACE_RADIOTAP_TSFT) 
74        /* Always aligned */
75        return (void*)p;
76    if (rtap->it_present & (1 << TRACE_RADIOTAP_TSFT))
77        p += sizeof (uint64_t);
78
79    if (field == TRACE_RADIOTAP_FLAGS)
80        /* Always aligned */
81        return (void*)p;
82    if (rtap->it_present & (1 << TRACE_RADIOTAP_FLAGS))
83        p += sizeof (uint8_t);
84
85    if (field == TRACE_RADIOTAP_RATE)
86        /* Always aligned */
87        return (void*)p;
88    if (rtap->it_present & (1 << TRACE_RADIOTAP_RATE))
89        p+= sizeof (uint8_t);
90
91    if (field == TRACE_RADIOTAP_CHANNEL)
92    {
93        ALIGN_NATURAL_16(p,s);
94        return (void *)p;
95    }
96    if (rtap->it_present & (1 << TRACE_RADIOTAP_CHANNEL))
97        p+= sizeof (uint32_t);
98
99    if (field == TRACE_RADIOTAP_FHSS)
100    {
101        ALIGN_NATURAL_16(p,s);
102        return (void *)p;
103    }
104    if (rtap->it_present & (1 << TRACE_RADIOTAP_FHSS))
105        p+= sizeof (uint16_t);
106
107    if (field == TRACE_RADIOTAP_DBM_ANTSIGNAL)
108        return (void *)p;
109    if (rtap->it_present & (1 << TRACE_RADIOTAP_DBM_ANTSIGNAL))
110        p+= sizeof (uint8_t);
111
112    if (field == TRACE_RADIOTAP_DBM_ANTNOISE)
113        return (void *)p;
114    if (rtap->it_present & (1 << TRACE_RADIOTAP_DBM_ANTNOISE))
115        p+= sizeof (uint8_t);
116
117    if (field == TRACE_RADIOTAP_LOCK_QUALITY)
118    {
119        ALIGN_NATURAL_16(p,s);
120        return (void *)p;
121    }
122    if (rtap->it_present & (1 << TRACE_RADIOTAP_LOCK_QUALITY))
123        p+= sizeof (uint16_t);
124
125    if (field == TRACE_RADIOTAP_TX_ATTENUATION)
126    {
127        ALIGN_NATURAL_16(p,s);
128        return (void *)p;
129    }
130    if (rtap->it_present & (1 << TRACE_RADIOTAP_TX_ATTENUATION))
131        p+= sizeof (uint16_t);
132
133    if (field == TRACE_RADIOTAP_DB_TX_ATTENUATION)
134    {
135        ALIGN_NATURAL_16(p,s);
136        return (void *)p;
137    }
138    if (rtap->it_present & (1 << TRACE_RADIOTAP_DB_TX_ATTENUATION))
139        p+= sizeof (uint16_t);
140
141    if (field == TRACE_RADIOTAP_DBM_TX_POWER)
142        return (void *)p;
143    if (rtap->it_present & (1 << TRACE_RADIOTAP_DBM_TX_POWER))
144        p+= sizeof (uint8_t);
145   
146    if (field == TRACE_RADIOTAP_ANTENNA)
147        return (void *)p;
148    if (rtap->it_present & (1 << TRACE_RADIOTAP_ANTENNA))
149        p+= sizeof (uint8_t);
150
151    if (field == TRACE_RADIOTAP_DB_ANTSIGNAL)
152        return (void *)p;
153    if (rtap->it_present & (1 << TRACE_RADIOTAP_DB_ANTSIGNAL))
154        p+= sizeof (uint8_t);
155
156    if (field == TRACE_RADIOTAP_DB_ANTNOISE)
157        return (void *) p;
158    if (rtap->it_present & (1 << TRACE_RADIOTAP_DB_ANTNOISE))
159        p+= sizeof (uint8_t);
160   
161    if (field == TRACE_RADIOTAP_FCS)
162        ALIGN_NATURAL_32(p,s);
163        return (void *)p;
164
165    /* Unknown field */
166    return NULL;
167} 
168   
169DLLEXPORT bool trace_get_wireless_tsft(void *link, 
170        libtrace_linktype_t linktype, uint64_t *tsft)
171{
172    uint64_t *p;
173
174    if (link == NULL || tsft == NULL) return false;
175
176    switch (linktype) {
177        case TRACE_TYPE_80211_RADIO:
178            if( p = (uint64_t *) trace_get_radiotap_field(link, 
179                        TRACE_RADIOTAP_TSFT)) {
180                *tsft = bswap_le_to_host64(*p);
181                return true;
182            } else break;
183           
184        case TRACE_TYPE_80211_PRISM:
185            return false;
186    }
187    /* Unsupported link type */
188    return false;
189}
190
191DLLEXPORT bool trace_get_wireless_flags(void *link, 
192        libtrace_linktype_t linktype, uint8_t *flags)
193{
194    uint8_t *p;
195   
196    if (link == NULL || flags == NULL) return false;
197   
198    switch(linktype) {
199        case TRACE_TYPE_80211_RADIO:
200            if ( p = (uint8_t *) trace_get_radiotap_field(link,
201                TRACE_RADIOTAP_FLAGS)) {
202                *flags = *p;
203                return true;
204            } else break;
205    }
206    /* Unsupported link type */
207    return false;
208}
209
210DLLEXPORT bool trace_get_wireless_rate(void *link, 
211        libtrace_linktype_t linktype, uint8_t *rate)
212{
213    uint8_t * p;
214    if (link == NULL || rate == NULL) return false ;
215    switch (linktype) {
216        case TRACE_TYPE_80211_RADIO:
217            if ( p = (uint8_t *) trace_get_radiotap_field(link,
218                TRACE_RADIOTAP_RATE)) {
219                *rate = *p;
220                return true;
221            } else break;
222           
223    }
224    return false;
225}
226
227DLLEXPORT bool trace_get_wireless_freq(void *link, 
228        libtrace_linktype_t linktype, uint16_t *freq)
229{
230    uint16_t *p;
231
232    if (link == NULL || freq == NULL) return false;
233    switch (linktype) {
234        case TRACE_TYPE_80211_RADIO:
235            /* NB: The channel field is actually two 16 bit fields.
236             * The chan_freq field is the first of those two, so we
237             * just cast it to a uint16_t.
238             */
239            if ( p = (uint16_t *) trace_get_radiotap_field(link,
240                    TRACE_RADIOTAP_CHANNEL)) {
241                *freq = bswap_le_to_host16(*p);
242                return true;
243            } else break;
244    }
245    return false;
246}
247   
248DLLEXPORT bool trace_get_wireless_channel_flags(void *link,
249        libtrace_linktype_t linktype, uint16_t *flags)
250{
251    uint16_t *p;
252    if (link == NULL || flags == NULL) return false;
253    switch (linktype) {
254        case TRACE_TYPE_80211_RADIO:
255            /* NB: The channel field is actually two 16 bit fields.
256             * The chan_flags field is the second of the two, so we need
257             * to take the pointer returned by getting the channel field
258             * and increment it.
259             */
260            if (p = (uint16_t *) trace_get_radiotap_field(link,
261                    TRACE_RADIOTAP_CHANNEL)) {
262                *flags = bswap_le_to_host16(*(++p));
263                return true;
264            } else break;
265    }
266    return false;
267}
268
269DLLEXPORT bool trace_get_wireless_fhss_hopset(void *link,
270        libtrace_linktype_t linktype, uint8_t *hopset)
271{
272    uint8_t *p;
273   
274    if (link == NULL || hopset == NULL) return false;
275    switch(linktype) {
276        case TRACE_TYPE_80211_RADIO:
277            /* NB: As above with the channel field, the fhss field is
278             * similar.
279             */
280            if( p = (uint8_t *) trace_get_radiotap_field(link,
281                    TRACE_RADIOTAP_FHSS)) {
282                *hopset = *p;
283                return true;
284            } else break;
285    }
286    return false;
287}
288
289DLLEXPORT bool trace_get_wireless_fhss_hoppattern(void *link,
290        libtrace_linktype_t linktype, uint8_t *hoppattern)
291{
292    uint8_t *p;
293    if (link == NULL || hoppattern == NULL) return false;
294    switch (linktype) {
295        case TRACE_TYPE_80211_RADIO:
296            if(p = (uint8_t *) trace_get_radiotap_field(link,
297                    TRACE_RADIOTAP_FHSS)) {
298                *hoppattern = *(++p);
299                return true;
300            } else break;
301    }
302    return false;
303}
304
305DLLEXPORT bool trace_get_wireless_signal_strength_dbm(void *link,
306        libtrace_linktype_t linktype, int8_t *strength)
307{
308    int8_t *p;
309   
310    if (link == NULL || strength == NULL) return false;
311    switch(linktype) {
312        case TRACE_TYPE_80211_RADIO:
313            if (p =  (int8_t *) trace_get_radiotap_field(link,
314                    TRACE_RADIOTAP_DBM_ANTSIGNAL)) {
315                *strength = *p;
316                return true;
317            } else break;
318    }
319    return false;
320}
321
322DLLEXPORT bool trace_get_wireless_noise_strength_dbm(void *link,
323        libtrace_linktype_t linktype, int8_t *strength)
324{
325    uint8_t *p;
326    if (link == NULL || strength == NULL) return false;
327    switch (linktype) {
328        case TRACE_TYPE_80211_RADIO:
329            if ( p = (int8_t *) trace_get_radiotap_field(link,
330                    TRACE_RADIOTAP_DBM_ANTNOISE)) {
331                *strength = *p;
332                return true;
333            } else break;
334    }
335    return false;
336}
337
338DLLEXPORT bool trace_get_wireless_signal_strength_db(void *link,
339        libtrace_linktype_t linktype, uint8_t *strength)
340{
341    uint8_t *p;
342   
343    if (link == NULL || strength == NULL) return false;
344    switch (linktype) {
345        case TRACE_TYPE_80211_RADIO:
346            if (p =  (uint8_t *) trace_get_radiotap_field(link,
347                    TRACE_RADIOTAP_DB_ANTSIGNAL)) {
348                *strength = *p;
349                return true;
350            } else break;
351    }
352    return false ;
353}
354
355DLLEXPORT bool trace_get_wireless_noise_strength_db(void *link,
356        libtrace_linktype_t linktype, uint8_t *strength)
357{
358    uint8_t *p;
359   
360    if (link == NULL || strength == NULL) return false;
361    switch (linktype) {
362        case TRACE_TYPE_80211_RADIO:
363            if (p = (uint8_t *) trace_get_radiotap_field(link,
364                    TRACE_RADIOTAP_DB_ANTNOISE)) {
365                *strength = *p;
366                return true;
367            } else break;
368    }
369    return false;
370}
371
372DLLEXPORT bool trace_get_wireless_lock_quality(void *link,
373        libtrace_linktype_t linktype, uint16_t *quality)
374{
375    uint16_t *p;
376   
377    if (link == NULL || quality == NULL) return false;
378    switch (linktype) {
379        case TRACE_TYPE_80211_RADIO:
380            if(p = (uint16_t *) trace_get_radiotap_field(link,
381                    TRACE_RADIOTAP_LOCK_QUALITY)) {
382                *quality = bswap_le_to_host16(*p);
383                return true;
384            } else break;
385    }
386    return false;
387}
388
389DLLEXPORT bool trace_get_wireless_tx_attenuation(void *link,
390        libtrace_linktype_t linktype, uint16_t *attenuation)
391{
392    uint16_t *p;
393    if (link == NULL || attenuation == 0) return false;
394    switch (linktype) {
395        case TRACE_TYPE_80211_RADIO:
396            if (p = (uint16_t *) trace_get_radiotap_field(link,
397                    TRACE_RADIOTAP_TX_ATTENUATION)) {
398                *attenuation = bswap_le_to_host16(*p);
399                return true;
400            } else break;
401    }
402    return false;
403}
404
405DLLEXPORT bool trace_get_wireless_tx_attenuation_db(void *link,
406        libtrace_linktype_t linktype, uint16_t *attenuation)
407{
408    uint16_t *p;
409    if (link == NULL || attenuation == NULL) return false;
410    switch (linktype) {
411        case TRACE_TYPE_80211_RADIO:
412            if (p = (uint16_t *) trace_get_radiotap_field(link,
413                    TRACE_RADIOTAP_DB_TX_ATTENUATION)) {
414                *attenuation = bswap_le_to_host16(*p);
415                return true;
416            } else break;
417    }
418    return false;
419}
420
421DLLEXPORT bool trace_get_wireless_tx_power_dbm(void *link,
422        libtrace_linktype_t linktype, int8_t *txpower)
423{
424    int8_t *p;
425   
426    if (link == NULL || txpower == NULL) return false;
427    switch (linktype) {
428        case TRACE_TYPE_80211_RADIO:
429            if (p=(int8_t *) trace_get_radiotap_field(link,
430                    TRACE_RADIOTAP_DBM_TX_POWER)) {
431                *txpower = *p;
432                return true;
433            } else break;
434    }
435    return false;
436}
437
438
439DLLEXPORT bool trace_get_wireless_antenna(void *link,
440        libtrace_linktype_t linktype, uint8_t *antenna)
441{
442    uint8_t *p;
443    if (link == NULL || antenna == NULL) return false;
444    switch (linktype) {
445        case TRACE_TYPE_80211_RADIO:
446            if (p = (uint8_t *) trace_get_radiotap_field(link,
447                    TRACE_RADIOTAP_ANTENNA)) {
448                *antenna = *p;
449                return true;
450            } else break;
451    }
452    return false;
453}
454
455DLLEXPORT bool trace_get_wireless_fcs(void *link,
456        libtrace_linktype_t linktype, uint32_t *fcs)
457{
458    uint32_t *p;
459    if (link == NULL || fcs == NULL) return false;
460    switch (linktype) {
461        case TRACE_TYPE_80211_RADIO:
462            if (p = (uint32_t *) trace_get_radiotap_field(link,
463                    TRACE_RADIOTAP_FCS)) {
464                *fcs = bswap_le_to_host32(*p);
465                return true;
466            } else break;
467    }
468    return false;
469}
470
Note: See TracBrowser for help on using the repository browser.