Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/bgp/bgp-cisco.c
1810 views
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 <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* bgp cisco method
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "bgplib.h"
29
30
typedef struct Ciscostate_s
31
{
32
Bgproute_t route;
33
Bgpnum_t paddr;
34
Bgpnum_t pbits;
35
} Ciscostate_t;
36
37
/*
38
* cisco identf
39
*/
40
41
static int
42
ciscoident(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* t;
49
Bgpnum_t addr;
50
unsigned char bits;
51
52
s = (char*)buf;
53
e = s + n;
54
for (;;)
55
{
56
for (;;)
57
{
58
if (s >= e)
59
return 0;
60
c = *s++;
61
if (c == '<' && s < (e - 4) && s[0] == 'b' && s[1] == 'r' && s[2] == '>' && s[3] == ' ')
62
s += 4;
63
else if (!isspace(c))
64
break;
65
}
66
f = s - 1;
67
for (;;)
68
{
69
if (s >= e)
70
return 0;
71
if (*s++ == '\n')
72
break;
73
}
74
if (!isascii(*f) && (s - f) > 256)
75
return 0;
76
if (((c = *f++) == '*' || c == '-' || c == '+' || c == 'r' || c == ' ') &&
77
((c = *f++) == '>' || c == 'h' || c == ' ') &&
78
((c = *f++) == 'a' || c == 'd' || c == 'i' || c == 's' || c == ' ') &&
79
isdigit(*f) && !strtoip4(f, &t, &addr, &bits) && *t == ' ')
80
break;
81
}
82
return 1;
83
}
84
85
/*
86
* cisco openf
87
*/
88
89
static int
90
ciscoopen(Dssfile_t* file, Dssdisc_t* disc)
91
{
92
if (!(file->data = (void*)vmnewof(file->dss->vm, 0, Ciscostate_t, 1, 0)))
93
{
94
if (disc->errorf)
95
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
96
return -1;
97
}
98
if ((file->flags & (DSS_FILE_WRITE|DSS_FILE_APPEND)) == DSS_FILE_WRITE)
99
{
100
sfprintf(file->io, "Status codes: s suppressed, d damped, h history, * valid, > best, i internal, r rib-failure, S stale\n");
101
sfprintf(file->io, "Origin codes: i IGP, e EGP, ? incomplete\n");
102
sfprintf(file->io, " Network Next Hop Metric LocPrf Weight Path\n");
103
}
104
return 0;
105
}
106
107
/*
108
* cisco readf
109
*/
110
111
static int
112
ciscoread(register Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
113
{
114
register Ciscostate_t* state = (Ciscostate_t*)file->data;
115
register Bgproute_t* rp;
116
register char* s;
117
register int i;
118
int n;
119
int o;
120
char* e;
121
char* p;
122
Bgpasn_t* ap;
123
Bgp_t* bgp;
124
Cxoperand_t r;
125
126
rp = &state->route;
127
for (;;)
128
{
129
if (!(s = sfgetr(file->io, '\n', 0)))
130
return 0;
131
e = s + sfvalue(file->io);
132
if (s[0] == ' ' && s[1] == '<' && s[2] == 'b' && s[3] == 'r' && s[4] == '>' && s[5] == ' ')
133
s += 6;
134
n = e - s;
135
if (n > 20 && (s[0] == ' ' || s[0] == '*' || s[0] == '-' || s[0] == '+' || s[0] == 'r') && (s[3] >= '0' && s[3] <= '9' || n > 61 && s[3] == ' ' && s[20] >= '0' && s[20] <= '9'))
136
{
137
rp->attr = 0;
138
rp->type = BGP_TYPE_table_dump;
139
rp->origin = BGP_ORIGIN_incomplete;
140
for (i = 0; i < 3; i++)
141
switch (s[i])
142
{
143
case '>':
144
rp->attr |= BGP_best;
145
break;
146
case 'a':
147
rp->attr |= BGP_atomic;
148
break;
149
case 'd':
150
rp->attr |= BGP_damped;
151
break;
152
case 'h':
153
rp->attr |= BGP_history;
154
break;
155
case 'i':
156
rp->attr |= BGP_internal;
157
break;
158
case 'r':
159
rp->attr |= BGP_rib_failure;
160
break;
161
case 's':
162
rp->attr |= BGP_suppressed;
163
break;
164
case 'S':
165
rp->attr |= BGP_stale;
166
break;
167
case '*':
168
rp->attr |= BGP_valid;
169
break;
170
case '+':
171
rp->type = BGP_TYPE_announce;
172
break;
173
case '-':
174
rp->type = BGP_TYPE_withdraw;
175
break;
176
}
177
s += 3;
178
if (*s == ' ')
179
s += 17;
180
else if (strtoip4(s, &p, &rp->addr.v4, &rp->bits))
181
break;
182
else
183
for (s = p; *s == ' '; s++);
184
if (*s == '\r' || *s == '\n')
185
{
186
if (!(s = sfgetr(file->io, '\n', 0)))
187
return 0;
188
if ((n = sfvalue(file->io)) <= 61)
189
continue;
190
e = s + n;
191
while (*s == ' ')
192
s++;
193
}
194
p = s + 41;
195
if (strtoip4(s, NiL, &rp->hop.v4, NiL))
196
break;
197
rp->med = isdigit(s[25]) ? strtol(s+20, NiL, 10) : 0;
198
rp->local = isdigit(s[32]) ? strtol(s+27, NiL, 10) : 0;
199
rp->weight = isdigit(s[39]) ? strtol(s+34, NiL, 10) : 0;
200
bgp = (Bgp_t*)file->dss->data;
201
if ((i = (*bgp->type_as16path->internalf)(file->dss->cx, bgp->type_as16path, NiL, &bgp->type_as16path->format, &r, p, e - p, file->dss->cx->rm, disc)) < 0)
202
break;
203
p += i;
204
if (r.value.buffer.size > elementsof(rp->data))
205
{
206
ap = (Bgpasn_t*)r.value.buffer.data;
207
n = r.value.buffer.size / sizeof(Bgpasn_t);
208
for (o = 0, i = 1; i < n; i++)
209
if (ap[i] != ap[o])
210
ap[o++] = ap[i];
211
r.value.buffer.size = o * sizeof(Bgpasn_t);
212
if (r.value.buffer.size > elementsof(rp->data))
213
{
214
o = elementsof(rp->data);
215
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
216
(*disc->errorf)(NiL, disc, 1, "%s: AS path too long -- truncated to %d", file->format->name, o / sizeof(Bgpasn_t));
217
}
218
else if (disc->errorf && !(file->dss->flags & DSS_QUIET))
219
(*disc->errorf)(NiL, disc, 1, "%s: AS path too long -- %d duplicates removed", file->format->name, n - o);
220
}
221
o = r.value.buffer.size;
222
memcpy(rp->data, r.value.buffer.data, o);
223
rp->path.offset = 0;
224
rp->path.size = o / sizeof(Bgpasn_t);
225
rp->cluster.offset = rp->cluster.size = rp->community.offset = rp->community.size = 0;
226
for (;;)
227
{
228
switch (*p++)
229
{
230
case 'C':
231
if ((i = (*bgp->type_community->internalf)(file->dss->cx, bgp->type_community, NiL, &bgp->type_community->format, &r, p, e - p, file->dss->cx->rm, disc)) < 0)
232
break;
233
p += i;
234
if ((n = r.value.buffer.size) > (elementsof(rp->data) - o))
235
{
236
n = (elementsof(rp->data) - o) & (sizeof(Bgpasn_t) - 1);
237
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
238
(*disc->errorf)(NiL, disc, 1, "%s: cluster list too long -- truncated to %d", file->format->name, n);
239
}
240
rp->community.offset = o;
241
rp->community.size = n / sizeof(Bgpasn_t);
242
memcpy(rp->data + o, r.value.buffer.data, n);
243
o += n;
244
continue;
245
case 'I':
246
if ((i = (*bgp->type_cluster->internalf)(file->dss->cx, bgp->type_cluster, NiL, &bgp->type_cluster->format, &r, p, e - p, file->dss->cx->rm, disc)) < 0)
247
break;
248
p += i;
249
o = roundof(o, sizeof(Bgpnum_t));
250
if ((n = r.value.buffer.size) > (elementsof(rp->data) - o))
251
{
252
n = (elementsof(rp->data) - o) & (sizeof(Bgpnum_t) - 1);
253
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
254
(*disc->errorf)(NiL, disc, 1, "%s: cluster list too long -- truncated to %d", file->format->name, n);
255
}
256
rp->cluster.offset = o;
257
rp->cluster.size = n / sizeof(Bgpnum_t);
258
memcpy(rp->data + o, r.value.buffer.data, n);
259
o += n;
260
continue;
261
case 'T':
262
rp->time = tmdate(p, &e, NiL);
263
if (p == e && disc->errorf && !(file->dss->flags & DSS_QUIET))
264
(*disc->errorf)(NiL, disc, 1, "%s: %s: invalid date/time", file->format->name, p);
265
p = e;
266
continue;
267
case 'e':
268
rp->origin = BGP_ORIGIN_egp;
269
break;
270
case 'i':
271
rp->origin = BGP_ORIGIN_igp;
272
break;
273
case '?':
274
rp->origin = BGP_ORIGIN_incomplete;
275
break;
276
case ' ':
277
case '\t':
278
continue;
279
}
280
break;
281
}
282
memset(rp->data + o, 0, elementsof(rp->data) - o);
283
record->data = rp;
284
record->size = rp->size = (char*)(rp->data + o) - (char*)rp;
285
return 1;
286
}
287
}
288
return 0;
289
}
290
291
/*
292
* cisco writef
293
*/
294
295
static int
296
ciscowrite(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
297
{
298
register Ciscostate_t* state = (Ciscostate_t*)file->data;
299
register Bgproute_t* rp = (Bgproute_t*)record->data;
300
register Sfio_t* io = file->io;
301
register int i;
302
register int j;
303
register int k;
304
Bgpasn_t* ap;
305
Bgpnum_t* np;
306
307
if (rp->type == BGP_TYPE_announce)
308
sfputc(io, '+');
309
else if (rp->type == BGP_TYPE_withdraw)
310
sfputc(io, '-');
311
else if (rp->attr & BGP_valid)
312
sfputc(io, '*');
313
else if (rp->attr & BGP_rib_failure)
314
sfputc(io, 'r');
315
else
316
sfputc(io, ' ');
317
if (rp->attr & BGP_best)
318
sfputc(io, '>');
319
else if (rp->attr & BGP_history)
320
sfputc(io, 'h');
321
else
322
sfputc(io, ' ');
323
if (rp->attr & BGP_atomic)
324
sfputc(io, 'a');
325
else if (rp->attr & BGP_damped)
326
sfputc(io, 'd');
327
else if (rp->attr & BGP_internal)
328
sfputc(io, 'i');
329
else if (rp->attr & BGP_suppressed)
330
sfputc(io, 's');
331
else if (rp->attr & BGP_stale)
332
sfputc(io, 'S');
333
else
334
sfputc(io, ' ');
335
if (rp->addr.v4 == state->paddr && rp->bits == state->pbits)
336
sfprintf(io, " ");
337
else
338
{
339
state->paddr = rp->addr.v4;
340
state->pbits = rp->bits;
341
if (sfprintf(io, "%-16s", fmtip4(rp->addr.v4, rp->bits)) > 16)
342
sfprintf(io, "\n ");
343
else
344
sfputc(io, ' ');
345
}
346
sfprintf(io, "%-19s ", fmtip4(rp->hop.v4, -1));
347
if (rp->med)
348
sfprintf(io, "%6u ", rp->med);
349
else
350
sfprintf(io, " ");
351
if (rp->local)
352
sfprintf(io, "%6u ", rp->local);
353
else
354
sfprintf(io, " ");
355
sfprintf(io, "%6u", rp->weight);
356
if (j = rp->path.size)
357
{
358
ap = BGPPATH(rp);
359
for (i = 0; i < j; i++)
360
if (ap[i] == BGP_SET16)
361
{
362
if (k = ap[++i])
363
{
364
k += i - 1;
365
sfprintf(io, " {%u", ap[++i]);
366
while (i < k)
367
sfprintf(io, ",%u", ap[++i]);
368
sfputc(io, '}');
369
}
370
else
371
sfprintf(io, " %u", ap[++i]);
372
}
373
else
374
sfprintf(io, " %u", ap[i]);
375
}
376
if (rp->community.size)
377
{
378
sfputc(io, ' ');
379
sfputc(io, 'C');
380
ap = BGPCOMMUNITY(rp);
381
for (i = 0, j = rp->community.size; i < j; i += 2)
382
sfprintf(io, " %u:%u", ap[i], ap[i+1]);
383
}
384
if (rp->cluster.size)
385
{
386
sfputc(io, ' ');
387
sfputc(io, 'I');
388
np = BGPCLUSTER(rp);
389
for (i = 0, j = rp->cluster.size; i < j; i++)
390
sfprintf(io, " %lu", np[i]);
391
}
392
if (rp->time)
393
sfprintf(io, " T %s", fmttime("%K", rp->time));
394
if (rp->origin)
395
{
396
sfputc(io, ' ');
397
sfputc(io, rp->origin);
398
}
399
if (sfputc(io, '\n') == EOF)
400
{
401
if (disc->errorf)
402
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: write error", file->format->name);
403
return -1;
404
}
405
return 0;
406
}
407
408
/*
409
* cisco closef
410
*/
411
412
static int
413
ciscoclose(Dssfile_t* file, Dssdisc_t* disc)
414
{
415
if (!file->data)
416
return -1;
417
vmfree(file->dss->vm, file->data);
418
return 0;
419
}
420
421
Dssformat_t bgp_cisco_format =
422
{
423
"cisco",
424
"cisco router dump format (2009-03-15)",
425
CXH,
426
ciscoident,
427
ciscoopen,
428
ciscoread,
429
ciscowrite,
430
0,
431
ciscoclose,
432
0,
433
0,
434
bgp_cisco_next
435
};
436
437