GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/bgpd/printconf.c Lines: 0 479 0.0 %
Date: 2017-11-07 Branches: 0 345 0.0 %

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