source: lib/protocols.c @ 1803a27

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 1803a27 was 1803a27, checked in by Scott Raynel <smr26@…>, 15 years ago

Fixes in get_payload_from_80211():

  • Detect the presence of 802.2 LLC/SNAP in 802.11 and skip accordingly
  • Detect whether an 802.11 MAC frame has 3 or 4 MAC addresses and skip accordingly
  • Property mode set to 100644
File size: 21.7 KB
Line 
1/* This file has the various helper functions used to decode various protocols
2 *
3 * $Id$
4 */ 
5#include "libtrace.h"
6#include "libtrace_int.h"
7#include "wag.h"
8#include <assert.h>
9#include <stdio.h>
10
11#ifndef WIN32
12#include <net/if_arp.h>
13#endif
14
15#ifndef ARPHRD_ETHER
16#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
17#endif
18
19#ifndef ARPHRD_PPP
20#define ARPHRD_PPP      512
21#endif
22
23
24/* Returns the payload from 802.3 ethernet.  Type optionally returned in
25 * "type" in host byte order.  This will return a vlan header.
26 */
27static void *trace_get_payload_from_ethernet(void *ethernet, 
28                uint16_t *type,
29                uint32_t *remaining)
30{
31        libtrace_ether_t *eth = (libtrace_ether_t*)ethernet;
32
33        if (remaining) {
34                if (*remaining < sizeof(*eth))
35                        return NULL;
36                *remaining-=sizeof(*eth);
37        }
38
39        if (type)
40                *type = ntohs(eth->ether_type);
41
42        return (void*)((char *)eth + sizeof(*eth));
43}
44
45/* skip any 802.1q headers if necessary
46 * type is input/output
47 */
48void *trace_get_vlan_payload_from_ethernet_payload(void *ethernet, uint16_t *type,
49                uint32_t *remaining)
50{
51        assert(type && "You must pass a type in!");
52
53        if (*type == 0x8100) {
54                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
55
56                if (remaining) {
57                        if (*remaining < sizeof(libtrace_8021q_t))
58                                return NULL;
59
60                        *remaining=*remaining-sizeof(libtrace_8021q_t);
61                }
62
63                *type = ntohs(vlanhdr->vlan_ether_type);
64
65                return (void*)((char *)ethernet + sizeof(*vlanhdr));
66        }
67
68        return ethernet;
69}
70
71/* skip any MPLS headers if necessary, guessing what the next type is
72 * type is input/output.  If the next type is "ethernet" this will
73 * return a type of 0x0000.
74 */
75static void *trace_get_mpls_payload_from_ethernet_payload(void *ethernet,
76                uint16_t *type, uint32_t *remaining)
77{
78        assert(type && "You must pass a type in!");
79
80        if (*type == 0x8847) {
81                if ((((char*)ethernet)[2]&0x01)==0) {
82                        *type = 0x8847;
83                }
84                else {
85                        if (!remaining || *remaining>=5) {
86                                switch (((char*)ethernet)[4]&0xF0) {
87                                        case 0x40:
88                                                *type = 0x0800;
89                                                break;
90                                        case 0x60:
91                                                *type = 0x86DD;
92                                                break;
93                                        default:
94                                                /* Ethernet */
95                                                *type = 0;
96                                }
97                        }
98                }
99                ethernet=(char*)ethernet+4;
100                if (remaining) {
101                        if (*remaining<4)
102                                return NULL;
103                        else
104                                *remaining-=4;
105                }
106
107
108                return ethernet;
109        }
110        else
111                return NULL;
112}
113
114static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
115{
116        libtrace_80211_t *wifi;
117        libtrace_802_11_payload_t *eth;
118        int8_t extra = 0; /* how many QoS bytes to skip */
119       
120        if (remaining && *remaining < sizeof(libtrace_80211_t))
121                return NULL;
122
123        wifi=(libtrace_80211_t*)link;
124
125        /* Data packet? */
126        if (wifi->type != 2) {
127                return NULL;
128        }
129
130        /* If FromDS and ToDS are both set then we have a four-address
131         * frame. Otherwise we have a three-address frame */
132        if (!(wifi->to_ds && wifi->from_ds)) 
133                extra -= 6; 
134       
135        /* Indicates QoS field present, see IEEE802.11e-2005 pg 21 */
136        if (wifi->subtype & 0x8) 
137                extra += 2;
138
139        if (remaining && *remaining < sizeof(*eth))
140                return NULL;
141
142        eth=(libtrace_802_11_payload_t *)((char*)wifi+sizeof(*wifi)+extra);
143       
144        if (eth->type == 0xaaaa)
145                /* Payload contains an 802.2 LLC/SNAP frame */
146                return trace_get_payload_from_llcsnap((void *)eth, type, remaining);
147                       
148        /* Otherwise we assume an Ethernet II frame */
149        if (type) *type=ntohs(eth->type);
150        if (remaining) *remaining = *remaining - sizeof(libtrace_80211_t) - extra - sizeof(*eth);
151       
152        return (void*)((char*)eth+sizeof(*eth));
153}
154
155/* NB: type is returned as an ARPHRD_ type for SLL*/
156void *trace_get_payload_from_linux_sll(void *link,
157                uint16_t *type, uint32_t *remaining) 
158{
159        libtrace_sll_header_t *sll;
160
161        sll = (libtrace_sll_header_t*) link;
162
163        if (remaining) {
164                if (*remaining < sizeof(*sll))
165                        return NULL;
166                *remaining-=sizeof(*sll);
167        }
168
169        /* What kind of wacked out header, has this in host order?! */
170        if (type) *type = ntohs(sll->hatype);
171
172        return (void*)((char*)sll+sizeof(*sll));
173
174}
175
176DLLEXPORT
177void *trace_get_payload_from_atm(void *link,
178                uint8_t *type, uint32_t *remaining)
179{
180        libtrace_atm_capture_cell_t *cell;
181        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t))
182                return NULL;
183        cell=(libtrace_atm_capture_cell_t*)link;
184
185        if (type)
186                *type=cell->pt;
187
188        if (remaining)
189                *remaining-=sizeof(libtrace_atm_capture_cell_t);
190
191        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
192}
193
194static void *trace_get_payload_from_llcsnap(void *link,
195                uint16_t *type, uint32_t *remaining)
196{
197        /* 64 byte capture. */
198        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
199
200        if (remaining) {
201                if (*remaining < sizeof(libtrace_llcsnap_t))
202                        return NULL;
203                *remaining-=(sizeof(libtrace_llcsnap_t));
204        }
205
206        llc = (libtrace_llcsnap_t*)((char *)llc);
207
208        if (type) *type = ntohs(llc->type);
209
210        return (void*)((char*)llc+sizeof(*llc));
211}
212
213static void *trace_get_payload_from_ppp(void *link, 
214                uint16_t *type, uint32_t *remaining)
215{
216        /* 64 byte capture. */
217        libtrace_ppp_t *ppp = (libtrace_ppp_t*)link;
218
219        if (remaining) {
220                if (*remaining < sizeof(libtrace_ppp_t))
221                        return NULL;
222                *remaining-=sizeof(libtrace_ppp_t);
223        }
224
225        if (type) {
226                switch(ntohs(ppp->protocol)) {
227                        case 0x0021: *type = 0x0800; break;
228                }
229        }
230
231
232        return (void*)((char *)ppp+sizeof(*ppp));
233}
234
235static void *trace_get_payload_from_pflog(void *link,
236                uint16_t *type, uint32_t *remaining)
237{
238        libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
239    if (remaining) {
240                if (*remaining<sizeof(*pflog)) 
241                        return NULL;
242                *remaining-=sizeof(*pflog);
243        }
244        if (type) {
245                switch(pflog->af) {
246                        case AF_INET6: *type=0x86DD; break;
247                        case AF_INET:  *type=0x0800; break;
248                        default:
249                                      /* Unknown */
250                                      return NULL;
251                }
252        }
253        return (void*)((char*)pflog+ sizeof(*pflog));
254}
255
256/* Returns the 'payload' of the prism header, which is the 802.11 frame */
257static void *trace_get_payload_from_prism (void *link,
258                uint16_t *type, uint32_t *remaining)
259{
260        if (remaining) {
261                if (*remaining<144) 
262                        return NULL;
263                *remaining-=144;
264        }
265
266        if (type) *type = 0;
267
268        return (void *) ((char*)link+144);
269}
270
271/* Returns the 'payload' of the radiotap header, which is the 802.11 frame */
272static void *trace_get_payload_from_radiotap (void *link, 
273                uint16_t *type, uint32_t *remaining)
274{
275        struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link;
276        uint16_t rtaplen = bswap_le_to_host16(rtap->it_len);
277        if (remaining) {
278                if (*remaining < rtaplen)
279                        return NULL;
280                *remaining -= rtaplen;
281        }
282
283        if (type) *type = 0;
284
285        return (void*) ((char*)link + rtaplen);
286}
287
288void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
289                uint16_t *type, uint32_t *remaining)
290{
291        void *l = NULL;
292        uint16_t dummytype;
293       
294        switch(linktype) {
295                case TRACE_TYPE_80211_PRISM:
296                        l = trace_get_payload_from_prism(link,type,remaining);
297                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
298                case TRACE_TYPE_80211_RADIO:
299                        l = trace_get_payload_from_radiotap(link,type,remaining);
300                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
301                case TRACE_TYPE_80211:
302                        return trace_get_payload_from_80211(link,type,remaining);
303
304                case TRACE_TYPE_ETH:
305                        return trace_get_payload_from_ethernet(link,type,remaining);
306                case TRACE_TYPE_NONE:
307                        if ((*(char*)link&0xF0) == 0x40)
308                                *type=0x0800;
309                        else if ((*(char*)link&0xF0) == 0x60)
310                                *type=0x86DD;
311                        return link; /* I love the simplicity */
312                case TRACE_TYPE_LINUX_SLL:
313                        l = trace_get_payload_from_linux_sll(link,&dummytype,remaining);
314                        if (type) *type = dummytype;
315                        return (l ? trace_get_payload_from_link(l,
316                                                arphrd_type_to_libtrace(dummytype), type, remaining) : NULL);
317                       
318                case TRACE_TYPE_PFLOG:
319                        return trace_get_payload_from_pflog(link,type,remaining);
320                case TRACE_TYPE_PPP:
321                        return trace_get_payload_from_ppp(link,type,remaining);
322                case TRACE_TYPE_ATM:
323                        l=trace_get_payload_from_atm(link,NULL,remaining);
324                        return (l ? trace_get_payload_from_llcsnap(l,
325                                                type, remaining):NULL);
326                case TRACE_TYPE_DUCK:
327                        return NULL; /* duck packets have no payload! */
328                case TRACE_TYPE_METADATA:
329                        return NULL; /* The payload is in these packets does
330                                        not correspond to a genuine link-layer
331                                        */
332                default:
333                        break;
334        }
335        fprintf(stderr,"Don't understand link layer type %i in trace_get_payload_from_link()\n",
336                linktype);
337        return NULL;
338}
339
340libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
341{
342        uint16_t type;
343        void *link = trace_get_link(packet);
344        void *ret;
345
346        if (!link)
347                return NULL;
348       
349        ret=trace_get_payload_from_link(
350                        link,
351                        trace_get_link_type(packet),
352                        &type, NULL);
353
354        if (!ret)
355                return NULL;
356
357        for(;;) {
358                switch(type) {
359                        case 0x8100:
360                                ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
361                                continue;
362                        case 0x8847:
363                                ret=trace_get_mpls_payload_from_ethernet_payload(ret,&type,NULL);
364
365                                if (ret && type == 0x0) {
366                                        ret=trace_get_payload_from_ethernet(ret,&type,NULL);
367                                }
368                                continue;
369                        default:
370                                break;
371                }
372
373                break;
374        }
375
376        if (!ret || type!=0x0800)
377                return NULL;
378
379        /* Not an IPv4 packet */
380        if (((libtrace_ip_t*)ret)->ip_v != 4)
381                return NULL;
382
383        return (libtrace_ip_t*)ret;
384}
385
386libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
387{
388        uint16_t type;
389        void *link=trace_get_link(packet);
390        void *ret;
391       
392        if (!link)
393                return NULL;
394
395        ret=trace_get_payload_from_link(
396                        link,
397                        trace_get_link_type(packet),
398                        &type,NULL);
399
400        if (!ret)
401                return NULL;
402
403        for(;;) {
404                switch(type) {
405                        case 0x8100:
406                                ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
407                                continue;
408                        case 0x8847:
409                                ret=trace_get_mpls_payload_from_ethernet_payload(ret,&type,NULL);
410
411                                if (ret && type == 0x0) {
412                                        ret=trace_get_payload_from_ethernet(ret,&type,NULL);
413                                }
414                                continue;
415                        default:
416                                break;
417                }
418
419                break;
420        }
421
422        if (!ret || type!=0x86DD)
423                return NULL;
424
425        return (libtrace_ip6_t*)ret;
426}
427
428#define SW_IP_OFFMASK 0xff1f
429
430DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
431                uint32_t *remaining) 
432{
433        void *trans_ptr = 0;
434
435        if ((ipptr->ip_off & SW_IP_OFFMASK) != 0) {
436                return NULL;
437        }
438
439        if (remaining) {
440                if (*remaining<(ipptr->ip_hl*4U)) {
441                        return NULL;
442                }
443                *remaining-=(ipptr->ip_hl * 4);
444        }
445
446        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
447
448        if (prot) *prot = ipptr->ip_p;
449
450        return trans_ptr;
451}
452
453void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
454                uint32_t *remaining) 
455{
456        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
457        uint8_t nxt = ipptr->nxt;
458
459        if (remaining) {
460                if (*remaining<sizeof(libtrace_ip6_t))
461                        return NULL;
462                *remaining-=sizeof(libtrace_ip6_t);
463        }
464
465        while(1) {
466                switch (nxt) {
467                        case 0: /* hop by hop options */
468                        case 43: /* routing */
469                        case 44: /* fragment */
470                        case 50: /* ESP */
471                        case 51: /* AH */
472                        case 60: /* Destination options */
473                                {
474                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
475                                        +sizeof(libtrace_ip6_ext_t);
476
477                                        if (remaining) {
478                                                if (*remaining < len) {
479                                                        /* Snap too short */
480                                                        return NULL;
481                                                }
482                                                *remaining-=len;
483                                        }
484
485                                        payload=(char*)payload+len;
486                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
487                                        continue;
488                                }
489                        default:
490                                if (prot) *prot=nxt;
491                                return payload;
492                }
493        }
494}
495
496DLLEXPORT void *trace_get_transport(libtrace_packet_t *packet, 
497                uint8_t *proto,
498                uint32_t *remaining
499                ) 
500{
501        void *transport;
502        uint8_t dummy_proto;
503        uint16_t ethertype;
504        void *link;
505        uint32_t dummy_remaining;
506
507        if (!proto) proto=&dummy_proto;
508
509        if (!remaining) remaining=&dummy_remaining;
510
511        *remaining = trace_get_capture_length(packet);
512
513        link=trace_get_link(packet);
514
515        if (!link)
516                return NULL;
517
518        transport = trace_get_payload_from_link(
519                        link,
520                        trace_get_link_type(packet),
521                        &ethertype,
522                        remaining);
523
524        if (!transport)
525                return NULL;
526
527        for(;;) {
528                switch(ethertype) {
529                case 0x8100:
530                        transport=trace_get_vlan_payload_from_ethernet_payload(
531                                          transport,&ethertype,NULL);
532                        continue;
533                case 0x8847:
534                        transport=trace_get_mpls_payload_from_ethernet_payload(
535                                          transport,&ethertype,NULL);
536
537                        if (transport && ethertype == 0x0) {
538                                transport=trace_get_payload_from_ethernet(
539                                                transport,&ethertype,NULL);
540                        }
541                        continue;
542                default:
543                        break;
544                }
545
546                break;
547        }
548
549        if (!transport)
550                return NULL;
551
552        switch (ethertype) {
553                case 0x0800: /* IPv4 */
554                        transport=trace_get_payload_from_ip(
555                                (libtrace_ip_t*)transport, proto, remaining);
556                        /* IPv6 */
557                        if (transport && *proto == 41) {
558                                transport=trace_get_payload_from_ip6(
559                                 (libtrace_ip6_t*)transport, proto,remaining);
560                        }
561                        return transport;
562                case 0x86DD: /* IPv6 */
563                        return trace_get_payload_from_ip6(
564                                (libtrace_ip6_t*)transport, proto, remaining);
565                       
566                default:
567                        *proto=0;
568                        return NULL;
569        }
570
571}
572
573DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
574        uint8_t proto;
575        libtrace_tcp_t *tcp;
576
577        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,NULL);
578
579        if (!tcp || proto != 6)
580                return NULL;
581
582        return (libtrace_tcp_t*)tcp;
583}
584
585DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
586{
587        libtrace_tcp_t *tcpptr = 0;
588
589        if (ip->ip_p == 6)  {
590                tcpptr = (libtrace_tcp_t *)
591                        trace_get_payload_from_ip(ip, NULL, remaining);
592        }
593
594        return tcpptr;
595}
596
597DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
598        uint8_t proto;
599        libtrace_udp_t *udp;
600
601        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,NULL);
602
603        if (!udp || proto != 17)
604                return NULL;
605
606        return udp;
607}
608
609DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
610{
611        libtrace_udp_t *udpptr = 0;
612
613        if (ip->ip_p == 17) {
614                udpptr = (libtrace_udp_t *)
615                        trace_get_payload_from_ip(ip, NULL, remaining);
616        }
617
618        return udpptr;
619}
620
621DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
622        uint8_t proto;
623        libtrace_icmp_t *icmp;
624
625        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,NULL);
626
627        if (!icmp || proto != 1)
628                return NULL;
629
630        return icmp;
631}
632
633DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
634{
635        libtrace_icmp_t *icmpptr = 0;
636
637        if (ip->ip_p == 1)  {
638                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
639                                NULL, remaining);
640        }
641
642        return icmpptr;
643}
644
645DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
646{
647        if (remaining) {
648                if (*remaining < sizeof(libtrace_udp_t))
649                        return NULL;
650                *remaining-=sizeof(libtrace_udp_t);
651        }
652        return (void*)((char*)udp+sizeof(libtrace_udp_t));
653}
654
655DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
656{
657        unsigned int dlen = tcp->doff*4;
658        if (remaining) {
659                if (*remaining < dlen)
660                        return NULL;
661                *remaining-=dlen;
662        }
663        return (void *)((char *)tcp+dlen);
664}
665
666DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
667{
668        if (remaining) {
669                if (*remaining < sizeof(libtrace_icmp_t))
670                        return NULL;
671                *remaining-=sizeof(libtrace_icmp_t);
672        }
673        return (char*)icmp+sizeof(libtrace_icmp_t);
674}
675
676struct ports_t {
677        uint16_t src;
678        uint16_t dst;
679};
680
681/* Return the client port
682 */
683DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
684{
685        uint32_t remaining;
686        const struct ports_t *port = 
687                (const struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
688                        NULL, &remaining);
689
690        /* snapped too early */
691        if (remaining<2)
692                return 0;
693
694        if (port)
695                return ntohs(port->src);
696        else
697                return 0;
698}
699
700/* Same as get_source_port except use the destination port */
701DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
702{
703        uint32_t remaining;
704        struct ports_t *port = 
705                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
706                        NULL, &remaining);
707        /* snapped to early */
708        if (remaining<4)
709                return 0;
710
711        if (port)
712                return ntohs(port->dst);
713        else
714                return 0;
715}
716
717
718uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
719        void *link = trace_get_link(packet);
720        libtrace_80211_t *wifi;
721        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
722        if (!link)
723                return NULL;
724        switch (trace_get_link_type(packet)) {
725                case TRACE_TYPE_80211:
726                        wifi=(libtrace_80211_t*)link;
727                        return (uint8_t*)&wifi->mac2;
728                case TRACE_TYPE_80211_RADIO:
729                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
730                                        link,NULL,NULL);
731                        return (uint8_t*)&wifi->mac1;
732                case TRACE_TYPE_80211_PRISM:
733                        wifi=(libtrace_80211_t*)((char*)link+144);
734                        return (uint8_t*)&wifi->mac2;
735                case TRACE_TYPE_ETH:
736                        return (uint8_t*)&ethptr->ether_shost;
737                case TRACE_TYPE_POS:
738                case TRACE_TYPE_NONE:
739                case TRACE_TYPE_HDLC_POS:
740                case TRACE_TYPE_LINUX_SLL:
741                case TRACE_TYPE_PFLOG:
742                case TRACE_TYPE_ATM:
743                case TRACE_TYPE_DUCK:
744                case TRACE_TYPE_METADATA:
745                        return NULL;
746                default:
747                        break;
748        }
749        fprintf(stderr,"Not implemented\n");
750        assert(0);
751        return NULL;
752}
753
754DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
755        void *link = trace_get_link(packet);
756        libtrace_80211_t *wifi;
757        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
758        if (!link)
759                return NULL;
760        switch (trace_get_link_type(packet)) {
761                case TRACE_TYPE_80211:
762                        wifi=(libtrace_80211_t*)link;
763                        return (uint8_t*)&wifi->mac1;
764                case TRACE_TYPE_80211_RADIO:
765                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
766                                        link,NULL,NULL);
767                        return (uint8_t*)&wifi->mac1;
768                case TRACE_TYPE_80211_PRISM:
769                        wifi=(libtrace_80211_t*)((char*)link+144);
770                        return (uint8_t*)&wifi->mac1;
771                case TRACE_TYPE_ETH:
772                        return (uint8_t*)&ethptr->ether_dhost;
773                case TRACE_TYPE_POS:
774                case TRACE_TYPE_NONE:
775                case TRACE_TYPE_ATM:
776                case TRACE_TYPE_HDLC_POS:
777                case TRACE_TYPE_LINUX_SLL:
778                case TRACE_TYPE_PFLOG:
779                case TRACE_TYPE_DUCK:
780                case TRACE_TYPE_METADATA:
781                        /* No MAC address */
782                        return NULL;
783                default:
784                        break;
785        }
786        fprintf(stderr,"Not implemented\n");
787        assert(0);
788        return NULL;
789}
790
791DLLEXPORT struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
792                struct sockaddr *addr)
793{
794        uint16_t proto;
795        uint32_t remaining;
796        void *l3;
797        struct ports_t *ports;
798        static struct sockaddr_storage dummy;
799
800        if (!addr)
801                addr=(struct sockaddr*)&dummy;
802
803        remaining = trace_get_capture_length(packet);
804
805        l3 = trace_get_payload_from_link(
806                        trace_get_link(packet),
807                        trace_get_link_type(packet),
808                        &proto,
809                        &remaining);
810
811        if (!l3)
812                return false;
813
814        for(;;) {
815                switch(proto) {
816                        case 0x8100:
817                                l3=trace_get_vlan_payload_from_ethernet_payload(
818                                                l3,&proto,NULL);
819                                continue;
820                        case 0x8847:
821                                l3=trace_get_mpls_payload_from_ethernet_payload(
822                                                l3,&proto,NULL);
823
824                                if (l3 && proto == 0x0) {
825                                        l3=trace_get_payload_from_ethernet(
826                                                l3,&proto,NULL);
827                                }
828                                continue;
829                        default:
830                                break;
831                }
832
833                break;
834        }
835
836        if (!l3)
837                return NULL;
838
839        switch (proto) {
840                case 0x0800: /* IPv4 */
841                {
842                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
843                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
844                        ports = (struct ports_t*)
845                                trace_get_payload_from_ip(ip,NULL,&remaining);
846                        addr4->sin_family=AF_INET;
847                        if (ports && remaining>=sizeof(*ports))
848                                addr4->sin_port=ports->src;
849                        else
850                                addr4->sin_port=0;
851                        addr4->sin_addr=ip->ip_src;
852                        return addr;
853                }
854                case 0x86DD: /* IPv6 */
855                {
856                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
857                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
858                        ports = (struct ports_t*)
859                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
860                        addr6->sin6_family=AF_INET6;
861                        if (ports && remaining>=sizeof(*ports))
862                                addr6->sin6_port=ports->dst;
863                        else
864                                addr6->sin6_port=0;
865                        addr6->sin6_flowinfo=0;
866                        addr6->sin6_addr=ip6->ip_src;
867                        return addr;
868                }
869                default:
870                        return NULL;
871        }
872}
873
874DLLEXPORT struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
875                struct sockaddr *addr)
876{
877        uint16_t proto;
878        uint32_t remaining;
879        void *transport;
880        static struct sockaddr_storage dummy;
881
882        if (!addr)
883                addr=(struct sockaddr*)&dummy;
884
885        remaining = trace_get_capture_length(packet);
886
887        transport = trace_get_payload_from_link(
888                        trace_get_link(packet),
889                        trace_get_link_type(packet),
890                        &proto,
891                        &remaining);
892
893        if (!transport)
894                return false;
895        for(;;) {
896                switch(proto) {
897                        case 0x8100:
898                                transport=trace_get_vlan_payload_from_ethernet_payload(transport,&proto,NULL);
899                                continue;
900                        case 0x8847:
901                                transport=trace_get_mpls_payload_from_ethernet_payload(transport,&proto,NULL);
902
903                                if (transport && proto == 0x0) {
904                                        transport=trace_get_payload_from_ethernet(
905                                                        transport,&proto,NULL);
906                                }
907                                continue;
908                        default:
909                                break;
910                }
911
912                break;
913        }
914
915        if (!transport)
916                return false;
917
918        switch (proto) {
919                case 0x0800: /* IPv4 */
920                {
921                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
922                        libtrace_ip_t *ip = (libtrace_ip_t*)transport;
923                        addr4->sin_family=AF_INET;
924                        addr4->sin_port=0;
925                        addr4->sin_addr=ip->ip_dst;
926                        return addr;
927                }
928                case 0x86DD: /* IPv6 */
929                {
930                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
931                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)transport;
932                        addr6->sin6_family=AF_INET6;
933                        addr6->sin6_port=0;
934                        addr6->sin6_flowinfo=0;
935                        addr6->sin6_addr=ip6->ip_dst;
936                        return addr;
937                }
938                default:
939                        return NULL;
940        }
941}
942
943/* parse an ip or tcp option
944 * @param[in,out] ptr   the pointer to the current option
945 * @param[in,out] len   the length of the remaining buffer
946 * @param[out] type     the type of the option
947 * @param[out] optlen   the length of the option
948 * @param[out] data     the data of the option
949 *
950 * @returns bool true if there is another option (and the fields are filled in)
951 *               or false if this was the last option.
952 *
953 * This updates ptr to point to the next option after this one, and updates
954 * len to be the number of bytes remaining in the options area.  Type is updated
955 * to be the code of this option, and data points to the data of this option,
956 * with optlen saying how many bytes there are.
957 *
958 * @note Beware of fragmented packets.
959 * @author Perry Lorier
960 */
961DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
962                        unsigned char *type,
963                        unsigned char *optlen,
964                        unsigned char **data)
965{
966        if (*len<=0)
967                return 0;
968        *type=**ptr;
969        switch(*type) {
970                case 0: /* End of options */
971                        return 0;
972                case 1: /* Pad */
973                        (*ptr)++;
974                        (*len)--;
975                        return 1;
976                default:
977                        *optlen = *(*ptr+1);
978                        if (*optlen<2)
979                                return 0; /* I have no idea wtf is going on
980                                           * with these packets
981                                           */
982                        (*len)-=*optlen;
983                        (*data)=(*ptr+2);
984                        (*ptr)+=*optlen;
985                        if (*len<0)
986                                return 0;
987                        return 1;
988        }
989        assert(0);
990}
991
992
Note: See TracBrowser for help on using the repository browser.