GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/printconf.c Lines: 0 402 0.0 %
Date: 2016-12-06 Branches: 0 301 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: printconf.c,v 1.97 2016/07/13 20:07:38 benno Exp $	*/
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA, PROFITS OR MIND, WHETHER IN
15
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <limits.h>
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
24
#include "bgpd.h"
25
#include "mrt.h"
26
#include "session.h"
27
#include "rde.h"
28
29
void		 print_op(enum comp_ops);
30
void		 print_community(int, int);
31
void		 print_extcommunity(struct filter_extcommunity *);
32
void		 print_origin(u_int8_t);
33
void		 print_set(struct filter_set_head *);
34
void		 print_mainconf(struct bgpd_config *);
35
void		 print_rdomain_targets(struct filter_set_head *, const char *);
36
void		 print_rdomain(struct rdomain *);
37
const char	*print_af(u_int8_t);
38
void		 print_network(struct network_config *, const char *);
39
void		 print_peer(struct peer_config *, struct bgpd_config *,
40
		    const char *);
41
const char	*print_auth_alg(u_int8_t);
42
const char	*print_enc_alg(u_int8_t);
43
void		 print_announce(struct peer_config *, const char *);
44
void		 print_as(struct filter_rule *);
45
void		 print_rule(struct peer *, struct filter_rule *);
46
const char	*mrt_type(enum mrt_type);
47
void		 print_mrt(struct bgpd_config *, u_int32_t, u_int32_t,
48
		    const char *, const char *);
