source: lib/protocols.c @ 63f4967

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

Cover destination protocol too

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