1 | /* Trivial libtrace program that prints the fields in the header for all |
---|
2 | * UDP packets in a trace. |
---|
3 | * |
---|
4 | * Designed to demonstrate the use of trace_get_transport() |
---|
5 | */ |
---|
6 | #include "libtrace.h" |
---|
7 | #include <stdio.h> |
---|
8 | #include <inttypes.h> |
---|
9 | #include <assert.h> |
---|
10 | #include <getopt.h> |
---|
11 | #include <arpa/inet.h> |
---|
12 | |
---|
13 | static void per_packet(libtrace_packet_t *packet) |
---|
14 | { |
---|
15 | uint8_t proto; |
---|
16 | uint32_t rem; |
---|
17 | void *transport = NULL; |
---|
18 | libtrace_udp_t *udp = NULL; |
---|
19 | |
---|
20 | /* OK, this is slightly tricky so pay attention. |
---|
21 | * |
---|
22 | * proto and rem are used as 'output' parameters here. What this |
---|
23 | * means is that their current values are ignored by the function |
---|
24 | * but they are updated to contain the protocol and amount of |
---|
25 | * payload remaining for the header that is being returned. |
---|
26 | * |
---|
27 | * We need to pass in the address of both these parameters, so |
---|
28 | * that they can be modified by the function. This is why there |
---|
29 | * is an '&' before both parameters. |
---|
30 | */ |
---|
31 | transport = trace_get_transport(packet, &proto, &rem); |
---|
32 | |
---|
33 | /* If there was no transport header, it can't be a UDP packet */ |
---|
34 | if (transport == NULL) |
---|
35 | return; |
---|
36 | |
---|
37 | /* Check if the protocol is UDP, using the defined value for UDP |
---|
38 | * that is defined in libtrace.h (search for libtrace_ipproto_t for |
---|
39 | * a full list) */ |
---|
40 | if (proto != TRACE_IPPROTO_UDP) |
---|
41 | return; |
---|
42 | |
---|
43 | /* One last check - make sure we have a full UDP header before |
---|
44 | * trying to grab fields out of it */ |
---|
45 | if (rem < sizeof(libtrace_udp_t)) |
---|
46 | return; |
---|
47 | |
---|
48 | /* Now, cast the returned header to the appropriate header type */ |
---|
49 | udp = (libtrace_udp_t *)transport; |
---|
50 | |
---|
51 | /* Dump each field to standard output. Be careful to byteswap any |
---|
52 | * fields that are larger than one byte, as these will be in network |
---|
53 | * byte order */ |
---|
54 | printf("UDP: source=%u dest=%u len=%u checksum=%u\n", |
---|
55 | ntohs(udp->source), ntohs(udp->dest), |
---|
56 | ntohs(udp->len), ntohs(udp->check)); |
---|
57 | } |
---|
58 | |
---|
59 | |
---|
60 | /* Due to the amount of error checking required in our main function, it |
---|
61 | * is a lot simpler and tidier to place all the calls to various libtrace |
---|
62 | * destroy functions into a separate function. |
---|
63 | */ |
---|
64 | static void libtrace_cleanup(libtrace_t *trace, libtrace_packet_t *packet) { |
---|
65 | |
---|
66 | /* It's very important to ensure that we aren't trying to destroy |
---|
67 | * a NULL structure, so each of the destroy calls will only occur |
---|
68 | * if the structure exists */ |
---|
69 | if (trace) |
---|
70 | trace_destroy(trace); |
---|
71 | |
---|
72 | if (packet) |
---|
73 | trace_destroy_packet(packet); |
---|
74 | |
---|
75 | } |
---|
76 | |
---|
77 | int main(int argc, char *argv[]) |
---|
78 | { |
---|
79 | /* This is essentially the same main function from readdemo.c */ |
---|
80 | |
---|
81 | libtrace_t *trace = NULL; |
---|
82 | libtrace_packet_t *packet = NULL; |
---|
83 | |
---|
84 | /* Ensure we have at least one argument after the program name */ |
---|
85 | if (argc < 2) { |
---|
86 | fprintf(stderr, "Usage: %s inputURI\n", argv[0]); |
---|
87 | return 1; |
---|
88 | } |
---|
89 | |
---|
90 | packet = trace_create_packet(); |
---|
91 | |
---|
92 | if (packet == NULL) { |
---|
93 | perror("Creating libtrace packet"); |
---|
94 | libtrace_cleanup(trace, packet); |
---|
95 | return 1; |
---|
96 | } |
---|
97 | |
---|
98 | trace = trace_create(argv[1]); |
---|
99 | |
---|
100 | if (trace_is_err(trace)) { |
---|
101 | trace_perror(trace,"Opening trace file"); |
---|
102 | libtrace_cleanup(trace, packet); |
---|
103 | return 1; |
---|
104 | } |
---|
105 | |
---|
106 | if (trace_start(trace) == -1) { |
---|
107 | trace_perror(trace,"Starting trace"); |
---|
108 | libtrace_cleanup(trace, packet); |
---|
109 | return 1; |
---|
110 | } |
---|
111 | |
---|
112 | |
---|
113 | while (trace_read_packet(trace,packet)>0) { |
---|
114 | per_packet(packet); |
---|
115 | } |
---|
116 | |
---|
117 | |
---|
118 | if (trace_is_err(trace)) { |
---|
119 | trace_perror(trace,"Reading packets"); |
---|
120 | libtrace_cleanup(trace, packet); |
---|
121 | return 1; |
---|
122 | } |
---|
123 | |
---|
124 | libtrace_cleanup(trace, packet); |
---|
125 | return 0; |
---|
126 | } |
---|