1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 2002-2012 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                 Glenn Fowler <gsf@research.att.com>                  *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * bgp cisco ipv6 method
23  *
24  * Glenn Fowler
25  * AT&T Research
26  */
27 
28 #include "bgplib.h"
29 
30 typedef struct Ciscov6state_s
31 {
32 	Bgproute_t		route;
33 	char*			line;
34 	unsigned char		prefix[IP6PREFIX];
35 } Ciscov6state_t;
36 
37 /*
38  * ciscov6 identf
39  */
40 
41 static int
ciscov6ident(Dssfile_t * file,void * buf,size_t n,Dssdisc_t * disc)42 ciscov6ident(Dssfile_t* file, void* buf, size_t n, Dssdisc_t* disc)
43 {
44 	register char*		s;
45 	register char*		e;
46 	register char*		f;
47 	register int		c;
48 	char*			v;
49 	int			m;
50 
51 	static const char*	magic[] = { "IPv6 Routing Table - ", "Codes: " };
52 
53 	m = 0;
54 	v = 0;
55 	s = (char*)buf;
56 	e = s + n;
57 	for (;;)
58 	{
59 		for (;;)
60 		{
61 			if (s >= e)
62 				return 0;
63 			c = *s++;
64 			if (!isspace(c))
65 				break;
66 		}
67 		f = s - 1;
68 		for (;;)
69 		{
70 			if (s >= e)
71 				return 0;
72 			if (*s++ == '\n')
73 				break;
74 		}
75 		if (!isascii(*f) && (s - f) > 256)
76 			return 0;
77 		v++;
78 		if (strneq(f, magic[m], strlen(magic[m])) && ++m >= elementsof(magic))
79 		{
80 			file->caller = v;
81 			break;
82 		}
83 	}
84 	return 1;
85 }
86 
87 /*
88  * ciscov6 openf
89  */
90 
91 static int
ciscov6open(Dssfile_t * file,Dssdisc_t * disc)92 ciscov6open(Dssfile_t* file, Dssdisc_t* disc)
93 {
94 	register char*			v = file->caller;
95 	register Ciscov6state_t*	state;
96 
97 	if (!(state = vmnewof(file->dss->vm, 0, Ciscov6state_t, 1, 0)))
98 	{
99 		if (disc->errorf)
100 			(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
101 		return -1;
102 	}
103 	file->data = state;
104 	if ((file->flags & (DSS_FILE_WRITE|DSS_FILE_APPEND)) == DSS_FILE_WRITE)
105 	{
106 		sfprintf(file->io, "Codes: C - Connected, L - Local, S - Static, R - RIP, B - BGP\n\
107        U - Per-user Static route\n\
108        I1 - ISIS L1, I2 - ISIS L2, IA - ISIS interarea\n\
109        O - OSPF intra, OI - OSPF inter, OE1 - OSPF ext 1, OE2 - OSPF ext 2\n");
110 	}
111 	while (v-- && sfgetr(file->io, '\n', 0));
112 	while ((state->line = sfgetr(file->io, '\n', 0)) && !isupper(*state->line));
113 	return 0;
114 }
115 
116 /*
117  * ciscov6 readf
118  */
119 
120 static int
ciscov6read(register Dssfile_t * file,Dssrecord_t * record,Dssdisc_t * disc)121 ciscov6read(register Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
122 {
123 	register Ciscov6state_t*	state = (Ciscov6state_t*)file->data;
124 	register Bgproute_t*		rp;
125 	register char*			s;
126 	int				o;
127 	int				p;
128 	char*				t;
129 
130 	rp = &state->route;
131 	while (s = state->line)
132 	{
133 		t = s;
134 		while (*s && *s != '\n' && *s != ' ' && *s != '\t')
135 			s++;
136 		switch (*t)
137 		{
138 		case 'B':
139 			rp->set = 0;
140 			rp->attr = BGP_valid;
141 			rp->type = BGP_TYPE_table_dump;
142 			rp->origin = BGP_ORIGIN_incomplete;
143 			o = 0;
144 			p = 0;
145 			for (;;)
146 			{
147 				while (*s == ' ' || *s == '\t')
148 					s++;
149 				if (*s && *s != '\n')
150 				{
151 					t = s;
152 					while (*s && *s != '\n' && *s != ' ' && *s != '\t')
153 						s++;
154 					while (*s == ' ' || *s == '\t')
155 						s++;
156 					switch (p)
157 					{
158 					case 0:
159 						if (!strtoip6(t, NiL, rp->prefixv6, rp->prefixv6 + IP6BITS))
160 							p = 1;
161 						break;
162 					case 1:
163 						if ((s - t) > 3 && t[0] == 'v' && t[1] == 'i' && t[2] == 'a')
164 							p = 2;
165 						break;
166 					case 2:
167 						if (!strtoip6(t, NiL, rp->hop.v6, NiL))
168 							p = 3;
169 						break;
170 					}
171 				}
172 				if ((!*s || *s == '\n') && (!(s = state->line = sfgetr(file->io, '\n', 0)) || *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n'))
173 					break;
174 			}
175 			if (p != 3)
176 				return 0;
177 			rp->set |= BGP_SET_prefixv6|BGP_SET_hopv6;
178 			break;
179 		default:
180 			while ((state->line = sfgetr(file->io, '\n', 0)) && !isupper(*state->line));
181 			continue;
182 		}
183 		memset(rp->data + o, 0, elementsof(rp->data) - o);
184 		record->data = rp;
185 		record->size = rp->size = (char*)(rp->data + o) - (char*)rp;
186 		return 1;
187 	}
188 	return 0;
189 }
190 
191 /*
192  * ciscov6 writef
193  */
194 
195 static int
ciscov6write(Dssfile_t * file,Dssrecord_t * record,Dssdisc_t * disc)196 ciscov6write(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
197 {
198 #if 0
199 	register Ciscov6state_t*	state = (Ciscov6state_t*)file->data;
200 	register Bgproute_t*	rp = (Bgproute_t*)record->data;
201 	register Sfio_t*	io = file->io;
202 	register int		i;
203 	register int		j;
204 	register int		k;
205 	Bgpasn_t*		ap;
206 	Bgpnum_t*		np;
207 
208 	if (rp->type == BGP_TYPE_announce)
209 		sfputc(io, '+');
210 	else if (rp->type == BGP_TYPE_withdraw)
211 		sfputc(io, '-');
212 	else if (rp->attr & BGP_valid)
213 		sfputc(io, '*');
214 	else if (rp->attr & BGP_rib_failure)
215 		sfputc(io, 'r');
216 	else
217 		sfputc(io, ' ');
218 	if (rp->attr & BGP_best)
219 		sfputc(io, '>');
220 	else if (rp->attr & BGP_history)
221 		sfputc(io, 'h');
222 	else
223 		sfputc(io, ' ');
224 	if (rp->attr & BGP_atomic)
225 		sfputc(io, 'a');
226 	else if (rp->attr & BGP_damped)
227 		sfputc(io, 'd');
228 	else if (rp->attr & BGP_internal)
229 		sfputc(io, 'i');
230 	else if (rp->attr & BGP_suppressed)
231 		sfputc(io, 's');
232 	else if (rp->attr & BGP_stale)
233 		sfputc(io, 'S');
234 	else
235 		sfputc(io, ' ');
236 	if (rp->addr == state->paddr && rp->bits == state->pbits)
237 		sfprintf(io, "                 ");
238 	else
239 	{
240 		state->paddr = rp->addr;
241 		state->pbits = rp->bits;
242 		if (sfprintf(io, "%-16s", fmtip4(rp->addr, rp->bits)) > 16)
243 			sfprintf(io, "\n                    ");
244 		else
245 			sfputc(io, ' ');
246 	}
247 	sfprintf(io, "%-19s ", fmtip4(rp->hop, -1));
248 	if (rp->med)
249 		sfprintf(io, "%6u ", rp->med);
250 	else
251 		sfprintf(io, "       ");
252 	if (rp->local)
253 		sfprintf(io, "%6u ", rp->local);
254 	else
255 		sfprintf(io, "       ");
256 	sfprintf(io, "%6u", rp->weight);
257 	if (j = rp->path.size)
258 	{
259 		ap = BGPPATH(rp);
260 		for (i = 0; i < j; i++)
261 			if (ap[i] == BGP_SET16)
262 			{
263 				if (k = ap[++i])
264 				{
265 					k += i - 1;
266 					sfprintf(io, " {%u", ap[++i]);
267 					while (i < k)
268 						sfprintf(io, ",%u", ap[++i]);
269 					sfputc(io, '}');
270 				}
271 				else
272 					sfprintf(io, " %u", ap[++i]);
273 			}
274 			else
275 				sfprintf(io, " %u", ap[i]);
276 	}
277 	if (rp->community.size)
278 	{
279 		sfputc(io, ' ');
280 		sfputc(io, 'C');
281 		ap = BGPCOMMUNITY(rp);
282 		for (i = 0, j = rp->community.size; i < j; i += 2)
283 			sfprintf(io, " %u:%u", ap[i], ap[i+1]);
284 	}
285 	if (rp->cluster.size)
286 	{
287 		sfputc(io, ' ');
288 		sfputc(io, 'I');
289 		np = BGPCLUSTER(rp);
290 		for (i = 0, j = rp->cluster.size; i < j; i++)
291 			sfprintf(io, " %lu", np[i]);
292 	}
293 	if (rp->time)
294 		sfprintf(io, " T %s", fmttime("%K", rp->time));
295 	if (rp->origin)
296 	{
297 		sfputc(io, ' ');
298 		sfputc(io, rp->origin);
299 	}
300 	if (sfputc(io, '\n') == EOF)
301 	{
302 		if (disc->errorf)
303 			(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: write error", file->format->name);
304 		return -1;
305 	}
306 #endif
307 	return 0;
308 }
309 
310 /*
311  * ciscov6 closef
312  */
313 
314 static int
ciscov6close(Dssfile_t * file,Dssdisc_t * disc)315 ciscov6close(Dssfile_t* file, Dssdisc_t* disc)
316 {
317 	if (!file->data)
318 		return -1;
319 	vmfree(file->dss->vm, file->data);
320 	return 0;
321 }
322 
323 Dssformat_t bgp_ciscov6_format =
324 {
325 	"ciscov6",
326 	"cisco ipv6 router dump format (2009-03-15)",
327 	CXH,
328 	ciscov6ident,
329 	ciscov6open,
330 	ciscov6read,
331 	ciscov6write,
332 	0,
333 	ciscov6close,
334 	0,
335 	0,
336 	bgp_ciscov6_next
337 };
338