source: lib/protocols_l2.c @ 49f8ceb

develop
Last change on this file since 49f8ceb was 49f8ceb, checked in by Jacob Van Walraven <jcv9@…>, 22 months ago

Fix incorrect type id for pcapng_meta, fix compiler warnings

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