source: lib/protocols.c @ 52c7cda

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

Added support for skipping Linux SLL headers to the trace_get_wireless functions, which means we can now use them on tcpdump captured traces.
Also reformatted link_wireless.c and cleaned up all of the compile warnings :)
Made trace_get_payload_from_linux_sll not static and added function prototypes for it and the new arphrd functions to libtrace_int.h

  • Property mode set to 100644
File size: 18.3 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
71static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
72{
73        /* TODO: Decode type != DATA
74         * TODO: We're assuming four address frame here... probably not good
75         */
76       
77        libtrace_80211_t *wifi;
78        libtrace_802_11_payload_t *eth;
79        uint8_t extra; /* how many QoS bytes to skip */
80       
81        if (remaining && *remaining < sizeof(libtrace_80211_t))
82                return NULL;
83
84        wifi=(libtrace_80211_t*)link;
85
86        /* Data packet? */
87        if (wifi->type != 2) {
88                return NULL;
89        }
90
91        /* Check for WME */
92        if (wifi->subtype & 0x8) {
93                /* indicates two octets of QoS before payload,
94                 * see IEEE802.11e-2005 pg 21
95                 * */
96                extra = 2;
97        } else 
98                extra = 0;
99
100        if (remaining && *remaining < sizeof(*eth))
101                return NULL;
102
103        eth=(libtrace_802_11_payload_t *)((char*)wifi+sizeof(*wifi)+extra);
104
105        if (type) *type=ntohs(eth->type);
106        if (remaining) *remaining = *remaining - sizeof(libtrace_80211_t) - extra - sizeof(*eth);
107       
108       
109        return (void*)((char*)eth+sizeof(*eth));
110}
111
112/* NB: type is returned as an ARPHRD_ type for SLL*/
113void *trace_get_payload_from_linux_sll(void *link,
114                uint16_t *type, uint32_t *remaining) 
115{
116        libtrace_sll_header_t *sll;
117        void *ret;
118
119        sll = (libtrace_sll_header_t*) link;
120
121        if (remaining) {
122                if (*remaining < sizeof(*sll))
123                        return NULL;
124                *remaining-=sizeof(*sll);
125        }
126
127        /* What kind of wacked out header, has this in host order?! */
128        //if (type) *type = htons(sll->protocol);
129
130        if (type) *type = ntohs(sll->hatype);
131
132        return (void*)((char*)sll+sizeof(*sll));
133
134}
135
136static void *trace_get_payload_from_atm(void *link,
137                uint16_t *type, uint32_t *remaining)
138{
139        /* 64 byte capture. */
140        libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
141
142        if (remaining) {
143                if (*remaining < sizeof(libtrace_llcsnap_t)+4)
144                        return NULL;
145                *remaining-=(sizeof(libtrace_llcsnap_t)+4);
146        }
147
148        /* advance the llc ptr +4 into the link layer.
149         * TODO: need to check what is in these 4 bytes.
150         * don't have time!
151         */
152        llc = (libtrace_llcsnap_t*)((char *)llc + 4);
153
154        if (type) *type = ntohs(llc->type);
155
156        return (void*)((char*)llc+sizeof(*llc));
157}
158
159static void *trace_get_payload_from_pos(void *link, 
160                uint16_t *type, uint32_t *remaining)
161{
162        /* 64 byte capture. */
163        libtrace_pos_t *pos = (libtrace_pos_t*)link;
164
165        if (remaining) {
166                if (*remaining < sizeof(libtrace_pos_t))
167                        return NULL;
168                *remaining-=sizeof(libtrace_pos_t);
169        }
170
171        if (type) *type = ntohs(pos->ether_type);
172
173        return (void*)((char *)pos+sizeof(*pos));
174}
175
176static void *trace_get_payload_from_pflog(void *link,
177                uint16_t *type, uint32_t *remaining)
178{
179        libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
180    if (remaining) {
181                if (*remaining<sizeof(*pflog)) 
182                        return NULL;
183                *remaining-=sizeof(*pflog);
184        }
185        if (type) {
186                switch(pflog->af) {
187                        case AF_INET6: *type=0x86DD; break;
188                        case AF_INET:  *type=0x0800; break;
189                        default:
190                                      /* Unknown */
191                                      return NULL;
192                }
193        }
194        return (void*)((char*)pflog+ sizeof(*pflog));
195}
196
197/* Returns the 'payload' of the prism header, which is the 802.11 frame */
198static void *trace_get_payload_from_prism (void *link,
199                uint16_t *type, uint32_t *remaining)
200{
201        if (remaining) {
202                if (*remaining<144) 
203                        return NULL;
204                *remaining-=144;
205        }
206
207        if (type) *type = 0;
208
209        return (void *) ((char*)link+144);
210}
211
212/* Returns the 'payload' of the radiotap header, which is the 802.11 frame */
213static void *trace_get_payload_from_radiotap (void *link, 
214                uint16_t *type, uint32_t *remaining)
215{
216        struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link;
217        uint16_t rtaplen = bswap_le_to_host16(rtap->it_len);
218        if (remaining) {
219                if (*remaining < rtaplen)
220                        return NULL;
221                *remaining -= rtaplen;
222        }
223
224        if (type) *type = 0;
225
226        return (void*) ((char*)link + rtaplen);
227}
228
229void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
230                uint16_t *type, uint32_t *remaining)
231{
232        void *l = NULL;
233        uint16_t dummytype;
234       
235        switch(linktype) {
236                case TRACE_TYPE_80211_PRISM:
237                        l = trace_get_payload_from_prism(link,type,remaining);
238                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
239                case TRACE_TYPE_80211_RADIO:
240                        l = trace_get_payload_from_radiotap(link,type,remaining);
241                        return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
242                case TRACE_TYPE_80211:
243                        return trace_get_payload_from_80211(link,type,remaining);
244
245                case TRACE_TYPE_ETH:
246                        return trace_get_payload_from_ethernet(link,type,remaining);
247                case TRACE_TYPE_NONE:
248                        if ((*(char*)link&0xF0) == 0x40)
249                                *type=0x0800;
250                        else if ((*(char*)link&0xF0) == 0x60)
251                                *type=0x86DD;
252                        return link; /* I love the simplicity */
253                case TRACE_TYPE_LINUX_SLL:
254                        l = trace_get_payload_from_linux_sll(link,&dummytype,remaining);
255                        if (type) *type = dummytype;
256                        return (l ? trace_get_payload_from_link(l,
257                                                arphrd_type_to_libtrace(dummytype), type, remaining) : NULL);
258                       
259                case TRACE_TYPE_PFLOG:
260                        return trace_get_payload_from_pflog(link,type,remaining);
261                case TRACE_TYPE_POS:
262                        return trace_get_payload_from_pos(link,type,remaining);
263                case TRACE_TYPE_ATM:
264                        return trace_get_payload_from_atm(link,type,remaining);
265                case TRACE_TYPE_DUCK:
266                        return NULL; /* duck packets have no payload! */
267        }
268        fprintf(stderr,"Don't understand link layer type %i in trace_get_payload_from_link()\n",
269                linktype);
270        return NULL;
271}
272
273libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
274{
275        uint16_t type;
276        void *link = trace_get_link(packet);
277        void *ret;
278
279        if (!link)
280                return NULL;
281       
282        ret=trace_get_payload_from_link(
283                        link,
284                        trace_get_link_type(packet),
285                        &type, NULL);
286
287        if (!ret)
288                return NULL;
289
290        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
291
292        if (!ret || type!=0x0800)
293                return NULL;
294
295        /* Not an IPv4 packet */
296        if (((libtrace_ip_t*)ret)->ip_v != 4)
297                return NULL;
298
299        return (libtrace_ip_t*)ret;
300}
301
302libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
303{
304        uint16_t type;
305        void *link=trace_get_link(packet);
306        void *ret;
307       
308        if (!link)
309                return NULL;
310
311        ret=trace_get_payload_from_link(
312                        link,
313                        trace_get_link_type(packet),
314                        &type,NULL);
315
316        if (!ret)
317                return NULL;
318
319        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
320
321        if (!ret || type!=0x86DD)
322                return NULL;
323
324        return (libtrace_ip6_t*)ret;
325}
326
327#define SW_IP_OFFMASK 0xff1f
328
329DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
330                uint32_t *remaining) 
331{
332        void *trans_ptr = 0;
333
334        if ((ipptr->ip_off & SW_IP_OFFMASK) != 0) {
335                return NULL;
336        }
337
338        if (remaining) {
339                if (*remaining<(ipptr->ip_hl*4U)) {
340                        return NULL;
341                }
342                *remaining-=(ipptr->ip_hl * 4);
343        }
344
345        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
346
347        if (prot) *prot = ipptr->ip_p;
348
349        return trans_ptr;
350}
351
352void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
353                uint32_t *remaining) 
354{
355        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
356        uint8_t nxt = ipptr->nxt;
357
358        if (remaining) {
359                if (*remaining<sizeof(libtrace_ip6_t))
360                        return NULL;
361                *remaining-=sizeof(libtrace_ip6_t);
362        }
363
364        while(1) {
365                switch (nxt) {
366                        case 0: /* hop by hop options */
367                        case 43: /* routing */
368                        case 44: /* fragment */
369                        case 50: /* ESP */
370                        case 51: /* AH */
371                        case 60: /* Destination options */
372                                {
373                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
374                                        +sizeof(libtrace_ip6_ext_t);
375
376                                        if (remaining) {
377                                                if (*remaining < len) {
378                                                        /* Snap too short */
379                                                        return NULL;
380                                                }
381                                                *remaining-=len;
382                                        }
383
384                                        payload=(char*)payload+len;
385                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
386                                        continue;
387                                }
388                        default:
389                                if (prot) *prot=nxt;
390                                return payload;
391                }
392        }
393}
394
395DLLEXPORT void *trace_get_transport(libtrace_packet_t *packet, 
396                uint8_t *proto,
397                uint32_t *remaining
398                ) 
399{
400        void *transport;
401        uint8_t dummy_proto;
402        uint16_t ethertype;
403        void *link;
404        uint32_t dummy_remaining;
405
406        if (!proto) proto=&dummy_proto;
407
408        if (!remaining) remaining=&dummy_remaining;
409
410        *remaining = trace_get_capture_length(packet);
411
412        link=trace_get_link(packet);
413
414        if (!link)
415                return NULL;
416
417        transport = trace_get_payload_from_link(
418                        link,
419                        trace_get_link_type(packet),
420                        &ethertype,
421                        remaining);
422
423        if (!transport)
424                return NULL;
425
426        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
427                        &ethertype,
428                        remaining);
429
430        if (!transport)
431                return NULL;
432
433        switch (ethertype) {
434                case 0x0800: /* IPv4 */
435                        transport=trace_get_payload_from_ip(
436                                (libtrace_ip_t*)transport, proto, remaining);
437                        /* IPv6 */
438                        if (transport && *proto == 41) {
439                                transport=trace_get_payload_from_ip6(
440                                 (libtrace_ip6_t*)transport, proto,remaining);
441                        }
442                        return transport;
443                case 0x86DD: /* IPv6 */
444                        return trace_get_payload_from_ip6(
445                                (libtrace_ip6_t*)transport, proto, remaining);
446                       
447                default:
448                        *proto=0;
449                        return NULL;
450        }
451
452}
453
454DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
455        uint8_t proto;
456        libtrace_tcp_t *tcp;
457
458        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,NULL);
459
460        if (!tcp || proto != 6)
461                return NULL;
462
463        return (libtrace_tcp_t*)tcp;
464}
465
466DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
467{
468        libtrace_tcp_t *tcpptr = 0;
469
470        if (ip->ip_p == 6)  {
471                tcpptr = (libtrace_tcp_t *)
472                        trace_get_payload_from_ip(ip, NULL, remaining);
473        }
474
475        return tcpptr;
476}
477
478DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
479        uint8_t proto;
480        libtrace_udp_t *udp;
481
482        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,NULL);
483
484        if (!udp || proto != 17)
485                return NULL;
486
487        return udp;
488}
489
490DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
491{
492        libtrace_udp_t *udpptr = 0;
493
494        if (ip->ip_p == 17) {
495                udpptr = (libtrace_udp_t *)
496                        trace_get_payload_from_ip(ip, NULL, remaining);
497        }
498
499        return udpptr;
500}
501
502DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
503        uint8_t proto;
504        libtrace_icmp_t *icmp;
505
506        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,NULL);
507
508        if (!icmp || proto != 1)
509                return NULL;
510
511        return icmp;
512}
513
514DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
515{
516        libtrace_icmp_t *icmpptr = 0;
517
518        if (ip->ip_p == 1)  {
519                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
520                                NULL, remaining);
521        }
522
523        return icmpptr;
524}
525
526DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
527{
528        if (remaining) {
529                if (*remaining < sizeof(libtrace_udp_t))
530                        return NULL;
531                *remaining-=sizeof(libtrace_udp_t);
532        }
533        return (void*)((char*)udp+sizeof(libtrace_udp_t));
534}
535
536DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
537{
538        unsigned int dlen = tcp->doff*4;
539        if (remaining) {
540                if (*remaining < dlen)
541                        return NULL;
542                *remaining-=dlen;
543        }
544        return (void *)((char *)tcp+dlen);
545}
546
547DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
548{
549        if (remaining) {
550                if (*remaining < sizeof(libtrace_icmp_t))
551                        return NULL;
552                *remaining-=sizeof(libtrace_icmp_t);
553        }
554        return (char*)icmp+sizeof(libtrace_icmp_t);
555}
556
557struct ports_t {
558        uint16_t src;
559        uint16_t dst;
560};
561
562/* Return the client port
563 */
564DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
565{
566        uint32_t remaining;
567        struct ports_t *port = 
568                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
569                        NULL, &remaining);
570
571        /* snapped too early */
572        if (remaining<2)
573                return 0;
574
575        if (port)
576                return ntohs(port->src);
577        else
578                return 0;
579}
580
581/* Same as get_source_port except use the destination port */
582DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
583{
584        uint32_t remaining;
585        struct ports_t *port = 
586                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
587                        NULL, &remaining);
588        /* snapped to early */
589        if (remaining<4)
590                return 0;
591
592        if (port)
593                return ntohs(port->dst);
594        else
595                return 0;
596}
597
598
599uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
600        void *link = trace_get_link(packet);
601        libtrace_80211_t *wifi;
602        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
603        if (!link)
604                return NULL;
605        switch (trace_get_link_type(packet)) {
606                case TRACE_TYPE_80211:
607                        wifi=(libtrace_80211_t*)link;
608                        return (uint8_t*)&wifi->mac2;
609                case TRACE_TYPE_80211_PRISM:
610                        wifi=(libtrace_80211_t*)((char*)link+144);
611                        return (uint8_t*)&wifi->mac2;
612                case TRACE_TYPE_ETH:
613                        return (uint8_t*)&ethptr->ether_shost;
614                case TRACE_TYPE_POS:
615                case TRACE_TYPE_NONE:
616                case TRACE_TYPE_HDLC_POS:
617                case TRACE_TYPE_LINUX_SLL:
618                case TRACE_TYPE_PFLOG:
619                case TRACE_TYPE_ATM:
620                case TRACE_TYPE_DUCK:
621                        return NULL;
622        }
623        fprintf(stderr,"Not implemented\n");
624        assert(0);
625        return NULL;
626}
627
628DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
629        void *link = trace_get_link(packet);
630        libtrace_80211_t *wifi;
631        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
632        if (!link)
633                return NULL;
634        switch (trace_get_link_type(packet)) {
635                case TRACE_TYPE_80211:
636                        wifi=(libtrace_80211_t*)link;
637                        return (uint8_t*)&wifi->mac1;
638                case TRACE_TYPE_80211_PRISM:
639                        wifi=(libtrace_80211_t*)((char*)link+144);
640                        return (uint8_t*)&wifi->mac1;
641                case TRACE_TYPE_ETH:
642                        return (uint8_t*)&ethptr->ether_dhost;
643                case TRACE_TYPE_POS:
644                case TRACE_TYPE_NONE:
645                case TRACE_TYPE_ATM:
646                case TRACE_TYPE_HDLC_POS:
647                case TRACE_TYPE_LINUX_SLL:
648                case TRACE_TYPE_PFLOG:
649                case TRACE_TYPE_DUCK:
650                        /* No MAC address */
651                        return NULL;
652        }
653        fprintf(stderr,"Not implemented\n");
654        assert(0);
655        return NULL;
656}
657
658DLLEXPORT struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
659                struct sockaddr *addr)
660{
661        uint16_t proto;
662        uint32_t remaining;
663        void *l3;
664        struct ports_t *ports;
665        static struct sockaddr_storage dummy;
666
667        if (!addr)
668                addr=(struct sockaddr*)&dummy;
669
670        remaining = trace_get_capture_length(packet);
671
672        l3 = trace_get_payload_from_link(
673                        trace_get_link(packet),
674                        trace_get_link_type(packet),
675                        &proto,
676                        &remaining);
677
678        if (!l3)
679                return false;
680
681        l3 = trace_get_vlan_payload_from_ethernet_payload(l3,
682                        &proto,
683                        &remaining);
684
685        if (!l3)
686                return NULL;
687
688        switch (proto) {
689                case 0x0800: /* IPv4 */
690                {
691                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
692                        libtrace_ip_t *ip = (libtrace_ip_t*)l3;
693                        ports = (struct ports_t*)
694                                trace_get_payload_from_ip(ip,NULL,&remaining);
695                        addr4->sin_family=AF_INET;
696                        if (ports && remaining>=sizeof(*ports))
697                                addr4->sin_port=ports->src;
698                        else
699                                addr4->sin_port=0;
700                        addr4->sin_addr=ip->ip_src;
701                        return addr;
702                }
703                case 0x86DD: /* IPv6 */
704                {
705                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
706                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
707                        ports = (struct ports_t*)
708                                trace_get_payload_from_ip6(ip6,NULL,&remaining);
709                        addr6->sin6_family=AF_INET6;
710                        if (ports && remaining>=sizeof(*ports))
711                                addr6->sin6_port=ports->dst;
712                        else
713                                addr6->sin6_port=0;
714                        addr6->sin6_flowinfo=0;
715                        addr6->sin6_addr=ip6->ip_src;
716                        return addr;
717                }
718                default:
719                        return NULL;
720        }
721}
722
723DLLEXPORT struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
724                struct sockaddr *addr)
725{
726        uint16_t proto;
727        uint32_t remaining;
728        void *transport;
729        static struct sockaddr_storage dummy;
730
731        if (!addr)
732                addr=(struct sockaddr*)&dummy;
733
734        remaining = trace_get_capture_length(packet);
735
736        transport = trace_get_payload_from_link(
737                        trace_get_link(packet),
738                        trace_get_link_type(packet),
739                        &proto,
740                        &remaining);
741
742        if (!transport)
743                return false;
744
745        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
746                        &proto,
747                        &remaining);
748
749        if (!transport)
750                return false;
751
752        switch (proto) {
753                case 0x0800: /* IPv4 */
754                {
755                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
756                        libtrace_ip_t *ip = (libtrace_ip_t*)transport;
757                        addr4->sin_family=AF_INET;
758                        addr4->sin_port=0;
759                        addr4->sin_addr=ip->ip_dst;
760                        return addr;
761                }
762                case 0x86DD: /* IPv6 */
763                {
764                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
765                        libtrace_ip6_t *ip6 = (libtrace_ip6_t*)transport;
766                        addr6->sin6_family=AF_INET6;
767                        addr6->sin6_port=0;
768                        addr6->sin6_flowinfo=0;
769                        addr6->sin6_addr=ip6->ip_dst;
770                        return addr;
771                }
772                default:
773                        return NULL;
774        }
775}
776
777/* parse an ip or tcp option
778 * @param[in,out] ptr   the pointer to the current option
779 * @param[in,out] len   the length of the remaining buffer
780 * @param[out] type     the type of the option
781 * @param[out] optlen   the length of the option
782 * @param[out] data     the data of the option
783 *
784 * @returns bool true if there is another option (and the fields are filled in)
785 *               or false if this was the last option.
786 *
787 * This updates ptr to point to the next option after this one, and updates
788 * len to be the number of bytes remaining in the options area.  Type is updated
789 * to be the code of this option, and data points to the data of this option,
790 * with optlen saying how many bytes there are.
791 *
792 * @note Beware of fragmented packets.
793 * @author Perry Lorier
794 */
795DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
796                        unsigned char *type,
797                        unsigned char *optlen,
798                        unsigned char **data)
799{
800        if (*len<=0)
801                return 0;
802        *type=**ptr;
803        switch(*type) {
804                case 0: /* End of options */
805                        return 0;
806                case 1: /* Pad */
807                        (*ptr)++;
808                        (*len)--;
809                        return 1;
810                default:
811                        *optlen = *(*ptr+1);
812                        if (*optlen<2)
813                                return 0; /* I have no idea wtf is going on
814                                           * with these packets
815                                           */
816                        (*len)-=*optlen;
817                        (*data)=(*ptr+2);
818                        (*ptr)+=*optlen;
819                        if (*len<0)
820                                return 0;
821                        return 1;
822        }
823        assert(0);
824}
825
826
Note: See TracBrowser for help on using the repository browser.