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