source: lib/protocols.c @ 6df012d

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

Fix get_payload_from_link for prism and radiotap.
Make sure to use bswap when looking at radiotap length.
Tidy up exported API, don't export get_payload_from_prism or _from_radiotap.

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