source: lib/protocols.c @ cab58c5

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

Fixed up brazillions of warnings

  • 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; /* 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
176DLLEXPORT
177void *trace_get_payload_from_atm(void *link,
178                uint8_t *type, uint32_t *remaining)
179{
180        libtrace_atm_capture_cell_t *cell;
181        if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t))
182                return NULL;
183        cell=(libtrace_atm_capture_cell_t*)link;
184
185        if (type)
186                *type=cell->pt;
187
188        if (remaining)
189                *remaining-=sizeof(libtrace_atm_capture_cell_t);
190
191        return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
192}
193
194static void *trace_get_payload_from_llcsnap(void *link,
195                uint16_t *type, uint32_t *remaining)
196{
197        /* 64 byte capture. */
198        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
199
200        if (remaining) {
201                if (*remaining < sizeof(libtrace_llcsnap_t))
202                        return NULL;
203                *remaining-=(sizeof(libtrace_llcsnap_t));
204        }
205
206        llc = (libtrace_llcsnap_t*)((char *)llc);
207
208        if (type) *type = ntohs(llc->type);
209
210        return (void*)((char*)llc+sizeof(*llc));
211}
212
213void *trace_get_payload_from_pos(void *link, 
214                uint16_t *type, uint32_t *remaining)
215{
216        /* 64 byte capture. */
217        libtrace_pos_t *pos = (libtrace_pos_t*)link;
218
219        if (remaining) {
220                if (*remaining < sizeof(libtrace_pos_t))
221                        return NULL;
222                *remaining-=sizeof(libtrace_pos_t);
223        }
224
225        /* This is documented by endace to be an ethertype.  The ethertype
226         * however is always ntohs(0x0021), which endace in their own tools
227         * ignore and assume IP, so...
228         */
229        /*if (type) *type = ntohs(pos->ether_type); */
230        if (type) *type = ntohs(0x0800);
231
232        return (void*)((char *)pos+sizeof(*pos));
233}
234
235static void *trace_get_payload_from_pflog(void *link,
236                uint16_t *type, uint32_t *remaining)
237{
238        libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
239    if (remaining) {
240                if (*remaining<sizeof(*pflog)) 
241                        return NULL;
242                *remaining-=sizeof(*pflog);
243        }
244        if (type) {
245                switch(pflog->af) {
246                        case AF_INET6: *type=0x86DD; break;
247                        case AF_INET:  *type=0x0800; break;
248                        default:
249                                      /* Unknown */
250                                      return NULL;
251                }
252        }
253        return (void*)((char*)pflog+ sizeof(*pflog));
254}
255
256/* Returns the 'payload' of the prism header, which is the 802.11 frame */
257static void *trace_get_payload_from_prism (void *link,
258                uint16_t *type, uint32_t *remaining)
259{
260        if (remaining) {
261                if (*remaining<144) 
262                        return NULL;
263                *remaining-=144;
264        }
265
266        if (type) *type = 0;
267
268        return (void *) ((char*)link+144);
269}
270
271/* Returns the 'payload' of the radiotap header, which is the 802.11 frame */
272static void *trace_get_payload_from_radiotap (void *link, 
273                uint16_t *type, uint32_t *remaining)
274{
275        struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link;
276        uint16_t rtaplen = bswap_le_to_host16(rtap->it_len);
277        if (remaining) {
278                if (*remaining < rtaplen)
279                        return NULL;
280                *remaining -= rtaplen;
281        }
282
283        if (type) *type = 0;
284
285        return (void*) ((char*)link + rtaplen);
286}
287
288void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
289                uint16_t *type, uint32_t *remaining)
290{
291        void *l = NULL;
292        uint16_t dummytype;
293       
294        switch(linktype) {
295                case TRACE_TYPE_80211_PRISM:
296                        l = trace_get_payload_from_prism(link,type,remaining);
297                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
298                case TRACE_TYPE_80211_RADIO:
299                        l = trace_get_payload_from_radiotap(link,type,remaining);
300                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
301                case TRACE_TYPE_80211:
302                        return trace_get_payload_from_80211(link,type,remaining);
303
304                case TRACE_TYPE_ETH:
305                        return trace_get_payload_from_ethernet(link,type,remaining);
306                case TRACE_TYPE_NONE:
307                        if ((*(char*)link&0xF0) == 0x40)
308                                *type=0x0800;
309                        else if ((*(char*)link&0xF0) == 0x60)
310                                *type=0x86DD;
311                        return link; /* I love the simplicity */
312                case TRACE_TYPE_LINUX_SLL:
313                        l = trace_get_payload_from_linux_sll(link,&dummytype,remaining);
314                        if (type) *type = dummytype;
315                        return (l ? trace_get_payload_from_link(l,
316                                                arphrd_type_to_libtrace(dummytype), type, remaining) : NULL);
317                       
318                case TRACE_TYPE_PFLOG:
319                        return trace_get_payload_from_pflog(link,type,remaining);
320                case TRACE_TYPE_POS:
321                        return trace_get_payload_from_pos(link,type,remaining);
322                case TRACE_TYPE_ATM:
323                        l=trace_get_payload_from_atm(link,NULL,remaining);
324                        return (l ? trace_get_payload_from_llcsnap(l,
325                                                type, remaining):NULL);
326                case TRACE_TYPE_DUCK:
327                        return NULL; /* duck packets have no payload! */
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                        return NULL;
739        }
740        fprintf(stderr,"Not implemented\n");
741        assert(0);
742        return NULL;
743}
744
745DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
746        void *link = trace_get_link(packet);
747        libtrace_80211_t *wifi;
748        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
749        if (!link)
750                return NULL;
751        switch (trace_get_link_type(packet)) {
752                case TRACE_TYPE_80211:
753                        wifi=(libtrace_80211_t*)link;
754                        return (uint8_t*)&wifi->mac1;
755                case TRACE_TYPE_80211_RADIO:
756                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
757                                        link,NULL,NULL);
758                        return (uint8_t*)&wifi->mac1;
759                case TRACE_TYPE_80211_PRISM:
760                        wifi=(libtrace_80211_t*)((char*)link+144);
761                        return (uint8_t*)&wifi->mac1;
762                case TRACE_TYPE_ETH:
763                        return (uint8_t*)&ethptr->ether_dhost;
764                case TRACE_TYPE_POS:
765                case TRACE_TYPE_NONE:
766                case TRACE_TYPE_ATM:
767                case TRACE_TYPE_HDLC_POS:
768                case TRACE_TYPE_LINUX_SLL:
769                case TRACE_TYPE_PFLOG:
770                case TRACE_TYPE_DUCK:
771                        /* No MAC address */
772                        return NULL;
773        }
774        fprintf(stderr,"Not implemented\n");
775        assert(0);
776        return NULL;
777}
778
779DLLEXPORT struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
780                struct sockaddr *addr)
781{
782        uint16_t proto;
783        uint32_t remaining;
784        void *l3;
785        struct ports_t *ports;
786        static struct sockaddr_storage dummy;
787
788        if (!addr)
789                addr=(struct sockaddr*)&dummy;
790
791        remaining = trace_get_capture_length(packet);
792
793        l3 = trace_get_payload_from_link(
794                        trace_get_link(packet),
795                        trace_get_link_type(packet),
796                        &proto,
797                        &remaining);
798
799        if (!l3)
800                return false;
801
802        for(;;) {
803                switch(proto) {
804                        case 0x8100:
805                                l3=trace_get_vlan_payload_from_ethernet_payload(
806                                                l3,&proto,NULL);
807                                continue;
808                        case 0x8847:
809                                l3=trace_get_mpls_payload_from_ethernet_payload(
810                                                l3,&proto,NULL);
811
812                                if (l3 && proto == 0x0) {
813                                        l3=trace_get_payload_from_ethernet(
814                                                l3,&proto,NULL);
815                                }
816                                continue;
817                        default:
818                                break;
819                }
820
821                break;
822        }
823
824        if (!l3)
825                return NULL;
826
827        switch (proto) {
828                case 0x0800: /* IPv4 */
829                {
830                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
831                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
832                        ports = (struct ports_t*)
833                                trace_get_payload_from_ip(ip,NULL,&remaining);
834                        addr4->sin_family=AF_INET;
835                        if (ports && remaining>=sizeof(*ports))
836                                addr4->sin_port=ports->src;
837                        else
838                                addr4->sin_port=0;
839                        addr4->sin_addr=ip->ip_src;
840                        return addr;
841                }
842                case 0x86DD: /* IPv6 */
843                {
844                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
845                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
846                        ports = (struct ports_t*)
847                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
848                        addr6->sin6_family=AF_INET6;
849                        if (ports && remaining>=sizeof(*ports))
850                                addr6->sin6_port=ports->dst;
851                        else
852                                addr6->sin6_port=0;
853                        addr6->sin6_flowinfo=0;
854                        addr6->sin6_addr=ip6->ip_src;
855                        return addr;
856                }
857                default:
858                        return NULL;
859        }
860}
861
862DLLEXPORT struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
863                struct sockaddr *addr)
864{
865        uint16_t proto;
866        uint32_t remaining;
867        void *transport;
868        static struct sockaddr_storage dummy;
869
870        if (!addr)
871                addr=(struct sockaddr*)&dummy;
872
873        remaining = trace_get_capture_length(packet);
874
875        transport = trace_get_payload_from_link(
876                        trace_get_link(packet),
877                        trace_get_link_type(packet),
878                        &proto,
879                        &remaining);
880
881        if (!transport)
882                return false;
883        for(;;) {
884                switch(proto) {
885                        case 0x8100:
886                                transport=trace_get_vlan_payload_from_ethernet_payload(transport,&proto,NULL);
887                                continue;
888                        case 0x8847:
889                                transport=trace_get_mpls_payload_from_ethernet_payload(transport,&proto,NULL);
890
891                                if (transport && proto == 0x0) {
892                                        transport=trace_get_payload_from_ethernet(
893                                                        transport,&proto,NULL);
894                                }
895                                continue;
896                        default:
897                                break;
898                }
899
900                break;
901        }
902
903        if (!transport)
904                return false;
905
906        switch (proto) {
907                case 0x0800: /* IPv4 */
908                {
909                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
910                        libtrace_ip_t *ip = (libtrace_ip_t*)transport;
911                        addr4->sin_family=AF_INET;
912                        addr4->sin_port=0;
913                        addr4->sin_addr=ip->ip_dst;
914                        return addr;
915                }
916                case 0x86DD: /* IPv6 */
917                {
918                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
919                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)transport;
920                        addr6->sin6_family=AF_INET6;
921                        addr6->sin6_port=0;
922                        addr6->sin6_flowinfo=0;
923                        addr6->sin6_addr=ip6->ip_dst;
924                        return addr;
925                }
926                default:
927                        return NULL;
928        }
929}
930
931/* parse an ip or tcp option
932 * @param[in,out] ptr   the pointer to the current option
933 * @param[in,out] len   the length of the remaining buffer
934 * @param[out] type     the type of the option
935 * @param[out] optlen   the length of the option
936 * @param[out] data     the data of the option
937 *
938 * @returns bool true if there is another option (and the fields are filled in)
939 *               or false if this was the last option.
940 *
941 * This updates ptr to point to the next option after this one, and updates
942 * len to be the number of bytes remaining in the options area.  Type is updated
943 * to be the code of this option, and data points to the data of this option,
944 * with optlen saying how many bytes there are.
945 *
946 * @note Beware of fragmented packets.
947 * @author Perry Lorier
948 */
949DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
950                        unsigned char *type,
951                        unsigned char *optlen,
952                        unsigned char **data)
953{
954        if (*len<=0)
955                return 0;
956        *type=**ptr;
957        switch(*type) {
958                case 0: /* End of options */
959                        return 0;
960                case 1: /* Pad */
961                        (*ptr)++;
962                        (*len)--;
963                        return 1;
964                default:
965                        *optlen = *(*ptr+1);
966                        if (*optlen<2)
967                                return 0; /* I have no idea wtf is going on
968                                           * with these packets
969                                           */
970                        (*len)-=*optlen;
971                        (*data)=(*ptr+2);
972                        (*ptr)+=*optlen;
973                        if (*len<0)
974                                return 0;
975                        return 1;
976        }
977        assert(0);
978}
979
980
Note: See TracBrowser for help on using the repository browser.