49
void		 print_groups(struct bgpd_config *, struct peer *);
50
int		 peer_compare(const void *, const void *);
51
52
void
53
print_op(enum comp_ops op)
54
{
55
	switch (op) {
56
	case OP_RANGE:
57
		printf("-");
58
		break;
59
	case OP_XRANGE:
60
		printf("><");
61
		break;
62
	case OP_EQ:
63
		printf("=");
64
		break;
65
	case OP_NE:
66
		printf("!=");
67
		break;
68
	case OP_LE:
69
		printf("<=");
70
		break;
71
	case OP_LT:
72
		printf("<");
73
		break;
74
	case OP_GE:
75
		printf(">=");
76
		break;
77
	case OP_GT:
78
		printf(">");
79
		break;
80
	default:
81
		printf("?");
82
		break;
83
	}
84
}
85
86
void
87
print_community(int as, int type)
88
{
89
	if (as == COMMUNITY_ANY)
90
		printf("*:");
91
	else if (as == COMMUNITY_NEIGHBOR_AS)
92
		printf("neighbor-as:");
93
	else
94
		printf("%u:", (unsigned int)as);
95
96
	if (type == COMMUNITY_ANY)
97
		printf("* ");
98
	else if (type == COMMUNITY_NEIGHBOR_AS)
99
		printf("neighbor-as ");
100
	else
101
		printf("%d ", type);
102
}
103
104
void
105
print_extcommunity(struct filter_extcommunity *c)
106
{
107
	switch (c->type & EXT_COMMUNITY_VALUE) {
108
	case EXT_COMMUNITY_TWO_AS:
109
		printf("%s %hu:%u ", log_ext_subtype(c->subtype),
110
		    c->data.ext_as.as, c->data.ext_as.val);
111
		break;
112
	case EXT_COMMUNITY_IPV4:
113
		printf("%s %s:%u ", log_ext_subtype(c->subtype),
114
		    inet_ntoa(c->data.ext_ip.addr), c->data.ext_ip.val);
115
		break;
116
	case EXT_COMMUNITY_FOUR_AS:
117
		printf("%s %s:%u ", log_ext_subtype(c->subtype),
118
		    log_as(c->data.ext_as4.as4), c->data.ext_as.val);
119
		break;
120
	case EXT_COMMUNITY_OPAQUE:
121
		printf("%s 0x%llx ", log_ext_subtype(c->subtype),
122
		    c->data.ext_opaq);
123
		break;
124
	default:
125
		printf("0x%x 0x%llx ", c->type, c->data.ext_opaq);
126
		break;
127
	}
128
}
129
130
void
131
print_origin(u_int8_t o)
132
{
133
	if (o == ORIGIN_IGP)
134
		printf("igp ");
135
	else if (o == ORIGIN_EGP)
136
		printf("egp ");
137
	else if (o == ORIGIN_INCOMPLETE)
138
		printf("incomplete ");
139
	else
140
		printf("%u ", o);
141
}
142
143
void
144
print_set(struct filter_set_head *set)
145
{
146
	struct filter_set	*s;
147
148
	if (TAILQ_EMPTY(set))
149
		return;
150
151
	printf("set { ");
152
	TAILQ_FOREACH(s, set, entry) {
153
		switch (s->type) {
154
		case ACTION_SET_LOCALPREF:
155
			printf("localpref %u ", s->action.metric);
156
			break;
157
		case ACTION_SET_RELATIVE_LOCALPREF:
158
			printf("localpref %+d ", s->action.relative);
159
			break;
160
		case ACTION_SET_MED:
161
			printf("metric %u ", s->action.metric);
162
			break;
163
		case ACTION_SET_RELATIVE_MED:
164
			printf("metric %+d ", s->action.relative);
165
			break;
166
		case ACTION_SET_WEIGHT:
167
			printf("weight %u ", s->action.metric);
168
			break;
169
		case ACTION_SET_RELATIVE_WEIGHT:
170
			printf("weight %+d ", s->action.relative);
171
			break;
172
		case ACTION_SET_NEXTHOP:
173
			printf("nexthop %s ", log_addr(&s->action.nexthop));
174
			break;
175
		case ACTION_SET_NEXTHOP_REJECT:
176
			printf("nexthop reject ");
177
			break;
178
		case ACTION_SET_NEXTHOP_BLACKHOLE:
179
			printf("nexthop blackhole ");
180
			break;
181
		case ACTION_SET_NEXTHOP_NOMODIFY:
182
			printf("nexthop no-modify ");
183
			break;
184
		case ACTION_SET_NEXTHOP_SELF:
185
			printf("nexthop self ");
186
			break;
187
		case ACTION_SET_PREPEND_SELF:
188
			printf("prepend-self %u ", s->action.prepend);
189
			break;
190
		case ACTION_SET_PREPEND_PEER:
191
			printf("prepend-neighbor %u ", s->action.prepend);
192
			break;
193
		case ACTION_DEL_COMMUNITY:
194
			printf("community delete ");
195
			print_community(s->action.community.as,
196
			    s->action.community.type);
197
			printf(" ");
198
			break;
199
		case ACTION_SET_COMMUNITY:
200
			printf("community ");
201
			print_community(s->action.community.as,
202
			    s->action.community.type);
203
			printf(" ");
204
			break;
205
		case ACTION_PFTABLE:
206
			printf("pftable %s ", s->action.pftable);
207
			break;
208
		case ACTION_RTLABEL:
209
			printf("rtlabel %s ", s->action.rtlabel);
210
			break;
211
		case ACTION_SET_ORIGIN:
212
			printf("origin ");
213
			print_origin(s->action.origin);
214
			break;
215
		case ACTION_RTLABEL_ID:
216
		case ACTION_PFTABLE_ID:
217
			/* not possible */
218
			printf("king bula saiz: config broken");
219
			break;
220
		case ACTION_SET_EXT_COMMUNITY:
221
			printf("ext-community ");
222
			print_extcommunity(&s->action.ext_community);
223
			break;
224
		case ACTION_DEL_EXT_COMMUNITY:
225
			printf("ext-community delete ");
226
			print_extcommunity(&s->action.ext_community);
227
			break;
228
		}
229
	}
230
	printf("}");
231
}
232
233
void
234
print_mainconf(struct bgpd_config *conf)
235
{
236
	struct in_addr		 ina;
237
	struct listen_addr	*la;
238
239
	printf("AS %s", log_as(conf->as));
240
	if (conf->as > USHRT_MAX && conf->short_as != AS_TRANS)
241
		printf(" %u", conf->short_as);
242
	ina.s_addr = conf->bgpid;
243
	printf("\nrouter-id %s\n", inet_ntoa(ina));
244
245
	printf("socket \"%s\"\n", conf->csock);
246
	if (conf->rcsock)
247
		printf("socket \"%s\" restricted\n", conf->rcsock);
248
	if (conf->holdtime)
249
		printf("holdtime %u\n", conf->holdtime);
250
	if (conf->min_holdtime)
251
		printf("holdtime min %u\n", conf->min_holdtime);
252
	if (conf->connectretry)
253
		printf("connect-retry %u\n", conf->connectretry);
254
255
	if (conf->flags & BGPD_FLAG_NO_EVALUATE)
256
		printf("route-collector yes\n");
257
258
	if (conf->flags & BGPD_FLAG_DECISION_ROUTEAGE)
259
		printf("rde route-age evaluate\n");
260
261
	if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS)
