source: lib/protocols.c @ eb1aab2

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

Fixed all the warnings about cases that weren't being dealt with by our switch statements - the original code was fine, but the warnings were annoying

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