source: lib/protocols.c @ 8889370

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

trace_get_payload_from_linux_sll now returns a pointer to the start of the next header intead of trying to jump through the next one. It also returns the hardware address type instead of the protocol type now. trace_get_payload_from_link has been updated to recurse to step through the protocols. This makes _from_linux_sll more like the rest of the functions in protocols.c.
We also now have arphrd_type_to_libtrace() and libtrace_to_arphrd_type() functions to help with this.

  • 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*/
113static void *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.