source: lib/protocols_l2.c @ fe4940e

developringperformance
Last change on this file since fe4940e was fe4940e, checked in by Shane Alcock <salcock@…>, 2 years ago

Cache packet framing length to avoid multiple calculations

Also when stripping vlan etc. headers, don't try to memmove if zero
bytes are going to be moved.

  • Property mode set to 100644
File size: 21.0 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 && removed > 0) {
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                        case 0x0057: *type = TRACE_ETHERTYPE_IPV6; break;                               
316                        /* If it isn't IP, then it is probably PPP control and
317                         * I can't imagine anyone caring about that too much
318                         */
319                        default: *type = 0; break;
320                }
321        }
322
323
324        return (void*)((char *)ppp+sizeof(*ppp));
325}
326
327void *trace_get_payload_from_pppoe(void *link, uint16_t *type, 
328                uint32_t *remaining) {
329        assert(type);
330       
331        if (remaining) {
332                if (*remaining < sizeof(libtrace_pppoe_t)) {
333                        *remaining = 0;
334                        return NULL;
335                }
336                *remaining -= sizeof(libtrace_pppoe_t);
337        }
338       
339        /* PPPoE is always followed by PPP */
340        return trace_get_payload_from_ppp(link + sizeof(libtrace_pppoe_t),
341                        type, remaining);
342}
343       
344/* Header for CHDLC framing */
345typedef struct libtrace_chdlc_t {
346        uint8_t address;        /** 0xF0 for unicast, 0xF8 for multicast */
347        uint8_t control;        /** Always 0x00 */
348        uint16_t ethertype;
349} libtrace_chdlc_t;
350
351/* Header for PPP in HDLC-like framing */
352typedef struct libtrace_ppp_hdlc_t {
353        uint8_t address;        /** Always should be 0xff */
354        uint8_t control;        /** Always should be 0x03 */
355        uint16_t protocol;     
356} libtrace_ppp_hdlc_t;
357
358static void *trace_get_payload_from_chdlc(void *link, uint16_t *type,
359                uint32_t *remaining) {
360
361        libtrace_chdlc_t *chdlc = (libtrace_chdlc_t *)link;
362
363        if (remaining) {
364                if (*remaining < sizeof(libtrace_chdlc_t)) {
365                        *remaining = 0;
366                        return NULL;
367                }
368                *remaining -= sizeof(libtrace_chdlc_t);
369        }
370
371        if (type) {
372                *type = ntohs(chdlc->ethertype);
373        }
374
375        return (void *)((char *)chdlc + sizeof(*chdlc));
376
377}
378
379static void *trace_get_payload_from_ppp_hdlc(void *link, 
380                uint16_t *type, uint32_t *remaining)
381{
382        libtrace_ppp_hdlc_t *ppp_hdlc = (libtrace_ppp_hdlc_t*)link;
383
384        if (remaining) {
385                if (*remaining < sizeof(libtrace_ppp_hdlc_t)) {
386                        *remaining = 0;
387                        return NULL;
388                }
389                *remaining-=sizeof(libtrace_ppp_hdlc_t);
390        }
391
392        if (type) {
393                /* http://www.iana.org/assignments/ppp-numbers */
394
395                switch(ntohs(ppp_hdlc->protocol)) {
396                        case 0x0021: /* IP */
397                                *type = TRACE_ETHERTYPE_IP;
398                                break;
399                        case 0x0057: /* IPV6 */
400                                *type = TRACE_ETHERTYPE_IPV6;
401                                break;
402                        case 0xc021: /* Link Control Protocol */
403                                *type = 0; /* No ethertype for this */
404                                break;
405
406                        default:
407                                printf("Unknown chdlc type: %04x\n",
408                                                ntohs(ppp_hdlc->protocol));
409                                *type = 0; /* Unknown */
410                }
411        }
412
413
414        return (void*)((char *)ppp_hdlc+sizeof(*ppp_hdlc));
415}
416
417void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
418                uint16_t *ethertype, uint32_t *remaining)
419{
420        void *l = NULL;
421
422        do {
423                l = trace_get_payload_from_meta(link, &linktype, remaining);
424                if (l != NULL) {
425                        link=l;
426                }
427        } while (l != NULL);
428
429        return trace_get_payload_from_layer2(link,linktype,ethertype,remaining);
430       
431}
432
433DLLEXPORT void *trace_get_layer2(const libtrace_packet_t *packet,
434                libtrace_linktype_t *linktype,
435                uint32_t *remaining) 
436{
437        uint32_t dummyrem;
438        void *meta = NULL;
439       
440        assert(packet != NULL);
441        assert(linktype != NULL);
442
443        if (remaining == NULL)
444                remaining = &dummyrem;
445
446        if (packet->l2_header) {
447                /* Use cached values */
448                *linktype = packet->link_type;
449                *remaining = packet->l2_remaining;
450                return packet->l2_header;
451        }
452
453        /* Code looks a bit inefficient, but I'm actually trying to avoid
454         * calling trace_get_packet_buffer more than once like we used to.
455         */
456       
457        meta = trace_get_packet_buffer(packet, linktype, remaining);
458
459        /* If there are no meta-data headers, we just return the start of the
460         * packet buffer, along with the linktype, etc.
461         */
462        switch(*linktype) {
463                /* meta points to a layer 2 header! */
464                case TRACE_TYPE_HDLC_POS:
465                case TRACE_TYPE_ETH:
466                case TRACE_TYPE_ATM:
467                case TRACE_TYPE_80211:
468                case TRACE_TYPE_NONE:
469                case TRACE_TYPE_POS:
470                case TRACE_TYPE_AAL5:
471                case TRACE_TYPE_DUCK:
472                case TRACE_TYPE_LLCSNAP:
473                case TRACE_TYPE_PPP:
474                case TRACE_TYPE_METADATA:
475                case TRACE_TYPE_NONDATA:
476                case TRACE_TYPE_OPENBSD_LOOP:
477                        ((libtrace_packet_t*)packet)->l2_header = meta;
478                        ((libtrace_packet_t*)packet)->l2_remaining = *remaining;
479                        return meta;
480                case TRACE_TYPE_LINUX_SLL:
481                case TRACE_TYPE_80211_RADIO:
482                case TRACE_TYPE_80211_PRISM:
483                case TRACE_TYPE_PFLOG:
484                case TRACE_TYPE_ERF_META:
485                case TRACE_TYPE_ETSILI:
486                        break;
487                case TRACE_TYPE_UNKNOWN:
488                case TRACE_TYPE_CONTENT_INVALID:
489                        return NULL;
490        }
491
492        /* If there are meta-data headers, we need to skip over them until we
493         * find a non-meta data header and return that.
494         */
495        for(;;) {
496                void *nexthdr = trace_get_payload_from_meta(meta, 
497                                linktype, remaining);
498               
499                if (nexthdr == NULL) {
500                        switch (*linktype) {
501                                /* meta points to a layer 2 header! */
502                                case TRACE_TYPE_HDLC_POS:
503                                case TRACE_TYPE_ETH:
504                                case TRACE_TYPE_ATM:
505                                case TRACE_TYPE_80211:
506                                case TRACE_TYPE_NONE:
507                                case TRACE_TYPE_POS:
508                                case TRACE_TYPE_AAL5:
509                                case TRACE_TYPE_DUCK:
510                                case TRACE_TYPE_LLCSNAP:
511                                case TRACE_TYPE_PPP:
512                                case TRACE_TYPE_METADATA:
513                                case TRACE_TYPE_NONDATA:
514                                case TRACE_TYPE_OPENBSD_LOOP:
515                                        ((libtrace_packet_t*)packet)->l2_header = meta;
516                                        ((libtrace_packet_t*)packet)->l2_remaining = *remaining;
517                                        return meta;
518                                case TRACE_TYPE_LINUX_SLL:
519                                case TRACE_TYPE_80211_RADIO:
520                                case TRACE_TYPE_80211_PRISM:
521                                case TRACE_TYPE_PFLOG:
522                                case TRACE_TYPE_ERF_META:
523                                case TRACE_TYPE_ETSILI:
524                                        break;
525                                case TRACE_TYPE_UNKNOWN:
526                                case TRACE_TYPE_CONTENT_INVALID:
527                                        return NULL;
528                        }
529                       
530                        /* Otherwise, we must have hit the end of the packet */
531                        return NULL;
532                }
533         
534               
535                meta = nexthdr;
536        }
537
538}
539
540DLLEXPORT
541void *trace_get_payload_from_atm(void *link,
542                uint8_t *type, uint32_t *remaining)
543{
544        libtrace_atm_capture_cell_t *cell;
545        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t)) {
546                *remaining = 0;
547                return NULL;
548        }
549        cell=(libtrace_atm_capture_cell_t*)link;
550
551        if (type)
552                *type=cell->pt;
553
554        if (remaining)
555                *remaining-=sizeof(libtrace_atm_capture_cell_t);
556
557        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
558}
559
560
561
562DLLEXPORT void *trace_get_payload_from_layer2(void *link,
563                libtrace_linktype_t linktype,
564                uint16_t *ethertype,
565                uint32_t *remaining)
566{
567        void *l;
568
569        if (linktype == TRACE_TYPE_UNKNOWN ||
570                        linktype == TRACE_TYPE_CONTENT_INVALID) {
571                fprintf(stderr, "Unable to determine linktype for packet\n");
572                return NULL;
573        }
574       
575        switch(linktype) {
576                /* Packet Metadata headers, not layer2 headers */
577                case TRACE_TYPE_80211_PRISM:
578                case TRACE_TYPE_80211_RADIO:
579                case TRACE_TYPE_PFLOG:
580                case TRACE_TYPE_LINUX_SLL:
581                case TRACE_TYPE_ETSILI:
582                        return NULL;
583
584                /* duck packets have no payload! */
585                case TRACE_TYPE_DUCK:
586                        return NULL;
587
588                /* The payload is in these packets does
589                   not correspond to a genuine link-layer
590                   */
591                case TRACE_TYPE_METADATA:
592                case TRACE_TYPE_NONDATA:
593                case TRACE_TYPE_ERF_META:
594                case TRACE_TYPE_CONTENT_INVALID:
595                case TRACE_TYPE_UNKNOWN:
596                        return NULL;
597
598                case TRACE_TYPE_80211:
599                        return trace_get_payload_from_80211(link,ethertype,remaining);
600                case TRACE_TYPE_ETH:
601                        return trace_get_payload_from_ethernet(link,ethertype,remaining);
602                case TRACE_TYPE_NONE:
603                        if ((*(char*)link&0xF0) == 0x40)
604                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
605                        else if ((*(char*)link&0xF0) == 0x60)
606                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
607                        return link; /* I love the simplicity */
608                case TRACE_TYPE_PPP:
609                        return trace_get_payload_from_ppp(link,ethertype,remaining);
610                case TRACE_TYPE_ATM:
611                        l=trace_get_payload_from_atm(link,NULL,remaining);
612                        /* FIXME: We shouldn't skip llcsnap here, we should
613                         * return an ethertype for it (somehow)
614                         */
615                        return (l ? trace_get_payload_from_llcsnap(l,
616                                                ethertype, remaining):NULL);
617                case TRACE_TYPE_LLCSNAP:
618                        return trace_get_payload_from_llcsnap(link,ethertype,remaining);
619
620                case TRACE_TYPE_HDLC_POS:
621                        return trace_get_payload_from_chdlc(link,ethertype,
622                                        remaining);
623                case TRACE_TYPE_POS:
624                        return trace_get_payload_from_ppp_hdlc(link,ethertype,
625                                        remaining);
626                /* TODO: Unsupported */
627                case TRACE_TYPE_AAL5:
628                        return NULL;
629
630                case TRACE_TYPE_OPENBSD_LOOP:
631                        link = link + 4; /* Loopback header is 4 bytes */
632                        if ((*(char*)link&0xF0) == 0x40)
633                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
634                        else if ((*(char*)link&0xF0) == 0x60)
635                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
636                        return link; /* I love the simplicity */
637               
638
639        }
640        return NULL;
641
642}
643
644/* Take a pointer to the start of an IEEE 802.11 MAC frame and return a pointer
645 * to the source MAC address. 
646 * If the frame does not contain a sender address, e.g. ACK frame, return NULL.
647 * If the frame is a 4-address WDS frame, return TA, i.e. addr2.
648 * NB: This function decodes the 802.11 header, so it assumes that there are no
649 * bit-errors. If there are, all bets are off.
650 */
651static
652uint8_t *get_source_mac_from_wifi(void *wifi) {
653        struct libtrace_80211_t *w;
654        if (wifi == NULL) return NULL;
655        w = (struct libtrace_80211_t *) wifi;
656
657        /* If the frame is of type CTRL */
658        if (w->type == 0x1)
659                /* If bit 2 of the subtype field is zero, this indicates that
660                 * there is no transmitter address, i.e. the frame is either an
661                 * ACK or a CTS frame */
662                if ((w->subtype & 0x2) == 0)
663                        return NULL;
664
665        /* Always return the address of the transmitter, i.e. address 2 */
666        return (uint8_t *) &w->mac2;
667}
668
669DLLEXPORT uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
670        void *link;
671        uint32_t remaining;
672        libtrace_linktype_t linktype;
673        assert(packet);
674        link = trace_get_layer2(packet,&linktype,&remaining);
675
676        if (!link)
677                return NULL;
678
679        switch (linktype) {
680                case TRACE_TYPE_ETH:
681                        return (uint8_t *)&(((libtrace_ether_t*)link)->ether_shost);
682                case TRACE_TYPE_80211:
683                        return get_source_mac_from_wifi(link);
684                /* These packets don't have MAC addresses */
685                case TRACE_TYPE_POS:
686                case TRACE_TYPE_NONE:
687                case TRACE_TYPE_HDLC_POS:
688                case TRACE_TYPE_PFLOG:
689                case TRACE_TYPE_ATM:
690                case TRACE_TYPE_DUCK:
691                case TRACE_TYPE_METADATA:
692                case TRACE_TYPE_AAL5:
693                case TRACE_TYPE_LLCSNAP:
694                case TRACE_TYPE_PPP:
695                case TRACE_TYPE_NONDATA:
696                case TRACE_TYPE_OPENBSD_LOOP:
697                case TRACE_TYPE_ERF_META:
698                case TRACE_TYPE_UNKNOWN:
699                case TRACE_TYPE_CONTENT_INVALID:
700                        return NULL;
701
702                /* Metadata headers should already be skipped */
703                case TRACE_TYPE_LINUX_SLL:
704                case TRACE_TYPE_80211_PRISM:
705                case TRACE_TYPE_80211_RADIO:
706                case TRACE_TYPE_ETSILI:
707                        assert(!"Metadata headers should already be skipped");
708                        break;
709        }
710        fprintf(stderr,"%s not implemented for linktype %i\n", __func__, linktype);
711        assert(0);
712        return NULL;
713}
714
715DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet)
716{
717        void *link;
718        libtrace_linktype_t linktype;
719        uint32_t remaining;
720        libtrace_80211_t *wifi;
721        libtrace_ether_t *ethptr;
722
723        link = trace_get_layer2(packet,&linktype,&remaining);
724
725        ethptr = (libtrace_ether_t*)link;
726
727
728        if (!link)
729                return NULL;
730
731        switch (linktype) {
732                case TRACE_TYPE_80211:
733                        wifi=(libtrace_80211_t*)link;
734                        return (uint8_t*)&wifi->mac1;
735                case TRACE_TYPE_ETH:
736                        return (uint8_t*)&ethptr->ether_dhost;
737                case TRACE_TYPE_POS:
738                case TRACE_TYPE_NONE:
739                case TRACE_TYPE_ATM:
740                case TRACE_TYPE_HDLC_POS:
741                case TRACE_TYPE_PFLOG:
742                case TRACE_TYPE_DUCK:
743                case TRACE_TYPE_METADATA:
744                case TRACE_TYPE_AAL5:
745                case TRACE_TYPE_LLCSNAP:
746                case TRACE_TYPE_PPP:   
747                case TRACE_TYPE_NONDATA:
748                case TRACE_TYPE_OPENBSD_LOOP:
749                case TRACE_TYPE_ERF_META:
750                case TRACE_TYPE_UNKNOWN:
751                case TRACE_TYPE_CONTENT_INVALID:
752                        /* No MAC address */
753                        return NULL;
754                /* Metadata headers should already be skipped */
755                case TRACE_TYPE_LINUX_SLL:
756                case TRACE_TYPE_80211_PRISM:
757                case TRACE_TYPE_80211_RADIO:
758                case TRACE_TYPE_ETSILI:
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.