1 /*
2 * warts2traceroute
3 *
4 * $Id: sc_warts2text.c,v 1.27 2020/03/17 07:32:17 mjl Exp $
5 *
6 * Matthew Luckie
7 * mjl@luckie.org.nz
8 *
9 * Copyright (C) 2005-2006 Matthew Luckie
10 * Copyright (C) 2006-2011 The University of Waikato
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, version 2.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 #include "internal.h"
31
32 #include "scamper_file.h"
33 #include "scamper_addr.h"
34 #include "scamper_list.h"
35 #include "trace/scamper_trace.h"
36 #include "ping/scamper_ping.h"
37 #include "tracelb/scamper_tracelb.h"
38 #include "dealias/scamper_dealias.h"
39 #include "tbit/scamper_tbit.h"
40 #include "sting/scamper_sting.h"
41 #include "mjl_splaytree.h"
42 #include "utils.h"
43
44 static splaytree_t *tree = NULL;
45 static char **files = NULL;
46 static int filec = 0;
47
48 typedef int (*wf_t)(scamper_file_t *, void *);
49 typedef void (*ff_t)(void *);
50 typedef scamper_addr_t *(*df_t)(void *);
51
52 typedef struct ip2descr
53 {
54 scamper_addr_t *addr;
55 char *descr;
56 } ip2descr_t;
57
58 typedef struct funcset
59 {
60 wf_t write;
61 ff_t datafree;
62 df_t dst;
63 } funcset_t;
64
ip2descr_cmp(const ip2descr_t * a,const ip2descr_t * b)65 static int ip2descr_cmp(const ip2descr_t *a, const ip2descr_t *b)
66 {
67 return scamper_addr_cmp(a->addr, b->addr);
68 }
69
70 /*
71 * ip2descr_line
72 *
73 * parse lines that look like the following:
74 * 1.2.3.4 "foo"
75 * 5.6.7.8 "bar"
76 */
ip2descr_line(char * line,void * param)77 static int ip2descr_line(char *line, void *param)
78 {
79 static int line_no = 1;
80 scamper_addr_t *addr = NULL;
81 ip2descr_t fm, *ip2descr = NULL;
82 char *ip = line, *descr = line, *tmp;
83
84 if(line[0] == '\0')
85 return 0;
86
87 while(*descr != '\0')
88 {
89 if(*descr == ' ' || *descr == '\t')
90 break;
91 descr++;
92 }
93 if(*descr == '\0')
94 {
95 fprintf(stderr, "premature end to line %d\n", line_no);
96 goto err;
97 }
98 *descr = '\0';
99 descr++;
100
101 while(*descr == ' ' || *descr == '\t')
102 descr++;
103
104 if(*descr != '"')
105 {
106 fprintf(stderr, "expected \" on line %d\n", line_no);
107 goto err;
108 }
109 descr++;
110
111 tmp = descr;
112 while(*tmp != '\0')
113 {
114 if(*tmp == '"')
115 break;
116 tmp++;
117 }
118 if(*tmp == '\0')
119 {
120 fprintf(stderr, "missing closing \" on line %d\n", line_no);
121 goto err;
122 }
123 *tmp = '\0';
124
125 if((addr = scamper_addr_resolve(AF_UNSPEC, ip)) == NULL)
126 {
127 fprintf(stderr, "invalid address '%s' on line %d\n", ip, line_no);
128 goto err;
129 }
130
131 fm.addr = addr;
132 if(splaytree_find(tree, &fm) != NULL)
133 {
134 fprintf(stderr, "duplicate definition for %s on line %d\n", ip, line_no);
135 goto err;
136 }
137
138 if((ip2descr = malloc_zero(sizeof(ip2descr_t))) == NULL)
139 {
140 fprintf(stderr, "could not malloc ip2descr\n");
141 goto err;
142 }
143 if((ip2descr->descr = strdup(descr)) == NULL)
144 {
145 fprintf(stderr, "could not dup descr on line %d\n", line_no);
146 goto err;
147 }
148 ip2descr->addr = addr; addr = NULL;
149
150 if(splaytree_insert(tree, ip2descr) == NULL)
151 {
152 fprintf(stderr, "could not add line %d\n", line_no);
153 goto err;
154 }
155
156 line_no++;
157 return 0;
158
159 err:
160 if(ip2descr != NULL)
161 {
162 if(ip2descr->addr != NULL) scamper_addr_free(ip2descr->addr);
163 if(ip2descr->descr != NULL) free(ip2descr->descr);
164 free(ip2descr);
165 }
166 if(addr != NULL) scamper_addr_free(addr);
167 return -1;
168 }
169
ip2descr_lookup(scamper_addr_t * addr)170 static char *ip2descr_lookup(scamper_addr_t *addr)
171 {
172 ip2descr_t fm, *ip2descr;
173 fm.addr = addr;
174 if((ip2descr = splaytree_find(tree, &fm)) == NULL)
175 return NULL;
176 return ip2descr->descr;
177 }
178
trace_dst(void * data)179 static scamper_addr_t *trace_dst(void *data)
180 {
181 return ((scamper_trace_t *)data)->dst;
182 }
183
ping_dst(void * data)184 static scamper_addr_t *ping_dst(void *data)
185 {
186 return ((scamper_ping_t *)data)->dst;
187 }
188
tracelb_dst(void * data)189 static scamper_addr_t *tracelb_dst(void *data)
190 {
191 return ((scamper_tracelb_t *)data)->dst;
192 }
193
tbit_dst(void * data)194 static scamper_addr_t *tbit_dst(void *data)
195 {
196 return ((scamper_tbit_t *)data)->dst;
197 }
198
sting_dst(void * data)199 static scamper_addr_t *sting_dst(void *data)
200 {
201 return ((scamper_sting_t *)data)->dst;
202 }
203
check_options(int argc,char * argv[])204 static int check_options(int argc, char *argv[])
205 {
206 char *opt_descr = NULL;
207 int i;
208
209 while((i = getopt(argc, argv, "d:")) != -1)
210 {
211 switch(i)
212 {
213 case 'd':
214 opt_descr = optarg;
215 break;
216
217 default:
218 return -1;
219 }
220 }
221
222 if(opt_descr != NULL)
223 {
224 if((tree = splaytree_alloc((splaytree_cmp_t)ip2descr_cmp)) == NULL)
225 return -1;
226 if(file_lines(opt_descr, ip2descr_line, NULL) != 0)
227 return -1;
228 }
229
230 filec = argc - optind;
231 if(filec > 0)
232 files = argv + optind;
233
234 return 0;
235 }
236
main(int argc,char * argv[])237 int main(int argc, char *argv[])
238 {
239 funcset_t funcs[] = {
240 {NULL, NULL, NULL},
241 {NULL, NULL, NULL}, /* list */
242 {NULL, NULL, NULL}, /* cycle start */
243 {NULL, NULL, NULL}, /* cycle def */
244 {NULL, NULL, NULL}, /* cycle stop */
245 {NULL, NULL, NULL}, /* addr */
246 {(wf_t)scamper_file_write_trace, (ff_t)scamper_trace_free, trace_dst},
247 {(wf_t)scamper_file_write_ping, (ff_t)scamper_ping_free, ping_dst},
248 {(wf_t)scamper_file_write_tracelb,(ff_t)scamper_tracelb_free, tracelb_dst},
249 {(wf_t)scamper_file_write_dealias,(ff_t)scamper_dealias_free, NULL},
250 {NULL, NULL, NULL}, /* neighbour discovery */
251 {(wf_t)scamper_file_write_tbit, (ff_t)scamper_tbit_free, tbit_dst},
252 {(wf_t)scamper_file_write_sting, (ff_t)scamper_sting_free, sting_dst},
253 {NULL, NULL, NULL}, /* sniff */
254 };
255 uint16_t types[] = {
256 SCAMPER_FILE_OBJ_TRACE,
257 SCAMPER_FILE_OBJ_PING,
258 SCAMPER_FILE_OBJ_TRACELB,
259 SCAMPER_FILE_OBJ_DEALIAS,
260 SCAMPER_FILE_OBJ_TBIT,
261 SCAMPER_FILE_OBJ_STING,
262 };
263 scamper_file_t *in, *out;
264 scamper_file_filter_t *filter;
265 scamper_addr_t *addr;
266 uint16_t type;
267 void *data;
268 char *descr;
269 int i;
270
271 if(check_options(argc, argv) != 0)
272 {
273 return -1;
274 }
275
276 if((out = scamper_file_openfd(STDOUT_FILENO, NULL, 'w', "text")) == NULL)
277 {
278 fprintf(stderr, "could not associate stdout\n");
279 return -1;
280 }
281
282 filter = scamper_file_filter_alloc(types, sizeof(types)/sizeof(uint16_t));
283 if(filter == NULL)
284 {
285 fprintf(stderr, "could not allocate filter\n");
286 return -1;
287 }
288
289 for(i=0; i<=filec; i++)
290 {
291 if(filec == 0)
292 {
293 if((in = scamper_file_openfd(STDIN_FILENO,"-",'r',"warts")) == NULL)
294 {
295 fprintf(stderr, "could not use stdin\n");
296 return -1;
297 }
298 }
299 else if(i < filec)
300 {
301 if((in = scamper_file_open(files[i], 'r', NULL)) == NULL)
302 {
303 fprintf(stderr, "could not open %s: %s\n",
304 files[i], strerror(errno));
305 return -1;
306 }
307 }
308 else break;
309
310 while(scamper_file_read(in, filter, &type, (void *)&data) == 0)
311 {
312 if(data == NULL) break; /* EOF */
313
314 assert(type < sizeof(funcs)/sizeof(funcset_t));
315 assert(funcs[type].write != NULL);
316
317 if(tree != NULL && funcs[type].dst != NULL &&
318 (addr = funcs[type].dst(data)) != NULL &&
319 (descr = ip2descr_lookup(addr)) != NULL)
320 {
321 printf("%s\n", descr);
322 }
323
324 funcs[type].write(out, data);
325 funcs[type].datafree(data);
326 }
327
328 scamper_file_close(in);
329 }
330
331 scamper_file_close(out);
332 return 0;
333 }
334