262
		printf("rde med compare always\n");
263
264
	if (conf->log & BGPD_LOG_UPDATES)
265
		printf("log updates\n");
266
267
	TAILQ_FOREACH(la, conf->listen_addrs, entry)
268
		printf("listen on %s\n",
269
		    log_sockaddr((struct sockaddr *)&la->sa));
270
271
	if (conf->flags & BGPD_FLAG_NEXTHOP_BGP)
272
		printf("nexthop qualify via bgp\n");
273
	if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT)
274
		printf("nexthop qualify via default\n");
275
	printf("fib-priority %hhu", conf->fib_priority);
276
}
277
278
void
279
print_rdomain_targets(struct filter_set_head *set, const char *tgt)
280
{
281
	struct filter_set	*s;
282
	TAILQ_FOREACH(s, set, entry) {
283
		printf("\t%s ", tgt);
284
		print_extcommunity(&s->action.ext_community);
285
		printf("\n");
286
	}
287
}
288
289
void
290
print_rdomain(struct rdomain *r)
291
{
292
	struct network *n;
293
294
	printf("rdomain %u {\n", r->rtableid);
295
	if (*r->descr)
296
		printf("\tdescr \"%s\"\n", r->descr);
297
	if (r->flags & F_RIB_NOFIBSYNC)
298
		printf("\tfib-update no\n");
299
	else
300
		printf("\tfib-update yes\n");
301
	printf("\tdepend on %s\n", r->ifmpe);
302
303
	TAILQ_FOREACH(n, &r->net_l, entry)
304
		print_network(&n->net, "\t");
305
306
	printf("\n\t%s\n", log_rd(r->rd));
307
308
	print_rdomain_targets(&r->export, "export-target");
309
	print_rdomain_targets(&r->import, "import-target");
310
311
	printf("}\n");
312
}
313
314
const char *
315
print_af(u_int8_t aid)
316
{
317
	/*
318
	 * Hack around the fact that aid2str() will return "IPv4 unicast"
319
	 * for AID_INET. AID_INET and AID_INET6 need special handling and
320
	 * the other AID should never end up here (at least for now).
321
	 */
322
	if (aid == AID_INET)
323
		return ("inet");
324
	if (aid == AID_INET6)
325
		return ("inet6");
326
	return (aid2str(aid));
327
}
328
329
void
330
print_network(struct network_config *n, const char *c)
331
{
332
	switch (n->type) {
333
	case NETWORK_STATIC:
334
		printf("%snetwork %s static", c, print_af(n->prefix.aid));
335
		break;
336
	case NETWORK_CONNECTED:
337
		printf("%snetwork %s connected", c, print_af(n->prefix.aid));
338
		break;
339
	default:
340
		printf("%snetwork %s/%u", c, log_addr(&n->prefix),
341
		    n->prefixlen);
342
		break;
343
	}
344
	if (!TAILQ_EMPTY(&n->attrset))
345
		printf(" ");
346
	print_set(&n->attrset);
347
	printf("\n");
348
}
349
350
void
351
print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c)
352
{
353
	char		*method;
354
	struct in_addr	 ina;
355
356
	if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) ||
