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