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