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