File: configdemo.c

package info (click to toggle)
libtrace3 3.0.7-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 3,676 kB
  • ctags: 3,140
  • sloc: ansic: 20,551; sh: 10,125; cpp: 1,384; makefile: 415; yacc: 96; lex: 50
file content (162 lines) | stat: -rw-r--r-- 4,866 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
 /* Another implementation of tracefilter that demonstrates the use of the
  * configuration system for traces
 */
#include "libtrace.h"
#include <stdio.h>
#include <inttypes.h>
#include <assert.h>
#include <getopt.h>

static int per_packet(libtrace_out_t *output, libtrace_packet_t *packet)
{
	/* All packets that reach this function must have matched the filter
	 * so we can write them out immediately */
	if (trace_write_packet(output, packet) == -1) {
		trace_perror_output(output, "Writing packet");
		return -1;
	}

	return 0;
}

/* The cleanup function has now been extended to destroy the filter and 
 * output trace as well */
static void libtrace_cleanup(libtrace_t *trace, libtrace_out_t *output, 
		libtrace_packet_t *packet, libtrace_filter_t *filter) {

        /* It's very important to ensure that we aren't trying to destroy
         * a NULL structure, so each of the destroy calls will only occur
         * if the structure exists */
        if (trace)
                trace_destroy(trace);

	if (output)
		trace_destroy_output(output);

        if (packet)
                trace_destroy_packet(packet);

	if (filter)
		trace_destroy_filter(filter);

}

int main(int argc, char *argv[])
{
        /* Unlike most of the other example programs, this is not a copy and
	 * paste job from readdemo.c as we now also have to initalise and
	 * start an output trace too */

	/* On top of that, we now have to manage a filter as well */

        libtrace_t *trace = NULL;
        libtrace_packet_t *packet = NULL;
	libtrace_out_t *output = NULL;
	libtrace_filter_t *filter = NULL;

	int level = 6;

	/* Check that we have all the required command line arguments */
	if (argc < 4) {
		fprintf(stderr, "Usage: %s inputURI bpffilter outputURI\n", 
			argv[0]);
		return 1;
	}
	
	/* Creating the packet structure */
        packet = trace_create_packet();

        if (packet == NULL) {
                perror("Creating libtrace packet");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }

	/* Creating the filter */
	filter = trace_create_filter(argv[2]);
	if (filter == NULL) {
		fprintf(stderr, "Failed to create filter (%s)\n", argv[2]);
		libtrace_cleanup(trace, output, packet, filter);
		return 1;
	}
	
	/* Creating and starting the INPUT trace */
        trace = trace_create(argv[1]);

        if (trace_is_err(trace)) {
                trace_perror(trace,"Opening trace file");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }

	/* Use the configuration system to tell libtrace to always use this
	 * filter when reading packets. For live captures, this means the
	 * filter will be pushed into the kernel or hardware, improving
	 * the performance over a software filter.
	 *
	 * Note that the configuration is performed BEFORE calling 
	 * trace_start(). 
	 */

	if (trace_config(trace, TRACE_OPTION_FILTER, filter) == -1) {
		trace_perror(trace, "Configuring filter");
		libtrace_cleanup(trace, output, packet, filter);
		return 1;
	}

        if (trace_start(trace) == -1) {
                trace_perror(trace,"Starting trace");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }

	
	/* Creating and starting the OUTPUT trace */
        output = trace_create_output(argv[3]);

        if (trace_is_err_output(output)) {
                trace_perror_output(output,"Opening output trace file");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }

        /* We're also going to set a compression level option for the output
	 * trace to ensure that our traces are compressed sensibly.
	 *
	 * Again, this must be done before calling trace_start_output().
	 */
	
	if (trace_config_output(output, TRACE_OPTION_OUTPUT_COMPRESS, &level) == -1) {
		trace_perror_output(output, "Configuring compression level");
		libtrace_cleanup(trace, output, packet, filter);
		return 1;
	}

	if (trace_start_output(output) == -1) {
                trace_perror_output(output,"Starting output trace");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }
        
	while (trace_read_packet(trace,packet)>0) {
                
		/* If something goes wrong when writing packets, we need to
		 * catch that error, tidy up and exit */
		if (per_packet(output, packet) == -1) {
			libtrace_cleanup(trace, output, packet, filter);
			return 1;
		}
        }

	/* Checking for any errors that might have occurred while reading the
	 * input trace */
        if (trace_is_err(trace)) {
                trace_perror(trace,"Reading packets");
                libtrace_cleanup(trace, output, packet, filter);
                return 1;
        }

        libtrace_cleanup(trace, output, packet, filter);
        return 0;
}