source: lib/protocols.c @ 64b6517

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

Fix pcap dependancies

  • Property mode set to 100644
File size: 12.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
12/* Returns the payload from 802.3 ethernet.  Type optionally returned in
13 * "type" in host byte order.  This will return a vlan header.
14 */
15static void *trace_get_payload_from_ethernet(void *ethernet, 
16                uint16_t *type,
17                uint32_t *remaining)
18{
19        libtrace_ether_t *eth = ethernet;
20
21        if (remaining) {
22                if (*remaining < sizeof(*eth))
23                        return NULL;
24                *remaining-=sizeof(*eth);
25        }
26
27        if (type)
28                *type = ntohs(eth->ether_type);
29
30        return (void*)((char *)eth + sizeof(*eth));
31}
32
33/* skip any 802.1q headers if necessary
34 * type is input/output
35 */
36static void *trace_get_vlan_payload_from_ethernet_payload(void *ethernet, uint16_t *type,
37                uint32_t *remaining)
38{
39        assert(type && "You must pass a type in!");
40
41        if (*type == 0x8100) {
42                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
43
44                if (remaining) {
45                        if (*remaining < sizeof(libtrace_8021q_t))
46                                return NULL;
47
48                        *remaining=*remaining-sizeof(libtrace_8021q_t);
49                }
50
51                *type = ntohs(vlanhdr->vlan_ether_type);
52
53                return (void*)((char *)ethernet + sizeof(*vlanhdr));
54        }
55
56        return NULL;
57}
58
59static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
60{
61        libtrace_80211_t *wifi = link;
62        struct ieee_802_11_payload *eth;
63
64        if (remaining && *remaining < sizeof(libtrace_80211_t))
65                return NULL;
66
67        /* Data packet? */
68        if (wifi->type != 2) {
69                return NULL;
70        }
71
72        if (remaining && *remaining < sizeof(*eth))
73                return NULL;
74
75        eth=(void*)((char*)wifi+sizeof(*eth));
76
77        if (*type) *type=eth->type;
78
79        return eth;
80}
81
82static void *trace_get_payload_from_linux_sll(void *link,
83                uint16_t *type, uint32_t *remaining) 
84{
85        struct trace_sll_header_t *sll;
86
87        sll = link;
88
89        if (remaining) {
90                if (*remaining < sizeof(*sll))
91                        return NULL;
92                *remaining-=sizeof(*sll);
93        }
94
95        if (*type) *type = sll->protocol;
96
97        return (void*)((char*)sll+sizeof(*sll));
98}
99
100static void *trace_get_payload_from_atm(void *link,
101                uint16_t *type, uint32_t *remaining)
102{
103        /* 64 byte capture. */
104        struct libtrace_llcsnap *llc = link;
105
106        if (remaining) {
107                if (*remaining < sizeof(struct libtrace_llcsnap)+4)
108                        return NULL;
109                *remaining-=(sizeof(struct libtrace_llcsnap)+4);
110        }
111
112        /* advance the llc ptr +4 into the link layer.
113         * TODO: need to check what is in these 4 bytes.
114         * don't have time!
115         */
116        llc = (void*)((char *)llc + 4);
117
118        if (*type) *type = ntohs(llc->type);
119
120        return (void*)((char*)llc+sizeof(*llc));
121}
122
123static void *trace_get_payload_from_legacy_pos(void *link, 
124                uint16_t *type, uint32_t *remaining)
125{
126        /* 64 byte capture. */
127        struct libtrace_pos *pos = link;
128
129        if (remaining) {
130                if (*remaining < sizeof(struct libtrace_pos))
131                        return NULL;
132                *remaining-=sizeof(struct libtrace_pos);
133        }
134
135        if (type) *type = ntohs(pos->ether_type);
136
137        return (void*)((char *)pos+sizeof(*pos));
138}
139
140static void *trace_get_payload_from_pflog(void *link,
141                uint16_t *type, uint32_t *remaining)
142{
143        struct trace_pflog_header_t *pflog = link;
144        if (remaining) {
145                if (*remaining<sizeof(*pflog)) 
146                        return NULL;
147                *remaining-=sizeof(*pflog);
148        }
149        if (type) {
150                switch(pflog->af) {
151                        case AF_INET6: *type=0x86DD; break;
152                        case AF_INET: *type=0x0800; break;
153                        default:
154                                      /* Unknown */
155                                      return NULL;
156                }
157        }
158        return (void*)((char*)pflog+ sizeof(*pflog));
159}
160
161void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
162                uint16_t *type, uint32_t *remaining)
163{
164        switch(linktype) {
165                case TRACE_TYPE_80211_PRISM:
166                        return trace_get_payload_from_80211((char*)link+144,
167                                        type,remaining);
168                case TRACE_TYPE_80211:
169                        return trace_get_payload_from_80211(link,type,remaining);
170                case TRACE_TYPE_ETH:
171                case TRACE_TYPE_LEGACY_ETH:
172                        return trace_get_payload_from_ethernet(link,type,remaining);
173                case TRACE_TYPE_NONE:
174                        return link; /* I love the simplicity */
175                case TRACE_TYPE_LINUX_SLL:
176                        return trace_get_payload_from_linux_sll(link,type,remaining);
177                case TRACE_TYPE_PFLOG:
178                        return trace_get_payload_from_pflog(link,type,remaining);
179                case TRACE_TYPE_LEGACY_POS:
180                        return trace_get_payload_from_legacy_pos(link,type,remaining);
181                case TRACE_TYPE_LEGACY_ATM:
182                case TRACE_TYPE_ATM:
183                        return trace_get_payload_from_atm(link,type,remaining);
184        }
185        fprintf(stderr,"Don't understand link layer type %i in trace_get_ip6()\n",
186                linktype);
187        return NULL;
188}
189
190libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
191{
192        uint16_t type;
193        void *ret=trace_get_payload_from_link(
194                        trace_get_link(packet),
195                        trace_get_link_type(packet),
196                        &type, NULL);
197
198        if (!ret)
199                return NULL;
200
201        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
202
203        if (!ret || type!=0x0800)
204                return NULL;
205
206        return ret;
207}
208
209libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
210{
211        uint16_t type;
212        void *ret=trace_get_payload_from_link(
213                        trace_get_link(packet),
214                        trace_get_link_type(packet),
215                        &type,NULL);
216
217        if (!ret)
218                return NULL;
219
220        ret=trace_get_vlan_payload_from_ethernet_payload(ret,&type,NULL);
221
222        if (!ret || type!=0x86DD)
223                return NULL;
224
225        return ret;
226}
227
228#define SW_IP_OFFMASK 0xff1f
229
230void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
231                uint32_t *remaining) 
232{
233        void *trans_ptr = 0;
234
235        if ((ipptr->ip_off & SW_IP_OFFMASK) != 0)
236                return NULL;
237
238        if (remaining) {
239                if (*remaining<(ipptr->ip_hl*4U)) {
240                        return NULL;
241                }
242                *remaining-=(ipptr->ip_hl * 4);
243        }
244
245        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
246
247        if (prot) *prot = ipptr->ip_p;
248
249        return trans_ptr;
250}
251
252void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
253                uint32_t *remaining) 
254{
255        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
256        uint8_t nxt = ipptr->nxt;
257
258        if (remaining) {
259                if (*remaining<sizeof(libtrace_ip6_t))
260                        return NULL;
261                *remaining-=sizeof(libtrace_ip6_t);
262        }
263
264        while(1) {
265                switch (nxt) {
266                        case 0: /* hop by hop options */
267                        case 43: /* routing */
268                        case 44: /* fragment */
269                        case 50: /* ESP */
270                        case 51: /* AH */
271                        case 60: /* Destination options */
272                                {
273                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
274                                        +sizeof(libtrace_ip6_ext_t);
275
276                                        if (remaining) {
277                                                if (*remaining < len) {
278                                                        /* Snap too short */
279                                                        return NULL;
280                                                }
281                                                *remaining-=len;
282                                        }
283
284                                        payload=(char*)payload+len;
285                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
286                                        continue;
287                                }
288                        default:
289                                if (prot) *prot=nxt;
290                                return payload;
291                }
292        }
293}
294
295void *trace_get_transport(libtrace_packet_t *packet, 
296                uint8_t *proto,
297                uint32_t *remaining
298                ) 
299{
300        void *transport;
301        uint8_t dummy;
302        uint16_t ethertype;
303
304        if (!proto) proto=&dummy;
305
306        if (remaining)
307                *remaining = trace_get_capture_length(packet);
308
309        transport = trace_get_payload_from_link(
310                        trace_get_link(packet),
311                        trace_get_link_type(packet),
312                        &ethertype,
313                        remaining);
314
315        if (!transport)
316                return NULL;
317
318        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
319                        &ethertype,
320                        remaining);
321
322        if (!transport)
323                return NULL;
324
325        switch (*proto) {
326                case 0x0800: /* IPv4 */
327                        transport=trace_get_payload_from_ip(transport, proto, remaining);
328                        /* IPv6 */
329                        if (transport && *proto == 41) {
330                                transport=trace_get_payload_from_ip6(transport,
331                                                proto,remaining);
332                        }
333                        return transport;
334                case 0x86DD: /* IPv6 */
335                        return trace_get_payload_from_ip6(transport, proto, remaining);
336                       
337                default:
338                        return NULL;
339        }
340
341}
342
343libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
344        uint8_t proto;
345        libtrace_tcp_t *tcp;
346
347        tcp=trace_get_transport(packet,&proto,NULL);
348
349        if (proto != 6)
350                return NULL;
351
352        return tcp;
353}
354
355libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
356{
357        struct libtrace_tcp *tcpptr = 0;
358
359        if (ip->ip_p == 6)  {
360                tcpptr = (struct libtrace_tcp *)
361                        trace_get_payload_from_ip(ip, NULL, remaining);
362        }
363
364        return tcpptr;
365}
366
367libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
368        uint8_t proto;
369        libtrace_udp_t *udp;
370
371        udp=trace_get_transport(packet,&proto,NULL);
372
373        if (proto != 17)
374                return NULL;
375
376        return udp;
377}
378
379libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
380{
381        struct libtrace_udp *udpptr = 0;
382
383        if (ip->ip_p == 17) {
384                udpptr = (libtrace_udp_t *)
385                        trace_get_payload_from_ip(ip, NULL, remaining);
386        }
387
388        return udpptr;
389}
390
391libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
392        uint8_t proto;
393        libtrace_icmp_t *icmp;
394
395        icmp=trace_get_transport(packet,&proto,NULL);
396
397        if (proto != 1)
398                return NULL;
399
400        return icmp;
401}
402
403libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
404{
405        libtrace_icmp_t *icmpptr = 0;
406
407        if (ip->ip_p == 1)  {
408                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
409                                NULL, remaining);
410        }
411
412        return icmpptr;
413}
414
415void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
416{
417        if (remaining) {
418                if (*remaining < sizeof(libtrace_udp_t))
419                        return NULL;
420                *remaining-=sizeof(libtrace_udp_t);
421        }
422        return (void*)((char*)udp+sizeof(libtrace_udp_t));
423}
424
425void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
426{
427        unsigned int dlen = tcp->doff*4;
428        if (remaining) {
429                if (*remaining < dlen)
430                        return NULL;
431                *remaining-=dlen;
432        }
433        return tcp+dlen;
434}
435
436void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
437{
438        if (remaining) {
439                if (*remaining < sizeof(libtrace_icmp_t))
440                        return NULL;
441                *remaining-=sizeof(libtrace_icmp_t);
442        }
443        return (char*)icmp+sizeof(libtrace_icmp_t);
444}
445
446struct ports_t {
447        uint16_t src;
448        uint16_t dst;
449};
450
451/* Return the client port
452 */
453uint16_t trace_get_source_port(const libtrace_packet_t *packet)
454{
455        struct ports_t *port = trace_get_transport((libtrace_packet_t*)packet,
456                        NULL, NULL);
457
458        return ntohs(port->src);
459}
460
461/* Same as get_source_port except use the destination port */
462uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
463{
464        struct ports_t *port = trace_get_transport((libtrace_packet_t*)packet,
465                        NULL, NULL);
466
467        return ntohs(port->dst);
468}
469
470
471uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
472        void *link = trace_get_link(packet);
473        libtrace_80211_t *wifi = link;
474        libtrace_ether_t *ethptr = link;
475        if (!link)
476                return NULL;
477        switch (trace_get_link_type(packet)) {
478                case TRACE_TYPE_80211:
479                        return (uint8_t*)&wifi->mac2;
480                case TRACE_TYPE_ETH:
481                        return (uint8_t*)&ethptr->ether_shost;
482                default:
483                        fprintf(stderr,"Not implemented\n");
484                        assert(0);
485        }
486}
487
488uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) {
489        void *link = trace_get_link(packet);
490        libtrace_80211_t *wifi = link;
491        libtrace_ether_t *ethptr = link;
492        if (!link)
493                return NULL;
494        switch (trace_get_link_type(packet)) {
495                case TRACE_TYPE_80211:
496                        return (uint8_t*)&wifi->mac1;
497                case TRACE_TYPE_ETH:
498                        return (uint8_t*)&ethptr->ether_dhost;
499                default:
500                        fprintf(stderr,"Not implemented\n");
501                        assert(0);
502        }
503}
504
505struct sockaddr *trace_get_source_address(const libtrace_packet_t *packet, 
506                struct sockaddr *addr)
507{
508        uint16_t proto;
509        uint32_t remaining;
510        void *transport;
511        static struct sockaddr_storage dummy;
512
513        if (!addr)
514                addr=(struct sockaddr*)&dummy;
515
516        remaining = trace_get_capture_length(packet);
517
518        transport = trace_get_payload_from_link(
519                        trace_get_link(packet),
520                        trace_get_link_type(packet),
521                        &proto,
522                        &remaining);
523
524        if (!transport)
525                return false;
526
527        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
528                        &proto,
529                        &remaining);
530
531        if (!transport)
532                return false;
533
534        switch (proto) {
535                case 0x0800: /* IPv4 */
536                {
537                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
538                        libtrace_ip_t *ip = transport;
539                        addr4->sin_family=AF_INET;
540                        addr4->sin_port=0;
541                        addr4->sin_addr=ip->ip_src;
542                        return addr;
543                }
544                case 0x86DD: /* IPv6 */
545                {
546                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
547                        libtrace_ip6_t *ip6 = transport;
548                        addr6->sin6_family=AF_INET6;
549                        addr6->sin6_port=0;
550                        addr6->sin6_flowinfo=0;
551                        addr6->sin6_addr=ip6->ip_src;
552                        return addr;
553                }
554                default:
555                        return NULL;
556        }
557}
558
559struct sockaddr *trace_get_destination_address(const libtrace_packet_t *packet, 
560                struct sockaddr *addr)
561{
562        uint16_t proto;
563        uint32_t remaining;
564        void *transport;
565        static struct sockaddr_storage dummy;
566
567        if (!addr)
568                addr=(struct sockaddr*)&dummy;
569
570        remaining = trace_get_capture_length(packet);
571
572        transport = trace_get_payload_from_link(
573                        trace_get_link(packet),
574                        trace_get_link_type(packet),
575                        &proto,
576                        &remaining);
577
578        if (!transport)
579                return false;
580
581        transport = trace_get_vlan_payload_from_ethernet_payload(transport,
582                        &proto,
583                        &remaining);
584
585        if (!transport)
586                return false;
587
588        switch (proto) {
589                case 0x0800: /* IPv4 */
590                {
591                        struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
592                        libtrace_ip_t *ip = transport;
593                        addr4->sin_family=AF_INET;
594                        addr4->sin_port=0;
595                        addr4->sin_addr=ip->ip_dst;
596                        return addr;
597                }
598                case 0x86DD: /* IPv6 */
599                {
600                        struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
601                        libtrace_ip6_t *ip6 = transport;
602                        addr6->sin6_family=AF_INET6;
603                        addr6->sin6_port=0;
604                        addr6->sin6_flowinfo=0;
605                        addr6->sin6_addr=ip6->ip_dst;
606                        return addr;
607                }
608                default:
609                        return NULL;
610        }
611}
612
Note: See TracBrowser for help on using the repository browser.