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