Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/dsslib/bgp/bgp-mrt.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 mrt method
23
*
24
* Glenn Fowler
25
* AT&T Research
26
*/
27
28
#include "bgplib.h"
29
#include "mrt.h"
30
31
#include <ip6.h>
32
#include <swap.h>
33
34
/*
35
* mcast_vpn_grp_addr => agg_addr
36
*/
37
38
#define GROUP_STATE 0
39
40
#define STATE_BGP_HEADER 1
41
#define STATE_BGP_MESSAGE 2
42
#define STATE_BGP_ATTRIBUTES 3
43
#define STATE_BGP_ANNOUNCE 4
44
#define STATE_BGP_PREFIX 5
45
#define STATE_BGP_NLRI 6
46
#define STATE_BGP_ATTR 7
47
#define STATE_TABLE_DUMP 8
48
#define STATE_TABLE_DUMP_V2_RIB 9
49
#define STATE_TABLE_DUMP_V2_RIB_GENERIC 10
50
51
#define BE1(p) (*(unsigned char*)(p))
52
#define BE2(p) ((BE1(p)<<8)|(BE1(p+1)))
53
#define BE4(p) ((BE1(p)<<24)|(BE1(p+1)<<16)|(BE1(p+2)<<8)|(BE1(p+3)))
54
#define BE(b,p,n) memcpy(b,p,n)
55
56
#define DATA(sp,rp) (rp=&sp->route,sp->osize=sp->size)
57
#define ZERO(sp,rp) ((rp->set&BGP_SET_mvpn?(sp->np->size=0,memset(sp->np,0,BGP_FIXED),memset(sp->np+1,0,BGP_FIXED),sp->np->unknown.size=0):0),sp->size=0,memset(rp,0,BGP_FIXED),sp->unknown.size=0)
58
#define HEAD(sp,rp) (rp->message=sp->message,rp->stamp=sp->time)
59
#define INIT(sp,rp) (DATA(sp,rp),ZERO(sp,rp),HEAD(sp,rp))
60
#define NEXT(sp,rp) (DATA(sp,rp),HEAD(sp,rp))
61
#define DONE(sp,rp,rec,dp) done(sp,rp,rec,dp)
62
63
#define PEER_IPV6 0x80
64
#define PEER_AS32 0x40
65
66
#define VPN_rd 0x01
67
#define VPN_key 0x02
68
#define VPN_multicast 0x04
69
#define VPN_originator 0x08
70
#define VPN_src_as 0x10
71
72
typedef struct Mrtpeer_s
73
{
74
Bgpnum_t type;
75
Bgpnum_t bgpid;
76
Bgpnum_t as;
77
Bgpaddr_t addr;
78
} Mrtpeer_t;
79
80
typedef struct Mrtstate_s
81
{
82
Bgproute_t route;
83
Bgproute_t* np;
84
Bgpnum_t time;
85
Bgpnum_t message;
86
Bgpnum_t best;
87
unsigned int size;
88
unsigned int osize;
89
int as32;
90
int entries;
91
int group;
92
int push;
93
int state;
94
char* buf;
95
char* nxt;
96
char* end;
97
char* bugbuf;
98
size_t bugsiz;
99
Mrtpeer_t* peer;
100
size_t peers;
101
size_t maxpeers;
102
struct Unknown_s
103
{
104
int size;
105
char data[2*1024];
106
} unknown;
107
} Mrtstate_t;
108
109
#if ANONYMIZE
110
111
#define ANONYMIZE_FORMAT bgp_mrt_anonymize_format
112
#define ANONYMIZE_NEXT bgp_mrt_anonymize_next
113
#define ANONYMIZE_FORMAT_NAME "-anonymize"
114
#define ANONYMIZE_FORMAT_DESCRIPTION " anonymizer"
115
116
#define ANONYMIZE_OPEN(f,d) anonymize_open(f,d)
117
#define ANONYMIZE_HEAD(b,n) memcpy(anonymize.head,b,n)
118
#define ANONYMIZE_DATA(b,n) (anonymize.data=b,anonymize.size=n)
119
#define ANONYMIZE_FLUSH(f,d) anonymize_flush(f,d)
120
#define ANONYMIZE_WRITE(f,r,d) return 0
121
122
#define AE1(p) anonymize_value(0,p,1)
123
#define AE2(p) anonymize_value(0,p,2)
124
#define AE4(p) anonymize_value(0,p,4)
125
#define AET(p) (swapmem(int_swap,&anonymize.time,p,4),anonymize.time++)
126
#define AE(b,p,n) anonymize_value((char*)b,(char*)p,n)
127
128
typedef struct Anonymize_s
129
{
130
uint32_t time;
131
Sfio_t* io;
132
char* data;
133
size_t size;
134
char head[MRT_HEAD];
135
unsigned char value[16];
136
} Anonymize_t;
137
138
static Anonymize_t anonymize = { 1293840000 };
139
140
static void
141
anonymize_open(Dssfile_t* file, Dssdisc_t* disc)
142
{
143
int i;
144
145
anonymize.io = sfstdout;
146
for (i = 0; i < sizeof(anonymize.value); i++)
147
anonymize.value[i] = i;
148
}
149
150
static unsigned int
151
anonymize_value(char* dat, char* buf, int n)
152
{
153
unsigned int r;
154
int i;
155
int j;
156
157
for (i = n - 1; i >= 0; i -= 4)
158
for (j = i; j > (i - 4) && j >= 0 && !++anonymize.value[j]; j--);
159
memcpy(buf, anonymize.value, n);
160
if (dat)
161
{
162
memcpy(dat, anonymize.value, n);
163
return 0;
164
}
165
r = 0;
166
for (i = 0; i < n; i++)
167
r = (r << 8) + anonymize.value[i];
168
return r;
169
}
170
171
static int
172
anonymize_flush(Dssfile_t* file, Dssdisc_t* disc)
173
{
174
if (anonymize.size)
175
{
176
if (sfwrite(anonymize.io, anonymize.head, MRT_HEAD) != MRT_HEAD || sfwrite(anonymize.io, anonymize.data, anonymize.size) != anonymize.size)
177
{
178
if (disc->errorf)
179
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "%s: write error", file->format->name);
180
return -1;
181
}
182
anonymize.size = 0;
183
}
184
return 0;
185
}
186
187
#else
188
189
#define ANONYMIZE 0
190
191
#define ANONYMIZE_FORMAT bgp_mrt_format
192
#define ANONYMIZE_NEXT bgp_mrt_next
193
#define ANONYMIZE_FORMAT_NAME ""
194
#define ANONYMIZE_FORMAT_DESCRIPTION ""
195
196
#define ANONYMIZE_OPEN(f,d)
197
#define ANONYMIZE_HEAD(b,n)
198
#define ANONYMIZE_DATA(b,n)
199
#define ANONYMIZE_FLUSH(f,d)
200
#define ANONYMIZE_WRITE(f,r,d)
201
202
#define AE1(p) BE1(p)
203
#define AE2(p) BE2(p)
204
#define AE4(p) BE4(p)
205
#define AET(p) BE4(p)
206
#define AE(b,p,n) BE(b,p,n)
207
208
#endif
209
210
/*
211
* dump n bytes of the payload
212
*/
213
214
#define PAYLOAD(f,b,n) do { if (((f)->dss->test & 0x0010) && n > 0) payload(b, n); } while (0)
215
216
static void
217
payload(char* buf, int n)
218
{
219
int i;
220
int j;
221
222
sfprintf(sfstderr, " payload");
223
for (i = j = 0; i < n; i++)
224
{
225
sfprintf(sfstderr, "%3x", BE1(buf + i));
226
if (++j >= 30)
227
{
228
j = 0;
229
sfprintf(sfstderr, "\n");
230
if ((n - i) > 1)
231
sfprintf(sfstderr, " ");
232
}
233
}
234
if (j)
235
sfprintf(sfstderr, "\n");
236
}
237
238
static char*
239
symbol(int group, int index)
240
{
241
static char buf[16];
242
243
switch (group)
244
{
245
case GROUP_MESSAGE:
246
switch (index)
247
{
248
case MRT_I_AM_DEAD: return "I_AM_DEAD";
249
case MRT_BGP: return "BGP";
250
case MRT_RIP: return "RIP";
251
case MRT_IDRP: return "IDRP";
252
case MRT_RIPNG: return "RIPNG";
253
case MRT_BGP4PLUS: return "BGP4PLUS";
254
case MRT_BGP4PLUS_01: return "BGP4PLUS_01";
255
case MRT_OSPFv2: return "OSPFv2";
256
case MRT_TABLE_DUMP: return "TABLE_DUMP";
257
case MRT_TABLE_DUMP_V2: return "TABLE_DUMP_V2";
258
case MRT_BGP4MP: return "BGP4MP";
259
case MRT_BGP4MP_ET: return "BGP4MP_ET";
260
case MRT_ISIS: return "ISIS";
261
case MRT_ISIS_ET: return "ISIS_ET";
262
case MRT_OSPFv3: return "OSPFv3";
263
case MRT_OSPFv3_ET: return "OSPFv3_ET";
264
}
265
break;
266
case GROUP_BGP:
267
switch (index)
268
{
269
case MRT_BGP_NULL: return "NULL";
270
case MRT_BGP_UPDATE: return "UPDATE";
271
case MRT_BGP_PREF_UPDATE: return "PREF_UPDATE";
272
case MRT_BGP_STATE_CHANGE: return "STATE_CHANGE";
273
case MRT_BGP_SYNC: return "SYNC";
274
case MRT_BGP_OPEN: return "OPEN";
275
case MRT_BGP_NOTIFY: return "NOTIFY";
276
case MRT_BGP_KEEPALIVE: return "KEEPALIVE";
277
}
278
break;
279
case GROUP_TABLE:
280
switch (index)
281
{
282
case MRT_TABLE_IPV4_UNICAST: return "IPV4_UNICAST";
283
case MRT_TABLE_IPV6_UNICAST: return "IPV6_UNICAST";
284
}
285
break;
286
case GROUP_TABLE_V2:
287
switch (index)
288
{
289
case MRT_TABLE_PEER_INDEX_TABLE: return "PEER_INDEX_TABLE";
290
case MRT_TABLE_RIB_IPV4_UNICAST: return "RIB_IPV4_UNICAST";
291
case MRT_TABLE_RIB_IPV4_MULTICAST: return "RIB_IPV4_MULTICAST";
292
case MRT_TABLE_RIB_IPV6_UNICAST: return "RIB_IPV6_UNICAST";
293
case MRT_TABLE_RIB_IPV6_MULTICAST: return "RIB_IPV6_MULTICAST";
294
case MRT_TABLE_RIB_GENERIC: return "RIB_GENERIC";
295
}
296
break;
297
case GROUP_BGP4MP:
298
case GROUP_BGP4MP_ET:
299
switch (index)
300
{
301
case MRT_BGP4MP_KEEPALIVE: return "KEEPALIVE";
302
case MRT_BGP4MP_STATE_CHANGE: return "STATE_CHANGE";
303
case MRT_BGP4MP_MESSAGE: return "MESSAGE";
304
case MRT_BGP4MP_UPDATE: return "UPDATE";
305
case MRT_BGP4MP_NOTIFY: return "NOTIFY";
306
case MRT_BGP4MP_MESSAGE_AS4: return "MESSAGE_AS4";
307
case MRT_BGP4MP_STATE_CHANGE_AS4: return "STATE_CHANGE_AS4";
308
case MRT_BGP4MP_MESSAGE_LOCAL: return "MESSAGE_LOCAL";
309
case MRT_BGP4MP_MESSAGE_AS4_LOCAL: return "MESSAGE_AS4_LOCAL";
310
case MRT_BGP4MP_EXTENSION_20: return "EXTENSION_20";
311
}
312
break;
313
case GROUP_ATTR:
314
switch (index)
315
{
316
case MRT_ATTR_ORIGIN: return "ORIGIN";
317
case MRT_ATTR_AS_PATH: return "AS_PATH";
318
case MRT_ATTR_HOP: return "HOP";
319
case MRT_ATTR_MED: return "MED";
320
case MRT_ATTR_LOCAL: return "LOCAL";
321
case MRT_ATTR_ATOMIC: return "ATOMIC";
322
case MRT_ATTR_AGGREGATOR: return "AGGREGATOR";
323
case MRT_ATTR_COMMUNITY: return "COMMUNITY";
324
case MRT_ATTR_ORIGINATOR: return "ORIGINATOR";
325
case MRT_ATTR_CLUSTER: return "CLUSTER";
326
case MRT_ATTR_DPA: return "DPA";
327
case MRT_ATTR_ADVERTIZER: return "ADVERTIZER";
328
case MRT_ATTR_RCID_PATH: return "RCID_PATH";
329
case MRT_ATTR_MP_REACH_NLRI: return "MP_REACH_NLRI";
330
case MRT_ATTR_MP_UNREACH_NLRI: return "MP_UNREACH_NLRI";
331
case MRT_ATTR_EXTENDED_COMMUNITY: return "EXTENDED_COMMUNITY";
332
case MRT_ATTR_AS32_PATH: return "AS32_PATH";
333
case MRT_ATTR_AGGREGATOR32: return "AGGREGATOR32";
334
case MRT_ATTR_CONNECTOR: return "CONNECTOR";
335
case MRT_ATTR_PMSI_TUNNEL: return "PMSI_TUNNEL";
336
case MRT_ATTR_SET: return "SET";
337
}
338
break;
339
case GROUP_AFI:
340
switch (index)
341
{
342
case MRT_AFI_IPV4: return "ipv4";
343
case MRT_AFI_IPV6: return "ipv6";
344
}
345
break;
346
case GROUP_SAFI:
347
switch (index)
348
{
349
case MRT_SAFI_NLRI_UCAST_FORWARD: return "NLRI_UCAST_FORWARD";
350
case MRT_SAFI_NLRI_MCAST_FORWARD: return "NLRI_MCAST_FORWARD";
351
case MRT_SAFI_NLRI_MLPS_LABEL: return "NLRI_MLPS_LABEL";
352
case MRT_SAFI_MCAST_VPN: return "MCAST_VPN";
353
case MRT_SAFI_VPN_MLPS_LABEL: return "VPN_MLPS_LABEL";
354
}
355
break;
356
case GROUP_MCAST_VPN:
357
switch (index)
358
{
359
case VPN_INTRA_AS_I_PMSI_A_D: return "INTRA_AS_I_PMSI_A_D";
360
case VPN_INTER_AS_I_PMSI_A_D: return "INTER_AS_I_PMSI_A_D";
361
case VPN_S_PMSI_A_D: return "S_PMSI_A_D";
362
case VPN_LEAF_A_D: return "LEAF_A_D";
363
case VPN_SOURCE_ACTIVE_A_D: return "SOURCE_ACTIVE_A_D";
364
case VPN_SHARED_TREE_JOIN: return "SHARED_TREE_JOIN";
365
case VPN_SOURCE_TREE_JOIN: return "SOURCE_TREE_JOIN";
366
}
367
break;
368
case GROUP_BGP_MESSAGE:
369
switch (index)
370
{
371
case MRT_BGP_MESSAGE_STATE_CHANGE: return "STATE_CHANGE";
372
case MRT_BGP_MESSAGE_OPEN: return "OPEN";
373
case MRT_BGP_MESSAGE_UPDATE: return "UPDATE";
374
case MRT_BGP_MESSAGE_NOTIFY: return "NOTIFY";
375
case MRT_BGP_MESSAGE_KEEPALIVE: return "KEEPALIVE";
376
}
377
break;
378
case GROUP_STATE:
379
switch (index)
380
{
381
case STATE_BGP_HEADER: return "BGP_HEADER";
382
case STATE_BGP_MESSAGE: return "BGP_MESSAGE";
383
case STATE_BGP_ATTRIBUTES: return "BGP_ATTRIBUTES";
384
case STATE_BGP_ANNOUNCE: return "BGP_ANNOUNCE";
385
case STATE_BGP_PREFIX: return "BGP_PREFIX";
386
case STATE_BGP_NLRI: return "BGP_NLRI";
387
case STATE_BGP_ATTR: return "BGP_ATTR";
388
case STATE_TABLE_DUMP: return "TABLE_DUMP";
389
case STATE_TABLE_DUMP_V2_RIB: return "TABLE_DUMP_V2_RIB";
390
case STATE_TABLE_DUMP_V2_RIB_GENERIC: return "TABLE_DUMP_V2_RIB_GENERIC";
391
}
392
break;
393
}
394
sfsprintf(buf, sizeof(buf), "(%d)", index);
395
return buf;
396
}
397
398
/*
399
* mrt identf
400
*/
401
402
static int
403
mrtident(Dssfile_t* file, void* buf, size_t n, Dssdisc_t* disc)
404
{
405
if (n < MRT_HEAD)
406
return 0;
407
#if ANONYMIZE
408
if (!(file->dss->meth->flags & BGP_METHOD_ANONYMIZE))
409
return 0;
410
#else
411
if (file->dss->meth->flags & BGP_METHOD_ANONYMIZE)
412
return 0;
413
#endif
414
switch (BE2((char*)buf + 4))
415
{
416
case MRT_BGP:
417
case MRT_BGP4PLUS:
418
case MRT_TABLE_DUMP:
419
case MRT_TABLE_DUMP_V2:
420
case MRT_BGP4MP:
421
case MRT_BGP4MP_ET:
422
/* implemented */
423
return 1;
424
case MRT_RIP:
425
case MRT_IDRP:
426
case MRT_RIPNG:
427
case MRT_BGP4PLUS_01:
428
case MRT_OSPFv2:
429
case MRT_ISIS:
430
case MRT_ISIS_ET:
431
case MRT_OSPFv3:
432
case MRT_OSPFv3_ET:
433
/* not implemented */
434
break;
435
default:
436
/* unknown */
437
break;
438
}
439
return 0;
440
}
441
442
/*
443
* mrt openf
444
*/
445
446
static int
447
mrtopen(Dssfile_t* file, Dssdisc_t* disc)
448
{
449
Bgp_t* bgp = (Bgp_t*)file->dss->data;
450
451
if (!(file->data = (void*)vmnewof(file->dss->vm, 0, Mrtstate_t, 1, 0)))
452
{
453
if (disc->errorf)
454
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
455
return -1;
456
}
457
((Mrtstate_t*)file->data)->np = bgp->sub;
458
ANONYMIZE_OPEN(file, disc);
459
return 0;
460
}
461
462
/*
463
* extract a route distinguisher
464
*/
465
466
static int
467
rd(Dssfile_t* file, Mrtstate_t* state, Bgproute_t* rp, char* end, Dssdisc_t* disc)
468
{
469
if ((state->buf + 8) > end)
470
{
471
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
472
(*disc->errorf)(NiL, disc, 1, "rd %s size %u -- %d available", symbol(GROUP_STATE, state->state), 8, (int)(end - state->buf));
473
return -1;
474
}
475
rp->rd_type = BE2(state->buf);
476
switch (rp->rd_type)
477
{
478
case 0:
479
rp->rd_as = AE2(state->buf + 2);
480
rp->rd_number = AE4(state->buf + 4);
481
break;
482
case 1:
483
rp->rd_addr.v4 = AE4(state->buf + 2);
484
rp->rd_number = AE2(state->buf + 6);
485
break;
486
case 2:
487
rp->rd_as = AE4(state->buf + 2);
488
rp->rd_number = AE2(state->buf + 6);
489
break;
490
}
491
if (file->dss->flags & DSS_DEBUG)
492
sfprintf(sfstderr, " nlri rd type %u number %u as %u addr %s\n", rp->rd_type, rp->rd_number, rp->rd_as, fmtip4(rp->rd_addr.v4, -1));
493
state->buf += 8;
494
return 0;
495
}
496
497
/*
498
* extract a prefix, or is it an nlri, no wait, nlri() calls this
499
* see what the RFCs say
500
*/
501
502
static int
503
prefix(Dssfile_t* file, Mrtstate_t* state, Bgproute_t* rp, int bits, char* end, Dssdisc_t* disc)
504
{
505
Bgpnum_t v4;
506
int i;
507
int n;
508
unsigned char v6[IP6BITS+1];
509
510
if (bits < 0)
511
bits = BE1(state->buf++);
512
switch (rp->afi)
513
{
514
case MRT_AFI_IPV4:
515
if (n = bits)
516
n = (n - 1) / 8 + 1;
517
if (n > 4 || n > (end - state->buf))
518
{
519
i = 4;
520
goto nope;
521
}
522
if (n == (end - state->buf))
523
state->state = 0;
524
v4 = 0;
525
for (i = 0; i < n; i++)
526
{
527
v4 <<= 8;
528
v4 |= AE1(state->buf++);
529
}
530
while (i++ < 4)
531
v4 <<= 8;
532
if (state->best != state->message && (state->best = state->message) || rp->addr.v4 != v4 || rp->bits != bits)
533
{
534
rp->addr.v4 = v4;
535
rp->bits = bits;
536
rp->attr |= BGP_best;
537
}
538
rp->set |= BGP_SET_prefixv4;
539
if (file->dss->flags & DSS_DEBUG)
540
sfprintf(sfstderr, " nlri %c %s prefix %s\n", rp->type, symbol(GROUP_AFI, rp->afi), fmtip4(rp->addr.v4, rp->bits));
541
break;
542
case MRT_AFI_IPV6:
543
if (v6[IP6BITS] = n = bits)
544
n = (n - 1) / 8 + 1;
545
if (n > 16 || n > (end - state->buf))
546
{
547
i = 16;
548
goto nope;
549
}
550
if (n == (end - state->buf))
551
state->state = 0;
552
i = 0;
553
while (i < n)
554
v6[i++] = AE1(state->buf++);
555
while (i < 16)
556
v6[i++] = 0;
557
if (state->best != state->message && (state->best = state->message) || memcmp(rp->prefixv6, v6, sizeof(rp->prefixv6)))
558
{
559
memcpy(rp->prefixv6, v6, sizeof(rp->prefixv6));
560
rp->attr |= BGP_best;
561
}
562
rp->set |= BGP_SET_prefixv6;
563
if (file->dss->flags & DSS_DEBUG)
564
sfprintf(sfstderr, " nlri %c %s prefix %s\n", rp->type, symbol(GROUP_AFI, rp->afi), fmtip6(rp->prefixv6, rp->prefixv6[IP6BITS]));
565
break;
566
}
567
return 0;
568
nope:
569
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
570
(*disc->errorf)(NiL, disc, 1, "nlri %s %s prefix bytes %d too large -- %d max, %d available", symbol(GROUP_STATE, state->state), symbol(GROUP_AFI, rp->afi), n, i, (int)(end - state->buf));
571
state->buf = end;
572
return 0;
573
}
574
575
/*
576
* extract a single nlri
577
*/
578
579
static int
580
nlri(register Dssfile_t* file, register Mrtstate_t* state, register Bgproute_t* rp, char* end, Dssdisc_t* disc)
581
{
582
int n;
583
int m;
584
int i;
585
int j;
586
int q;
587
int v;
588
char* buf;
589
Bgpnum_t* np;
590
Bgproute_t* op;
591
592
j = BE1(state->buf++);
593
switch (rp->safi)
594
{
595
case MRT_SAFI_NLRI_UCAST_FORWARD:
596
case MRT_SAFI_NLRI_MCAST_FORWARD:
597
break;
598
case MRT_SAFI_NLRI_MLPS_LABEL:
599
case MRT_SAFI_VPN_MLPS_LABEL:
600
m = q = 0;
601
for (;;)
602
{
603
m++;
604
rp->label = AE2(state->buf + q);
605
q += 2;
606
n = BE1(state->buf + q);
607
q += 1;
608
/* XXX: where is the BGP_TYPE_withdraw check documented */
609
if ((n & 1) || rp->type == BGP_TYPE_withdraw)
610
{
611
rp->label = (rp->label << 4) | (n >> 4);
612
break;
613
}
614
/* XXX: where is "no TTL present" documented */
615
}
616
j -= q * 8;
617
m *= 2;
618
BGPALLOC(rp, state->size, Bgpnum_t, np, m, &rp->labels, "nlri label list", disc);
619
for (q = 0; q < m; q += 2)
620
{
621
v = AE2(state->buf) << 8;
622
state->buf += 2;
623
n = BE1(state->buf);
624
state->buf += 1;
625
if (q < (rp->labels.size - 1))
626
{
627
np[q] = (v | n) >> 4;
628
np[q+1] = n & 0xf;
629
}
630
}
631
if (file->dss->flags & DSS_DEBUG)
632
sfprintf(sfstderr, " nlri %c %s/%s label %u labels %d\n", rp->type, symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), rp->label, rp->labels.size / 2);
633
if (rp->safi == MRT_SAFI_VPN_MLPS_LABEL)
634
{
635
buf = state->buf;
636
if (rd(file, state, rp, end, disc))
637
goto nope;
638
j -= 8 * (state->buf - buf);
639
}
640
break;
641
case MRT_SAFI_MCAST_VPN:
642
rp->set |= BGP_SET_mvpn;
643
op = rp;
644
rp = state->np;
645
rp->afi = op->afi;
646
rp->safi = op->safi;
647
m = BE1(state->buf++);
648
if (m > (int)(end - state->buf))
649
{
650
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
651
(*disc->errorf)(NiL, disc, 1, "nlri %s.%s size %d too large -- %d available", symbol(GROUP_SAFI, op->safi), symbol(GROUP_MCAST_VPN, j), m, (int)(end - state->buf));
652
goto nope;
653
}
654
end = state->buf + m;
655
if (file->dss->flags & DSS_DEBUG)
656
sfprintf(sfstderr, " %s.%s size %d available %d/%d\n", symbol(GROUP_SAFI, op->safi), symbol(GROUP_MCAST_VPN, j), m, (int)(end - state->buf), (int)(state->end - state->buf));
657
PAYLOAD(file, state->buf, m);
658
switch (j)
659
{
660
case VPN_INTRA_AS_I_PMSI_A_D:
661
q = VPN_rd|VPN_originator;
662
break;
663
case VPN_INTER_AS_I_PMSI_A_D:
664
q = VPN_rd|VPN_src_as;
665
break;
666
case VPN_S_PMSI_A_D:
667
q = VPN_rd|VPN_multicast|VPN_originator;
668
break;
669
case VPN_LEAF_A_D:
670
q = VPN_key|VPN_originator;
671
break;
672
case VPN_SOURCE_ACTIVE_A_D:
673
q = VPN_rd|VPN_multicast;
674
break;
675
case VPN_SHARED_TREE_JOIN:
676
case VPN_SOURCE_TREE_JOIN:
677
q = VPN_rd|VPN_src_as|VPN_multicast;
678
break;
679
default:
680
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
681
(*disc->errorf)(NiL, disc, 1, "%s.%s unknown route type", symbol(GROUP_SAFI, op->safi), symbol(GROUP_MCAST_VPN, j));
682
goto skip;
683
}
684
if ((q & VPN_rd) && rd(file, state, rp, end, disc))
685
goto nope;
686
if (q & VPN_key)
687
{
688
rp++;
689
rp->afi = op->afi;
690
rp->safi = op->safi;
691
if (nlri(file, state, rp, end, disc))
692
goto nope;
693
}
694
if (q & VPN_src_as)
695
{
696
rp->src_as = AE4(state->buf);
697
state->buf += 4;
698
}
699
if (q & VPN_multicast)
700
{
701
i = BE1(state->buf++);
702
switch (i)
703
{
704
case MRT_BITS_IPV4:
705
rp->src_addr.v4 = AE4(state->buf);
706
state->buf += 4;
707
break;
708
case MRT_BITS_IPV6:
709
AE(rp->src_addr.v6, state->buf, 16);
710
state->buf += 16;
711
rp->set |= BGP_SET_src_addrv6;
712
break;
713
default:
714
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
715
(*disc->errorf)(NiL, disc, 1, "%u: unknown mcast source length", i);
716
goto skip;
717
}
718
i = BE1(state->buf++);
719
switch (i)
720
{
721
case MRT_BITS_IPV4:
722
rp->agg_addr.v4 = AE4(state->buf);
723
state->buf += 4;
724
rp->set |= BGP_SET_agg_addrv4;
725
break;
726
case MRT_BITS_IPV6:
727
AE(rp->agg_addr.v6, state->buf, 16);
728
state->buf += 16;
729
rp->set |= BGP_SET_agg_addrv6;
730
break;
731
default:
732
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
733
(*disc->errorf)(NiL, disc, 1, "%u: unknown mcast group length", i);
734
goto skip;
735
}
736
}
737
if (q & VPN_originator)
738
{
739
if (op->afi == MRT_AFI_IPV4 || (int)(end - state->buf) == 4)
740
{
741
rp->originator.v4 = AE4(state->buf);
742
state->buf += 4;
743
rp->set &= ~BGP_SET_originatorv6;
744
}
745
else if (op->afi == MRT_AFI_IPV6 || (int)(end - state->buf) == 16)
746
{
747
AE(rp->originator.v6, state->buf, 16);
748
state->buf += 16;
749
rp->set |= BGP_SET_originatorv6;
750
}
751
else
752
{
753
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
754
(*disc->errorf)(NiL, disc, 1, "%u: unknown afi index (size %d)", op->afi, (int)(end - state->buf));
755
goto nope;
756
}
757
}
758
if (state->buf < end)
759
{
760
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
761
(*disc->errorf)(NiL, disc, 1, "nlri %s.%s size %d -- %d unused", symbol(GROUP_SAFI, op->safi), symbol(GROUP_MCAST_VPN, j), m, (int)(end - state->buf));
762
state->buf = end;
763
}
764
rp->type = j;
765
goto done;
766
default:
767
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
768
(*disc->errorf)(NiL, disc, 1, "%u: unknown safi index", rp->safi);
769
goto skip;
770
}
771
if (file->dss->flags & DSS_DEBUG)
772
sfprintf(sfstderr, " nlri %c %s/%s bits %d\n", rp->type, symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), j);
773
if (prefix(file, state, rp, j, end, disc))
774
goto nope;
775
done:
776
if (state->buf > end)
777
{
778
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
779
(*disc->errorf)(NiL, disc, 1, "nlri attribute %s overflow", symbol(GROUP_STATE, state->state));
780
goto nope;
781
}
782
return 0;
783
skip:
784
state->buf = end;
785
return 0;
786
nope:
787
state->buf = end;
788
return -1;
789
}
790
791
/*
792
* extract a single attribute
793
*/
794
795
static int
796
attr(register Dssfile_t* file, register Mrtstate_t* state, register Bgproute_t* rp, char* end, Dssdisc_t* disc)
797
{
798
register int i;
799
int j;
800
int k;
801
int m;
802
int n;
803
int q;
804
int r;
805
Bgpasn_t* ap;
806
Bgpnum_t* ap32;
807
Bgpnum_t* np;
808
char* nxt;
809
unsigned char* up;
810
unsigned long v;
811
unsigned int type;
812
unsigned int flag;
813
unsigned int size;
814
815
if (state->buf >= (end - 3))
816
{
817
state->buf = end;
818
return 0;
819
}
820
flag = BE1(state->buf++);
821
type = BE1(state->buf++);
822
size = BE1(state->buf++);
823
if (flag & 0x10)
824
{
825
if (state->buf >= end)
826
{
827
state->buf = end;
828
return 0;
829
}
830
size = (size << 8) | BE1(state->buf++);
831
}
832
if (file->dss->flags & DSS_DEBUG)
833
sfprintf(sfstderr, " attr flag 0x%02x %s size %u available %d/%d\n", flag, symbol(GROUP_ATTR, type), size, (int)(end - state->buf), (int)(state->end - state->buf));
834
if ((nxt = state->buf + size) > end)
835
{
836
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
837
(*disc->errorf)(NiL, disc, 1, "nlri attribute %s size %u -- %d available", symbol(GROUP_ATTR, type), size, (int)(end - state->buf));
838
goto nope;
839
}
840
switch (type)
841
{
842
case MRT_ATTR_ORIGIN:
843
switch (BE1(state->buf))
844
{
845
case 0:
846
rp->origin = BGP_ORIGIN_igp;
847
break;
848
case 1:
849
rp->origin = BGP_ORIGIN_egp;
850
break;
851
default:
852
rp->origin = BGP_ORIGIN_incomplete;
853
break;
854
}
855
break;
856
case MRT_ATTR_AS_PATH:
857
if (!state->as32 && (m = size))
858
{
859
PAYLOAD(file, state->buf, m);
860
for (i = j = 0; i <= (m - 4); i += 2)
861
{
862
/* <type> 1:set 2:sequence 3:confed_sequence 4:confed_set <length> */
863
k = BE1(state->buf + i);
864
if (k < 1 || k > 4)
865
break;
866
if (!(k & 2))
867
j += 2;
868
k = BE1(state->buf + i + 1);
869
if ((i + 2 + k) > m)
870
break;
871
while (k-- > 0 && i <= (m - 4))
872
{
873
i += 2;
874
j++;
875
if (AE2(state->buf + i) == BGP_SET16)
876
j += 2;
877
}
878
}
879
880
/*
881
* XXX: mrt has no "old bgp" or "new bgp" marker
882
* old bgp AS_PATH contain 16 bit AS (i==m)
883
* new bgp AS_PATH contain 32 bit AS (i!=m most of the time)
884
* there is a small chance of hitting an AS32 encoding that is also a valid AS16
885
* how about an RFC that addresses all the XXX in this parser
886
*/
887
888
if (i == m)
889
{
890
BGPALLOC(rp, state->size, Bgpasn_t, ap, j, &rp->path, "AS16 path", disc);
891
for (i = j = q = 0; i <= (m - 2); i += 2)
892
{
893
/* <type> 1:set 2:sequence 3:confed_sequence 4:confed_set <length> */
894
k = BE1(state->buf + i + 1);
895
if (BE1(state->buf + i) & 2)
896
q += k;
897
else
898
{
899
q++;
900
ap[j++] = BGP_SET16;
901
ap[j++] = k;
902
}
903
while (k-- > 0 && i <= (m - 4))
904
{
905
i += 2;
906
if ((ap[j++] = AE2(state->buf + i)) == BGP_SET16)
907
{
908
ap[j++] = 0;
909
ap[j++] = BGP_SET16;
910
}
911
}
912
}
913
rp->path.elements = q;
914
if (file->dss->flags & DSS_DEBUG)
915
{
916
sfprintf(sfstderr, " AS16 path [%d]", q);
917
for (i = 0; i < j; i++)
918
if (ap[i] != BGP_SET16)
919
sfprintf(sfstderr, " %u", ap[i]);
920
else if (ap[++i])
921
sfprintf(sfstderr, " :");
922
else
923
sfprintf(sfstderr, " %u", ap[++i]);
924
sfprintf(sfstderr, "\n");
925
}
926
break;
927
}
928
state->as32 = 1;
929
}
930
/*FALLTHROUGH*/
931
case MRT_ATTR_AS32_PATH:
932
if (m = size)
933
{
934
PAYLOAD(file, state->buf, m);
935
for (i = j = 0; i <= (m - 6); i += 4)
936
{
937
/* <type> 1:set 2:sequence 3:confed_sequence 4:confed_set <length> */
938
k = BE1(state->buf + i + 1);
939
if (!(BE1(state->buf + i) & 2))
940
j += 2;
941
i -= 2;
942
while (k-- > 0 && i <= (m - 8))
943
{
944
i += 4;
945
j++;
946
if (AE4(state->buf + i) == BGP_SET32)
947
j += 2;
948
}
949
}
950
BGPALLOC(rp, state->size, Bgpnum_t, ap32, j, &rp->path32, "AS32 path", disc);
951
for (i = j = q = 0; i <= (m - 2); i += 4)
952
{
953
k = BE1(state->buf + i + 1);
954
if (BE1(state->buf + i) & 2)
955
q += k;
956
else
957
{
958
q++;
959
ap32[j++] = BGP_SET32;
960
ap32[j++] = k;
961
}
962
i -= 2;
963
while (k-- > 0 && i <= (m - 8))
964
{
965
i += 4;
966
if ((ap32[j++] = AE4(state->buf + i)) == BGP_SET32)
967
{
968
ap32[j++] = 0;
969
ap32[j++] = BGP_SET32;
970
}
971
}
972
}
973
rp->path32.elements = q;
974
if (file->dss->flags & DSS_DEBUG)
975
{
976
sfprintf(sfstderr, " AS32 path [%u]", q);
977
for (i = 0; i < j; i++)
978
if (ap[i] != BGP_SET16)
979
sfprintf(sfstderr, " %u", ap32[i]);
980
else if (ap[++i])
981
sfprintf(sfstderr, " :");
982
else
983
sfprintf(sfstderr, " %u", ap32[++i]);
984
sfprintf(sfstderr, "\n");
985
}
986
}
987
break;
988
case MRT_ATTR_HOP:
989
rp->hop.v4 = AE4(state->buf);
990
break;
991
case MRT_ATTR_MED:
992
rp->med = AE4(state->buf);
993
break;
994
case MRT_ATTR_LOCAL:
995
rp->local = AE4(state->buf);
996
break;
997
case MRT_ATTR_ATOMIC:
998
rp->attr |= BGP_atomic;
999
break;
1000
case MRT_ATTR_AGGREGATOR:
1001
rp->agg_as = AE2(state->buf);
1002
rp->agg_addr.v4 = AE4(state->buf + 2);
1003
break;
1004
case MRT_ATTR_COMMUNITY:
1005
k = size / 2;
1006
BGPALLOC(rp, state->size, Bgpasn_t, ap, k, &rp->community, "community list", disc);
1007
for (i = j = 0; j < k; i += 4)
1008
{
1009
v = AE4(state->buf + i);
1010
ap[j++] = (v >> 16) & 0xffff;
1011
ap[j++] = v & 0xffff;
1012
}
1013
break;
1014
case MRT_ATTR_ORIGINATOR:
1015
rp->set &= ~BGP_SET_originatorv6;
1016
rp->originator.v4 = AE4(state->buf);
1017
break;
1018
case MRT_ATTR_CLUSTER:
1019
k = size / 4;
1020
BGPALLOC(rp, state->size, Bgpnum_t, np, k, &rp->cluster, "cluster list", disc);
1021
for (i = j = 0; j < k; i += 4)
1022
np[j++] = AE4(state->buf + i);
1023
break;
1024
case MRT_ATTR_DPA:
1025
rp->dpa_as = AE2(state->buf);
1026
rp->dpa_addr.v4 = AE4(state->buf + 2);
1027
break;
1028
case MRT_ATTR_MP_REACH_NLRI:
1029
rp->type = BGP_TYPE_announce;
1030
reach:
1031
PAYLOAD(file, state->buf, size);
1032
switch (state->state)
1033
{
1034
case STATE_TABLE_DUMP_V2_RIB: /* XXX: how can afi/safi be inline? */
1035
k = BE2(state->buf);
1036
n = BE1(state->buf + 3);
1037
if (!(k == MRT_AFI_IPV4 && n == 4 || k == MRT_AFI_IPV6 && n == 16))
1038
{
1039
k = 0;
1040
break;
1041
}
1042
/*FALLTHROUGH*/
1043
case STATE_BGP_ANNOUNCE:
1044
rp->afi = BE2(state->buf);
1045
rp->safi = BE1(state->buf + 2);
1046
state->buf += 3;
1047
k = 1;
1048
break;
1049
default:
1050
k = 0;
1051
break;
1052
}
1053
if (rp->type == BGP_TYPE_announce)
1054
{
1055
n = BE1(state->buf++);
1056
if (file->dss->flags & DSS_DEBUG)
1057
sfprintf(sfstderr, " nlri mp %s %s/%s hop %d %s state %s\n", "announce", symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), n, k ? "inline" : "global", symbol(GROUP_STATE, state->state));
1058
if (n == 4 || rp->afi == MRT_AFI_IPV4)
1059
{
1060
if (n > 4)
1061
state->buf += n - 4;
1062
rp->hop.v4 = AE4(state->buf);
1063
state->buf += 4;
1064
rp->set |= BGP_SET_hopv4;
1065
}
1066
else if (n == 16 || rp->afi == MRT_AFI_IPV6)
1067
{
1068
if (n > 16)
1069
state->buf += n - 16;
1070
AE(rp->hop.v6, state->buf, 16);
1071
state->buf += 16;
1072
rp->set |= BGP_SET_hopv6;
1073
}
1074
else
1075
goto unknown;
1076
if (state->buf < nxt)
1077
{
1078
/* reserved */
1079
k = BE1(state->buf++);
1080
if (k && (file->dss->flags & DSS_DEBUG))
1081
sfprintf(sfstderr, " nlri reserved %u -- should be 0\n", k);
1082
}
1083
}
1084
else if (file->dss->flags & DSS_DEBUG)
1085
sfprintf(sfstderr, " nlri mp %s %s/%s %s state %s\n", "withdraw", symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), k == 1 ? "inline" : "global", symbol(GROUP_STATE, state->state));
1086
if (state->buf < nxt)
1087
{
1088
state->nxt = state->end;
1089
state->end = nxt;
1090
state->push = state->state == STATE_BGP_MESSAGE ? STATE_BGP_ATTR : state->state;
1091
state->state = STATE_BGP_NLRI;
1092
return 0;
1093
}
1094
break;
1095
case MRT_ATTR_MP_UNREACH_NLRI:
1096
rp->type = BGP_TYPE_withdraw;
1097
goto reach;
1098
case MRT_ATTR_EXTENDED_COMMUNITY:
1099
k = size;
1100
BGPALLOC(rp, state->size, unsigned char, up, k, &rp->extended, "extended community list", disc);
1101
AE(up, state->buf, k);
1102
break;
1103
case MRT_ATTR_AGGREGATOR32:
1104
rp->agg_as32 = AE4(state->buf);
1105
rp->agg_addr32.v4 = AE4(state->buf + 4);
1106
break;
1107
case MRT_ATTR_ADVERTIZER:
1108
case MRT_ATTR_RCID_PATH:
1109
case MRT_ATTR_SET:
1110
default:
1111
unknown:
1112
if ((sizeof(state->unknown.data) - state->unknown.size) > 14)
1113
{
1114
i = state->unknown.size;
1115
i += sfsprintf(state->unknown.data + i, sizeof(state->unknown.data) - i, "0x%02x:%u:%u:0x", flag, type, size);
1116
for (m = 0; m < size; m++)
1117
i += sfsprintf(state->unknown.data + i, sizeof(state->unknown.data) - i, "%02x", AE1(state->buf + m));
1118
state->unknown.data[i++] = ';';
1119
state->unknown.size = i;
1120
}
1121
break;
1122
}
1123
done:
1124
state->buf = nxt;
1125
return 1;
1126
nope:
1127
state->buf = end;
1128
return -1;
1129
}
1130
1131
/*
1132
* extract path attributes
1133
*/
1134
1135
static int
1136
pathattr(register Dssfile_t* file, register Mrtstate_t* state, register Bgproute_t* rp, Dssdisc_t* disc)
1137
{
1138
char* end;
1139
size_t n;
1140
size_t r;
1141
int x;
1142
unsigned int size;
1143
1144
rp->hop.v4 = 0;
1145
size = BE2(state->buf);
1146
end = (state->buf += 2) + size;
1147
if (file->dss->flags & DSS_DEBUG)
1148
sfprintf(sfstderr, " attr size %4u available %d\n", size, (int)(state->end - end) + size);
1149
if (end > state->end)
1150
{
1151
/*
1152
* old mrtd had a 4 byte short bug that we fix here
1153
* hoping that no other corruption is 4 bytes short
1154
* this costs a memcpy -- how much buggy data is there?
1155
*/
1156
1157
r = end - state->end;
1158
if (r == 4)
1159
{
1160
n = r + state->end - state->buf;
1161
if (n > state->bugsiz)
1162
{
1163
if (!(state->bugbuf = vmnewof(file->dss->vm, state->bugbuf, char, n, 0)))
1164
{
1165
if (disc->errorf)
1166
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space [bugbuf]");
1167
return -1;
1168
}
1169
}
1170
memcpy(state->bugbuf, state->buf, state->end - state->buf);
1171
state->buf = state->bugbuf;
1172
end = state->end = state->buf + n;
1173
if (sfread(file->io, end - r, r) != (ssize_t)r)
1174
{
1175
if (disc->errorf)
1176
(*disc->errorf)(NiL, disc, 2, "header size invalid -- 4 byte bug workaround failed");
1177
return -1;
1178
}
1179
}
1180
else
1181
{
1182
if (disc->errorf && !(file->dss->flags & DSS_QUIET))
1183
(*disc->errorf)(NiL, disc, 1, "%u: invalid path attribute buffer size -- %d available", size, (int)(state->end - state->buf));
1184
end = state->end;
1185
}
1186
}
1187
while ((x = attr(file, state, rp, end, disc)) > 0);
1188
return x;
1189
}
1190
1191
static void
1192
done(Mrtstate_t* state, Bgproute_t* rp, Dssrecord_t* record, Dssdisc_t* disc)
1193
{
1194
char* s;
1195
1196
rp->attr |= state->group;
1197
state->group |= BGP_PART;
1198
if (state->unknown.size)
1199
{
1200
BGPALLOC(rp, state->size, char, s, state->unknown.size, &rp->unknown, "unknown attributes", disc);
1201
memcpy(s, state->unknown.data, state->unknown.size);
1202
state->unknown.size = 0;
1203
}
1204
if (state->osize > state->size)
1205
memset(rp->data + state->size, 0, state->osize - state->size);
1206
record->data = rp;
1207
record->size = rp->size = BGP_FIXED + state->size;
1208
}
1209
1210
/*
1211
* mrt readf
1212
*/
1213
1214
static int
1215
mrtread(register Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
1216
{
1217
register Mrtstate_t* state = (Mrtstate_t*)file->data;
1218
register Bgproute_t* rp;
1219
register int i;
1220
int j;
1221
int afi;
1222
int safi;
1223
Bgpnum_t n;
1224
unsigned int type;
1225
unsigned int subtype;
1226
uint32_t size;
1227
uint32_t addr;
1228
uintmax_t skip = 0;
1229
1230
if (file->dss->flags & DSS_DEBUG)
1231
{
1232
sfsync(sfstdout);
1233
sfsync(sfstderr);
1234
}
1235
for (;;)
1236
{
1237
switch (state->state)
1238
{
1239
case 0:
1240
ANONYMIZE_FLUSH(file, disc);
1241
if (!(state->buf = (char*)sfreserve(file->io, MRT_HEAD, -1)))
1242
break;
1243
state->message++;
1244
state->group ^= BGP_MESSAGE;
1245
state->group &= ~BGP_PART;
1246
state->time = AET(state->buf);
1247
type = BE2(state->buf + 4);
1248
subtype = BE2(state->buf + 6);
1249
size = BE4(state->buf + 8);
1250
ANONYMIZE_HEAD(state->buf, MRT_HEAD);
1251
if (file->dss->flags & DSS_DEBUG)
1252
sfprintf(sfstderr, "message %6lu record %6lu time %8lu %s.%s size %I*u offset %I*u\n", state->message, file->count, state->time, symbol(GROUP_MESSAGE, type), symbol(type, subtype), sizeof(size), size, sizeof(file->offset), file->offset + skip);
1253
if (!(state->buf = (char*)sfreserve(file->io, size, -1)))
1254
break;
1255
skip += size;
1256
PAYLOAD(file, state->buf, size);
1257
ANONYMIZE_DATA(state->buf, size);
1258
state->end = state->buf + size;
1259
switch (type)
1260
{
1261
case MRT_I_AM_DEAD:
1262
case MRT_BGP:
1263
INIT(state, rp);
1264
rp->src_as = AE2(state->buf + 0);
1265
rp->src_addr.v4 = AE4(state->buf + 2);
1266
if (type == MRT_I_AM_DEAD)
1267
{
1268
state->buf += 6;
1269
subtype = MRT_BGP_STATE_CHANGE;
1270
}
1271
else
1272
{
1273
rp->dst_as = AE2(state->buf + 6);
1274
rp->dst_addr.v4 = AE4(state->buf + 8);
1275
state->buf += 12;
1276
}
1277
switch (subtype)
1278
{
1279
case MRT_BGP_PREF_UPDATE:
1280
type = MRT_BGP_MESSAGE_UPDATE;
1281
break;
1282
case MRT_BGP_STATE_CHANGE:
1283
type = MRT_BGP_MESSAGE_STATE_CHANGE;
1284
break;
1285
case MRT_BGP_OPEN:
1286
type = MRT_BGP_MESSAGE_OPEN;
1287
break;
1288
case MRT_BGP_NOTIFY:
1289
type = MRT_BGP_MESSAGE_NOTIFY;
1290
break;
1291
case MRT_BGP_KEEPALIVE:
1292
type = MRT_BGP_MESSAGE_KEEPALIVE;
1293
break;
1294
default:
1295
continue;
1296
}
1297
state->state = STATE_BGP_MESSAGE;
1298
break;
1299
case MRT_TABLE_DUMP:
1300
INIT(state, rp);
1301
state->buf += 4;
1302
switch (subtype)
1303
{
1304
case MRT_TABLE_IPV6_UNICAST:
1305
rp->afi = MRT_AFI_IPV6;
1306
rp->safi = MRT_SAFI_NLRI_UCAST_FORWARD;
1307
break;
1308
default:
1309
rp->afi = MRT_AFI_IPV4;
1310
rp->safi = MRT_SAFI_NLRI_UCAST_FORWARD;
1311
break;
1312
}
1313
state->state = STATE_TABLE_DUMP;
1314
break;
1315
case MRT_TABLE_DUMP_V2:
1316
afi = safi = 0;
1317
switch (subtype)
1318
{
1319
case MRT_TABLE_PEER_INDEX_TABLE:
1320
i = BE2(state->buf + 4);
1321
state->buf += 6 + i;
1322
state->peers = BE2(state->buf);
1323
state->buf += 2;
1324
if (state->peers > state->maxpeers)
1325
{
1326
state->maxpeers = roundof(state->peers, 32);
1327
if (!(state->peer = vmnewof(file->dss->vm, state->peer, Mrtpeer_t, state->maxpeers, 0)))
1328
{
1329
if (disc->errorf)
1330
(*disc->errorf)(NiL, disc, ERROR_SYSTEM|2, "out of space");
1331
return -1;
1332
}
1333
}
1334
if (file->dss->flags & DSS_DEBUG)
1335
sfprintf(sfstderr, " peers %d\n", state->peers);
1336
for (i = 0; i < state->peers; i++)
1337
{
1338
state->peer[i].type = BE1(state->buf++);
1339
state->peer[i].bgpid = AE4(state->buf);
1340
state->buf += 4;
1341
if (state->peer[i].type & PEER_IPV6)
1342
{
1343
AE(state->peer[i].addr.v6, state->buf, IP6ADDR);
1344
state->buf += IP6ADDR;
1345
}
1346
else
1347
{
1348
state->peer[i].addr.v4 = AE4(state->buf);
1349
state->buf += 4;
1350
}
1351
if (state->peer[i].type & PEER_AS32)
1352
{
1353
state->peer[i].as = AE4(state->buf);
1354
state->buf += 4;
1355
}
1356
else
1357
{
1358
state->peer[i].as = AE2(state->buf);
1359
state->buf += 2;
1360
}
1361
if (file->dss->flags & DSS_DEBUG)
1362
sfprintf(sfstderr, " peer %2d %8d %s\n", i, state->peer[i].as, (state->peer[i].type & PEER_IPV6) ? fmtip6(state->peer[i].addr.v6, -1) : fmtip4(state->peer[i].addr.v4, -1));
1363
}
1364
continue;
1365
case MRT_TABLE_RIB_IPV4_UNICAST:
1366
afi = MRT_AFI_IPV4;
1367
safi = MRT_SAFI_NLRI_UCAST_FORWARD;
1368
break;
1369
case MRT_TABLE_RIB_IPV4_MULTICAST:
1370
afi = MRT_AFI_IPV4;
1371
safi = MRT_SAFI_NLRI_MCAST_FORWARD;
1372
break;
1373
case MRT_TABLE_RIB_IPV6_UNICAST:
1374
afi = MRT_AFI_IPV6;
1375
safi = MRT_SAFI_NLRI_UCAST_FORWARD;
1376
break;
1377
case MRT_TABLE_RIB_IPV6_MULTICAST:
1378
afi = MRT_AFI_IPV6;
1379
safi = MRT_SAFI_NLRI_MCAST_FORWARD;
1380
break;
1381
case MRT_TABLE_RIB_GENERIC:
1382
state->state = STATE_TABLE_DUMP_V2_RIB_GENERIC;
1383
break;
1384
default:
1385
continue;
1386
}
1387
INIT(state, rp);
1388
rp->type = BGP_TYPE_table_dump;
1389
j = AE4(state->buf); /* sequence */
1390
state->buf += 4;
1391
rp->set &= ~(BGP_SET_prefixv4|BGP_SET_prefixv6);
1392
if (state->state == STATE_TABLE_DUMP_V2_RIB_GENERIC)
1393
{
1394
rp->afi = BE2(state->buf);
1395
rp->safi = BE1(state->buf + 2);
1396
state->buf += 3;
1397
if (file->dss->flags & DSS_DEBUG)
1398
sfprintf(sfstderr, " %s %s/%s sequence %u\n", symbol(GROUP_STATE, state->state), symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), j);
1399
if (nlri(file, state, rp, state->end, disc))
1400
return -1;
1401
}
1402
else
1403
{
1404
rp->afi = afi;
1405
rp->safi = safi;
1406
state->state = STATE_TABLE_DUMP_V2_RIB;
1407
if (file->dss->flags & DSS_DEBUG)
1408
sfprintf(sfstderr, " %s %s/%s sequence %u\n", symbol(GROUP_STATE, state->state), symbol(GROUP_AFI, rp->afi), symbol(GROUP_SAFI, rp->safi), j);
1409
if (prefix(file, state, rp, -1, state->end, disc))
1410
continue;
1411
}
1412
state->entries = BE2(state->buf);
1413
state->buf += 2;
1414
if (file->dss->flags & DSS_DEBUG)
1415
sfprintf(sfstderr, " table entries %u\n", state->entries);
1416
continue;
1417
case MRT_BGP4MP:
1418
case MRT_BGP4MP_ET:
1419
INIT(state, rp);
1420
if (type == MRT_BGP4MP_ET)
1421
{
1422
rp->usec = BE4(state->buf + 0);
1423
state->buf += 4;
1424
}
1425
switch (subtype)
1426
{
1427
case MRT_BGP4MP_MESSAGE_AS4:
1428
case MRT_BGP4MP_STATE_CHANGE_AS4:
1429
case MRT_BGP4MP_MESSAGE_AS4_LOCAL:
1430
rp->src_as32 = AE4(state->buf + 0);
1431
rp->dst_as32 = AE4(state->buf + 4);
1432
state->buf += 8;
1433
break;
1434
default:
1435
rp->src_as = AE2(state->buf + 0);
1436
rp->dst_as = AE2(state->buf + 2);
1437
state->buf += 4;
1438
break;
1439
}
1440
if (BE2(state->buf + 2) == MRT_AFI_IPV6)
1441
{
1442
rp->attr |= BGP_ipv6;
1443
rp->set |= BGP_SET_src_addrv6;
1444
AE(rp->src_addr.v6, state->buf + 4, sizeof(rp->src_addr.v6));
1445
AE(rp->dst_addr.v6, state->buf + 20, sizeof(rp->dst_addr.v6));
1446
state->buf += 36;
1447
}
1448
else
1449
{
1450
rp->src_addr.v4 = AE4(state->buf + 4);
1451
rp->dst_addr.v4 = AE4(state->buf + 8);
1452
state->buf += 12;
1453
}
1454
switch (subtype)
1455
{
1456
case MRT_BGP4MP_STATE_CHANGE:
1457
case MRT_BGP4MP_STATE_CHANGE_AS4:
1458
rp->type = BGP_TYPE_state_change;
1459
rp->old_state = BE2(state->buf + 0);
1460
rp->new_state = BE2(state->buf + 2);
1461
DONE(state, rp, record, disc);
1462
return 1;
1463
case MRT_BGP4MP_MESSAGE:
1464
case MRT_BGP4MP_MESSAGE_AS4:
1465
case MRT_BGP4MP_MESSAGE_LOCAL:
1466
case MRT_BGP4MP_MESSAGE_AS4_LOCAL:
1467
case MRT_BGP4MP_EXTENSION_20:
1468
state->buf += 16;
1469
state->state = STATE_BGP_HEADER;
1470
break;
1471
default:
1472
DONE(state, rp, record, disc);
1473
return 1;
1474
}
1475
break;
1476
}
1477
continue;
1478
case STATE_BGP_HEADER:
1479
type = BE1(state->buf + 2);
1480
state->buf += 3;
1481
state->state = STATE_BGP_MESSAGE;
1482
/*FALLTHROUGH*/
1483
case STATE_BGP_MESSAGE:
1484
NEXT(state, rp);
1485
if (file->dss->flags & DSS_DEBUG)
1486
sfprintf(sfstderr, " %s.%s\n", symbol(GROUP_STATE, state->state), symbol(GROUP_BGP_MESSAGE, type));
1487
switch (type)
1488
{
1489
case MRT_BGP_MESSAGE_STATE_CHANGE:
1490
state->state = 0;
1491
rp->type = BGP_TYPE_state_change;
1492
rp->old_state = BE2(state->buf + 0);
1493
rp->new_state = BE2(state->buf + 2);
1494
DONE(state, rp, record, disc);
1495
return 1;
1496
case MRT_BGP_MESSAGE_OPEN:
1497
state->state = 0;
1498
rp->type = BGP_TYPE_open;
1499
rp->open_version = BE1(state->buf + 0);
1500
rp->open_as = AE2(state->buf + 1);
1501
rp->open_hold = AE2(state->buf + 3);
1502
rp->open_id = AE4(state->buf + 5);
1503
rp->open_size = BE1(state->buf + 9);
1504
if (rp->open_size > (state->end - (state->buf + 10)))
1505
rp->open_size = state->end - (state->buf + 10);
1506
AE(rp->data, state->buf + 10, rp->open_size);
1507
state->size = rp->open_size;
1508
DONE(state, rp, record, disc);
1509
return 1;
1510
case MRT_BGP_MESSAGE_UPDATE:
1511
break;
1512
case MRT_BGP_MESSAGE_NOTIFY:
1513
state->state = 0;
1514
rp->type = BGP_TYPE_notification;
1515
rp->note_code = BE1(state->buf + 0);
1516
rp->note_subcode = BE1(state->buf + 1);
1517
rp->note_size = state->end - (state->buf + 2);
1518
if (rp->note_size > sizeof(rp->data))
1519
rp->note_size = sizeof(rp->data);
1520
AE(rp->data, state->buf + 2, rp->note_size);
1521
state->size = rp->note_size;
1522
DONE(state, rp, record, disc);
1523
return 1;
1524
case MRT_BGP_MESSAGE_KEEPALIVE:
1525
state->state = 0;
1526
rp->type = BGP_TYPE_keepalive;
1527
DONE(state, rp, record, disc);
1528
return 1;
1529
default:
1530
state->state = 0;
1531
continue;
1532
}
1533
size = BE2(state->buf);
1534
state->nxt = (state->buf += 2) + size;
1535
rp->type = BGP_TYPE_withdraw;
1536
rp->attr = BGP_best|BGP_valid;
1537
state->state = STATE_BGP_ATTRIBUTES;
1538
/*FALLTHROUGH*/
1539
case STATE_BGP_ATTRIBUTES:
1540
NEXT(state, rp);
1541
rp->set &= ~(BGP_SET_prefixv4|BGP_SET_prefixv6);
1542
if (state->buf < state->nxt)
1543
{
1544
if (file->dss->flags & DSS_DEBUG)
1545
sfprintf(sfstderr, " %s size %lu\n", symbol(GROUP_STATE, state->state), state->nxt - state->buf);
1546
rp->bits = BE1(state->buf++);
1547
i = rp->bits;
1548
if (i & 7)
1549
i += 8;
1550
i >>= 3;
1551
addr = 0;
1552
for (j = 0; j < i; j++)
1553
addr = (addr << 8) | AE1(state->buf++);
1554
for (; j < 4; j++)
1555
addr <<= 8;
1556
rp->addr.v4 = addr;
1557
rp->set |= BGP_SET_prefixv4;
1558
DONE(state, rp, record, disc);
1559
return 1;
1560
}
1561
state->state = STATE_BGP_ANNOUNCE;
1562
if (pathattr(file, state, rp, disc))
1563
return -1;
1564
if (state->state)
1565
continue;
1566
DONE(state, rp, record, disc);
1567
return 1;
1568
case STATE_BGP_ANNOUNCE:
1569
NEXT(state, rp);
1570
rp->type = BGP_TYPE_announce;
1571
state->state = STATE_BGP_PREFIX;
1572
goto state_bgp_prefix;
1573
case STATE_BGP_PREFIX:
1574
NEXT(state, rp);
1575
state_bgp_prefix:
1576
rp->set &= ~(BGP_SET_prefixv4|BGP_SET_prefixv6);
1577
if (state->buf < state->end)
1578
{
1579
if (file->dss->flags & DSS_DEBUG)
1580
sfprintf(sfstderr, " %s size %lu\n", symbol(GROUP_STATE, state->state), state->end - state->buf);
1581
rp->bits = BE1(state->buf++);
1582
i = rp->bits;
1583
if (i & 7)
1584
i += 8;
1585
i >>= 3;
1586
addr = 0;
1587
for (j = 0; j < i; j++)
1588
addr = (addr << 8) | AE1(state->buf++);
1589
for (; j < 4; j++)
1590
addr <<= 8;
1591
rp->addr.v4 = addr;
1592
rp->set |= BGP_SET_prefixv4;
1593
DONE(state, rp, record, disc);
1594
return 1;
1595
}
1596
state->state = 0;
1597
continue;
1598
case STATE_BGP_NLRI:
1599
if (state->buf < state->end)
1600
{
1601
NEXT(state, rp);
1602
if (nlri(file, state, rp, state->end, disc))
1603
return -1;
1604
if (state->buf >= state->end)
1605
{
1606
state->end = state->nxt;
1607
state->state = state->push;
1608
}
1609
DONE(state, rp, record, disc);
1610
return 1;
1611
}
1612
state->end = state->nxt;
1613
state->state = STATE_BGP_ATTR;
1614
continue;
1615
case STATE_BGP_ATTR:
1616
NEXT(state, rp);
1617
while ((i = attr(file, state, rp, state->end, disc)) > 0);
1618
if (i < 0)
1619
return -1;
1620
if (state->state == STATE_BGP_ATTR)
1621
state->state = state->push;
1622
continue;
1623
case STATE_TABLE_DUMP:
1624
while (state->buf < state->end)
1625
{
1626
afi = rp->afi;
1627
safi = rp->safi;
1628
INIT(state, rp);
1629
rp->afi = afi;
1630
rp->safi = safi;
1631
rp->type = BGP_TYPE_table_dump;
1632
rp->attr = BGP_valid;
1633
if (rp->afi == MRT_AFI_IPV6)
1634
{
1635
if (state->best != state->message)
1636
{
1637
state->best = state->message;
1638
rp->attr |= BGP_best;
1639
}
1640
else if (memcmp(rp->prefixv6, state->buf, sizeof(rp->prefixv6)))
1641
rp->attr |= BGP_best;
1642
AE(rp->prefixv6, state->buf, sizeof(rp->prefixv6));
1643
rp->stamp = AET(state->buf + 18);
1644
AE(rp->src_addr.v6, state->buf + 22, sizeof(rp->src_addr.v6));
1645
rp->src_as = AE2(state->buf + 38);
1646
state->buf += 40;
1647
rp->attr |= BGP_ipv6;
1648
rp->set |= BGP_SET_prefixv6|BGP_SET_src_addrv6;
1649
}
1650
else
1651
{
1652
n = AE4(state->buf);
1653
if (state->best != state->message)
1654
{
1655
state->best = state->message;
1656
rp->attr |= BGP_best;
1657
}
1658
else if (rp->addr.v4 != n)
1659
rp->attr |= BGP_best;
1660
rp->addr.v4 = n;
1661
rp->bits = BE1(state->buf + 4);
1662
rp->stamp = AET(state->buf + 6);
1663
rp->src_addr.v4 = AE4(state->buf + 10);
1664
rp->src_as = AE2(state->buf + 14);
1665
state->buf += 16;
1666
}
1667
if (pathattr(file, state, rp, disc))
1668
return -1;
1669
if (state->state != STATE_TABLE_DUMP)
1670
break;
1671
DONE(state, rp, record, disc);
1672
return 1;
1673
}
1674
state->state = 0;
1675
continue;
1676
case STATE_TABLE_DUMP_V2_RIB:
1677
case STATE_TABLE_DUMP_V2_RIB_GENERIC:
1678
for (;;)
1679
{
1680
if (state->buf >= state->end || state->entries-- <= 0)
1681
{
1682
state->state = 0;
1683
break;
1684
}
1685
PAYLOAD(file, state->buf, state->end - state->buf);
1686
NEXT(state, rp);
1687
rp->type = BGP_TYPE_table_dump;
1688
rp->attr = BGP_valid;
1689
i = BE2(state->buf);
1690
state->buf += 2;
1691
rp->stamp = AET(state->buf);
1692
state->buf += 4;
1693
if (state->peer[i].type & PEER_IPV6)
1694
{
1695
rp->attr |= BGP_ipv6;
1696
rp->set |= BGP_SET_src_addrv6;
1697
BE(rp->src_addr.v6, state->peer[i].addr.v6, sizeof(rp->src_addr.v6));
1698
}
1699
else
1700
rp->src_addr.v4 = state->peer[i].addr.v4;
1701
if (state->peer[i].type & PEER_AS32)
1702
rp->src_as32 = state->peer[i].as;
1703
else
1704
rp->src_as = state->peer[i].as;
1705
if (pathattr(file, state, rp, disc))
1706
return -1;
1707
if (state->state == STATE_BGP_NLRI)
1708
break;
1709
DONE(state, rp, record, disc);
1710
return 1;
1711
}
1712
continue;
1713
}
1714
break;
1715
}
1716
return 0;
1717
}
1718
1719
/*
1720
* mrt writef
1721
*/
1722
1723
static int
1724
mrtwrite(Dssfile_t* file, Dssrecord_t* record, Dssdisc_t* disc)
1725
{
1726
if (record)
1727
ANONYMIZE_WRITE(file, record, disc);
1728
if (disc->errorf)
1729
(*disc->errorf)(NiL, disc, 2, "%s: record write not implemented", file->format->name);
1730
return -1;
1731
}
1732
1733
/*
1734
* mrt closef
1735
*/
1736
1737
static int
1738
mrtclose(Dssfile_t* file, Dssdisc_t* disc)
1739
{
1740
if (!file->data)
1741
return -1;
1742
vmfree(file->dss->vm, file->data);
1743
return 0;
1744
}
1745
1746
Dssformat_t ANONYMIZE_FORMAT =
1747
{
1748
"mrt" ANONYMIZE_FORMAT_NAME,
1749
"mrt binary format" ANONYMIZE_FORMAT_DESCRIPTION " (2011-09-11) -T0x0010 enables payload trace [http://tools.ietf.org/html/draft-ietf-grow-mrt-15]",
1750
CXH,
1751
mrtident,
1752
mrtopen,
1753
mrtread,
1754
mrtwrite,
1755
dss_no_fseek,
1756
mrtclose,
1757
0,
1758
0,
1759
ANONYMIZE_NEXT
1760
};
1761
1762