source: lib/protocols_l2.c @ 2193905

develop
Last change on this file since 2193905 was 2193905, checked in by Jacob Van Walraven <jcv9@…>, 2 years ago

Apply changes required for pull request #81

  • Property mode set to 100644
File size: 21.6 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->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->l2_header) {
459                /* Use cached values */
460                *linktype = packet->link_type;
461                *remaining = packet->l2_remaining;
462                return packet->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)->l2_header = meta;
490                        ((libtrace_packet_t*)packet)->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_ETSILI:
498                        break;
499                case TRACE_TYPE_UNKNOWN:
500                case TRACE_TYPE_CONTENT_INVALID:
501                        return NULL;
502        }
503
504        /* If there are meta-data headers, we need to skip over them until we
505         * find a non-meta data header and return that.
506         */
507        for(;;) {
508                void *nexthdr = trace_get_payload_from_meta(meta, 
509                                linktype, remaining);
510               
511                if (nexthdr == NULL) {
512                        switch (*linktype) {
513                                /* meta points to a layer 2 header! */
514                                case TRACE_TYPE_HDLC_POS:
515                                case TRACE_TYPE_ETH:
516                                case TRACE_TYPE_ATM:
517                                case TRACE_TYPE_80211:
518                                case TRACE_TYPE_NONE:
519                                case TRACE_TYPE_POS:
520                                case TRACE_TYPE_AAL5:
521                                case TRACE_TYPE_DUCK:
522                                case TRACE_TYPE_LLCSNAP:
523                                case TRACE_TYPE_PPP:
524                                case TRACE_TYPE_METADATA:
525                                case TRACE_TYPE_NONDATA:
526                                case TRACE_TYPE_OPENBSD_LOOP:
527                                        ((libtrace_packet_t*)packet)->l2_header = meta;
528                                        ((libtrace_packet_t*)packet)->l2_remaining = *remaining;
529                                        return meta;
530                                case TRACE_TYPE_LINUX_SLL:
531                                case TRACE_TYPE_80211_RADIO:
532                                case TRACE_TYPE_80211_PRISM:
533                                case TRACE_TYPE_PFLOG:
534                                case TRACE_TYPE_ERF_META:
535                                case TRACE_TYPE_ETSILI:
536                                        break;
537                                case TRACE_TYPE_UNKNOWN:
538                                case TRACE_TYPE_CONTENT_INVALID:
539                                        return NULL;
540                        }
541                       
542                        /* Otherwise, we must have hit the end of the packet */
543                        return NULL;
544                }
545         
546               
547                meta = nexthdr;
548        }
549
550}
551
552DLLEXPORT
553void *trace_get_payload_from_atm(void *link,
554                uint8_t *type, uint32_t *remaining)
555{
556        libtrace_atm_capture_cell_t *cell;
557        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t)) {
558                *remaining = 0;
559                return NULL;
560        }
561        cell=(libtrace_atm_capture_cell_t*)link;
562
563        if (type)
564                *type=cell->pt;
565
566        if (remaining)
567                *remaining-=sizeof(libtrace_atm_capture_cell_t);
568
569        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
570}
571
572
573
574DLLEXPORT void *trace_get_payload_from_layer2(void *link,
575                libtrace_linktype_t linktype,
576                uint16_t *ethertype,
577                uint32_t *remaining)
578{
579        void *l;
580
581        if (linktype == TRACE_TYPE_UNKNOWN ||
582                        linktype == TRACE_TYPE_CONTENT_INVALID) {
583                fprintf(stderr, "Unable to determine linktype for packet\n");
584                return NULL;
585        }
586       
587        switch(linktype) {
588                /* Packet Metadata headers, not layer2 headers */
589                case TRACE_TYPE_80211_PRISM:
590                case TRACE_TYPE_80211_RADIO:
591                case TRACE_TYPE_PFLOG:
592                case TRACE_TYPE_LINUX_SLL:
593                case TRACE_TYPE_ETSILI:
594                        return NULL;
595
596                /* duck packets have no payload! */
597                case TRACE_TYPE_DUCK:
598                        return NULL;
599
600                /* The payload is in these packets does
601                   not correspond to a genuine link-layer
602                   */
603                case TRACE_TYPE_METADATA:
604                case TRACE_TYPE_NONDATA:
605                case TRACE_TYPE_ERF_META:
606                case TRACE_TYPE_CONTENT_INVALID:
607                case TRACE_TYPE_UNKNOWN:
608                        return NULL;
609
610                case TRACE_TYPE_80211:
611                        return trace_get_payload_from_80211(link,ethertype,remaining);
612                case TRACE_TYPE_ETH:
613                        return trace_get_payload_from_ethernet(link,ethertype,remaining);
614                case TRACE_TYPE_NONE:
615                        if ((*(char*)link&0xF0) == 0x40)
616                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
617                        else if ((*(char*)link&0xF0) == 0x60)
618                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
619                        return link; /* I love the simplicity */
620                case TRACE_TYPE_PPP:
621                        return trace_get_payload_from_ppp(link,ethertype,remaining);
622                case TRACE_TYPE_ATM:
623                        l=trace_get_payload_from_atm(link,NULL,remaining);
624                        /* FIXME: We shouldn't skip llcsnap here, we should
625                         * return an ethertype for it (somehow)
626                         */
627                        return (l ? trace_get_payload_from_llcsnap(l,
628                                                ethertype, remaining):NULL);
629                case TRACE_TYPE_LLCSNAP:
630                        return trace_get_payload_from_llcsnap(link,ethertype,remaining);
631
632                case TRACE_TYPE_HDLC_POS:
633                        return trace_get_payload_from_chdlc(link,ethertype,
634                                        remaining);
635                case TRACE_TYPE_POS:
636                        return trace_get_payload_from_ppp_hdlc(link,ethertype,
637                                        remaining);
638                /* TODO: Unsupported */
639                case TRACE_TYPE_AAL5:
640                        return NULL;
641
642                case TRACE_TYPE_OPENBSD_LOOP:
643                        link = link + 4; /* Loopback header is 4 bytes */
644                        if ((*(char*)link&0xF0) == 0x40)
645                                *ethertype=TRACE_ETHERTYPE_IP;   /* IPv4 */
646                        else if ((*(char*)link&0xF0) == 0x60)
647                                *ethertype=TRACE_ETHERTYPE_IPV6; /* IPv6 */
648                        return link; /* I love the simplicity */
649               
650
651        }
652        return NULL;
653
654}
655
656/* Take a pointer to the start of an IEEE 802.11 MAC frame and return a pointer
657 * to the source MAC address. 
658 * If the frame does not contain a sender address, e.g. ACK frame, return NULL.
659 * If the frame is a 4-address WDS frame, return TA, i.e. addr2.
660 * NB: This function decodes the 802.11 header, so it assumes that there are no
661 * bit-errors. If there are, all bets are off.
662 */
663static
664uint8_t *get_source_mac_from_wifi(void *wifi) {
665        struct libtrace_80211_t *w;
666        if (wifi == NULL) return NULL;
667        w = (struct libtrace_80211_t *) wifi;
668
669        /* If the frame is of type CTRL */
670        if (w->type == 0x1)
671                /* If bit 2 of the subtype field is zero, this indicates that
672                 * there is no transmitter address, i.e. the frame is either an
673                 * ACK or a CTS frame */
674                if ((w->subtype & 0x2) == 0)
675                        return NULL;
676
677        /* Always return the address of the transmitter, i.e. address 2 */
678        return (uint8_t *) &w->mac2;
679}
680
681DLLEXPORT uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
682        /* Ensure the supplied packet is not NULL */
683        if (!packet) {
684                fprintf(stderr, "NULL packet passed into trace_get_source_mac()\n");
685                return NULL;
686        }
687
688        void *link;
689        uint32_t remaining;
690        libtrace_linktype_t linktype;
691        link = trace_get_layer2(packet,&linktype,&remaining);
692
693        if (!link)
694                return NULL;
695
696        switch (linktype) {
697                case TRACE_TYPE_ETH:
698                        return (uint8_t *)&(((libtrace_ether_t*)link)->ether_shost);
699                case TRACE_TYPE_80211:
700                        return get_source_mac_from_wifi(link);
701                /* These packets don't have MAC addresses */
702                case TRACE_TYPE_POS:
703                case TRACE_TYPE_NONE:
704                case TRACE_TYPE_HDLC_POS:
705                case TRACE_TYPE_PFLOG:
706                case TRACE_TYPE_ATM:
707                case TRACE_TYPE_DUCK:
708                case TRACE_TYPE_METADATA:
709                case TRACE_TYPE_AAL5:
710                case TRACE_TYPE_LLCSNAP:
711                case TRACE_TYPE_PPP:
712                case TRACE_TYPE_NONDATA:
713                case TRACE_TYPE_OPENBSD_LOOP:
714                case TRACE_TYPE_ERF_META:
715                case TRACE_TYPE_UNKNOWN:
716                case TRACE_TYPE_CONTENT_INVALID:
717                        return NULL;
718
719                /* Metadata headers should already be skipped */
720                case TRACE_TYPE_LINUX_SLL:
721                case TRACE_TYPE_80211_PRISM:
722                case TRACE_TYPE_80211_RADIO:
723                case TRACE_TYPE_ETSILI:
724                        fprintf(stderr, "Metadata headers should already be skipped in trace_get_source_mac()\n");
725                        return NULL;
726        }
727        fprintf(stderr,"%s not implemented for linktype %i\n", __func__, linktype);
728        return NULL;
729}
730
731DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
732        /* Ensure the supplied packet is not NULL */
733        if (!packet) {
734                fprintf(stderr, "NULL packet passed into trace_get_destination_mac()\n");
735                return NULL;
736        }
737
738        void *link;
739        libtrace_linktype_t linktype;
740        uint32_t remaining;
741        libtrace_80211_t *wifi;
742        libtrace_ether_t *ethptr;
743
744        link = trace_get_layer2(packet,&linktype,&remaining);
745
746        ethptr = (libtrace_ether_t*)link;
747
748
749        if (!link)
750                return NULL;
751
752        switch (linktype) {
753                case TRACE_TYPE_80211:
754                        wifi=(libtrace_80211_t*)link;
755                        return (uint8_t*)&wifi->mac1;
756                case TRACE_TYPE_ETH:
757                        return (uint8_t*)&ethptr->ether_dhost;
758                case TRACE_TYPE_POS:
759                case TRACE_TYPE_NONE:
760                case TRACE_TYPE_ATM:
761                case TRACE_TYPE_HDLC_POS:
762                case TRACE_TYPE_PFLOG:
763                case TRACE_TYPE_DUCK:
764                case TRACE_TYPE_METADATA:
765                case TRACE_TYPE_AAL5:
766                case TRACE_TYPE_LLCSNAP:
767                case TRACE_TYPE_PPP:   
768                case TRACE_TYPE_NONDATA:
769                case TRACE_TYPE_OPENBSD_LOOP:
770                case TRACE_TYPE_ERF_META:
771                case TRACE_TYPE_UNKNOWN:
772                case TRACE_TYPE_CONTENT_INVALID:
773                        /* No MAC address */
774                        return NULL;
775                /* Metadata headers should already be skipped */
776                case TRACE_TYPE_LINUX_SLL:
777                case TRACE_TYPE_80211_PRISM:
778                case TRACE_TYPE_80211_RADIO:
779                case TRACE_TYPE_ETSILI:
780                        fprintf(stderr, "Metadata headers should already be skipped in trace_get_destination_mac()\n");
781                        return NULL;
782        }
783        fprintf(stderr,"Not implemented\n");
784        return NULL;
785}
786
Note: See TracBrowser for help on using the repository browser.