357
	    (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128))
358
		printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr),
359
		    p->remote_masklen);
360
	else
361
		printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr));
362
	if (p->descr[0])
363
		printf("%s\tdescr \"%s\"\n", c, p->descr);
364
	if (p->rib[0])
365
		printf("%s\trib \"%s\"\n", c, p->rib);
366
	if (p->remote_as)
367
		printf("%s\tremote-as %s\n", c, log_as(p->remote_as));
368
	if (p->down)
369
		printf("%s\tdown\n", c);
370
	if (p->distance > 1)
371
		printf("%s\tmultihop %u\n", c, p->distance);
372
	if (p->passive)
373
		printf("%s\tpassive\n", c);
374
	if (p->local_addr.aid)
375
		printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr));
376
	if (p->max_prefix) {
377
		printf("%s\tmax-prefix %u", c, p->max_prefix);
378
		if (p->max_prefix_restart)
379
			printf(" restart %u", p->max_prefix_restart);
380
		printf("\n");
381
	}
382
	if (p->holdtime)
383
		printf("%s\tholdtime %u\n", c, p->holdtime);
384
	if (p->min_holdtime)
385
		printf("%s\tholdtime min %u\n", c, p->min_holdtime);
386
	if (p->announce_capa == 0)
387
		printf("%s\tannounce capabilities no\n", c);
388
	if (p->capabilities.refresh == 0)
389
		printf("%s\tannounce refresh no\n", c);
390
	if (p->capabilities.grestart.restart == 0)
391
		printf("%s\tannounce restart no\n", c);
392
	if (p->capabilities.as4byte == 0)
393
		printf("%s\tannounce as4byte no\n", c);
394
	if (p->announce_type == ANNOUNCE_SELF)
395
		printf("%s\tannounce self\n", c);
396
	else if (p->announce_type == ANNOUNCE_NONE)
397
		printf("%s\tannounce none\n", c);
398
	else if (p->announce_type == ANNOUNCE_ALL)
399
		printf("%s\tannounce all\n", c);
400
	else if (p->announce_type == ANNOUNCE_DEFAULT_ROUTE)
401
		printf("%s\tannounce default-route\n", c);
402
	else
403
		printf("%s\tannounce ???\n", c);
404
	if (p->enforce_as == ENFORCE_AS_ON)
405
		printf("%s\tenforce neighbor-as yes\n", c);
406
	else
407
		printf("%s\tenforce neighbor-as no\n", c);
408
	if (p->reflector_client) {
409
		if (conf->clusterid == 0)
410
			printf("%s\troute-reflector\n", c);
411
		else {
412
			ina.s_addr = conf->clusterid;
413
			printf("%s\troute-reflector %s\n", c,
414
			    inet_ntoa(ina));
415
		}
416
	}
417
	if (p->demote_group[0])
418
		printf("%s\tdemote %s\n", c, p->demote_group);
419
	if (p->if_depend[0])
420
		printf("%s\tdepend on \"%s\"\n", c, p->if_depend);
421
	if (p->flags & PEERFLAG_TRANS_AS)
422
		printf("%s\ttransparent-as yes\n", c);
423
424
	if (p->flags & PEERFLAG_LOG_UPDATES)
425
		printf("%s\tlog updates\n", c);
426
427
	if (p->auth.method == AUTH_MD5SIG)
428
		printf("%s\ttcp md5sig\n", c);
429
	else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP ||
