1 /* $OpenBSD: rtr_proto.c,v 1.28 2024/01/10 16:08:36 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2020 Claudio Jeker <claudio@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 OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 #include <sys/tree.h> 19 #include <errno.h> 20 #include <stdint.h> 21 #include <poll.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "bgpd.h" 28 #include "session.h" 29 #include "log.h" 30 31 struct rtr_header { 32 uint8_t version; 33 uint8_t type; 34 uint16_t session_id; /* or error code */ 35 uint32_t length; 36 } __packed; 37 38 #define RTR_MAX_VERSION 2 39 #define RTR_MAX_LEN 2048 40 #define RTR_DEFAULT_REFRESH 3600 41 #define RTR_DEFAULT_RETRY 600 42 #define RTR_DEFAULT_EXPIRE 7200 43 #define RTR_DEFAULT_ACTIVE 60 44 45 enum rtr_pdu_type { 46 SERIAL_NOTIFY = 0, 47 SERIAL_QUERY, 48 RESET_QUERY, 49 CACHE_RESPONSE, 50 IPV4_PREFIX, 51 IPV6_PREFIX = 6, 52 END_OF_DATA = 7, 53 CACHE_RESET = 8, 54 ROUTER_KEY = 9, 55 ERROR_REPORT = 10, 56 ASPA = 11, 57 }; 58 59 struct rtr_notify { 60 struct rtr_header hdr; 61 uint32_t serial; 62 } __packed; 63 64 struct rtr_query { 65 struct rtr_header hdr; 66 uint32_t serial; 67 } __packed; 68 69 struct rtr_reset { 70 struct rtr_header hdr; 71 } __packed; 72 73 struct rtr_response { 74 struct rtr_header hdr; 75 } __packed; 76 77 #define FLAG_ANNOUNCE 0x1 78 #define FLAG_MASK FLAG_ANNOUNCE 79 struct rtr_ipv4 { 80 struct rtr_header hdr; 81 uint8_t flags; 82 uint8_t prefixlen; 83 uint8_t maxlen; 84 uint8_t zero; 85 uint32_t prefix; 86 uint32_t asnum; 87 } __packed; 88 89 struct rtr_ipv6 { 90 struct rtr_header hdr; 91 uint8_t flags; 92 uint8_t prefixlen; 93 uint8_t maxlen; 94 uint8_t zero; 95 uint32_t prefix[4]; 96 uint32_t asnum; 97 } __packed; 98 99 struct rtr_routerkey { 100 struct rtr_header hdr; 101 uint8_t ski[20]; 102 uint32_t asnum; 103 /* followed by Subject Public Key Info */ 104 } __packed; 105 106 #define FLAG_AFI_V6 0x1 107 #define FLAG_AFI_MASK FLAG_AFI_V6 108 struct rtr_aspa { 109 struct rtr_header hdr; 110 uint8_t flags; 111 uint8_t afi_flags; 112 uint16_t cnt; 113 uint32_t cas; 114 /* array of spas with cnt elements follows */ 115 } __packed; 116 117 struct rtr_endofdata { 118 struct rtr_header hdr; 119 uint32_t serial; 120 uint32_t refresh; 121 uint32_t retry; 122 uint32_t expire; 123 } __packed; 124 125 struct rtr_endofdata_v0 { 126 struct rtr_header hdr; 127 uint32_t serial; 128 } __packed; 129 130 enum rtr_event { 131 RTR_EVNT_START, 132 RTR_EVNT_CON_OPEN, 133 RTR_EVNT_CON_CLOSE, 134 RTR_EVNT_TIMER_REFRESH, 135 RTR_EVNT_TIMER_RETRY, 136 RTR_EVNT_TIMER_EXPIRE, 137 RTR_EVNT_TIMER_ACTIVE, 138 RTR_EVNT_SEND_ERROR, 139 RTR_EVNT_SERIAL_NOTIFY, 140 RTR_EVNT_CACHE_RESPONSE, 141 RTR_EVNT_END_OF_DATA, 142 RTR_EVNT_CACHE_RESET, 143 RTR_EVNT_NO_DATA, 144 RTR_EVNT_RESET_AND_CLOSE, 145 RTR_EVNT_UNSUPP_PROTO_VERSION, 146 RTR_EVNT_NEGOTIATION_DONE, 147 }; 148 149 static const char *rtr_eventnames[] = { 150 "start", 151 "connection open", 152 "connection closed", 153 "refresh timer expired", 154 "retry timer expired", 155 "expire timer expired", 156 "activity timer expired", 157 "sent error", 158 "serial notify received", 159 "cache response received", 160 "end of data received", 161 "cache reset received", 162 "no data", 163 "connection closed with reset", 164 "unsupported protocol version", 165 "negotiation done", 166 }; 167 168 enum rtr_state { 169 RTR_STATE_CLOSED, 170 RTR_STATE_ERROR, 171 /* sessions with a state below this line will poll for incoming data */ 172 RTR_STATE_ESTABLISHED, 173 RTR_STATE_EXCHANGE, 174 RTR_STATE_NEGOTIATION, 175 }; 176 177 static const char *rtr_statenames[] = { 178 "closed", 179 "error", 180 "established", 181 "exchange", 182 "negotiation", 183 }; 184 185 struct rtr_session { 186 TAILQ_ENTRY(rtr_session) entry; 187 char descr[PEER_DESCR_LEN]; 188 struct roa_tree roa_set; 189 struct aspa_tree aspa; 190 struct aspa_tree aspa_oldv6; 191 struct ibuf_read r; 192 struct msgbuf w; 193 struct timer_head timers; 194 uint32_t id; /* rtr_config id */ 195 uint32_t serial; 196 uint32_t refresh; 197 uint32_t retry; 198 uint32_t expire; 199 uint32_t active; 200 int session_id; 201 int fd; 202 int active_lock; 203 enum rtr_state state; 204 enum reconf_action reconf_action; 205 enum rtr_error last_sent_error; 206 enum rtr_error last_recv_error; 207 char last_sent_msg[REASON_LEN]; 208 char last_recv_msg[REASON_LEN]; 209 uint8_t version; 210 }; 211 212 TAILQ_HEAD(, rtr_session) rtrs = TAILQ_HEAD_INITIALIZER(rtrs); 213 214 static void rtr_fsm(struct rtr_session *, enum rtr_event); 215 216 static const char * 217 log_rtr(struct rtr_session *rs) 218 { 219 return rs->descr; 220 } 221 222 static const char * 223 log_rtr_type(enum rtr_pdu_type type) 224 { 225 static char buf[20]; 226 227 switch (type) { 228 case SERIAL_NOTIFY: 229 return "serial notify"; 230 case SERIAL_QUERY: 231 return "serial query"; 232 case RESET_QUERY: 233 return "reset query"; 234 case CACHE_RESPONSE: 235 return "cache response"; 236 case IPV4_PREFIX: 237 return "IPv4 prefix"; 238 case IPV6_PREFIX: 239 return "IPv6 prefix"; 240 case END_OF_DATA: 241 return "end of data"; 242 case CACHE_RESET: 243 return "cache reset"; 244 case ROUTER_KEY: 245 return "router key"; 246 case ERROR_REPORT: 247 return "error report"; 248 case ASPA: 249 return "aspa"; 250 default: 251 snprintf(buf, sizeof(buf), "unknown %u", type); 252 return buf; 253 } 254 }; 255 256 static void 257 rtr_reset_cache(struct rtr_session *rs) 258 { 259 /* reset session */ 260 rs->session_id = -1; 261 timer_stop(&rs->timers, Timer_Rtr_Expire); 262 free_roatree(&rs->roa_set); 263 free_aspatree(&rs->aspa); 264 free_aspatree(&rs->aspa_oldv6); 265 } 266 267 static struct ibuf * 268 rtr_newmsg(struct rtr_session *rs, enum rtr_pdu_type type, uint32_t len, 269 uint16_t session_id) 270 { 271 struct ibuf *buf; 272 int saved_errno; 273 274 if (len > RTR_MAX_LEN) { 275 errno = ERANGE; 276 return NULL; 277 } 278 len += sizeof(struct rtr_header); 279 if ((buf = ibuf_open(len)) == NULL) 280 goto fail; 281 if (ibuf_add_n8(buf, rs->version) == -1) 282 goto fail; 283 if (ibuf_add_n8(buf, type) == -1) 284 goto fail; 285 if (ibuf_add_n16(buf, session_id) == -1) 286 goto fail; 287 if (ibuf_add_n32(buf, len) == -1) 288 goto fail; 289 290 return buf; 291 292 fail: 293 saved_errno = errno; 294 ibuf_free(buf); 295 errno = saved_errno; 296 return NULL; 297 } 298 299 static void rtr_send_error(struct rtr_session *, struct ibuf *, enum rtr_error, 300 const char *, ...) __attribute__((__format__ (printf, 4, 5))); 301 302 /* 303 * Try to send an error PDU to cache, put connection into error 304 * state. 305 */ 306 static void 307 rtr_send_error(struct rtr_session *rs, struct ibuf *pdu, enum rtr_error err, 308 const char *fmt, ...) 309 { 310 struct ibuf *buf; 311 va_list ap; 312 size_t len = 0, mlen = 0; 313 314 rs->last_sent_error = err; 315 memset(rs->last_sent_msg, 0, sizeof(rs->last_sent_msg)); 316 if (fmt != NULL) { 317 va_start(ap, fmt); 318 vsnprintf(rs->last_sent_msg, sizeof(rs->last_sent_msg), 319 fmt, ap); 320 mlen = strlen(rs->last_sent_msg); 321 va_end(ap); 322 } 323 324 log_warnx("rtr %s: sending error: %s%s%s", log_rtr(rs), 325 log_rtr_error(err), mlen > 0 ? ": " : "", rs->last_sent_msg); 326 327 if (pdu != NULL) { 328 ibuf_rewind(pdu); 329 len = ibuf_size(pdu); 330 } 331 332 buf = rtr_newmsg(rs, ERROR_REPORT, 2 * sizeof(uint32_t) + len + mlen, 333 err); 334 if (buf == NULL) 335 goto fail; 336 if (ibuf_add_n32(buf, len) == -1) 337 goto fail; 338 if (pdu != NULL) { 339 if (ibuf_add_ibuf(buf, pdu) == -1) 340 goto fail; 341 } 342 if (ibuf_add_n32(buf, mlen) == -1) 343 goto fail; 344 if (ibuf_add(buf, rs->last_sent_msg, mlen) == -1) 345 goto fail; 346 ibuf_close(&rs->w, buf); 347 348 rtr_fsm(rs, RTR_EVNT_SEND_ERROR); 349 return; 350 351 fail: 352 log_warn("rtr %s: send error report", log_rtr(rs)); 353 ibuf_free(buf); 354 } 355 356 static void 357 rtr_send_reset_query(struct rtr_session *rs) 358 { 359 struct ibuf *buf; 360 361 buf = rtr_newmsg(rs, RESET_QUERY, 0, 0); 362 if (buf == NULL) 363 goto fail; 364 ibuf_close(&rs->w, buf); 365 return; 366 367 fail: 368 rtr_send_error(rs, NULL, INTERNAL_ERROR, 369 "send %s: %s", log_rtr_type(RESET_QUERY), strerror(errno)); 370 ibuf_free(buf); 371 } 372 373 static void 374 rtr_send_serial_query(struct rtr_session *rs) 375 { 376 struct ibuf *buf; 377 378 buf = rtr_newmsg(rs, SERIAL_QUERY, sizeof(uint32_t), rs->session_id); 379 if (buf == NULL) 380 goto fail; 381 if (ibuf_add_n32(buf, rs->serial) == -1) 382 goto fail; 383 ibuf_close(&rs->w, buf); 384 return; 385 386 fail: 387 rtr_send_error(rs, NULL, INTERNAL_ERROR, 388 "send %s: %s", log_rtr_type(SERIAL_QUERY), strerror(errno)); 389 ibuf_free(buf); 390 } 391 392 /* 393 * Check the session_id of the rtr_header to match the expected value. 394 * Returns -1 on failure and 0 on success. 395 */ 396 static int 397 rtr_check_session_id(struct rtr_session *rs, uint16_t session_id, 398 struct rtr_header *rh, struct ibuf *pdu) 399 { 400 if (session_id != ntohs(rh->session_id)) { 401 rtr_send_error(rs, pdu, CORRUPT_DATA, 402 "%s: bad session_id %d (expected %d)", 403 log_rtr_type(rh->type), ntohs(rh->session_id), session_id); 404 return -1; 405 } 406 return 0; 407 } 408 409 /* 410 * Parse the common rtr header (first 8 bytes) including the 411 * included length field. 412 * Returns -1 on failure. On success msgtype and msglen are set 413 * and the function return 0. 414 */ 415 static int 416 rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr, 417 size_t *msglen, enum rtr_pdu_type *msgtype) 418 { 419 struct rtr_header rh; 420 size_t len; 421 422 if (ibuf_get(hdr, &rh, sizeof(rh)) == -1) 423 fatal("%s: ibuf_get", __func__); 424 425 len = ntohl(rh.length); 426 427 if (len > RTR_MAX_LEN) { 428 rtr_send_error(rs, hdr, CORRUPT_DATA, "%s: too big: %zu bytes", 429 log_rtr_type(rh.type), len); 430 return -1; 431 } 432 433 if (rs->state == RTR_STATE_NEGOTIATION) { 434 switch (rh.type) { 435 case CACHE_RESPONSE: 436 case CACHE_RESET: 437 case ERROR_REPORT: 438 if (rh.version < rs->version) 439 rs->version = rh.version; 440 rtr_fsm(rs, RTR_EVNT_NEGOTIATION_DONE); 441 break; 442 case SERIAL_NOTIFY: 443 /* ignore SERIAL_NOTIFY */ 444 break; 445 default: 446 rtr_send_error(rs, hdr, CORRUPT_DATA, 447 "%s: out of context", log_rtr_type(rh.type)); 448 return -1; 449 } 450 } else if (rh.version != rs->version && rh.type != ERROR_REPORT) { 451 goto badversion; 452 } 453 454 switch (rh.type) { 455 case SERIAL_NOTIFY: 456 if (len != sizeof(struct rtr_notify)) 457 goto badlen; 458 break; 459 case CACHE_RESPONSE: 460 if (len != sizeof(struct rtr_response)) 461 goto badlen; 462 break; 463 case IPV4_PREFIX: 464 if (len != sizeof(struct rtr_ipv4)) 465 goto badlen; 466 break; 467 case IPV6_PREFIX: 468 if (len != sizeof(struct rtr_ipv6)) 469 goto badlen; 470 break; 471 case END_OF_DATA: 472 if (rs->version == 0) { 473 if (len != sizeof(struct rtr_endofdata_v0)) 474 goto badlen; 475 } else { 476 if (len != sizeof(struct rtr_endofdata)) 477 goto badlen; 478 } 479 break; 480 case CACHE_RESET: 481 if (len != sizeof(struct rtr_reset)) 482 goto badlen; 483 break; 484 case ROUTER_KEY: 485 if (rs->version < 1) 486 goto badversion; 487 if (len < sizeof(struct rtr_routerkey)) 488 goto badlen; 489 break; 490 case ERROR_REPORT: 491 if (len < 16) 492 goto badlen; 493 break; 494 case ASPA: 495 if (rs->version < 2) 496 goto badversion; 497 if (len < sizeof(struct rtr_aspa) || (len % 4) != 0) 498 goto badlen; 499 break; 500 default: 501 rtr_send_error(rs, hdr, UNSUPP_PDU_TYPE, "type %s", 502 log_rtr_type(rh.type)); 503 return -1; 504 } 505 506 *msglen = len; 507 *msgtype = rh.type; 508 509 return 0; 510 511 badlen: 512 rtr_send_error(rs, hdr, CORRUPT_DATA, "%s: bad length: %zu bytes", 513 log_rtr_type(rh.type), len); 514 return -1; 515 516 badversion: 517 rtr_send_error(rs, hdr, UNEXP_PROTOCOL_VERS, "%s: version %d", 518 log_rtr_type(rh.type), rh.version); 519 return -1; 520 } 521 522 static int 523 rtr_parse_notify(struct rtr_session *rs, struct ibuf *pdu) 524 { 525 struct rtr_notify notify; 526 527 /* ignore SERIAL_NOTIFY during startup */ 528 if (rs->state == RTR_STATE_NEGOTIATION) 529 return 0; 530 531 if (ibuf_get(pdu, ¬ify, sizeof(notify)) == -1) 532 goto badlen; 533 534 if (rtr_check_session_id(rs, rs->session_id, ¬ify.hdr, pdu) == -1) 535 return -1; 536 537 if (rs->state != RTR_STATE_ESTABLISHED) { 538 log_warnx("rtr %s: received %s: while in state %s (ignored)", 539 log_rtr(rs), log_rtr_type(SERIAL_NOTIFY), 540 rtr_statenames[rs->state]); 541 return 0; 542 } 543 544 rtr_fsm(rs, RTR_EVNT_SERIAL_NOTIFY); 545 return 0; 546 547 badlen: 548 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 549 log_rtr_type(SERIAL_NOTIFY)); 550 return -1; 551 } 552 553 static int 554 rtr_parse_cache_response(struct rtr_session *rs, struct ibuf *pdu) 555 { 556 struct rtr_response resp; 557 558 if (ibuf_get(pdu, &resp, sizeof(resp)) == -1) 559 goto badlen; 560 561 /* set session_id if not yet happened */ 562 if (rs->session_id == -1) 563 rs->session_id = ntohs(resp.hdr.session_id); 564 565 if (rtr_check_session_id(rs, rs->session_id, &resp.hdr, pdu) == -1) 566 return -1; 567 568 if (rs->state != RTR_STATE_ESTABLISHED) { 569 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 570 log_rtr_type(CACHE_RESPONSE)); 571 return -1; 572 } 573 574 rtr_fsm(rs, RTR_EVNT_CACHE_RESPONSE); 575 return 0; 576 577 badlen: 578 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 579 log_rtr_type(CACHE_RESPONSE)); 580 return -1; 581 } 582 583 static int 584 rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu) 585 { 586 struct rtr_ipv4 ip4; 587 struct roa *roa; 588 589 if (ibuf_get(pdu, &ip4, sizeof(ip4)) == -1) 590 goto badlen; 591 592 if (rtr_check_session_id(rs, 0, &ip4.hdr, pdu) == -1) 593 return -1; 594 595 if (rs->state != RTR_STATE_EXCHANGE) { 596 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 597 log_rtr_type(IPV4_PREFIX)); 598 return -1; 599 } 600 601 if (ip4.prefixlen > 32 || ip4.maxlen > 32 || 602 ip4.prefixlen > ip4.maxlen) { 603 rtr_send_error(rs, pdu, CORRUPT_DATA, 604 "%s: bad prefixlen / maxlen", log_rtr_type(IPV4_PREFIX)); 605 return -1; 606 } 607 608 if ((roa = calloc(1, sizeof(*roa))) == NULL) { 609 rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory"); 610 return -1; 611 } 612 roa->aid = AID_INET; 613 roa->prefixlen = ip4.prefixlen; 614 roa->maxlen = ip4.maxlen; 615 roa->asnum = ntohl(ip4.asnum); 616 roa->prefix.inet.s_addr = ip4.prefix; 617 618 if (ip4.flags & FLAG_ANNOUNCE) { 619 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 620 rtr_send_error(rs, pdu, DUP_REC_RECV, "%s %s", 621 log_rtr_type(IPV4_PREFIX), log_roa(roa)); 622 free(roa); 623 return -1; 624 } 625 } else { 626 struct roa *r; 627 628 r = RB_FIND(roa_tree, &rs->roa_set, roa); 629 if (r == NULL) { 630 rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s", 631 log_rtr_type(IPV4_PREFIX), log_roa(roa)); 632 free(roa); 633 return -1; 634 } 635 RB_REMOVE(roa_tree, &rs->roa_set, r); 636 free(r); 637 free(roa); 638 } 639 640 return 0; 641 642 badlen: 643 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 644 log_rtr_type(IPV4_PREFIX)); 645 return -1; 646 } 647 648 static int 649 rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu) 650 { 651 struct rtr_ipv6 ip6; 652 struct roa *roa; 653 654 if (ibuf_get(pdu, &ip6, sizeof(ip6)) == -1) 655 goto badlen; 656 657 if (rtr_check_session_id(rs, 0, &ip6.hdr, pdu) == -1) 658 return -1; 659 660 if (rs->state != RTR_STATE_EXCHANGE) { 661 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 662 log_rtr_type(IPV6_PREFIX)); 663 return -1; 664 } 665 666 if (ip6.prefixlen > 128 || ip6.maxlen > 128 || 667 ip6.prefixlen > ip6.maxlen) { 668 rtr_send_error(rs, pdu, CORRUPT_DATA, 669 "%s: bad prefixlen / maxlen", log_rtr_type(IPV6_PREFIX)); 670 return -1; 671 } 672 673 if ((roa = calloc(1, sizeof(*roa))) == NULL) { 674 rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory"); 675 return -1; 676 } 677 roa->aid = AID_INET6; 678 roa->prefixlen = ip6.prefixlen; 679 roa->maxlen = ip6.maxlen; 680 roa->asnum = ntohl(ip6.asnum); 681 memcpy(&roa->prefix.inet6, ip6.prefix, sizeof(roa->prefix.inet6)); 682 683 if (ip6.flags & FLAG_ANNOUNCE) { 684 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 685 rtr_send_error(rs, pdu, DUP_REC_RECV, "%s %s", 686 log_rtr_type(IPV6_PREFIX), log_roa(roa)); 687 free(roa); 688 return -1; 689 } 690 } else { 691 struct roa *r; 692 693 r = RB_FIND(roa_tree, &rs->roa_set, roa); 694 if (r == NULL) { 695 rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s", 696 log_rtr_type(IPV6_PREFIX), log_roa(roa)); 697 free(roa); 698 return -1; 699 } 700 RB_REMOVE(roa_tree, &rs->roa_set, r); 701 free(r); 702 free(roa); 703 } 704 return 0; 705 706 badlen: 707 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 708 log_rtr_type(IPV6_PREFIX)); 709 return -1; 710 } 711 712 static int 713 rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu) 714 { 715 struct rtr_aspa rtr_aspa; 716 struct aspa_tree *aspatree; 717 struct aspa_set *aspa, *a; 718 uint16_t cnt, i; 719 720 if (ibuf_get(pdu, &rtr_aspa, sizeof(rtr_aspa)) == -1) 721 goto badlen; 722 723 cnt = ntohs(rtr_aspa.cnt); 724 if (ibuf_size(pdu) != cnt * sizeof(uint32_t)) 725 goto badlen; 726 727 if (rs->state != RTR_STATE_EXCHANGE) { 728 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 729 log_rtr_type(ASPA)); 730 return -1; 731 } 732 733 if (rtr_aspa.afi_flags & FLAG_AFI_V6) { 734 aspatree = &rs->aspa_oldv6; 735 } else { 736 aspatree = &rs->aspa; 737 } 738 739 /* create aspa_set entry from the rtr aspa pdu */ 740 if ((aspa = calloc(1, sizeof(*aspa))) == NULL) { 741 rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory"); 742 return -1; 743 } 744 aspa->as = ntohl(rtr_aspa.cas); 745 aspa->num = cnt; 746 if (cnt > 0) { 747 if ((aspa->tas = calloc(cnt, sizeof(uint32_t))) == NULL) { 748 free_aspa(aspa); 749 rtr_send_error(rs, NULL, INTERNAL_ERROR, 750 "out of memory"); 751 return -1; 752 } 753 for (i = 0; i < cnt; i++) { 754 if (ibuf_get_n32(pdu, &aspa->tas[i]) == -1) 755 goto badlen; 756 } 757 } 758 759 if (rtr_aspa.flags & FLAG_ANNOUNCE) { 760 a = RB_INSERT(aspa_tree, aspatree, aspa); 761 if (a != NULL) { 762 RB_REMOVE(aspa_tree, aspatree, a); 763 free_aspa(a); 764 765 if (RB_INSERT(aspa_tree, aspatree, aspa) != NULL) { 766 rtr_send_error(rs, NULL, INTERNAL_ERROR, 767 "corrupt aspa tree"); 768 free_aspa(aspa); 769 return -1; 770 } 771 } 772 } else { 773 a = RB_FIND(aspa_tree, aspatree, aspa); 774 if (a == NULL) { 775 rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s", 776 log_rtr_type(ASPA), log_aspa(aspa)); 777 free_aspa(aspa); 778 return -1; 779 } 780 RB_REMOVE(aspa_tree, aspatree, a); 781 free_aspa(a); 782 free_aspa(aspa); 783 } 784 785 return 0; 786 787 badlen: 788 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 789 log_rtr_type(ASPA)); 790 return -1; 791 } 792 793 static int 794 rtr_parse_end_of_data_v0(struct rtr_session *rs, struct ibuf *pdu) 795 { 796 struct rtr_endofdata_v0 eod; 797 798 if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) 799 goto badlen; 800 801 if (rtr_check_session_id(rs, rs->session_id, &eod.hdr, pdu) == -1) 802 return -1; 803 804 if (rs->state != RTR_STATE_EXCHANGE) { 805 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 806 log_rtr_type(END_OF_DATA)); 807 return -1; 808 } 809 810 rs->serial = ntohl(eod.serial); 811 812 rtr_fsm(rs, RTR_EVNT_END_OF_DATA); 813 return 0; 814 815 badlen: 816 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 817 log_rtr_type(END_OF_DATA)); 818 return -1; 819 } 820 821 static int 822 rtr_parse_end_of_data(struct rtr_session *rs, struct ibuf *pdu) 823 { 824 struct rtr_endofdata eod; 825 uint32_t t; 826 827 /* version 0 does not have the timing values */ 828 if (rs->version == 0) 829 return rtr_parse_end_of_data_v0(rs, pdu); 830 831 if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) 832 goto badlen; 833 834 if (rtr_check_session_id(rs, rs->session_id, &eod.hdr, pdu) == -1) 835 return -1; 836 837 if (rs->state != RTR_STATE_EXCHANGE) { 838 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 839 log_rtr_type(END_OF_DATA)); 840 return -1; 841 } 842 843 rs->serial = ntohl(eod.serial); 844 /* validate timer values to be in the right range */ 845 t = ntohl(eod.refresh); 846 if (t < 1 || t > 86400) 847 goto bad; 848 rs->refresh = t; 849 t = ntohl(eod.retry); 850 if (t < 1 || t > 7200) 851 goto bad; 852 rs->retry = t; 853 t = ntohl(eod.expire); 854 if (t < 600 || t > 172800) 855 goto bad; 856 if (t <= rs->retry || t <= rs->refresh) 857 goto bad; 858 rs->expire = t; 859 860 rtr_fsm(rs, RTR_EVNT_END_OF_DATA); 861 return 0; 862 863 bad: 864 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad timeout values", 865 log_rtr_type(END_OF_DATA)); 866 return -1; 867 868 badlen: 869 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 870 log_rtr_type(END_OF_DATA)); 871 return -1; 872 } 873 874 static int 875 rtr_parse_cache_reset(struct rtr_session *rs, struct ibuf *pdu) 876 { 877 struct rtr_reset reset; 878 879 if (ibuf_get(pdu, &reset, sizeof(reset)) == -1) 880 goto badlen; 881 882 if (rtr_check_session_id(rs, 0, &reset.hdr, pdu) == -1) 883 return -1; 884 885 if (rs->state != RTR_STATE_ESTABLISHED) { 886 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context", 887 log_rtr_type(CACHE_RESET)); 888 return -1; 889 } 890 891 rtr_fsm(rs, RTR_EVNT_CACHE_RESET); 892 return 0; 893 894 badlen: 895 rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length", 896 log_rtr_type(CACHE_RESET)); 897 return -1; 898 } 899 900 static char * 901 ibuf_get_string(struct ibuf *buf, size_t len) 902 { 903 char *str; 904 905 if (ibuf_size(buf) < len) { 906 errno = EBADMSG; 907 return (NULL); 908 } 909 str = strndup(ibuf_data(buf), len); 910 if (str == NULL) 911 return (NULL); 912 ibuf_skip(buf, len); 913 return (str); 914 } 915 916 /* 917 * Parse an Error Response message. This function behaves a bit different 918 * from other parse functions since on error the connection needs to be 919 * dropped without sending an error response back. 920 */ 921 static int 922 rtr_parse_error(struct rtr_session *rs, struct ibuf *pdu) 923 { 924 struct rtr_header rh; 925 struct ibuf err_pdu; 926 uint32_t pdu_len, msg_len; 927 char *str = NULL; 928 uint16_t errcode; 929 int rv = -1; 930 931 if (ibuf_get(pdu, &rh, sizeof(rh)) == -1) 932 goto fail; 933 errcode = ntohs(rh.session_id); 934 935 if (ibuf_get_n32(pdu, &pdu_len) == -1) 936 goto fail; 937 938 /* for now just ignore the embedded pdu */ 939 if (ibuf_get_ibuf(pdu, pdu_len, &err_pdu) == -1) 940 goto fail; 941 942 if (ibuf_get_n32(pdu, &msg_len) == -1) 943 goto fail; 944 945 /* optional error msg */ 946 if (msg_len != 0) 947 if ((str = ibuf_get_string(pdu, msg_len)) == NULL) 948 goto fail; 949 950 log_warnx("rtr %s: received error: %s%s%s", log_rtr(rs), 951 log_rtr_error(errcode), str ? ": " : "", str ? str : ""); 952 953 if (errcode == NO_DATA_AVAILABLE) { 954 rtr_fsm(rs, RTR_EVNT_NO_DATA); 955 rv = 0; 956 } else if (errcode == UNSUPP_PROTOCOL_VERS) 957 rtr_fsm(rs, RTR_EVNT_UNSUPP_PROTO_VERSION); 958 else 959 rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE); 960 961 rs->last_recv_error = errcode; 962 if (str) 963 strlcpy(rs->last_recv_msg, str, sizeof(rs->last_recv_msg)); 964 else 965 memset(rs->last_recv_msg, 0, sizeof(rs->last_recv_msg)); 966 967 free(str); 968 return rv; 969 970 fail: 971 log_warnx("rtr %s: received %s: bad encoding", log_rtr(rs), 972 log_rtr_type(ERROR_REPORT)); 973 rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE); 974 return -1; 975 } 976 977 /* 978 * Try to process received rtr message, it is possible that not a full 979 * message is in the buffer. In that case stop, once new data is available 980 * a retry will be done. 981 */ 982 static void 983 rtr_process_msg(struct rtr_session *rs) 984 { 985 struct ibuf rbuf, hdr, msg; 986 size_t msglen; 987 enum rtr_pdu_type msgtype; 988 989 ibuf_from_buffer(&rbuf, rs->r.buf, rs->r.wpos); 990 991 for (;;) { 992 if (ibuf_size(&rbuf) < sizeof(struct rtr_header)) 993 break; 994 995 /* parse header */ 996 ibuf_from_buffer(&hdr, ibuf_data(&rbuf), 997 sizeof(struct rtr_header)); 998 if (rtr_parse_header(rs, &hdr, &msglen, &msgtype) == -1) 999 return; 1000 1001 /* extract message */ 1002 if (ibuf_get_ibuf(&rbuf, msglen, &msg) == -1) 1003 break; 1004 1005 switch (msgtype) { 1006 case SERIAL_NOTIFY: 1007 if (rtr_parse_notify(rs, &msg) == -1) 1008 return; 1009 break; 1010 case CACHE_RESPONSE: 1011 if (rtr_parse_cache_response(rs, &msg) == -1) 1012 return; 1013 break; 1014 case IPV4_PREFIX: 1015 if (rtr_parse_ipv4_prefix(rs, &msg) == -1) 1016 return; 1017 break; 1018 case IPV6_PREFIX: 1019 if (rtr_parse_ipv6_prefix(rs, &msg) == -1) 1020 return; 1021 break; 1022 case END_OF_DATA: 1023 if (rtr_parse_end_of_data(rs, &msg) == -1) 1024 return; 1025 break; 1026 case CACHE_RESET: 1027 if (rtr_parse_cache_reset(rs, &msg) == -1) 1028 return; 1029 break; 1030 case ROUTER_KEY: 1031 /* silently ignore router key */ 1032 break; 1033 case ERROR_REPORT: 1034 if (rtr_parse_error(rs, &msg) == -1) { 1035 /* no need to send back an error */ 1036 return; 1037 } 1038 break; 1039 case ASPA: 1040 if (rtr_parse_aspa(rs, &msg) == -1) 1041 return; 1042 break; 1043 default: 1044 /* unreachable, checked in rtr_parse_header() */ 1045 rtr_send_error(rs, &msg, UNSUPP_PDU_TYPE, "type %s", 1046 log_rtr_type(msgtype)); 1047 return; 1048 } 1049 } 1050 1051 memmove(&rs->r.buf, ibuf_data(&rbuf), ibuf_size(&rbuf)); 1052 rs->r.wpos = ibuf_size(&rbuf); 1053 } 1054 1055 /* 1056 * Simple FSM for RTR sessions 1057 */ 1058 static void 1059 rtr_fsm(struct rtr_session *rs, enum rtr_event event) 1060 { 1061 enum rtr_state prev_state = rs->state; 1062 1063 switch (event) { 1064 case RTR_EVNT_UNSUPP_PROTO_VERSION: 1065 if (rs->state == RTR_STATE_NEGOTIATION) { 1066 if (rs->version > 0) 1067 rs->version--; 1068 else { 1069 /* 1070 * can't downgrade anymore, fail connection 1071 * RFC requires to send the error with our 1072 * highest version number. 1073 */ 1074 rs->version = RTR_MAX_VERSION; 1075 rtr_send_error(rs, NULL, UNSUPP_PROTOCOL_VERS, 1076 "negotiation failed"); 1077 return; 1078 } 1079 1080 if (rs->fd != -1) { 1081 /* flush buffers */ 1082 msgbuf_clear(&rs->w); 1083 rs->r.wpos = 0; 1084 close(rs->fd); 1085 rs->fd = -1; 1086 } 1087 1088 /* retry connection with lower version */ 1089 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 1090 rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0); 1091 break; 1092 } 1093 /* FALLTHROUGH */ 1094 case RTR_EVNT_RESET_AND_CLOSE: 1095 rtr_reset_cache(rs); 1096 rtr_recalc(); 1097 /* FALLTHROUGH */ 1098 case RTR_EVNT_CON_CLOSE: 1099 if (rs->state == RTR_STATE_NEGOTIATION) { 1100 /* consider any close event as a version failure. */ 1101 rtr_fsm(rs, RTR_EVNT_UNSUPP_PROTO_VERSION); 1102 break; 1103 } 1104 if (rs->fd != -1) { 1105 /* flush buffers */ 1106 msgbuf_clear(&rs->w); 1107 rs->r.wpos = 0; 1108 close(rs->fd); 1109 rs->fd = -1; 1110 } 1111 rs->state = RTR_STATE_CLOSED; 1112 /* try to reopen session */ 1113 timer_set(&rs->timers, Timer_Rtr_Retry, 1114 arc4random_uniform(10)); 1115 break; 1116 case RTR_EVNT_START: 1117 case RTR_EVNT_TIMER_RETRY: 1118 switch (rs->state) { 1119 case RTR_STATE_ERROR: 1120 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1121 return; 1122 case RTR_STATE_CLOSED: 1123 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 1124 rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0); 1125 return; 1126 default: 1127 break; 1128 } 1129 /* FALLTHROUGH */ 1130 case RTR_EVNT_CON_OPEN: 1131 timer_stop(&rs->timers, Timer_Rtr_Retry); 1132 if (rs->session_id == -1) 1133 rtr_send_reset_query(rs); 1134 else 1135 rtr_send_serial_query(rs); 1136 break; 1137 case RTR_EVNT_SERIAL_NOTIFY: 1138 /* schedule a refresh after a quick wait */ 1139 timer_set(&rs->timers, Timer_Rtr_Refresh, 1140 arc4random_uniform(10)); 1141 break; 1142 case RTR_EVNT_TIMER_REFRESH: 1143 /* send serial query */ 1144 rtr_send_serial_query(rs); 1145 break; 1146 case RTR_EVNT_TIMER_EXPIRE: 1147 rtr_reset_cache(rs); 1148 rtr_recalc(); 1149 break; 1150 case RTR_EVNT_TIMER_ACTIVE: 1151 log_warnx("rtr %s: activity timer fired", log_rtr(rs)); 1152 rtr_sem_release(rs->active_lock); 1153 rtr_recalc(); 1154 rs->active_lock = 0; 1155 break; 1156 case RTR_EVNT_CACHE_RESPONSE: 1157 rs->state = RTR_STATE_EXCHANGE; 1158 timer_stop(&rs->timers, Timer_Rtr_Refresh); 1159 timer_stop(&rs->timers, Timer_Rtr_Retry); 1160 timer_set(&rs->timers, Timer_Rtr_Active, rs->active); 1161 /* prevent rtr_recalc from running while active */ 1162 rs->active_lock = 1; 1163 rtr_sem_acquire(rs->active_lock); 1164 break; 1165 case RTR_EVNT_END_OF_DATA: 1166 /* start refresh and expire timers */ 1167 timer_set(&rs->timers, Timer_Rtr_Refresh, rs->refresh); 1168 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 1169 timer_stop(&rs->timers, Timer_Rtr_Active); 1170 rs->state = RTR_STATE_ESTABLISHED; 1171 rtr_sem_release(rs->active_lock); 1172 rtr_recalc(); 1173 rs->active_lock = 0; 1174 break; 1175 case RTR_EVNT_CACHE_RESET: 1176 rtr_reset_cache(rs); 1177 rtr_recalc(); 1178 /* retry after a quick wait */ 1179 timer_set(&rs->timers, Timer_Rtr_Retry, 1180 arc4random_uniform(10)); 1181 break; 1182 case RTR_EVNT_NO_DATA: 1183 /* start retry timer */ 1184 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 1185 /* stop refresh timer just to be sure */ 1186 timer_stop(&rs->timers, Timer_Rtr_Refresh); 1187 rs->state = RTR_STATE_ESTABLISHED; 1188 break; 1189 case RTR_EVNT_SEND_ERROR: 1190 rtr_reset_cache(rs); 1191 rtr_recalc(); 1192 rs->state = RTR_STATE_ERROR; 1193 /* flush receive buffer */ 1194 rs->r.wpos = 0; 1195 break; 1196 case RTR_EVNT_NEGOTIATION_DONE: 1197 rs->state = RTR_STATE_ESTABLISHED; 1198 break; 1199 } 1200 1201 log_debug("rtr %s: state change %s -> %s, reason: %s", 1202 log_rtr(rs), rtr_statenames[prev_state], rtr_statenames[rs->state], 1203 rtr_eventnames[event]); 1204 } 1205 1206 /* 1207 * IO handler for RTR sessions 1208 */ 1209 static void 1210 rtr_dispatch_msg(struct pollfd *pfd, struct rtr_session *rs) 1211 { 1212 ssize_t n; 1213 int error; 1214 1215 if (pfd->revents & POLLHUP) { 1216 log_warnx("rtr %s: Connection closed, hangup", log_rtr(rs)); 1217 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1218 return; 1219 } 1220 if (pfd->revents & (POLLERR|POLLNVAL)) { 1221 log_warnx("rtr %s: Connection closed, error", log_rtr(rs)); 1222 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1223 return; 1224 } 1225 if (pfd->revents & POLLOUT && rs->w.queued) { 1226 if ((error = ibuf_write(&rs->w)) == -1) { 1227 if (errno != EAGAIN) { 1228 log_warn("rtr %s: write error", log_rtr(rs)); 1229 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1230 } 1231 } 1232 if (error == 0) 1233 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1234 if (rs->w.queued == 0 && rs->state == RTR_STATE_ERROR) 1235 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1236 } 1237 if (pfd->revents & POLLIN) { 1238 if ((n = read(rs->fd, rs->r.buf + rs->r.wpos, 1239 sizeof(rs->r.buf) - rs->r.wpos)) == -1) { 1240 if (errno != EINTR && errno != EAGAIN) { 1241 log_warn("rtr %s: read error", log_rtr(rs)); 1242 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1243 } 1244 return; 1245 } 1246 if (n == 0) { 1247 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1248 return; 1249 } 1250 rs->r.wpos += n; 1251 1252 /* new data arrived, try to process it */ 1253 rtr_process_msg(rs); 1254 } 1255 1256 } 1257 1258 void 1259 rtr_check_events(struct pollfd *pfds, size_t npfds) 1260 { 1261 struct rtr_session *rs; 1262 struct timer *t; 1263 time_t now; 1264 size_t i = 0; 1265 1266 for (i = 0; i < npfds; i++) { 1267 if (pfds[i].revents == 0) 1268 continue; 1269 TAILQ_FOREACH(rs, &rtrs, entry) 1270 if (rs->fd == pfds[i].fd) { 1271 rtr_dispatch_msg(&pfds[i], rs); 1272 break; 1273 } 1274 if (rs == NULL) 1275 log_warnx("%s: unknown fd in pollfds", __func__); 1276 } 1277 1278 /* run all timers */ 1279 now = getmonotime(); 1280 TAILQ_FOREACH(rs, &rtrs, entry) 1281 if ((t = timer_nextisdue(&rs->timers, now)) != NULL) { 1282 log_debug("rtr %s: %s triggered", log_rtr(rs), 1283 timernames[t->type]); 1284 /* stop timer so it does not trigger again */ 1285 timer_stop(&rs->timers, t->type); 1286 switch (t->type) { 1287 case Timer_Rtr_Refresh: 1288 rtr_fsm(rs, RTR_EVNT_TIMER_REFRESH); 1289 break; 1290 case Timer_Rtr_Retry: 1291 rtr_fsm(rs, RTR_EVNT_TIMER_RETRY); 1292 break; 1293 case Timer_Rtr_Expire: 1294 rtr_fsm(rs, RTR_EVNT_TIMER_EXPIRE); 1295 break; 1296 case Timer_Rtr_Active: 1297 rtr_fsm(rs, RTR_EVNT_TIMER_ACTIVE); 1298 break; 1299 default: 1300 fatalx("King Bula lost in time"); 1301 } 1302 } 1303 } 1304 1305 size_t 1306 rtr_count(void) 1307 { 1308 struct rtr_session *rs; 1309 size_t count = 0; 1310 1311 TAILQ_FOREACH(rs, &rtrs, entry) 1312 count++; 1313 return count; 1314 } 1315 1316 size_t 1317 rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout) 1318 { 1319 struct rtr_session *rs; 1320 time_t now = getmonotime(); 1321 size_t i = 0; 1322 1323 TAILQ_FOREACH(rs, &rtrs, entry) { 1324 time_t nextaction; 1325 struct pollfd *pfd = pfds + i++; 1326 1327 if (i > npfds) 1328 fatalx("%s: too many sessions for pollfd", __func__); 1329 1330 if ((nextaction = timer_nextduein(&rs->timers, now)) != -1 && 1331 nextaction < *timeout) 1332 *timeout = nextaction; 1333 1334 if (rs->state == RTR_STATE_CLOSED) { 1335 pfd->fd = -1; 1336 continue; 1337 } 1338 1339 pfd->fd = rs->fd; 1340 pfd->events = 0; 1341 1342 if (rs->w.queued) 1343 pfd->events |= POLLOUT; 1344 if (rs->state >= RTR_STATE_ESTABLISHED) 1345 pfd->events |= POLLIN; 1346 } 1347 1348 return i; 1349 } 1350 1351 struct rtr_session * 1352 rtr_new(uint32_t id, char *descr) 1353 { 1354 struct rtr_session *rs; 1355 1356 if ((rs = calloc(1, sizeof(*rs))) == NULL) 1357 fatal("RTR session %s", descr); 1358 1359 RB_INIT(&rs->roa_set); 1360 RB_INIT(&rs->aspa); 1361 RB_INIT(&rs->aspa_oldv6); 1362 TAILQ_INIT(&rs->timers); 1363 msgbuf_init(&rs->w); 1364 1365 strlcpy(rs->descr, descr, sizeof(rs->descr)); 1366 rs->id = id; 1367 rs->session_id = -1; 1368 rs->version = RTR_MAX_VERSION; 1369 rs->refresh = RTR_DEFAULT_REFRESH; 1370 rs->retry = RTR_DEFAULT_RETRY; 1371 rs->expire = RTR_DEFAULT_EXPIRE; 1372 rs->active = RTR_DEFAULT_ACTIVE; 1373 rs->state = RTR_STATE_CLOSED; 1374 rs->reconf_action = RECONF_REINIT; 1375 rs->last_recv_error = NO_ERROR; 1376 rs->last_sent_error = NO_ERROR; 1377 1378 /* make sure that some timer is running to abort bad sessions */ 1379 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 1380 1381 log_debug("rtr %s: new session, start", log_rtr(rs)); 1382 TAILQ_INSERT_TAIL(&rtrs, rs, entry); 1383 rtr_fsm(rs, RTR_EVNT_START); 1384 1385 return rs; 1386 } 1387 1388 struct rtr_session * 1389 rtr_get(uint32_t id) 1390 { 1391 struct rtr_session *rs; 1392 1393 TAILQ_FOREACH(rs, &rtrs, entry) 1394 if (rs->id == id) 1395 return rs; 1396 return NULL; 1397 } 1398 1399 void 1400 rtr_free(struct rtr_session *rs) 1401 { 1402 if (rs == NULL) 1403 return; 1404 1405 rtr_reset_cache(rs); 1406 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1407 timer_remove_all(&rs->timers); 1408 free(rs); 1409 } 1410 1411 void 1412 rtr_open(struct rtr_session *rs, int fd) 1413 { 1414 if (rs->state != RTR_STATE_CLOSED && 1415 rs->state != RTR_STATE_NEGOTIATION) { 1416 log_warnx("rtr %s: bad session state", log_rtr(rs)); 1417 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1418 } 1419 1420 if (rs->state == RTR_STATE_CLOSED) 1421 rs->version = RTR_MAX_VERSION; 1422 1423 rs->fd = rs->w.fd = fd; 1424 rs->state = RTR_STATE_NEGOTIATION; 1425 rtr_fsm(rs, RTR_EVNT_CON_OPEN); 1426 } 1427 1428 void 1429 rtr_config_prep(void) 1430 { 1431 struct rtr_session *rs; 1432 1433 TAILQ_FOREACH(rs, &rtrs, entry) 1434 rs->reconf_action = RECONF_DELETE; 1435 } 1436 1437 void 1438 rtr_config_merge(void) 1439 { 1440 struct rtr_session *rs, *nrs; 1441 1442 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1443 if (rs->reconf_action == RECONF_DELETE) { 1444 TAILQ_REMOVE(&rtrs, rs, entry); 1445 rtr_free(rs); 1446 } 1447 } 1448 1449 void 1450 rtr_config_keep(struct rtr_session *rs) 1451 { 1452 rs->reconf_action = RECONF_KEEP; 1453 } 1454 1455 void 1456 rtr_roa_merge(struct roa_tree *rt) 1457 { 1458 struct rtr_session *rs; 1459 struct roa *roa; 1460 1461 TAILQ_FOREACH(rs, &rtrs, entry) { 1462 RB_FOREACH(roa, roa_tree, &rs->roa_set) 1463 rtr_roa_insert(rt, roa); 1464 } 1465 } 1466 1467 void 1468 rtr_aspa_merge(struct aspa_tree *at) 1469 { 1470 struct rtr_session *rs; 1471 struct aspa_set *aspa; 1472 1473 TAILQ_FOREACH(rs, &rtrs, entry) { 1474 RB_FOREACH(aspa, aspa_tree, &rs->aspa) 1475 rtr_aspa_insert(at, aspa); 1476 RB_FOREACH(aspa, aspa_tree, &rs->aspa_oldv6) 1477 rtr_aspa_insert(at, aspa); 1478 } 1479 } 1480 1481 void 1482 rtr_shutdown(void) 1483 { 1484 struct rtr_session *rs, *nrs; 1485 1486 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1487 rtr_free(rs); 1488 } 1489 1490 void 1491 rtr_show(struct rtr_session *rs, pid_t pid) 1492 { 1493 struct ctl_show_rtr msg; 1494 struct ctl_timer ct; 1495 u_int i; 1496 time_t d; 1497 1498 memset(&msg, 0, sizeof(msg)); 1499 1500 /* descr, remote_addr, local_addr and remote_port set by parent */ 1501 msg.version = rs->version; 1502 msg.serial = rs->serial; 1503 msg.refresh = rs->refresh; 1504 msg.retry = rs->retry; 1505 msg.expire = rs->expire; 1506 msg.session_id = rs->session_id; 1507 msg.last_sent_error = rs->last_sent_error; 1508 msg.last_recv_error = rs->last_recv_error; 1509 strlcpy(msg.last_sent_msg, rs->last_sent_msg, 1510 sizeof(msg.last_sent_msg)); 1511 strlcpy(msg.last_recv_msg, rs->last_recv_msg, 1512 sizeof(msg.last_recv_msg)); 1513 1514 /* send back imsg */ 1515 rtr_imsg_compose(IMSG_CTL_SHOW_RTR, rs->id, pid, &msg, sizeof(msg)); 1516 1517 /* send back timer imsgs */ 1518 for (i = 1; i < Timer_Max; i++) { 1519 if (!timer_running(&rs->timers, i, &d)) 1520 continue; 1521 ct.type = i; 1522 ct.val = d; 1523 rtr_imsg_compose(IMSG_CTL_SHOW_TIMER, rs->id, pid, 1524 &ct, sizeof(ct)); 1525 } 1526 } 1527