source: lib/protocols.c @ a842286

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

Finish migration to protocols.c, add more IPv6 support

  • Property mode set to 100644
File size: 10.6 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
9
10static void *trace_get_ip_from_ethernet(void *ethernet, int *skipped)
11{
12        libtrace_ether_t *eth = ethernet;
13       
14        if (ntohs(eth->ether_type)==0x0800) {
15                if (skipped)
16                        *skipped=sizeof(libtrace_ether_t);
17                return (void*)((char *)eth + sizeof(*eth));
18        } else if (ntohs(eth->ether_type) == 0x8100) {
19                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)eth;
20                if (skipped)
21                        *skipped=sizeof(libtrace_ether_t);
22                if (ntohs(vlanhdr->vlan_ether_type) == 0x0800) {
23                        return (void*)((char *)eth + sizeof(*vlanhdr));
24                }
25        }
26       
27        return NULL;
28}
29
30static void *trace_get_ip6_from_ethernet(void *ethernet, int *skipped)
31{
32        libtrace_ether_t *eth = ethernet;
33       
34        if (ntohs(eth->ether_type)==0x86DD) {
35                if (skipped)
36                        *skipped=sizeof(libtrace_ether_t);
37                return (void*)((char *)eth + sizeof(*eth));
38        } else if (ntohs(eth->ether_type) == 0x8100) {
39                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)eth;
40                if (skipped)
41                        *skipped=sizeof(libtrace_ether_t);
42                if (ntohs(vlanhdr->vlan_ether_type) == 0x86DD) {
43                        return (void*)((char *)eth + sizeof(*vlanhdr));
44                }
45        }
46       
47        return NULL;
48}
49
50static void *trace_get_ip_from_80211(void *link, int *skipped)
51{
52        libtrace_80211_t *wifi = link;
53        struct ieee_802_11_payload *eth;
54
55        if (*skipped) skipped+=sizeof(libtrace_80211_t);
56
57        if (!wifi) {
58                return NULL;
59        }
60
61        /* Data packet? */
62        if (wifi->type != 2) {
63                return NULL;
64        }
65
66        if (skipped) *skipped+=sizeof(*eth);
67        eth=(void*)((char*)wifi+sizeof(libtrace_80211_t));
68
69        if (ntohs(eth->type) == 0x0800) {
70                return (void*)((char*)eth + sizeof(*eth));
71        } else if (ntohs(eth->type) == 0x8100) {
72                struct libtrace_8021q *vlanhdr = (struct libtrace_8021q *)eth;
73                if (ntohs(vlanhdr->vlan_ether_type) == 0x0800) {
74                        if (skipped) *skipped+=sizeof(*vlanhdr);
75                        return (void*)((char*)eth + sizeof(*vlanhdr));
76                }
77        }
78
79        return NULL;
80}
81
82static void *trace_get_ip6_from_80211(void *link, int *skipped)
83{
84        libtrace_80211_t *wifi = link;
85        struct ieee_802_11_payload *eth;
86
87        if (*skipped) skipped+=sizeof(libtrace_80211_t);
88
89        if (!wifi) {
90                return NULL;
91        }
92
93        /* Data packet? */
94        if (wifi->type != 2) {
95                return NULL;
96        }
97
98        if (skipped) *skipped+=sizeof(*eth);
99        eth=(void*)((char*)wifi+sizeof(libtrace_80211_t));
100
101        if (ntohs(eth->type) == 0x86DD) {
102                return (void*)((char*)eth + sizeof(*eth));
103        } else if (ntohs(eth->type) == 0x8100) {
104                struct libtrace_8021q *vlanhdr = (struct libtrace_8021q *)eth;
105                if (ntohs(vlanhdr->vlan_ether_type) == 0x86DD) {
106                        if (skipped) *skipped+=sizeof(*vlanhdr);
107                        return (void*)((char*)eth + sizeof(*vlanhdr));
108                }
109        }
110
111        return NULL;
112}
113
114/* TODO: split these cases into get_*_from_* functions */
115struct libtrace_ip *trace_get_ip(const struct libtrace_packet_t *packet) {
116        struct libtrace_ip *ipptr = 0;
117
118        switch(trace_get_link_type(packet)) {
119                case TRACE_TYPE_80211_PRISM:
120                        ipptr = trace_get_ip_from_80211(
121                                        (char*)trace_get_link(packet)+144,
122                                        NULL);
123                        break;
124                case TRACE_TYPE_80211:
125                        ipptr = trace_get_ip_from_80211(
126                                        trace_get_link(packet),
127                                        NULL);
128                        break;
129                case TRACE_TYPE_ETH:
130                case TRACE_TYPE_LEGACY_ETH:
131                        ipptr = trace_get_ip_from_ethernet(
132                                        trace_get_link(packet),
133                                        NULL);
134                        break;
135                case TRACE_TYPE_NONE:
136                        ipptr = trace_get_link(packet);
137                        break;
138                case TRACE_TYPE_LINUX_SLL:
139                        {
140                                struct trace_sll_header_t *sll;
141
142                                sll = trace_get_link(packet);
143                                if (!sll) {
144                                        ipptr = NULL;
145                                } else if (ntohs(sll->protocol)!=0x0800) {
146                                        ipptr = NULL;
147                                }
148                                else {
149                                        ipptr=(void*)((char*)sll+sizeof(*sll));
150                                }
151                        }
152                        break;
153                case TRACE_TYPE_PFLOG:
154                        {
155                                struct trace_pflog_header_t *pflog;
156                                pflog = trace_get_link(packet);
157                                if (!pflog) {
158                                        ipptr = NULL;
159                                        break;
160                                }
161                                if (pflog->af != AF_INET6) {
162                                        ipptr = NULL;
163                                } else {
164                                        ipptr = (void*)((char*)pflog+
165                                                sizeof(*pflog));
166                                }
167                        }
168                        break;
169                case TRACE_TYPE_LEGACY_POS:
170                        {
171                                /* 64 byte capture. */
172                                struct libtrace_pos *pos = 
173                                        trace_get_link(packet);
174                                if (ntohs(pos->ether_type) == 0x0800) {
175                                        ipptr=(void*)((char *)pos+sizeof(*pos));
176                                } else {
177                                        ipptr=NULL;
178                                }
179                                break;
180                               
181                        }
182                case TRACE_TYPE_LEGACY_ATM:
183                case TRACE_TYPE_ATM:
184                        {
185                                /* 64 byte capture. */
186                                struct libtrace_llcsnap *llc = 
187                                        trace_get_link(packet);
188
189                                /* advance the llc ptr +4 into the link layer.
190                                 * need to check what is in these 4 bytes.
191                                 * don't have time!
192                                 */
193                                llc = (void*)((char *)llc + 4);
194                                if (ntohs(llc->type) == 0x0800) {
195                                        ipptr=(void*)((char*)llc+sizeof(*llc));
196                                } else {
197                                        ipptr = NULL;
198                                }
199                                break;
200                        }
201                default:
202                        fprintf(stderr,"Don't understand link layer type %i in trace_get_ip6()\n",
203                                trace_get_link_type(packet));
204                        ipptr=NULL;
205                        break;
206        }
207
208        return ipptr;
209}
210
211/* TODO: split these cases into get_*_from_* functions */
212struct libtrace_ip6 *trace_get_ip6(const struct libtrace_packet_t *packet) {
213        libtrace_ip6_t *ipptr = 0;
214
215        switch(trace_get_link_type(packet)) {
216                case TRACE_TYPE_80211_PRISM:
217                        {
218                                ipptr = trace_get_ip6_from_80211(
219                                        (char*)trace_get_link(packet)+144, NULL);
220                        }
221                        break;
222                case TRACE_TYPE_80211:
223                        ipptr = trace_get_ip6_from_80211(
224                                        trace_get_link(packet),
225                                        NULL);
226                        break;
227                case TRACE_TYPE_ETH:
228                case TRACE_TYPE_LEGACY_ETH:
229                        {
230                                ipptr = trace_get_ip6_from_ethernet(
231                                                trace_get_link(packet),
232                                                NULL);
233                                break;
234                        }
235                case TRACE_TYPE_NONE:
236                        ipptr = trace_get_link(packet);
237                        break;
238                case TRACE_TYPE_LINUX_SLL:
239                        {
240                                trace_sll_header_t *sll;
241
242                                sll = trace_get_link(packet);
243                                if (!sll) {
244                                        ipptr = NULL;
245                                } else if (ntohs(sll->protocol)!=0x86DD) {
246                                        ipptr = NULL;
247                                }
248                                else {
249                                        ipptr = (void*)((char*)sll+
250                                                        sizeof(*sll));
251                                }
252                        }
253                        break;
254                case TRACE_TYPE_PFLOG:
255                        {
256                                struct trace_pflog_header_t *pflog;
257                                pflog = trace_get_link(packet);
258                                if (!pflog) {
259                                        ipptr = NULL;
260                                        break;
261                                }
262                                if (pflog->af != AF_INET) {
263                                        ipptr = NULL;
264                                } else {
265                                        ipptr = (void*)((char*)pflog+
266                                                sizeof(*pflog));
267                                }
268                        }
269                        break;
270                case TRACE_TYPE_LEGACY_POS:
271                        {
272                                /* 64 byte capture. */
273                                struct libtrace_pos *pos = 
274                                        trace_get_link(packet);
275                                if (ntohs(pos->ether_type) == 0x86DD) {
276                                        ipptr=(void*)((char *)pos+sizeof(*pos));
277                                } else {
278                                        ipptr=NULL;
279                                }
280                                break;
281                               
282                        }
283                case TRACE_TYPE_LEGACY_ATM:
284                case TRACE_TYPE_ATM:
285                        {
286                                /* 64 byte capture. */
287                                struct libtrace_llcsnap *llc = 
288                                        trace_get_link(packet);
289
290                                /* advance the llc ptr +4 into the link layer.
291                                 * need to check what is in these 4 bytes.
292                                 * don't have time!
293                                 */
294                                llc = (void*)((char *)llc + 4);
295                                if (ntohs(llc->type) == 0x86DD) {
296                                        ipptr=(void*)((char*)llc+sizeof(*llc));
297                                } else {
298                                        ipptr = NULL;
299                                }
300                                break;
301                        }
302                default:
303                        fprintf(stderr,"Don't understand link layer type %i in trace_get_ip()\n",
304                                trace_get_link_type(packet));
305                        ipptr=NULL;
306                        break;
307        }
308
309        return ipptr;
310}
311
312#define SW_IP_OFFMASK 0xff1f
313
314void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
315                int *skipped) 
316{
317        void *trans_ptr = 0;
318
319        if ((ipptr->ip_off & SW_IP_OFFMASK) == 0) {
320                if (skipped) *skipped=(ipptr->ip_hl * 4);
321                trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
322                if (prot) *prot = ipptr->ip_p;
323        }
324        return trans_ptr;
325}
326
327void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
328                int *skipped) 
329{
330        void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
331        uint8_t nxt = ipptr->nxt;
332
333        if (skipped) skipped+=sizeof(libtrace_ip6_t);
334
335        while(1) {
336                switch (nxt) {
337                        case 0: /* hop by hop options */
338                        case 43: /* routing */
339                        case 44: /* fragment */
340                        case 50: /* ESP */
341                        case 51: /* AH */
342                        case 60: /* Destination options */
343                                {
344                                        uint16_t len=((libtrace_ip6_ext_t*)payload)->len
345                                        +sizeof(libtrace_ip6_ext_t);
346
347                                        if (skipped)
348                                                *skipped+=len;
349
350                                        payload=(char*)payload+len;
351                                        nxt=((libtrace_ip6_ext_t*)payload)->nxt;
352                                        continue;
353                                }
354                        default:
355                                if (prot) *prot=nxt;
356                                return payload;
357                }
358        }
359}
360
361static void *trace_get_ip4_transport(const libtrace_packet_t *packet,
362                uint8_t *proto) 
363{
364        libtrace_ip_t *ipptr = 0;
365
366        if (!(ipptr = trace_get_ip(packet))) {
367                return 0;
368        }
369
370        return trace_get_payload_from_ip(ipptr,proto,NULL);
371}
372
373static void *trace_get_ip6_transport(const libtrace_packet_t *packet,
374                uint8_t *proto) 
375{
376        libtrace_ip6_t *ipptr = 0;
377
378        if (!(ipptr = trace_get_ip6(packet))) {
379                return 0;
380        }
381
382        return trace_get_payload_from_ip6(ipptr,proto,NULL);
383}
384
385void *trace_get_transport(const struct libtrace_packet_t *packet, 
386                uint8_t *proto) 
387{
388        void *transport;
389        uint8_t dummy;
390
391        if (!proto) proto=&dummy;
392
393        transport=trace_get_ip4_transport(packet,proto);
394        if (transport) {
395                if (*proto == 41) {
396                        trace_get_payload_from_ip6(transport,proto,NULL);
397                }
398                return transport;
399        }
400
401        return trace_get_ip6_transport(packet,proto);
402}
403
404libtrace_tcp_t *trace_get_tcp(const libtrace_packet_t *packet) {
405        uint8_t proto;
406        libtrace_tcp_t *tcp;
407
408        tcp=trace_get_transport(packet,&proto);
409
410        if (proto != 6)
411                return NULL;
412
413        return tcp;
414}
415
416libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, int *skipped)
417{
418        struct libtrace_tcp *tcpptr = 0;
419
420        if (ip->ip_p == 6)  {
421                tcpptr = (struct libtrace_tcp *)
422                        trace_get_payload_from_ip(ip, NULL, skipped);
423        }
424
425        return tcpptr;
426}
427
428libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
429        uint8_t proto;
430        libtrace_udp_t *udp;
431
432        udp=trace_get_transport(packet,&proto);
433
434        if (proto != 17)
435                return NULL;
436
437        return udp;
438}
439
440libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, int *skipped)
441{
442        struct libtrace_udp *udpptr = 0;
443
444        if (ip->ip_p == 17) {
445                udpptr = (libtrace_udp_t *)
446                        trace_get_payload_from_ip(ip, NULL, skipped);
447        }
448
449        return udpptr;
450}
451
452libtrace_icmp_t *trace_get_icmp(const libtrace_packet_t *packet) {
453        uint8_t proto;
454        libtrace_icmp_t *icmp;
455
456        icmp=trace_get_transport(packet,&proto);
457
458        if (proto != 1)
459                return NULL;
460
461        return icmp;
462}
463
464libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, int *skipped)
465{
466        libtrace_icmp_t *icmpptr = 0;
467
468        if (ip->ip_p == 1)  {
469                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, NULL, skipped);
470        }
471
472        return icmpptr;
473}
474
475void *trace_get_payload_from_udp(libtrace_udp_t *udp, int *skipped)
476{
477        if (skipped) *skipped+=sizeof(libtrace_udp_t);
478        return (void*)((char*)udp+sizeof(libtrace_udp_t));
479}
480
481void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, int *skipped)
482{
483        int dlen = tcp->doff*4;
484        if (skipped) *skipped=dlen;
485        return tcp+dlen;
486}
487
488void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, int *skipped)
489{
490        if (skipped) *skipped = sizeof(libtrace_icmp_t);
491        return (char*)icmp+sizeof(libtrace_icmp_t);
492}
493
Note: See TracBrowser for help on using the repository browser.