source: lib/protocols.c @ 89bfc98

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

This should be static

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