source: lib/protocols.c @ 4a207b8

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

Endace POS traces are in fact PPP traces. Deal with this correctly, even when
converting between trace formats

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