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