source: lib/protocols.c @ 7c3be58

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

Get mac addresses through radiotap headers, cleans up some warnings

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