430
	    p->auth.method == AUTH_IPSEC_MANUAL_AH) {
431
		if (p->auth.method == AUTH_IPSEC_MANUAL_ESP)
432
			method = "esp";
433
		else
434
			method = "ah";
435
436
		printf("%s\tipsec %s in spi %u %s XXXXXX", c, method,
437
		    p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in));
438
		if (p->auth.enc_alg_in)
439
			printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in));
440
		printf("\n");
441
442
		printf("%s\tipsec %s out spi %u %s XXXXXX", c, method,
443
		    p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out));
444
		if (p->auth.enc_alg_out)
445
			printf(" %s XXXXXX",
446
			    print_enc_alg(p->auth.enc_alg_out));
447
		printf("\n");
448
	} else if (p->auth.method == AUTH_IPSEC_IKE_AH)
449
		printf("%s\tipsec ah ike\n", c);
450
	else if (p->auth.method == AUTH_IPSEC_IKE_ESP)
451
		printf("%s\tipsec esp ike\n", c);
452
453
	if (p->ttlsec)
454
		printf("%s\tttl-security yes\n", c);
455
456
	print_announce(p, c);
457
458
	if (p->softreconfig_in == 1)
459
		printf("%s\tsoftreconfig in yes\n", c);
460
	else
461
		printf("%s\tsoftreconfig in no\n", c);
462
463
	if (p->softreconfig_out == 1)
464
		printf("%s\tsoftreconfig out yes\n", c);
465
	else
466
		printf("%s\tsoftreconfig out no\n", c);
467
468
469
	print_mrt(conf, p->id, p->groupid, c, "\t");
470
471
	printf("%s}\n", c);
