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