source: lib/protocols.c @ be22b51

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since be22b51 was be22b51, checked in by Shane Alcock <salcock@…>, 14 years ago

Other libtrace programs don't like meta-data so added a new trace_type that would allow them to ignore it without having to do anything special

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