1 /* $OpenBSD: printconf.c,v 1.156 2022/07/11 17:08:21 claudio 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 "session.h" 28 #include "rde.h" 29 #include "log.h" 30 31 void print_prefix(struct filter_prefix *p); 32 const char *community_type(struct community *c); 33 void print_community(struct community *c); 34 void print_origin(uint8_t); 35 void print_set(struct filter_set_head *); 36 void print_mainconf(struct bgpd_config *); 37 void print_l3vpn_targets(struct filter_set_head *, const char *); 38 void print_l3vpn(struct l3vpn *); 39 const char *print_af(uint8_t); 40 void print_network(struct network_config *, const char *); 41 void print_as_sets(struct as_set_head *); 42 void print_prefixsets(struct prefixset_head *); 43 void print_originsets(struct prefixset_head *); 44 void print_roa(struct roa_tree *); 45 void print_rtrs(struct rtr_config_head *); 46 void print_peer(struct peer_config *, struct bgpd_config *, 47 const char *); 48 const char *print_auth_alg(enum auth_alg); 49 const char *print_enc_alg(enum auth_enc_alg); 50 void print_announce(struct peer_config *, const char *); 51 void print_as(struct filter_rule *); 52 void print_rule(struct bgpd_config *, struct filter_rule *); 53 const char *mrt_type(enum mrt_type); 54 void print_mrt(struct bgpd_config *, uint32_t, uint32_t, 55 const char *, const char *); 56 void print_groups(struct bgpd_config *); 57 int peer_compare(const void *, const void *); 58 59 void 60 print_prefix(struct filter_prefix *p) 61 { 62 uint8_t max_len = 0; 63 64 switch (p->addr.aid) { 65 case AID_INET: 66 case AID_VPN_IPv4: 67 max_len = 32; 68 break; 69 case AID_INET6: 70 case AID_VPN_IPv6: 71 max_len = 128; 72 break; 73 case AID_UNSPEC: 74 /* no prefix to print */ 75 return; 76 } 77 78 printf("%s/%u", log_addr(&p->addr), p->len); 79 80 switch (p->op) { 81 case OP_NONE: 82 break; 83 case OP_NE: 84 printf(" prefixlen != %u", p->len_min); 85 break; 86 case OP_XRANGE: 87 printf(" prefixlen %u >< %u ", p->len_min, p->len_max); 88 break; 89 case OP_RANGE: 90 if (p->len_min == p->len_max && p->len != p->len_min) 91 printf(" prefixlen = %u", p->len_min); 92 else if (p->len == p->len_min && p->len_max == max_len) 93 printf(" or-longer"); 94 else if (p->len == p->len_min && p->len != p->len_max) 95 printf(" maxlen %u", p->len_max); 96 else if (p->len_max == max_len) 97 printf(" prefixlen >= %u", p->len_min); 98 else 99 printf(" prefixlen %u - %u", p->len_min, p->len_max); 100 break; 101 default: 102 printf(" prefixlen %u ??? %u", p->len_min, p->len_max); 103 break; 104 } 105 } 106 107 const char * 108 community_type(struct community *c) 109 { 110 switch ((uint8_t)c->flags) { 111 case COMMUNITY_TYPE_BASIC: 112 return "community"; 113 case COMMUNITY_TYPE_LARGE: 114 return "large-community"; 115 case COMMUNITY_TYPE_EXT: 116 return "ext-community"; 117 default: 118 return "???"; 119 } 120 } 121 122 void 123 print_community(struct community *c) 124 { 125 struct in_addr addr; 126 int type; 127 uint8_t subtype; 128 129 switch ((uint8_t)c->flags) { 130 case COMMUNITY_TYPE_BASIC: 131 switch ((c->flags >> 8) & 0xff) { 132 case COMMUNITY_ANY: 133 printf("*:"); 134 break; 135 case COMMUNITY_NEIGHBOR_AS: 136 printf("neighbor-as:"); 137 break; 138 case COMMUNITY_LOCAL_AS: 139 printf("local-as:"); 140 break; 141 default: 142 printf("%u:", c->data1); 143 break; 144 } 145 switch ((c->flags >> 16) & 0xff) { 146 case COMMUNITY_ANY: 147 printf("* "); 148 break; 149 case COMMUNITY_NEIGHBOR_AS: 150 printf("neighbor-as "); 151 break; 152 case COMMUNITY_LOCAL_AS: 153 printf("local-as "); 154 break; 155 default: 156 printf("%u ", c->data2); 157 break; 158 } 159 break; 160 case COMMUNITY_TYPE_LARGE: 161 switch ((c->flags >> 8) & 0xff) { 162 case COMMUNITY_ANY: 163 printf("*:"); 164 break; 165 case COMMUNITY_NEIGHBOR_AS: 166 printf("neighbor-as:"); 167 break; 168 case COMMUNITY_LOCAL_AS: 169 printf("local-as:"); 170 break; 171 default: 172 printf("%u:", c->data1); 173 break; 174 } 175 switch ((c->flags >> 16) & 0xff) { 176 case COMMUNITY_ANY: 177 printf("*:"); 178 break; 179 case COMMUNITY_NEIGHBOR_AS: 180 printf("neighbor-as:"); 181 break; 182 case COMMUNITY_LOCAL_AS: 183 printf("local-as:"); 184 break; 185 default: 186 printf("%u:", c->data2); 187 break; 188 } 189 switch ((c->flags >> 24) & 0xff) { 190 case COMMUNITY_ANY: 191 printf("* "); 192 break; 193 case COMMUNITY_NEIGHBOR_AS: 194 printf("neighbor-as "); 195 break; 196 case COMMUNITY_LOCAL_AS: 197 printf("local-as "); 198 break; 199 default: 200 printf("%u ", c->data3); 201 break; 202 } 203 break; 204 case COMMUNITY_TYPE_EXT: 205 if ((c->flags >> 24 & 0xff) == COMMUNITY_ANY) { 206 printf("* * "); 207 break; 208 } 209 type = (int32_t)c->data3 >> 8; 210 subtype = c->data3; 211 printf("%s ", log_ext_subtype(type, subtype)); 212 if ((c->flags >> 8 & 0xff) == COMMUNITY_ANY) { 213 printf("* "); 214 break; 215 } 216 217 switch (type) { 218 case EXT_COMMUNITY_TRANS_TWO_AS: 219 case EXT_COMMUNITY_TRANS_FOUR_AS: 220 if ((c->flags >> 8 & 0xff) == COMMUNITY_NEIGHBOR_AS) 221 printf("neighbor-as:"); 222 else if ((c->flags >> 8 & 0xff) == COMMUNITY_LOCAL_AS) 223 printf("local-as:"); 224 else 225 printf("%s:", log_as(c->data1)); 226 break; 227 case EXT_COMMUNITY_TRANS_IPV4: 228 addr.s_addr = htonl(c->data1); 229 printf("%s:", inet_ntoa(addr)); 230 break; 231 } 232 233 switch (type) { 234 case EXT_COMMUNITY_TRANS_TWO_AS: 235 case EXT_COMMUNITY_TRANS_FOUR_AS: 236 case EXT_COMMUNITY_TRANS_IPV4: 237 if ((c->flags >> 16 & 0xff) == COMMUNITY_ANY) 238 printf("* "); 239 else if ((c->flags >> 16 & 0xff) == 240 COMMUNITY_NEIGHBOR_AS) 241 printf("neighbor-as "); 242 else if ((c->flags >> 16 & 0xff) == COMMUNITY_LOCAL_AS) 243 printf("local-as "); 244 else 245 printf("%u ", c->data2); 246 break; 247 case EXT_COMMUNITY_NON_TRANS_OPAQUE: 248 if (subtype == EXT_COMMUNITY_SUBTYPE_OVS) { 249 switch (c->data2) { 250 case EXT_COMMUNITY_OVS_VALID: 251 printf("valid "); 252 break; 253 case EXT_COMMUNITY_OVS_NOTFOUND: 254 printf("not-found "); 255 break; 256 case EXT_COMMUNITY_OVS_INVALID: 257 printf("invalid "); 258 break; 259 } 260 break; 261 } 262 printf("0x%x%08x ", c->data1 & 0xffff, c->data2); 263 break; 264 case EXT_COMMUNITY_TRANS_OPAQUE: 265 case EXT_COMMUNITY_TRANS_EVPN: 266 default: 267 printf("0x%x%08x ", c->data1 & 0xffff, c->data2); 268 break; 269 } 270 } 271 } 272 273 void 274 print_origin(uint8_t o) 275 { 276 if (o == ORIGIN_IGP) 277 printf("igp "); 278 else if (o == ORIGIN_EGP) 279 printf("egp "); 280 else if (o == ORIGIN_INCOMPLETE) 281 printf("incomplete "); 282 else 283 printf("%u ", o); 284 } 285 286 void 287 print_set(struct filter_set_head *set) 288 { 289 struct filter_set *s; 290 291 if (TAILQ_EMPTY(set)) 292 return; 293 294 printf("set { "); 295 TAILQ_FOREACH(s, set, entry) { 296 switch (s->type) { 297 case ACTION_SET_LOCALPREF: 298 printf("localpref %u ", s->action.metric); 299 break; 300 case ACTION_SET_RELATIVE_LOCALPREF: 301 printf("localpref %+d ", s->action.relative); 302 break; 303 case ACTION_SET_MED: 304 printf("metric %u ", s->action.metric); 305 break; 306 case ACTION_SET_RELATIVE_MED: 307 printf("metric %+d ", s->action.relative); 308 break; 309 case ACTION_SET_WEIGHT: 310 printf("weight %u ", s->action.metric); 311 break; 312 case ACTION_SET_RELATIVE_WEIGHT: 313 printf("weight %+d ", s->action.relative); 314 break; 315 case ACTION_SET_NEXTHOP: 316 printf("nexthop %s ", log_addr(&s->action.nexthop)); 317 break; 318 case ACTION_SET_NEXTHOP_REJECT: 319 printf("nexthop reject "); 320 break; 321 case ACTION_SET_NEXTHOP_BLACKHOLE: 322 printf("nexthop blackhole "); 323 break; 324 case ACTION_SET_NEXTHOP_NOMODIFY: 325 printf("nexthop no-modify "); 326 break; 327 case ACTION_SET_NEXTHOP_SELF: 328 printf("nexthop self "); 329 break; 330 case ACTION_SET_PREPEND_SELF: 331 printf("prepend-self %u ", s->action.prepend); 332 break; 333 case ACTION_SET_PREPEND_PEER: 334 printf("prepend-neighbor %u ", s->action.prepend); 335 break; 336 case ACTION_SET_AS_OVERRIDE: 337 printf("as-override "); 338 break; 339 case ACTION_DEL_COMMUNITY: 340 printf("%s delete ", 341 community_type(&s->action.community)); 342 print_community(&s->action.community); 343 break; 344 case ACTION_SET_COMMUNITY: 345 printf("%s ", community_type(&s->action.community)); 346 print_community(&s->action.community); 347 break; 348 case ACTION_PFTABLE: 349 printf("pftable %s ", s->action.pftable); 350 break; 351 case ACTION_RTLABEL: 352 printf("rtlabel %s ", s->action.rtlabel); 353 break; 354 case ACTION_SET_ORIGIN: 355 printf("origin "); 356 print_origin(s->action.origin); 357 break; 358 case ACTION_RTLABEL_ID: 359 case ACTION_PFTABLE_ID: 360 case ACTION_SET_NEXTHOP_REF: 361 /* not possible */ 362 printf("king bula saiz: config broken"); 363 break; 364 } 365 } 366 printf("}"); 367 } 368 369 void 370 print_mainconf(struct bgpd_config *conf) 371 { 372 struct in_addr ina; 373 struct listen_addr *la; 374 375 printf("AS %s", log_as(conf->as)); 376 if (conf->as > USHRT_MAX && conf->short_as != AS_TRANS) 377 printf(" %u", conf->short_as); 378 ina.s_addr = conf->bgpid; 379 printf("\nrouter-id %s\n", inet_ntoa(ina)); 380 381 printf("socket \"%s\"\n", conf->csock); 382 if (conf->rcsock) 383 printf("socket \"%s\" restricted\n", conf->rcsock); 384 if (conf->holdtime != INTERVAL_HOLD) 385 printf("holdtime %u\n", conf->holdtime); 386 if (conf->min_holdtime != MIN_HOLDTIME) 387 printf("holdtime min %u\n", conf->min_holdtime); 388 if (conf->connectretry != INTERVAL_CONNECTRETRY) 389 printf("connect-retry %u\n", conf->connectretry); 390 391 if (conf->flags & BGPD_FLAG_DECISION_ROUTEAGE) 392 printf("rde route-age evaluate\n"); 393 if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS) 394 printf("rde med compare always\n"); 395 if (conf->flags & BGPD_FLAG_DECISION_ALL_PATHS) 396 printf("rde evaluate all\n"); 397 398 if (conf->flags & BGPD_FLAG_NO_AS_SET) 399 printf("reject as-set yes\n"); 400 401 if (conf->log & BGPD_LOG_UPDATES) 402 printf("log updates\n"); 403 404 TAILQ_FOREACH(la, conf->listen_addrs, entry) { 405 struct bgpd_addr addr; 406 uint16_t port; 407 408 sa2addr((struct sockaddr *)&la->sa, &addr, &port); 409 printf("listen on %s", 410 log_sockaddr((struct sockaddr *)&la->sa, la->sa_len)); 411 if (port != BGP_PORT) 412 printf(" port %hu", port); 413 printf("\n"); 414 } 415 416 if (conf->flags & BGPD_FLAG_NEXTHOP_BGP) 417 printf("nexthop qualify via bgp\n"); 418 if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) 419 printf("nexthop qualify via default\n"); 420 if (conf->fib_priority != RTP_BGP) 421 printf("fib-priority %hhu\n", conf->fib_priority); 422 printf("\n"); 423 } 424 425 void 426 print_l3vpn_targets(struct filter_set_head *set, const char *tgt) 427 { 428 struct filter_set *s; 429 TAILQ_FOREACH(s, set, entry) { 430 printf("\t%s ", tgt); 431 print_community(&s->action.community); 432 printf("\n"); 433 } 434 } 435 436 void 437 print_l3vpn(struct l3vpn *vpn) 438 { 439 struct network *n; 440 441 printf("vpn \"%s\" on %s {\n", vpn->descr, vpn->ifmpe); 442 printf("\t%s\n", log_rd(vpn->rd)); 443 444 print_l3vpn_targets(&vpn->export, "export-target"); 445 print_l3vpn_targets(&vpn->import, "import-target"); 446 447 if (vpn->flags & F_RIB_NOFIBSYNC) 448 printf("\tfib-update no\n"); 449 else 450 printf("\tfib-update yes\n"); 451 452 TAILQ_FOREACH(n, &vpn->net_l, entry) 453 print_network(&n->net, "\t"); 454 455 printf("}\n"); 456 } 457 458 const char * 459 print_af(uint8_t aid) 460 { 461 /* 462 * Hack around the fact that aid2str() will return "IPv4 unicast" 463 * for AID_INET. AID_INET and AID_INET6 need special handling and 464 * the other AID should never end up here (at least for now). 465 */ 466 if (aid == AID_INET) 467 return ("inet"); 468 if (aid == AID_INET6) 469 return ("inet6"); 470 return (aid2str(aid)); 471 } 472 473 void 474 print_network(struct network_config *n, const char *c) 475 { 476 switch (n->type) { 477 case NETWORK_STATIC: 478 printf("%snetwork %s static", c, print_af(n->prefix.aid)); 479 break; 480 case NETWORK_CONNECTED: 481 printf("%snetwork %s connected", c, print_af(n->prefix.aid)); 482 break; 483 case NETWORK_RTLABEL: 484 printf("%snetwork %s rtlabel \"%s\"", c, 485 print_af(n->prefix.aid), rtlabel_id2name(n->rtlabel)); 486 break; 487 case NETWORK_PRIORITY: 488 printf("%snetwork %s priority %d", c, 489 print_af(n->prefix.aid), n->priority); 490 break; 491 case NETWORK_PREFIXSET: 492 printf("%snetwork prefix-set %s", c, n->psname); 493 break; 494 default: 495 printf("%snetwork %s/%u", c, log_addr(&n->prefix), 496 n->prefixlen); 497 break; 498 } 499 if (!TAILQ_EMPTY(&n->attrset)) 500 printf(" "); 501 print_set(&n->attrset); 502 printf("\n"); 503 } 504 505 void 506 print_as_sets(struct as_set_head *as_sets) 507 { 508 struct as_set *aset; 509 uint32_t *as; 510 size_t i, n; 511 int len; 512 513 SIMPLEQ_FOREACH(aset, as_sets, entry) { 514 printf("as-set \"%s\" {\n\t", aset->name); 515 as = set_get(aset->set, &n); 516 for (i = 0, len = 8; i < n; i++) { 517 if (len > 72) { 518 printf("\n\t"); 519 len = 8; 520 } 521 len += printf("%u ", as[i]); 522 } 523 printf("\n}\n\n"); 524 } 525 } 526 527 void 528 print_prefixsets(struct prefixset_head *psh) 529 { 530 struct prefixset *ps; 531 struct prefixset_item *psi; 532 533 SIMPLEQ_FOREACH(ps, psh, entry) { 534 int count = 0; 535 printf("prefix-set \"%s\" {", ps->name); 536 RB_FOREACH(psi, prefixset_tree, &ps->psitems) { 537 if (count++ % 2 == 0) 538 printf("\n\t"); 539 else 540 printf(", "); 541 print_prefix(&psi->p); 542 } 543 printf("\n}\n\n"); 544 } 545 } 546 547 void 548 print_originsets(struct prefixset_head *psh) 549 { 550 struct prefixset *ps; 551 struct roa *roa; 552 struct bgpd_addr addr; 553 554 SIMPLEQ_FOREACH(ps, psh, entry) { 555 printf("origin-set \"%s\" {", ps->name); 556 RB_FOREACH(roa, roa_tree, &ps->roaitems) { 557 printf("\n\t"); 558 addr.aid = roa->aid; 559 addr.v6 = roa->prefix.inet6; 560 printf("%s/%u", log_addr(&addr), roa->prefixlen); 561 if (roa->prefixlen != roa->maxlen) 562 printf(" maxlen %u", roa->maxlen); 563 printf(" source-as %u", roa->asnum); 564 } 565 printf("\n}\n\n"); 566 } 567 } 568 569 void 570 print_roa(struct roa_tree *r) 571 { 572 struct roa *roa; 573 struct bgpd_addr addr; 574 575 if (RB_EMPTY(r)) 576 return; 577 578 printf("roa-set {"); 579 RB_FOREACH(roa, roa_tree, r) { 580 printf("\n\t"); 581 addr.aid = roa->aid; 582 addr.v6 = roa->prefix.inet6; 583 printf("%s/%u", log_addr(&addr), roa->prefixlen); 584 if (roa->prefixlen != roa->maxlen) 585 printf(" maxlen %u", roa->maxlen); 586 printf(" source-as %u", roa->asnum); 587 if (roa->expires != 0) 588 printf(" expires %lld", (long long)roa->expires); 589 } 590 printf("\n}\n\n"); 591 } 592 593 void 594 print_rtrs(struct rtr_config_head *rh) 595 { 596 struct rtr_config *r; 597 598 SIMPLEQ_FOREACH(r, rh, entry) { 599 printf("rtr %s {\n", log_addr(&r->remote_addr)); 600 printf("\tdescr \"%s\"\n", r->descr); 601 printf("\tport %u\n", r->remote_port); 602 if (r->local_addr.aid != AID_UNSPEC) 603 printf("local-addr %s\n", log_addr(&r->local_addr)); 604 printf("}\n\n"); 605 } 606 } 607 608 void 609 print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c) 610 { 611 char *method; 612 struct in_addr ina; 613 614 if ((p->remote_addr.aid == AID_INET && p->remote_masklen != 32) || 615 (p->remote_addr.aid == AID_INET6 && p->remote_masklen != 128)) 616 printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), 617 p->remote_masklen); 618 else 619 printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr)); 620 if (p->descr[0]) 621 printf("%s\tdescr \"%s\"\n", c, p->descr); 622 if (p->rib[0]) 623 printf("%s\trib \"%s\"\n", c, p->rib); 624 if (p->remote_as) 625 printf("%s\tremote-as %s\n", c, log_as(p->remote_as)); 626 if (p->local_as != conf->as) { 627 printf("%s\tlocal-as %s", c, log_as(p->local_as)); 628 if (p->local_as > USHRT_MAX && p->local_short_as != AS_TRANS) 629 printf(" %u", p->local_short_as); 630 printf("\n"); 631 } 632 if (p->down) 633 printf("%s\tdown\n", c); 634 if (p->distance > 1) 635 printf("%s\tmultihop %u\n", c, p->distance); 636 if (p->passive) 637 printf("%s\tpassive\n", c); 638 if (p->local_addr_v4.aid) 639 printf("%s\tlocal-address %s\n", c, 640 log_addr(&p->local_addr_v4)); 641 if (p->local_addr_v6.aid) 642 printf("%s\tlocal-address %s\n", c, 643 log_addr(&p->local_addr_v6)); 644 if (p->remote_port != BGP_PORT) 645 printf("%s\tport %hu\n", c, p->remote_port); 646 if (p->max_prefix) { 647 printf("%s\tmax-prefix %u", c, p->max_prefix); 648 if (p->max_prefix_restart) 649 printf(" restart %u", p->max_prefix_restart); 650 printf("\n"); 651 } 652 if (p->max_out_prefix) { 653 printf("%s\tmax-prefix %u out", c, p->max_out_prefix); 654 if (p->max_out_prefix_restart) 655 printf(" restart %u", p->max_out_prefix_restart); 656 printf("\n"); 657 } 658 if (p->holdtime) 659 printf("%s\tholdtime %u\n", c, p->holdtime); 660 if (p->min_holdtime) 661 printf("%s\tholdtime min %u\n", c, p->min_holdtime); 662 if (p->export_type == EXPORT_NONE) 663 printf("%s\texport none\n", c); 664 else if (p->export_type == EXPORT_DEFAULT_ROUTE) 665 printf("%s\texport default-route\n", c); 666 if (p->enforce_as == ENFORCE_AS_ON) 667 printf("%s\tenforce neighbor-as yes\n", c); 668 else 669 printf("%s\tenforce neighbor-as no\n", c); 670 if (p->enforce_local_as == ENFORCE_AS_ON) 671 printf("%s\tenforce local-as yes\n", c); 672 else 673 printf("%s\tenforce local-as no\n", c); 674 if (p->reflector_client) { 675 if (conf->clusterid == 0) 676 printf("%s\troute-reflector\n", c); 677 else { 678 ina.s_addr = conf->clusterid; 679 printf("%s\troute-reflector %s\n", c, 680 inet_ntoa(ina)); 681 } 682 } 683 if (p->demote_group[0]) 684 printf("%s\tdemote %s\n", c, p->demote_group); 685 if (p->if_depend[0]) 686 printf("%s\tdepend on \"%s\"\n", c, p->if_depend); 687 if (p->flags & PEERFLAG_TRANS_AS) 688 printf("%s\ttransparent-as yes\n", c); 689 690 if (conf->flags & BGPD_FLAG_DECISION_ALL_PATHS) { 691 if (!(p->flags & PEERFLAG_EVALUATE_ALL)) 692 printf("%s\trde evaluate default\n", c); 693 } else { 694 if (p->flags & PEERFLAG_EVALUATE_ALL) 695 printf("%s\trde evaluate all\n", c); 696 } 697 698 if (conf->flags & BGPD_FLAG_NO_AS_SET) { 699 if (!(p->flags & PEERFLAG_NO_AS_SET)) 700 printf("%s\treject as-set no\n", c); 701 } else { 702 if (p->flags & PEERFLAG_NO_AS_SET) 703 printf("%s\treject as-set yes\n", c); 704 } 705 706 if (p->flags & PEERFLAG_LOG_UPDATES) 707 printf("%s\tlog updates\n", c); 708 709 if (p->auth.method == AUTH_MD5SIG) 710 printf("%s\ttcp md5sig\n", c); 711 else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP || 712 p->auth.method == AUTH_IPSEC_MANUAL_AH) { 713 if (p->auth.method == AUTH_IPSEC_MANUAL_ESP) 714 method = "esp"; 715 else 716 method = "ah"; 717 718 printf("%s\tipsec %s in spi %u %s XXXXXX", c, method, 719 p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in)); 720 if (p->auth.enc_alg_in) 721 printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in)); 722 printf("\n"); 723 724 printf("%s\tipsec %s out spi %u %s XXXXXX", c, method, 725 p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out)); 726 if (p->auth.enc_alg_out) 727 printf(" %s XXXXXX", 728 print_enc_alg(p->auth.enc_alg_out)); 729 printf("\n"); 730 } else if (p->auth.method == AUTH_IPSEC_IKE_AH) 731 printf("%s\tipsec ah ike\n", c); 732 else if (p->auth.method == AUTH_IPSEC_IKE_ESP) 733 printf("%s\tipsec esp ike\n", c); 734 735 if (p->ttlsec) 736 printf("%s\tttl-security yes\n", c); 737 738 print_announce(p, c); 739 740 print_mrt(conf, p->id, p->groupid, c, "\t"); 741 742 printf("%s}\n", c); 743 } 744 745 const char * 746 print_auth_alg(enum auth_alg alg) 747 { 748 switch (alg) { 749 case AUTH_AALG_SHA1HMAC: 750 return ("sha1"); 751 case AUTH_AALG_MD5HMAC: 752 return ("md5"); 753 default: 754 return ("???"); 755 } 756 } 757 758 const char * 759 print_enc_alg(enum auth_enc_alg alg) 760 { 761 switch (alg) { 762 case AUTH_EALG_3DESCBC: 763 return ("3des"); 764 case AUTH_EALG_AES: 765 return ("aes"); 766 default: 767 return ("???"); 768 } 769 } 770 771 static const char * 772 print_addpath_mode(enum addpath_mode mode) 773 { 774 switch (mode) { 775 case ADDPATH_EVAL_NONE: 776 return "none"; 777 case ADDPATH_EVAL_BEST: 778 return "best"; 779 case ADDPATH_EVAL_ECMP: 780 return "ecmp"; 781 case ADDPATH_EVAL_AS_WIDE: 782 return "as-wide-best"; 783 case ADDPATH_EVAL_ALL: 784 return "all"; 785 } 786 } 787 788 void 789 print_announce(struct peer_config *p, const char *c) 790 { 791 uint8_t aid; 792 793 if (p->announce_capa == 0) 794 printf("%s\tannounce capabilities no\n", c); 795 796 for (aid = 0; aid < AID_MAX; aid++) 797 if (p->capabilities.mp[aid]) 798 printf("%s\tannounce %s\n", c, aid2str(aid)); 799 800 if (p->capabilities.refresh == 0) 801 printf("%s\tannounce refresh no\n", c); 802 if (p->capabilities.enhanced_rr == 1) 803 printf("%s\tannounce enhanced refresh yes\n", c); 804 if (p->capabilities.grestart.restart == 0) 805 printf("%s\tannounce restart no\n", c); 806 if (p->capabilities.as4byte == 0) 807 printf("%s\tannounce as4byte no\n", c); 808 if (p->capabilities.add_path[0] & CAPA_AP_RECV) 809 printf("%s\tannounce add-path recv yes\n", c); 810 if (p->capabilities.add_path[0] & CAPA_AP_SEND) { 811 printf("%s\tannounce add-path send %s", c, 812 print_addpath_mode(p->eval.mode)); 813 if (p->eval.extrapaths != 0) 814 printf(" plus %d", p->eval.extrapaths); 815 if (p->eval.maxpaths != 0) 816 printf(" max %d", p->eval.maxpaths); 817 printf("\n"); 818 } 819 if (p->capabilities.role_ena) { 820 printf("%s\tannounce policy %s%s\n", c, 821 log_policy(p->capabilities.role), 822 p->capabilities.role_ena == 2 ? " enforce" : ""); 823 } 824 825 } 826 827 void 828 print_as(struct filter_rule *r) 829 { 830 if (r->match.as.flags & AS_FLAG_AS_SET_NAME) { 831 printf("as-set \"%s\" ", r->match.as.name); 832 return; 833 } 834 switch (r->match.as.op) { 835 case OP_RANGE: 836 printf("%s - ", log_as(r->match.as.as_min)); 837 printf("%s ", log_as(r->match.as.as_max)); 838 break; 839 case OP_XRANGE: 840 printf("%s >< ", log_as(r->match.as.as_min)); 841 printf("%s ", log_as(r->match.as.as_max)); 842 break; 843 case OP_NE: 844 printf("!= %s ", log_as(r->match.as.as_min)); 845 break; 846 default: 847 printf("%s ", log_as(r->match.as.as_min)); 848 break; 849 } 850 } 851 852 void 853 print_rule(struct bgpd_config *conf, struct filter_rule *r) 854 { 855 struct peer *p; 856 int i; 857 858 if (r->action == ACTION_ALLOW) 859 printf("allow "); 860 else if (r->action == ACTION_DENY) 861 printf("deny "); 862 else 863 printf("match "); 864 if (r->quick) 865 printf("quick "); 866 867 if (r->rib[0]) 868 printf("rib %s ", r->rib); 869 870 if (r->dir == DIR_IN) 871 printf("from "); 872 else if (r->dir == DIR_OUT) 873 printf("to "); 874 else 875 printf("eeeeeeeps. "); 876 877 if (r->peer.peerid) { 878 RB_FOREACH(p, peer_head, &conf->peers) 879 if (p->conf.id == r->peer.peerid) 880 break; 881 if (p == NULL) 882 printf("? "); 883 else 884 printf("%s ", log_addr(&p->conf.remote_addr)); 885 } else if (r->peer.groupid) { 886 RB_FOREACH(p, peer_head, &conf->peers) 887 if (p->conf.groupid == r->peer.groupid) 888 break; 889 if (p == NULL) 890 printf("group ? "); 891 else 892 printf("group \"%s\" ", p->conf.group); 893 } else if (r->peer.remote_as) { 894 printf("AS %s ", log_as(r->peer.remote_as)); 895 } else if (r->peer.ebgp) { 896 printf("ebgp "); 897 } else if (r->peer.ibgp) { 898 printf("ibgp "); 899 } else 900 printf("any "); 901 902 if (r->match.ovs.is_set) { 903 switch (r->match.ovs.validity) { 904 case ROA_VALID: 905 printf("ovs valid "); 906 break; 907 case ROA_INVALID: 908 printf("ovs invalid "); 909 break; 910 case ROA_NOTFOUND: 911 printf("ovs not-found "); 912 break; 913 default: 914 printf("ovs ??? %d ??? ", r->match.ovs.validity); 915 } 916 } 917 918 if (r->match.prefix.addr.aid != AID_UNSPEC) { 919 printf("prefix "); 920 print_prefix(&r->match.prefix); 921 printf(" "); 922 } 923 924 if (r->match.prefixset.name[0] != '\0') 925 printf("prefix-set \"%s\" ", r->match.prefixset.name); 926 if (r->match.prefixset.flags & PREFIXSET_FLAG_LONGER) 927 printf("or-longer "); 928 929 if (r->match.originset.name[0] != '\0') 930 printf("origin-set \"%s\" ", r->match.originset.name); 931 932 if (r->match.nexthop.flags) { 933 if (r->match.nexthop.flags == FILTER_NEXTHOP_NEIGHBOR) 934 printf("nexthop neighbor "); 935 else 936 printf("nexthop %s ", log_addr(&r->match.nexthop.addr)); 937 } 938 939 if (r->match.as.type) { 940 if (r->match.as.type == AS_ALL) 941 printf("AS "); 942 else if (r->match.as.type == AS_SOURCE) 943 printf("source-as "); 944 else if (r->match.as.type == AS_TRANSIT) 945 printf("transit-as "); 946 else if (r->match.as.type == AS_PEER) 947 printf("peer-as "); 948 else 949 printf("unfluffy-as "); 950 print_as(r); 951 } 952 953 if (r->match.aslen.type) { 954 printf("%s %u ", r->match.aslen.type == ASLEN_MAX ? 955 "max-as-len" : "max-as-seq", r->match.aslen.aslen); 956 } 957 958 for (i = 0; i < MAX_COMM_MATCH; i++) { 959 struct community *c = &r->match.community[i]; 960 if (c->flags != 0) { 961 printf("%s ", community_type(c)); 962 print_community(c); 963 } 964 } 965 966 if (r->match.maxcomm != 0) 967 printf("max-communities %d ", r->match.maxcomm - 1); 968 if (r->match.maxextcomm != 0) 969 printf("max-ext-communities %d ", r->match.maxextcomm - 1); 970 if (r->match.maxlargecomm != 0) 971 printf("max-large-communities %d ", r->match.maxlargecomm - 1); 972 973 print_set(&r->set); 974 975 printf("\n"); 976 } 977 978 const char * 979 mrt_type(enum mrt_type t) 980 { 981 switch (t) { 982 case MRT_NONE: 983 break; 984 case MRT_TABLE_DUMP: 985 return "table"; 986 case MRT_TABLE_DUMP_MP: 987 return "table-mp"; 988 case MRT_TABLE_DUMP_V2: 989 return "table-v2"; 990 case MRT_ALL_IN: 991 return "all in"; 992 case MRT_ALL_OUT: 993 return "all out"; 994 case MRT_UPDATE_IN: 995 return "updates in"; 996 case MRT_UPDATE_OUT: 997 return "updates out"; 998 } 999 return "unfluffy MRT"; 1000 } 1001 1002 void 1003 print_mrt(struct bgpd_config *conf, uint32_t pid, uint32_t gid, 1004 const char *prep, const char *prep2) 1005 { 1006 struct mrt *m; 1007 1008 if (conf->mrt == NULL) 1009 return; 1010 1011 LIST_FOREACH(m, conf->mrt, entry) 1012 if ((gid != 0 && m->group_id == gid) || 1013 (m->peer_id == pid && m->group_id == gid)) { 1014 printf("%s%sdump ", prep, prep2); 1015 if (m->rib[0]) 1016 printf("rib %s ", m->rib); 1017 printf("%s \"%s\"", mrt_type(m->type), 1018 MRT2MC(m)->name); 1019 if (MRT2MC(m)->ReopenTimerInterval == 0) 1020 printf("\n"); 1021 else 1022 printf(" %d\n", MRT2MC(m)->ReopenTimerInterval); 1023 } 1024 if (!LIST_EMPTY(conf->mrt)) 1025 printf("\n"); 1026 } 1027 1028 void 1029 print_groups(struct bgpd_config *conf) 1030 { 1031 struct peer_config **peerlist; 1032 struct peer *p; 1033 u_int peer_cnt, i; 1034 uint32_t prev_groupid; 1035 const char *tab = "\t"; 1036 const char *nada = ""; 1037 const char *c; 1038 1039 peer_cnt = 0; 1040 RB_FOREACH(p, peer_head, &conf->peers) 1041 peer_cnt++; 1042 1043 if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL) 1044 fatal("print_groups calloc"); 1045 1046 i = 0; 1047 RB_FOREACH(p, peer_head, &conf->peers) 1048 peerlist[i++] = &p->conf; 1049 1050 qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare); 1051 1052 prev_groupid = 0; 1053 for (i = 0; i < peer_cnt; i++) { 1054 if (peerlist[i]->groupid) { 1055 c = tab; 1056 if (peerlist[i]->groupid != prev_groupid) { 1057 if (prev_groupid) 1058 printf("}\n\n"); 1059 printf("group \"%s\" {\n", peerlist[i]->group); 1060 prev_groupid = peerlist[i]->groupid; 1061 } 1062 } else 1063 c = nada; 1064 1065 print_peer(peerlist[i], conf, c); 1066 } 1067 1068 if (prev_groupid) 1069 printf("}\n\n"); 1070 1071 free(peerlist); 1072 } 1073 1074 int 1075 peer_compare(const void *aa, const void *bb) 1076 { 1077 const struct peer_config * const *a; 1078 const struct peer_config * const *b; 1079 1080 a = aa; 1081 b = bb; 1082 1083 return ((*a)->groupid - (*b)->groupid); 1084 } 1085 1086 void 1087 print_config(struct bgpd_config *conf, struct rib_names *rib_l) 1088 { 1089 struct filter_rule *r; 1090 struct network *n; 1091 struct rde_rib *rr; 1092 struct l3vpn *vpn; 1093 1094 print_mainconf(conf); 1095 print_rtrs(&conf->rtrs); 1096 print_roa(&conf->roa); 1097 print_as_sets(&conf->as_sets); 1098 print_prefixsets(&conf->prefixsets); 1099 print_originsets(&conf->originsets); 1100 TAILQ_FOREACH(n, &conf->networks, entry) 1101 print_network(&n->net, ""); 1102 if (!SIMPLEQ_EMPTY(&conf->l3vpns)) 1103 printf("\n"); 1104 SIMPLEQ_FOREACH(vpn, &conf->l3vpns, entry) 1105 print_l3vpn(vpn); 1106 printf("\n"); 1107 SIMPLEQ_FOREACH(rr, rib_l, entry) { 1108 if (rr->flags & F_RIB_NOEVALUATE) 1109 printf("rde rib %s no evaluate\n", rr->name); 1110 else if (rr->flags & F_RIB_NOFIB) 1111 printf("rde rib %s\n", rr->name); 1112 else 1113 printf("rde rib %s rtable %u fib-update %s\n", rr->name, 1114 rr->rtableid, rr->flags & F_RIB_NOFIBSYNC ? 1115 "no" : "yes"); 1116 } 1117 printf("\n"); 1118 print_mrt(conf, 0, 0, "", ""); 1119 print_groups(conf); 1120 TAILQ_FOREACH(r, conf->filters, entry) 1121 print_rule(conf, r); 1122 } 1123