source: lib/protocols_l2.c @ 7428ab2

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

Add trace_strip_packet to libtrace API

This function will allow callers to strip MPLS and VLAN headers from
libtrace packets. Some analysis tools (especially those written with
libpcap in the days before these technologies were popular) don't
work so well when these headers are present.

Stripping VLAN headers also makes BPF filtering easier.

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