1 /* $OpenBSD: printconf.c,v 1.67 2009/03/26 13:59:30 henning 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 <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 #include "bgpd.h" 24 #include "mrt.h" 25 #include "session.h" 26 27 void print_op(enum comp_ops); 28 void print_community(int, int); 29 void print_set(struct filter_set_head *); 30 void print_mainconf(struct bgpd_config *); 31 void print_network(struct network_config *); 32 void print_peer(struct peer_config *, struct bgpd_config *, 33 const char *); 34 const char *print_auth_alg(u_int8_t); 35 const char *print_enc_alg(u_int8_t); 36 const char *print_safi(u_int8_t); 37 void print_rule(struct peer *, struct filter_rule *); 38 const char * mrt_type(enum mrt_type); 39 void print_mrt(u_int32_t, u_int32_t, const char *, const char *); 40 void print_groups(struct bgpd_config *, struct peer *); 41 int peer_compare(const void *, const void *); 42 43 void 44 print_op(enum comp_ops op) 45 { 46 switch (op) { 47 case OP_RANGE: 48 printf("-"); 49 break; 50 case OP_XRANGE: 51 printf("><"); 52 break; 53 case OP_EQ: 54 printf("="); 55 break; 56 case OP_NE: 57 printf("!="); 58 break; 59 case OP_LE: 60 printf("<="); 61 break; 62 case OP_LT: 63 printf("<"); 64 break; 65 case OP_GE: 66 printf(">="); 67 break; 68 case OP_GT: 69 printf(">"); 70 break; 71 default: 72 printf("?"); 73 break; 74 } 75 } 76 77 void 78 print_community(int as, int type) 79 { 80 if (as == COMMUNITY_ANY) 81 printf("*:"); 82 else if (as == COMMUNITY_NEIGHBOR_AS) 83 printf("neighbor-as:"); 84 else 85 printf("%d:", as); 86 87 if (type == COMMUNITY_ANY) 88 printf("* "); 89 else if (type == COMMUNITY_NEIGHBOR_AS) 90 printf("neighbor-as "); 91 else 92 printf("%d ", type); 93 } 94 95 void 96 print_set(struct filter_set_head *set) 97 { 98 struct filter_set *s; 99 100 if (TAILQ_EMPTY(set)) 101 return; 102 103 printf("set { "); 104 TAILQ_FOREACH(s, set, entry) { 105 switch (s->type) { 106 case ACTION_SET_LOCALPREF: 107 printf("localpref %u ", s->action.metric); 108 break; 109 case ACTION_SET_RELATIVE_LOCALPREF: 110 printf("localpref %+d ", s->action.relative); 111 break; 112 case ACTION_SET_MED: 113 printf("metric %u ", s->action.metric); 114 break; 115 case ACTION_SET_RELATIVE_MED: 116 printf("metric %+d ", s->action.relative); 117 break; 118 case ACTION_SET_WEIGHT: 119 printf("weight %u ", s->action.metric); 120 break; 121 case ACTION_SET_RELATIVE_WEIGHT: 122 printf("weight %+d ", s->action.relative); 123 break; 124 case ACTION_SET_NEXTHOP: 125 printf("nexthop %s ", log_addr(&s->action.nexthop)); 126 break; 127 case ACTION_SET_NEXTHOP_REJECT: 128 printf("nexthop reject "); 129 break; 130 case ACTION_SET_NEXTHOP_BLACKHOLE: 131 printf("nexthop blackhole "); 132 break; 133 case ACTION_SET_NEXTHOP_NOMODIFY: 134 printf("nexthop no-modify "); 135 break; 136 case ACTION_SET_NEXTHOP_SELF: 137 printf("nexthop self "); 138 break; 139 case ACTION_SET_PREPEND_SELF: 140 printf("prepend-self %u ", s->action.prepend); 141 break; 142 case ACTION_SET_PREPEND_PEER: 143 printf("prepend-neighbor %u ", s->action.prepend); 144 break; 145 case ACTION_DEL_COMMUNITY: 146 printf("community delete "); 147 print_community(s->action.community.as, 148 s->action.community.type); 149 printf(" "); 150 break; 151 case ACTION_SET_COMMUNITY: 152 printf("community "); 153 print_community(s->action.community.as, 154 s->action.community.type); 155 printf(" "); 156 break; 157 case ACTION_PFTABLE: 158 printf("pftable %s ", s->action.pftable); 159 break; 160 case ACTION_RTLABEL: 161 printf("rtlabel %s ", s->action.rtlabel); 162 break; 163 case ACTION_RTLABEL_ID: 164 case ACTION_PFTABLE_ID: 165 /* not possible */ 166 printf("king bula saiz: config broken"); 167 break; 168 } 169 } 170 printf("}"); 171 } 172 173 void 174 print_mainconf(struct bgpd_config *conf) 175 { 176 struct in_addr ina; 177 struct listen_addr *la; 178 179 printf("AS %s", log_as(conf->as)); 180 if (conf->as > USHRT_MAX && conf->short_as != AS_TRANS) 181 printf(" %u", conf->short_as); 182 ina.s_addr = conf->bgpid; 183 printf("\nrouter-id %s\n", inet_ntoa(ina)); 184 if (conf->holdtime) 185 printf("holdtime %u\n", conf->holdtime); 186 if (conf->min_holdtime) 187 printf("holdtime min %u\n", conf->min_holdtime); 188 189 if (conf->flags & BGPD_FLAG_NO_FIB_UPDATE) 190 printf("fib-update no\n"); 191 else 192 printf("fib-update yes\n"); 193 194 if (conf->flags & BGPD_FLAG_NO_EVALUATE) 195 printf("route-collector yes\n"); 196 197 if (conf->flags & BGPD_FLAG_DECISION_ROUTEAGE) 198 printf("rde route-age evaluate\n"); 199 200 if (conf->flags & BGPD_FLAG_DECISION_MED_ALWAYS) 201 printf("rde med compare always\n"); 202 203 if (conf->log & BGPD_LOG_UPDATES) 204 printf("log updates\n"); 205 206 TAILQ_FOREACH(la, conf->listen_addrs, entry) 207 printf("listen on %s\n", 208 log_sockaddr((struct sockaddr *)&la->sa)); 209 210 if (conf->flags & BGPD_FLAG_NEXTHOP_BGP) 211 printf("nexthop qualify via bgp\n"); 212 if (conf->flags & BGPD_FLAG_NEXTHOP_DEFAULT) 213 printf("nexthop qualify via default\n"); 214 215 if (conf->flags & BGPD_FLAG_REDIST_CONNECTED) { 216 printf("network inet connected"); 217 if (!TAILQ_EMPTY(&conf->connectset)) 218 printf(" "); 219 print_set(&conf->connectset); 220 printf("\n"); 221 } 222 if (conf->flags & BGPD_FLAG_REDIST_STATIC) { 223 printf("network inet static"); 224 if (!TAILQ_EMPTY(&conf->staticset)) 225 printf(" "); 226 print_set(&conf->staticset); 227 printf("\n"); 228 } 229 if (conf->flags & BGPD_FLAG_REDIST6_CONNECTED) { 230 printf("network inet6 connected"); 231 if (!TAILQ_EMPTY(&conf->connectset6)) 232 printf(" "); 233 print_set(&conf->connectset6); 234 printf("\n"); 235 } 236 if (conf->flags & BGPD_FLAG_REDIST_STATIC) { 237 printf("network inet6 static"); 238 if (!TAILQ_EMPTY(&conf->staticset6)) 239 printf(" "); 240 print_set(&conf->staticset6); 241 printf("\n"); 242 } 243 if (conf->rtableid) 244 printf("rtable %u\n", conf->rtableid); 245 } 246 247 void 248 print_network(struct network_config *n) 249 { 250 printf("network %s/%u", log_addr(&n->prefix), n->prefixlen); 251 if (!TAILQ_EMPTY(&n->attrset)) 252 printf(" "); 253 print_set(&n->attrset); 254 printf("\n"); 255 } 256 257 void 258 print_peer(struct peer_config *p, struct bgpd_config *conf, const char *c) 259 { 260 char *method; 261 struct in_addr ina; 262 263 if ((p->remote_addr.af == AF_INET && p->remote_masklen != 32) || 264 (p->remote_addr.af == AF_INET6 && p->remote_masklen != 128)) 265 printf("%sneighbor %s/%u {\n", c, log_addr(&p->remote_addr), 266 p->remote_masklen); 267 else 268 printf("%sneighbor %s {\n", c, log_addr(&p->remote_addr)); 269 if (p->descr[0]) 270 printf("%s\tdescr \"%s\"\n", c, p->descr); 271 if (p->remote_as) 272 printf("%s\tremote-as %s\n", c, log_as(p->remote_as)); 273 if (p->down) 274 printf("%s\tdown\n", c); 275 if (p->distance > 1) 276 printf("%s\tmultihop %u\n", c, p->distance); 277 if (p->passive) 278 printf("%s\tpassive\n", c); 279 if (p->local_addr.af) 280 printf("%s\tlocal-address %s\n", c, log_addr(&p->local_addr)); 281 if (p->max_prefix) { 282 printf("%s\tmax-prefix %u", c, p->max_prefix); 283 if (p->max_prefix_restart) 284 printf(" restart %u", p->max_prefix_restart); 285 printf("\n"); 286 } 287 if (p->holdtime) 288 printf("%s\tholdtime %u\n", c, p->holdtime); 289 if (p->min_holdtime) 290 printf("%s\tholdtime min %u\n", c, p->min_holdtime); 291 if (p->announce_capa == 0) 292 printf("%s\tannounce capabilities no\n", c); 293 if (p->announce_type == ANNOUNCE_SELF) 294 printf("%s\tannounce self\n", c); 295 else if (p->announce_type == ANNOUNCE_NONE) 296 printf("%s\tannounce none\n", c); 297 else if (p->announce_type == ANNOUNCE_ALL) 298 printf("%s\tannounce all\n", c); 299 else if (p->announce_type == ANNOUNCE_DEFAULT_ROUTE) 300 printf("%s\tannounce default-route\n", c); 301 else 302 printf("%s\tannounce ???\n", c); 303 if (p->enforce_as == ENFORCE_AS_ON) 304 printf("%s\tenforce neighbor-as yes\n", c); 305 else 306 printf("%s\tenforce neighbor-as no\n", c); 307 if (p->reflector_client) { 308 if (conf->clusterid == 0) 309 printf("%s\troute-reflector\n", c); 310 else { 311 ina.s_addr = conf->clusterid; 312 printf("%s\troute-reflector %s\n", c, 313 inet_ntoa(ina)); 314 } 315 } 316 if (p->demote_group[0]) 317 printf("%s\tdemote %s\n", c, p->demote_group); 318 if (p->if_depend[0]) 319 printf("%s\tdepend on \"%s\"\n", c, p->if_depend); 320 if (p->flags & PEERFLAG_TRANS_AS) 321 printf("%s\ttransparent-as yes\n", c); 322 323 if (p->auth.method == AUTH_MD5SIG) 324 printf("%s\ttcp md5sig\n", c); 325 else if (p->auth.method == AUTH_IPSEC_MANUAL_ESP || 326 p->auth.method == AUTH_IPSEC_MANUAL_AH) { 327 if (p->auth.method == AUTH_IPSEC_MANUAL_ESP) 328 method = "esp"; 329 else 330 method = "ah"; 331 332 printf("%s\tipsec %s in spi %u %s XXXXXX", c, method, 333 p->auth.spi_in, print_auth_alg(p->auth.auth_alg_in)); 334 if (p->auth.enc_alg_in) 335 printf(" %s XXXXXX", print_enc_alg(p->auth.enc_alg_in)); 336 printf("\n"); 337 338 printf("%s\tipsec %s out spi %u %s XXXXXX", c, method, 339 p->auth.spi_out, print_auth_alg(p->auth.auth_alg_out)); 340 if (p->auth.enc_alg_out) 341 printf(" %s XXXXXX", 342 print_enc_alg(p->auth.enc_alg_out)); 343 printf("\n"); 344 } else if (p->auth.method == AUTH_IPSEC_IKE_AH) 345 printf("%s\tipsec ah ike\n", c); 346 else if (p->auth.method == AUTH_IPSEC_IKE_ESP) 347 printf("%s\tipsec esp ike\n", c); 348 349 if (p->ttlsec) 350 printf("%s\tttl-security yes\n", c); 351 352 printf("%s\tannounce IPv4 %s\n", c, print_safi(p->capabilities.mp_v4)); 353 printf("%s\tannounce IPv6 %s\n", c, print_safi(p->capabilities.mp_v6)); 354 355 if (p->softreconfig_in == 1) 356 printf("%s\tsoftreconfig in yes\n", c); 357 else 358 printf("%s\tsoftreconfig in no\n", c); 359 360 if (p->softreconfig_out == 1) 361 printf("%s\tsoftreconfig out yes\n", c); 362 else 363 printf("%s\tsoftreconfig out no\n", c); 364 365 366 print_mrt(p->id, p->groupid, c, "\t"); 367 368 printf("%s}\n", c); 369 } 370 371 const char * 372 print_auth_alg(u_int8_t alg) 373 { 374 switch (alg) { 375 case SADB_AALG_SHA1HMAC: 376 return ("sha1"); 377 case SADB_AALG_MD5HMAC: 378 return ("md5"); 379 default: 380 return ("???"); 381 } 382 } 383 384 const char * 385 print_enc_alg(u_int8_t alg) 386 { 387 switch (alg) { 388 case SADB_EALG_3DESCBC: 389 return ("3des"); 390 case SADB_X_EALG_AES: 391 return ("aes"); 392 default: 393 return ("???"); 394 } 395 } 396 397 const char * 398 print_safi(u_int8_t safi) 399 { 400 switch (safi) { 401 case SAFI_NONE: 402 return ("none"); 403 case SAFI_UNICAST: 404 return ("unicast"); 405 default: 406 return ("?"); 407 } 408 } 409 410 void 411 print_rule(struct peer *peer_l, struct filter_rule *r) 412 { 413 struct peer *p; 414 415 if (r->action == ACTION_ALLOW) 416 printf("allow "); 417 else if (r->action == ACTION_DENY) 418 printf("deny "); 419 else 420 printf("match "); 421 422 if (r->quick) 423 printf("quick "); 424 425 if (r->dir == DIR_IN) 426 printf("from "); 427 else if (r->dir == DIR_OUT) 428 printf("to "); 429 else 430 printf("eeeeeeeps. "); 431 432 if (r->peer.peerid) { 433 for (p = peer_l; p != NULL && p->conf.id != r->peer.peerid; 434 p = p->next) 435 ; /* nothing */ 436 if (p == NULL) 437 printf("? "); 438 else 439 printf("%s ", log_addr(&p->conf.remote_addr)); 440 } else if (r->peer.groupid) { 441 for (p = peer_l; p != NULL && 442 p->conf.groupid != r->peer.groupid; p = p->next) 443 ; /* nothing */ 444 if (p == NULL) 445 printf("group ? "); 446 else 447 printf("group \"%s\" ", p->conf.group); 448 } else 449 printf("any "); 450 451 if (r->match.prefix.addr.af) 452 printf("prefix %s/%u ", log_addr(&r->match.prefix.addr), 453 r->match.prefix.len); 454 455 if (r->match.prefix.addr.af == 0 && r->match.prefixlen.af) { 456 if (r->match.prefixlen.af == AF_INET) 457 printf("inet "); 458 if (r->match.prefixlen.af == AF_INET6) 459 printf("inet6 "); 460 } 461 462 if (r->match.prefixlen.op) { 463 if (r->match.prefixlen.op == OP_RANGE || 464 r->match.prefixlen.op == OP_XRANGE) { 465 printf("prefixlen %u ", r->match.prefixlen.len_min); 466 print_op(r->match.prefixlen.op); 467 printf(" %u ", r->match.prefixlen.len_max); 468 } else { 469 printf("prefixlen "); 470 print_op(r->match.prefixlen.op); 471 printf(" %u ", r->match.prefixlen.len_min); 472 } 473 } 474 475 if (r->match.as.type) { 476 if (r->match.as.type == AS_ALL) 477 printf("AS %s ", log_as(r->match.as.as)); 478 else if (r->match.as.type == AS_SOURCE) 479 printf("source-as %s ", log_as(r->match.as.as)); 480 else if (r->match.as.type == AS_TRANSIT) 481 printf("transit-as %s ", log_as(r->match.as.as)); 482 else if (r->match.as.type == AS_PEER) 483 printf("peer-as %s ", log_as(r->match.as.as)); 484 else 485 printf("unfluffy-as %s ", log_as(r->match.as.as)); 486 } 487 488 if (r->match.community.as != COMMUNITY_UNSET) { 489 printf("community "); 490 print_community(r->match.community.as, 491 r->match.community.type); 492 } 493 494 print_set(&r->set); 495 496 printf("\n"); 497 } 498 499 const char * 500 mrt_type(enum mrt_type t) 501 { 502 switch (t) { 503 case MRT_NONE: 504 break; 505 case MRT_TABLE_DUMP: 506 return "table"; 507 case MRT_TABLE_DUMP_MP: 508 return "table-mp"; 509 case MRT_ALL_IN: 510 return "all in"; 511 case MRT_ALL_OUT: 512 return "all out"; 513 case MRT_UPDATE_IN: 514 return "updates in"; 515 case MRT_UPDATE_OUT: 516 return "updates out"; 517 } 518 return "unfluffy MRT"; 519 } 520 521 struct mrt_head *xmrt_l = NULL; 522 523 void 524 print_mrt(u_int32_t pid, u_int32_t gid, const char *prep, const char *prep2) 525 { 526 struct mrt *m; 527 528 if (xmrt_l == NULL) 529 return; 530 531 LIST_FOREACH(m, xmrt_l, entry) 532 if ((gid != 0 && m->group_id == gid) || 533 (m->peer_id == pid && m->group_id == gid)) { 534 if (MRT2MC(m)->ReopenTimerInterval == 0) 535 printf("%s%sdump %s %s\n", prep, prep2, 536 mrt_type(m->type), MRT2MC(m)->name); 537 else 538 printf("%s%sdump %s %s %d\n", prep, prep2, 539 mrt_type(m->type), 540 MRT2MC(m)->name, 541 MRT2MC(m)->ReopenTimerInterval); 542 } 543 } 544 545 void 546 print_groups(struct bgpd_config *conf, struct peer *peer_l) 547 { 548 struct peer_config **peerlist; 549 struct peer *p; 550 u_int peer_cnt, i; 551 u_int32_t prev_groupid; 552 const char *tab = "\t"; 553 const char *nada = ""; 554 const char *c; 555 556 peer_cnt = 0; 557 for (p = peer_l; p != NULL; p = p->next) 558 peer_cnt++; 559 560 if ((peerlist = calloc(peer_cnt, sizeof(struct peer_config *))) == NULL) 561 fatal("print_groups calloc"); 562 563 i = 0; 564 for (p = peer_l; p != NULL; p = p->next) 565 peerlist[i++] = &p->conf; 566 567 qsort(peerlist, peer_cnt, sizeof(struct peer_config *), peer_compare); 568 569 prev_groupid = 0; 570 for (i = 0; i < peer_cnt; i++) { 571 if (peerlist[i]->groupid) { 572 c = tab; 573 if (peerlist[i]->groupid != prev_groupid) { 574 if (prev_groupid) 575 printf("}\n\n"); 576 printf("group \"%s\" {\n", peerlist[i]->group); 577 prev_groupid = peerlist[i]->groupid; 578 } 579 } else 580 c = nada; 581 582 print_peer(peerlist[i], conf, c); 583 } 584 585 if (prev_groupid) 586 printf("}\n\n"); 587 588 free(peerlist); 589 } 590 591 int 592 peer_compare(const void *aa, const void *bb) 593 { 594 const struct peer_config * const *a; 595 const struct peer_config * const *b; 596 597 a = aa; 598 b = bb; 599 600 return ((*a)->groupid - (*b)->groupid); 601 } 602 603 void 604 print_config(struct bgpd_config *conf, struct network_head *net_l, 605 struct peer *peer_l, struct filter_head *rules_l, struct mrt_head *mrt_l) 606 { 607 struct filter_rule *r; 608 struct network *n; 609 610 xmrt_l = mrt_l; 611 printf("\n"); 612 print_mainconf(conf); 613 printf("\n"); 614 TAILQ_FOREACH(n, net_l, entry) 615 print_network(&n->net); 616 printf("\n"); 617 print_mrt(0, 0, "", ""); 618 printf("\n"); 619 print_groups(conf, peer_l); 620 printf("\n"); 621 TAILQ_FOREACH(r, rules_l, entry) 622 print_rule(peer_l, r); 623 } 624