source: lib/protocols.c @ a005846

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

squish implicit declaration warnings

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