source: lib/protocols.c @ 5e85c23

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

Minor tidy-up of get_payload_from_80211, though it looks like this
function (and possibly the 802.11 frame struct that libtrace provides)
will need to change to accomodate 3 and 4 address formats nicely.

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