source: lib/protocols_transport.c @ c2afda6

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c2afda6 was c2afda6, checked in by Shane Alcock <salcock@…>, 11 years ago
  • Adjusted the "shortcut" protocol access functions to return NULL if a full header (minus options) is not present.
  • Property mode set to 100644
File size: 5.0 KB
Line 
1#include "libtrace.h"
2#include "protocols.h"
3#include <assert.h>
4#include <stdlib.h>
5#include <stdio.h> // fprintf
6
7DLLEXPORT void *trace_get_transport(const libtrace_packet_t *packet, 
8                uint8_t *proto,
9                uint32_t *remaining
10                ) 
11{
12        uint8_t dummy_proto;
13        uint16_t ethertype;
14        uint32_t dummy_remaining;
15        void *transport;
16
17        if (!proto) proto=&dummy_proto;
18
19        if (!remaining) remaining=&dummy_remaining;
20
21        transport = trace_get_layer3(packet,&ethertype,remaining);
22
23        if (!transport || *remaining == 0)
24                return NULL;
25
26        switch (ethertype) {
27                case TRACE_ETHERTYPE_IP: /* IPv4 */
28                        transport=trace_get_payload_from_ip(
29                                (libtrace_ip_t*)transport, proto, remaining);
30                        /* IPv6 */
31                        if (transport && *proto == TRACE_IPPROTO_IPV6) {
32                                transport=trace_get_payload_from_ip6(
33                                 (libtrace_ip6_t*)transport, proto,remaining);
34                        }
35                        return transport;
36                case TRACE_ETHERTYPE_IPV6: /* IPv6 */
37                        return trace_get_payload_from_ip6(
38                                (libtrace_ip6_t*)transport, proto, remaining);
39                       
40        }
41
42        *proto=0;
43        return NULL;
44}
45
46DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
47        uint8_t proto;
48        uint32_t rem = 0;
49        libtrace_tcp_t *tcp;
50
51        tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,&rem);
52
53        if (!tcp || proto != TRACE_IPPROTO_TCP)
54                return NULL;
55
56        /* We should return NULL if there isn't a full TCP header, because the
57         * caller has no way of telling how much of a TCP header we have
58         * returned - use trace_get_transport() if you want to deal with
59         * partial headers
60         *
61         * NOTE: We're not going to insist that all the TCP options are present
62         * as well, because lots of traces are snapped after 20 bytes of TCP
63         * header and I don't really want to break libtrace programs that
64         * use this function to process those traces */
65
66        if (rem < sizeof(libtrace_tcp_t))
67                return NULL;
68
69        return (libtrace_tcp_t*)tcp;
70}
71
72DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
73{
74        libtrace_tcp_t *tcpptr = 0;
75
76        if (ip->ip_p == TRACE_IPPROTO_TCP)  {
77                tcpptr = (libtrace_tcp_t *)
78                        trace_get_payload_from_ip(ip, NULL, remaining);
79        }
80
81        return tcpptr;
82}
83
84DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
85        uint8_t proto;
86        uint32_t rem = 0;
87        libtrace_udp_t *udp;
88
89        udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,&rem);
90
91        if (!udp || proto != TRACE_IPPROTO_UDP)
92                return NULL;
93
94        /* Make sure we return a full UDP header as the caller has no way of
95         * telling how much of the packet is remaining */
96        if (rem < sizeof(libtrace_udp_t))
97                return NULL;
98
99        return udp;
100}
101
102DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
103{
104        libtrace_udp_t *udpptr = 0;
105
106        if (ip->ip_p == TRACE_IPPROTO_UDP) {
107                udpptr = (libtrace_udp_t *)
108                        trace_get_payload_from_ip(ip, NULL, remaining);
109        }
110
111        return udpptr;
112}
113
114DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
115        uint8_t proto;
116        uint32_t rem = 0;
117        libtrace_icmp_t *icmp;
118
119        icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,&rem);
120
121        if (!icmp || proto != TRACE_IPPROTO_ICMP)
122                return NULL;
123
124        /* Make sure we return a full ICMP header as the caller has no way of
125         * telling how much of the packet is remaining */
126        if (rem < sizeof(libtrace_icmp_t))
127                return NULL;
128
129        return icmp;
130}
131
132DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
133{
134        libtrace_icmp_t *icmpptr = 0;
135
136        if (ip->ip_p == TRACE_IPPROTO_ICMP)  {
137                icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
138                                NULL, remaining);
139        }
140
141        return icmpptr;
142}
143
144DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
145{
146        if (remaining) {
147                if (*remaining < sizeof(libtrace_udp_t)) {
148                        *remaining = 0;
149                        return NULL;
150                }
151                *remaining-=sizeof(libtrace_udp_t);
152        }
153        return (void*)((char*)udp+sizeof(libtrace_udp_t));
154}
155
156DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
157{
158        unsigned int dlen = tcp->doff*4;
159        if (remaining) {
160                if (*remaining < dlen) {
161                        *remaining = 0;
162                        return NULL;
163                }
164                *remaining-=dlen;
165        }
166        return (void *)((char *)tcp+dlen);
167}
168
169DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
170{
171        if (remaining) {
172                if (*remaining < sizeof(libtrace_icmp_t)) {
173                        *remaining = 0;
174                        return NULL;
175                }
176                *remaining-=sizeof(libtrace_icmp_t);
177        }
178        return (char*)icmp+sizeof(libtrace_icmp_t);
179}
180
181/* Return the client port
182 */
183DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
184{
185        uint32_t remaining;
186        const struct ports_t *port = 
187                (const struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
188                        NULL, &remaining);
189
190        /* snapped too early */
191        if (remaining<2)
192                return 0;
193
194        if (port)
195                return ntohs(port->src);
196        else
197                return 0;
198}
199
200/* Same as get_source_port except use the destination port */
201DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
202{
203        uint32_t remaining;
204        struct ports_t *port = 
205                (struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
206                        NULL, &remaining);
207        /* snapped to early */
208        if (remaining<4)
209                return 0;
210
211        if (port)
212                return ntohs(port->dst);
213        else
214                return 0;
215}
216
217
Note: See TracBrowser for help on using the repository browser.