source: lib/protocols_transport.c @ f6730d8

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since f6730d8 was f6730d8, checked in by Shane Alcock <salcock@…>, 11 years ago
  • Updated licensing and documentation for the protocol decoders
  • Moved trace_get_source_mac and trace_get_destination_mac into protocols_l2.c which is much more appropriate
  • Re-wrote trace_get_destination_mac to match the behaviour of trace_get_source_mac, especially with regard to ignoring link types that match meta-data headers
  • Added TRACE_TYPE_NONDATA handlers to several switch statements
  • Property mode set to 100644
File size: 6.5 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#include "libtrace.h"
36#include "protocols.h"
37#include <assert.h>
38#include <stdlib.h>
39#include <stdio.h> // fprintf
40
41/* This file contains all the protocol decoding functions for transport layer
42 * protocols. This includes functions for access port numbers.
43 *
44 * Supported protocols include (but are not limited to):
45 *      TCP
46 *      UDP
47 *      ICMP
48 */
49
50DLLEXPORT void *trace_get_transport(const libtrace_packet_t *packet, 
51                uint8_t *proto,
52                uint32_t *remaining
53                ) 
54{
55        uint8_t dummy_proto;
56        uint16_t ethertype;
57        uint32_t dummy_remaining;
58        void *transport;
59
60        if (!proto) proto=&dummy_proto;
61
62        if (!remaining) remaining=&dummy_remaining;
63
64        transport = trace_get_layer3(packet,&ethertype,remaining);
65
66        if (!transport || *remaining == 0)
67                return NULL;
68
69        switch (ethertype) {
70                case TRACE_ETHERTYPE_IP: /* IPv4 */
71                        transport=trace_get_payload_from_ip(
72                                (libtrace_ip_t*)transport, proto, remaining);
73                        /* IPv6 */
74                        if (transport && *proto == TRACE_IPPROTO_IPV6) {
75                                transport=trace_get_payload_from_ip6(
76                                 (libtrace_ip6_t*)transport, proto,remaining);
77                        }
78                        return transport;
79                case TRACE_ETHERTYPE_IPV6: /* IPv6 */
80                        return trace_get_payload_from_ip6(
81                                (libtrace_ip6_t*)transport, proto, remaining);
82                       
83        }
84
85        *proto=0;
86        return NULL;
87}
88
89DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
90        uint8_t proto;
91        uint32_t rem = 0;
92        libtrace_tcp_t *tcp;
93
94        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,&rem);
95
96        if (!tcp || proto != TRACE_IPPROTO_TCP)
97                return NULL;
98
99        /* We should return NULL if there isn't a full TCP header, because the
100         * caller has no way of telling how much of a TCP header we have
101         * returned - use trace_get_transport() if you want to deal with
102         * partial headers
103         *
104         * NOTE: We're not going to insist that all the TCP options are present
105         * as well, because lots of traces are snapped after 20 bytes of TCP
106         * header and I don't really want to break libtrace programs that
107         * use this function to process those traces */
108
109        if (rem < sizeof(libtrace_tcp_t))
110                return NULL;
111
112        return (libtrace_tcp_t*)tcp;
113}
114
115DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
116{
117        libtrace_tcp_t *tcpptr = 0;
118
119        if (ip->ip_p == TRACE_IPPROTO_TCP)  {
120                tcpptr = (libtrace_tcp_t *)
121                        trace_get_payload_from_ip(ip, NULL, remaining);
122        }
123
124        return tcpptr;
125}
126
127DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
128        uint8_t proto;
129        uint32_t rem = 0;
130        libtrace_udp_t *udp;
131
132        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,&rem);
133
134        if (!udp || proto != TRACE_IPPROTO_UDP)
135                return NULL;
136
137        /* Make sure we return a full UDP header as the caller has no way of
138         * telling how much of the packet is remaining */
139        if (rem < sizeof(libtrace_udp_t))
140                return NULL;
141
142        return udp;
143}
144
145DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
146{
147        libtrace_udp_t *udpptr = 0;
148
149        if (ip->ip_p == TRACE_IPPROTO_UDP) {
150                udpptr = (libtrace_udp_t *)
151                        trace_get_payload_from_ip(ip, NULL, remaining);
152        }
153
154        return udpptr;
155}
156
157DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
158        uint8_t proto;
159        uint32_t rem = 0;
160        libtrace_icmp_t *icmp;
161
162        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,&rem);
163
164        if (!icmp || proto != TRACE_IPPROTO_ICMP)
165                return NULL;
166
167        /* Make sure we return a full ICMP header as the caller has no way of
168         * telling how much of the packet is remaining */
169        if (rem < sizeof(libtrace_icmp_t))
170                return NULL;
171
172        return icmp;
173}
174
175DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
176{
177        libtrace_icmp_t *icmpptr = 0;
178
179        if (ip->ip_p == TRACE_IPPROTO_ICMP)  {
180                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
181                                NULL, remaining);
182        }
183
184        return icmpptr;
185}
186
187DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
188{
189        if (remaining) {
190                if (*remaining < sizeof(libtrace_udp_t)) {
191                        *remaining = 0;
192                        return NULL;
193                }
194                *remaining-=sizeof(libtrace_udp_t);
195        }
196        return (void*)((char*)udp+sizeof(libtrace_udp_t));
197}
198
199DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
200{
201        unsigned int dlen = tcp->doff*4;
202        if (remaining) {
203                if (*remaining < dlen) {
204                        *remaining = 0;
205                        return NULL;
206                }
207                *remaining-=dlen;
208        }
209        return (void *)((char *)tcp+dlen);
210}
211
212DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
213{
214        if (remaining) {
215                if (*remaining < sizeof(libtrace_icmp_t)) {
216                        *remaining = 0;
217                        return NULL;
218                }
219                *remaining-=sizeof(libtrace_icmp_t);
220        }
221        return (char*)icmp+sizeof(libtrace_icmp_t);
222}
223
224/* Return the source port
225 */
226DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
227{
228        uint32_t remaining;
229        uint8_t proto;
230        const struct ports_t *port = 
231                (const struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
232                        &proto, &remaining);
233
234        /* Snapped too early */
235        if (remaining<2)
236                return 0;
237
238        /* ICMP *technically* doesn't have ports */
239        if (proto == TRACE_IPPROTO_ICMP)
240                return 0;
241
242        if (port)
243                return ntohs(port->src);
244        else
245                return 0;
246}
247
248/* Same as get_source_port except use the destination port */
249DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
250{
251        uint32_t remaining;
252        uint8_t proto;
253        struct ports_t *port = 
254                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
255                        &proto, &remaining);
256        /* Snapped too early */
257        if (remaining<4)
258                return 0;
259       
260        /* ICMP *technically* doesn't have ports */
261        if (proto == TRACE_IPPROTO_ICMP)
262                return 0;
263
264        if (port)
265                return ntohs(port->dst);
266        else
267                return 0;
268}
269
270
Note: See TracBrowser for help on using the repository browser.