source: lib/link_wireless.c @ 630460b

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 630460b was ee6e802, checked in by Shane Alcock <salcock@…>, 5 years ago

Updated copyright blurb on all source files

In some cases, this meant adding copyright blurbs to files that
had never had them before.

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