1 /* $OpenBSD: rtr_proto.c,v 1.12 2023/02/02 20:31:37 job 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 }; 37 38 #define RTR_MAX_LEN 2048 39 #define RTR_DEFAULT_REFRESH 3600 40 #define RTR_DEFAULT_RETRY 600 41 #define RTR_DEFAULT_EXPIRE 7200 42 43 enum rtr_pdu_type { 44 SERIAL_NOTIFY = 0, 45 SERIAL_QUERY, 46 RESET_QUERY, 47 CACHE_RESPONSE, 48 IPV4_PREFIX, 49 IPV6_PREFIX = 6, 50 END_OF_DATA = 7, 51 CACHE_RESET = 8, 52 ROUTER_KEY = 9, 53 ERROR_REPORT = 10, 54 }; 55 56 #define FLAG_ANNOUNCE 0x1 57 #define FLAG_MASK FLAG_ANNOUNCE 58 struct rtr_ipv4 { 59 uint8_t flags; 60 uint8_t prefixlen; 61 uint8_t maxlen; 62 uint8_t zero; 63 uint32_t prefix; 64 uint32_t asnum; 65 }; 66 67 struct rtr_ipv6 { 68 uint8_t flags; 69 uint8_t prefixlen; 70 uint8_t maxlen; 71 uint8_t zero; 72 uint32_t prefix[4]; 73 uint32_t asnum; 74 }; 75 76 struct rtr_endofdata { 77 uint32_t serial; 78 uint32_t refresh; 79 uint32_t retry; 80 uint32_t expire; 81 }; 82 83 enum rtr_event { 84 RTR_EVNT_START, 85 RTR_EVNT_CON_OPEN, 86 RTR_EVNT_CON_CLOSE, 87 RTR_EVNT_TIMER_REFRESH, 88 RTR_EVNT_TIMER_RETRY, 89 RTR_EVNT_TIMER_EXPIRE, 90 RTR_EVNT_SEND_ERROR, 91 RTR_EVNT_SERIAL_NOTIFY, 92 RTR_EVNT_CACHE_RESPONSE, 93 RTR_EVNT_END_OF_DATA, 94 RTR_EVNT_CACHE_RESET, 95 RTR_EVNT_NO_DATA, 96 RTR_EVNT_RESET_AND_CLOSE, 97 }; 98 99 static const char *rtr_eventnames[] = { 100 "start", 101 "connection open", 102 "connection closed", 103 "refresh timer expired", 104 "retry timer expired", 105 "expire timer expired", 106 "sent error", 107 "serial notify received", 108 "cache response received", 109 "end of data received", 110 "cache reset received", 111 "no data", 112 "connection closed with reset", 113 }; 114 115 enum rtr_state { 116 RTR_STATE_CLOSED, 117 RTR_STATE_ERROR, 118 RTR_STATE_IDLE, 119 RTR_STATE_ACTIVE, 120 }; 121 122 static const char *rtr_statenames[] = { 123 "closed", 124 "error", 125 "idle", 126 "active" 127 }; 128 129 struct rtr_session { 130 TAILQ_ENTRY(rtr_session) entry; 131 char descr[PEER_DESCR_LEN]; 132 struct roa_tree roa_set; 133 struct ibuf_read r; 134 struct msgbuf w; 135 struct timer_head timers; 136 uint32_t id; /* rtr_config id */ 137 uint32_t serial; 138 uint32_t refresh; 139 uint32_t retry; 140 uint32_t expire; 141 int session_id; 142 int fd; 143 enum rtr_state state; 144 enum reconf_action reconf_action; 145 enum rtr_error last_sent_error; 146 enum rtr_error last_recv_error; 147 char last_sent_msg[REASON_LEN]; 148 char last_recv_msg[REASON_LEN]; 149 }; 150 151 TAILQ_HEAD(, rtr_session) rtrs = TAILQ_HEAD_INITIALIZER(rtrs); 152 153 static void rtr_fsm(struct rtr_session *, enum rtr_event); 154 155 static const char * 156 log_rtr(struct rtr_session *rs) 157 { 158 return rs->descr; 159 } 160 161 static const char * 162 log_rtr_type(enum rtr_pdu_type type) 163 { 164 static char buf[20]; 165 166 switch (type) { 167 case SERIAL_NOTIFY: 168 return "serial notify"; 169 case SERIAL_QUERY: 170 return "serial query"; 171 case RESET_QUERY: 172 return "reset query"; 173 case CACHE_RESPONSE: 174 return "cache response"; 175 case IPV4_PREFIX: 176 return "IPv4 prefix"; 177 case IPV6_PREFIX: 178 return "IPv6 prefix"; 179 case END_OF_DATA: 180 return "end of data"; 181 case CACHE_RESET: 182 return "cache reset"; 183 case ROUTER_KEY: 184 return "router key"; 185 case ERROR_REPORT: 186 return "error report"; 187 default: 188 snprintf(buf, sizeof(buf), "unknown %u", type); 189 return buf; 190 } 191 }; 192 193 static struct ibuf * 194 rtr_newmsg(enum rtr_pdu_type type, uint32_t len, uint16_t session_id) 195 { 196 struct ibuf *buf; 197 struct rtr_header rh; 198 199 if (len > RTR_MAX_LEN) { 200 errno = ERANGE; 201 return NULL; 202 } 203 len += sizeof(rh); 204 if ((buf = ibuf_open(len)) == NULL) 205 return NULL; 206 207 memset(&rh, 0, sizeof(rh)); 208 rh.version = 1; 209 rh.type = type; 210 rh.session_id = htons(session_id); 211 rh.length = htonl(len); 212 213 /* cannot fail with fixed buffers */ 214 ibuf_add(buf, &rh, sizeof(rh)); 215 return buf; 216 } 217 218 /* 219 * Try to send an error PDU to cache, put connection into error 220 * state. 221 */ 222 static void 223 rtr_send_error(struct rtr_session *rs, enum rtr_error err, char *msg, 224 void *pdu, size_t len) 225 { 226 struct ibuf *buf; 227 size_t mlen = 0; 228 uint32_t hdrlen; 229 230 rs->last_sent_error = err; 231 if (msg) { 232 mlen = strlen(msg); 233 strlcpy(rs->last_sent_msg, msg, sizeof(rs->last_sent_msg)); 234 } else 235 memset(rs->last_sent_msg, 0, sizeof(rs->last_sent_msg)); 236 237 rtr_fsm(rs, RTR_EVNT_SEND_ERROR); 238 239 buf = rtr_newmsg(ERROR_REPORT, 2 * sizeof(hdrlen) + len + mlen, err); 240 if (buf == NULL) { 241 log_warn("rtr %s: send error report", log_rtr(rs)); 242 return; 243 } 244 245 /* cannot fail with fixed buffers */ 246 hdrlen = ntohl(len); 247 ibuf_add(buf, &hdrlen, sizeof(hdrlen)); 248 ibuf_add(buf, pdu, len); 249 hdrlen = ntohl(mlen); 250 ibuf_add(buf, &hdrlen, sizeof(hdrlen)); 251 ibuf_add(buf, msg, mlen); 252 ibuf_close(&rs->w, buf); 253 254 log_warnx("rtr %s: sending error report[%u] %s", log_rtr(rs), err, 255 msg ? msg : ""); 256 } 257 258 static void 259 rtr_reset_query(struct rtr_session *rs) 260 { 261 struct ibuf *buf; 262 263 buf = rtr_newmsg(RESET_QUERY, 0, 0); 264 if (buf == NULL) { 265 log_warn("rtr %s: send reset query", log_rtr(rs)); 266 rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0); 267 return; 268 } 269 ibuf_close(&rs->w, buf); 270 } 271 272 static void 273 rtr_serial_query(struct rtr_session *rs) 274 { 275 struct ibuf *buf; 276 uint32_t s; 277 278 buf = rtr_newmsg(SERIAL_QUERY, sizeof(s), rs->session_id); 279 if (buf == NULL) { 280 log_warn("rtr %s: send serial query", log_rtr(rs)); 281 rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0); 282 return; 283 } 284 285 /* cannot fail with fixed buffers */ 286 s = htonl(rs->serial); 287 ibuf_add(buf, &s, sizeof(s)); 288 ibuf_close(&rs->w, buf); 289 } 290 291 /* 292 * Validate the common rtr header (first 8 bytes) including the 293 * included length field. 294 * Returns -1 on failure. On success msgtype and msglen are set 295 * and the function return 0. 296 */ 297 static int 298 rtr_parse_header(struct rtr_session *rs, void *buf, 299 size_t *msglen, enum rtr_pdu_type *msgtype) 300 { 301 struct rtr_header rh; 302 uint32_t len = 16; /* default for ERROR_REPORT */ 303 int session_id; 304 305 memcpy(&rh, buf, sizeof(rh)); 306 307 if (rh.version != 1) { 308 log_warnx("rtr %s: received message with unsupported version", 309 log_rtr(rs)); 310 rtr_send_error(rs, UNEXP_PROTOCOL_VERS, NULL, &rh, sizeof(rh)); 311 return -1; 312 } 313 314 *msgtype = rh.type; 315 *msglen = ntohl(rh.length); 316 317 switch (*msgtype) { 318 case SERIAL_NOTIFY: 319 session_id = rs->session_id; 320 len = 12; 321 break; 322 case CACHE_RESPONSE: 323 /* set session_id if not yet happened */ 324 if (rs->session_id == -1) 325 rs->session_id = ntohs(rh.session_id); 326 session_id = rs->session_id; 327 len = 8; 328 break; 329 case IPV4_PREFIX: 330 session_id = 0; 331 len = 20; 332 break; 333 case IPV6_PREFIX: 334 session_id = 0; 335 len = 32; 336 break; 337 case END_OF_DATA: 338 session_id = rs->session_id; 339 len = 24; 340 break; 341 case CACHE_RESET: 342 session_id = 0; 343 len = 8; 344 break; 345 case ROUTER_KEY: 346 len = 36; /* XXX probably too small, but we ignore it */ 347 /* FALLTHROUGH */ 348 case ERROR_REPORT: 349 if (*msglen > RTR_MAX_LEN) { 350 log_warnx("rtr %s: received %s: msg too big: %zu byte", 351 log_rtr(rs), log_rtr_type(*msgtype), *msglen); 352 rtr_send_error(rs, CORRUPT_DATA, "too big", 353 &rh, sizeof(rh)); 354 return -1; 355 } 356 if (*msglen < len) { 357 log_warnx("rtr %s: received %s: msg too small: " 358 "%zu byte", log_rtr(rs), log_rtr_type(*msgtype), 359 *msglen); 360 rtr_send_error(rs, CORRUPT_DATA, "too small", 361 &rh, sizeof(rh)); 362 return -1; 363 } 364 /* 365 * session_id check omitted since ROUTER_KEY and ERROR_REPORT 366 * use the field for different things. 367 */ 368 return 0; 369 default: 370 log_warnx("rtr %s: received unknown message: type %u", 371 log_rtr(rs), *msgtype); 372 rtr_send_error(rs, UNSUPP_PDU_TYPE, NULL, &rh, sizeof(rh)); 373 return -1; 374 } 375 376 if (len != *msglen) { 377 log_warnx("rtr %s: received %s: illegal len: %zu byte not %u", 378 log_rtr(rs), log_rtr_type(*msgtype), *msglen, len); 379 rtr_send_error(rs, CORRUPT_DATA, "bad length", 380 &rh, sizeof(rh)); 381 return -1; 382 } 383 384 if (session_id != ntohs(rh.session_id)) { 385 /* ignore SERIAL_NOTIFY during startup */ 386 if (rs->session_id == -1 && *msgtype == SERIAL_NOTIFY) 387 return 0; 388 389 log_warnx("rtr %s: received %s: bad session_id: %d != %d", 390 log_rtr(rs), log_rtr_type(*msgtype), ntohs(rh.session_id), 391 session_id); 392 rtr_send_error(rs, CORRUPT_DATA, "bad session_id", 393 &rh, sizeof(rh)); 394 return -1; 395 } 396 397 return 0; 398 } 399 400 static int 401 rtr_parse_notify(struct rtr_session *rs, uint8_t *buf, size_t len) 402 { 403 if (rs->state == RTR_STATE_ACTIVE) { 404 log_warnx("rtr %s: received %s: while active (ignored)", 405 log_rtr(rs), log_rtr_type(SERIAL_NOTIFY)); 406 return 0; 407 } 408 409 rtr_fsm(rs, RTR_EVNT_SERIAL_NOTIFY); 410 return 0; 411 } 412 413 static int 414 rtr_parse_cache_response(struct rtr_session *rs, uint8_t *buf, size_t len) 415 { 416 if (rs->state != RTR_STATE_IDLE) { 417 log_warnx("rtr %s: received %s: out of context", 418 log_rtr(rs), log_rtr_type(CACHE_RESPONSE)); 419 return -1; 420 } 421 422 rtr_fsm(rs, RTR_EVNT_CACHE_RESPONSE); 423 return 0; 424 } 425 426 static int 427 rtr_parse_ipv4_prefix(struct rtr_session *rs, uint8_t *buf, size_t len) 428 { 429 struct rtr_ipv4 ip4; 430 struct roa *roa; 431 432 if (len != sizeof(struct rtr_header) + sizeof(ip4)) { 433 log_warnx("rtr %s: received %s: bad pdu len", 434 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 435 rtr_send_error(rs, CORRUPT_DATA, "bad len", buf, len); 436 return -1; 437 } 438 439 if (rs->state != RTR_STATE_ACTIVE) { 440 log_warnx("rtr %s: received %s: out of context", 441 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 442 rtr_send_error(rs, CORRUPT_DATA, NULL, buf, len); 443 return -1; 444 } 445 446 memcpy(&ip4, buf + sizeof(struct rtr_header), sizeof(ip4)); 447 if (ip4.prefixlen > 32 || ip4.maxlen > 32 || 448 ip4.prefixlen > ip4.maxlen) { 449 log_warnx("rtr: %s: received %s: bad prefixlen / maxlen", 450 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 451 rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", 452 buf, len); 453 return -1; 454 } 455 456 if ((roa = calloc(1, sizeof(*roa))) == NULL) { 457 log_warn("rtr %s: received %s", 458 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 459 rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0); 460 return -1; 461 } 462 roa->aid = AID_INET; 463 roa->prefixlen = ip4.prefixlen; 464 roa->maxlen = ip4.maxlen; 465 roa->asnum = ntohl(ip4.asnum); 466 roa->prefix.inet.s_addr = ip4.prefix; 467 468 if (ip4.flags & FLAG_ANNOUNCE) { 469 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 470 log_warnx("rtr %s: received %s: duplicate announcement", 471 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 472 rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len); 473 free(roa); 474 return -1; 475 } 476 } else { 477 struct roa *r; 478 479 r = RB_FIND(roa_tree, &rs->roa_set, roa); 480 if (r == NULL) { 481 log_warnx("rtr %s: received %s: unknown withdrawal", 482 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 483 rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len); 484 free(roa); 485 return -1; 486 } 487 RB_REMOVE(roa_tree, &rs->roa_set, r); 488 free(r); 489 free(roa); 490 } 491 492 return 0; 493 } 494 495 static int 496 rtr_parse_ipv6_prefix(struct rtr_session *rs, uint8_t *buf, size_t len) 497 { 498 struct rtr_ipv6 ip6; 499 struct roa *roa; 500 501 if (len != sizeof(struct rtr_header) + sizeof(ip6)) { 502 log_warnx("rtr %s: received %s: bad pdu len", 503 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 504 rtr_send_error(rs, CORRUPT_DATA, "bad len", buf, len); 505 return -1; 506 } 507 508 if (rs->state != RTR_STATE_ACTIVE) { 509 log_warnx("rtr %s: received %s: out of context", 510 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 511 rtr_send_error(rs, CORRUPT_DATA, NULL, buf, len); 512 return -1; 513 } 514 515 memcpy(&ip6, buf + sizeof(struct rtr_header), sizeof(ip6)); 516 if (ip6.prefixlen > 128 || ip6.maxlen > 128 || 517 ip6.prefixlen > ip6.maxlen) { 518 log_warnx("rtr: %s: received %s: bad prefixlen / maxlen", 519 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 520 rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", 521 buf, len); 522 return -1; 523 } 524 525 if ((roa = calloc(1, sizeof(*roa))) == NULL) { 526 log_warn("rtr %s: received %s", 527 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 528 rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0); 529 return -1; 530 } 531 roa->aid = AID_INET6; 532 roa->prefixlen = ip6.prefixlen; 533 roa->maxlen = ip6.maxlen; 534 roa->asnum = ntohl(ip6.asnum); 535 memcpy(&roa->prefix.inet6, ip6.prefix, sizeof(roa->prefix.inet6)); 536 537 if (ip6.flags & FLAG_ANNOUNCE) { 538 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 539 log_warnx("rtr %s: received %s: duplicate announcement", 540 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 541 rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len); 542 free(roa); 543 return -1; 544 } 545 } else { 546 struct roa *r; 547 548 r = RB_FIND(roa_tree, &rs->roa_set, roa); 549 if (r == NULL) { 550 log_warnx("rtr %s: received %s: unknown withdrawal", 551 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 552 rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len); 553 free(roa); 554 return -1; 555 } 556 RB_REMOVE(roa_tree, &rs->roa_set, r); 557 free(r); 558 free(roa); 559 } 560 return 0; 561 } 562 563 static int 564 rtr_parse_end_of_data(struct rtr_session *rs, uint8_t *buf, size_t len) 565 { 566 struct rtr_endofdata eod; 567 uint32_t t; 568 569 buf += sizeof(struct rtr_header); 570 len -= sizeof(struct rtr_header); 571 572 if (len != sizeof(eod)) { 573 log_warnx("rtr %s: received %s: bad pdu len", 574 log_rtr(rs), log_rtr_type(END_OF_DATA)); 575 return -1; 576 } 577 578 memcpy(&eod, buf, sizeof(eod)); 579 580 if (rs->state != RTR_STATE_ACTIVE) { 581 log_warnx("rtr %s: received %s: out of context", 582 log_rtr(rs), log_rtr_type(END_OF_DATA)); 583 return -1; 584 } 585 586 rs->serial = ntohl(eod.serial); 587 /* validate timer values to be in the right range */ 588 t = ntohl(eod.refresh); 589 if (t < 1 || t > 86400) 590 goto bad; 591 rs->refresh = t; 592 t = ntohl(eod.retry); 593 if (t < 1 || t > 7200) 594 goto bad; 595 rs->retry = t; 596 t = ntohl(eod.expire); 597 if (t < 600 || t > 172800) 598 goto bad; 599 if (t <= rs->retry || t <= rs->refresh) 600 goto bad; 601 rs->expire = t; 602 603 rtr_fsm(rs, RTR_EVNT_END_OF_DATA); 604 return 0; 605 606 bad: 607 log_warnx("rtr %s: received %s: bad timeout values", 608 log_rtr(rs), log_rtr_type(END_OF_DATA)); 609 return -1; 610 } 611 612 static int 613 rtr_parse_cache_reset(struct rtr_session *rs, uint8_t *buf, size_t len) 614 { 615 if (rs->state != RTR_STATE_IDLE) { 616 log_warnx("rtr %s: received %s: out of context", 617 log_rtr(rs), log_rtr_type(CACHE_RESET)); 618 return -1; 619 } 620 621 rtr_fsm(rs, RTR_EVNT_CACHE_RESET); 622 return 0; 623 } 624 625 /* 626 * Parse an Error Response message. This function behaves a bit different 627 * from other parse functions since on error the connection needs to be 628 * dropped without sending an error response back. 629 */ 630 static int 631 rtr_parse_error(struct rtr_session *rs, uint8_t *buf, size_t len) 632 { 633 struct rtr_header rh; 634 uint32_t pdu_len, msg_len; 635 uint8_t *msg; 636 char *str = NULL; 637 uint16_t errcode; 638 639 memcpy(&rh, buf, sizeof(rh)); 640 buf += sizeof(struct rtr_header); 641 len -= sizeof(struct rtr_header); 642 errcode = ntohs(rh.session_id); 643 644 memcpy(&pdu_len, buf, sizeof(pdu_len)); 645 pdu_len = ntohl(pdu_len); 646 647 if (len < pdu_len + sizeof(pdu_len)) { 648 log_warnx("rtr %s: received %s: bad encapsulated pdu len: %u " 649 "byte", log_rtr(rs), log_rtr_type(ERROR_REPORT), pdu_len); 650 rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE); 651 return -1; 652 } 653 654 /* for now just ignore the embedded pdu */ 655 buf += pdu_len + sizeof(pdu_len); 656 len -= pdu_len + sizeof(pdu_len); 657 658 memcpy(&msg_len, buf, sizeof(msg_len)); 659 msg_len = ntohl(msg_len); 660 661 if (len < msg_len + sizeof(msg_len)) { 662 log_warnx("rtr %s: received %s: bad msg len: %u byte", 663 log_rtr(rs), log_rtr_type(ERROR_REPORT), msg_len); 664 rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE); 665 return -1; 666 } 667 668 msg = buf + sizeof(msg_len); 669 if (msg_len != 0) 670 /* optional error msg, no need to check for failure */ 671 str = strndup(msg, msg_len); 672 673 log_warnx("rtr %s: received error: %s%s%s", log_rtr(rs), 674 log_rtr_error(errcode), str ? ": " : "", str ? str : ""); 675 676 if (errcode == NO_DATA_AVAILABLE) { 677 rtr_fsm(rs, RTR_EVNT_NO_DATA); 678 } else { 679 rtr_fsm(rs, RTR_EVNT_RESET_AND_CLOSE); 680 rs->last_recv_error = errcode; 681 if (str) 682 strlcpy(rs->last_recv_msg, str, 683 sizeof(rs->last_recv_msg)); 684 else 685 memset(rs->last_recv_msg, 0, 686 sizeof(rs->last_recv_msg)); 687 688 free(str); 689 return -1; 690 } 691 free(str); 692 693 return 0; 694 } 695 696 /* 697 * Try to process received rtr message, it is possible that not a full 698 * message is in the buffer. In that case stop, once new data is available 699 * a retry will be done. 700 */ 701 static void 702 rtr_process_msg(struct rtr_session *rs) 703 { 704 size_t rpos, av, left; 705 void *rptr; 706 size_t msglen; 707 enum rtr_pdu_type msgtype; 708 709 rpos = 0; 710 av = rs->r.wpos; 711 712 for (;;) { 713 if (rpos + sizeof(struct rtr_header) > av) 714 break; 715 rptr = rs->r.buf + rpos; 716 if (rtr_parse_header(rs, rptr, &msglen, &msgtype) == -1) 717 return; 718 719 /* missing data */ 720 if (rpos + msglen > av) 721 break; 722 723 switch (msgtype) { 724 case SERIAL_NOTIFY: 725 if (rtr_parse_notify(rs, rptr, msglen) == -1) { 726 rtr_send_error(rs, CORRUPT_DATA, NULL, 727 rptr, msglen); 728 return; 729 } 730 break; 731 case CACHE_RESPONSE: 732 if (rtr_parse_cache_response(rs, rptr, msglen) == -1) { 733 rtr_send_error(rs, CORRUPT_DATA, NULL, 734 rptr, msglen); 735 return; 736 } 737 break; 738 case IPV4_PREFIX: 739 if (rtr_parse_ipv4_prefix(rs, rptr, msglen) == -1) { 740 return; 741 } 742 break; 743 case IPV6_PREFIX: 744 if (rtr_parse_ipv6_prefix(rs, rptr, msglen) == -1) { 745 return; 746 } 747 break; 748 case END_OF_DATA: 749 if (rtr_parse_end_of_data(rs, rptr, msglen) == -1) { 750 rtr_send_error(rs, CORRUPT_DATA, NULL, 751 rptr, msglen); 752 return; 753 } 754 break; 755 case CACHE_RESET: 756 if (rtr_parse_cache_reset(rs, rptr, msglen) == -1) { 757 rtr_send_error(rs, CORRUPT_DATA, NULL, 758 rptr, msglen); 759 return; 760 } 761 break; 762 case ROUTER_KEY: 763 /* silently ignore router key */ 764 break; 765 case ERROR_REPORT: 766 if (rtr_parse_error(rs, rptr, msglen) == -1) 767 /* no need to send back an error */ 768 return; 769 break; 770 default: 771 log_warnx("rtr %s: received %s: unexpected pdu type", 772 log_rtr(rs), log_rtr_type(msgtype)); 773 rtr_send_error(rs, INVALID_REQUEST, NULL, rptr, msglen); 774 return; 775 } 776 rpos += msglen; 777 } 778 779 left = av - rpos; 780 memmove(&rs->r.buf, rs->r.buf + rpos, left); 781 rs->r.wpos = left; 782 } 783 784 /* 785 * Simple FSM for RTR sessions 786 */ 787 static void 788 rtr_fsm(struct rtr_session *rs, enum rtr_event event) 789 { 790 enum rtr_state prev_state = rs->state; 791 792 switch (event) { 793 case RTR_EVNT_RESET_AND_CLOSE: 794 rs->state = RTR_STATE_ERROR; 795 /* FALLTHROUGH */ 796 case RTR_EVNT_CON_CLOSE: 797 if (rs->state == RTR_STATE_ERROR) { 798 /* reset session */ 799 rs->session_id = -1; 800 free_roatree(&rs->roa_set); 801 rtr_recalc(); 802 } 803 if (rs->state != RTR_STATE_CLOSED) { 804 /* flush buffers */ 805 msgbuf_clear(&rs->w); 806 rs->r.wpos = 0; 807 close(rs->fd); 808 rs->fd = -1; 809 } 810 rs->state = RTR_STATE_CLOSED; 811 /* try to reopen session */ 812 timer_set(&rs->timers, Timer_Rtr_Retry, 813 arc4random_uniform(10)); 814 break; 815 case RTR_EVNT_START: 816 case RTR_EVNT_TIMER_RETRY: 817 switch (rs->state) { 818 case RTR_STATE_ERROR: 819 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 820 return; 821 case RTR_STATE_CLOSED: 822 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 823 rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0); 824 return; 825 default: 826 break; 827 } 828 /* FALLTHROUGH */ 829 case RTR_EVNT_CON_OPEN: 830 timer_stop(&rs->timers, Timer_Rtr_Retry); 831 if (rs->session_id == -1) 832 rtr_reset_query(rs); 833 else 834 rtr_serial_query(rs); 835 break; 836 case RTR_EVNT_SERIAL_NOTIFY: 837 /* schedule a refresh after a quick wait */ 838 timer_set(&rs->timers, Timer_Rtr_Refresh, 839 arc4random_uniform(10)); 840 break; 841 case RTR_EVNT_TIMER_REFRESH: 842 /* send serial query */ 843 rtr_serial_query(rs); 844 break; 845 case RTR_EVNT_TIMER_EXPIRE: 846 free_roatree(&rs->roa_set); 847 rtr_recalc(); 848 break; 849 case RTR_EVNT_CACHE_RESPONSE: 850 rs->state = RTR_STATE_ACTIVE; 851 timer_stop(&rs->timers, Timer_Rtr_Refresh); 852 timer_stop(&rs->timers, Timer_Rtr_Retry); 853 break; 854 case RTR_EVNT_END_OF_DATA: 855 /* start refresh and expire timers */ 856 timer_set(&rs->timers, Timer_Rtr_Refresh, rs->refresh); 857 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 858 rs->state = RTR_STATE_IDLE; 859 rtr_recalc(); 860 break; 861 case RTR_EVNT_CACHE_RESET: 862 /* reset session and retry after a quick wait */ 863 rs->session_id = -1; 864 free_roatree(&rs->roa_set); 865 rtr_recalc(); 866 timer_set(&rs->timers, Timer_Rtr_Retry, 867 arc4random_uniform(10)); 868 break; 869 case RTR_EVNT_NO_DATA: 870 /* start retry timer */ 871 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 872 /* stop refresh timer just to be sure */ 873 timer_stop(&rs->timers, Timer_Rtr_Refresh); 874 break; 875 case RTR_EVNT_SEND_ERROR: 876 rs->state = RTR_STATE_ERROR; 877 /* flush receive buffer */ 878 rs->r.wpos = 0; 879 break; 880 } 881 882 log_info("rtr %s: state change %s -> %s, reason: %s", 883 log_rtr(rs), rtr_statenames[prev_state], rtr_statenames[rs->state], 884 rtr_eventnames[event]); 885 } 886 887 /* 888 * IO handler for RTR sessions 889 */ 890 static void 891 rtr_dispatch_msg(struct pollfd *pfd, struct rtr_session *rs) 892 { 893 ssize_t n; 894 int error; 895 896 if (pfd->revents & POLLHUP) { 897 log_warnx("rtr %s: Connection closed, hangup", log_rtr(rs)); 898 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 899 return; 900 } 901 if (pfd->revents & (POLLERR|POLLNVAL)) { 902 log_warnx("rtr %s: Connection closed, error", log_rtr(rs)); 903 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 904 return; 905 } 906 if (pfd->revents & POLLOUT && rs->w.queued) { 907 if ((error = ibuf_write(&rs->w)) <= 0 && errno != EAGAIN) { 908 if (error == 0) 909 log_warnx("rtr %s: Connection closed", 910 log_rtr(rs)); 911 else if (error == -1) 912 log_warn("rtr %s: write error", log_rtr(rs)); 913 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 914 return; 915 } 916 if (rs->w.queued == 0 && rs->state == RTR_STATE_ERROR) 917 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 918 } 919 if (pfd->revents & POLLIN) { 920 if ((n = read(rs->fd, rs->r.buf + rs->r.wpos, 921 sizeof(rs->r.buf) - rs->r.wpos)) == -1) { 922 if (errno != EINTR && errno != EAGAIN) { 923 log_warn("rtr %s: read error", log_rtr(rs)); 924 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 925 } 926 return; 927 } 928 if (n == 0) { 929 log_warnx("rtr %s: Connection closed", log_rtr(rs)); 930 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 931 return; 932 } 933 rs->r.wpos += n; 934 935 /* new data arrived, try to process it */ 936 rtr_process_msg(rs); 937 } 938 939 } 940 941 void 942 rtr_check_events(struct pollfd *pfds, size_t npfds) 943 { 944 struct rtr_session *rs; 945 struct timer *t; 946 time_t now; 947 size_t i = 0; 948 949 for (i = 0; i < npfds; i++) { 950 if (pfds[i].revents == 0) 951 continue; 952 TAILQ_FOREACH(rs, &rtrs, entry) 953 if (rs->fd == pfds[i].fd) { 954 rtr_dispatch_msg(&pfds[i], rs); 955 break; 956 } 957 if (rs == NULL) 958 log_warnx("%s: unknown fd in pollfds", __func__); 959 } 960 961 /* run all timers */ 962 now = getmonotime(); 963 TAILQ_FOREACH(rs, &rtrs, entry) 964 if ((t = timer_nextisdue(&rs->timers, now)) != NULL) { 965 log_debug("rtr %s: %s triggered", log_rtr(rs), 966 timernames[t->type]); 967 /* stop timer so it does not trigger again */ 968 timer_stop(&rs->timers, t->type); 969 switch (t->type) { 970 case Timer_Rtr_Refresh: 971 rtr_fsm(rs, RTR_EVNT_TIMER_REFRESH); 972 break; 973 case Timer_Rtr_Retry: 974 rtr_fsm(rs, RTR_EVNT_TIMER_RETRY); 975 break; 976 case Timer_Rtr_Expire: 977 rtr_fsm(rs, RTR_EVNT_TIMER_EXPIRE); 978 break; 979 default: 980 fatalx("King Bula lost in time"); 981 } 982 } 983 } 984 985 size_t 986 rtr_count(void) 987 { 988 struct rtr_session *rs; 989 size_t count = 0; 990 991 TAILQ_FOREACH(rs, &rtrs, entry) 992 count++; 993 return count; 994 } 995 996 size_t 997 rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout) 998 { 999 struct rtr_session *rs; 1000 time_t now = getmonotime(); 1001 size_t i = 0; 1002 1003 TAILQ_FOREACH(rs, &rtrs, entry) { 1004 time_t nextaction; 1005 struct pollfd *pfd = pfds + i++; 1006 1007 if (i > npfds) 1008 fatalx("%s: too many sessions for pollfd", __func__); 1009 1010 if ((nextaction = timer_nextduein(&rs->timers, now)) != -1 && 1011 nextaction < *timeout) 1012 *timeout = nextaction; 1013 1014 if (rs->state == RTR_STATE_CLOSED) { 1015 pfd->fd = -1; 1016 continue; 1017 } 1018 1019 pfd->fd = rs->fd; 1020 pfd->events = 0; 1021 1022 if (rs->w.queued) 1023 pfd->events |= POLLOUT; 1024 if (rs->state >= RTR_STATE_IDLE) 1025 pfd->events |= POLLIN; 1026 } 1027 1028 return i; 1029 } 1030 1031 struct rtr_session * 1032 rtr_new(uint32_t id, char *descr) 1033 { 1034 struct rtr_session *rs; 1035 1036 if ((rs = calloc(1, sizeof(*rs))) == NULL) 1037 fatal("RTR session %s", descr); 1038 1039 RB_INIT(&rs->roa_set); 1040 TAILQ_INIT(&rs->timers); 1041 msgbuf_init(&rs->w); 1042 1043 strlcpy(rs->descr, descr, sizeof(rs->descr)); 1044 rs->id = id; 1045 rs->session_id = -1; 1046 rs->refresh = RTR_DEFAULT_REFRESH; 1047 rs->retry = RTR_DEFAULT_RETRY; 1048 rs->expire = RTR_DEFAULT_EXPIRE; 1049 rs->state = RTR_STATE_CLOSED; 1050 rs->reconf_action = RECONF_REINIT; 1051 rs->last_recv_error = NO_ERROR; 1052 rs->last_sent_error = NO_ERROR; 1053 1054 /* make sure that some timer is running to abort bad sessions */ 1055 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 1056 1057 log_debug("rtr %s: new session, start", log_rtr(rs)); 1058 TAILQ_INSERT_TAIL(&rtrs, rs, entry); 1059 rtr_fsm(rs, RTR_EVNT_START); 1060 1061 return rs; 1062 } 1063 1064 struct rtr_session * 1065 rtr_get(uint32_t id) 1066 { 1067 struct rtr_session *rs; 1068 1069 TAILQ_FOREACH(rs, &rtrs, entry) 1070 if (rs->id == id) 1071 return rs; 1072 return NULL; 1073 } 1074 1075 void 1076 rtr_free(struct rtr_session *rs) 1077 { 1078 if (rs == NULL) 1079 return; 1080 1081 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1082 timer_remove_all(&rs->timers); 1083 free_roatree(&rs->roa_set); 1084 free(rs); 1085 } 1086 1087 void 1088 rtr_open(struct rtr_session *rs, int fd) 1089 { 1090 if (rs->state != RTR_STATE_CLOSED) { 1091 log_warnx("rtr %s: bad session state", log_rtr(rs)); 1092 rtr_fsm(rs, RTR_EVNT_CON_CLOSE); 1093 } 1094 1095 log_debug("rtr %s: connection opened", log_rtr(rs)); 1096 1097 rs->fd = rs->w.fd = fd; 1098 rs->state = RTR_STATE_IDLE; 1099 rtr_fsm(rs, RTR_EVNT_CON_OPEN); 1100 } 1101 1102 void 1103 rtr_config_prep(void) 1104 { 1105 struct rtr_session *rs; 1106 1107 TAILQ_FOREACH(rs, &rtrs, entry) 1108 rs->reconf_action = RECONF_DELETE; 1109 } 1110 1111 void 1112 rtr_config_merge(void) 1113 { 1114 struct rtr_session *rs, *nrs; 1115 1116 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1117 if (rs->reconf_action == RECONF_DELETE) { 1118 TAILQ_REMOVE(&rtrs, rs, entry); 1119 rtr_free(rs); 1120 } 1121 } 1122 1123 void 1124 rtr_config_keep(struct rtr_session *rs) 1125 { 1126 rs->reconf_action = RECONF_KEEP; 1127 } 1128 1129 void 1130 rtr_roa_merge(struct roa_tree *rt) 1131 { 1132 struct rtr_session *rs; 1133 struct roa *roa; 1134 1135 TAILQ_FOREACH(rs, &rtrs, entry) { 1136 RB_FOREACH(roa, roa_tree, &rs->roa_set) 1137 roa_insert(rt, roa); 1138 } 1139 } 1140 1141 void 1142 rtr_shutdown(void) 1143 { 1144 struct rtr_session *rs, *nrs; 1145 1146 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1147 rtr_free(rs); 1148 } 1149 1150 void 1151 rtr_show(struct rtr_session *rs, pid_t pid) 1152 { 1153 struct ctl_show_rtr msg; 1154 struct ctl_timer ct; 1155 u_int i; 1156 time_t d; 1157 1158 memset(&msg, 0, sizeof(msg)); 1159 1160 /* descr, remote_addr, local_addr and remote_port set by parent */ 1161 msg.serial = rs->serial; 1162 msg.refresh = rs->refresh; 1163 msg.retry = rs->retry; 1164 msg.expire = rs->expire; 1165 msg.session_id = rs->session_id; 1166 msg.last_sent_error = rs->last_sent_error; 1167 msg.last_recv_error = rs->last_recv_error; 1168 strlcpy(msg.last_sent_msg, rs->last_sent_msg, 1169 sizeof(msg.last_sent_msg)); 1170 strlcpy(msg.last_recv_msg, rs->last_recv_msg, 1171 sizeof(msg.last_recv_msg)); 1172 1173 /* send back imsg */ 1174 rtr_imsg_compose(IMSG_CTL_SHOW_RTR, rs->id, pid, &msg, sizeof(msg)); 1175 1176 /* send back timer imsgs */ 1177 for (i = 1; i < Timer_Max; i++) { 1178 if (!timer_running(&rs->timers, i, &d)) 1179 continue; 1180 ct.type = i; 1181 ct.val = d; 1182 rtr_imsg_compose(IMSG_CTL_SHOW_TIMER, rs->id, pid, 1183 &ct, sizeof(ct)); 1184 } 1185 } 1186