Annotation of embedaddon/bird2/proto/rpki/packets.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD -- The Resource Public Key Infrastructure (RPKI) to Router Protocol
! 3: *
! 4: * (c) 2015 CZ.NIC
! 5: * (c) 2015 Pavel Tvrdik <pawel.tvrdik@gmail.com>
! 6: *
! 7: * This file was a part of RTRlib: http://rpki.realmv6.org/
! 8: *
! 9: * Can be freely distributed and used under the terms of the GNU GPL.
! 10: */
! 11:
! 12: #include <stdlib.h>
! 13: #include <string.h>
! 14: #include <stdio.h>
! 15:
! 16: #undef LOCAL_DEBUG
! 17:
! 18: #include "rpki.h"
! 19: #include "transport.h"
! 20: #include "packets.h"
! 21:
! 22: #define RPKI_ADD_FLAG 0b00000001
! 23:
! 24: enum rpki_transmit_type {
! 25: RPKI_RECV = 0,
! 26: RPKI_SEND = 1,
! 27: };
! 28:
! 29: enum pdu_error_type {
! 30: CORRUPT_DATA = 0,
! 31: INTERNAL_ERROR = 1,
! 32: NO_DATA_AVAIL = 2,
! 33: INVALID_REQUEST = 3,
! 34: UNSUPPORTED_PROTOCOL_VER = 4,
! 35: UNSUPPORTED_PDU_TYPE = 5,
! 36: WITHDRAWAL_OF_UNKNOWN_RECORD = 6,
! 37: DUPLICATE_ANNOUNCEMENT = 7,
! 38: PDU_TOO_BIG = 32
! 39: };
! 40:
! 41: static const char *str_pdu_error_type[] = {
! 42: [CORRUPT_DATA] = "Corrupt-Data",
! 43: [INTERNAL_ERROR] = "Internal-Error",
! 44: [NO_DATA_AVAIL] = "No-Data-Available",
! 45: [INVALID_REQUEST] = "Invalid-Request",
! 46: [UNSUPPORTED_PROTOCOL_VER] = "Unsupported-Protocol-Version",
! 47: [UNSUPPORTED_PDU_TYPE] = "Unsupported-PDU-Type",
! 48: [WITHDRAWAL_OF_UNKNOWN_RECORD]= "Withdrawal-Of-Unknown-Record",
! 49: [DUPLICATE_ANNOUNCEMENT] = "Duplicate-Announcement",
! 50: [PDU_TOO_BIG] = "PDU-Too-Big",
! 51: };
! 52:
! 53: enum pdu_type {
! 54: SERIAL_NOTIFY = 0,
! 55: SERIAL_QUERY = 1,
! 56: RESET_QUERY = 2,
! 57: CACHE_RESPONSE = 3,
! 58: IPV4_PREFIX = 4,
! 59: RESERVED = 5,
! 60: IPV6_PREFIX = 6,
! 61: END_OF_DATA = 7,
! 62: CACHE_RESET = 8,
! 63: ROUTER_KEY = 9,
! 64: ERROR = 10,
! 65: PDU_TYPE_MAX
! 66: };
! 67:
! 68: static const char *str_pdu_type_[] = {
! 69: [SERIAL_NOTIFY] = "Serial Notify",
! 70: [SERIAL_QUERY] = "Serial Query",
! 71: [RESET_QUERY] = "Reset Query",
! 72: [CACHE_RESPONSE] = "Cache Response",
! 73: [IPV4_PREFIX] = "IPv4 Prefix",
! 74: [RESERVED] = "Reserved",
! 75: [IPV6_PREFIX] = "IPv6 Prefix",
! 76: [END_OF_DATA] = "End of Data",
! 77: [CACHE_RESET] = "Cache Reset",
! 78: [ROUTER_KEY] = "Router Key",
! 79: [ERROR] = "Error"
! 80: };
! 81:
! 82: static const char *str_pdu_type(uint type) {
! 83: if (type < PDU_TYPE_MAX)
! 84: return str_pdu_type_[type];
! 85: else
! 86: return "Undefined packet type";
! 87: }
! 88:
! 89: /*
! 90: * 0 8 16 24 31
! 91: * .-------------------------------------------.
! 92: * | Protocol | PDU | |
! 93: * | Version | Type | reserved = zero |
! 94: * | 0 or 1 | 0 - 10 | |
! 95: * +-------------------------------------------+
! 96: * | |
! 97: * | Length >= 8 |
! 98: * | |
! 99: * `-------------------------------------------' */
! 100: struct pdu_header {
! 101: u8 ver;
! 102: u8 type;
! 103: u16 reserved;
! 104: u32 len;
! 105: } PACKED;
! 106:
! 107: struct pdu_cache_response {
! 108: u8 ver;
! 109: u8 type;
! 110: u16 session_id;
! 111: u32 len;
! 112: } PACKED;
! 113:
! 114: struct pdu_serial_notify {
! 115: u8 ver;
! 116: u8 type;
! 117: u16 session_id;
! 118: u32 len;
! 119: u32 serial_num;
! 120: } PACKED;
! 121:
! 122: struct pdu_serial_query {
! 123: u8 ver;
! 124: u8 type;
! 125: u16 session_id;
! 126: u32 len;
! 127: u32 serial_num;
! 128: } PACKED;
! 129:
! 130: struct pdu_ipv4 {
! 131: u8 ver;
! 132: u8 type;
! 133: u16 reserved;
! 134: u32 len;
! 135: u8 flags;
! 136: u8 prefix_len;
! 137: u8 max_prefix_len;
! 138: u8 zero;
! 139: ip4_addr prefix;
! 140: u32 asn;
! 141: } PACKED;
! 142:
! 143: struct pdu_ipv6 {
! 144: u8 ver;
! 145: u8 type;
! 146: u16 reserved;
! 147: u32 len;
! 148: u8 flags;
! 149: u8 prefix_len;
! 150: u8 max_prefix_len;
! 151: u8 zero;
! 152: ip6_addr prefix;
! 153: u32 asn;
! 154: } PACKED;
! 155:
! 156: /*
! 157: * 0 8 16 24 31
! 158: * .-------------------------------------------.
! 159: * | Protocol | PDU | |
! 160: * | Version | Type | Error Code |
! 161: * | 1 | 10 | |
! 162: * +-------------------------------------------+
! 163: * | |
! 164: * | Length |
! 165: * | |
! 166: * +-------------------------------------------+
! 167: * | |
! 168: * | Length of Encapsulated PDU |
! 169: * | |
! 170: * +-------------------------------------------+
! 171: * | |
! 172: * ~ Copy of Erroneous PDU ~
! 173: * | |
! 174: * +-------------------------------------------+
! 175: * | |
! 176: * | Length of Error Text |
! 177: * | |
! 178: * +-------------------------------------------+
! 179: * | |
! 180: * | Arbitrary Text |
! 181: * | of |
! 182: * ~ Error Diagnostic Message ~
! 183: * | |
! 184: * `-------------------------------------------' */
! 185: struct pdu_error {
! 186: u8 ver;
! 187: u8 type;
! 188: u16 error_code;
! 189: u32 len;
! 190: u32 len_enc_pdu; /* Length of Encapsulated PDU */
! 191: byte rest[]; /* Copy of Erroneous PDU
! 192: * Length of Error Text
! 193: * Error Diagnostic Message */
! 194: } PACKED;
! 195:
! 196: struct pdu_reset_query {
! 197: u8 ver;
! 198: u8 type;
! 199: u16 flags;
! 200: u32 len;
! 201: } PACKED;
! 202:
! 203: struct pdu_end_of_data_v0 {
! 204: u8 ver;
! 205: u8 type;
! 206: u16 session_id;
! 207: u32 len;
! 208: u32 serial_num;
! 209: } PACKED;
! 210:
! 211: struct pdu_end_of_data_v1 {
! 212: u8 ver;
! 213: u8 type;
! 214: u16 session_id;
! 215: u32 len;
! 216: u32 serial_num;
! 217: u32 refresh_interval;
! 218: u32 retry_interval;
! 219: u32 expire_interval;
! 220: } PACKED;
! 221:
! 222: static const size_t min_pdu_size[] = {
! 223: [SERIAL_NOTIFY] = sizeof(struct pdu_serial_notify),
! 224: [SERIAL_QUERY] = sizeof(struct pdu_serial_query),
! 225: [RESET_QUERY] = sizeof(struct pdu_reset_query),
! 226: [CACHE_RESPONSE] = sizeof(struct pdu_cache_response),
! 227: [IPV4_PREFIX] = sizeof(struct pdu_ipv4),
! 228: [RESERVED] = sizeof(struct pdu_header),
! 229: [IPV6_PREFIX] = sizeof(struct pdu_ipv6),
! 230: [END_OF_DATA] = sizeof(struct pdu_end_of_data_v0),
! 231: [CACHE_RESET] = sizeof(struct pdu_cache_response),
! 232: [ROUTER_KEY] = sizeof(struct pdu_header), /* FIXME */
! 233: [ERROR] = 16,
! 234: };
! 235:
! 236: static int rpki_send_error_pdu(struct rpki_cache *cache, const enum pdu_error_type error_code, const u32 err_pdu_len, const struct pdu_header *erroneous_pdu, const char *fmt, ...);
! 237:
! 238: static void
! 239: rpki_pdu_to_network_byte_order(struct pdu_header *pdu)
! 240: {
! 241: pdu->reserved = htons(pdu->reserved);
! 242: pdu->len = htonl(pdu->len);
! 243:
! 244: switch (pdu->type)
! 245: {
! 246: case SERIAL_QUERY:
! 247: {
! 248: /* Note that a session_id is converted using converting header->reserved */
! 249: struct pdu_serial_query *sq_pdu = (void *) pdu;
! 250: sq_pdu->serial_num = htonl(sq_pdu->serial_num);
! 251: break;
! 252: }
! 253:
! 254: case ERROR:
! 255: {
! 256: struct pdu_error *err = (void *) pdu;
! 257: u32 *err_text_len = (u32 *)(err->rest + err->len_enc_pdu);
! 258: *err_text_len = htonl(*err_text_len);
! 259: err->len_enc_pdu = htonl(err->len_enc_pdu);
! 260: break;
! 261: }
! 262:
! 263: case RESET_QUERY:
! 264: break;
! 265:
! 266: default:
! 267: bug("PDU type %s should not be sent by us", str_pdu_type(pdu->type));
! 268: }
! 269: }
! 270:
! 271: static void
! 272: rpki_pdu_to_host_byte_order(struct pdu_header *pdu)
! 273: {
! 274: /* The Router Key PDU has two one-byte fields instead of one two-bytes field. */
! 275: if (pdu->type != ROUTER_KEY)
! 276: pdu->reserved = ntohs(pdu->reserved);
! 277:
! 278: pdu->len = ntohl(pdu->len);
! 279:
! 280: switch (pdu->type)
! 281: {
! 282: case SERIAL_NOTIFY:
! 283: {
! 284: /* Note that a session_id is converted using converting header->reserved */
! 285: struct pdu_serial_notify *sn_pdu = (void *) pdu;
! 286: sn_pdu->serial_num = ntohl(sn_pdu->serial_num);
! 287: break;
! 288: }
! 289:
! 290: case END_OF_DATA:
! 291: {
! 292: /* Note that a session_id is converted using converting header->reserved */
! 293: struct pdu_end_of_data_v0 *eod0 = (void *) pdu;
! 294: eod0->serial_num = ntohl(eod0->serial_num); /* Same either for version 1 */
! 295:
! 296: if (pdu->ver == RPKI_VERSION_1)
! 297: {
! 298: struct pdu_end_of_data_v1 *eod1 = (void *) pdu;
! 299: eod1->expire_interval = ntohl(eod1->expire_interval);
! 300: eod1->refresh_interval = ntohl(eod1->refresh_interval);
! 301: eod1->retry_interval = ntohl(eod1->retry_interval);
! 302: }
! 303: break;
! 304: }
! 305:
! 306: case IPV4_PREFIX:
! 307: {
! 308: struct pdu_ipv4 *ipv4 = (void *) pdu;
! 309: ipv4->prefix = ip4_ntoh(ipv4->prefix);
! 310: ipv4->asn = ntohl(ipv4->asn);
! 311: break;
! 312: }
! 313:
! 314: case IPV6_PREFIX:
! 315: {
! 316: struct pdu_ipv6 *ipv6 = (void *) pdu;
! 317: ipv6->prefix = ip6_ntoh(ipv6->prefix);
! 318: ipv6->asn = ntohl(ipv6->asn);
! 319: break;
! 320: }
! 321:
! 322: case ERROR:
! 323: {
! 324: /* Note that a error_code is converted using converting header->reserved */
! 325: struct pdu_error *err = (void *) pdu;
! 326: err->len_enc_pdu = ntohl(err->len_enc_pdu);
! 327: u32 *err_text_len = (u32 *)(err->rest + err->len_enc_pdu);
! 328: *err_text_len = htonl(*err_text_len);
! 329: break;
! 330: }
! 331:
! 332: case ROUTER_KEY:
! 333: /* Router Key PDU is not supported yet */
! 334:
! 335: case SERIAL_QUERY:
! 336: case RESET_QUERY:
! 337: /* Serial/Reset Query are sent only in direction router to cache.
! 338: * We don't care here. */
! 339:
! 340: case CACHE_RESPONSE:
! 341: case CACHE_RESET:
! 342: /* Converted with pdu->reserved */
! 343: break;
! 344: }
! 345: }
! 346:
! 347: /**
! 348: * rpki_convert_pdu_back_to_network_byte_order - convert host-byte order PDU back to network-byte order
! 349: * @out: allocated memory for writing a converted PDU of size @in->len
! 350: * @in: host-byte order PDU
! 351: *
! 352: * Assumed: |A == ntoh(ntoh(A))|
! 353: */
! 354: static struct pdu_header *
! 355: rpki_pdu_back_to_network_byte_order(struct pdu_header *out, const struct pdu_header *in)
! 356: {
! 357: memcpy(out, in, in->len);
! 358: rpki_pdu_to_host_byte_order(out);
! 359: return out;
! 360: }
! 361:
! 362: static void
! 363: rpki_log_packet(struct rpki_cache *cache, const struct pdu_header *pdu, const enum rpki_transmit_type action)
! 364: {
! 365: if (!(cache->p->p.debug & D_PACKETS))
! 366: return;
! 367:
! 368: const char *str_type = str_pdu_type(pdu->type);
! 369: char detail[256];
! 370:
! 371: #define SAVE(fn) \
! 372: do { \
! 373: if (fn < 0) \
! 374: { \
! 375: bsnprintf(detail + sizeof(detail) - 16, 16, "... <too long>)"); \
! 376: goto detail_finished; \
! 377: } \
! 378: } while(0) \
! 379:
! 380: switch (pdu->type)
! 381: {
! 382: case SERIAL_NOTIFY:
! 383: case SERIAL_QUERY:
! 384: SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u, serial number: %u)", pdu->reserved, ((struct pdu_serial_notify *) pdu)->serial_num));
! 385: break;
! 386:
! 387: case END_OF_DATA:
! 388: {
! 389: const struct pdu_end_of_data_v1 *eod = (void *) pdu;
! 390: if (eod->ver == RPKI_VERSION_1)
! 391: SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u, serial number: %u, refresh: %us, retry: %us, expire: %us)", eod->session_id, eod->serial_num, eod->refresh_interval, eod->retry_interval, eod->expire_interval));
! 392: else
! 393: SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u, serial number: %u)", eod->session_id, eod->serial_num));
! 394: break;
! 395: }
! 396:
! 397: case CACHE_RESPONSE:
! 398: SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u)", pdu->reserved));
! 399: break;
! 400:
! 401: case IPV4_PREFIX:
! 402: {
! 403: const struct pdu_ipv4 *ipv4 = (void *) pdu;
! 404: SAVE(bsnprintf(detail, sizeof(detail), "(%I4/%u-%u AS%u)", ipv4->prefix, ipv4->prefix_len, ipv4->max_prefix_len, ipv4->asn));
! 405: break;
! 406: }
! 407:
! 408: case IPV6_PREFIX:
! 409: {
! 410: const struct pdu_ipv6 *ipv6 = (void *) pdu;
! 411: SAVE(bsnprintf(detail, sizeof(detail), "(%I6/%u-%u AS%u)", ipv6->prefix, ipv6->prefix_len, ipv6->max_prefix_len, ipv6->asn));
! 412: break;
! 413: }
! 414:
! 415: case ROUTER_KEY:
! 416: /* We don't support saving Router Key PDUs yet */
! 417: SAVE(bsnprintf(detail, sizeof(detail), "(ignored)"));
! 418: break;
! 419:
! 420: case ERROR:
! 421: {
! 422: const struct pdu_error *err = (void *) pdu;
! 423: SAVE(bsnprintf(detail, sizeof(detail), "(%s", str_pdu_error_type[err->error_code]));
! 424:
! 425: /* Optional description of error */
! 426: const u32 len_err_txt = *((u32 *) (err->rest + err->len_enc_pdu));
! 427: if (len_err_txt > 0)
! 428: {
! 429: size_t expected_len = err->len_enc_pdu + len_err_txt + 16;
! 430: if (expected_len == err->len)
! 431: {
! 432: char txt[len_err_txt + 1];
! 433: char *pdu_txt = (char *) err->rest + err->len_enc_pdu + 4;
! 434: bsnprintf(txt, sizeof(txt), "%s", pdu_txt); /* it's ensured that txt is ended with a null byte */
! 435: SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail), ": '%s'", txt));
! 436: }
! 437: else
! 438: {
! 439: SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail), ", malformed size"));
! 440: }
! 441: }
! 442:
! 443: /* Optional encapsulated erroneous packet */
! 444: if (err->len_enc_pdu)
! 445: {
! 446: SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail), ", %s packet:", str_pdu_type(((struct pdu_header *) err->rest)->type)));
! 447: if (err->rest + err->len_enc_pdu <= (byte *)err + err->len)
! 448: {
! 449: for (const byte *c = err->rest; c != err->rest + err->len_enc_pdu; c++)
! 450: SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail), " %02X", *c));
! 451: }
! 452: }
! 453:
! 454: SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail), ")"));
! 455: break;
! 456: }
! 457:
! 458: default:
! 459: *detail = '\0';
! 460: }
! 461: #undef SAVE
! 462:
! 463: detail_finished:
! 464:
! 465: if (action == RPKI_RECV)
! 466: {
! 467: CACHE_TRACE(D_PACKETS, cache, "Received %s packet %s", str_type, detail);
! 468: }
! 469: else
! 470: {
! 471: CACHE_TRACE(D_PACKETS, cache, "Sending %s packet %s", str_type, detail);
! 472: }
! 473:
! 474: #if defined(LOCAL_DEBUG) || defined(GLOBAL_DEBUG)
! 475: int seq = 0;
! 476: for(const byte *c = pdu; c != pdu + pdu->len; c++)
! 477: {
! 478: if ((seq % 4) == 0)
! 479: DBG("%2d: ", seq);
! 480:
! 481: DBG(" 0x%02X %-3u", *c, *c);
! 482:
! 483: if ((++seq % 4) == 0)
! 484: DBG("\n");
! 485: }
! 486: if ((seq % 4) != 0)
! 487: DBG("\n");
! 488: #endif
! 489: }
! 490:
! 491: static int
! 492: rpki_send_pdu(struct rpki_cache *cache, const void *pdu, const uint len)
! 493: {
! 494: struct rpki_proto *p = cache->p;
! 495: sock *sk = cache->tr_sock->sk;
! 496:
! 497: rpki_log_packet(cache, pdu, RPKI_SEND);
! 498:
! 499: if (sk->tbuf != sk->tpos)
! 500: {
! 501: RPKI_WARN(p, "Old packet overwritten in TX buffer");
! 502: }
! 503:
! 504: if (len > sk->tbsize)
! 505: {
! 506: RPKI_WARN(p, "%u bytes is too much for send", len);
! 507: ASSERT(0);
! 508: return RPKI_ERROR;
! 509: }
! 510:
! 511: memcpy(sk->tbuf, pdu, len);
! 512: rpki_pdu_to_network_byte_order((void *) sk->tbuf);
! 513:
! 514: if (!sk_send(sk, len))
! 515: {
! 516: DBG("Cannot send just the whole data. It will be sent using a call of tx_hook()");
! 517: }
! 518:
! 519: return RPKI_SUCCESS;
! 520: }
! 521:
! 522: /**
! 523: * rpki_check_receive_packet - make a basic validation of received RPKI PDU header
! 524: * @cache: cache connection instance
! 525: * @pdu: RPKI PDU in network byte order
! 526: *
! 527: * This function checks protocol version, PDU type, version and size. If all is all right then
! 528: * function returns |RPKI_SUCCESS| otherwise sends Error PDU and returns
! 529: * |RPKI_ERROR|.
! 530: */
! 531: static int
! 532: rpki_check_receive_packet(struct rpki_cache *cache, const struct pdu_header *pdu)
! 533: {
! 534: u32 pdu_len = ntohl(pdu->len);
! 535:
! 536: /*
! 537: * Minimal and maximal allowed PDU size is treated in rpki_rx_hook() function.
! 538: * @header.len corresponds to number of bytes of @pdu and
! 539: * it is in range from RPKI_PDU_HEADER_LEN to RPKI_PDU_MAX_LEN bytes.
! 540: */
! 541:
! 542: /* Do not handle error PDUs here, leave this task to rpki_handle_error_pdu() */
! 543: if (pdu->ver != cache->version && pdu->type != ERROR)
! 544: {
! 545: /* If this is the first PDU we have received */
! 546: if (cache->request_session_id)
! 547: {
! 548: if (pdu->type == SERIAL_NOTIFY)
! 549: {
! 550: /*
! 551: * The router MUST ignore any Serial Notify PDUs it might receive from
! 552: * the cache during this initial start-up period, regardless of the
! 553: * Protocol Version field in the Serial Notify PDU.
! 554: * (https://tools.ietf.org/html/draft-ietf-sidr-rpki-rtr-rfc6810-bis-07#section-7)
! 555: */
! 556: }
! 557: else if (!cache->last_update &&
! 558: (pdu->ver <= RPKI_MAX_VERSION) &&
! 559: (pdu->ver < cache->version))
! 560: {
! 561: CACHE_TRACE(D_EVENTS, cache, "Downgrade session to %s from %u to %u version", rpki_get_cache_ident(cache), cache->version, pdu->ver);
! 562: cache->version = pdu->ver;
! 563: }
! 564: else
! 565: {
! 566: /* If this is not the first PDU we have received, something is wrong with
! 567: * the server implementation -> Error */
! 568: rpki_send_error_pdu(cache, UNSUPPORTED_PROTOCOL_VER, pdu_len, pdu, "PDU with unsupported Protocol version received");
! 569: return RPKI_ERROR;
! 570: }
! 571: }
! 572: }
! 573:
! 574: if ((pdu->type >= PDU_TYPE_MAX) || (pdu->ver == RPKI_VERSION_0 && pdu->type == ROUTER_KEY))
! 575: {
! 576: rpki_send_error_pdu(cache, UNSUPPORTED_PDU_TYPE, pdu_len, pdu, "Unsupported PDU type %u received", pdu->type);
! 577: return RPKI_ERROR;
! 578: }
! 579:
! 580: if (pdu_len < min_pdu_size[pdu->type])
! 581: {
! 582: rpki_send_error_pdu(cache, CORRUPT_DATA, pdu_len, pdu, "Received %s packet with %d bytes, but expected at least %d bytes", str_pdu_type(pdu->type), pdu_len, min_pdu_size[pdu->type]);
! 583: return RPKI_ERROR;
! 584: }
! 585:
! 586: return RPKI_SUCCESS;
! 587: }
! 588:
! 589: static int
! 590: rpki_handle_error_pdu(struct rpki_cache *cache, const struct pdu_error *pdu)
! 591: {
! 592: switch (pdu->error_code)
! 593: {
! 594: case CORRUPT_DATA:
! 595: case INTERNAL_ERROR:
! 596: case INVALID_REQUEST:
! 597: case UNSUPPORTED_PDU_TYPE:
! 598: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 599: break;
! 600:
! 601: case NO_DATA_AVAIL:
! 602: rpki_cache_change_state(cache, RPKI_CS_ERROR_NO_DATA_AVAIL);
! 603: break;
! 604:
! 605: case UNSUPPORTED_PROTOCOL_VER:
! 606: CACHE_TRACE(D_PACKETS, cache, "Client uses unsupported protocol version");
! 607: if (pdu->ver <= RPKI_MAX_VERSION &&
! 608: pdu->ver < cache->version)
! 609: {
! 610: CACHE_TRACE(D_EVENTS, cache, "Downgrading from protocol version %d to version %d", cache->version, pdu->ver);
! 611: cache->version = pdu->ver;
! 612: rpki_cache_change_state(cache, RPKI_CS_FAST_RECONNECT);
! 613: }
! 614: else
! 615: {
! 616: CACHE_TRACE(D_PACKETS, cache, "Got UNSUPPORTED_PROTOCOL_VER error PDU with invalid values, " \
! 617: "current version: %d, PDU version: %d", cache->version, pdu->ver);
! 618: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 619: }
! 620: break;
! 621:
! 622: default:
! 623: CACHE_TRACE(D_PACKETS, cache, "Error unknown, server sent unsupported error code %u", pdu->error_code);
! 624: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 625: break;
! 626: }
! 627:
! 628: return RPKI_SUCCESS;
! 629: }
! 630:
! 631: static void
! 632: rpki_handle_serial_notify_pdu(struct rpki_cache *cache, const struct pdu_serial_notify *pdu)
! 633: {
! 634: /* The router MUST ignore any Serial Notify PDUs it might receive from
! 635: * the cache during this initial start-up period, regardless of the
! 636: * Protocol Version field in the Serial Notify PDU.
! 637: * (https://tools.ietf.org/html/draft-ietf-sidr-rpki-rtr-rfc6810-bis-07#section-7)
! 638: */
! 639: if (cache->request_session_id)
! 640: {
! 641: CACHE_TRACE(D_PACKETS, cache, "Ignore a Serial Notify packet during initial start-up period");
! 642: return;
! 643: }
! 644:
! 645: /* XXX Serial number should be compared using method RFC 1982 (3.2) */
! 646: if (cache->serial_num != pdu->serial_num)
! 647: rpki_cache_change_state(cache, RPKI_CS_SYNC_START);
! 648: }
! 649:
! 650: static int
! 651: rpki_handle_cache_response_pdu(struct rpki_cache *cache, const struct pdu_cache_response *pdu)
! 652: {
! 653: if (cache->request_session_id)
! 654: {
! 655: if (cache->last_update)
! 656: {
! 657: /*
! 658: * This isn't the first sync and we already received records. This point
! 659: * is after Reset Query and before importing new records from cache
! 660: * server. We need to load new ones and kick out missing ones. So start
! 661: * a refresh cycle.
! 662: */
! 663: if (cache->p->roa4_channel)
! 664: rt_refresh_begin(cache->p->roa4_channel->table, cache->p->roa4_channel);
! 665: if (cache->p->roa6_channel)
! 666: rt_refresh_begin(cache->p->roa6_channel->table, cache->p->roa6_channel);
! 667:
! 668: cache->p->refresh_channels = 1;
! 669: }
! 670: cache->session_id = pdu->session_id;
! 671: cache->request_session_id = 0;
! 672: }
! 673: else
! 674: {
! 675: if (cache->session_id != pdu->session_id)
! 676: {
! 677: byte tmp[pdu->len];
! 678: const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu);
! 679: rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Wrong session_id %u in Cache Response PDU", pdu->session_id);
! 680: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 681: return RPKI_ERROR;
! 682: }
! 683: }
! 684:
! 685: rpki_cache_change_state(cache, RPKI_CS_SYNC_RUNNING);
! 686: return RPKI_SUCCESS;
! 687: }
! 688:
! 689: /**
! 690: * rpki_prefix_pdu_2_net_addr - convert IPv4/IPv6 Prefix PDU into net_addr_union
! 691: * @pdu: host byte order IPv4/IPv6 Prefix PDU
! 692: * @n: allocated net_addr_union for save ROA
! 693: *
! 694: * This function reads ROA data from IPv4/IPv6 Prefix PDU and
! 695: * write them into net_addr_roa4 or net_addr_roa6 data structure.
! 696: */
! 697: static net_addr_union *
! 698: rpki_prefix_pdu_2_net_addr(const struct pdu_header *pdu, net_addr_union *n)
! 699: {
! 700: /*
! 701: * Note that sizeof(net_addr_roa6) > sizeof(net_addr)
! 702: * and thence we must use net_addr_union and not only net_addr
! 703: */
! 704:
! 705: if (pdu->type == IPV4_PREFIX)
! 706: {
! 707: const struct pdu_ipv4 *ipv4 = (void *) pdu;
! 708: n->roa4.type = NET_ROA4;
! 709: n->roa4.length = sizeof(net_addr_roa4);
! 710: n->roa4.prefix = ipv4->prefix;
! 711: n->roa4.asn = ipv4->asn;
! 712: n->roa4.pxlen = ipv4->prefix_len;
! 713: n->roa4.max_pxlen = ipv4->max_prefix_len;
! 714: }
! 715: else
! 716: {
! 717: const struct pdu_ipv6 *ipv6 = (void *) pdu;
! 718: n->roa6.type = NET_ROA6;
! 719: n->roa6.length = sizeof(net_addr_roa6);
! 720: n->roa6.prefix = ipv6->prefix;
! 721: n->roa6.asn = ipv6->asn;
! 722: n->roa6.pxlen = ipv6->prefix_len;
! 723: n->roa6.max_pxlen = ipv6->max_prefix_len;
! 724: }
! 725:
! 726: return n;
! 727: }
! 728:
! 729: static int
! 730: rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu)
! 731: {
! 732: const enum pdu_type type = pdu->type;
! 733: ASSERT(type == IPV4_PREFIX || type == IPV6_PREFIX);
! 734:
! 735: net_addr_union addr = {};
! 736: rpki_prefix_pdu_2_net_addr(pdu, &addr);
! 737:
! 738: struct channel *channel = NULL;
! 739:
! 740: if (type == IPV4_PREFIX)
! 741: channel = cache->p->roa4_channel;
! 742: if (type == IPV6_PREFIX)
! 743: channel = cache->p->roa6_channel;
! 744:
! 745: if (!channel)
! 746: {
! 747: CACHE_TRACE(D_ROUTES, cache, "Skip %N, missing %s channel", &addr, (type == IPV4_PREFIX ? "roa4" : "roa6"), addr);
! 748: return RPKI_ERROR;
! 749: }
! 750:
! 751: cache->last_rx_prefix = current_time();
! 752:
! 753: /* A place for 'flags' is same for both data structures pdu_ipv4 or pdu_ipv6 */
! 754: struct pdu_ipv4 *pfx = (void *) pdu;
! 755: if (pfx->flags & RPKI_ADD_FLAG)
! 756: rpki_table_add_roa(cache, channel, &addr);
! 757: else
! 758: rpki_table_remove_roa(cache, channel, &addr);
! 759:
! 760: return RPKI_SUCCESS;
! 761: }
! 762:
! 763: static uint
! 764: rpki_check_interval(struct rpki_cache *cache, const char *(check_fn)(uint), uint interval)
! 765: {
! 766: if (check_fn(interval))
! 767: {
! 768: RPKI_WARN(cache->p, "%s, received %u seconds", check_fn(interval), interval);
! 769: return 0;
! 770: }
! 771: return 1;
! 772: }
! 773:
! 774: static void
! 775: rpki_handle_end_of_data_pdu(struct rpki_cache *cache, const struct pdu_end_of_data_v1 *pdu)
! 776: {
! 777: const struct rpki_config *cf = (void *) cache->p->p.cf;
! 778:
! 779: if (pdu->session_id != cache->session_id)
! 780: {
! 781: byte tmp[pdu->len];
! 782: const struct pdu_header *hton_pdu = rpki_pdu_back_to_network_byte_order((void *) tmp, (const void *) pdu);
! 783: rpki_send_error_pdu(cache, CORRUPT_DATA, pdu->len, hton_pdu, "Received Session ID %u, but expected %u", pdu->session_id, cache->session_id);
! 784: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 785: return;
! 786: }
! 787:
! 788: if (pdu->ver == RPKI_VERSION_1)
! 789: {
! 790: if (!cf->keep_refresh_interval && rpki_check_interval(cache, rpki_check_refresh_interval, pdu->refresh_interval))
! 791: cache->refresh_interval = pdu->refresh_interval;
! 792:
! 793: if (!cf->keep_retry_interval && rpki_check_interval(cache, rpki_check_retry_interval, pdu->retry_interval))
! 794: cache->retry_interval = pdu->retry_interval;
! 795:
! 796: if (!cf->keep_expire_interval && rpki_check_interval(cache, rpki_check_expire_interval, pdu->expire_interval))
! 797: cache->expire_interval = pdu->expire_interval;
! 798:
! 799: CACHE_TRACE(D_EVENTS, cache, "New interval values: "
! 800: "refresh: %s%us, "
! 801: "retry: %s%us, "
! 802: "expire: %s%us",
! 803: (cf->keep_refresh_interval ? "keeps " : ""), cache->refresh_interval,
! 804: (cf->keep_retry_interval ? "keeps " : ""), cache->retry_interval,
! 805: (cf->keep_expire_interval ? "keeps " : ""), cache->expire_interval);
! 806: }
! 807:
! 808: if (cache->p->refresh_channels)
! 809: {
! 810: cache->p->refresh_channels = 0;
! 811: if (cache->p->roa4_channel)
! 812: rt_refresh_end(cache->p->roa4_channel->table, cache->p->roa4_channel);
! 813: if (cache->p->roa6_channel)
! 814: rt_refresh_end(cache->p->roa6_channel->table, cache->p->roa6_channel);
! 815: }
! 816:
! 817: cache->last_update = current_time();
! 818: cache->serial_num = pdu->serial_num;
! 819: rpki_cache_change_state(cache, RPKI_CS_ESTABLISHED);
! 820: }
! 821:
! 822: /**
! 823: * rpki_rx_packet - process a received RPKI PDU
! 824: * @cache: RPKI connection instance
! 825: * @pdu: a RPKI PDU in network byte order
! 826: */
! 827: static void
! 828: rpki_rx_packet(struct rpki_cache *cache, struct pdu_header *pdu)
! 829: {
! 830: struct rpki_proto *p = cache->p;
! 831:
! 832: if (rpki_check_receive_packet(cache, pdu) == RPKI_ERROR)
! 833: {
! 834: rpki_cache_change_state(cache, RPKI_CS_ERROR_FATAL);
! 835: return;
! 836: }
! 837:
! 838: rpki_pdu_to_host_byte_order(pdu);
! 839: rpki_log_packet(cache, pdu, RPKI_RECV);
! 840:
! 841: switch (pdu->type)
! 842: {
! 843: case RESET_QUERY:
! 844: case SERIAL_QUERY:
! 845: RPKI_WARN(p, "Received a %s packet that is destined for cache server", str_pdu_type(pdu->type));
! 846: break;
! 847:
! 848: case SERIAL_NOTIFY:
! 849: /* This is a signal to synchronize with the cache server just now */
! 850: rpki_handle_serial_notify_pdu(cache, (void *) pdu);
! 851: break;
! 852:
! 853: case CACHE_RESPONSE:
! 854: rpki_handle_cache_response_pdu(cache, (void *) pdu);
! 855: break;
! 856:
! 857: case IPV4_PREFIX:
! 858: case IPV6_PREFIX:
! 859: rpki_handle_prefix_pdu(cache, pdu);
! 860: break;
! 861:
! 862: case END_OF_DATA:
! 863: rpki_handle_end_of_data_pdu(cache, (void *) pdu);
! 864: break;
! 865:
! 866: case CACHE_RESET:
! 867: /* Cache cannot provide an incremental update. */
! 868: rpki_cache_change_state(cache, RPKI_CS_NO_INCR_UPDATE_AVAIL);
! 869: break;
! 870:
! 871: case ERROR:
! 872: rpki_handle_error_pdu(cache, (void *) pdu);
! 873: break;
! 874:
! 875: case ROUTER_KEY:
! 876: /* TODO: Implement Router Key PDU handling */
! 877: break;
! 878:
! 879: default:
! 880: CACHE_TRACE(D_PACKETS, cache, "Received unsupported type (%u)", pdu->type);
! 881: };
! 882: }
! 883:
! 884: int
! 885: rpki_rx_hook(struct birdsock *sk, uint size)
! 886: {
! 887: struct rpki_cache *cache = sk->data;
! 888: struct rpki_proto *p = cache->p;
! 889:
! 890: byte *pkt_start = sk->rbuf;
! 891: byte *end = pkt_start + size;
! 892:
! 893: DBG("rx hook got %u bytes \n", size);
! 894:
! 895: while (end >= pkt_start + RPKI_PDU_HEADER_LEN)
! 896: {
! 897: struct pdu_header *pdu = (void *) pkt_start;
! 898: u32 pdu_size = ntohl(pdu->len);
! 899:
! 900: if (pdu_size < RPKI_PDU_HEADER_LEN || pdu_size > RPKI_PDU_MAX_LEN)
! 901: {
! 902: RPKI_WARN(p, "Received invalid packet length %u, purge the whole receiving buffer", pdu_size);
! 903: return 1; /* Purge recv buffer */
! 904: }
! 905:
! 906: if (end < pkt_start + pdu_size)
! 907: break;
! 908:
! 909: rpki_rx_packet(cache, pdu);
! 910:
! 911: /* It is possible that bird socket was freed/closed */
! 912: if (p->p.proto_state == PS_DOWN || sk != cache->tr_sock->sk)
! 913: return 0;
! 914:
! 915: pkt_start += pdu_size;
! 916: }
! 917:
! 918: if (pkt_start != sk->rbuf)
! 919: {
! 920: CACHE_DBG(cache, "Move %u bytes of a memory at the start of buffer", end - pkt_start);
! 921: memmove(sk->rbuf, pkt_start, end - pkt_start);
! 922: sk->rpos = sk->rbuf + (end - pkt_start);
! 923: }
! 924:
! 925: return 0; /* Not purge sk->rbuf */
! 926: }
! 927:
! 928: void
! 929: rpki_err_hook(struct birdsock *sk, int error_num)
! 930: {
! 931: struct rpki_cache *cache = sk->data;
! 932:
! 933: if (error_num)
! 934: {
! 935: /* sk->err may contains a SSH error description */
! 936: if (sk->err)
! 937: CACHE_TRACE(D_EVENTS, cache, "Lost connection: %s", sk->err);
! 938: else
! 939: CACHE_TRACE(D_EVENTS, cache, "Lost connection: %M", error_num);
! 940: }
! 941: else
! 942: {
! 943: CACHE_TRACE(D_EVENTS, cache, "The other side closed a connection");
! 944: }
! 945:
! 946:
! 947: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT);
! 948: }
! 949:
! 950: static int
! 951: rpki_fire_tx(struct rpki_cache *cache)
! 952: {
! 953: sock *sk = cache->tr_sock->sk;
! 954:
! 955: uint bytes_to_send = sk->tpos - sk->tbuf;
! 956: DBG("Sending %u bytes", bytes_to_send);
! 957: return sk_send(sk, bytes_to_send);
! 958: }
! 959:
! 960: void
! 961: rpki_tx_hook(sock *sk)
! 962: {
! 963: struct rpki_cache *cache = sk->data;
! 964:
! 965: while (rpki_fire_tx(cache) > 0)
! 966: ;
! 967: }
! 968:
! 969: void
! 970: rpki_connected_hook(sock *sk)
! 971: {
! 972: struct rpki_cache *cache = sk->data;
! 973:
! 974: CACHE_TRACE(D_EVENTS, cache, "Connected");
! 975: proto_notify_state(&cache->p->p, PS_UP);
! 976:
! 977: sk->rx_hook = rpki_rx_hook;
! 978: sk->tx_hook = rpki_tx_hook;
! 979:
! 980: rpki_cache_change_state(cache, RPKI_CS_SYNC_START);
! 981: }
! 982:
! 983: /**
! 984: * rpki_send_error_pdu - send RPKI Error PDU
! 985: * @cache: RPKI connection instance
! 986: * @error_code: PDU Error type
! 987: * @err_pdu_len: length of @erroneous_pdu
! 988: * @erroneous_pdu: optional network byte-order PDU that invokes Error by us or NULL
! 989: * @fmt: optional description text of error or NULL
! 990: * @args: optional arguments for @fmt
! 991: *
! 992: * This function prepares Error PDU and sends it to a cache server.
! 993: */
! 994: static int
! 995: rpki_send_error_pdu(struct rpki_cache *cache, const enum pdu_error_type error_code, const u32 err_pdu_len, const struct pdu_header *erroneous_pdu, const char *fmt, ...)
! 996: {
! 997: va_list args;
! 998: char msg[128];
! 999:
! 1000: /* Size including the terminating null byte ('\0') */
! 1001: int msg_len = 0;
! 1002:
! 1003: /* Don't send errors for erroneous error PDUs */
! 1004: if (err_pdu_len >= 2)
! 1005: {
! 1006: if (erroneous_pdu->type == ERROR)
! 1007: return RPKI_SUCCESS;
! 1008: }
! 1009:
! 1010: if (fmt)
! 1011: {
! 1012: va_start(args, fmt);
! 1013: msg_len = bvsnprintf(msg, sizeof(msg), fmt, args) + 1;
! 1014: }
! 1015:
! 1016: u32 pdu_size = 16 + err_pdu_len + msg_len;
! 1017: byte pdu[pdu_size];
! 1018: memset(pdu, 0, sizeof(pdu));
! 1019:
! 1020: struct pdu_error *e = (void *) pdu;
! 1021: e->ver = cache->version;
! 1022: e->type = ERROR;
! 1023: e->error_code = error_code;
! 1024: e->len = pdu_size;
! 1025:
! 1026: e->len_enc_pdu = err_pdu_len;
! 1027: if (err_pdu_len > 0)
! 1028: memcpy(e->rest, erroneous_pdu, err_pdu_len);
! 1029:
! 1030: *((u32 *)(e->rest + err_pdu_len)) = msg_len;
! 1031: if (msg_len > 0)
! 1032: memcpy(e->rest + err_pdu_len + 4, msg, msg_len);
! 1033:
! 1034: return rpki_send_pdu(cache, pdu, pdu_size);
! 1035: }
! 1036:
! 1037: int
! 1038: rpki_send_serial_query(struct rpki_cache *cache)
! 1039: {
! 1040: struct pdu_serial_query pdu = {
! 1041: .ver = cache->version,
! 1042: .type = SERIAL_QUERY,
! 1043: .session_id = cache->session_id,
! 1044: .len = sizeof(pdu),
! 1045: .serial_num = cache->serial_num
! 1046: };
! 1047:
! 1048: if (rpki_send_pdu(cache, &pdu, sizeof(pdu)) != RPKI_SUCCESS)
! 1049: {
! 1050: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT);
! 1051: return RPKI_ERROR;
! 1052: }
! 1053:
! 1054: return RPKI_SUCCESS;
! 1055: }
! 1056:
! 1057: int
! 1058: rpki_send_reset_query(struct rpki_cache *cache)
! 1059: {
! 1060: struct pdu_reset_query pdu = {
! 1061: .ver = cache->version,
! 1062: .type = RESET_QUERY,
! 1063: .len = sizeof(pdu),
! 1064: };
! 1065:
! 1066: if (rpki_send_pdu(cache, &pdu, sizeof(pdu)) != RPKI_SUCCESS)
! 1067: {
! 1068: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT);
! 1069: return RPKI_ERROR;
! 1070: }
! 1071:
! 1072: return RPKI_SUCCESS;
! 1073: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>