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