1 /*
2  * Copyright (c) 2014, 2018 by Farsight Security, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 
25 #include <sys/uio.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 #include <fstrm.h>
30 
31 #include "libmy/print_string.h"
32 
33 static fstrm_res
process_start_frame(struct fstrm_reader * r,struct fstrm_writer_options * wopt)34 process_start_frame(struct fstrm_reader *r, struct fstrm_writer_options *wopt)
35 {
36 	fstrm_res res;
37 	const struct fstrm_control *control = NULL;
38 	size_t n_content_type = 0;
39 	const uint8_t *content_type = NULL;
40 	size_t len_content_type = 0;
41 
42 	res = fstrm_reader_get_control(r, FSTRM_CONTROL_START, &control);
43 	if (res != fstrm_res_success)
44 		return res;
45 	fputs("FSTRM_CONTROL_START.\n", stderr);
46 
47 	res = fstrm_control_get_num_field_content_type(control, &n_content_type);
48 	if (res != fstrm_res_success)
49 		return res;
50 	if (n_content_type > 0) {
51 		res = fstrm_control_get_field_content_type(control, 0,
52 			&content_type, &len_content_type);
53 		if (res != fstrm_res_success)
54 			return res;
55 		fprintf(stderr, "FSTRM_CONTROL_FIELD_CONTENT_TYPE (%zd bytes).\n ",
56 			len_content_type);
57 		print_string(content_type, len_content_type, stderr);
58 		fputc('\n', stderr);
59 	}
60 
61 	if (wopt != NULL && content_type != NULL) {
62 		res = fstrm_writer_options_add_content_type(wopt,
63 			content_type, len_content_type);
64 		if (res != fstrm_res_success)
65 			return res;
66 	}
67 
68 	return fstrm_res_success;
69 }
70 
71 static fstrm_res
print_stop_frame(struct fstrm_reader * r)72 print_stop_frame(struct fstrm_reader *r)
73 {
74 	fstrm_res res;
75 	const struct fstrm_control *control = NULL;
76 
77 	res = fstrm_reader_get_control(r, FSTRM_CONTROL_STOP, &control);
78 	if (res != fstrm_res_success)
79 		return res;
80 	fputs("FSTRM_CONTROL_STOP.\n", stderr);
81 
82 	return fstrm_res_success;
83 }
84 
85 static fstrm_res
print_data_frame(const uint8_t * data,size_t len_data)86 print_data_frame(const uint8_t *data, size_t len_data)
87 {
88 	fprintf(stderr, "Data frame (%zd) bytes.\n", len_data);
89 	putchar(' ');
90 	print_string(data, len_data, stdout);
91 	putchar('\n');
92 	return fstrm_res_success;
93 }
94 
main(int argc,char ** argv)95 int main(int argc, char **argv)
96 {
97 	const char *input_fname = NULL;
98 	const char *output_fname = NULL;
99 
100 	fstrm_res res = fstrm_res_failure;
101 	struct fstrm_file_options *fopt = NULL;
102 	struct fstrm_writer_options *wopt = NULL;
103 	struct fstrm_reader *r = NULL;
104 	struct fstrm_writer *w = NULL;
105 
106 	int rv = EXIT_FAILURE;
107 
108 	/* Args. */
109 	if (argc != 2 && argc != 3) {
110 		fprintf(stderr, "Usage: %s <INPUT FILE> [<OUTPUT FILE>]\n", argv[0]);
111 		fprintf(stderr, "Dumps a Frame Streams formatted input file.\n\n");
112 		return EXIT_FAILURE;
113 	}
114 	input_fname = argv[1];
115 	if (argc == 3)
116 		output_fname = argv[2];
117 
118 	/* Line buffering. */
119 	setvbuf(stdout, NULL, _IOLBF, 0);
120 	setvbuf(stderr, NULL, _IOLBF, 0);
121 
122 	/* Setup file reader options. */
123 	fopt = fstrm_file_options_init();
124 	fstrm_file_options_set_file_path(fopt, input_fname);
125 
126 	/* Initialize file reader. */
127 	r = fstrm_file_reader_init(fopt, NULL);
128 	if (r == NULL) {
129 		fputs("Error: fstrm_file_reader_init() failed.\n", stderr);
130 		goto out;
131 	}
132 	res = fstrm_reader_open(r);
133 	if (res != fstrm_res_success) {
134 		fputs("Error: fstrm_reader_open() failed.\n", stderr);
135 		goto out;
136 	}
137 
138 	if (output_fname != NULL) {
139 		/* Setup file writer options. */
140 		fstrm_file_options_set_file_path(fopt, output_fname);
141 
142 		/* Setup writer options. */
143 		wopt = fstrm_writer_options_init();
144 
145 		/* Copy "content type" from the reader's START frame. */
146 		res = process_start_frame(r, wopt);
147 		if (res != fstrm_res_success) {
148 			fputs("Error: process_start_frame() failed.\n", stderr);
149 			goto out;
150 		}
151 
152 		/* Initialize file writer. */
153 		w = fstrm_file_writer_init(fopt, wopt);
154 		if (w == NULL) {
155 			fputs("Error: fstrm_file_writer_init() failed.\n", stderr);
156 			goto out;
157 		}
158 		res = fstrm_writer_open(w);
159 		if (res != fstrm_res_success) {
160 			fstrm_writer_destroy(&w);
161 			fputs("Error: fstrm_writer_open() failed.\n", stderr);
162 			goto out;
163 		}
164 	} else {
165 		/* Process the START frame. */
166 		res = process_start_frame(r, NULL);
167 		if (res != fstrm_res_success) {
168 			fprintf(stderr, "Error: process_start_frame() failed.\n");
169 			goto out;
170 		}
171 	}
172 
173 	/* Loop over data frames. */
174 	for (;;) {
175 		const uint8_t *data;
176 		size_t len_data;
177 
178 		res = fstrm_reader_read(r, &data, &len_data);
179 		if (res == fstrm_res_success) {
180 			/* Got a data frame. */
181 			res = print_data_frame(data, len_data);
182 			if (res != fstrm_res_success) {
183 				fprintf(stderr, "Error: print_data_frame() failed.\n");
184 				goto out;
185 			}
186 			if (w != NULL) {
187 				/* Write the data frame. */
188 				res = fstrm_writer_write(w, data, len_data);
189 				if (res != fstrm_res_success) {
190 					fprintf(stderr, "Error: write_data_frame() failed.\n");
191 					goto out;
192 				}
193 			}
194 		} else if (res == fstrm_res_stop) {
195 			/* Normal end of data stream. */
196 			res = print_stop_frame(r);
197 			if (res != fstrm_res_success) {
198 				fprintf(stderr, "Error: unable to read STOP frame.\n");
199 				goto out;
200 			}
201 			rv = EXIT_SUCCESS;
202 			break;
203 		} else {
204 			/* Abnormal end. */
205 			fprintf(stderr, "Error: fstrm_reader_read() failed.\n");
206 			goto out;
207 		}
208 	}
209 
210 out:
211 	/* Cleanup options. */
212 	fstrm_file_options_destroy(&fopt);
213 	fstrm_writer_options_destroy(&wopt);
214 
215 	/* Cleanup reader. */
216 	fstrm_reader_destroy(&r);
217 
218 	/* Cleanup writer. */
219 	if (w != NULL) {
220 		res = fstrm_writer_close(w);
221 		if (res != fstrm_res_success) {
222 			fprintf(stderr, "Error: fstrm_writer_close() failed.\n");
223 			rv = EXIT_FAILURE;
224 		}
225 		fstrm_writer_destroy(&w);
226 	}
227 
228 	return rv;
229 }
230