source: lib/link_wireless.c @ d5a27e8

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since d5a27e8 was d5a27e8, checked in by Perry Lorier <perry@…>, 14 years ago

Update the copyright information
Fix libpcap issue
Remove all swig/python builds

  • Property mode set to 100644
File size: 16.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) 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        if (bswap_le_to_host32(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
196/*
197 * This function isn't portable across drivers, so has been left static
198 * for now. Maybe it will be included in the API later if it becomes useful
199 * and we come up with a suitable abstraction.
200 */
201static
202bool trace_get_wireless_flags(void *link, 
203                libtrace_linktype_t linktype, uint8_t *flags)
204{
205        uint8_t *p;
206        void *l;
207        uint16_t type;
208
209        if (link == NULL || flags == NULL) return false;
210
211        switch(linktype) {
212                case TRACE_TYPE_80211_RADIO:
213                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
214                                                        TRACE_RADIOTAP_FLAGS))) {
215                                *flags = *p;
216                                return true;
217                        } else break;
218                case TRACE_TYPE_LINUX_SLL:
219                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
220                        return trace_get_wireless_flags(l, arphrd_type_to_libtrace(type), flags);
221                default:
222                        return false;
223        }
224        return false;
225}
226
227DLLEXPORT bool trace_get_wireless_rate(void *link, 
228                libtrace_linktype_t linktype, uint8_t *rate)
229{
230        uint8_t * p;
231        void *l;
232        uint16_t type;
233
234        if (link == NULL || rate == NULL) return false ;
235        switch (linktype) {
236                case TRACE_TYPE_80211_RADIO:
237                        if ( (p = (uint8_t *) trace_get_radiotap_field(link,
238                                                        TRACE_RADIOTAP_RATE))) {
239                                *rate = *p;
240                                return true;
241                        } else break;
242                case TRACE_TYPE_LINUX_SLL:
243                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
244                        return trace_get_wireless_rate(l, arphrd_type_to_libtrace(type), rate);
245                default:
246                        return false;
247        }
248        return false;
249}
250
251DLLEXPORT bool trace_get_wireless_freq(void *link, 
252                libtrace_linktype_t linktype, uint16_t *freq)
253{
254        uint16_t *p;
255        void *l;
256        uint16_t type;
257
258        if (link == NULL || freq == NULL) return false;
259        switch (linktype) {
260                case TRACE_TYPE_80211_RADIO:
261                        /* NB: The channel field is actually two 16 bit fields.
262                         * The chan_freq field is the first of those two, so we
263                         * just cast it to a uint16_t.
264                         */
265                        if (( p = (uint16_t *) trace_get_radiotap_field(link,
266                                                        TRACE_RADIOTAP_CHANNEL))) {
267                                *freq = bswap_le_to_host16(*p);
268                                return true;
269                        } else break;
270                case TRACE_TYPE_LINUX_SLL:
271                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
272                        return trace_get_wireless_freq(l, arphrd_type_to_libtrace(type), freq);
273                default:
274                        return false;
275        }
276        return false;
277}
278
279/*
280 * This function isn't portable across drivers, so has been left static
281 * for now. Maybe it will be included in the API later if it becomes useful
282 * and we come up with a suitable abstraction.
283 */
284static
285bool trace_get_wireless_channel_flags(void *link,
286                libtrace_linktype_t linktype, uint16_t *flags)
287{
288        uint16_t *p;
289        void *l;
290        uint16_t type;
291        if (link == NULL || flags == NULL) return false;
292        switch (linktype) {
293                case TRACE_TYPE_80211_RADIO:
294                        /* NB: The channel field is actually two 16 bit fields.
295                         * The chan_flags field is the second of the two, so we need
296                         * to take the pointer returned by getting the channel field
297                         * and increment it.
298                         */
299                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
300                                                        TRACE_RADIOTAP_CHANNEL))) {
301                                *flags = bswap_le_to_host16(*(++p));
302                                return true;
303                        } else break;
304                case TRACE_TYPE_LINUX_SLL:
305                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
306                        return trace_get_wireless_channel_flags(l, arphrd_type_to_libtrace(type), flags);
307                default:
308                        return false;
309        }
310        return false;
311}
312
313/* Not sure that this function is useful for now - who uses FHSS?
314 * This might get exported in the future if it becomes useful
315 */
316static
317bool trace_get_wireless_fhss_hopset(void *link,
318                libtrace_linktype_t linktype, uint8_t *hopset)
319{
320        uint8_t *p;
321        void *l;
322        uint16_t type;
323
324        if (link == NULL || hopset == NULL) return false;
325        switch(linktype) {
326                case TRACE_TYPE_80211_RADIO:
327                        /* NB: As above with the channel field, the fhss field is
328                         * similar.
329                         */
330                        if( (p = (uint8_t *) trace_get_radiotap_field(link,
331                                                        TRACE_RADIOTAP_FHSS))) {
332                                *hopset = *p;
333                                return true;
334                        } else break;
335                case TRACE_TYPE_LINUX_SLL:
336                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
337                        return trace_get_wireless_fhss_hopset(l, arphrd_type_to_libtrace(type), hopset);
338                default:
339                        return false;
340        }
341        return false;
342}
343
344/* Not sure that this function is useful for now - who uses FHSS?
345 * This might get exported in the future if it becomes useful
346 */
347static
348bool trace_get_wireless_fhss_hoppattern(void *link,
349                libtrace_linktype_t linktype, uint8_t *hoppattern)
350{
351        uint8_t *p;
352        void *l;
353        uint16_t type;
354        if (link == NULL || hoppattern == NULL) return false;
355        switch (linktype) {
356                case TRACE_TYPE_80211_RADIO:
357                        if((p = (uint8_t *) trace_get_radiotap_field(link,
358                                                        TRACE_RADIOTAP_FHSS))) {
359                                *hoppattern = *(++p);
360                                return true;
361                        } else break;
362                case TRACE_TYPE_LINUX_SLL:
363                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
364                        return trace_get_wireless_fhss_hoppattern(l, arphrd_type_to_libtrace(type), hoppattern);
365                default:
366                        return false;
367        }
368        return false;
369}
370
371DLLEXPORT bool trace_get_wireless_signal_strength_dbm(void *link,
372                libtrace_linktype_t linktype, int8_t *strength)
373{
374        int8_t *p;
375        void *l;
376        uint16_t type;
377
378        if (link == NULL || strength == NULL) return false;
379        switch(linktype) {
380                case TRACE_TYPE_80211_RADIO:
381                        if ((p =  (int8_t *) trace_get_radiotap_field(link,
382                                                        TRACE_RADIOTAP_DBM_ANTSIGNAL))) {
383                                *strength = *p;
384                                return true;
385                        } else break;
386                case TRACE_TYPE_LINUX_SLL:
387                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
388                        return trace_get_wireless_signal_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
389                default:
390                        return false;
391        }
392        return false;
393}
394
395DLLEXPORT bool trace_get_wireless_noise_strength_dbm(void *link,
396                libtrace_linktype_t linktype, int8_t *strength)
397{
398        uint8_t *p;
399        void *l;
400        uint16_t type;
401
402        if (link == NULL || strength == NULL) return false;
403        switch (linktype) {
404                case TRACE_TYPE_80211_RADIO:
405                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
406                                        TRACE_RADIOTAP_DBM_ANTNOISE))) {
407                                *strength = *p;
408                                return true;
409                        } else break;
410                case TRACE_TYPE_LINUX_SLL:
411                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
412                        return trace_get_wireless_noise_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
413                default:
414                        return false;
415        }
416        return false;
417}
418
419DLLEXPORT bool trace_get_wireless_signal_strength_db(void *link,
420                libtrace_linktype_t linktype, uint8_t *strength)
421{
422        uint8_t *p;
423        void *l;
424        uint16_t type;
425
426        if (link == NULL || strength == NULL) return false;
427        switch (linktype) {
428                case TRACE_TYPE_80211_RADIO:
429                        if ((p =  (uint8_t *) trace_get_radiotap_field(link,
430                                                        TRACE_RADIOTAP_DB_ANTSIGNAL))) {
431                                *strength = *p;
432                                return true;
433                        } else break;
434                case TRACE_TYPE_LINUX_SLL:
435                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
436                        return trace_get_wireless_signal_strength_db(l, arphrd_type_to_libtrace(type), strength);
437                default:
438                        return false;
439        }
440        return false ;
441}
442
443DLLEXPORT bool trace_get_wireless_noise_strength_db(void *link,
444                libtrace_linktype_t linktype, uint8_t *strength)
445{
446        uint8_t *p;
447        void *l;
448        uint16_t type;
449
450        if (link == NULL || strength == NULL) return false;
451        switch (linktype) {
452                case TRACE_TYPE_80211_RADIO:
453                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
454                                                        TRACE_RADIOTAP_DB_ANTNOISE))) {
455                                *strength = *p;
456                                return true;
457                        } else break;
458                case TRACE_TYPE_LINUX_SLL:
459                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
460                        return trace_get_wireless_noise_strength_db(l, arphrd_type_to_libtrace(type), strength);
461                default:
462                        return false;
463        }
464        return false;
465}
466
467/* Not sure if this function is useful. As the radiotap documentation says,
468 * there's no set metric for defining the quality of the Barker Code Lock.
469 * Maybe it will be exported later if it becomes useful.
470 */
471static
472bool trace_get_wireless_lock_quality(void *link,
473                libtrace_linktype_t linktype, uint16_t *quality)
474{
475        uint16_t *p;
476        void *l;
477        uint16_t type;
478
479        if (link == NULL || quality == NULL) return false;
480        switch (linktype) {
481                case TRACE_TYPE_80211_RADIO:
482                        if((p = (uint16_t *) trace_get_radiotap_field(link,
483                                                        TRACE_RADIOTAP_LOCK_QUALITY))) {
484                                *quality = bswap_le_to_host16(*p);
485                                return true;
486                        } else break;
487                case TRACE_TYPE_LINUX_SLL:
488                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
489                        return trace_get_wireless_lock_quality(l, arphrd_type_to_libtrace(type), quality);
490                default:
491                        return false;
492        }
493        return false;
494}
495
496DLLEXPORT bool trace_get_wireless_tx_attenuation(void *link,
497                libtrace_linktype_t linktype, uint16_t *attenuation)
498{
499        uint16_t *p;
500        void *l;
501        uint16_t type;
502
503        if (link == NULL || attenuation == 0) return false;
504        switch (linktype) {
505                case TRACE_TYPE_80211_RADIO:
506                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
507                                                        TRACE_RADIOTAP_TX_ATTENUATION))) {
508                                *attenuation = bswap_le_to_host16(*p);
509                                return true;
510                        } else break;
511                case TRACE_TYPE_LINUX_SLL:
512                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
513                        return trace_get_wireless_tx_attenuation(l, arphrd_type_to_libtrace(type), attenuation);
514                default:
515                        return false;
516        }
517        return false;
518}
519
520DLLEXPORT bool trace_get_wireless_tx_attenuation_db(void *link,
521                libtrace_linktype_t linktype, uint16_t *attenuation)
522{
523        uint16_t *p;
524        void *l;
525        uint16_t type;
526
527        if (link == NULL || attenuation == NULL) return false;
528        switch (linktype) {
529                case TRACE_TYPE_80211_RADIO:
530                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
531                                                        TRACE_RADIOTAP_DB_TX_ATTENUATION))) {
532                                *attenuation = bswap_le_to_host16(*p);
533                                return true;
534                        } else break;
535                case TRACE_TYPE_LINUX_SLL:
536                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
537                        return trace_get_wireless_tx_attenuation_db(l, arphrd_type_to_libtrace(type), attenuation);
538                default:
539                        return false;
540        }
541        return false;
542}
543
544DLLEXPORT bool trace_get_wireless_tx_power_dbm(void *link,
545                libtrace_linktype_t linktype, int8_t *txpower)
546{
547        int8_t *p;
548        void *l;
549        uint16_t type;
550
551        if (link == NULL || txpower == NULL) return false;
552        switch (linktype) {
553                case TRACE_TYPE_80211_RADIO:
554                        if ((p=(int8_t *) trace_get_radiotap_field(link,
555                                                        TRACE_RADIOTAP_DBM_TX_POWER))) {
556                                *txpower = *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_tx_power_dbm(l, arphrd_type_to_libtrace(type), txpower);
562                default:
563                        return false;
564        }
565        return false;
566}
567
568
569DLLEXPORT bool trace_get_wireless_antenna(void *link,
570                libtrace_linktype_t linktype, uint8_t *antenna)
571{
572        uint8_t *p;
573        void *l;
574        uint16_t type;
575
576        if (link == NULL || antenna == NULL) return false;
577        switch (linktype) {
578                case TRACE_TYPE_80211_RADIO:
579                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
580                                                        TRACE_RADIOTAP_ANTENNA))) {
581                                *antenna = *p;
582                                return true;
583                        } else break;
584                case TRACE_TYPE_LINUX_SLL:
585                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
586                        return trace_get_wireless_antenna(l, arphrd_type_to_libtrace(type), antenna);
587                default:
588                        return false;
589        }
590        return false;
591}
592
593DLLEXPORT bool trace_get_wireless_fcs(void *link,
594                libtrace_linktype_t linktype, uint32_t *fcs)
595{
596        uint32_t *p;
597        void *l;
598        uint16_t type;
599
600        if (link == NULL || fcs == NULL) return false;
601        switch (linktype) {
602                case TRACE_TYPE_80211_RADIO:
603                        if ((p = (uint32_t *) trace_get_radiotap_field(link,
604                                                        TRACE_RADIOTAP_FCS))) {
605                                *fcs = bswap_le_to_host32(*p);
606                                return true;
607                        } else break;
608                case TRACE_TYPE_LINUX_SLL:
609                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
610                        return trace_get_wireless_fcs(l, arphrd_type_to_libtrace(type), fcs);
611                default:
612                        return false;
613        }
614        return false;
615}
616
Note: See TracBrowser for help on using the repository browser.