source: lib/protocols.c @ c4cf162

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

Adds initial wireless support to libtrace. Applications can now use the trace_get_wireless_* functions to get wireless information such as signal strength, noise levels, frame check sequences, etc.

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