472
}
473
474
const char *
475
print_auth_alg(u_int8_t alg)
476
{
477
	switch (alg) {
478
	case SADB_AALG_SHA1HMAC:
479
		return ("sha1");
480
	case SADB_AALG_MD5HMAC:
481
		return ("md5");
482
	default:
483
		return ("???");
484
	}
485
}
486
487
const char *
488
print_enc_alg(u_int8_t alg)
489
{
490
	switch (alg) {
491
	case SADB_EALG_3DESCBC:
492
		return ("3des");
493
	case SADB_X_EALG_AES:
494
		return ("aes");
495
	default:
496
		return ("???");
497
	}
498
}
499
500
void
501
print_announce(struct peer_config *p, const char *c)
502
{
503
	u_int8_t	aid;
504
505
	for (aid = 0; aid < AID_MAX; aid++)
506
		if (p->capabilities.mp[aid])
507
			printf("%s\tannounce %s\n", c, aid2str(aid));
508
}
509
510
void print_as(struct filter_rule *r)
511
{
512
	switch(r->match.as.op) {
513
	case OP_RANGE:
514
		printf("%s - ", log_as(r->match.as.as_min));
515
		printf("%s ", log_as(r->match.as.as_max));
516
		break;
517
	case OP_XRANGE:
518
		printf("%s >< ", log_as(r->match.as.as_min));
519
		printf("%s ", log_as(r->match.as.as_max));
520
		break;
521
	case OP_NE:
522
		printf("!= %s ", log_as(r->match.as.as));
523
		break;
524
	default:
525
		printf("%s ", log_as(r->match.as.as));
526
		break;
527
	}
528
}
529
530
void
531
print_rule(struct peer *peer_l, struct filter_rule *r)
532
{
533
	struct peer	*p;
534
535
	if (r->action == ACTION_ALLOW)
536
		printf("allow ");
537
	else if (r->action == ACTION_DENY)
538
		printf("deny ");
539
	else
540
		printf("match ");
541
	if (r->quick)
542
		printf("quick ");
543
544
	if (r->rib[0])
545
		printf("rib %s ", r->rib);
546
547
	if (r->dir == DIR_IN)
548
		printf("from ");
549
	else if (r->dir == DIR_OUT)
550
		printf("to ");
551
	else
552
		printf("eeeeeeeps. ");
553
554
	if (r->peer.peerid) {
555
		for (p = peer_l; p != NULL && p->conf.id != r->peer.peerid;
556
		    p = p->next)
557
			;	/* nothing */
558
		if (p == NULL)
559
			printf("? ");
560
		else
561
			printf("%s ", log_addr(&p->conf.remote_addr));
562
	} else if (r->peer.groupid) {
563
		for (p = peer_l; p != NULL &&
564
		    p->conf.groupid != r->peer.groupid; p = p->next)
565
			;	/* nothing */
566
		if (p == NULL)
567
			printf("group ? ");
568
		else
569
			printf("group \"%s\" ", p->conf.group);
570
	} else if (r->peer.remote_as) {
571
		printf("AS %s ", log_as(r->peer.remote_as));
572
	} else
573
		printf("any ");
574
575
	if (r->match.prefix.addr.aid)
576
		printf("prefix %s/%u ", log_addr(&r->match.prefix.addr),
577
		    r->match.prefix.len);
578
579
	if (r->match.prefix.op) {
580
		if (r->match.prefix.op == OP_RANGE ||
581
		    r->match.prefix.op == OP_XRANGE) {
582
			printf("prefixlen %u ", r->match.prefix.len_min);
583
			print_op(r->match.prefix.op);
584
			printf(" %u ", r->match.prefix.len_max);
585
		} else {
586
			printf("prefixlen ");
587
			print_op(r->match.prefix.op);
588
			printf(" %u ", r->match.prefix.len_min);
589
		}
590
	}
591
592
	if (r->match.nexthop.flags) {
593
		if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
594
			printf("nexthop neighbor ");
595
		else
596
			printf("nexthop %s ", log_addr(&r->match.nexthop.addr));
597
	}
598
599
	if (r->match.as.type) {
600
		if (r->match.as.type == AS_ALL)
601
			printf("AS ");
602
		else if (r->match.as.type == AS_SOURCE)
603
			printf("source-as ");
604
		else if (r->match.as.type == AS_TRANSIT)
605
			printf("transit-as ");
606
		else if (r->match.as.type == AS_PEER)
607
			printf("peer-as ");
608
		else
609
			printf("unfluffy-as ");
610
		print_as(r);
611
	}
612
613
	if (r->match.aslen.type) {
614
		printf("%s %u ", r->match.aslen.type == ASLEN_MAX ?
615
		    "max-as-len" : "max-as-seq", r->match.aslen.aslen);
616
	}
617
618
	if (r->match.community.as != COMMUNITY_UNSET) {
619
		printf("community ");
620
		print_community(r->match.community.as,
621
		    r->match.community.type);
622
	}
623
	if (r->match.ext_community.flags & EXT_COMMUNITY_FLAG_VALID) {
624
		printf("ext-community ");
625
		print_extcommunity(&r->match.ext_community);
626
	}
627
628
	print_set(&r->set);
629
630
	printf("\n");
631
}
632
633
const char *
634
mrt_type(enum mrt_type t)
635
{
636
	switch (t) {
637
	case MRT_NONE:
638
		break;
639
	case MRT_TABLE_DUMP:
640
		return "table";
641
	case MRT_TABLE_DUMP_MP:
642
		return "table-mp";
643
	case MRT_TABLE_DUMP_V2:
644
		return "table-v2";
645
	case MRT_ALL_IN:
646
		return "all in";
647
	case MRT_ALL_OUT:
648
		return "all out";
649
	case MRT_UPDATE_IN:
650
		return "updates in";
651
	case MRT_UPDATE_OUT:
652
		return "updates out";
653
	}
654
	return "unfluffy MRT";
655
}
656
657
void
658
print_mrt(struct bgpd_config *conf, u_int32_t pid, u_int32_t gid,
659
    const char *prep, const char *prep2)
