xref: /openbsd-src/usr.sbin/bgpd/printconf.c (revision e3db1f63b9983ca4cf18b686be12853eccdfd031)
1*e3db1f63Sclaudio /*	$OpenBSD: printconf.c,v 1.181 2025/01/27 15:22:11 claudio Exp $	*/
2977216a6Shenning 
3977216a6Shenning /*
4977216a6Shenning  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5280f24a4Sphessler  * Copyright (c) 2016 Job Snijders <job@instituut.net>
6280f24a4Sphessler  * Copyright (c) 2016 Peter Hessler <phessler@openbsd.org>
7977216a6Shenning  *
8977216a6Shenning  * Permission to use, copy, modify, and distribute this software for any
9977216a6Shenning  * purpose with or without fee is hereby granted, provided that the above
10977216a6Shenning  * copyright notice and this permission notice appear in all copies.
11977216a6Shenning  *
12977216a6Shenning  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13977216a6Shenning  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14977216a6Shenning  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15977216a6Shenning  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16977216a6Shenning  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA, PROFITS OR MIND, WHETHER IN
17977216a6Shenning  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18977216a6Shenning  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19977216a6Shenning  */
20977216a6Shenning 
21b2cd1366Sguenther #include <limits.h>
22977216a6Shenning #include <stdio.h>
23cbcb38a8Shenning #include <stdlib.h>
24425bb0f0Shenning #include <string.h>
25977216a6Shenning 
26977216a6Shenning #include "bgpd.h"
27977216a6Shenning #include "session.h"
2898daafc0Sclaudio #include "rde.h"
295e3f6f95Sbenno #include "log.h"
30977216a6Shenning 
314ea66b69Sclaudio void		 print_prefix(struct filter_prefix *p);
32e7adcfeaSclaudio const char	*community_type(struct community *c);
33e7adcfeaSclaudio void		 print_community(struct community *c);
3439386878Sclaudio void		 print_origin(uint8_t);
3598d902b5Sclaudio void		 print_set(struct filter_set_head *);
36020327f0Shenning void		 print_mainconf(struct bgpd_config *);
374e0c4e97Sclaudio void		 print_l3vpn_targets(struct filter_set_head *, const char *);
384e0c4e97Sclaudio void		 print_l3vpn(struct l3vpn *);
3939386878Sclaudio const char	*print_af(uint8_t);
401274ebf8Sclaudio void		 print_network(struct network_config *, const char *);
417d4aa781Sclaudio void		 print_flowspec(struct flowspec_config *, const char *);
4259e404fbSclaudio void		 print_as_sets(struct as_set_head *);
43441aaadcSbenno void		 print_prefixsets(struct prefixset_head *);
446f1dba6eSclaudio void		 print_originsets(struct prefixset_head *);
456aa533f4Sclaudio void		 print_roa(struct roa_tree *);
46ff84f55eSclaudio void		 print_aspa(struct aspa_tree *);
47bd9df44eSclaudio void		 print_rtrs(struct rtr_config_head *);
48d7629114Sclaudio void		 print_peer(struct peer *, struct bgpd_config *, const char *);
4993662c4eSclaudio const char	*print_auth_alg(enum auth_alg);
5093662c4eSclaudio const char	*print_enc_alg(enum auth_enc_alg);
5186729c90Sclaudio void		 print_announce(struct peer_config *, const char *);
52708dc8caSbenno void		 print_as(struct filter_rule *);
5382fc6237Sclaudio void		 print_rule(struct bgpd_config *, struct filter_rule *);
54866636d1Sclaudio const char	*mrt_type(enum mrt_type);
5539386878Sclaudio void		 print_mrt(struct bgpd_config *, uint32_t, uint32_t,
56d288d268Sclaudio 		    const char *, const char *);
5782fc6237Sclaudio void		 print_groups(struct bgpd_config *);
58cbcb38a8Shenning int		 peer_compare(const void *, const void *);
59977216a6Shenning 
60977216a6Shenning void
614ea66b69Sclaudio print_prefix(struct filter_prefix *p)
62977216a6Shenning {
6339386878Sclaudio 	uint8_t max_len = 0;
640d3ce282Sclaudio 
650d3ce282Sclaudio 	switch (p->addr.aid) {
660d3ce282Sclaudio 	case AID_INET:
670d3ce282Sclaudio 	case AID_VPN_IPv4:
680d3ce282Sclaudio 		max_len = 32;
69d77f1165Sclaudio 		break;
700d3ce282Sclaudio 	case AID_INET6:
71290f96faSdenis 	case AID_VPN_IPv6:
720d3ce282Sclaudio 		max_len = 128;
730d3ce282Sclaudio 		break;
740d3ce282Sclaudio 	case AID_UNSPEC:
750d3ce282Sclaudio 		/* no prefix to print */
760d3ce282Sclaudio 		return;
770d3ce282Sclaudio 	}
780d3ce282Sclaudio 
794ea66b69Sclaudio 	printf("%s/%u", log_addr(&p->addr), p->len);
800d3ce282Sclaudio 
810d3ce282Sclaudio 	switch (p->op) {
820d3ce282Sclaudio 	case OP_NONE:
83d77f1165Sclaudio 		break;
84977216a6Shenning 	case OP_NE:
850d3ce282Sclaudio 		printf(" prefixlen != %u", p->len_min);
86977216a6Shenning 		break;
870d3ce282Sclaudio 	case OP_XRANGE:
880d3ce282Sclaudio 		printf(" prefixlen %u >< %u ", p->len_min, p->len_max);
89977216a6Shenning 		break;
900d3ce282Sclaudio 	case OP_RANGE:
916f1dba6eSclaudio 		if (p->len_min == p->len_max && p->len != p->len_min)
925d31d72bSclaudio 			printf(" prefixlen = %u", p->len_min);
935bbea992Sclaudio 		else if (p->len == p->len_min && p->len_max == max_len)
940d3ce282Sclaudio 			printf(" or-longer");
956f1dba6eSclaudio 		else if (p->len == p->len_min && p->len != p->len_max)
965bbea992Sclaudio 			printf(" maxlen %u", p->len_max);
970d3ce282Sclaudio 		else if (p->len_max == max_len)
980d3ce282Sclaudio 			printf(" prefixlen >= %u", p->len_min);
990d3ce282Sclaudio 		else
1000d3ce282Sclaudio 			printf(" prefixlen %u - %u", p->len_min, p->len_max);
101977216a6Shenning 		break;
102977216a6Shenning 	default:
1030d3ce282Sclaudio 		printf(" prefixlen %u ??? %u", p->len_min, p->len_max);
104977216a6Shenning 		break;
105977216a6Shenning 	}
106977216a6Shenning }
107977216a6Shenning 
108dd87f852Sclaudio const char *
109e7adcfeaSclaudio community_type(struct community *c)
1107d5dac02Sclaudio {
11139386878Sclaudio 	switch ((uint8_t)c->flags) {
112dd87f852Sclaudio 	case COMMUNITY_TYPE_BASIC:
113dd87f852Sclaudio 		return "community";
114dd87f852Sclaudio 	case COMMUNITY_TYPE_LARGE:
115dd87f852Sclaudio 		return "large-community";
11636e003c6Sclaudio 	case COMMUNITY_TYPE_EXT:
11736e003c6Sclaudio 		return "ext-community";
118dd87f852Sclaudio 	default:
119dd87f852Sclaudio 		return "???";
120dd87f852Sclaudio 	}
1217d5dac02Sclaudio }
1227d5dac02Sclaudio 
1237d5dac02Sclaudio void
124e7adcfeaSclaudio print_community(struct community *c)
125280f24a4Sphessler {
12636e003c6Sclaudio 	struct in_addr addr;
127f8162053Sclaudio 	int type;
12839386878Sclaudio 	uint8_t subtype;
12936e003c6Sclaudio 
13039386878Sclaudio 	switch ((uint8_t)c->flags) {
131dd87f852Sclaudio 	case COMMUNITY_TYPE_BASIC:
132e7adcfeaSclaudio 		switch ((c->flags >> 8) & 0xff) {
133dd87f852Sclaudio 		case COMMUNITY_ANY:
134280f24a4Sphessler 			printf("*:");
135dd87f852Sclaudio 			break;
136dd87f852Sclaudio 		case COMMUNITY_NEIGHBOR_AS:
137280f24a4Sphessler 			printf("neighbor-as:");
138dd87f852Sclaudio 			break;
139dd87f852Sclaudio 		case COMMUNITY_LOCAL_AS:
140a07e3c3cSphessler 			printf("local-as:");
141dd87f852Sclaudio 			break;
142dd87f852Sclaudio 		default:
143e7adcfeaSclaudio 			printf("%u:", c->data1);
144dd87f852Sclaudio 			break;
145280f24a4Sphessler 		}
146e7adcfeaSclaudio 		switch ((c->flags >> 16) & 0xff) {
147dd87f852Sclaudio 		case COMMUNITY_ANY:
148dd87f852Sclaudio 			printf("* ");
149dd87f852Sclaudio 			break;
150dd87f852Sclaudio 		case COMMUNITY_NEIGHBOR_AS:
151dd87f852Sclaudio 			printf("neighbor-as ");
152dd87f852Sclaudio 			break;
153dd87f852Sclaudio 		case COMMUNITY_LOCAL_AS:
154dd87f852Sclaudio 			printf("local-as ");
155dd87f852Sclaudio 			break;
156dd87f852Sclaudio 		default:
157e7adcfeaSclaudio 			printf("%u ", c->data2);
158dd87f852Sclaudio 			break;
159dd87f852Sclaudio 		}
160dd87f852Sclaudio 		break;
161dd87f852Sclaudio 	case COMMUNITY_TYPE_LARGE:
162e7adcfeaSclaudio 		switch ((c->flags >> 8) & 0xff) {
163dd87f852Sclaudio 		case COMMUNITY_ANY:
164dd87f852Sclaudio 			printf("*:");
165dd87f852Sclaudio 			break;
166dd87f852Sclaudio 		case COMMUNITY_NEIGHBOR_AS:
167dd87f852Sclaudio 			printf("neighbor-as:");
168dd87f852Sclaudio 			break;
169dd87f852Sclaudio 		case COMMUNITY_LOCAL_AS:
170dd87f852Sclaudio 			printf("local-as:");
171dd87f852Sclaudio 			break;
172dd87f852Sclaudio 		default:
173e7adcfeaSclaudio 			printf("%u:", c->data1);
174dd87f852Sclaudio 			break;
175dd87f852Sclaudio 		}
176e7adcfeaSclaudio 		switch ((c->flags >> 16) & 0xff) {
177dd87f852Sclaudio 		case COMMUNITY_ANY:
178dd87f852Sclaudio 			printf("*:");
179dd87f852Sclaudio 			break;
180dd87f852Sclaudio 		case COMMUNITY_NEIGHBOR_AS:
181dd87f852Sclaudio 			printf("neighbor-as:");
182dd87f852Sclaudio 			break;
183dd87f852Sclaudio 		case COMMUNITY_LOCAL_AS:
184dd87f852Sclaudio 			printf("local-as:");
185dd87f852Sclaudio 			break;
186dd87f852Sclaudio 		default:
187e7adcfeaSclaudio 			printf("%u:", c->data2);
188dd87f852Sclaudio 			break;
189dd87f852Sclaudio 		}
190e7adcfeaSclaudio 		switch ((c->flags >> 24) & 0xff) {
191dd87f852Sclaudio 		case COMMUNITY_ANY:
192dd87f852Sclaudio 			printf("* ");
193dd87f852Sclaudio 			break;
194dd87f852Sclaudio 		case COMMUNITY_NEIGHBOR_AS:
195dd87f852Sclaudio 			printf("neighbor-as ");
196dd87f852Sclaudio 			break;
197dd87f852Sclaudio 		case COMMUNITY_LOCAL_AS:
198dd87f852Sclaudio 			printf("local-as ");
199dd87f852Sclaudio 			break;
200dd87f852Sclaudio 		default:
201e7adcfeaSclaudio 			printf("%u ", c->data3);
202dd87f852Sclaudio 			break;
203dd87f852Sclaudio 		}
204dd87f852Sclaudio 		break;
20536e003c6Sclaudio 	case COMMUNITY_TYPE_EXT:
206e7adcfeaSclaudio 		if ((c->flags >> 24 & 0xff) == COMMUNITY_ANY) {
2070e6216fdSclaudio 			printf("* * ");
2080e6216fdSclaudio 			break;
2090e6216fdSclaudio 		}
210e7adcfeaSclaudio 		type = (int32_t)c->data3 >> 8;
211e7adcfeaSclaudio 		subtype = c->data3;
212e7adcfeaSclaudio 		printf("%s ", log_ext_subtype(type, subtype));
213e7adcfeaSclaudio 		if ((c->flags >> 8 & 0xff) == COMMUNITY_ANY) {
2140e6216fdSclaudio 			printf("* ");
2150e6216fdSclaudio 			break;
2160e6216fdSclaudio 		}
2170e6216fdSclaudio 
218e7adcfeaSclaudio 		switch (type) {
219bf8e2920Sclaudio 		case EXT_COMMUNITY_TRANS_TWO_AS:
22036e003c6Sclaudio 		case EXT_COMMUNITY_TRANS_FOUR_AS:
221a1957465Sclaudio 		case EXT_COMMUNITY_GEN_TWO_AS:
222a1957465Sclaudio 		case EXT_COMMUNITY_GEN_FOUR_AS:
223e7adcfeaSclaudio 			if ((c->flags >> 8 & 0xff) == COMMUNITY_NEIGHBOR_AS)
2240e6216fdSclaudio 				printf("neighbor-as:");
225e7adcfeaSclaudio 			else if ((c->flags >> 8 & 0xff) == COMMUNITY_LOCAL_AS)
2260e6216fdSclaudio 				printf("local-as:");
2270e6216fdSclaudio 			else
228e7adcfeaSclaudio 				printf("%s:", log_as(c->data1));
229536f41e5Sclaudio 			break;
230bf8e2920Sclaudio 		case EXT_COMMUNITY_TRANS_IPV4:
231a1957465Sclaudio 		case EXT_COMMUNITY_GEN_IPV4:
232e7adcfeaSclaudio 			addr.s_addr = htonl(c->data1);
2330e6216fdSclaudio 			printf("%s:", inet_ntoa(addr));
2340e6216fdSclaudio 			break;
2350e6216fdSclaudio 		}
2360e6216fdSclaudio 
237e7adcfeaSclaudio 		switch (type) {
2380e6216fdSclaudio 		case EXT_COMMUNITY_TRANS_TWO_AS:
2390e6216fdSclaudio 		case EXT_COMMUNITY_TRANS_FOUR_AS:
2400e6216fdSclaudio 		case EXT_COMMUNITY_TRANS_IPV4:
241a1957465Sclaudio 		case EXT_COMMUNITY_GEN_TWO_AS:
242a1957465Sclaudio 		case EXT_COMMUNITY_GEN_FOUR_AS:
243a1957465Sclaudio 		case EXT_COMMUNITY_GEN_IPV4:
244e7adcfeaSclaudio 			if ((c->flags >> 16 & 0xff) == COMMUNITY_ANY)
2450e6216fdSclaudio 				printf("* ");
246e7adcfeaSclaudio 			else if ((c->flags >> 16 & 0xff) ==
247e7adcfeaSclaudio 			    COMMUNITY_NEIGHBOR_AS)
2480e6216fdSclaudio 				printf("neighbor-as ");
249e7adcfeaSclaudio 			else if ((c->flags >> 16 & 0xff) == COMMUNITY_LOCAL_AS)
2500e6216fdSclaudio 				printf("local-as ");
2510e6216fdSclaudio 			else
252e7adcfeaSclaudio 				printf("%u ", c->data2);
253bf8e2920Sclaudio 			break;
254bf8e2920Sclaudio 		case EXT_COMMUNITY_NON_TRANS_OPAQUE:
255e7adcfeaSclaudio 			if (subtype == EXT_COMMUNITY_SUBTYPE_OVS) {
256e7adcfeaSclaudio 				switch (c->data2) {
257bf8e2920Sclaudio 				case EXT_COMMUNITY_OVS_VALID:
258bf8e2920Sclaudio 					printf("valid ");
259bf8e2920Sclaudio 					break;
260bf8e2920Sclaudio 				case EXT_COMMUNITY_OVS_NOTFOUND:
261bf8e2920Sclaudio 					printf("not-found ");
262bf8e2920Sclaudio 					break;
263bf8e2920Sclaudio 				case EXT_COMMUNITY_OVS_INVALID:
264bf8e2920Sclaudio 					printf("invalid ");
265bf8e2920Sclaudio 					break;
266bf8e2920Sclaudio 				}
267536f41e5Sclaudio 				break;
2680e6216fdSclaudio 			}
269e7adcfeaSclaudio 			printf("0x%x%08x ", c->data1 & 0xffff, c->data2);
2700e6216fdSclaudio 			break;
271e7adcfeaSclaudio 		case EXT_COMMUNITY_TRANS_OPAQUE:
272e7adcfeaSclaudio 		case EXT_COMMUNITY_TRANS_EVPN:
273536f41e5Sclaudio 		default:
274e7adcfeaSclaudio 			printf("0x%x%08x ", c->data1 & 0xffff, c->data2);
275536f41e5Sclaudio 			break;
276536f41e5Sclaudio 		}
277536f41e5Sclaudio 	}
27836e003c6Sclaudio }
279536f41e5Sclaudio 
280536f41e5Sclaudio void
28139386878Sclaudio print_origin(uint8_t o)
282cd3afea8Shenning {
283cd3afea8Shenning 	if (o == ORIGIN_IGP)
284cd3afea8Shenning 		printf("igp ");
285cd3afea8Shenning 	else if (o == ORIGIN_EGP)
286cd3afea8Shenning 		printf("egp ");
287cd3afea8Shenning 	else if (o == ORIGIN_INCOMPLETE)
288cd3afea8Shenning 		printf("incomplete ");
289cd3afea8Shenning 	else
290cd3afea8Shenning 		printf("%u ", o);
291cd3afea8Shenning }
292cd3afea8Shenning 
293cd3afea8Shenning void
29498d902b5Sclaudio print_set(struct filter_set_head *set)
295866636d1Sclaudio {
29698d902b5Sclaudio 	struct filter_set	*s;
29798d902b5Sclaudio 
29876630fdaSclaudio 	if (TAILQ_EMPTY(set))
29998d902b5Sclaudio 		return;
30098d902b5Sclaudio 
301866636d1Sclaudio 	printf("set { ");
30276630fdaSclaudio 	TAILQ_FOREACH(s, set, entry) {
30398d902b5Sclaudio 		switch (s->type) {
30498d902b5Sclaudio 		case ACTION_SET_LOCALPREF:
30598d902b5Sclaudio 			printf("localpref %u ", s->action.metric);
30698d902b5Sclaudio 			break;
3072704869fSclaudio 		case ACTION_SET_RELATIVE_LOCALPREF:
3082704869fSclaudio 			printf("localpref %+d ", s->action.relative);
3092704869fSclaudio 			break;
31098d902b5Sclaudio 		case ACTION_SET_MED:
31198d902b5Sclaudio 			printf("metric %u ", s->action.metric);
31298d902b5Sclaudio 			break;
3132704869fSclaudio 		case ACTION_SET_RELATIVE_MED:
3142704869fSclaudio 			printf("metric %+d ", s->action.relative);
3152704869fSclaudio 			break;
316aa5d92feSclaudio 		case ACTION_SET_WEIGHT:
317aa5d92feSclaudio 			printf("weight %u ", s->action.metric);
318aa5d92feSclaudio 			break;
319aa5d92feSclaudio 		case ACTION_SET_RELATIVE_WEIGHT:
320aa5d92feSclaudio 			printf("weight %+d ", s->action.relative);
321aa5d92feSclaudio 			break;
32298d902b5Sclaudio 		case ACTION_SET_NEXTHOP:
32398d902b5Sclaudio 			printf("nexthop %s ", log_addr(&s->action.nexthop));
32498d902b5Sclaudio 			break;
32598d902b5Sclaudio 		case ACTION_SET_NEXTHOP_REJECT:
326c29e5df5Shenning 			printf("nexthop reject ");
32798d902b5Sclaudio 			break;
32898d902b5Sclaudio 		case ACTION_SET_NEXTHOP_BLACKHOLE:
329c29e5df5Shenning 			printf("nexthop blackhole ");
33098d902b5Sclaudio 			break;
331ce9d64eaSclaudio 		case ACTION_SET_NEXTHOP_NOMODIFY:
332ce9d64eaSclaudio 			printf("nexthop no-modify ");
333ce9d64eaSclaudio 			break;
3347c989460Shenning 		case ACTION_SET_NEXTHOP_SELF:
3357c989460Shenning 			printf("nexthop self ");
3367c989460Shenning 			break;
33798d902b5Sclaudio 		case ACTION_SET_PREPEND_SELF:
33898d902b5Sclaudio 			printf("prepend-self %u ", s->action.prepend);
33998d902b5Sclaudio 			break;
34098d902b5Sclaudio 		case ACTION_SET_PREPEND_PEER:
34198d902b5Sclaudio 			printf("prepend-neighbor %u ", s->action.prepend);
34298d902b5Sclaudio 			break;
343d7a2dcd7Sclaudio 		case ACTION_SET_AS_OVERRIDE:
344d7a2dcd7Sclaudio 			printf("as-override ");
345d7a2dcd7Sclaudio 			break;
346aaa4f5dfSclaudio 		case ACTION_DEL_COMMUNITY:
347dd87f852Sclaudio 			printf("%s delete ",
348dd87f852Sclaudio 			    community_type(&s->action.community));
349dd87f852Sclaudio 			print_community(&s->action.community);
350aaa4f5dfSclaudio 			break;
35198d902b5Sclaudio 		case ACTION_SET_COMMUNITY:
352dd87f852Sclaudio 			printf("%s ", community_type(&s->action.community));
353dd87f852Sclaudio 			print_community(&s->action.community);
354280f24a4Sphessler 			break;
35598d902b5Sclaudio 		case ACTION_PFTABLE:
35698d902b5Sclaudio 			printf("pftable %s ", s->action.pftable);
35798d902b5Sclaudio 			break;
35815aea9d4Sclaudio 		case ACTION_RTLABEL:
35915aea9d4Sclaudio 			printf("rtlabel %s ", s->action.rtlabel);
36015aea9d4Sclaudio 			break;
361cd3afea8Shenning 		case ACTION_SET_ORIGIN:
362cd3afea8Shenning 			printf("origin ");
363cd3afea8Shenning 			print_origin(s->action.origin);
364cd3afea8Shenning 			break;
36515aea9d4Sclaudio 		case ACTION_RTLABEL_ID:
366e2691ddeSclaudio 		case ACTION_PFTABLE_ID:
36723676e2aSclaudio 		case ACTION_SET_NEXTHOP_REF:
36815aea9d4Sclaudio 			/* not possible */
369e2691ddeSclaudio 			printf("king bula saiz: config broken");
37015aea9d4Sclaudio 			break;
371866636d1Sclaudio 		}
372866636d1Sclaudio 	}
37398d902b5Sclaudio 	printf("}");
37498d902b5Sclaudio }
375866636d1Sclaudio 
376866636d1Sclaudio void
377020327f0Shenning print_mainconf(struct bgpd_config *conf)
378020327f0Shenning {
379020327f0Shenning 	struct in_addr		 ina;
380f99a9452Shenning 	struct listen_addr	*la;
381020327f0Shenning 
3820c88bf70Sclaudio 	printf("AS %s", log_as(conf->as));
3830c88bf70Sclaudio 	if (conf->as > USHRT_MAX && conf->short_as != AS_TRANS)
3840c88bf70Sclaudio 		printf(" %u", conf->short_as);
385bcd6516bSclaudio 	ina.s_addr = htonl(conf->bgpid);
3860c88bf70Sclaudio 	printf("\nrouter-id %s\n", inet_ntoa(ina));
3871daa807cSclaudio 
3881daa807cSclaudio 	printf("socket \"%s\"\n", conf->csock);
3891daa807cSclaudio 	if (conf->rcsock)
3901daa807cSclaudio 		printf("socket \"%s\" restricted\n", conf->rcsock);
391043e486bSclaudio 	if (conf->holdtime != INTERVAL_HOLD)
392020327f0Shenning 		printf("holdtime %u\n", conf->holdtime);
393043e486bSclaudio 	if (conf->min_holdtime != MIN_HOLDTIME)
394020327f0Shenning 		printf("holdtime min %u\n", conf->min_holdtime);
395043e486bSclaudio 	if (conf->connectretry != INTERVAL_CONNECTRETRY)
396471e75faSreyk 		printf("connect-retry %u\n", conf->connectretry);
3976c15f943Sclaudio 	if (conf->staletime != INTERVAL_STALE)
3986c15f943Sclaudio 		printf("staletime %u\n", conf->staletime);
399020327f0Shenning 
40088ca7a8dSclaudio 	if (conf->flags & BGPD_FLAG_DECISION_ROUTEAGE)
40188ca7a8dSclaudio 		printf("rde route-age evaluate\n");
40214aa7f77Sclaudio 	if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS)
40314aa7f77Sclaudio 		printf("rde med compare always\n");
40405ebbbf6Sclaudio 	if (conf->flags & BGPD_FLAG_DECISION_ALL_PATHS)
40505ebbbf6Sclaudio 		printf("rde evaluate all\n");
40614aa7f77Sclaudio 
407*e3db1f63Sclaudio 	if (conf->flags & BGPD_FLAG_PERMIT_AS_SET)
408*e3db1f63Sclaudio 		printf("reject as-set no\n");
409aa528464Sclaudio 
410020327f0Shenning 	if (conf->log & BGPD_LOG_UPDATES)
411020327f0Shenning 		printf("log updates\n");
412020327f0Shenning 
4133c001116Sclaudio 	TAILQ_FOREACH(la, conf->listen_addrs, entry) {
4143c001116Sclaudio 		struct bgpd_addr addr;
4153c001116Sclaudio 		uint16_t port;
4163c001116Sclaudio 
4173c001116Sclaudio 		sa2addr((struct sockaddr *)&la->sa, &addr, &port);
4183c001116Sclaudio 		printf("listen on %s",
419255fe563Sclaudio 		    log_sockaddr((struct sockaddr *)&la->sa, la->sa_len));
4203c001116Sclaudio 		if (port != BGP_PORT)
4213c001116Sclaudio 			printf(" port %hu", port);
4223c001116Sclaudio 		printf("\n");
4233c001116Sclaudio 	}
4247fedd3ccSclaudio 
425faf535a4Sclaudio 	if (conf->flags & BGPD_FLAG_NEXTHOP_BGP)
426faf535a4Sclaudio 		printf("nexthop qualify via bgp\n");
427faf535a4Sclaudio 	if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT)
428faf535a4Sclaudio 		printf("nexthop qualify via default\n");
429ce68a032Sclaudio 	if (conf->fib_priority != kr_default_prio())
430043e486bSclaudio 		printf("fib-priority %hhu\n", conf->fib_priority);
431043e486bSclaudio 	printf("\n");
432610bcb44Sclaudio }
433faf535a4Sclaudio 
434610bcb44Sclaudio void
4354e0c4e97Sclaudio print_l3vpn_targets(struct filter_set_head *set, const char *tgt)
436610bcb44Sclaudio {
437610bcb44Sclaudio 	struct filter_set	*s;
438610bcb44Sclaudio 	TAILQ_FOREACH(s, set, entry) {
439610bcb44Sclaudio 		printf("\t%s ", tgt);
44036e003c6Sclaudio 		print_community(&s->action.community);
4417fedd3ccSclaudio 		printf("\n");
4427fedd3ccSclaudio 	}
4437fedd3ccSclaudio }
444610bcb44Sclaudio 
445610bcb44Sclaudio void
4464e0c4e97Sclaudio print_l3vpn(struct l3vpn *vpn)
447610bcb44Sclaudio {
4481274ebf8Sclaudio 	struct network *n;
4491274ebf8Sclaudio 
4504e0c4e97Sclaudio 	printf("vpn \"%s\" on %s {\n", vpn->descr, vpn->ifmpe);
451f3d22dbcSclaudio 	printf("\t%s\n", log_rd(vpn->rd));
4524e0c4e97Sclaudio 
4534e0c4e97Sclaudio 	print_l3vpn_targets(&vpn->export, "export-target");
4544e0c4e97Sclaudio 	print_l3vpn_targets(&vpn->import, "import-target");
4554e0c4e97Sclaudio 
4564e0c4e97Sclaudio 	if (vpn->flags & F_RIB_NOFIBSYNC)
457610bcb44Sclaudio 		printf("\tfib-update no\n");
458610bcb44Sclaudio 	else
459610bcb44Sclaudio 		printf("\tfib-update yes\n");
460610bcb44Sclaudio 
4614e0c4e97Sclaudio 	TAILQ_FOREACH(n, &vpn->net_l, entry)
4621274ebf8Sclaudio 		print_network(&n->net, "\t");
4631274ebf8Sclaudio 
464610bcb44Sclaudio 	printf("}\n");
465e6f00aedSclaudio }
466610bcb44Sclaudio 
467610bcb44Sclaudio const char *
46839386878Sclaudio print_af(uint8_t aid)
469610bcb44Sclaudio {
470610bcb44Sclaudio 	/*
471610bcb44Sclaudio 	 * Hack around the fact that aid2str() will return "IPv4 unicast"
4727d4aa781Sclaudio 	 * for AID_INET. AID_INET, AID_INET6 and the flowspec AID need
4737d4aa781Sclaudio 	 * special handling and the other AID should never end up here.
474610bcb44Sclaudio 	 */
4757d4aa781Sclaudio 	if (aid == AID_INET || aid == AID_FLOWSPECv4)
476610bcb44Sclaudio 		return ("inet");
4777d4aa781Sclaudio 	if (aid == AID_INET6 || aid == AID_FLOWSPECv6)
478610bcb44Sclaudio 		return ("inet6");
479610bcb44Sclaudio 	return (aid2str(aid));
480020327f0Shenning }
481020327f0Shenning 
482020327f0Shenning void
4831274ebf8Sclaudio print_network(struct network_config *n, const char *c)
484294d4e13Shenning {
485610bcb44Sclaudio 	switch (n->type) {
486610bcb44Sclaudio 	case NETWORK_STATIC:
4871274ebf8Sclaudio 		printf("%snetwork %s static", c, print_af(n->prefix.aid));
488610bcb44Sclaudio 		break;
489610bcb44Sclaudio 	case NETWORK_CONNECTED:
4901274ebf8Sclaudio 		printf("%snetwork %s connected", c, print_af(n->prefix.aid));
491610bcb44Sclaudio 		break;
492f6296dcfSphessler 	case NETWORK_RTLABEL:
493f6296dcfSphessler 		printf("%snetwork %s rtlabel \"%s\"", c,
494f6296dcfSphessler 		    print_af(n->prefix.aid), rtlabel_id2name(n->rtlabel));
495f6296dcfSphessler 		break;
4968d028d67Sbenno 	case NETWORK_PRIORITY:
4978d028d67Sbenno 		printf("%snetwork %s priority %d", c,
4988d028d67Sbenno 		    print_af(n->prefix.aid), n->priority);
4998d028d67Sbenno 		break;
50047feec7cSbenno 	case NETWORK_PREFIXSET:
50147feec7cSbenno 		printf("%snetwork prefix-set %s", c, n->psname);
50247feec7cSbenno 		break;
503610bcb44Sclaudio 	default:
5041274ebf8Sclaudio 		printf("%snetwork %s/%u", c, log_addr(&n->prefix),
5051274ebf8Sclaudio 		    n->prefixlen);
506610bcb44Sclaudio 		break;
507610bcb44Sclaudio 	}
50876630fdaSclaudio 	if (!TAILQ_EMPTY(&n->attrset))
5096a49a14cSclaudio 		printf(" ");
510866636d1Sclaudio 	print_set(&n->attrset);
511866636d1Sclaudio 	printf("\n");
512294d4e13Shenning }
513294d4e13Shenning 
5147d4aa781Sclaudio static void
5157d4aa781Sclaudio print_flowspec_list(struct flowspec *f, int type, int is_v6)
5167d4aa781Sclaudio {
5177d4aa781Sclaudio 	const uint8_t *comp;
5187d4aa781Sclaudio 	const char *fmt;
5197d4aa781Sclaudio 	int complen, off = 0;
5207d4aa781Sclaudio 
5217d4aa781Sclaudio 	if (flowspec_get_component(f->data, f->len, type, is_v6,
5227d4aa781Sclaudio 	    &comp, &complen) != 1)
5237d4aa781Sclaudio 		return;
5247d4aa781Sclaudio 
5257d4aa781Sclaudio 	printf("%s ", flowspec_fmt_label(type));
5267d4aa781Sclaudio 	fmt = flowspec_fmt_num_op(comp, complen, &off);
5277d4aa781Sclaudio 	if (off == -1) {
5287d4aa781Sclaudio 		printf("%s ", fmt);
5297d4aa781Sclaudio 	} else {
5307d4aa781Sclaudio 		printf("{ %s ", fmt);
5317d4aa781Sclaudio 		do {
5327d4aa781Sclaudio 			fmt = flowspec_fmt_num_op(comp, complen, &off);
5337d4aa781Sclaudio 			printf("%s ", fmt);
5347d4aa781Sclaudio 		} while (off != -1);
5357d4aa781Sclaudio 		printf("} ");
5367d4aa781Sclaudio 	}
5377d4aa781Sclaudio }
5387d4aa781Sclaudio 
5397d4aa781Sclaudio static void
5407d4aa781Sclaudio print_flowspec_flags(struct flowspec *f, int type, int is_v6)
5417d4aa781Sclaudio {
5427d4aa781Sclaudio 	const uint8_t *comp;
5437d4aa781Sclaudio 	const char *fmt, *flags;
5447d4aa781Sclaudio 	int complen, off = 0;
5457d4aa781Sclaudio 
5467d4aa781Sclaudio 	switch (type) {
5477d4aa781Sclaudio 	case FLOWSPEC_TYPE_TCP_FLAGS:
5487d4aa781Sclaudio 		flags = FLOWSPEC_TCP_FLAG_STRING;
5497d4aa781Sclaudio 		break;
5507d4aa781Sclaudio 	case FLOWSPEC_TYPE_FRAG:
5517d4aa781Sclaudio 		if (!is_v6)
5527d4aa781Sclaudio 			flags = FLOWSPEC_FRAG_STRING4;
5537d4aa781Sclaudio 		else
5547d4aa781Sclaudio 			flags = FLOWSPEC_FRAG_STRING6;
5557d4aa781Sclaudio 		break;
5560adb143fSclaudio 	default:
5570adb143fSclaudio 		printf("??? ");
5580adb143fSclaudio 		return;
5597d4aa781Sclaudio 	}
5607d4aa781Sclaudio 
5610adb143fSclaudio 	if (flowspec_get_component(f->data, f->len, type, is_v6,
5620adb143fSclaudio 	    &comp, &complen) != 1)
5630adb143fSclaudio 		return;
5640adb143fSclaudio 
5650adb143fSclaudio 	printf("%s ", flowspec_fmt_label(type));
5660adb143fSclaudio 
5677d4aa781Sclaudio 	fmt = flowspec_fmt_bin_op(comp, complen, &off, flags);
5687d4aa781Sclaudio 	if (off == -1) {
5697d4aa781Sclaudio 		printf("%s ", fmt);
5707d4aa781Sclaudio 	} else {
5717d4aa781Sclaudio 		printf("{ %s ", fmt);
5727d4aa781Sclaudio 		do {
5737d4aa781Sclaudio 			fmt = flowspec_fmt_bin_op(comp, complen, &off, flags);
5747d4aa781Sclaudio 			printf("%s ", fmt);
5757d4aa781Sclaudio 		} while (off != -1);
5767d4aa781Sclaudio 		printf("} ");
5777d4aa781Sclaudio 	}
5787d4aa781Sclaudio }
5797d4aa781Sclaudio 
5807d4aa781Sclaudio static void
5817d4aa781Sclaudio print_flowspec_addr(struct flowspec *f, int type, int is_v6)
5827d4aa781Sclaudio {
5837d4aa781Sclaudio 	struct bgpd_addr addr;
5847d4aa781Sclaudio 	uint8_t plen;
5857d4aa781Sclaudio 
5867d4aa781Sclaudio 	flowspec_get_addr(f->data, f->len, type, is_v6, &addr, &plen, NULL);
5877d4aa781Sclaudio 	if (plen == 0)
5887d4aa781Sclaudio 		printf("%s any ", flowspec_fmt_label(type));
5897d4aa781Sclaudio 	else
5907d4aa781Sclaudio 		printf("%s %s/%u ", flowspec_fmt_label(type),
5917d4aa781Sclaudio 		    log_addr(&addr), plen);
5927d4aa781Sclaudio }
5937d4aa781Sclaudio 
5947d4aa781Sclaudio void
5957d4aa781Sclaudio print_flowspec(struct flowspec_config *fconf, const char *c)
5967d4aa781Sclaudio {
5977d4aa781Sclaudio 	struct flowspec *f = fconf->flow;
5987d4aa781Sclaudio 	int is_v6 = (f->aid == AID_FLOWSPECv6);
5997d4aa781Sclaudio 
6007d4aa781Sclaudio 	printf("%sflowspec %s ", c, print_af(f->aid));
6017d4aa781Sclaudio 
6027d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_PROTO, is_v6);
6037d4aa781Sclaudio 
6047d4aa781Sclaudio 	print_flowspec_addr(f, FLOWSPEC_TYPE_SOURCE, is_v6);
6057d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_SRC_PORT, is_v6);
6067d4aa781Sclaudio 
6077d4aa781Sclaudio 	print_flowspec_addr(f, FLOWSPEC_TYPE_DEST, is_v6);
6087d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_DST_PORT, is_v6);
6097d4aa781Sclaudio 
6107d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_DSCP, is_v6);
6117d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_PKT_LEN, is_v6);
6127d4aa781Sclaudio 	print_flowspec_flags(f, FLOWSPEC_TYPE_TCP_FLAGS, is_v6);
6137d4aa781Sclaudio 	print_flowspec_flags(f, FLOWSPEC_TYPE_FRAG, is_v6);
6147d4aa781Sclaudio 
6157d4aa781Sclaudio 	/* TODO: fixup the code handling to be like in the parser */
6167d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_TYPE, is_v6);
6177d4aa781Sclaudio 	print_flowspec_list(f, FLOWSPEC_TYPE_ICMP_CODE, is_v6);
6187d4aa781Sclaudio 
6197d4aa781Sclaudio 	print_set(&fconf->attrset);
6207d4aa781Sclaudio 	printf("\n");
6217d4aa781Sclaudio }
6227d4aa781Sclaudio 
623294d4e13Shenning void
62459e404fbSclaudio print_as_sets(struct as_set_head *as_sets)
62559e404fbSclaudio {
62659e404fbSclaudio 	struct as_set *aset;
62739386878Sclaudio 	uint32_t *as;
62859e404fbSclaudio 	size_t i, n;
62959e404fbSclaudio 	int len;
63059e404fbSclaudio 
63159e404fbSclaudio 	SIMPLEQ_FOREACH(aset, as_sets, entry) {
63259e404fbSclaudio 		printf("as-set \"%s\" {\n\t", aset->name);
63359e404fbSclaudio 		as = set_get(aset->set, &n);
63459e404fbSclaudio 		for (i = 0, len = 8; i < n; i++) {
63559e404fbSclaudio 			if (len > 72) {
63659e404fbSclaudio 				printf("\n\t");
63759e404fbSclaudio 				len = 8;
63859e404fbSclaudio 			}
63959e404fbSclaudio 			len += printf("%u ", as[i]);
64059e404fbSclaudio 		}
64159e404fbSclaudio 		printf("\n}\n\n");
64259e404fbSclaudio 	}
64359e404fbSclaudio }
64459e404fbSclaudio 
64559e404fbSclaudio void
646441aaadcSbenno print_prefixsets(struct prefixset_head *psh)
647441aaadcSbenno {
648441aaadcSbenno 	struct prefixset	*ps;
649441aaadcSbenno 	struct prefixset_item	*psi;
650441aaadcSbenno 
651441aaadcSbenno 	SIMPLEQ_FOREACH(ps, psh, entry) {
652b7fbf694Sclaudio 		int count = 0;
6534ea66b69Sclaudio 		printf("prefix-set \"%s\" {", ps->name);
654d32b24c8Sclaudio 		RB_FOREACH(psi, prefixset_tree, &ps->psitems) {
6554ea66b69Sclaudio 			if (count++ % 2 == 0)
6564ea66b69Sclaudio 				printf("\n\t");
6574ea66b69Sclaudio 			else
6584ea66b69Sclaudio 				printf(", ");
6594ea66b69Sclaudio 			print_prefix(&psi->p);
660b7fbf694Sclaudio 		}
661b7fbf694Sclaudio 		printf("\n}\n\n");
662441aaadcSbenno 	}
663441aaadcSbenno }
664441aaadcSbenno 
665441aaadcSbenno void
6666f1dba6eSclaudio print_originsets(struct prefixset_head *psh)
667502ece1dSclaudio {
668502ece1dSclaudio 	struct prefixset	*ps;
6696aa533f4Sclaudio 	struct roa		*roa;
6706aa533f4Sclaudio 	struct bgpd_addr	 addr;
671502ece1dSclaudio 
672502ece1dSclaudio 	SIMPLEQ_FOREACH(ps, psh, entry) {
6736f1dba6eSclaudio 		printf("origin-set \"%s\" {", ps->name);
6746aa533f4Sclaudio 		RB_FOREACH(roa, roa_tree, &ps->roaitems) {
675502ece1dSclaudio 			printf("\n\t");
6766aa533f4Sclaudio 			addr.aid = roa->aid;
6776aa533f4Sclaudio 			addr.v6 = roa->prefix.inet6;
6786aa533f4Sclaudio 			printf("%s/%u", log_addr(&addr), roa->prefixlen);
6796aa533f4Sclaudio 			if (roa->prefixlen != roa->maxlen)
6806aa533f4Sclaudio 				printf(" maxlen %u", roa->maxlen);
6816aa533f4Sclaudio 			printf(" source-as %u", roa->asnum);
682502ece1dSclaudio 		}
683502ece1dSclaudio 		printf("\n}\n\n");
684502ece1dSclaudio 	}
685502ece1dSclaudio }
686502ece1dSclaudio 
687502ece1dSclaudio void
6886aa533f4Sclaudio print_roa(struct roa_tree *r)
6896f1dba6eSclaudio {
6906aa533f4Sclaudio 	struct roa	*roa;
6916f1dba6eSclaudio 
6926aa533f4Sclaudio 	if (RB_EMPTY(r))
6936f1dba6eSclaudio 		return;
6946f1dba6eSclaudio 
6956f1dba6eSclaudio 	printf("roa-set {");
6966aa533f4Sclaudio 	RB_FOREACH(roa, roa_tree, r) {
6976290e740Sclaudio 		printf("\n\t%s", log_roa(roa));
6986f1dba6eSclaudio 	}
6996f1dba6eSclaudio 	printf("\n}\n\n");
7006f1dba6eSclaudio }
7016f1dba6eSclaudio 
7026f1dba6eSclaudio void
703ff84f55eSclaudio print_aspa(struct aspa_tree *a)
704ff84f55eSclaudio {
705ff84f55eSclaudio 	struct aspa_set	*aspa;
706ff84f55eSclaudio 
707ff84f55eSclaudio 	if (RB_EMPTY(a))
708ff84f55eSclaudio 		return;
709ff84f55eSclaudio 
710ff84f55eSclaudio 	printf("aspa-set {");
711ff84f55eSclaudio 	RB_FOREACH(aspa, aspa_tree, a) {
7126290e740Sclaudio 		printf("\n\t%s", log_aspa(aspa));
713ff84f55eSclaudio 	}
714ff84f55eSclaudio 	printf("\n}\n\n");
715ff84f55eSclaudio }
716ff84f55eSclaudio 
717a2dc744eSclaudio static void
718a2dc744eSclaudio print_auth(struct auth_config *auth, const char *c)
719a2dc744eSclaudio {
720a2dc744eSclaudio 	char *method;
721a2dc744eSclaudio 
722a2dc744eSclaudio 	if (auth->method == AUTH_MD5SIG)
723a2dc744eSclaudio 		printf("%s\ttcp md5sig\n", c);
724a2dc744eSclaudio 	else if (auth->method == AUTH_IPSEC_MANUAL_ESP ||
725a2dc744eSclaudio 	    auth->method == AUTH_IPSEC_MANUAL_AH) {
726a2dc744eSclaudio 		if (auth->method == AUTH_IPSEC_MANUAL_ESP)
727a2dc744eSclaudio 			method = "esp";
728a2dc744eSclaudio 		else
729a2dc744eSclaudio 			method = "ah";
730a2dc744eSclaudio 
731a2dc744eSclaudio 		printf("%s\tipsec %s in spi %u %s XXXXXX", c, method,
732a2dc744eSclaudio 		    auth->spi_in, print_auth_alg(auth->auth_alg_in));
733a2dc744eSclaudio 		if (auth->enc_alg_in)
734a2dc744eSclaudio 			printf(" %s XXXXXX", print_enc_alg(auth->enc_alg_in));
735a2dc744eSclaudio 		printf("\n");
736a2dc744eSclaudio 
737a2dc744eSclaudio 		printf("%s\tipsec %s out spi %u %s XXXXXX", c, method,
738a2dc744eSclaudio 		    auth->spi_out, print_auth_alg(auth->auth_alg_out));
739a2dc744eSclaudio 		if (auth->enc_alg_out)
740a2dc744eSclaudio 			printf(" %s XXXXXX",
741a2dc744eSclaudio 			    print_enc_alg(auth->enc_alg_out));
742a2dc744eSclaudio 		printf("\n");
743a2dc744eSclaudio 	} else if (auth->method == AUTH_IPSEC_IKE_AH)
744a2dc744eSclaudio 		printf("%s\tipsec ah ike\n", c);
745a2dc744eSclaudio 	else if (auth->method == AUTH_IPSEC_IKE_ESP)
746a2dc744eSclaudio 		printf("%s\tipsec esp ike\n", c);
747a2dc744eSclaudio 
748a2dc744eSclaudio }
749a2dc744eSclaudio 
750ff84f55eSclaudio void
751bd9df44eSclaudio print_rtrs(struct rtr_config_head *rh)
752bd9df44eSclaudio {
753bd9df44eSclaudio 	struct rtr_config *r;
754bd9df44eSclaudio 
755bd9df44eSclaudio 	SIMPLEQ_FOREACH(r, rh, entry) {
756bd9df44eSclaudio 		printf("rtr %s {\n", log_addr(&r->remote_addr));
757bd9df44eSclaudio 		printf("\tdescr \"%s\"\n", r->descr);
758bd9df44eSclaudio 		printf("\tport %u\n", r->remote_port);
759bd9df44eSclaudio 		if (r->local_addr.aid != AID_UNSPEC)
760bd9df44eSclaudio 			printf("local-addr %s\n", log_addr(&r->local_addr));
761a2dc744eSclaudio 		print_auth(&r->auth, "");
762bd9df44eSclaudio 		printf("}\n\n");
763bd9df44eSclaudio 	}
764bd9df44eSclaudio }
765bd9df44eSclaudio 
766bd9df44eSclaudio void
767d7629114Sclaudio print_peer(struct peer *peer, struct bgpd_config *conf, const char *c)
768020327f0Shenning {
769c7bd57b6Sclaudio 	struct in_addr		 ina;
770d7629114Sclaudio 	struct peer_config	*p = &peer->conf;
771020327f0Shenning 
772d6c2e4e8Sclaudio 	if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) ||
773d6c2e4e8Sclaudio 	    (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128))
7746bf392efShenning 		printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr),
7756bf392efShenning 		    p->remote_masklen);
7766bf392efShenning 	else
777020327f0Shenning 		printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr));
778d8abd003Shenning 	if (p->descr[0])
779020327f0Shenning 		printf("%s\tdescr \"%s\"\n", c, p->descr);
78098daafc0Sclaudio 	if (p->rib[0])
78198daafc0Sclaudio 		printf("%s\trib \"%s\"\n", c, p->rib);
7826bf392efShenning 	if (p->remote_as)
7830c88bf70Sclaudio 		printf("%s\tremote-as %s\n", c, log_as(p->remote_as));
784f0bc600cSphessler 	if (p->local_as != conf->as) {
785f0bc600cSphessler 		printf("%s\tlocal-as %s", c, log_as(p->local_as));
786f0bc600cSphessler 		if (p->local_as > USHRT_MAX && p->local_short_as != AS_TRANS)
787f0bc600cSphessler 			printf(" %u", p->local_short_as);
788f0bc600cSphessler 		printf("\n");
789f0bc600cSphessler 	}
790dbdbcd65Shenning 	if (p->down)
791dbdbcd65Shenning 		printf("%s\tdown\n", c);
792020327f0Shenning 	if (p->distance > 1)
793020327f0Shenning 		printf("%s\tmultihop %u\n", c, p->distance);
794020327f0Shenning 	if (p->passive)
795020327f0Shenning 		printf("%s\tpassive\n", c);
796589de3c2Sclaudio 	if (p->local_addr_v4.aid)
797589de3c2Sclaudio 		printf("%s\tlocal-address %s\n", c,
798589de3c2Sclaudio 		    log_addr(&p->local_addr_v4));
799589de3c2Sclaudio 	if (p->local_addr_v6.aid)
800589de3c2Sclaudio 		printf("%s\tlocal-address %s\n", c,
801589de3c2Sclaudio 		    log_addr(&p->local_addr_v6));
8023c001116Sclaudio 	if (p->remote_port != BGP_PORT)
8033c001116Sclaudio 		printf("%s\tport %hu\n", c, p->remote_port);
804c0c94bccSclaudio 	if (p->role != ROLE_NONE)
805c0c94bccSclaudio 		printf("%s\trole %s\n", c, log_policy(p->role));
80668030d48Shenning 	if (p->max_prefix) {
80768030d48Shenning 		printf("%s\tmax-prefix %u", c, p->max_prefix);
80868030d48Shenning 		if (p->max_prefix_restart)
80968030d48Shenning 			printf(" restart %u", p->max_prefix_restart);
81068030d48Shenning 		printf("\n");
81168030d48Shenning 	}
812c84ce86dSclaudio 	if (p->max_out_prefix) {
813c84ce86dSclaudio 		printf("%s\tmax-prefix %u out", c, p->max_out_prefix);
814c84ce86dSclaudio 		if (p->max_out_prefix_restart)
815c84ce86dSclaudio 			printf(" restart %u", p->max_out_prefix_restart);
816c84ce86dSclaudio 		printf("\n");
817c84ce86dSclaudio 	}
818020327f0Shenning 	if (p->holdtime)
819020327f0Shenning 		printf("%s\tholdtime %u\n", c, p->holdtime);
820020327f0Shenning 	if (p->min_holdtime)
821020327f0Shenning 		printf("%s\tholdtime min %u\n", c, p->min_holdtime);
8226c15f943Sclaudio 	if (p->staletime)
8236c15f943Sclaudio 		printf("%s\tstaletime %u\n", c, p->staletime);
824f390b1a7Sclaudio 	if (p->export_type == EXPORT_NONE)
825f390b1a7Sclaudio 		printf("%s\texport none\n", c);
826f390b1a7Sclaudio 	else if (p->export_type == EXPORT_DEFAULT_ROUTE)
827f390b1a7Sclaudio 		printf("%s\texport default-route\n", c);
828c7bd57b6Sclaudio 	if (p->enforce_as == ENFORCE_AS_ON)
829c7bd57b6Sclaudio 		printf("%s\tenforce neighbor-as yes\n", c);
830c7bd57b6Sclaudio 	else
831c7bd57b6Sclaudio 		printf("%s\tenforce neighbor-as no\n", c);
8326c1bc9bcSphessler 	if (p->enforce_local_as == ENFORCE_AS_ON)
8336c1bc9bcSphessler 		printf("%s\tenforce local-as yes\n", c);
8346c1bc9bcSphessler 	else
8356c1bc9bcSphessler 		printf("%s\tenforce local-as no\n", c);
836c7bd57b6Sclaudio 	if (p->reflector_client) {
837c7bd57b6Sclaudio 		if (conf->clusterid == 0)
838c7bd57b6Sclaudio 			printf("%s\troute-reflector\n", c);
839c7bd57b6Sclaudio 		else {
840bcd6516bSclaudio 			ina.s_addr = htonl(conf->clusterid);
841c7bd57b6Sclaudio 			printf("%s\troute-reflector %s\n", c,
842c7bd57b6Sclaudio 			    inet_ntoa(ina));
843c7bd57b6Sclaudio 		}
844c7bd57b6Sclaudio 	}
84527428f9dShenning 	if (p->demote_group[0])
84627428f9dShenning 		printf("%s\tdemote %s\n", c, p->demote_group);
847dc228c27Shenning 	if (p->if_depend[0])
848dc228c27Shenning 		printf("%s\tdepend on \"%s\"\n", c, p->if_depend);
849241ce197Shenning 	if (p->flags & PEERFLAG_TRANS_AS)
850181a1be0Shenning 		printf("%s\ttransparent-as yes\n", c);
851a27194f9Shenning 
85205ebbbf6Sclaudio 	if (conf->flags & BGPD_FLAG_DECISION_ALL_PATHS) {
85305ebbbf6Sclaudio 		if (!(p->flags & PEERFLAG_EVALUATE_ALL))
85405ebbbf6Sclaudio 			printf("%s\trde evaluate default\n", c);
85505ebbbf6Sclaudio 	} else {
85605ebbbf6Sclaudio 		if (p->flags & PEERFLAG_EVALUATE_ALL)
85705ebbbf6Sclaudio 			printf("%s\trde evaluate all\n", c);
85805ebbbf6Sclaudio 	}
85905ebbbf6Sclaudio 
860*e3db1f63Sclaudio 	if (conf->flags & BGPD_FLAG_PERMIT_AS_SET) {
861*e3db1f63Sclaudio 		if (!(p->flags & PEERFLAG_PERMIT_AS_SET))
862aa528464Sclaudio 			printf("%s\treject as-set yes\n", c);
863*e3db1f63Sclaudio 	} else {
864*e3db1f63Sclaudio 		if (p->flags & PEERFLAG_PERMIT_AS_SET)
865*e3db1f63Sclaudio 			printf("%s\treject as-set no\n", c);
866aa528464Sclaudio 	}
867aa528464Sclaudio 
8687285b4d6Sphessler 	if (p->flags & PEERFLAG_LOG_UPDATES)
8697285b4d6Sphessler 		printf("%s\tlog updates\n", c);
8707285b4d6Sphessler 
871a2dc744eSclaudio 	print_auth(&peer->auth_conf, c);
872866636d1Sclaudio 
873906a57b3Shenning 	if (p->ttlsec)
874906a57b3Shenning 		printf("%s\tttl-security yes\n", c);
875906a57b3Shenning 
87686729c90Sclaudio 	print_announce(p, c);
8776987aa3aShenning 
878d288d268Sclaudio 	print_mrt(conf, p->id, p->groupid, c, "\t");
879866636d1Sclaudio 
880020327f0Shenning 	printf("%s}\n", c);
881020327f0Shenning }
882020327f0Shenning 
883a27194f9Shenning const char *
88493662c4eSclaudio print_auth_alg(enum auth_alg alg)
885a27194f9Shenning {
886a27194f9Shenning 	switch (alg) {
88793662c4eSclaudio 	case AUTH_AALG_SHA1HMAC:
888a27194f9Shenning 		return ("sha1");
88993662c4eSclaudio 	case AUTH_AALG_MD5HMAC:
890a27194f9Shenning 		return ("md5");
891a27194f9Shenning 	default:
892a27194f9Shenning 		return ("???");
893a27194f9Shenning 	}
894a27194f9Shenning }
895a27194f9Shenning 
896a27194f9Shenning const char *
89793662c4eSclaudio print_enc_alg(enum auth_enc_alg alg)
898a27194f9Shenning {
899a27194f9Shenning 	switch (alg) {
90093662c4eSclaudio 	case AUTH_EALG_3DESCBC:
901a27194f9Shenning 		return ("3des");
90293662c4eSclaudio 	case AUTH_EALG_AES:
903a27194f9Shenning 		return ("aes");
904a27194f9Shenning 	default:
905a27194f9Shenning 		return ("???");
906a27194f9Shenning 	}
907a27194f9Shenning }
908a27194f9Shenning 
9095014683fSclaudio static const char *
9105014683fSclaudio print_addpath_mode(enum addpath_mode mode)
9115014683fSclaudio {
9125014683fSclaudio 	switch (mode) {
9135014683fSclaudio 	case ADDPATH_EVAL_NONE:
9145014683fSclaudio 		return "none";
9155014683fSclaudio 	case ADDPATH_EVAL_BEST:
9165014683fSclaudio 		return "best";
9175014683fSclaudio 	case ADDPATH_EVAL_ECMP:
9185014683fSclaudio 		return "ecmp";
9195014683fSclaudio 	case ADDPATH_EVAL_AS_WIDE:
9205014683fSclaudio 		return "as-wide-best";
9215014683fSclaudio 	case ADDPATH_EVAL_ALL:
9225014683fSclaudio 		return "all";
923a6facc3cSclaudio 	default:
924a6facc3cSclaudio 		return "???";
9255014683fSclaudio 	}
9265014683fSclaudio }
9275014683fSclaudio 
92886729c90Sclaudio void
92986729c90Sclaudio print_announce(struct peer_config *p, const char *c)
9306987aa3aShenning {
93139386878Sclaudio 	uint8_t	aid;
9324b1bc0cbSclaudio 	int match = 0;
93386729c90Sclaudio 
934110c1584Sclaudio 	for (aid = AID_MIN; aid < AID_MAX; aid++)
9354b1bc0cbSclaudio 		if (p->capabilities.mp[aid] == 2) {
9364b1bc0cbSclaudio 			printf("%s\tannounce %s enforce\n", c, aid2str(aid));
9374b1bc0cbSclaudio 			match = 1;
9384b1bc0cbSclaudio 		} else if (p->capabilities.mp[aid]) {
93986729c90Sclaudio 			printf("%s\tannounce %s\n", c, aid2str(aid));
9404b1bc0cbSclaudio 			match = 1;
9414b1bc0cbSclaudio 		}
9424b1bc0cbSclaudio 	if (!match) {
9434b1bc0cbSclaudio 		printf("%s\tannounce IPv4 none\n", c);
9444b1bc0cbSclaudio 		printf("%s\tannounce IPv6 none\n", c);
9454b1bc0cbSclaudio 	}
9461114d9c2Sclaudio 
9474b1bc0cbSclaudio 	if (p->capabilities.refresh == 2)
9484b1bc0cbSclaudio 		printf("%s\tannounce refresh enforce\n", c);
9494b1bc0cbSclaudio 	else if (p->capabilities.refresh == 0)
9501114d9c2Sclaudio 		printf("%s\tannounce refresh no\n", c);
9514b1bc0cbSclaudio 
9524b1bc0cbSclaudio 	if (p->capabilities.enhanced_rr == 2)
9534b1bc0cbSclaudio 		printf("%s\tannounce enhanced refresh enforce\n", c);
9544b1bc0cbSclaudio 	else if (p->capabilities.enhanced_rr == 1)
95570078a52Sclaudio 		printf("%s\tannounce enhanced refresh yes\n", c);
9564b1bc0cbSclaudio 
9574b1bc0cbSclaudio 	if (p->capabilities.grestart.restart == 2)
9584b1bc0cbSclaudio 		printf("%s\tannounce restart enforce\n", c);
9594b1bc0cbSclaudio 	else if (p->capabilities.grestart.restart == 0)
9601114d9c2Sclaudio 		printf("%s\tannounce restart no\n", c);
9614b1bc0cbSclaudio 
9626c15f943Sclaudio 	if (p->capabilities.grestart.restart != 0 &&
9636c15f943Sclaudio 	    p->capabilities.grestart.grnotification)
9646c15f943Sclaudio 		printf("%s\tannounce graceful notification yes\n", c);
9656c15f943Sclaudio 
9664b1bc0cbSclaudio 	if (p->capabilities.as4byte == 2)
9674b1bc0cbSclaudio 		printf("%s\tannounce as4byte enforce\n", c);
9684b1bc0cbSclaudio 	else if (p->capabilities.as4byte == 0)
9691114d9c2Sclaudio 		printf("%s\tannounce as4byte no\n", c);
9704b1bc0cbSclaudio 
97125cbba3aSclaudio 	if (p->capabilities.ext_msg == 2)
97263aaa84cSclaudio 		printf("%s\tannounce extended message enforce\n", c);
97325cbba3aSclaudio 	else if (p->capabilities.ext_msg == 1)
97463aaa84cSclaudio 		printf("%s\tannounce extended message yes\n", c);
97525cbba3aSclaudio 
976927cc6daSclaudio 	if (p->capabilities.ext_nh[AID_INET] == 2)
977927cc6daSclaudio 		printf("%s\tannounce extended nexthop enforce\n", c);
978927cc6daSclaudio 	else if (p->capabilities.ext_nh[AID_INET] == 1)
979927cc6daSclaudio 		printf("%s\tannounce extended nexthop yes\n", c);
980927cc6daSclaudio 
9814b1bc0cbSclaudio 	if (p->capabilities.add_path[AID_MIN] & CAPA_AP_RECV_ENFORCE)
9824b1bc0cbSclaudio 		printf("%s\tannounce add-path recv enforce\n", c);
9834b1bc0cbSclaudio 	else if (p->capabilities.add_path[AID_MIN] & CAPA_AP_RECV)
9841114d9c2Sclaudio 		printf("%s\tannounce add-path recv yes\n", c);
9854b1bc0cbSclaudio 
9864b1bc0cbSclaudio 	if (p->capabilities.add_path[AID_MIN] & CAPA_AP_SEND) {
9875014683fSclaudio 		printf("%s\tannounce add-path send %s", c,
9885014683fSclaudio 		    print_addpath_mode(p->eval.mode));
9895014683fSclaudio 		if (p->eval.extrapaths != 0)
9905014683fSclaudio 			printf(" plus %d", p->eval.extrapaths);
9915014683fSclaudio 		if (p->eval.maxpaths != 0)
9925014683fSclaudio 			printf(" max %d", p->eval.maxpaths);
9934b1bc0cbSclaudio 		if (p->capabilities.add_path[AID_MIN] & CAPA_AP_SEND_ENFORCE)
9944b1bc0cbSclaudio 			printf(" enforce");
9955014683fSclaudio 		printf("\n");
9965014683fSclaudio 	}
9974b1bc0cbSclaudio 
9984b1bc0cbSclaudio 	if (p->capabilities.policy == 2)
9994b1bc0cbSclaudio 		printf("%s\tannounce policy enforce\n", c);
10004b1bc0cbSclaudio 	else if (p->capabilities.policy == 1)
10014b1bc0cbSclaudio 		printf("%s\tannounce policy yes\n", c);
10024b1bc0cbSclaudio 	else
10034b1bc0cbSclaudio 		printf("%s\tannounce policy no\n", c);
10046987aa3aShenning }
10056987aa3aShenning 
1006043e486bSclaudio void
1007043e486bSclaudio print_as(struct filter_rule *r)
1008708dc8caSbenno {
1009a8e18e82Sclaudio 	if (r->match.as.flags & AS_FLAG_AS_SET_NAME) {
1010a8e18e82Sclaudio 		printf("as-set \"%s\" ", r->match.as.name);
1011a8e18e82Sclaudio 		return;
1012a8e18e82Sclaudio 	}
1013708dc8caSbenno 	switch (r->match.as.op) {
1014708dc8caSbenno 	case OP_RANGE:
1015708dc8caSbenno 		printf("%s - ", log_as(r->match.as.as_min));
1016708dc8caSbenno 		printf("%s ", log_as(r->match.as.as_max));
1017708dc8caSbenno 		break;
1018708dc8caSbenno 	case OP_XRANGE:
1019708dc8caSbenno 		printf("%s >< ", log_as(r->match.as.as_min));
1020708dc8caSbenno 		printf("%s ", log_as(r->match.as.as_max));
1021708dc8caSbenno 		break;
1022708dc8caSbenno 	case OP_NE:
1023052562feSclaudio 		printf("!= %s ", log_as(r->match.as.as_min));
1024708dc8caSbenno 		break;
1025708dc8caSbenno 	default:
1026052562feSclaudio 		printf("%s ", log_as(r->match.as.as_min));
1027708dc8caSbenno 		break;
1028708dc8caSbenno 	}
1029708dc8caSbenno }
1030708dc8caSbenno 
1031020327f0Shenning void
103282fc6237Sclaudio print_rule(struct bgpd_config *conf, struct filter_rule *r)
1033977216a6Shenning {
1034977216a6Shenning 	struct peer *p;
1035dd87f852Sclaudio 	int i;
1036977216a6Shenning 
1037977216a6Shenning 	if (r->action == ACTION_ALLOW)
1038977216a6Shenning 		printf("allow ");
1039977216a6Shenning 	else if (r->action == ACTION_DENY)
1040977216a6Shenning 		printf("deny ");
1041977216a6Shenning 	else
1042977216a6Shenning 		printf("match ");
1043977216a6Shenning 	if (r->quick)
1044977216a6Shenning 		printf("quick ");
1045977216a6Shenning 
1046faa8a8beSclaudio 	if (r->rib[0])
1047faa8a8beSclaudio 		printf("rib %s ", r->rib);
1048faa8a8beSclaudio 
1049977216a6Shenning 	if (r->dir == DIR_IN)
1050977216a6Shenning 		printf("from ");
1051977216a6Shenning 	else if (r->dir == DIR_OUT)
1052977216a6Shenning 		printf("to ");
1053977216a6Shenning 	else
1054977216a6Shenning 		printf("eeeeeeeps. ");
1055977216a6Shenning 
1056977216a6Shenning 	if (r->peer.peerid) {
10577876190cSclaudio 		RB_FOREACH(p, peer_head, &conf->peers)
105882fc6237Sclaudio 			if (p->conf.id == r->peer.peerid)
105982fc6237Sclaudio 				break;
1060977216a6Shenning 		if (p == NULL)
1061977216a6Shenning 			printf("? ");
1062977216a6Shenning 		else
1063977216a6Shenning 			printf("%s ", log_addr(&p->conf.remote_addr));
1064977216a6Shenning 	} else if (r->peer.groupid) {
10657876190cSclaudio 		RB_FOREACH(p, peer_head, &conf->peers)
106682fc6237Sclaudio 			if (p->conf.groupid == r->peer.groupid)
106782fc6237Sclaudio 				break;
1068977216a6Shenning 		if (p == NULL)
1069977216a6Shenning 			printf("group ? ");
1070977216a6Shenning 		else
1071c81b3773Sclaudio 			printf("group \"%s\" ", p->conf.group);
107251e30accSphessler 	} else if (r->peer.remote_as) {
107351e30accSphessler 		printf("AS %s ", log_as(r->peer.remote_as));
1074b28cd7d4Sphessler 	} else if (r->peer.ebgp) {
1075b28cd7d4Sphessler 		printf("ebgp ");
1076b28cd7d4Sphessler 	} else if (r->peer.ibgp) {
1077b28cd7d4Sphessler 		printf("ibgp ");
1078977216a6Shenning 	} else
1079977216a6Shenning 		printf("any ");
1080977216a6Shenning 
10816f1dba6eSclaudio 	if (r->match.ovs.is_set) {
10826f1dba6eSclaudio 		switch (r->match.ovs.validity) {
10836f1dba6eSclaudio 		case ROA_VALID:
10846f1dba6eSclaudio 			printf("ovs valid ");
10856f1dba6eSclaudio 			break;
10866f1dba6eSclaudio 		case ROA_INVALID:
10876f1dba6eSclaudio 			printf("ovs invalid ");
10886f1dba6eSclaudio 			break;
10896f1dba6eSclaudio 		case ROA_NOTFOUND:
10906f1dba6eSclaudio 			printf("ovs not-found ");
10916f1dba6eSclaudio 			break;
10926f1dba6eSclaudio 		default:
10936f1dba6eSclaudio 			printf("ovs ??? %d ??? ", r->match.ovs.validity);
10946f1dba6eSclaudio 		}
10956f1dba6eSclaudio 	}
10966f1dba6eSclaudio 
1097060f4cb2Sclaudio 	if (r->match.avs.is_set) {
1098060f4cb2Sclaudio 		switch (r->match.avs.validity) {
1099060f4cb2Sclaudio 		case ASPA_VALID:
1100060f4cb2Sclaudio 			printf("avs valid ");
1101060f4cb2Sclaudio 			break;
1102060f4cb2Sclaudio 		case ASPA_INVALID:
1103060f4cb2Sclaudio 			printf("avs invalid ");
1104060f4cb2Sclaudio 			break;
1105060f4cb2Sclaudio 		case ASPA_UNKNOWN:
1106060f4cb2Sclaudio 			printf("avs unknown ");
1107060f4cb2Sclaudio 			break;
1108060f4cb2Sclaudio 		default:
1109060f4cb2Sclaudio 			printf("avs ??? %d ??? ", r->match.avs.validity);
1110060f4cb2Sclaudio 		}
1111060f4cb2Sclaudio 	}
1112060f4cb2Sclaudio 
11134ea66b69Sclaudio 	if (r->match.prefix.addr.aid != AID_UNSPEC) {
11144ea66b69Sclaudio 		printf("prefix ");
11154ea66b69Sclaudio 		print_prefix(&r->match.prefix);
11164ea66b69Sclaudio 		printf(" ");
11174ea66b69Sclaudio 	}
1118977216a6Shenning 
11196f1dba6eSclaudio 	if (r->match.prefixset.name[0] != '\0')
1120441aaadcSbenno 		printf("prefix-set \"%s\" ", r->match.prefixset.name);
11219ed42aa2Sbenno 	if (r->match.prefixset.flags & PREFIXSET_FLAG_LONGER)
11229ed42aa2Sbenno 		printf("or-longer ");
1123441aaadcSbenno 
11246f1dba6eSclaudio 	if (r->match.originset.name[0] != '\0')
11256f1dba6eSclaudio 		printf("origin-set \"%s\" ", r->match.originset.name);
11266f1dba6eSclaudio 
1127e0a3dc9bSclaudio 	if (r->match.nexthop.flags) {
1128e0a3dc9bSclaudio 		if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR)
1129e0a3dc9bSclaudio 			printf("nexthop neighbor ");
1130e0a3dc9bSclaudio 		else
1131e0a3dc9bSclaudio 			printf("nexthop %s ", log_addr(&r->match.nexthop.addr));
1132e0a3dc9bSclaudio 	}
1133e0a3dc9bSclaudio 
1134977216a6Shenning 	if (r->match.as.type) {
1135977216a6Shenning 		if (r->match.as.type == AS_ALL)
1136708dc8caSbenno 			printf("AS ");
1137977216a6Shenning 		else if (r->match.as.type == AS_SOURCE)
1138708dc8caSbenno 			printf("source-as ");
1139977216a6Shenning 		else if (r->match.as.type == AS_TRANSIT)
1140708dc8caSbenno 			printf("transit-as ");
11414768e43cShenning 		else if (r->match.as.type == AS_PEER)
1142708dc8caSbenno 			printf("peer-as ");
1143977216a6Shenning 		else
1144708dc8caSbenno 			printf("unfluffy-as ");
1145708dc8caSbenno 		print_as(r);
1146977216a6Shenning 	}
1147977216a6Shenning 
11484a044d31Sclaudio 	if (r->match.aslen.type) {
11494a044d31Sclaudio 		printf("%s %u ", r->match.aslen.type == ASLEN_MAX ?
11504a044d31Sclaudio 		    "max-as-len" : "max-as-seq", r->match.aslen.aslen);
11514a044d31Sclaudio 	}
11524a044d31Sclaudio 
1153dd87f852Sclaudio 	for (i = 0; i < MAX_COMM_MATCH; i++) {
1154e7adcfeaSclaudio 		struct community *c = &r->match.community[i];
1155e7adcfeaSclaudio 		if (c->flags != 0) {
1156dd87f852Sclaudio 			printf("%s ", community_type(c));
1157dd87f852Sclaudio 			print_community(c);
1158dd87f852Sclaudio 		}
11590df2230cSclaudio 	}
11600df2230cSclaudio 
1161bd0e176eSclaudio 	if (r->match.maxcomm != 0)
1162bd0e176eSclaudio 		printf("max-communities %d ", r->match.maxcomm - 1);
1163bd0e176eSclaudio 	if (r->match.maxextcomm != 0)
1164bd0e176eSclaudio 		printf("max-ext-communities %d ", r->match.maxextcomm - 1);
1165bd0e176eSclaudio 	if (r->match.maxlargecomm != 0)
1166bd0e176eSclaudio 		printf("max-large-communities %d ", r->match.maxlargecomm - 1);
1167bd0e176eSclaudio 
1168866636d1Sclaudio 	print_set(&r->set);
1169977216a6Shenning 
1170977216a6Shenning 	printf("\n");
1171977216a6Shenning }
1172020327f0Shenning 
1173866636d1Sclaudio const char *
1174866636d1Sclaudio mrt_type(enum mrt_type t)
1175866636d1Sclaudio {
1176866636d1Sclaudio 	switch (t) {
1177866636d1Sclaudio 	case MRT_NONE:
1178dfafe578Sclaudio 		break;
1179866636d1Sclaudio 	case MRT_TABLE_DUMP:
1180866636d1Sclaudio 		return "table";
1181dfafe578Sclaudio 	case MRT_TABLE_DUMP_MP:
1182dfafe578Sclaudio 		return "table-mp";
1183566a7707Sclaudio 	case MRT_TABLE_DUMP_V2:
1184566a7707Sclaudio 		return "table-v2";
1185866636d1Sclaudio 	case MRT_ALL_IN:
1186866636d1Sclaudio 		return "all in";
1187866636d1Sclaudio 	case MRT_ALL_OUT:
1188866636d1Sclaudio 		return "all out";
1189866636d1Sclaudio 	case MRT_UPDATE_IN:
1190866636d1Sclaudio 		return "updates in";
1191866636d1Sclaudio 	case MRT_UPDATE_OUT:
1192866636d1Sclaudio 		return "updates out";
1193866636d1Sclaudio 	}
1194866636d1Sclaudio 	return "unfluffy MRT";
1195866636d1Sclaudio }
1196866636d1Sclaudio 
1197866636d1Sclaudio void
119839386878Sclaudio print_mrt(struct bgpd_config *conf, uint32_t pid, uint32_t gid,
1199d288d268Sclaudio     const char *prep, const char *prep2)
1200866636d1Sclaudio {
1201866636d1Sclaudio 	struct mrt	*m;
1202866636d1Sclaudio 
1203d288d268Sclaudio 	if (conf->mrt == NULL)
1204866636d1Sclaudio 		return;
1205866636d1Sclaudio 
1206d288d268Sclaudio 	LIST_FOREACH(m, conf->mrt, entry)
12073ac41105Sclaudio 		if ((gid != 0 && m->group_id == gid) ||
12083ac41105Sclaudio 		    (m->peer_id == pid && m->group_id == gid)) {
120998daafc0Sclaudio 			printf("%s%sdump ", prep, prep2);
121098daafc0Sclaudio 			if (m->rib[0])
121198daafc0Sclaudio 				printf("rib %s ", m->rib);
1212566a7707Sclaudio 			printf("%s \"%s\"", mrt_type(m->type),
121398daafc0Sclaudio 			    MRT2MC(m)->name);
1214566a7707Sclaudio 			if (MRT2MC(m)->ReopenTimerInterval == 0)
1215566a7707Sclaudio 				printf("\n");
1216866636d1Sclaudio 			else
1217566a7707Sclaudio 				printf(" %d\n", MRT2MC(m)->ReopenTimerInterval);
1218866636d1Sclaudio 		}
121963a28b9cSbenno 	if (!LIST_EMPTY(conf->mrt))
122063a28b9cSbenno 		printf("\n");
1221866636d1Sclaudio }
1222866636d1Sclaudio 
1223020327f0Shenning void
122482fc6237Sclaudio print_groups(struct bgpd_config *conf)
1225cbcb38a8Shenning {
1226d7629114Sclaudio 	struct peer	**peerlist;
1227cbcb38a8Shenning 	struct peer	 *p;
1228cbcb38a8Shenning 	u_int		  peer_cnt, i;
122939386878Sclaudio 	uint32_t	  prev_groupid;
1230cbcb38a8Shenning 	const char	 *c;
1231cbcb38a8Shenning 
1232cbcb38a8Shenning 	peer_cnt = 0;
12337876190cSclaudio 	RB_FOREACH(p, peer_head, &conf->peers)
1234cbcb38a8Shenning 		peer_cnt++;
1235d7629114Sclaudio 	if ((peerlist = calloc(peer_cnt, sizeof(*peerlist))) == NULL)
1236cbcb38a8Shenning 		fatal("print_groups calloc");
1237cbcb38a8Shenning 	i = 0;
12387876190cSclaudio 	RB_FOREACH(p, peer_head, &conf->peers)
1239d7629114Sclaudio 		peerlist[i++] = p;
1240cbcb38a8Shenning 
1241d7629114Sclaudio 	qsort(peerlist, peer_cnt, sizeof(*peerlist), peer_compare);
1242cbcb38a8Shenning 
1243cbcb38a8Shenning 	prev_groupid = 0;
1244cbcb38a8Shenning 	for (i = 0; i < peer_cnt; i++) {
1245d7629114Sclaudio 		if (peerlist[i]->conf.groupid) {
1246d7629114Sclaudio 			c = "\t";
1247d7629114Sclaudio 			if (peerlist[i]->conf.groupid != prev_groupid) {
1248cbcb38a8Shenning 				if (prev_groupid)
1249cbcb38a8Shenning 					printf("}\n\n");
1250d7629114Sclaudio 				printf("group \"%s\" {\n",
1251d7629114Sclaudio 				    peerlist[i]->conf.group);
1252d7629114Sclaudio 				prev_groupid = peerlist[i]->conf.groupid;
1253cbcb38a8Shenning 			}
1254cbcb38a8Shenning 		} else
1255d7629114Sclaudio 			c = "";
1256cbcb38a8Shenning 
1257cbcb38a8Shenning 		print_peer(peerlist[i], conf, c);
1258cbcb38a8Shenning 	}
1259cbcb38a8Shenning 
1260cbcb38a8Shenning 	if (prev_groupid)
1261cbcb38a8Shenning 		printf("}\n\n");
1262cbcb38a8Shenning 
1263cbcb38a8Shenning 	free(peerlist);
1264cbcb38a8Shenning }
1265cbcb38a8Shenning 
1266cbcb38a8Shenning int
1267cbcb38a8Shenning peer_compare(const void *aa, const void *bb)
1268cbcb38a8Shenning {
1269d7629114Sclaudio 	const struct peer * const *a;
1270d7629114Sclaudio 	const struct peer * const *b;
1271cbcb38a8Shenning 
1272cbcb38a8Shenning 	a = aa;
1273cbcb38a8Shenning 	b = bb;
1274cbcb38a8Shenning 
1275d7629114Sclaudio 	return ((*a)->conf.groupid - (*b)->conf.groupid);
1276cbcb38a8Shenning }
1277cbcb38a8Shenning 
1278cbcb38a8Shenning void
127982fc6237Sclaudio print_config(struct bgpd_config *conf, struct rib_names *rib_l)
1280020327f0Shenning {
1281020327f0Shenning 	struct filter_rule	*r;
1282294d4e13Shenning 	struct network		*n;
12837d4aa781Sclaudio 	struct flowspec_config	*f;
128498daafc0Sclaudio 	struct rde_rib		*rr;
12854e0c4e97Sclaudio 	struct l3vpn		*vpn;
1286020327f0Shenning 
1287020327f0Shenning 	print_mainconf(conf);
1288bd9df44eSclaudio 	print_rtrs(&conf->rtrs);
12896f1dba6eSclaudio 	print_roa(&conf->roa);
1290ff84f55eSclaudio 	print_aspa(&conf->aspa);
1291965dc109Sclaudio 	print_as_sets(&conf->as_sets);
12926f1dba6eSclaudio 	print_prefixsets(&conf->prefixsets);
12936f1dba6eSclaudio 	print_originsets(&conf->originsets);
129482fc6237Sclaudio 	TAILQ_FOREACH(n, &conf->networks, entry)
12951274ebf8Sclaudio 		print_network(&n->net, "");
12967d4aa781Sclaudio 	RB_FOREACH(f, flowspec_tree, &conf->flowspecs)
12977d4aa781Sclaudio 		print_flowspec(f, "");
129882fc6237Sclaudio 	if (!SIMPLEQ_EMPTY(&conf->l3vpns))
1299610bcb44Sclaudio 		printf("\n");
130082fc6237Sclaudio 	SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry)
13014e0c4e97Sclaudio 		print_l3vpn(vpn);
1302610bcb44Sclaudio 	printf("\n");
130389ee02f7Sclaudio 	if (conf->filtered_in_locrib)
130489ee02f7Sclaudio 		printf("rde rib Loc-RIB include filtered\n");
130598daafc0Sclaudio 	SIMPLEQ_FOREACH(rr, rib_l, entry) {
130698daafc0Sclaudio 		if (rr->flags & F_RIB_NOEVALUATE)
130798daafc0Sclaudio 			printf("rde rib %s no evaluate\n", rr->name);
1308459fcfe4Sclaudio 		else if (rr->flags & F_RIB_NOFIB)
130998daafc0Sclaudio 			printf("rde rib %s\n", rr->name);
1310459fcfe4Sclaudio 		else
1311459fcfe4Sclaudio 			printf("rde rib %s rtable %u fib-update %s\n", rr->name,
1312459fcfe4Sclaudio 			    rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ?
1313459fcfe4Sclaudio 			    "no" : "yes");
131498daafc0Sclaudio 	}
131598daafc0Sclaudio 	printf("\n");
1316d288d268Sclaudio 	print_mrt(conf, 0, 0, "", "");
131782fc6237Sclaudio 	print_groups(conf);
131882fc6237Sclaudio 	TAILQ_FOREACH(r, conf->filters, entry)
131982fc6237Sclaudio 		print_rule(conf, r);
1320020327f0Shenning }
1321