source: lib/protocols.c @ 16da8f3

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

Add ATM support

  • Property mode set to 100644
File size: 21.2 KB
Line 
1/* This file has the various helper functions used to decode various protocols
2 *
3 * $Id$
4 */ 
5#include "libtrace.h"
6#include "libtrace_int.h"
7#include "wag.h"
8#include <assert.h>
9#include <stdio.h>
10
11#ifndef WIN32
12#include <net/if_arp.h>
13#endif
14
15#ifndef ARPHRD_ETHER
16#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
17#endif
18
19#ifndef ARPHRD_PPP
20#define ARPHRD_PPP      512
21#endif
22
23
24/* Returns the payload from 802.3 ethernet.  Type optionally returned in
25 * "type" in host byte order.  This will return a vlan header.
26 */
27static void *trace_get_payload_from_ethernet(void *ethernet, 
28                uint16_t *type,
29                uint32_t *remaining)
30{
31        libtrace_ether_t *eth = (libtrace_ether_t*)ethernet;
32
33        if (remaining) {
34                if (*remaining < sizeof(*eth))
35                        return NULL;
36                *remaining-=sizeof(*eth);
37        }
38
39        if (type)
40                *type = ntohs(eth->ether_type);
41
42        return (void*)((char *)eth + sizeof(*eth));
43}
44
45/* skip any 802.1q headers if necessary
46 * type is input/output
47 */
48void *trace_get_vlan_payload_from_ethernet_payload(void *ethernet, uint16_t *type,
49                uint32_t *remaining)
50{
51        assert(type && "You must pass a type in!");
52
53        if (*type == 0x8100) {
54                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
55
56                if (remaining) {
57                        if (*remaining < sizeof(libtrace_8021q_t))
58                                return NULL;
59
60                        *remaining=*remaining-sizeof(libtrace_8021q_t);
61                }
62
63                *type = ntohs(vlanhdr->vlan_ether_type);
64
65                return (void*)((char *)ethernet + sizeof(*vlanhdr));
66        }
67
68        return ethernet;
69}
70
71/* skip any MPLS headers if necessary, guessing what the next type is
72 * type is input/output.  If the next type is "ethernet" this will
73 * return a type of 0x0000.
74 */
75static void *trace_get_mpls_payload_from_ethernet_payload(void *ethernet,
76                uint16_t *type, uint32_t *remaining)
77{
78        assert(type && "You must pass a type in!");
79
80        if (*type == 0x8847) {
81                if ((((char*)ethernet)[2]&0x01)==0) {
82                        *type = 0x8847;
83                }
84                else {
85                        if (!remaining || *remaining>=5) {
86                                switch (((char*)ethernet)[4]&0xF0) {
87                                        case 0x40:
88                                                *type = 0x0800;
89                                                break;
90                                        case 0x60:
91                                                *type = 0x86DD;
92                                                break;
93                                        default:
94                                                /* Ethernet */
95                                                *type = 0;
96                                }
97                        }
98                }
99                ethernet=(char*)ethernet+4;
100                if (remaining) {
101                        if (*remaining<4)
102                                return NULL;
103                        else
104                                *remaining-=4;
105                }
106
107
108                return ethernet;
109        }
110        else
111                return NULL;
112}
113
114static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
115{
116        /* TODO: Decode type != DATA
117         * TODO: We're assuming four address frame here... probably not good
118         */
119       
120        libtrace_80211_t *wifi;
121        libtrace_802_11_payload_t *eth;
122        uint8_t extra; /* how many QoS bytes to skip */
123       
124        if (remaining && *remaining < sizeof(libtrace_80211_t))
125                return NULL;
126
127        wifi=(libtrace_80211_t*)link;
128
129        /* Data packet? */
130        if (wifi->type != 2) {
131                return NULL;
132        }
133
134        /* Check for WME */
135        if (wifi->subtype & 0x8) {
136                /* indicates two octets of QoS before payload,
137                 * see IEEE802.11e-2005 pg 21
138                 * */
139                extra = 2;
140        } else 
141                extra = 0;
142
143        if (remaining && *remaining < sizeof(*eth))
144                return NULL;
145
146        eth=(libtrace_802_11_payload_t *)((char*)wifi+sizeof(*wifi)+extra);
147
148        if (type) *type=ntohs(eth->type);
149        if (remaining) *remaining = *remaining - sizeof(libtrace_80211_t) - extra - sizeof(*eth);
150       
151       
152        return (void*)((char*)eth+sizeof(*eth));
153}
154
155/* NB: type is returned as an ARPHRD_ type for SLL*/
156void *trace_get_payload_from_linux_sll(void *link,
157                uint16_t *type, uint32_t *remaining) 
158{
159        libtrace_sll_header_t *sll;
160
161        sll = (libtrace_sll_header_t*) link;
162
163        if (remaining) {
164                if (*remaining < sizeof(*sll))
165                        return NULL;
166                *remaining-=sizeof(*sll);
167        }
168
169        /* What kind of wacked out header, has this in host order?! */
170        if (type) *type = ntohs(sll->hatype);
171
172        return (void*)((char*)sll+sizeof(*sll));
173
174}
175
176static void *trace_get_payload_from_atm(void *link,
177                uint8_t *type, uint32_t *remaining)
178{
179        libtrace_atm_capture_cell_t *cell;
180        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t))
181                return NULL;
182        cell=(libtrace_atm_capture_cell_t*)link;
183
184        if (type)
185                type=cell->pt;
186
187        if (remaining)
188                *remaining-=sizeof(libtrace_atm_capture_cell_t);
189
190        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
191}
192
193static void *trace_get_payload_from_llcsnap(void *link,
194                uint16_t *type, uint32_t *remaining)
195{
196        /* 64 byte capture. */
197        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
198
199        if (remaining) {
200                if (*remaining < sizeof(libtrace_llcsnap_t))
201                        return NULL;
202                *remaining-=(sizeof(libtrace_llcsnap_t));
203        }
204
205        llc = (libtrace_llcsnap_t*)((char *)llc);
206
207        if (type) *type = ntohs(llc->type);
208
209        return (void*)((char*)llc+sizeof(*llc));
210}
211
212static void *trace_get_payload_from_pos(void *link, 
213                uint16_t *type, uint32_t *remaining)
214{
215        /* 64 byte capture. */
216        libtrace_pos_t *pos = (libtrace_pos_t*)link;
217
218        if (remaining) {
219                if (*remaining < sizeof(libtrace_pos_t))
220                        return NULL;
221                *remaining-=sizeof(libtrace_pos_t);
222        }
223
224        if (type) *type = ntohs(pos->ether_type);
225
226        return (void*)((char *)pos+sizeof(*pos));
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_POS:
315                        return trace_get_payload_from_pos(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        }
323        fprintf(stderr,"Don't understand link layer type %i in trace_get_payload_from_link()\n",
324                linktype);
325        return NULL;
326}
327
328libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
329{
330        uint16_t type;
331        void *link = trace_get_link(packet);
332        void *ret;
333
334        if (!link)
335                return NULL;
336       
337        ret=trace_get_payload_from_link(
338                        link,
339                        trace_get_link_type(packet),
340                        &type, NULL);
341
342        if (!ret)
343                return NULL;
344
345        for(;;) {
346                switch(type) {
347                        case 0x8100:
348                                ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
349                                continue;
350                        case 0x8847:
351                                ret=trace_get_mpls_payload_from_ethernet_payload(ret,&type,NULL);
352
353                                if (ret && type == 0x0) {
354                                        ret=trace_get_payload_from_ethernet(ret,&type,NULL);
355                                }
356                                continue;
357                        default:
358                                break;
359                }
360
361                break;
362        }
363
364        if (!ret || type!=0x0800)
365                return NULL;
366
367        /* Not an IPv4 packet */
368        if (((libtrace_ip_t*)ret)->ip_v != 4)
369                return NULL;
370
371        return (libtrace_ip_t*)ret;
372}
373
374libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
375{
376        uint16_t type;
377        void *link=trace_get_link(packet);
378        void *ret;
379       
380        if (!link)
381                return NULL;
382
383        ret=trace_get_payload_from_link(
384                        link,
385                        trace_get_link_type(packet),
386                        &type,NULL);
387
388        if (!ret)
389                return NULL;
390
391        for(;;) {
392                switch(type) {
393                        case 0x8100:
394                                ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
395                                continue;
396                        case 0x8847:
397                                ret=trace_get_mpls_payload_from_ethernet_payload(ret,&type,NULL);
398
399                                if (ret && type == 0x0) {
400                                        ret=trace_get_payload_from_ethernet(ret,&type,NULL);
401                                }
402                                continue;
403                        default:
404                                break;
405                }
406
407                break;
408        }
409
410        if (!ret || type!=0x86DD)
411                return NULL;
412
413        return (libtrace_ip6_t*)ret;
414}
415
416#define SW_IP_OFFMASK 0xff1f
417
418DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
419                uint32_t *remaining) 
420{
421        void *trans_ptr = 0;
422
423        if ((ipptr->ip_off & SW_IP_OFFMASK) != 0) {
424                return NULL;
425        }
426
427        if (remaining) {
428                if (*remaining<(ipptr->ip_hl*4U)) {
429                        return NULL;
430                }
431                *remaining-=(ipptr->ip_hl * 4);
432        }
433
434        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
435
436        if (prot) *prot = ipptr->ip_p;
437
438        return trans_ptr;
439}
440
441void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
442                uint32_t *remaining) 
443{
444        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
445        uint8_t nxt = ipptr->nxt;
446
447        if (remaining) {
448                if (*remaining<sizeof(libtrace_ip6_t))
449                        return NULL;
450                *remaining-=sizeof(libtrace_ip6_t);
451        }
452
453        while(1) {
454                switch (nxt) {
455                        case 0: /* hop by hop options */
456                        case 43: /* routing */
457                        case 44: /* fragment */
458                        case 50: /* ESP */
459                        case 51: /* AH */
460                        case 60: /* Destination options */
461                                {
462                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
463                                        +sizeof(libtrace_ip6_ext_t);
464
465                                        if (remaining) {
466                                                if (*remaining < len) {
467                                                        /* Snap too short */
468                                                        return NULL;
469                                                }
470                                                *remaining-=len;
471                                        }
472
473                                        payload=(char*)payload+len;
474                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
475                                        continue;
476                                }
477                        default:
478                                if (prot) *prot=nxt;
479                                return payload;
480                }
481        }
482}
483
484DLLEXPORT void *trace_get_transport(libtrace_packet_t *packet, 
485                uint8_t *proto,
486                uint32_t *remaining
487                ) 
488{
489        void *transport;
490        uint8_t dummy_proto;
491        uint16_t ethertype;
492        void *link;
493        uint32_t dummy_remaining;
494
495        if (!proto) proto=&dummy_proto;
496
497        if (!remaining) remaining=&dummy_remaining;
498
499        *remaining = trace_get_capture_length(packet);
500
501        link=trace_get_link(packet);
502
503        if (!link)
504                return NULL;
505
506        transport = trace_get_payload_from_link(
507                        link,
508                        trace_get_link_type(packet),
509                        &ethertype,
510                        remaining);
511
512        if (!transport)
513                return NULL;
514
515        for(;;) {
516                switch(ethertype) {
517                case 0x8100:
518                        transport=trace_get_vlan_payload_from_ethernet_payload(
519                                          transport,&ethertype,NULL);
520                        continue;
521                case 0x8847:
522                        transport=trace_get_mpls_payload_from_ethernet_payload(
523                                          transport,&ethertype,NULL);
524
525                        if (transport && ethertype == 0x0) {
526                                transport=trace_get_payload_from_ethernet(
527                                                transport,&ethertype,NULL);
528                        }
529                        continue;
530                default:
531                        break;
532                }
533
534                break;
535        }
536
537        if (!transport)
538                return NULL;
539
540        switch (ethertype) {
541                case 0x0800: /* IPv4 */
542                        transport=trace_get_payload_from_ip(
543                                (libtrace_ip_t*)transport, proto, remaining);
544                        /* IPv6 */
545                        if (transport && *proto == 41) {
546                                transport=trace_get_payload_from_ip6(
547                                 (libtrace_ip6_t*)transport, proto,remaining);
548                        }
549                        return transport;
550                case 0x86DD: /* IPv6 */
551                        return trace_get_payload_from_ip6(
552                                (libtrace_ip6_t*)transport, proto, remaining);
553                       
554                default:
555                        *proto=0;
556                        return NULL;
557        }
558
559}
560
561DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
562        uint8_t proto;
563        libtrace_tcp_t *tcp;
564
565        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,NULL);
566
567        if (!tcp || proto != 6)
568                return NULL;
569
570        return (libtrace_tcp_t*)tcp;
571}
572
573DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
574{
575        libtrace_tcp_t *tcpptr = 0;
576
577        if (ip->ip_p == 6)  {
578                tcpptr = (libtrace_tcp_t *)
579                        trace_get_payload_from_ip(ip, NULL, remaining);
580        }
581
582        return tcpptr;
583}
584
585DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
586        uint8_t proto;
587        libtrace_udp_t *udp;
588
589        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,NULL);
590
591        if (!udp || proto != 17)
592                return NULL;
593
594        return udp;
595}
596
597DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
598{
599        libtrace_udp_t *udpptr = 0;
600
601        if (ip->ip_p == 17) {
602                udpptr = (libtrace_udp_t *)
603                        trace_get_payload_from_ip(ip, NULL, remaining);
604        }
605
606        return udpptr;
607}
608
609DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
610        uint8_t proto;
611        libtrace_icmp_t *icmp;
612
613        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,NULL);
614
615        if (!icmp || proto != 1)
616                return NULL;
617
618        return icmp;
619}
620
621DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
622{
623        libtrace_icmp_t *icmpptr = 0;
624
625        if (ip->ip_p == 1)  {
626                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
627                                NULL, remaining);
628        }
629
630        return icmpptr;
631}
632
633DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
634{
635        if (remaining) {
636                if (*remaining < sizeof(libtrace_udp_t))
637                        return NULL;
638                *remaining-=sizeof(libtrace_udp_t);
639        }
640        return (void*)((char*)udp+sizeof(libtrace_udp_t));
641}
642
643DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
644{
645        unsigned int dlen = tcp->doff*4;
646        if (remaining) {
647                if (*remaining < dlen)
648                        return NULL;
649                *remaining-=dlen;
650        }
651        return (void *)((char *)tcp+dlen);
652}
653
654DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
655{
656        if (remaining) {
657                if (*remaining < sizeof(libtrace_icmp_t))
658                        return NULL;
659                *remaining-=sizeof(libtrace_icmp_t);
660        }
661        return (char*)icmp+sizeof(libtrace_icmp_t);
662}
663
664struct ports_t {
665        uint16_t src;
666        uint16_t dst;
667};
668
669/* Return the client port
670 */
671DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
672{
673        uint32_t remaining;
674        struct ports_t *port = 
675                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
676                        NULL, &remaining);
677
678        /* snapped too early */
679        if (remaining<2)
680                return 0;
681
682        if (port)
683                return ntohs(port->src);
684        else
685                return 0;
686}
687
688/* Same as get_source_port except use the destination port */
689DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
690{
691        uint32_t remaining;
692        struct ports_t *port = 
693                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
694                        NULL, &remaining);
695        /* snapped to early */
696        if (remaining<4)
697                return 0;
698
699        if (port)
700                return ntohs(port->dst);
701        else
702                return 0;
703}
704
705
706uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
707        void *link = trace_get_link(packet);
708        libtrace_80211_t *wifi;
709        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
710        if (!link)
711                return NULL;
712        switch (trace_get_link_type(packet)) {
713                case TRACE_TYPE_80211:
714                        wifi=(libtrace_80211_t*)link;
715                        return (uint8_t*)&wifi->mac2;
716                case TRACE_TYPE_80211_RADIO:
717                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
718                                        link,NULL,NULL);
719                        return (uint8_t*)&wifi->mac1;
720                case TRACE_TYPE_80211_PRISM:
721                        wifi=(libtrace_80211_t*)((char*)link+144);
722                        return (uint8_t*)&wifi->mac2;
723                case TRACE_TYPE_ETH:
724                        return (uint8_t*)&ethptr->ether_shost;
725                case TRACE_TYPE_POS:
726                case TRACE_TYPE_NONE:
727                case TRACE_TYPE_HDLC_POS:
728                case TRACE_TYPE_LINUX_SLL:
729                case TRACE_TYPE_PFLOG:
730                case TRACE_TYPE_ATM:
731                case TRACE_TYPE_DUCK:
732                        return NULL;
733        }
734        fprintf(stderr,"Not implemented\n");
735        assert(0);
736        return NULL;
737}
738
739DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
740        void *link = trace_get_link(packet);
741        libtrace_80211_t *wifi;
742        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
743        if (!link)
744                return NULL;
745        switch (trace_get_link_type(packet)) {
746                case TRACE_TYPE_80211:
747                        wifi=(libtrace_80211_t*)link;
748                        return (uint8_t*)&wifi->mac1;
749                case TRACE_TYPE_80211_RADIO:
750                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
751                                        link,NULL,NULL);
752                        return (uint8_t*)&wifi->mac1;
753                case TRACE_TYPE_80211_PRISM:
754                        wifi=(libtrace_80211_t*)((char*)link+144);
755                        return (uint8_t*)&wifi->mac1;
756                case TRACE_TYPE_ETH:
757                        return (uint8_t*)&ethptr->ether_dhost;
758                case TRACE_TYPE_POS:
759                case TRACE_TYPE_NONE:
760                case TRACE_TYPE_ATM:
761                case TRACE_TYPE_HDLC_POS:
762                case TRACE_TYPE_LINUX_SLL:
763                case TRACE_TYPE_PFLOG:
764                case TRACE_TYPE_DUCK:
765                        /* No MAC address */
766                        return NULL;
767        }
768        fprintf(stderr,"Not implemented\n");
769        assert(0);
770        return NULL;
771}
772
773DLLEXPORT struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
774                struct sockaddr *addr)
775{
776        uint16_t proto;
777        uint32_t remaining;
778        void *l3;
779        struct ports_t *ports;
780        static struct sockaddr_storage dummy;
781
782        if (!addr)
783                addr=(struct sockaddr*)&dummy;
784
785        remaining = trace_get_capture_length(packet);
786
787        l3 = trace_get_payload_from_link(
788                        trace_get_link(packet),
789                        trace_get_link_type(packet),
790                        &proto,
791                        &remaining);
792
793        if (!l3)
794                return false;
795
796        for(;;) {
797                switch(proto) {
798                        case 0x8100:
799                                l3=trace_get_vlan_payload_from_ethernet_payload(
800                                                l3,&proto,NULL);
801                                continue;
802                        case 0x8847:
803                                l3=trace_get_mpls_payload_from_ethernet_payload(
804                                                l3,&proto,NULL);
805
806                                if (l3 && proto == 0x0) {
807                                        l3=trace_get_payload_from_ethernet(
808                                                l3,&proto,NULL);
809                                }
810                                continue;
811                        default:
812                                break;
813                }
814
815                break;
816        }
817
818        if (!l3)
819                return NULL;
820
821        switch (proto) {
822                case 0x0800: /* IPv4 */
823                {
824                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
825                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
826                        ports = (struct ports_t*)
827                                trace_get_payload_from_ip(ip,NULL,&remaining);
828                        addr4->sin_family=AF_INET;
829                        if (ports && remaining>=sizeof(*ports))
830                                addr4->sin_port=ports->src;
831                        else
832                                addr4->sin_port=0;
833                        addr4->sin_addr=ip->ip_src;
834                        return addr;
835                }
836                case 0x86DD: /* IPv6 */
837                {
838                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
839                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
840                        ports = (struct ports_t*)
841                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
842                        addr6->sin6_family=AF_INET6;
843                        if (ports && remaining>=sizeof(*ports))
844                                addr6->sin6_port=ports->dst;
845                        else
846                                addr6->sin6_port=0;
847                        addr6->sin6_flowinfo=0;
848                        addr6->sin6_addr=ip6->ip_src;
849                        return addr;
850                }
851                default:
852                        return NULL;
853        }
854}
855
856DLLEXPORT struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
857                struct sockaddr *addr)
858{
859        uint16_t proto;
860        uint32_t remaining;
861        void *transport;
862        static struct sockaddr_storage dummy;
863
864        if (!addr)
865                addr=(struct sockaddr*)&dummy;
866
867        remaining = trace_get_capture_length(packet);
868
869        transport = trace_get_payload_from_link(
870                        trace_get_link(packet),
871                        trace_get_link_type(packet),
872                        &proto,
873                        &remaining);
874
875        if (!transport)
876                return false;
877        for(;;) {
878                switch(proto) {
879                        case 0x8100:
880                                transport=trace_get_vlan_payload_from_ethernet_payload(transport,&proto,NULL);
881                                continue;
882                        case 0x8847:
883                                transport=trace_get_mpls_payload_from_ethernet_payload(transport,&proto,NULL);
884
885                                if (transport && proto == 0x0) {
886                                        transport=trace_get_payload_from_ethernet(
887                                                        transport,&proto,NULL);
888                                }
889                                continue;
890                        default:
891                                break;
892                }
893
894                break;
895        }
896
897        if (!transport)
898                return false;
899
900        switch (proto) {
901                case 0x0800: /* IPv4 */
902                {
903                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
904                        libtrace_ip_t *ip = (libtrace_ip_t*)transport;
905                        addr4->sin_family=AF_INET;
906                        addr4->sin_port=0;
907                        addr4->sin_addr=ip->ip_dst;
908                        return addr;
909                }
910                case 0x86DD: /* IPv6 */
911                {
912                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
913                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)transport;
914                        addr6->sin6_family=AF_INET6;
915                        addr6->sin6_port=0;
916                        addr6->sin6_flowinfo=0;
917                        addr6->sin6_addr=ip6->ip_dst;
918                        return addr;
919                }
920                default:
921                        return NULL;
922        }
923}
924
925/* parse an ip or tcp option
926 * @param[in,out] ptr   the pointer to the current option
927 * @param[in,out] len   the length of the remaining buffer
928 * @param[out] type     the type of the option
929 * @param[out] optlen   the length of the option
930 * @param[out] data     the data of the option
931 *
932 * @returns bool true if there is another option (and the fields are filled in)
933 *               or false if this was the last option.
934 *
935 * This updates ptr to point to the next option after this one, and updates
936 * len to be the number of bytes remaining in the options area.  Type is updated
937 * to be the code of this option, and data points to the data of this option,
938 * with optlen saying how many bytes there are.
939 *
940 * @note Beware of fragmented packets.
941 * @author Perry Lorier
942 */
943DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
944                        unsigned char *type,
945                        unsigned char *optlen,
946                        unsigned char **data)
947{
948        if (*len<=0)
949                return 0;
950        *type=**ptr;
951        switch(*type) {
952                case 0: /* End of options */
953                        return 0;
954                case 1: /* Pad */
955                        (*ptr)++;
956                        (*len)--;
957                        return 1;
958                default:
959                        *optlen = *(*ptr+1);
960                        if (*optlen<2)
961                                return 0; /* I have no idea wtf is going on
962                                           * with these packets
963                                           */
964                        (*len)-=*optlen;
965                        (*data)=(*ptr+2);
966                        (*ptr)+=*optlen;
967                        if (*len<0)
968                                return 0;
969                        return 1;
970        }
971        assert(0);
972}
973
974
Note: See TracBrowser for help on using the repository browser.