source: lib/protocols_l2.c @ 89e2ff7

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivendag_formatrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 89e2ff7 was ee6e802, checked in by Shane Alcock <salcock@…>, 4 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: 20.3 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#include "libtrace_int.h"
27#include "libtrace.h"
28#include "protocols.h"
29#include <assert.h>
30#include <stdlib.h>
31#include <string.h>
32
33
34/* This file contains all the protocol decoding functions for layer 2
35 * (and 2.5) protocols. This includes functions for accessing MAC addresses.
36 *
37 * Supported protocols include (but are not limited to):
38 *      Ethernet
39 *      802.11
40 *      802.1q (vlan)
41 *      MPLS
42 *      PPPoE
43 *      LLCSnap
44 *      ATM
45 */
46
47
48/* Returns the payload from 802.3 ethernet.  Type optionally returned in
49 * "type" in host byte order.  This will return a vlan header.
50 */
51void *trace_get_payload_from_ethernet(void *ethernet, 
52                uint16_t *type,
53                uint32_t *remaining)
54{
55        libtrace_ether_t *eth = (libtrace_ether_t*)ethernet;
56
57        if (remaining) {
58                if (*remaining < sizeof(*eth)) {
59                        *remaining = 0;
60                        return NULL;
61                }
62                *remaining-=sizeof(*eth);
63        }
64
65        if (type)
66                *type = ntohs(eth->ether_type);
67
68        return (void*)((char *)eth + sizeof(*eth));
69}
70
71/* Skip any 802.1q headers if necessary
72 * type is now output only (why check it if we don't need to?)
73 */
74void *trace_get_payload_from_vlan(void *ethernet, uint16_t *type,
75                uint32_t *remaining)
76{
77        libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
78
79        if (remaining) {
80                if (*remaining < sizeof(libtrace_8021q_t)) {
81                        *remaining = 0;
82                        return NULL;
83                }
84
85                *remaining=*remaining-sizeof(libtrace_8021q_t);
86        }
87
88        if (type)
89                *type = ntohs(vlanhdr->vlan_ether_type);
90
91        return (void*)((char *)ethernet + sizeof(*vlanhdr));
92
93}
94
95libtrace_packet_t *trace_strip_packet(libtrace_packet_t *packet) {
96
97        libtrace_ether_t *ethernet;
98        libtrace_linktype_t linktype;
99        uint16_t ethertype;
100        uint32_t remaining;
101        char *nextpayload;
102        uint16_t finalethertype = 0;
103        uint16_t caplen, removed = 0;
104        char *dest;
105        uint8_t done = 0;
106        uint32_t oldrem;
107
108        /* For now, this will just work for Ethernet packets. */
109        ethernet = (libtrace_ether_t *)trace_get_layer2(packet, 
110                        &linktype, &remaining);
111
112        if (linktype != TRACE_TYPE_ETH) {
113                return packet;
114        }
115
116        /* No headers to strip, return the original packet */
117        if (ethernet->ether_type == TRACE_ETHERTYPE_IP ||
118                        ethernet->ether_type == TRACE_ETHERTYPE_IPV6) {
119                return packet;
120        }
121
122        if (remaining <= sizeof(libtrace_ether_t))
123                return packet;
124
125        caplen = trace_get_capture_length(packet);
126        ethertype = ntohs(ethernet->ether_type);
127        dest = ((char *)ethernet) + sizeof(libtrace_ether_t);
128        nextpayload = dest;
129        remaining -= sizeof(libtrace_ether_t);
130
131        /* I'd normally use trace_get_layer3 here, but it works out faster
132         * to do it this way (mostly less function call overhead).
133         *
134         * XXX This approach is going to just strip everything between the
135         * Ethernet and IP headers -- is there a use case where someone
136         * might want to selectively strip headers?
137         */
138        while (!done) {
139
140                if (nextpayload == NULL || remaining == 0)
141                        break;
142
143                oldrem = remaining;
144                switch (ethertype) {
145
146                case TRACE_ETHERTYPE_8021Q:
147                        nextpayload = (char *)trace_get_payload_from_vlan(
148                                        nextpayload,
149                                        &ethertype, &remaining);
150                        removed += (oldrem - remaining);
151                        break;
152
153                case TRACE_ETHERTYPE_MPLS:
154                        nextpayload = (char *)trace_get_payload_from_mpls(
155                                        nextpayload,
156                                        &ethertype, &remaining);
157                        removed += (oldrem - remaining);
158                        break;
159                case TRACE_ETHERTYPE_PPP_SES:
160                        nextpayload = (char *)trace_get_payload_from_pppoe(
161                                        nextpayload,
162                                        &ethertype, &remaining);
163                        removed += (oldrem - remaining);
164                        break;
165
166                case TRACE_ETHERTYPE_IP:
167                case TRACE_ETHERTYPE_IPV6:
168                default:
169                        if (finalethertype == 0)
170                                finalethertype = ethertype;
171                        done = true;
172                        break;
173                }
174        }
175
176        if (nextpayload != NULL) {
177
178                ethernet->ether_type = ntohs(finalethertype);
179                trace_set_capture_length(packet, caplen - removed);
180                memmove(nextpayload - (dest - (char *)packet->payload), 
181                        packet->payload, 
182                        (dest - (char *)packet->payload));
183                packet->payload = nextpayload - (dest - (char *)packet->payload);
184                packet->l2_header = NULL;
185        }
186       
187        return packet;
188
189}
190
191/* Skip any MPLS headers if necessary, guessing what the next type is
192 * type is input/output.  If the next type is "ethernet" this will
193 * return a type of 0x0000.
194 */
195void *trace_get_payload_from_mpls(void *ethernet, uint16_t *type, 
196                uint32_t *remaining)
197{
198       
199        assert(type);
200        if ((((char*)ethernet)[2]&0x01)==0) {
201                /* The MPLS Stack bit is set */
202                *type = TRACE_ETHERTYPE_MPLS;
203        }
204        else {
205                if (!remaining || *remaining>=5) {
206                        switch (((char*)ethernet)[4]&0xF0) {
207                                case 0x40:      /* IPv4 */
208                                        *type = TRACE_ETHERTYPE_IP;
209                                        break;
210                                case 0x60:      /* IPv6 */
211                                        *type = TRACE_ETHERTYPE_IPV6;
212                                        break;
213                                default:        /* VPLS */
214                                        /* Ethernet */
215                                        *type = 0;
216                        }
217                }
218        }
219        ethernet=(char*)ethernet+4;
220        if (remaining) {
221                if (*remaining<4)
222                        return NULL;
223                else
224                        *remaining-=4;
225        }
226
227
228        return ethernet;
229}
230
231static void *trace_get_payload_from_llcsnap(void *link,
232                uint16_t *type, uint32_t *remaining)
233{
234        /* 64 byte capture. */
235        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
236
237        if (remaining) {
238                if (*remaining < sizeof(libtrace_llcsnap_t)) {
239                        *remaining = 0;
240                        return NULL;
241                }
242                *remaining-=(sizeof(libtrace_llcsnap_t));
243        }
244
245        llc = (libtrace_llcsnap_t*)((char *)llc);
246
247        if (type) *type = ntohs(llc->type);
248
249        return (void*)((char*)llc+sizeof(*llc));
250}
251
252
253static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
254{
255        libtrace_80211_t *wifi;
256        uint16_t *eth; /* ethertype */
257        int8_t extra = 0; /* how many QoS bytes to skip */
258       
259        if (remaining && *remaining < sizeof(libtrace_80211_t)) {
260                *remaining = 0;
261                return NULL;
262        }
263
264        wifi=(libtrace_80211_t*)link;
265
266        /* Data packet? */
267        if (wifi->type != 2) {
268                return NULL;
269        }
270
271        /* If FromDS and ToDS are both set then we have a four-address
272         * frame. Otherwise we have a three-address frame */
273        if (!(wifi->to_ds && wifi->from_ds)) 
274                extra -= 6; 
275       
276        /* Indicates QoS field present, see IEEE802.11e-2005 pg 21 */
277        if (wifi->subtype & 0x8) 
278                extra += 2;
279
280        if (remaining && *remaining < sizeof(*eth)) {
281                *remaining = 0;
282                return NULL;
283        }
284
285        eth=(uint16_t *)((char*)wifi+sizeof(*wifi)+extra);
286       
287        if (*eth == 0xaaaa)
288                /* Payload contains an 802.2 LLC/SNAP frame */
289                return trace_get_payload_from_llcsnap((void *)eth, type, remaining);
290                       
291        /* Otherwise we assume an Ethernet II frame */
292        if (type) *type=ntohs(*eth);
293        if (remaining) *remaining = *remaining - sizeof(libtrace_80211_t) - extra - sizeof(*eth);
294       
295        return (void*)((char*)eth+sizeof(*eth));
296}
297
298static void *trace_get_payload_from_ppp(void *link, 
299                uint16_t *type, uint32_t *remaining)
300{
301        /* 64 byte capture. */
302        libtrace_ppp_t *ppp = (libtrace_ppp_t*)link;
303
304        if (remaining) {
305                if (*remaining < sizeof(libtrace_ppp_t)) {
306                        *remaining = 0;
307                        return NULL;
308                }
309                *remaining-=sizeof(libtrace_ppp_t);
310        }
311
312        if (type) {
313                switch(ntohs(ppp->protocol)) {
314                        case 0x0021: *type = TRACE_ETHERTYPE_IP; break;
315                        /* If it isn't IP, then it is probably PPP control and
316                         * I can't imagine anyone caring about that too much
317                         */
318                        default: *type = 0; break;
319                }
320        }
321
322
323        return (void*)((char *)ppp+sizeof(*ppp));
324}
325
326void *trace_get_payload_from_pppoe(void *link, uint16_t *type, 
327                uint32_t *remaining) {
328        assert(type);
329       
330        if (remaining) {
331                if (*remaining < sizeof(libtrace_pppoe_t)) {
332                        *remaining = 0;
333                        return NULL;
334                }
335                *remaining -= sizeof(libtrace_pppoe_t);
336        }
337       
338        /* PPPoE is always followed by PPP */
339        return trace_get_payload_from_ppp(link + sizeof(libtrace_pppoe_t),
340                        type, remaining);
341}
342       
343/* Header for CHDLC framing */
344typedef struct libtrace_chdlc_t {
345        uint8_t address;        /** 0xF0 for unicast, 0xF8 for multicast */
346        uint8_t control;        /** Always 0x00 */
347        uint16_t ethertype;
348} libtrace_chdlc_t;
349
350/* Header for PPP in HDLC-like framing */
351typedef struct libtrace_ppp_hdlc_t {
352        uint8_t address;        /** Always should be 0xff */
353        uint8_t control;        /** Always should be 0x03 */
354        uint16_t protocol;     
355} libtrace_ppp_hdlc_t;
356
357static void *trace_get_payload_from_chdlc(void *link, uint16_t *type,
358                uint32_t *remaining) {
359
360        libtrace_chdlc_t *chdlc = (libtrace_chdlc_t *)link;
361
362        if (remaining) {
363                if (*remaining < sizeof(libtrace_chdlc_t)) {
364                        *remaining = 0;
365                        return NULL;
366                }
367                *remaining -= sizeof(libtrace_chdlc_t);
368        }
369
370        if (type) {
371                *type = ntohs(chdlc->ethertype);
372        }
373
374        return (void *)((char *)chdlc + sizeof(*chdlc));
375
376}
377
378static void *trace_get_payload_from_ppp_hdlc(void *link, 
379                uint16_t *type, uint32_t *remaining)
380{
381        libtrace_ppp_hdlc_t *ppp_hdlc = (libtrace_ppp_hdlc_t*)link;
382
383        if (remaining) {
384                if (*remaining < sizeof(libtrace_ppp_hdlc_t)) {
385                        *remaining = 0;
386                        return NULL;
387                }
388                *remaining-=sizeof(libtrace_ppp_hdlc_t);
389        }
390
391        if (type) {
392                /* http://www.iana.org/assignments/ppp-numbers */
393
394                switch(ntohs(ppp_hdlc->protocol)) {
395                        case 0x0021: /* IP */
396                                *type = TRACE_ETHERTYPE_IP;
397                                break;
398                        case 0xc021: /* Link Control Protocol */
399                                *type = 0; /* No ethertype for this */
400                                break;
401
402                        default:
403                                printf("Unknown chdlc type: %04x\n",
404                                                ntohs(ppp_hdlc->protocol));
405                                *type = 0; /* Unknown */
406                }
407        }
408
409
410        return (void*)((char *)ppp_hdlc+sizeof(*ppp_hdlc));
411}
412
413void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
414                uint16_t *ethertype, uint32_t *remaining)
415{
416        void *l = NULL;
417
418        do {
419                l = trace_get_payload_from_meta(link, &linktype, remaining);
420                if (l != NULL) {
421                        link=l;
422                }
423        } while (l != NULL);
424
425        return trace_get_payload_from_layer2(link,linktype,ethertype,remaining);
426       
427}
428
429DLLEXPORT void *trace_get_layer2(const libtrace_packet_t *packet,
430                libtrace_linktype_t *linktype,
431                uint32_t *remaining) 
432{
433        uint32_t dummyrem;
434        void *meta = NULL;
435       
436        assert(packet != NULL);
437        assert(linktype != NULL);
438
439        if (remaining == NULL)
440                remaining = &dummyrem;
441
442        if (packet->l2_header) {
443                /* Use cached values */
444                *linktype = packet->link_type;
445                *remaining = packet->l2_remaining;
446                return packet->l2_header;
447        }
448
449        /* Code looks a bit inefficient, but I'm actually trying to avoid
450         * calling trace_get_packet_buffer more than once like we used to.
451         */
452       
453        meta = trace_get_packet_buffer(packet, linktype, remaining);
454
455        /* If there are no meta-data headers, we just return the start of the
456         * packet buffer, along with the linktype, etc.
457         */
458        switch(*linktype) {
459                /* meta points to a layer 2 header! */
460                case TRACE_TYPE_HDLC_POS:
461                case TRACE_TYPE_ETH:
462                case TRACE_TYPE_ATM:
463                case TRACE_TYPE_80211:
464                case TRACE_TYPE_NONE:
465                case TRACE_TYPE_POS:
466                case TRACE_TYPE_AAL5:
467                case TRACE_TYPE_DUCK:
468                case TRACE_TYPE_LLCSNAP:
469                case TRACE_TYPE_PPP:
470                case TRACE_TYPE_METADATA:
471                case TRACE_TYPE_NONDATA:
472                case TRACE_TYPE_OPENBSD_LOOP:
473                        ((libtrace_packet_t*)packet)->l2_header = meta;
474                        ((libtrace_packet_t*)packet)->l2_remaining = *remaining;
475                        return meta;
476                case TRACE_TYPE_LINUX_SLL:
477                case TRACE_TYPE_80211_RADIO:
478                case TRACE_TYPE_80211_PRISM:
479                case TRACE_TYPE_PFLOG:
480                        break;
481                case TRACE_TYPE_UNKNOWN:
482                        return NULL;
483        }
484
485        /* If there are meta-data headers, we need to skip over them until we
486         * find a non-meta data header and return that.
487         */
488        for(;;) {
489                void *nexthdr = trace_get_payload_from_meta(meta, 
490                                linktype, remaining);
491               
492                if (nexthdr == NULL) {
493                        switch (*linktype) {
494                                /* meta points to a layer 2 header! */
495                                case TRACE_TYPE_HDLC_POS:
496                                case TRACE_TYPE_ETH:
497                                case TRACE_TYPE_ATM:
498                                case TRACE_TYPE_80211:
499                                case TRACE_TYPE_NONE:
500                                case TRACE_TYPE_POS:
501                                case TRACE_TYPE_AAL5:
502                                case TRACE_TYPE_DUCK:
503                                case TRACE_TYPE_LLCSNAP:
504                                case TRACE_TYPE_PPP:
505                                case TRACE_TYPE_METADATA:
506                                case TRACE_TYPE_NONDATA:
507                                case TRACE_TYPE_OPENBSD_LOOP:
508                                        ((libtrace_packet_t*)packet)->l2_header = meta;
509                                        ((libtrace_packet_t*)packet)->l2_remaining = *remaining;
510                                        return meta;
511                                case TRACE_TYPE_LINUX_SLL:
512                                case TRACE_TYPE_80211_RADIO:
513                                case TRACE_TYPE_80211_PRISM:
514                                case TRACE_TYPE_PFLOG:
515                                        break;
516                                case TRACE_TYPE_UNKNOWN:
517                                        return NULL;
518                        }
519                       
520                        /* Otherwise, we must have hit the end of the packet */
521                        return NULL;
522                }
523         
524               
525                meta = nexthdr;
526        }
527
528}
529
530DLLEXPORT
531void *trace_get_payload_from_atm(void *link,
532                uint8_t *type, uint32_t *remaining)
533{
534        libtrace_atm_capture_cell_t *cell;
535        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t)) {
536                *remaining = 0;
537                return NULL;
538        }
539        cell=(libtrace_atm_capture_cell_t*)link;
540
541        if (type)
542                *type=cell->pt;
543
544        if (remaining)
545                *remaining-=sizeof(libtrace_atm_capture_cell_t);
546
547        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
548}
549
550
551
552DLLEXPORT void *trace_get_payload_from_layer2(void *link,
553                libtrace_linktype_t linktype,
554                uint16_t *ethertype,
555                uint32_t *remaining)
556{
557        void *l;
558
559        if (linktype == TRACE_TYPE_UNKNOWN) {
560                fprintf(stderr, "Unable to determine linktype for packet\n");
561                return NULL;
562        }
563       
564        switch(linktype) {
565                /* Packet Metadata headers, not layer2 headers */
566                case TRACE_TYPE_80211_PRISM:
567                case TRACE_TYPE_80211_RADIO:
568                case TRACE_TYPE_PFLOG:
569                case TRACE_TYPE_LINUX_SLL:
570                        return NULL;
571
572                /* duck packets have no payload! */
573                case TRACE_TYPE_DUCK:
574                        return NULL;
575
576                /* The payload is in these packets does
577                   not correspond to a genuine link-layer
578                   */
579                case TRACE_TYPE_METADATA:
580                case TRACE_TYPE_NONDATA:
581                case TRACE_TYPE_UNKNOWN:
582                        return NULL;
583
584                case TRACE_TYPE_80211:
585                        return trace_get_payload_from_80211(link,ethertype,remaining);
586                case TRACE_TYPE_ETH:
587                        return trace_get_payload_from_ethernet(link,ethertype,remaining);
588                case TRACE_TYPE_NONE:
589                        if ((*(char*)link&0xF0) == 0x40)
590                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
591                        else if ((*(char*)link&0xF0) == 0x60)
592                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
593                        return link; /* I love the simplicity */
594                case TRACE_TYPE_PPP:
595                        return trace_get_payload_from_ppp(link,ethertype,remaining);
596                case TRACE_TYPE_ATM:
597                        l=trace_get_payload_from_atm(link,NULL,remaining);
598                        /* FIXME: We shouldn't skip llcsnap here, we should
599                         * return an ethertype for it (somehow)
600                         */
601                        return (l ? trace_get_payload_from_llcsnap(l,
602                                                ethertype, remaining):NULL);
603                case TRACE_TYPE_LLCSNAP:
604                        return trace_get_payload_from_llcsnap(link,ethertype,remaining);
605
606                case TRACE_TYPE_HDLC_POS:
607                        return trace_get_payload_from_chdlc(link,ethertype,
608                                        remaining);
609                case TRACE_TYPE_POS:
610                        return trace_get_payload_from_ppp_hdlc(link,ethertype,
611                                        remaining);
612                /* TODO: Unsupported */
613                case TRACE_TYPE_AAL5:
614                        return NULL;
615
616                case TRACE_TYPE_OPENBSD_LOOP:
617                        link = link + 4; /* Loopback header is 4 bytes */
618                        if ((*(char*)link&0xF0) == 0x40)
619                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
620                        else if ((*(char*)link&0xF0) == 0x60)
621                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
622                        return link; /* I love the simplicity */
623               
624
625        }
626        return NULL;
627
628}
629
630/* Take a pointer to the start of an IEEE 802.11 MAC frame and return a pointer
631 * to the source MAC address. 
632 * If the frame does not contain a sender address, e.g. ACK frame, return NULL.
633 * If the frame is a 4-address WDS frame, return TA, i.e. addr2.
634 * NB: This function decodes the 802.11 header, so it assumes that there are no
635 * bit-errors. If there are, all bets are off.
636 */
637static
638uint8_t *get_source_mac_from_wifi(void *wifi) {
639        struct libtrace_80211_t *w;
640        if (wifi == NULL) return NULL;
641        w = (struct libtrace_80211_t *) wifi;
642
643        /* If the frame is of type CTRL */
644        if (w->type == 0x1)
645                /* If bit 2 of the subtype field is zero, this indicates that
646                 * there is no transmitter address, i.e. the frame is either an
647                 * ACK or a CTS frame */
648                if ((w->subtype & 0x2) == 0)
649                        return NULL;
650
651        /* Always return the address of the transmitter, i.e. address 2 */
652        return (uint8_t *) &w->mac2;
653}
654
655DLLEXPORT uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
656        void *link;
657        uint32_t remaining;
658        libtrace_linktype_t linktype;
659        assert(packet);
660        link = trace_get_layer2(packet,&linktype,&remaining);
661
662        if (!link)
663                return NULL;
664
665        switch (linktype) {
666                case TRACE_TYPE_ETH:
667                        return (uint8_t *)&(((libtrace_ether_t*)link)->ether_shost);
668                case TRACE_TYPE_80211:
669                        return get_source_mac_from_wifi(link);
670                /* These packets don't have MAC addresses */
671                case TRACE_TYPE_POS:
672                case TRACE_TYPE_NONE:
673                case TRACE_TYPE_HDLC_POS:
674                case TRACE_TYPE_PFLOG:
675                case TRACE_TYPE_ATM:
676                case TRACE_TYPE_DUCK:
677                case TRACE_TYPE_METADATA:
678                case TRACE_TYPE_AAL5:
679                case TRACE_TYPE_LLCSNAP:
680                case TRACE_TYPE_PPP:
681                case TRACE_TYPE_NONDATA:
682                case TRACE_TYPE_OPENBSD_LOOP:
683                case TRACE_TYPE_UNKNOWN:
684                        return NULL;
685
686                /* Metadata headers should already be skipped */
687                case TRACE_TYPE_LINUX_SLL:
688                case TRACE_TYPE_80211_PRISM:
689                case TRACE_TYPE_80211_RADIO:
690                        assert(!"Metadata headers should already be skipped");
691                        break;
692        }
693        fprintf(stderr,"%s not implemented for linktype %i\n", __func__, linktype);
694        assert(0);
695        return NULL;
696}
697
698DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet)
699{
700        void *link;
701        libtrace_linktype_t linktype;
702        uint32_t remaining;
703        libtrace_80211_t *wifi;
704        libtrace_ether_t *ethptr;
705
706        link = trace_get_layer2(packet,&linktype,&remaining);
707
708        ethptr = (libtrace_ether_t*)link;
709
710
711        if (!link)
712                return NULL;
713
714        switch (linktype) {
715                case TRACE_TYPE_80211:
716                        wifi=(libtrace_80211_t*)link;
717                        return (uint8_t*)&wifi->mac1;
718                case TRACE_TYPE_ETH:
719                        return (uint8_t*)&ethptr->ether_dhost;
720                case TRACE_TYPE_POS:
721                case TRACE_TYPE_NONE:
722                case TRACE_TYPE_ATM:
723                case TRACE_TYPE_HDLC_POS:
724                case TRACE_TYPE_PFLOG:
725                case TRACE_TYPE_DUCK:
726                case TRACE_TYPE_METADATA:
727                case TRACE_TYPE_AAL5:
728                case TRACE_TYPE_LLCSNAP:
729                case TRACE_TYPE_PPP:   
730                case TRACE_TYPE_NONDATA:
731                case TRACE_TYPE_OPENBSD_LOOP:
732                case TRACE_TYPE_UNKNOWN:
733                        /* No MAC address */
734                        return NULL;
735                /* Metadata headers should already be skipped */
736                case TRACE_TYPE_LINUX_SLL:
737                case TRACE_TYPE_80211_PRISM:
738                case TRACE_TYPE_80211_RADIO:
739                        assert(!"Metadata headers should already be skipped");
740                        break;
741        }
742        fprintf(stderr,"Not implemented\n");
743        assert(0);
744        return NULL;
745}
746
Note: See TracBrowser for help on using the repository browser.