source: lib/protocols.c @ e8a6c52

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

Internal changes to trace_get_source_mac(). Now deals with Linux SLL headers :)

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