source: lib/protocols_l2.c @ 84d137d

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

Attempt at a faster stripping approach

Unfortunately, the stripping is more indiscriminate. We won't be able
to choose whether we just want VLAN or MPLS stripped -- it'll all get
thrown away, but this is probably the most common use case anyway.

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