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