source: lib/protocols.c @ 4af54d1

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

Split protocol decode logic into a seperate file, cleaned up some of the
protocol decode logic. Started IPv6 support, added some
trace_get_payload_from_* helper functions

  • Property mode set to 100644
File size: 9.7 KB
Line 
1#include "libtrace.h"
2#include "libtrace_int.h"
3#include "wag.h"
4
5/* This file has the various helper functions used to decode various protocols */
6
7static void *trace_get_ip_from_ethernet(void *ethernet, int *skipped)
8{
9        libtrace_ether_t *eth = ethernet;
10       
11        if (ntohs(eth->ether_type)==0x0800) {
12                if (skipped)
13                        *skipped=sizeof(libtrace_ether_t);
14                return (void*)((char *)eth + sizeof(*eth));
15        } else if (ntohs(eth->ether_type) == 0x8100) {
16                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)eth;
17                if (skipped)
18                        *skipped=sizeof(libtrace_ether_t);
19                if (ntohs(vlanhdr->vlan_ether_type) == 0x0800) {
20                        return (void*)((char *)eth + sizeof(*vlanhdr));
21                }
22        }
23       
24        return NULL;
25}
26
27static void *trace_get_ip6_from_ethernet(void *ethernet, int *skipped)
28{
29        libtrace_ether_t *eth = ethernet;
30       
31        if (ntohs(eth->ether_type)==0x86DD) {
32                if (skipped)
33                        *skipped=sizeof(libtrace_ether_t);
34                return (void*)((char *)eth + sizeof(*eth));
35        } else if (ntohs(eth->ether_type) == 0x8100) {
36                libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)eth;
37                if (skipped)
38                        *skipped=sizeof(libtrace_ether_t);
39                if (ntohs(vlanhdr->vlan_ether_type) == 0x86DD) {
40                        return (void*)((char *)eth + sizeof(*vlanhdr));
41                }
42        }
43       
44        return NULL;
45}
46
47static void *trace_get_ip_from_80211(void *link, int *skipped)
48{
49        libtrace_80211_t *wifi = link;
50        struct ieee_802_11_payload *eth;
51
52        if (*skipped) skipped+=sizeof(libtrace_80211_t);
53
54        if (!wifi) {
55                return NULL;
56        }
57
58        /* Data packet? */
59        if (wifi->type != 2) {
60                return NULL;
61        }
62
63        if (skipped) *skipped+=sizeof(*eth);
64        eth=(void*)((char*)wifi+sizeof(libtrace_80211_t));
65
66        if (ntohs(eth->type) == 0x0800) {
67                return (void*)((char*)eth + sizeof(*eth));
68        } else if (ntohs(eth->type) == 0x8100) {
69                struct libtrace_8021q *vlanhdr = (struct libtrace_8021q *)eth;
70                if (ntohs(vlanhdr->vlan_ether_type) == 0x0800) {
71                        if (skipped) *skipped+=sizeof(*vlanhdr);
72                        return (void*)((char*)eth + sizeof(*vlanhdr));
73                }
74        }
75
76        return NULL;
77}
78
79static void *trace_get_ip6_from_80211(void *link, int *skipped)
80{
81        libtrace_80211_t *wifi = link;
82        struct ieee_802_11_payload *eth;
83
84        if (*skipped) skipped+=sizeof(libtrace_80211_t);
85
86        if (!wifi) {
87                return NULL;
88        }
89
90        /* Data packet? */
91        if (wifi->type != 2) {
92                return NULL;
93        }
94
95        if (skipped) *skipped+=sizeof(*eth);
96        eth=(void*)((char*)wifi+sizeof(libtrace_80211_t));
97
98        if (ntohs(eth->type) == 0x86DD) {
99                return (void*)((char*)eth + sizeof(*eth));
100        } else if (ntohs(eth->type) == 0x8100) {
101                struct libtrace_8021q *vlanhdr = (struct libtrace_8021q *)eth;
102                if (ntohs(vlanhdr->vlan_ether_type) == 0x86DD) {
103                        if (skipped) *skipped+=sizeof(*vlanhdr);
104                        return (void*)((char*)eth + sizeof(*vlanhdr));
105                }
106        }
107
108        return NULL;
109}
110
111/* TODO: split these cases into get_*_from_* functions */
112struct libtrace_ip *trace_get_ip(const struct libtrace_packet_t *packet) {
113        struct libtrace_ip *ipptr = 0;
114
115        switch(trace_get_link_type(packet)) {
116                case TRACE_TYPE_80211_PRISM:
117                        ipptr = trace_get_ip_from_80211(
118                                        (char*)trace_get_link(packet)+144,
119                                        NULL);
120                        break;
121                case TRACE_TYPE_80211:
122                        ipptr = trace_get_ip_from_80211(
123                                        trace_get_link(packet),
124                                        NULL);
125                        break;
126                case TRACE_TYPE_ETH:
127                case TRACE_TYPE_LEGACY_ETH:
128                        ipptr = trace_get_ip_from_ethernet(
129                                        trace_get_link(packet),
130                                        NULL);
131                        break;
132                case TRACE_TYPE_NONE:
133                        ipptr = trace_get_link(packet);
134                        break;
135                case TRACE_TYPE_LINUX_SLL:
136                        {
137                                struct trace_sll_header_t *sll;
138
139                                sll = trace_get_link(packet);
140                                if (!sll) {
141                                        ipptr = NULL;
142                                        break;
143                                }
144                                if (ntohs(sll->protocol)!=0x86DD) {
145                                        ipptr = NULL;
146                                }
147                                else {
148                                        ipptr = (void*)((char*)sll+
149                                                        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) == 0x86DD) {
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) == 0x86DD) {
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                                        break;
246                                }
247                                if (ntohs(sll->protocol)!=0x0800) {
248                                        ipptr = NULL;
249                                }
250                                else {
251                                        ipptr = (void*)((char*)sll+
252                                                        sizeof(*sll));
253                                }
254                        }
255                        break;
256                case TRACE_TYPE_PFLOG:
257                        {
258                                struct trace_pflog_header_t *pflog;
259                                pflog = trace_get_link(packet);
260                                if (!pflog) {
261                                        ipptr = NULL;
262                                        break;
263                                }
264                                if (pflog->af != AF_INET) {
265                                        ipptr = NULL;
266                                } else {
267                                        ipptr = (void*)((char*)pflog+
268                                                sizeof(*pflog));
269                                }
270                        }
271                        break;
272                case TRACE_TYPE_LEGACY_POS:
273                        {
274                                /* 64 byte capture. */
275                                struct libtrace_pos *pos = 
276                                        trace_get_link(packet);
277                                if (ntohs(pos->ether_type) == 0x0800) {
278                                        ipptr=(void*)((char *)pos+sizeof(*pos));
279                                } else {
280                                        ipptr=NULL;
281                                }
282                                break;
283                               
284                        }
285                case TRACE_TYPE_LEGACY_ATM:
286                case TRACE_TYPE_ATM:
287                        {
288                                /* 64 byte capture. */
289                                struct libtrace_llcsnap *llc = 
290                                        trace_get_link(packet);
291
292                                /* advance the llc ptr +4 into the link layer.
293                                 * need to check what is in these 4 bytes.
294                                 * don't have time!
295                                 */
296                                llc = (void*)((char *)llc + 4);
297                                if (ntohs(llc->type) == 0x0800) {
298                                        ipptr=(void*)((char*)llc+sizeof(*llc));
299                                } else {
300                                        ipptr = NULL;
301                                }
302                                break;
303                        }
304                default:
305                        fprintf(stderr,"Don't understand link layer type %i in trace_get_ip()\n",
306                                trace_get_link_type(packet));
307                        ipptr=NULL;
308                        break;
309        }
310
311        return ipptr;
312}
313
314#define SW_IP_OFFMASK 0xff1f
315
316void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, int *skipped) 
317{
318        void *trans_ptr = 0;
319
320        if ((ipptr->ip_off & SW_IP_OFFMASK) == 0) {
321                if (skipped) *skipped=(ipptr->ip_hl * 4);
322                trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
323        }
324        return trans_ptr;
325}
326
327void *trace_get_transport(const struct libtrace_packet_t *packet) 
328{
329        struct libtrace_ip *ipptr = 0;
330
331        if (!(ipptr = trace_get_ip(packet))) {
332                return 0;
333        }
334
335        return trace_get_payload_from_ip(ipptr,NULL);
336}
337
338libtrace_tcp_t *trace_get_tcp(const libtrace_packet_t *packet) {
339        struct libtrace_tcp *tcpptr = 0;
340        struct libtrace_ip *ipptr = 0;
341
342        if(!(ipptr = trace_get_ip(packet))) {
343                return 0;
344        }
345        if (ipptr->ip_p == 6) {
346                tcpptr = (struct libtrace_tcp *)trace_get_payload_from_ip(ipptr, 0);
347        }
348        return tcpptr;
349}
350
351libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, int *skipped)
352{
353        struct libtrace_tcp *tcpptr = 0;
354
355        if (ip->ip_p == 6)  {
356                tcpptr = (struct libtrace_tcp *)trace_get_payload_from_ip(ip, skipped);
357        }
358
359        return tcpptr;
360}
361
362libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
363        struct libtrace_udp *udpptr = 0;
364        struct libtrace_ip *ipptr = 0;
365       
366        if(!(ipptr = trace_get_ip(packet))) {
367                return 0;
368        }
369        if (ipptr->ip_p == 17)  {
370                udpptr = (struct libtrace_udp *)trace_get_payload_from_ip(ipptr, 0);
371        }
372
373        return udpptr;
374}
375
376libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, int *skipped)
377{
378        struct libtrace_udp *udpptr = 0;
379
380        if (ip->ip_p == 17) {
381                udpptr = (libtrace_udp_t *)trace_get_payload_from_ip(ip, skipped);
382        }
383
384        return udpptr;
385}
386
387libtrace_icmp_t *trace_get_icmp(const libtrace_packet_t *packet) {
388        struct libtrace_icmp *icmpptr = 0;
389        struct libtrace_ip *ipptr = 0;
390       
391        if(!(ipptr = trace_get_ip(packet))) {
392                return 0;
393        }
394        if (ipptr->ip_p == 1){
395                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ipptr, 0);
396        }
397        return icmpptr;
398}
399
400libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, int *skipped)
401{
402        libtrace_icmp_t *icmpptr = 0;
403
404        if (ip->ip_p == 1)  {
405                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, skipped);
406        }
407
408        return icmpptr;
409}
410
411void *trace_get_payload_from_udp(libtrace_udp_t *udp, int *skipped)
412{
413        if (skipped) *skipped+=sizeof(libtrace_udp_t);
414        return (void*)((char*)udp+sizeof(libtrace_udp_t));
415}
416
417void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, int *skipped)
418{
419        int dlen = tcp->doff*4;
420        if (skipped) *skipped=dlen;
421        return tcp+dlen;
422}
423
424void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, int *skipped)
425{
426        if (skipped) *skipped = sizeof(libtrace_icmp_t);
427        return (char*)icmp+sizeof(libtrace_icmp_t);
428}
429
Note: See TracBrowser for help on using the repository browser.