1 /* $OpenBSD: rtr_proto.c,v 1.4 2021/08/02 16:42:13 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 if (ip4.prefixlen > 32 || ip4.maxlen > 32 || 453 ip4.prefixlen > ip4.maxlen) { 454 log_warnx("rtr: %s: received %s: bad prefixlen / maxlen", 455 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 456 rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", 457 buf, len); 458 return -1; 459 } 460 roa->aid = AID_INET; 461 roa->prefixlen = ip4.prefixlen; 462 roa->maxlen = ip4.maxlen; 463 roa->asnum = ntohl(ip4.asnum); 464 roa->prefix.inet.s_addr = ip4.prefix; 465 466 if (ip4.flags & FLAG_ANNOUNCE) { 467 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 468 log_warnx("rtr %s: received %s: duplicate announcement", 469 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 470 rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len); 471 free(roa); 472 return -1; 473 } 474 } else { 475 struct roa *r; 476 477 r = RB_FIND(roa_tree, &rs->roa_set, roa); 478 if (r == NULL) { 479 log_warnx("rtr %s: received %s: unknown withdrawl", 480 log_rtr(rs), log_rtr_type(IPV4_PREFIX)); 481 rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len); 482 free(roa); 483 return -1; 484 } 485 RB_REMOVE(roa_tree, &rs->roa_set, r); 486 free(r); 487 free(roa); 488 } 489 490 return 0; 491 } 492 493 static int 494 rtr_parse_ipv6_prefix(struct rtr_session *rs, uint8_t *buf, size_t len) 495 { 496 struct rtr_ipv6 ip6; 497 struct roa *roa; 498 499 if (len != sizeof(struct rtr_header) + sizeof(ip6)) { 500 log_warnx("rtr %s: received %s: bad pdu len", 501 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 502 rtr_send_error(rs, CORRUPT_DATA, "bad len", buf, len); 503 return -1; 504 } 505 506 if (rs->state != RTR_STATE_ACTIVE) { 507 log_warnx("rtr %s: received %s: out of context", 508 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 509 rtr_send_error(rs, CORRUPT_DATA, NULL, buf, len); 510 return -1; 511 } 512 513 memcpy(&ip6, buf + sizeof(struct rtr_header), sizeof(ip6)); 514 515 if ((roa = calloc(1, sizeof(*roa))) == NULL) { 516 log_warn("rtr %s: received %s", 517 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 518 rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL, 0); 519 return -1; 520 } 521 if (ip6.prefixlen > 128 || ip6.maxlen > 128 || 522 ip6.prefixlen > ip6.maxlen) { 523 log_warnx("rtr: %s: received %s: bad prefixlen / maxlen", 524 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 525 rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", 526 buf, len); 527 return -1; 528 } 529 roa->aid = AID_INET6; 530 roa->prefixlen = ip6.prefixlen; 531 roa->maxlen = ip6.maxlen; 532 roa->asnum = ntohl(ip6.asnum); 533 memcpy(&roa->prefix.inet6, ip6.prefix, sizeof(roa->prefix.inet6)); 534 535 if (ip6.flags & FLAG_ANNOUNCE) { 536 if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) { 537 log_warnx("rtr %s: received %s: duplicate announcement", 538 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 539 rtr_send_error(rs, DUP_REC_RECV, NULL, buf, len); 540 free(roa); 541 return -1; 542 } 543 } else { 544 struct roa *r; 545 546 r = RB_FIND(roa_tree, &rs->roa_set, roa); 547 if (r == NULL) { 548 log_warnx("rtr %s: received %s: unknown withdrawl", 549 log_rtr(rs), log_rtr_type(IPV6_PREFIX)); 550 rtr_send_error(rs, UNK_REC_WDRAWL, NULL, buf, len); 551 free(roa); 552 return -1; 553 } 554 RB_REMOVE(roa_tree, &rs->roa_set, r); 555 free(r); 556 free(roa); 557 } 558 return 0; 559 } 560 561 static int 562 rtr_parse_end_of_data(struct rtr_session *rs, uint8_t *buf, size_t len) 563 { 564 struct rtr_endofdata eod; 565 uint32_t t; 566 567 buf += sizeof(struct rtr_header); 568 len -= sizeof(struct rtr_header); 569 570 if (len != sizeof(eod)) { 571 log_warnx("rtr %s: received %s: bad pdu len", 572 log_rtr(rs), log_rtr_type(END_OF_DATA)); 573 return -1; 574 } 575 576 memcpy(&eod, buf, sizeof(eod)); 577 578 if (rs->state != RTR_STATE_ACTIVE) { 579 log_warnx("rtr %s: received %s: out of context", 580 log_rtr(rs), log_rtr_type(END_OF_DATA)); 581 return -1; 582 } 583 584 rs->serial = ntohl(eod.serial); 585 /* validate timer values to be in the right range */ 586 t = ntohl(eod.refresh); 587 if (t < 1 || t > 86400) 588 goto bad; 589 rs->refresh = t; 590 t = ntohl(eod.retry); 591 if (t < 1 || t > 7200) 592 goto bad; 593 rs->retry = t; 594 t = ntohl(eod.expire); 595 if (t < 600 || t > 172800) 596 goto bad; 597 if (t <= rs->retry || t <= rs->refresh) 598 goto bad; 599 rs->expire = t; 600 601 rtr_fsm(rs, RTR_EVNT_END_OF_DATA); 602 return 0; 603 604 bad: 605 log_warnx("rtr %s: received %s: bad timeout values", 606 log_rtr(rs), log_rtr_type(END_OF_DATA)); 607 return -1; 608 } 609 610 static int 611 rtr_parse_cache_reset(struct rtr_session *rs, uint8_t *buf, size_t len) 612 { 613 if (rs->state != RTR_STATE_IDLE) { 614 log_warnx("rtr %s: received %s: out of context", 615 log_rtr(rs), log_rtr_type(CACHE_RESET)); 616 return -1; 617 } 618 619 rtr_fsm(rs, RTR_EVNT_CACHE_RESET); 620 return 0; 621 } 622 623 /* 624 * Parse an Error Response message. This function behaves a bit different 625 * from other parse functions since on error the connection needs to be 626 * dropped without sending an error response back. 627 */ 628 static int 629 rtr_parse_error(struct rtr_session *rs, uint8_t *buf, size_t len) 630 { 631 struct rtr_header rh; 632 uint32_t pdu_len, msg_len; 633 uint8_t *msg; 634 char *str = NULL; 635 uint16_t errcode; 636 637 memcpy(&rh, buf, sizeof(rh)); 638 buf += sizeof(struct rtr_header); 639 len -= sizeof(struct rtr_header); 640 errcode = ntohs(rh.session_id); 641 642 memcpy(&pdu_len, buf, sizeof(pdu_len)); 643 pdu_len = ntohs(pdu_len); 644 645 if (len < pdu_len + sizeof(pdu_len)) { 646 log_warnx("rtr %s: received %s: bad pdu len: %u byte", 647 log_rtr(rs), log_rtr_type(ERROR_REPORT), pdu_len); 648 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 649 return -1; 650 } 651 652 /* for now just ignore the embedded pdu */ 653 buf += pdu_len + sizeof(pdu_len); 654 len -= pdu_len + sizeof(pdu_len); 655 656 memcpy(&msg_len, buf, sizeof(msg_len)); 657 msg_len = ntohs(msg_len); 658 659 if (len < msg_len + sizeof(msg_len)) { 660 log_warnx("rtr %s: received %s: bad msg len: %u byte", 661 log_rtr(rs), log_rtr_type(ERROR_REPORT), msg_len); 662 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 663 return -1; 664 } 665 666 msg = buf + sizeof(msg_len); 667 if (msg_len != 0) 668 /* optional error msg, no need to check for failure */ 669 str = strndup(msg, msg_len); 670 671 log_warnx("rtr %s: received error: %s%s%s", log_rtr(rs), 672 log_rtr_error(errcode), str ? ": " : "", str ? str : ""); 673 674 if (errcode == NO_DATA_AVAILABLE) { 675 rtr_fsm(rs, RTR_EVNT_NO_DATA); 676 } else { 677 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 678 rs->last_recv_error = errcode; 679 if (str) 680 strlcpy(rs->last_recv_msg, str, 681 sizeof(rs->last_recv_msg)); 682 else 683 memset(rs->last_recv_msg, 0, 684 sizeof(rs->last_recv_msg)); 685 686 free(str); 687 return -1; 688 } 689 free(str); 690 691 return 0; 692 } 693 694 /* 695 * Try to process received rtr message, it is possible that not a full 696 * message is in the buffer. In that case stop, once new data is available 697 * a retry will be done. 698 */ 699 static void 700 rtr_process_msg(struct rtr_session *rs) 701 { 702 size_t rpos, av, left; 703 void *rptr; 704 size_t msglen; 705 enum rtr_pdu_type msgtype; 706 707 rpos = 0; 708 av = rs->r.wpos; 709 710 for (;;) { 711 if (rpos + sizeof(struct rtr_header) > av) 712 break; 713 rptr = rs->r.buf + rpos; 714 if (rtr_parse_header(rs, rptr, &msglen, &msgtype) == -1) 715 return; 716 717 /* missing data */ 718 if (rpos + msglen > av) 719 break; 720 721 switch (msgtype) { 722 case SERIAL_NOTIFY: 723 if (rtr_parse_notify(rs, rptr, msglen) == -1) { 724 rtr_send_error(rs, CORRUPT_DATA, NULL, 725 rptr, msglen); 726 return; 727 } 728 break; 729 case CACHE_RESPONSE: 730 if (rtr_parse_cache_response(rs, rptr, msglen) == -1) { 731 rtr_send_error(rs, CORRUPT_DATA, NULL, 732 rptr, msglen); 733 return; 734 } 735 break; 736 case IPV4_PREFIX: 737 if (rtr_parse_ipv4_prefix(rs, rptr, msglen) == -1) { 738 return; 739 } 740 break; 741 case IPV6_PREFIX: 742 if (rtr_parse_ipv6_prefix(rs, rptr, msglen) == -1) { 743 return; 744 } 745 break; 746 case END_OF_DATA: 747 if (rtr_parse_end_of_data(rs, rptr, msglen) == -1) { 748 rtr_send_error(rs, CORRUPT_DATA, NULL, 749 rptr, msglen); 750 return; 751 } 752 break; 753 case CACHE_RESET: 754 if (rtr_parse_cache_reset(rs, rptr, msglen) == -1) { 755 rtr_send_error(rs, CORRUPT_DATA, NULL, 756 rptr, msglen); 757 return; 758 } 759 break; 760 case ROUTER_KEY: 761 /* silently ignore router key */ 762 break; 763 case ERROR_REPORT: 764 if (rtr_parse_error(rs, rptr, msglen) == -1) 765 /* no need to send back an error */ 766 return; 767 break; 768 default: 769 log_warnx("rtr %s: received %s: unexpected pdu type", 770 log_rtr(rs), log_rtr_type(msgtype)); 771 rtr_send_error(rs, INVALID_REQUEST, NULL, rptr, msglen); 772 return; 773 } 774 rpos += msglen; 775 } 776 777 left = av - rpos; 778 memmove(&rs->r.buf, rs->r.buf + rpos, left); 779 rs->r.wpos = left; 780 } 781 782 /* 783 * Simple FSM for RTR sessions 784 */ 785 static void 786 rtr_fsm(struct rtr_session *rs, enum rtr_event event) 787 { 788 enum rtr_state prev_state = rs->state; 789 790 switch (event) { 791 case RTR_EVNT_CON_CLOSED: 792 if (rs->state != RTR_STATE_CLOSED) { 793 /* flush buffers */ 794 msgbuf_clear(&rs->w); 795 rs->r.wpos = 0; 796 close(rs->fd); 797 rs->fd = -1; 798 } 799 rs->state = RTR_STATE_CLOSED; 800 /* try to reopen session */ 801 timer_set(&rs->timers, Timer_Rtr_Retry, 802 arc4random_uniform(10)); 803 break; 804 case RTR_EVNT_START: 805 case RTR_EVNT_TIMER_RETRY: 806 switch (rs->state) { 807 case RTR_STATE_ERROR: 808 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 809 return; 810 case RTR_STATE_CLOSED: 811 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 812 rtr_imsg_compose(IMSG_SOCKET_CONN, rs->id, 0, NULL, 0); 813 return; 814 default: 815 break; 816 } 817 /* FALLTHROUGH */ 818 case RTR_EVNT_CON_OPEN: 819 timer_stop(&rs->timers, Timer_Rtr_Retry); 820 if (rs->session_id == -1) 821 rtr_reset_query(rs); 822 else 823 rtr_serial_query(rs); 824 break; 825 case RTR_EVNT_SERIAL_NOTIFY: 826 /* schedule a refresh after a quick wait */ 827 timer_set(&rs->timers, Timer_Rtr_Refresh, 828 arc4random_uniform(10)); 829 break; 830 case RTR_EVNT_TIMER_REFRESH: 831 /* send serial query */ 832 rtr_serial_query(rs); 833 break; 834 case RTR_EVNT_TIMER_EXPIRE: 835 free_roatree(&rs->roa_set); 836 rtr_recalc(); 837 break; 838 case RTR_EVNT_CACHE_RESPONSE: 839 rs->state = RTR_STATE_ACTIVE; 840 timer_stop(&rs->timers, Timer_Rtr_Refresh); 841 timer_stop(&rs->timers, Timer_Rtr_Retry); 842 break; 843 case RTR_EVNT_END_OF_DATA: 844 /* start refresh and expire timers */ 845 timer_set(&rs->timers, Timer_Rtr_Refresh, rs->refresh); 846 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 847 rs->state = RTR_STATE_IDLE; 848 rtr_recalc(); 849 break; 850 case RTR_EVNT_CACHE_RESET: 851 /* reset session and retry after a quick wait */ 852 rs->session_id = -1; 853 free_roatree(&rs->roa_set); 854 timer_set(&rs->timers, Timer_Rtr_Retry, 855 arc4random_uniform(10)); 856 break; 857 case RTR_EVNT_NO_DATA: 858 /* start retry timer */ 859 timer_set(&rs->timers, Timer_Rtr_Retry, rs->retry); 860 /* stop refresh timer just to be sure */ 861 timer_stop(&rs->timers, Timer_Rtr_Refresh); 862 break; 863 case RTR_EVNT_SEND_ERROR: 864 rs->state = RTR_STATE_ERROR; 865 /* flush receive buffer */ 866 rs->r.wpos = 0; 867 break; 868 } 869 870 log_info("rtr %s: state change %s -> %s, reason: %s", 871 log_rtr(rs), rtr_statenames[prev_state], rtr_statenames[rs->state], 872 rtr_eventnames[event]); 873 } 874 875 /* 876 * IO handler for RTR sessions 877 */ 878 static void 879 rtr_dispatch_msg(struct pollfd *pfd, struct rtr_session *rs) 880 { 881 ssize_t n; 882 int error; 883 884 if (pfd->revents & POLLHUP) { 885 log_warnx("rtr %s: Connection closed, hangup", log_rtr(rs)); 886 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 887 return; 888 } 889 if (pfd->revents & (POLLERR|POLLNVAL)) { 890 log_warnx("rtr %s: Connection closed, error", log_rtr(rs)); 891 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 892 return; 893 } 894 if (pfd->revents & POLLOUT && rs->w.queued) { 895 if ((error = ibuf_write(&rs->w)) <= 0 && errno != EAGAIN) { 896 if (error == 0) 897 log_warnx("rtr %s: Connection closed", 898 log_rtr(rs)); 899 else if (error == -1) 900 log_warn("rtr %s: write error", log_rtr(rs)); 901 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 902 return; 903 } 904 if (rs->w.queued == 0 && rs->state == RTR_STATE_ERROR) 905 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 906 } 907 if (pfd->revents & POLLIN) { 908 if ((n = read(rs->fd, rs->r.buf + rs->r.wpos, 909 sizeof(rs->r.buf) - rs->r.wpos)) == -1) { 910 if (errno != EINTR && errno != EAGAIN) { 911 log_warn("rtr %s: read error", log_rtr(rs)); 912 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 913 } 914 return; 915 } 916 if (n == 0) { 917 log_warnx("rtr %s: Connection closed", log_rtr(rs)); 918 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 919 return; 920 } 921 rs->r.wpos += n; 922 923 /* new data arrived, try to process it */ 924 rtr_process_msg(rs); 925 } 926 927 } 928 929 void 930 rtr_check_events(struct pollfd *pfds, size_t npfds) 931 { 932 struct rtr_session *rs; 933 struct timer *t; 934 time_t now; 935 size_t i = 0; 936 937 for (i = 0; i < npfds; i++) { 938 if (pfds[i].revents == 0) 939 continue; 940 TAILQ_FOREACH(rs, &rtrs, entry) 941 if (rs->fd == pfds[i].fd) { 942 rtr_dispatch_msg(&pfds[i], rs); 943 break; 944 } 945 if (rs == NULL) 946 log_warnx("%s: unknown fd in pollfds", __func__); 947 } 948 949 /* run all timers */ 950 now = getmonotime(); 951 TAILQ_FOREACH(rs, &rtrs, entry) 952 if ((t = timer_nextisdue(&rs->timers, now)) != NULL) { 953 log_debug("rtr %s: %s triggered", log_rtr(rs), 954 timernames[t->type]); 955 /* stop timer so it does not trigger again */ 956 timer_stop(&rs->timers, t->type); 957 switch (t->type) { 958 case Timer_Rtr_Refresh: 959 rtr_fsm(rs, RTR_EVNT_TIMER_REFRESH); 960 break; 961 case Timer_Rtr_Retry: 962 rtr_fsm(rs, RTR_EVNT_TIMER_RETRY); 963 break; 964 case Timer_Rtr_Expire: 965 rtr_fsm(rs, RTR_EVNT_TIMER_EXPIRE); 966 break; 967 default: 968 fatalx("King Bula lost in time"); 969 } 970 } 971 } 972 973 size_t 974 rtr_count(void) 975 { 976 struct rtr_session *rs; 977 size_t count = 0; 978 979 TAILQ_FOREACH(rs, &rtrs, entry) 980 count++; 981 return count; 982 } 983 984 size_t 985 rtr_poll_events(struct pollfd *pfds, size_t npfds, time_t *timeout) 986 { 987 struct rtr_session *rs; 988 time_t now = getmonotime(); 989 size_t i = 0; 990 991 TAILQ_FOREACH(rs, &rtrs, entry) { 992 time_t nextaction; 993 struct pollfd *pfd = pfds + i++; 994 995 if (i > npfds) 996 fatalx("%s: too many sessions for pollfd", __func__); 997 998 if ((nextaction = timer_nextduein(&rs->timers, now)) != -1 && 999 nextaction < *timeout) 1000 *timeout = nextaction; 1001 1002 if (rs->state == RTR_STATE_CLOSED) { 1003 pfd->fd = -1; 1004 continue; 1005 } 1006 1007 pfd->fd = rs->fd; 1008 pfd->events = 0; 1009 1010 if (rs->w.queued) 1011 pfd->events |= POLLOUT; 1012 if (rs->state >= RTR_STATE_IDLE) 1013 pfd->events |= POLLIN; 1014 } 1015 1016 return i; 1017 } 1018 1019 struct rtr_session * 1020 rtr_new(uint32_t id, char *descr) 1021 { 1022 struct rtr_session *rs; 1023 1024 if ((rs = calloc(1, sizeof(*rs))) == NULL) 1025 fatal("RTR session %s", descr); 1026 1027 RB_INIT(&rs->roa_set); 1028 TAILQ_INIT(&rs->timers); 1029 msgbuf_init(&rs->w); 1030 1031 strlcpy(rs->descr, descr, sizeof(rs->descr)); 1032 rs->id = id; 1033 rs->session_id = -1; 1034 rs->refresh = RTR_DEFAULT_REFRESH; 1035 rs->retry = RTR_DEFAULT_RETRY; 1036 rs->expire = RTR_DEFAULT_EXPIRE; 1037 rs->state = RTR_STATE_CLOSED; 1038 rs->reconf_action = RECONF_REINIT; 1039 rs->last_recv_error = NO_ERROR; 1040 rs->last_sent_error = NO_ERROR; 1041 1042 /* make sure that some timer is running to abort bad sessions */ 1043 timer_set(&rs->timers, Timer_Rtr_Expire, rs->expire); 1044 1045 log_debug("rtr %s: new session, start", log_rtr(rs)); 1046 TAILQ_INSERT_TAIL(&rtrs, rs, entry); 1047 rtr_fsm(rs, RTR_EVNT_START); 1048 1049 return rs; 1050 } 1051 1052 struct rtr_session * 1053 rtr_get(uint32_t id) 1054 { 1055 struct rtr_session *rs; 1056 1057 TAILQ_FOREACH(rs, &rtrs, entry) 1058 if (rs->id == id) 1059 return rs; 1060 return NULL; 1061 } 1062 1063 void 1064 rtr_free(struct rtr_session *rs) 1065 { 1066 if (rs == NULL) 1067 return; 1068 1069 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 1070 timer_remove_all(&rs->timers); 1071 free_roatree(&rs->roa_set); 1072 free(rs); 1073 } 1074 1075 void 1076 rtr_open(struct rtr_session *rs, int fd) 1077 { 1078 if (rs->state != RTR_STATE_CLOSED) { 1079 log_warnx("rtr %s: bad session state", log_rtr(rs)); 1080 rtr_fsm(rs, RTR_EVNT_CON_CLOSED); 1081 } 1082 1083 log_debug("rtr %s: connection opened", log_rtr(rs)); 1084 1085 rs->fd = rs->w.fd = fd; 1086 rs->state = RTR_STATE_IDLE; 1087 rtr_fsm(rs, RTR_EVNT_CON_OPEN); 1088 } 1089 1090 void 1091 rtr_config_prep(void) 1092 { 1093 struct rtr_session *rs; 1094 1095 TAILQ_FOREACH(rs, &rtrs, entry) 1096 rs->reconf_action = RECONF_DELETE; 1097 } 1098 1099 void 1100 rtr_config_merge(void) 1101 { 1102 struct rtr_session *rs, *nrs; 1103 1104 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1105 if (rs->reconf_action == RECONF_DELETE) { 1106 TAILQ_REMOVE(&rtrs, rs, entry); 1107 rtr_free(rs); 1108 } 1109 } 1110 1111 void 1112 rtr_config_keep(struct rtr_session *rs) 1113 { 1114 rs->reconf_action = RECONF_KEEP; 1115 } 1116 1117 void 1118 rtr_roa_merge(struct roa_tree *rt) 1119 { 1120 struct rtr_session *rs; 1121 struct roa *roa; 1122 1123 TAILQ_FOREACH(rs, &rtrs, entry) { 1124 RB_FOREACH(roa, roa_tree, &rs->roa_set) 1125 roa_insert(rt, roa); 1126 } 1127 } 1128 1129 void 1130 rtr_shutdown(void) 1131 { 1132 struct rtr_session *rs, *nrs; 1133 1134 TAILQ_FOREACH_SAFE(rs, &rtrs, entry, nrs) 1135 rtr_free(rs); 1136 } 1137 1138 void 1139 rtr_show(struct rtr_session *rs, pid_t pid) 1140 { 1141 struct ctl_show_rtr msg; 1142 struct ctl_timer ct; 1143 u_int i; 1144 time_t d; 1145 1146 memset(&msg, 0, sizeof(msg)); 1147 1148 /* descr, remote_addr, local_addr and remote_port set by parent */ 1149 msg.serial = rs->serial; 1150 msg.refresh = rs->refresh; 1151 msg.retry = rs->retry; 1152 msg.expire = rs->expire; 1153 msg.session_id = rs->session_id; 1154 msg.last_sent_error = rs->last_sent_error; 1155 msg.last_recv_error = rs->last_recv_error; 1156 strlcpy(msg.last_sent_msg, rs->last_sent_msg, 1157 sizeof(msg.last_sent_msg)); 1158 strlcpy(msg.last_recv_msg, rs->last_recv_msg, 1159 sizeof(msg.last_recv_msg)); 1160 1161 /* send back imsg */ 1162 rtr_imsg_compose(IMSG_CTL_SHOW_RTR, rs->id, pid, &msg, sizeof(msg)); 1163 1164 /* send back timer imsgs */ 1165 for (i = 1; i < Timer_Max; i++) { 1166 if (!timer_running(&rs->timers, i, &d)) 1167 continue; 1168 ct.type = i; 1169 ct.val = d; 1170 rtr_imsg_compose(IMSG_CTL_SHOW_TIMER, rs->id, pid, 1171 &ct, sizeof(ct)); 1172 } 1173 } 1174