660
{
661
	struct mrt	*m;
662
663
	if (conf->mrt == NULL)
664
		return;
665
666
	LIST_FOREACH(m, conf->mrt, entry)
667
		if ((gid != 0 && m->group_id == gid) ||
668
		    (m->peer_id == pid && m->group_id == gid)) {
669
			printf("%s%sdump ", prep, prep2);
670
			if (m->rib[0])
671
				printf("rib %s ", m->rib);
672
			printf("%s \"%s\"", mrt_type(m->type),
673
			    MRT2MC(m)->name);
674
			if (MRT2MC(m)->ReopenTimerInterval == 0)
675
				printf("\n");
676
			else
677
				printf(" %d\n", MRT2MC(m)->ReopenTimerInterval);
678
		}
679
}
680
681
void
682
print_groups(struct bgpd_config *conf, struct peer *peer_l)
683
{
684
	struct peer_config	**peerlist;
685
	struct peer		 *p;
686
	u_int			  peer_cnt, i;
687
	u_int32_t		  prev_groupid;
688
	const char		 *tab	= "\t";
689
	const char		 *nada	= "";
690
	const char		 *c;
691
692
	peer_cnt = 0;
693
	for (p = peer_l; p != NULL; p = p->next)
694
		peer_cnt++;
695
696
	if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL)
697
		fatal("print_groups calloc");
698
699
	i = 0;
700
	for (p = peer_l; p != NULL; p = p->next)
701
		peerlist[i++] = &p->conf;
702
703
	qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare);
704
705
	prev_groupid = 0;
706
	for (i = 0; i < peer_cnt; i++) {
707
		if (peerlist[i]->groupid) {
708
			c = tab;
709
			if (peerlist[i]->groupid != prev_groupid) {
710
				if (prev_groupid)
711
					printf("}\n\n");
712
				printf("group \"%s\" {\n", peerlist[i]->group);
713
				prev_groupid = peerlist[i]->groupid;
714
			}
715
		} else
716
			c = nada;
717
718
		print_peer(peerlist[i], conf, c);
719
	}
720
721
	if (prev_groupid)
722
		printf("}\n\n");
723
724
	free(peerlist);
725
}
726
727
int
728
peer_compare(const void *aa, const void *bb)
729
{
730
	const struct peer_config * const *a;
731
	const struct peer_config * const *b;
732
733
	a = aa;
734
	b = bb;
735
736
	return ((*a)->groupid - (*b)->groupid);
737
}
738
739
void
740
print_config(struct bgpd_config *conf, struct rib_names *rib_l,
741
    struct network_head *net_l, struct peer *peer_l,
742
    struct filter_head *rules_l, struct mrt_head *mrt_l,
743
    struct rdomain_head *rdom_l)
744
{
745
	struct filter_rule	*r;
746
	struct network		*n;
747
	struct rde_rib		*rr;
748
	struct rdomain		*rd;
749
750
	print_mainconf(conf);
751
	printf("\n");
752
	TAILQ_FOREACH(n, net_l, entry)
753
		print_network(&n->net, "");
754
	printf("\n");
755
	SIMPLEQ_FOREACH(rd, rdom_l, entry)
756
		print_rdomain(rd);
757
	printf("\n");
758
	SIMPLEQ_FOREACH(rr, rib_l, entry) {
759
		if (rr->flags & F_RIB_NOEVALUATE)
760
			printf("rde rib %s no evaluate\n", rr->name);
761
		else if (rr->flags & F_RIB_NOFIB)
762
			printf("rde rib %s\n", rr->name);
763
		else
764
			printf("rde rib %s rtable %u fib-update %s\n", rr->name,
765
			    rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ?
766
			    "no" : "yes");
767
	}
768
	printf("\n");
769
	print_mrt(conf, 0, 0, "", "");
770
	printf("\n");
771
	print_groups(conf, peer_l);
772
	printf("\n");
773
	TAILQ_FOREACH(r, rules_l, entry)
774
		print_rule(peer_l, r);
775
}