source: lib/link_wireless.c @ 325f86f

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 325f86f was ebf8071, checked in by Shane Alcock <salcock@…>, 12 years ago
  • Updated licensing and documentation for another set of source files
  • Property mode set to 100644
File size: 16.4 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Scott Raynel
8 *          Perry Lorier
9 *         
10 * All rights reserved.
11 *
12 * This code has been developed by the University of Waikato WAND
13 * research group. For further information please see http://www.wand.net.nz/
14 *
15 * libtrace is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * libtrace is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with libtrace; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 *
29 * $Id$
30 *
31 */
32
33#include "libtrace.h"
34#include "libtrace_int.h"
35
36/* The file contains all the functions necessary to access various measurement
37 * values that are specific to wireless MACs ( RadioTap in particular ).
38 *
39 * Credit for all this code goes to Scott Raynel.
40 */
41
42/* Used for Radiotap fields which must be naturally aligned */
43#define ALIGN_NATURAL_64(_p,_s) \
44        while ( (_p - _s) % sizeof(uint64_t)) _p++
45#define ALIGN_NATURAL_32(_p,_s) \
46        while ( (_p - _s) % sizeof(uint32_t)) _p++
47#define ALIGN_NATURAL_16(_p,_s) \
48        while ( (_p - _s) % sizeof(uint16_t)) _p++
49
50/** Gets a field from a Radiotap header.
51 * @param link the radiotap header
52 * @param field the radiotap field we want to access
53 * @return a void pointer to the field. It is up to the caller to cast to the
54 * appropriate type.
55 * @note Radiotap fields are always little-endian
56 */
57static void *trace_get_radiotap_field(void *link, libtrace_radiotap_field_t field)
58{
59        struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t *)link;
60        uint8_t *p;
61        uint8_t *s;
62
63        /* Check if the field exists in the radiotap header before proceeding
64        */
65        if ((bswap_le_to_host32(rtap->it_present) & (1 << field)) == 0) return NULL;
66
67        /* Skip over any extended bitmasks */
68        p = (uint8_t *) &(rtap->it_present);
69
70        while ( bswap_le_to_host32(*((uint32_t*)p)) & (1U << TRACE_RADIOTAP_EXT) ) {
71                p += sizeof (uint32_t);
72        }
73
74        /* Point p at the first field of radiotap data and remember it for later
75         * when we're doing field alignment
76         */
77        p += sizeof(uint32_t);
78        s = p;
79
80        if (field == TRACE_RADIOTAP_TSFT) 
81                /* Always aligned */
82                return (void*)p;
83        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_TSFT))
84                p += sizeof (uint64_t);
85
86        if (field == TRACE_RADIOTAP_FLAGS)
87                /* Always aligned */
88                return (void*)p;
89        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_FLAGS))
90                p += sizeof (uint8_t);
91
92        if (field == TRACE_RADIOTAP_RATE)
93                /* Always aligned */
94                return (void*)p;
95        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_RATE))
96                p+= sizeof (uint8_t);
97
98        if (field == TRACE_RADIOTAP_CHANNEL)
99        {
100                ALIGN_NATURAL_16(p,s);
101                return (void *)p;
102        }
103        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_CHANNEL))
104                p+= sizeof (uint32_t);
105
106        if (field == TRACE_RADIOTAP_FHSS)
107        {
108                ALIGN_NATURAL_16(p,s);
109                return (void *)p;
110        }
111        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_FHSS))
112                p+= sizeof (uint16_t);
113
114        if (field == TRACE_RADIOTAP_DBM_ANTSIGNAL)
115                return (void *)p;
116        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DBM_ANTSIGNAL))
117                p+= sizeof (uint8_t);
118
119        if (field == TRACE_RADIOTAP_DBM_ANTNOISE)
120                return (void *)p;
121        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DBM_ANTNOISE))
122                p+= sizeof (uint8_t);
123
124        if (field == TRACE_RADIOTAP_LOCK_QUALITY)
125        {
126                ALIGN_NATURAL_16(p,s);
127                return (void *)p;
128        }
129        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_LOCK_QUALITY))
130                p+= sizeof (uint16_t);
131
132        if (field == TRACE_RADIOTAP_TX_ATTENUATION)
133        {
134                ALIGN_NATURAL_16(p,s);
135                return (void *)p;
136        }
137        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_TX_ATTENUATION))
138                p+= sizeof (uint16_t);
139
140        if (field == TRACE_RADIOTAP_DB_TX_ATTENUATION)
141        {
142                ALIGN_NATURAL_16(p,s);
143                return (void *)p;
144        }
145        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DB_TX_ATTENUATION))
146                p+= sizeof (uint16_t);
147
148        if (field == TRACE_RADIOTAP_DBM_TX_POWER)
149                return (void *)p;
150        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DBM_TX_POWER))
151                p+= sizeof (uint8_t);
152
153        if (field == TRACE_RADIOTAP_ANTENNA)
154                return (void *)p;
155        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_ANTENNA))
156                p+= sizeof (uint8_t);
157
158        if (field == TRACE_RADIOTAP_DB_ANTSIGNAL)
159                return (void *)p;
160        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DB_ANTSIGNAL))
161                p+= sizeof (uint8_t);
162
163        if (field == TRACE_RADIOTAP_DB_ANTNOISE)
164                return (void *) p;
165        /*
166        if (bswap_le_to_host32(rtap->it_present) & (1 << TRACE_RADIOTAP_DB_ANTNOISE))
167                p+= sizeof (uint8_t);
168        */
169
170        /* Unknown field */
171        return NULL;
172} 
173
174DLLEXPORT bool trace_get_wireless_tsft(void *link, 
175                libtrace_linktype_t linktype, uint64_t *tsft)
176{
177        uint64_t *p;
178        void *l;
179        uint16_t type;
180        if (link == NULL || tsft == NULL) return false;
181
182        switch (linktype) {
183                case TRACE_TYPE_80211_RADIO:
184                        if( (p = (uint64_t *) trace_get_radiotap_field(link, 
185                                                        TRACE_RADIOTAP_TSFT))) {
186                                *tsft = bswap_le_to_host64(*p);
187                                return true;
188                        } else break;
189                case TRACE_TYPE_LINUX_SLL:
190                        l = trace_get_payload_from_linux_sll(link, &type, NULL );
191                        return trace_get_wireless_tsft(l, arphrd_type_to_libtrace(type), tsft);
192
193                case TRACE_TYPE_80211_PRISM:
194                        return false;
195                default:
196                        return false;
197        }
198        return false;
199}
200
201/*
202 * This function isn't portable across drivers, so has been left static
203 * for now. Maybe it will be included in the API later if it becomes useful
204 * and we come up with a suitable abstraction.
205 * This function isn't marked static as the various format modules need to
206 * access it for get_wire_length(). It's not meant to be exported though.
207 */
208bool trace_get_wireless_flags(void *link, 
209                libtrace_linktype_t linktype, uint8_t *flags)
210{
211        uint8_t *p;
212        void *l;
213        uint16_t type;
214
215        if (link == NULL || flags == NULL) return false;
216
217        switch(linktype) {
218                case TRACE_TYPE_80211_RADIO:
219                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
220                                                        TRACE_RADIOTAP_FLAGS))) {
221                                *flags = *p;
222                                return true;
223                        } else break;
224                case TRACE_TYPE_LINUX_SLL:
225                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
226                        return trace_get_wireless_flags(l, arphrd_type_to_libtrace(type), flags);
227                default:
228                        return false;
229        }
230        return false;
231}
232
233DLLEXPORT bool trace_get_wireless_rate(void *link, 
234                libtrace_linktype_t linktype, uint8_t *rate)
235{
236        uint8_t * p;
237        void *l;
238        uint16_t type;
239
240        if (link == NULL || rate == NULL) return false ;
241        switch (linktype) {
242                case TRACE_TYPE_80211_RADIO:
243                        if ( (p = (uint8_t *) trace_get_radiotap_field(link,
244                                                        TRACE_RADIOTAP_RATE))) {
245                                *rate = *p;
246                                return true;
247                        } else break;
248                case TRACE_TYPE_LINUX_SLL:
249                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
250                        return trace_get_wireless_rate(l, arphrd_type_to_libtrace(type), rate);
251                default:
252                        return false;
253        }
254        return false;
255}
256
257DLLEXPORT bool trace_get_wireless_freq(void *link, 
258                libtrace_linktype_t linktype, uint16_t *freq)
259{
260        uint16_t *p;
261        void *l;
262        uint16_t type;
263
264        if (link == NULL || freq == NULL) return false;
265        switch (linktype) {
266                case TRACE_TYPE_80211_RADIO:
267                        /* NB: The channel field is actually two 16 bit fields.
268                         * The chan_freq field is the first of those two, so we
269                         * just cast it to a uint16_t.
270                         */
271                        if (( p = (uint16_t *) trace_get_radiotap_field(link,
272                                                        TRACE_RADIOTAP_CHANNEL))) {
273                                *freq = bswap_le_to_host16(*p);
274                                return true;
275                        } else break;
276                case TRACE_TYPE_LINUX_SLL:
277                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
278                        return trace_get_wireless_freq(l, arphrd_type_to_libtrace(type), freq);
279                default:
280                        return false;
281        }
282        return false;
283}
284
285/*
286 * This function isn't portable across drivers, so has been left static
287 * for now. Maybe it will be included in the API later if it becomes useful
288 * and we come up with a suitable abstraction.
289 */
290static
291bool trace_get_wireless_channel_flags(void *link,
292                libtrace_linktype_t linktype, uint16_t *flags)
293{
294        uint16_t *p;
295        void *l;
296        uint16_t type;
297        if (link == NULL || flags == NULL) return false;
298        switch (linktype) {
299                case TRACE_TYPE_80211_RADIO:
300                        /* NB: The channel field is actually two 16 bit fields.
301                         * The chan_flags field is the second of the two, so we need
302                         * to take the pointer returned by getting the channel field
303                         * and increment it.
304                         */
305                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
306                                                        TRACE_RADIOTAP_CHANNEL))) {
307                                *flags = bswap_le_to_host16(*(++p));
308                                return true;
309                        } else break;
310                case TRACE_TYPE_LINUX_SLL:
311                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
312                        return trace_get_wireless_channel_flags(l, arphrd_type_to_libtrace(type), flags);
313                default:
314                        return false;
315        }
316        return false;
317}
318
319/* Not sure that this function is useful for now - who uses FHSS?
320 * This might get exported in the future if it becomes useful
321 */
322static
323bool trace_get_wireless_fhss_hopset(void *link,
324                libtrace_linktype_t linktype, uint8_t *hopset)
325{
326        uint8_t *p;
327        void *l;
328        uint16_t type;
329
330        if (link == NULL || hopset == NULL) return false;
331        switch(linktype) {
332                case TRACE_TYPE_80211_RADIO:
333                        /* NB: As above with the channel field, the fhss field is
334                         * similar.
335                         */
336                        if( (p = (uint8_t *) trace_get_radiotap_field(link,
337                                                        TRACE_RADIOTAP_FHSS))) {
338                                *hopset = *p;
339                                return true;
340                        } else break;
341                case TRACE_TYPE_LINUX_SLL:
342                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
343                        return trace_get_wireless_fhss_hopset(l, arphrd_type_to_libtrace(type), hopset);
344                default:
345                        return false;
346        }
347        return false;
348}
349
350/* Not sure that this function is useful for now - who uses FHSS?
351 * This might get exported in the future if it becomes useful
352 */
353static
354bool trace_get_wireless_fhss_hoppattern(void *link,
355                libtrace_linktype_t linktype, uint8_t *hoppattern)
356{
357        uint8_t *p;
358        void *l;
359        uint16_t type;
360        if (link == NULL || hoppattern == 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_FHSS))) {
365                                *hoppattern = *(++p);
366                                return true;
367                        } else break;
368                case TRACE_TYPE_LINUX_SLL:
369                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
370                        return trace_get_wireless_fhss_hoppattern(l, arphrd_type_to_libtrace(type), hoppattern);
371                default:
372                        return false;
373        }
374        return false;
375}
376
377DLLEXPORT bool trace_get_wireless_signal_strength_dbm(void *link,
378                libtrace_linktype_t linktype, int8_t *strength)
379{
380        int8_t *p;
381        void *l;
382        uint16_t type;
383
384        if (link == NULL || strength == NULL) return false;
385        switch(linktype) {
386                case TRACE_TYPE_80211_RADIO:
387                        if ((p =  (int8_t *) trace_get_radiotap_field(link,
388                                                        TRACE_RADIOTAP_DBM_ANTSIGNAL))) {
389                                *strength = *p;
390                                return true;
391                        } else break;
392                case TRACE_TYPE_LINUX_SLL:
393                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
394                        return trace_get_wireless_signal_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
395                default:
396                        return false;
397        }
398        return false;
399}
400
401DLLEXPORT bool trace_get_wireless_noise_strength_dbm(void *link,
402                libtrace_linktype_t linktype, int8_t *strength)
403{
404        uint8_t *p;
405        void *l;
406        uint16_t type;
407
408        if (link == NULL || strength == NULL) return false;
409        switch (linktype) {
410                case TRACE_TYPE_80211_RADIO:
411                        if (( p = (uint8_t *) trace_get_radiotap_field(link,
412                                        TRACE_RADIOTAP_DBM_ANTNOISE))) {
413                                *strength = *p;
414                                return true;
415                        } else break;
416                case TRACE_TYPE_LINUX_SLL:
417                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
418                        return trace_get_wireless_noise_strength_dbm(l, arphrd_type_to_libtrace(type), strength);
419                default:
420                        return false;
421        }
422        return false;
423}
424
425DLLEXPORT bool trace_get_wireless_signal_strength_db(void *link,
426                libtrace_linktype_t linktype, uint8_t *strength)
427{
428        uint8_t *p;
429        void *l;
430        uint16_t type;
431
432        if (link == NULL || strength == NULL) return false;
433        switch (linktype) {
434                case TRACE_TYPE_80211_RADIO:
435                        if ((p =  (uint8_t *) trace_get_radiotap_field(link,
436                                                        TRACE_RADIOTAP_DB_ANTSIGNAL))) {
437                                *strength = *p;
438                                return true;
439                        } else break;
440                case TRACE_TYPE_LINUX_SLL:
441                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
442                        return trace_get_wireless_signal_strength_db(l, arphrd_type_to_libtrace(type), strength);
443                default:
444                        return false;
445        }
446        return false ;
447}
448
449DLLEXPORT bool trace_get_wireless_noise_strength_db(void *link,
450                libtrace_linktype_t linktype, uint8_t *strength)
451{
452        uint8_t *p;
453        void *l;
454        uint16_t type;
455
456        if (link == NULL || strength == NULL) return false;
457        switch (linktype) {
458                case TRACE_TYPE_80211_RADIO:
459                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
460                                                        TRACE_RADIOTAP_DB_ANTNOISE))) {
461                                *strength = *p;
462                                return true;
463                        } else break;
464                case TRACE_TYPE_LINUX_SLL:
465                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
466                        return trace_get_wireless_noise_strength_db(l, arphrd_type_to_libtrace(type), strength);
467                default:
468                        return false;
469        }
470        return false;
471}
472
473/* Not sure if this function is useful. As the radiotap documentation says,
474 * there's no set metric for defining the quality of the Barker Code Lock.
475 * Maybe it will be exported later if it becomes useful.
476 */
477static
478bool trace_get_wireless_lock_quality(void *link,
479                libtrace_linktype_t linktype, uint16_t *quality)
480{
481        uint16_t *p;
482        void *l;
483        uint16_t type;
484
485        if (link == NULL || quality == NULL) return false;
486        switch (linktype) {
487                case TRACE_TYPE_80211_RADIO:
488                        if((p = (uint16_t *) trace_get_radiotap_field(link,
489                                                        TRACE_RADIOTAP_LOCK_QUALITY))) {
490                                *quality = bswap_le_to_host16(*p);
491                                return true;
492                        } else break;
493                case TRACE_TYPE_LINUX_SLL:
494                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
495                        return trace_get_wireless_lock_quality(l, arphrd_type_to_libtrace(type), quality);
496                default:
497                        return false;
498        }
499        return false;
500}
501
502DLLEXPORT bool trace_get_wireless_tx_attenuation(void *link,
503                libtrace_linktype_t linktype, uint16_t *attenuation)
504{
505        uint16_t *p;
506        void *l;
507        uint16_t type;
508
509        if (link == NULL || attenuation == 0) return false;
510        switch (linktype) {
511                case TRACE_TYPE_80211_RADIO:
512                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
513                                                        TRACE_RADIOTAP_TX_ATTENUATION))) {
514                                *attenuation = bswap_le_to_host16(*p);
515                                return true;
516                        } else break;
517                case TRACE_TYPE_LINUX_SLL:
518                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
519                        return trace_get_wireless_tx_attenuation(l, arphrd_type_to_libtrace(type), attenuation);
520                default:
521                        return false;
522        }
523        return false;
524}
525
526DLLEXPORT bool trace_get_wireless_tx_attenuation_db(void *link,
527                libtrace_linktype_t linktype, uint16_t *attenuation)
528{
529        uint16_t *p;
530        void *l;
531        uint16_t type;
532
533        if (link == NULL || attenuation == NULL) return false;
534        switch (linktype) {
535                case TRACE_TYPE_80211_RADIO:
536                        if ((p = (uint16_t *) trace_get_radiotap_field(link,
537                                                        TRACE_RADIOTAP_DB_TX_ATTENUATION))) {
538                                *attenuation = bswap_le_to_host16(*p);
539                                return true;
540                        } else break;
541                case TRACE_TYPE_LINUX_SLL:
542                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
543                        return trace_get_wireless_tx_attenuation_db(l, arphrd_type_to_libtrace(type), attenuation);
544                default:
545                        return false;
546        }
547        return false;
548}
549
550DLLEXPORT bool trace_get_wireless_tx_power_dbm(void *link,
551                libtrace_linktype_t linktype, int8_t *txpower)
552{
553        int8_t *p;
554        void *l;
555        uint16_t type;
556
557        if (link == NULL || txpower == NULL) return false;
558        switch (linktype) {
559                case TRACE_TYPE_80211_RADIO:
560                        if ((p=(int8_t *) trace_get_radiotap_field(link,
561                                                        TRACE_RADIOTAP_DBM_TX_POWER))) {
562                                *txpower = *p;
563                                return true;
564                        } else break;
565                case TRACE_TYPE_LINUX_SLL:
566                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
567                        return trace_get_wireless_tx_power_dbm(l, arphrd_type_to_libtrace(type), txpower);
568                default:
569                        return false;
570        }
571        return false;
572}
573
574
575DLLEXPORT bool trace_get_wireless_antenna(void *link,
576                libtrace_linktype_t linktype, uint8_t *antenna)
577{
578        uint8_t *p;
579        void *l;
580        uint16_t type;
581
582        if (link == NULL || antenna == NULL) return false;
583        switch (linktype) {
584                case TRACE_TYPE_80211_RADIO:
585                        if ((p = (uint8_t *) trace_get_radiotap_field(link,
586                                                        TRACE_RADIOTAP_ANTENNA))) {
587                                *antenna = *p;
588                                return true;
589                        } else break;
590                case TRACE_TYPE_LINUX_SLL:
591                        l = trace_get_payload_from_linux_sll(link, &type, NULL);
592                        return trace_get_wireless_antenna(l, arphrd_type_to_libtrace(type), antenna);
593                default:
594                        return false;
595        }
596        return false;
597}
598
Note: See TracBrowser for help on using the repository browser.