source: lib/protocols.c @ a21af3d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since a21af3d was a21af3d, checked in by Perry Lorier <perry@…>, 15 years ago

Kill dead (commented out) code

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