source: lib/link_wireless.c @ f0c639b

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since f0c639b was f0c639b, checked in by Scott Raynel <smr26@…>, 14 years ago
  • Remove trace_get_wireless_fcs as it is no longer part of the Radiotap standard.
  • Update trace_get_wire_length to account for the presence (or absence) of FCS bytes at the end of wireless frames. (only pcap and pcapfile for now)
  • Update radiotap libpacketdump decoder to no longer output non-standard FCS field.
  • Update test-wireless to ensure new length functions work correctly.
  • Property mode set to 100644
File size: 16.3 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) 2007 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 ((bswap_le_to_host32(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 ( bswap_le_to_host32(*((uint32_t*)p)) & (1U << 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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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 (bswap_le_to_host32(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        /*
159        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DB_ANTNOISE))
160                p+= sizeof (uint8_t);
161        */
162
163        /* Unknown field */
164        return NULL;
165} 
166
167DLLEXPORT bool trace_get_wireless_tsft(void *link, 
168                libtrace_linktype_t linktype, uint64_t *tsft)
169{
170        uint64_t *p;
171        void *l;
172        uint16_t type;
173        if (link == NULL || tsft == NULL) return false;
174
175        switch (linktype) {
176                case TRACE_TYPE_80211_RADIO:
177                        if( (p = (uint64_t *) trace_get_radiotap_field(link, 
178                                                        TRACE_RADIOTAP_TSFT))) {
179                                *tsft = bswap_le_to_host64(*p);
180                                return true;
181                        } else break;
182                case TRACE_TYPE_LINUX_SLL:
183                        l = trace_get_payload_from_linux_sll(link, &type, NULL );
184                        return trace_get_wireless_tsft(l, arphrd_type_to_libtrace(type), tsft);
185
186                case TRACE_TYPE_80211_PRISM:
187                        return false;
188                default:
189                        return false;
190        }
191        return false;
192}
193
194/*
195 * This function isn't portable across drivers, so has been left static
196 * for now. Maybe it will be included in the API later if it becomes useful
197 * and we come up with a suitable abstraction.
198 * This function isn't marked static as the various format modules need to
199 * access it for get_wire_length(). It's not meant to be exported though.
200 */
201bool trace_get_wireless_flags(void *link, 
202                libtrace_linktype_t linktype, uint8_t *flags)
203{
204        uint8_t *p;
205        void *l;
206        uint16_t type;
207
208        if (link == NULL || flags == NULL) return false;
209
210        switch(linktype) {
211                case TRACE_TYPE_80211_RADIO:
212                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
213                                                        TRACE_RADIOTAP_FLAGS))) {
214                                *flags = *p;
215                                return true;
216                        } else break;
217                case TRACE_TYPE_LINUX_SLL:
218                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
219                        return trace_get_wireless_flags(l, arphrd_type_to_libtrace(type), flags);
220                default:
221                        return false;
222        }
223        return false;
224}
225
226DLLEXPORT bool trace_get_wireless_rate(void *link, 
227                libtrace_linktype_t linktype, uint8_t *rate)
228{
229        uint8_t * p;
230        void *l;
231        uint16_t type;
232
233        if (link == NULL || rate == NULL) return false ;
234        switch (linktype) {
235                case TRACE_TYPE_80211_RADIO:
236                        if ( (p = (uint8_t *) trace_get_radiotap_field(link,
237                                                        TRACE_RADIOTAP_RATE))) {
238                                *rate = *p;
239                                return true;
240                        } else break;
241                case TRACE_TYPE_LINUX_SLL:
242                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
243                        return trace_get_wireless_rate(l, arphrd_type_to_libtrace(type), rate);
244                default:
245                        return false;
246        }
247        return false;
248}
249
250DLLEXPORT bool trace_get_wireless_freq(void *link, 
251                libtrace_linktype_t linktype, uint16_t *freq)
252{
253        uint16_t *p;
254        void *l;
255        uint16_t type;
256
257        if (link == NULL || freq == NULL) return false;
258        switch (linktype) {
259                case TRACE_TYPE_80211_RADIO:
260                        /* NB: The channel field is actually two 16 bit fields.
261                         * The chan_freq field is the first of those two, so we
262                         * just cast it to a uint16_t.
263                         */
264                        if (( p = (uint16_t *) trace_get_radiotap_field(link,
265                                                        TRACE_RADIOTAP_CHANNEL))) {
266                                *freq = bswap_le_to_host16(*p);
267                                return true;
268                        } else break;
269                case TRACE_TYPE_LINUX_SLL:
270                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
271                        return trace_get_wireless_freq(l, arphrd_type_to_libtrace(type), freq);
272                default:
273                        return false;
274        }
275        return false;
276}
277
278/*
279 * This function isn't portable across drivers, so has been left static
280 * for now. Maybe it will be included in the API later if it becomes useful
281 * and we come up with a suitable abstraction.
282 */
283static
284bool trace_get_wireless_channel_flags(void *link,
285                libtrace_linktype_t linktype, uint16_t *flags)
286{
287        uint16_t *p;
288        void *l;
289        uint16_t type;
290        if (link == NULL || flags == NULL) return false;
291        switch (linktype) {
292                case TRACE_TYPE_80211_RADIO:
293                        /* NB: The channel field is actually two 16 bit fields.
294                         * The chan_flags field is the second of the two, so we need
295                         * to take the pointer returned by getting the channel field
296                         * and increment it.
297                         */
298                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
299                                                        TRACE_RADIOTAP_CHANNEL))) {
300                                *flags = bswap_le_to_host16(*(++p));
301                                return true;
302                        } else break;
303                case TRACE_TYPE_LINUX_SLL:
304                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
305                        return trace_get_wireless_channel_flags(l, arphrd_type_to_libtrace(type), flags);
306                default:
307                        return false;
308        }
309        return false;
310}
311
312/* Not sure that this function is useful for now - who uses FHSS?
313 * This might get exported in the future if it becomes useful
314 */
315static
316bool trace_get_wireless_fhss_hopset(void *link,
317                libtrace_linktype_t linktype, uint8_t *hopset)
318{
319        uint8_t *p;
320        void *l;
321        uint16_t type;
322
323        if (link == NULL || hopset == NULL) return false;
324        switch(linktype) {
325                case TRACE_TYPE_80211_RADIO:
326                        /* NB: As above with the channel field, the fhss field is
327                         * similar.
328                         */
329                        if( (p = (uint8_t *) trace_get_radiotap_field(link,
330                                                        TRACE_RADIOTAP_FHSS))) {
331                                *hopset = *p;
332                                return true;
333                        } else break;
334                case TRACE_TYPE_LINUX_SLL:
335                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
336                        return trace_get_wireless_fhss_hopset(l, arphrd_type_to_libtrace(type), hopset);
337                default:
338                        return false;
339        }
340        return false;
341}
342
343/* Not sure that this function is useful for now - who uses FHSS?
344 * This might get exported in the future if it becomes useful
345 */
346static
347bool trace_get_wireless_fhss_hoppattern(void *link,
348                libtrace_linktype_t linktype, uint8_t *hoppattern)
349{
350        uint8_t *p;
351        void *l;
352        uint16_t type;
353        if (link == NULL || hoppattern == NULL) return false;
354        switch (linktype) {
355                case TRACE_TYPE_80211_RADIO:
356                        if((p = (uint8_t *) trace_get_radiotap_field(link,
357                                                        TRACE_RADIOTAP_FHSS))) {
358                                *hoppattern = *(++p);
359                                return true;
360                        } else break;
361                case TRACE_TYPE_LINUX_SLL:
362                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
363                        return trace_get_wireless_fhss_hoppattern(l, arphrd_type_to_libtrace(type), hoppattern);
364                default:
365                        return false;
366        }
367        return false;
368}
369
370DLLEXPORT bool trace_get_wireless_signal_strength_dbm(void *link,
371                libtrace_linktype_t linktype, int8_t *strength)
372{
373        int8_t *p;
374        void *l;
375        uint16_t type;
376
377        if (link == NULL || strength == NULL) return false;
378        switch(linktype) {
379                case TRACE_TYPE_80211_RADIO:
380                        if ((p =  (int8_t *) trace_get_radiotap_field(link,
381                                                        TRACE_RADIOTAP_DBM_ANTSIGNAL))) {
382                                *strength = *p;
383                                return true;
384                        } else break;
385                case TRACE_TYPE_LINUX_SLL:
386                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
387                        return trace_get_wireless_signal_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
388                default:
389                        return false;
390        }
391        return false;
392}
393
394DLLEXPORT bool trace_get_wireless_noise_strength_dbm(void *link,
395                libtrace_linktype_t linktype, int8_t *strength)
396{
397        uint8_t *p;
398        void *l;
399        uint16_t type;
400
401        if (link == NULL || strength == NULL) return false;
402        switch (linktype) {
403                case TRACE_TYPE_80211_RADIO:
404                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
405                                        TRACE_RADIOTAP_DBM_ANTNOISE))) {
406                                *strength = *p;
407                                return true;
408                        } else break;
409                case TRACE_TYPE_LINUX_SLL:
410                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
411                        return trace_get_wireless_noise_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
412                default:
413                        return false;
414        }
415        return false;
416}
417
418DLLEXPORT bool trace_get_wireless_signal_strength_db(void *link,
419                libtrace_linktype_t linktype, uint8_t *strength)
420{
421        uint8_t *p;
422        void *l;
423        uint16_t type;
424
425        if (link == NULL || strength == NULL) return false;
426        switch (linktype) {
427                case TRACE_TYPE_80211_RADIO:
428                        if ((p =  (uint8_t *) trace_get_radiotap_field(link,
429                                                        TRACE_RADIOTAP_DB_ANTSIGNAL))) {
430                                *strength = *p;
431                                return true;
432                        } else break;
433                case TRACE_TYPE_LINUX_SLL:
434                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
435                        return trace_get_wireless_signal_strength_db(l, arphrd_type_to_libtrace(type), strength);
436                default:
437                        return false;
438        }
439        return false ;
440}
441
442DLLEXPORT bool trace_get_wireless_noise_strength_db(void *link,
443                libtrace_linktype_t linktype, uint8_t *strength)
444{
445        uint8_t *p;
446        void *l;
447        uint16_t type;
448
449        if (link == NULL || strength == NULL) return false;
450        switch (linktype) {
451                case TRACE_TYPE_80211_RADIO:
452                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
453                                                        TRACE_RADIOTAP_DB_ANTNOISE))) {
454                                *strength = *p;
455                                return true;
456                        } else break;
457                case TRACE_TYPE_LINUX_SLL:
458                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
459                        return trace_get_wireless_noise_strength_db(l, arphrd_type_to_libtrace(type), strength);
460                default:
461                        return false;
462        }
463        return false;
464}
465
466/* Not sure if this function is useful. As the radiotap documentation says,
467 * there's no set metric for defining the quality of the Barker Code Lock.
468 * Maybe it will be exported later if it becomes useful.
469 */
470static
471bool trace_get_wireless_lock_quality(void *link,
472                libtrace_linktype_t linktype, uint16_t *quality)
473{
474        uint16_t *p;
475        void *l;
476        uint16_t type;
477
478        if (link == NULL || quality == NULL) return false;
479        switch (linktype) {
480                case TRACE_TYPE_80211_RADIO:
481                        if((p = (uint16_t *) trace_get_radiotap_field(link,
482                                                        TRACE_RADIOTAP_LOCK_QUALITY))) {
483                                *quality = bswap_le_to_host16(*p);
484                                return true;
485                        } else break;
486                case TRACE_TYPE_LINUX_SLL:
487                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
488                        return trace_get_wireless_lock_quality(l, arphrd_type_to_libtrace(type), quality);
489                default:
490                        return false;
491        }
492        return false;
493}
494
495DLLEXPORT bool trace_get_wireless_tx_attenuation(void *link,
496                libtrace_linktype_t linktype, uint16_t *attenuation)
497{
498        uint16_t *p;
499        void *l;
500        uint16_t type;
501
502        if (link == NULL || attenuation == 0) return false;
503        switch (linktype) {
504                case TRACE_TYPE_80211_RADIO:
505                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
506                                                        TRACE_RADIOTAP_TX_ATTENUATION))) {
507                                *attenuation = bswap_le_to_host16(*p);
508                                return true;
509                        } else break;
510                case TRACE_TYPE_LINUX_SLL:
511                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
512                        return trace_get_wireless_tx_attenuation(l, arphrd_type_to_libtrace(type), attenuation);
513                default:
514                        return false;
515        }
516        return false;
517}
518
519DLLEXPORT bool trace_get_wireless_tx_attenuation_db(void *link,
520                libtrace_linktype_t linktype, uint16_t *attenuation)
521{
522        uint16_t *p;
523        void *l;
524        uint16_t type;
525
526        if (link == NULL || attenuation == NULL) return false;
527        switch (linktype) {
528                case TRACE_TYPE_80211_RADIO:
529                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
530                                                        TRACE_RADIOTAP_DB_TX_ATTENUATION))) {
531                                *attenuation = bswap_le_to_host16(*p);
532                                return true;
533                        } else break;
534                case TRACE_TYPE_LINUX_SLL:
535                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
536                        return trace_get_wireless_tx_attenuation_db(l, arphrd_type_to_libtrace(type), attenuation);
537                default:
538                        return false;
539        }
540        return false;
541}
542
543DLLEXPORT bool trace_get_wireless_tx_power_dbm(void *link,
544                libtrace_linktype_t linktype, int8_t *txpower)
545{
546        int8_t *p;
547        void *l;
548        uint16_t type;
549
550        if (link == NULL || txpower == NULL) return false;
551        switch (linktype) {
552                case TRACE_TYPE_80211_RADIO:
553                        if ((p=(int8_t *) trace_get_radiotap_field(link,
554                                                        TRACE_RADIOTAP_DBM_TX_POWER))) {
555                                *txpower = *p;
556                                return true;
557                        } else break;
558                case TRACE_TYPE_LINUX_SLL:
559                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
560                        return trace_get_wireless_tx_power_dbm(l, arphrd_type_to_libtrace(type), txpower);
561                default:
562                        return false;
563        }
564        return false;
565}
566
567
568DLLEXPORT bool trace_get_wireless_antenna(void *link,
569                libtrace_linktype_t linktype, uint8_t *antenna)
570{
571        uint8_t *p;
572        void *l;
573        uint16_t type;
574
575        if (link == NULL || antenna == NULL) return false;
576        switch (linktype) {
577                case TRACE_TYPE_80211_RADIO:
578                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
579                                                        TRACE_RADIOTAP_ANTENNA))) {
580                                *antenna = *p;
581                                return true;
582                        } else break;
583                case TRACE_TYPE_LINUX_SLL:
584                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
585                        return trace_get_wireless_antenna(l, arphrd_type_to_libtrace(type), antenna);
586                default:
587                        return false;
588        }
589        return false;
590}
591
Note: See TracBrowser for help on using the repository browser.