source: lib/protocols.c @ 5069b69

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 5069b69 was 5069b69, checked in by Perry Lorier <perry@…>, 15 years ago

Update comments

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