source: lib/protocols.c @ bad6a93

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

trace_get_vlan_payload_from_ethernet is now available to libtrace users.
Fixed error where erf wire length was having padding subtracted from it - wire length doesn't include padding.
erf can also attach padding to the end of packets - get_capture_length now returns the minimum of the record length - padding and the wire length.
Added support for RT_LOSTCONN - also other zero sized rt packets shouldn't cause TRACE_EVENT_TERMINATE anymore
rt header information is no longer stored statically when doing a non-blocking read
The packet->buffer for rt packets is now regarded as external, so now trace_destroy_packet shouldn't cause a segfault

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