source: lib/link_wireless.c @ 52c7cda

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

Added support for skipping Linux SLL headers to the trace_get_wireless functions, which means we can now use them on tcpdump captured traces.
Also reformatted link_wireless.c and cleaned up all of the compile warnings :)
Made trace_get_payload_from_linux_sll not static and added function prototypes for it and the new arphrd functions to libtrace_int.h

  • Property mode set to 100644
File size: 15.6 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        void *l;
174        uint16_t type;
175        if (link == NULL || tsft == NULL) return false;
176
177        switch (linktype) {
178                case TRACE_TYPE_80211_RADIO:
179                        if( (p = (uint64_t *) trace_get_radiotap_field(link, 
180                                                        TRACE_RADIOTAP_TSFT))) {
181                                *tsft = bswap_le_to_host64(*p);
182                                return true;
183                        } else break;
184                case TRACE_TYPE_LINUX_SLL:
185                        l = trace_get_payload_from_linux_sll(link, &type, NULL );
186                        return trace_get_wireless_tsft(l, arphrd_type_to_libtrace(type), tsft);
187
188                case TRACE_TYPE_80211_PRISM:
189                        return false;
190                default:
191                        return false;
192        }
193        return false;
194}
195
196DLLEXPORT bool trace_get_wireless_flags(void *link, 
197                libtrace_linktype_t linktype, uint8_t *flags)
198{
199        uint8_t *p;
200        void *l;
201        uint16_t type;
202
203        if (link == NULL || flags == NULL) return false;
204
205        switch(linktype) {
206                case TRACE_TYPE_80211_RADIO:
207                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
208                                                        TRACE_RADIOTAP_FLAGS))) {
209                                *flags = *p;
210                                return true;
211                        } else break;
212                case TRACE_TYPE_LINUX_SLL:
213                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
214                        return trace_get_wireless_flags(l, arphrd_type_to_libtrace(type), flags);
215                default:
216                        return false;
217        }
218        return false;
219}
220
221DLLEXPORT bool trace_get_wireless_rate(void *link, 
222                libtrace_linktype_t linktype, uint8_t *rate)
223{
224        uint8_t * p;
225        void *l;
226        uint16_t type;
227
228        if (link == NULL || rate == NULL) return false ;
229        switch (linktype) {
230                case TRACE_TYPE_80211_RADIO:
231                        if ( (p = (uint8_t *) trace_get_radiotap_field(link,
232                                                        TRACE_RADIOTAP_RATE))) {
233                                *rate = *p;
234                                return true;
235                        } else break;
236                case TRACE_TYPE_LINUX_SLL:
237                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
238                        return trace_get_wireless_rate(l, arphrd_type_to_libtrace(type), rate);
239                default:
240                        return false;
241        }
242        return false;
243}
244
245DLLEXPORT bool trace_get_wireless_freq(void *link, 
246                libtrace_linktype_t linktype, uint16_t *freq)
247{
248        uint16_t *p;
249        void *l;
250        uint16_t type;
251
252        if (link == NULL || freq == 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_freq field is the first of those two, so we
257                         * just cast it to a uint16_t.
258                         */
259                        if (( p = (uint16_t *) trace_get_radiotap_field(link,
260                                                        TRACE_RADIOTAP_CHANNEL))) {
261                                *freq = bswap_le_to_host16(*p);
262                                return true;
263                        } else break;
264                case TRACE_TYPE_LINUX_SLL:
265                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
266                        return trace_get_wireless_freq(l, arphrd_type_to_libtrace(type), freq);
267                default:
268                        return false;
269        }
270        return false;
271}
272
273DLLEXPORT bool trace_get_wireless_channel_flags(void *link,
274                libtrace_linktype_t linktype, uint16_t *flags)
275{
276        uint16_t *p;
277        void *l;
278        uint16_t type;
279        if (link == NULL || flags == NULL) return false;
280        switch (linktype) {
281                case TRACE_TYPE_80211_RADIO:
282                        /* NB: The channel field is actually two 16 bit fields.
283                         * The chan_flags field is the second of the two, so we need
284                         * to take the pointer returned by getting the channel field
285                         * and increment it.
286                         */
287                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
288                                                        TRACE_RADIOTAP_CHANNEL))) {
289                                *flags = bswap_le_to_host16(*(++p));
290                                return true;
291                        } else break;
292                case TRACE_TYPE_LINUX_SLL:
293                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
294                        return trace_get_wireless_channel_flags(l, arphrd_type_to_libtrace(type), flags);
295                default:
296                        return false;
297        }
298        return false;
299}
300
301DLLEXPORT bool trace_get_wireless_fhss_hopset(void *link,
302                libtrace_linktype_t linktype, uint8_t *hopset)
303{
304        uint8_t *p;
305        void *l;
306        uint16_t type;
307
308        if (link == NULL || hopset == NULL) return false;
309        switch(linktype) {
310                case TRACE_TYPE_80211_RADIO:
311                        /* NB: As above with the channel field, the fhss field is
312                         * similar.
313                         */
314                        if( (p = (uint8_t *) trace_get_radiotap_field(link,
315                                                        TRACE_RADIOTAP_FHSS))) {
316                                *hopset = *p;
317                                return true;
318                        } else break;
319                case TRACE_TYPE_LINUX_SLL:
320                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
321                        return trace_get_wireless_fhss_hopset(l, arphrd_type_to_libtrace(type), hopset);
322                default:
323                        return false;
324        }
325        return false;
326}
327
328DLLEXPORT bool trace_get_wireless_fhss_hoppattern(void *link,
329                libtrace_linktype_t linktype, uint8_t *hoppattern)
330{
331        uint8_t *p;
332        void *l;
333        uint16_t type;
334        if (link == NULL || hoppattern == NULL) return false;
335        switch (linktype) {
336                case TRACE_TYPE_80211_RADIO:
337                        if((p = (uint8_t *) trace_get_radiotap_field(link,
338                                                        TRACE_RADIOTAP_FHSS))) {
339                                *hoppattern = *(++p);
340                                return true;
341                        } else break;
342                case TRACE_TYPE_LINUX_SLL:
343                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
344                        return trace_get_wireless_fhss_hoppattern(l, arphrd_type_to_libtrace(type), hoppattern);
345                default:
346                        return false;
347        }
348        return false;
349}
350
351DLLEXPORT bool trace_get_wireless_signal_strength_dbm(void *link,
352                libtrace_linktype_t linktype, int8_t *strength)
353{
354        int8_t *p;
355        void *l;
356        uint16_t type;
357
358        if (link == NULL || strength == NULL) return false;
359        switch(linktype) {
360                case TRACE_TYPE_80211_RADIO:
361                        if ((p =  (int8_t *) trace_get_radiotap_field(link,
362                                                        TRACE_RADIOTAP_DBM_ANTSIGNAL))) {
363                                *strength = *p;
364                                return true;
365                        } else break;
366                case TRACE_TYPE_LINUX_SLL:
367                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
368                        return trace_get_wireless_signal_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
369                default:
370                        return false;
371        }
372        return false;
373}
374
375DLLEXPORT bool trace_get_wireless_noise_strength_dbm(void *link,
376                libtrace_linktype_t linktype, int8_t *strength)
377{
378        uint8_t *p;
379        void *l;
380        uint16_t type;
381
382        if (link == NULL || strength == NULL) return false;
383        switch (linktype) {
384                case TRACE_TYPE_80211_RADIO:
385                        if (( p = (int8_t *) trace_get_radiotap_field(link,
386                                                        TRACE_RADIOTAP_DBM_ANTNOISE))) {
387                                *strength = *p;
388                                return true;
389                        } else break;
390                case TRACE_TYPE_LINUX_SLL:
391                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
392                        return trace_get_wireless_noise_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
393                default:
394                        return false;
395        }
396        return false;
397}
398
399DLLEXPORT bool trace_get_wireless_signal_strength_db(void *link,
400                libtrace_linktype_t linktype, uint8_t *strength)
401{
402        uint8_t *p;
403        void *l;
404        uint16_t type;
405
406        if (link == NULL || strength == NULL) return false;
407        switch (linktype) {
408                case TRACE_TYPE_80211_RADIO:
409                        if ((p =  (uint8_t *) trace_get_radiotap_field(link,
410                                                        TRACE_RADIOTAP_DB_ANTSIGNAL))) {
411                                *strength = *p;
412                                return true;
413                        } else break;
414                case TRACE_TYPE_LINUX_SLL:
415                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
416                        return trace_get_wireless_signal_strength_db(l, arphrd_type_to_libtrace(type), strength);
417                default:
418                        return false;
419        }
420        return false ;
421}
422
423DLLEXPORT bool trace_get_wireless_noise_strength_db(void *link,
424                libtrace_linktype_t linktype, uint8_t *strength)
425{
426        uint8_t *p;
427        void *l;
428        uint16_t type;
429
430        if (link == NULL || strength == NULL) return false;
431        switch (linktype) {
432                case TRACE_TYPE_80211_RADIO:
433                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
434                                                        TRACE_RADIOTAP_DB_ANTNOISE))) {
435                                *strength = *p;
436                                return true;
437                        } else break;
438                case TRACE_TYPE_LINUX_SLL:
439                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
440                        return trace_get_wireless_noise_strength_db(l, arphrd_type_to_libtrace(type), strength);
441                default:
442                        return false;
443        }
444        return false;
445}
446
447DLLEXPORT bool trace_get_wireless_lock_quality(void *link,
448                libtrace_linktype_t linktype, uint16_t *quality)
449{
450        uint16_t *p;
451        void *l;
452        uint16_t type;
453
454        if (link == NULL || quality == NULL) return false;
455        switch (linktype) {
456                case TRACE_TYPE_80211_RADIO:
457                        if((p = (uint16_t *) trace_get_radiotap_field(link,
458                                                        TRACE_RADIOTAP_LOCK_QUALITY))) {
459                                *quality = bswap_le_to_host16(*p);
460                                return true;
461                        } else break;
462                case TRACE_TYPE_LINUX_SLL:
463                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
464                        return trace_get_wireless_lock_quality(l, arphrd_type_to_libtrace(type), quality);
465                default:
466                        return false;
467        }
468        return false;
469}
470
471DLLEXPORT bool trace_get_wireless_tx_attenuation(void *link,
472                libtrace_linktype_t linktype, uint16_t *attenuation)
473{
474        uint16_t *p;
475        void *l;
476        uint16_t type;
477
478        if (link == NULL || attenuation == 0) return false;
479        switch (linktype) {
480                case TRACE_TYPE_80211_RADIO:
481                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
482                                                        TRACE_RADIOTAP_TX_ATTENUATION))) {
483                                *attenuation = 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_tx_attenuation(l, arphrd_type_to_libtrace(type), attenuation);
489                default:
490                        return false;
491        }
492        return false;
493}
494
495DLLEXPORT bool trace_get_wireless_tx_attenuation_db(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 == NULL) return false;
503        switch (linktype) {
504                case TRACE_TYPE_80211_RADIO:
505                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
506                                                        TRACE_RADIOTAP_DB_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_db(l, arphrd_type_to_libtrace(type), attenuation);
513                default:
514                        return false;
515        }
516        return false;
517}
518
519DLLEXPORT bool trace_get_wireless_tx_power_dbm(void *link,
520                libtrace_linktype_t linktype, int8_t *txpower)
521{
522        int8_t *p;
523        void *l;
524        uint16_t type;
525
526        if (link == NULL || txpower == NULL) return false;
527        switch (linktype) {
528                case TRACE_TYPE_80211_RADIO:
529                        if ((p=(int8_t *) trace_get_radiotap_field(link,
530                                                        TRACE_RADIOTAP_DBM_TX_POWER))) {
531                                *txpower = *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_power_dbm(l, arphrd_type_to_libtrace(type), txpower);
537                default:
538                        return false;
539        }
540        return false;
541}
542
543
544DLLEXPORT bool trace_get_wireless_antenna(void *link,
545                libtrace_linktype_t linktype, uint8_t *antenna)
546{
547        uint8_t *p;
548        void *l;
549        uint16_t type;
550
551        if (link == NULL || antenna == NULL) return false;
552        switch (linktype) {
553                case TRACE_TYPE_80211_RADIO:
554                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
555                                                        TRACE_RADIOTAP_ANTENNA))) {
556                                *antenna = *p;
557                                return true;
558                        } else break;
559                case TRACE_TYPE_LINUX_SLL:
560                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
561                        return trace_get_wireless_antenna(l, arphrd_type_to_libtrace(type), antenna);
562                default:
563                        return false;
564        }
565        return false;
566}
567
568DLLEXPORT bool trace_get_wireless_fcs(void *link,
569                libtrace_linktype_t linktype, uint32_t *fcs)
570{
571        uint32_t *p;
572        void *l;
573        uint16_t type;
574
575        if (link == NULL || fcs == NULL) return false;
576        switch (linktype) {
577                case TRACE_TYPE_80211_RADIO:
578                        if ((p = (uint32_t *) trace_get_radiotap_field(link,
579                                                        TRACE_RADIOTAP_FCS))) {
580                                *fcs = bswap_le_to_host32(*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_fcs(l, arphrd_type_to_libtrace(type), fcs);
586                default:
587                        return false;
588        }
589        return false;
590}
591
Note: See TracBrowser for help on using the repository browser.