Return to rpki.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / rpki |
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: * Using RTRlib: http://rpki.realmv6.org/ ! 8: * ! 9: * Can be freely distributed and used under the terms of the GNU GPL. ! 10: */ ! 11: ! 12: /** ! 13: * DOC: RPKI To Router (RPKI-RTR) ! 14: * ! 15: * The RPKI-RTR protocol is implemented in several files: |rpki.c| containing ! 16: * the routes handling, protocol logic, timer events, cache connection, ! 17: * reconfiguration, configuration and protocol glue with BIRD core, |packets.c| ! 18: * containing the RPKI packets handling and finally all transports files: ! 19: * |transport.c|, |tcp_transport.c| and |ssh_transport.c|. ! 20: * ! 21: * The |transport.c| is a middle layer and interface for each specific ! 22: * transport. Transport is a way how to wrap a communication with a cache ! 23: * server. There is supported an unprotected TCP transport and an encrypted ! 24: * SSHv2 transport. The SSH transport requires LibSSH library. LibSSH is ! 25: * loading dynamically using |dlopen()| function. SSH support is integrated in ! 26: * |sysdep/unix/io.c|. Each transport must implement an initialization ! 27: * function, an open function and a socket identification function. That's all. ! 28: * ! 29: * This implementation is based on the RTRlib (http://rpki.realmv6.org/). The ! 30: * BIRD takes over files |packets.c|, |rtr.c| (inside |rpki.c|), |transport.c|, ! 31: * |tcp_transport.c| and |ssh_transport.c| from RTRlib. ! 32: * ! 33: * A RPKI-RTR connection is described by a structure &rpki_cache. The main ! 34: * logic is located in |rpki_cache_change_state()| function. There is a state ! 35: * machine. The standard starting state flow looks like |Down| ~> |Connecting| ! 36: * ~> |Sync-Start| ~> |Sync-Running| ~> |Established| and then the last three ! 37: * states are periodically repeated. ! 38: * ! 39: * |Connecting| state establishes the transport connection. The state from a ! 40: * call |rpki_cache_change_state(CONNECTING)| to a call |rpki_connected_hook()| ! 41: * ! 42: * |Sync-Start| state starts with sending |Reset Query| or |Serial Query| and ! 43: * then waits for |Cache Response|. The state from |rpki_connected_hook()| to ! 44: * |rpki_handle_cache_response_pdu()| ! 45: * ! 46: * During |Sync-Running| BIRD receives data with IPv4/IPv6 Prefixes from cache ! 47: * server. The state starts from |rpki_handle_cache_response_pdu()| and ends ! 48: * in |rpki_handle_end_of_data_pdu()|. ! 49: * ! 50: * |Established| state means that BIRD has synced all data with cache server. ! 51: * Schedules a refresh timer event that invokes |Sync-Start|. Schedules Expire ! 52: * timer event and stops a Retry timer event. ! 53: * ! 54: * |Transport Error| state means that we have some troubles with a network ! 55: * connection. We cannot connect to a cache server or we wait too long for some ! 56: * expected PDU for received - |Cache Response| or |End of Data|. It closes ! 57: * current connection and schedules a Retry timer event. ! 58: * ! 59: * |Fatal Protocol Error| is occurred e.g. by received a bad Session ID. We ! 60: * restart a protocol, so all ROAs are flushed immediately. ! 61: * ! 62: * The RPKI-RTR protocol (RFC 6810 bis) defines configurable refresh, retry and ! 63: * expire intervals. For maintaining a connection are used timer events that ! 64: * are scheduled by |rpki_schedule_next_refresh()|, ! 65: * |rpki_schedule_next_retry()| and |rpki_schedule_next_expire()| functions. ! 66: * ! 67: * A Refresh timer event performs a sync of |Established| connection. So it ! 68: * shifts state to |Sync-Start|. If at the beginning of second call of a ! 69: * refresh event is connection in |Sync-Start| state then we didn't receive a ! 70: * |Cache Response| from a cache server and we invoke |Transport Error| state. ! 71: * ! 72: * A Retry timer event attempts to connect cache server. It is activated after ! 73: * |Transport Error| state and terminated by reaching |Established| state. ! 74: * If cache connection is still connecting to the cache server at the beginning ! 75: * of an event call then the Retry timer event invokes |Transport Error| state. ! 76: * ! 77: * An Expire timer event checks expiration of ROAs. If a last successful sync ! 78: * was more ago than the expire interval then the Expire timer event invokes a ! 79: * protocol restart thereby removes all ROAs learned from that cache server and ! 80: * continue trying to connect to cache server. The Expire event is activated ! 81: * by initial successful loading of ROAs, receiving End of Data PDU. ! 82: * ! 83: * A reconfiguration of cache connection works well without restarting when we ! 84: * change only intervals values. ! 85: * ! 86: * Supported standards: ! 87: * - RFC 6810 - main RPKI-RTR standard ! 88: * - RFC 6810 bis - an explicit timing parameters and protocol version number negotiation ! 89: */ ! 90: ! 91: #include <stdlib.h> ! 92: #include <netdb.h> ! 93: ! 94: #undef LOCAL_DEBUG ! 95: ! 96: #include "rpki.h" ! 97: #include "lib/string.h" ! 98: #include "nest/cli.h" ! 99: ! 100: /* Return values for reconfiguration functions */ ! 101: #define NEED_RESTART 0 ! 102: #define SUCCESSFUL_RECONF 1 ! 103: ! 104: static int rpki_open_connection(struct rpki_cache *cache); ! 105: static void rpki_close_connection(struct rpki_cache *cache); ! 106: static void rpki_schedule_next_refresh(struct rpki_cache *cache); ! 107: static void rpki_schedule_next_retry(struct rpki_cache *cache); ! 108: static void rpki_schedule_next_expire_check(struct rpki_cache *cache); ! 109: static void rpki_stop_refresh_timer_event(struct rpki_cache *cache); ! 110: static void rpki_stop_retry_timer_event(struct rpki_cache *cache); ! 111: static void rpki_stop_expire_timer_event(struct rpki_cache *cache); ! 112: ! 113: ! 114: /* ! 115: * Routes handling ! 116: */ ! 117: ! 118: void ! 119: rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr) ! 120: { ! 121: struct rpki_proto *p = cache->p; ! 122: ! 123: rta a0 = { ! 124: .src = p->p.main_source, ! 125: .source = RTS_RPKI, ! 126: .scope = SCOPE_UNIVERSE, ! 127: .dest = RTD_NONE, ! 128: }; ! 129: ! 130: rta *a = rta_lookup(&a0); ! 131: rte *e = rte_get_temp(a); ! 132: ! 133: e->pflags = 0; ! 134: ! 135: rte_update2(channel, &pfxr->n, e, a0.src); ! 136: } ! 137: ! 138: void ! 139: rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr) ! 140: { ! 141: struct rpki_proto *p = cache->p; ! 142: rte_update2(channel, &pfxr->n, NULL, p->p.main_source); ! 143: } ! 144: ! 145: ! 146: /* ! 147: * RPKI Protocol Logic ! 148: */ ! 149: ! 150: static const char *str_cache_states[] = { ! 151: [RPKI_CS_CONNECTING] = "Connecting", ! 152: [RPKI_CS_ESTABLISHED] = "Established", ! 153: [RPKI_CS_RESET] = "Reseting", ! 154: [RPKI_CS_SYNC_START] = "Sync-Start", ! 155: [RPKI_CS_SYNC_RUNNING] = "Sync-Running", ! 156: [RPKI_CS_FAST_RECONNECT] = "Fast-Reconnect", ! 157: [RPKI_CS_NO_INCR_UPDATE_AVAIL]= "No-Increment-Update-Available", ! 158: [RPKI_CS_ERROR_NO_DATA_AVAIL] = "Cache-Error-No-Data-Available", ! 159: [RPKI_CS_ERROR_FATAL] = "Fatal-Protocol-Error", ! 160: [RPKI_CS_ERROR_TRANSPORT] = "Transport-Error", ! 161: [RPKI_CS_SHUTDOWN] = "Down" ! 162: }; ! 163: ! 164: /** ! 165: * rpki_cache_state_to_str - give a text representation of cache state ! 166: * @state: A cache state ! 167: * ! 168: * The function converts logic cache state into string. ! 169: */ ! 170: const char * ! 171: rpki_cache_state_to_str(enum rpki_cache_state state) ! 172: { ! 173: return str_cache_states[state]; ! 174: } ! 175: ! 176: /** ! 177: * rpki_start_cache - connect to a cache server ! 178: * @cache: RPKI connection instance ! 179: * ! 180: * This function is a high level method to kick up a connection to a cache server. ! 181: */ ! 182: static void ! 183: rpki_start_cache(struct rpki_cache *cache) ! 184: { ! 185: rpki_cache_change_state(cache, RPKI_CS_CONNECTING); ! 186: } ! 187: ! 188: /** ! 189: * rpki_force_restart_proto - force shutdown and start protocol again ! 190: * @p: RPKI protocol instance ! 191: * ! 192: * This function calls shutdown and frees all protocol resources as well. ! 193: * After calling this function should be no operations with protocol data, ! 194: * they could be freed already. ! 195: */ ! 196: static void ! 197: rpki_force_restart_proto(struct rpki_proto *p) ! 198: { ! 199: if (p->cache) ! 200: { ! 201: CACHE_DBG(p->cache, "Connection object destroying"); ! 202: } ! 203: ! 204: /* Sign as freed */ ! 205: p->cache = NULL; ! 206: ! 207: proto_notify_state(&p->p, PS_DOWN); ! 208: } ! 209: ! 210: /** ! 211: * rpki_cache_change_state - check and change cache state ! 212: * @cache: RPKI cache instance ! 213: * @new_state: suggested new state ! 214: * ! 215: * This function makes transitions between internal states. ! 216: * It represents the core of logic management of RPKI protocol. ! 217: * Cannot transit into the same state as cache is in already. ! 218: */ ! 219: void ! 220: rpki_cache_change_state(struct rpki_cache *cache, const enum rpki_cache_state new_state) ! 221: { ! 222: const enum rpki_cache_state old_state = cache->state; ! 223: ! 224: if (old_state == new_state) ! 225: return; ! 226: ! 227: cache->state = new_state; ! 228: CACHE_TRACE(D_EVENTS, cache, "Changing from %s to %s state", rpki_cache_state_to_str(old_state), rpki_cache_state_to_str(new_state)); ! 229: ! 230: switch (new_state) ! 231: { ! 232: case RPKI_CS_CONNECTING: ! 233: { ! 234: sock *sk = cache->tr_sock->sk; ! 235: ! 236: if (sk == NULL || sk->fd < 0) ! 237: rpki_open_connection(cache); ! 238: else ! 239: rpki_cache_change_state(cache, RPKI_CS_SYNC_START); ! 240: ! 241: rpki_schedule_next_retry(cache); ! 242: break; ! 243: } ! 244: ! 245: case RPKI_CS_ESTABLISHED: ! 246: rpki_schedule_next_refresh(cache); ! 247: rpki_schedule_next_expire_check(cache); ! 248: rpki_stop_retry_timer_event(cache); ! 249: break; ! 250: ! 251: case RPKI_CS_RESET: ! 252: /* Resetting cache connection. */ ! 253: cache->request_session_id = 1; ! 254: cache->serial_num = 0; ! 255: rpki_cache_change_state(cache, RPKI_CS_SYNC_START); ! 256: break; ! 257: ! 258: case RPKI_CS_SYNC_START: ! 259: /* Requesting for receive ROAs from a cache server. */ ! 260: if (cache->request_session_id) ! 261: { ! 262: /* Send request for Session ID */ ! 263: if (rpki_send_reset_query(cache) != RPKI_SUCCESS) ! 264: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT); ! 265: } ! 266: else ! 267: { ! 268: /* We have already a session_id. So send a Serial Query and start an incremental sync */ ! 269: if (rpki_send_serial_query(cache) != RPKI_SUCCESS) ! 270: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT); ! 271: } ! 272: break; ! 273: ! 274: case RPKI_CS_SYNC_RUNNING: ! 275: /* The state between Cache Response and End of Data. Only waiting for ! 276: * receiving all IP Prefix PDUs and finally a End of Data PDU. */ ! 277: break; ! 278: ! 279: case RPKI_CS_NO_INCR_UPDATE_AVAIL: ! 280: /* Server was unable to answer the last Serial Query and sent Cache Reset. */ ! 281: rpki_cache_change_state(cache, RPKI_CS_RESET); ! 282: break; ! 283: ! 284: case RPKI_CS_ERROR_NO_DATA_AVAIL: ! 285: /* No validation records are available on the cache server. */ ! 286: rpki_cache_change_state(cache, RPKI_CS_RESET); ! 287: break; ! 288: ! 289: case RPKI_CS_ERROR_FATAL: ! 290: /* Fatal protocol error occurred. */ ! 291: rpki_force_restart_proto(cache->p); ! 292: break; ! 293: ! 294: case RPKI_CS_ERROR_TRANSPORT: ! 295: /* Error on the transport socket occurred. */ ! 296: rpki_close_connection(cache); ! 297: rpki_schedule_next_retry(cache); ! 298: rpki_stop_refresh_timer_event(cache); ! 299: break; ! 300: ! 301: case RPKI_CS_FAST_RECONNECT: ! 302: /* Reconnect without any waiting period */ ! 303: rpki_close_connection(cache); ! 304: rpki_cache_change_state(cache, RPKI_CS_CONNECTING); ! 305: break; ! 306: ! 307: case RPKI_CS_SHUTDOWN: ! 308: bug("This isn't never really called."); ! 309: break; ! 310: }; ! 311: } ! 312: ! 313: ! 314: /* ! 315: * RPKI Timer Events ! 316: */ ! 317: ! 318: static void ! 319: rpki_schedule_next_refresh(struct rpki_cache *cache) ! 320: { ! 321: btime t = cache->refresh_interval S; ! 322: ! 323: CACHE_DBG(cache, "after %t s", t); ! 324: tm_start(cache->refresh_timer, t); ! 325: } ! 326: ! 327: static void ! 328: rpki_schedule_next_retry(struct rpki_cache *cache) ! 329: { ! 330: btime t = cache->retry_interval S; ! 331: ! 332: CACHE_DBG(cache, "after %t s", t); ! 333: tm_start(cache->retry_timer, t); ! 334: } ! 335: ! 336: static void ! 337: rpki_schedule_next_expire_check(struct rpki_cache *cache) ! 338: { ! 339: /* A minimum time to wait is 1 second */ ! 340: btime t = cache->last_update + cache->expire_interval S - current_time(); ! 341: t = MAX(t, 1 S); ! 342: ! 343: CACHE_DBG(cache, "after %t s", t); ! 344: tm_start(cache->expire_timer, t); ! 345: } ! 346: ! 347: static void ! 348: rpki_stop_refresh_timer_event(struct rpki_cache *cache) ! 349: { ! 350: CACHE_DBG(cache, "Stop"); ! 351: tm_stop(cache->refresh_timer); ! 352: } ! 353: ! 354: static void ! 355: rpki_stop_retry_timer_event(struct rpki_cache *cache) ! 356: { ! 357: CACHE_DBG(cache, "Stop"); ! 358: tm_stop(cache->retry_timer); ! 359: } ! 360: ! 361: static void UNUSED ! 362: rpki_stop_expire_timer_event(struct rpki_cache *cache) ! 363: { ! 364: CACHE_DBG(cache, "Stop"); ! 365: tm_stop(cache->expire_timer); ! 366: } ! 367: ! 368: static int ! 369: rpki_do_we_recv_prefix_pdu_in_last_seconds(struct rpki_cache *cache) ! 370: { ! 371: if (!cache->last_rx_prefix) ! 372: return 0; ! 373: ! 374: return ((current_time() - cache->last_rx_prefix) <= 2 S); ! 375: } ! 376: ! 377: /** ! 378: * rpki_refresh_hook - control a scheduling of downloading data from cache server ! 379: * @tm: refresh timer with cache connection instance in data ! 380: * ! 381: * This function is periodically called during &ESTABLISHED or &SYNC* state ! 382: * cache connection. The first refresh schedule is invoked after receiving a ! 383: * |End of Data| PDU and has run by some &ERROR is occurred. ! 384: */ ! 385: static void ! 386: rpki_refresh_hook(timer *tm) ! 387: { ! 388: struct rpki_cache *cache = tm->data; ! 389: ! 390: CACHE_DBG(cache, "%s", rpki_cache_state_to_str(cache->state)); ! 391: ! 392: switch (cache->state) ! 393: { ! 394: case RPKI_CS_ESTABLISHED: ! 395: rpki_cache_change_state(cache, RPKI_CS_SYNC_START); ! 396: break; ! 397: ! 398: case RPKI_CS_SYNC_START: ! 399: /* We sent Serial/Reset Query in last refresh hook call ! 400: * and didn't receive Cache Response yet. It is probably ! 401: * troubles with network. */ ! 402: case RPKI_CS_SYNC_RUNNING: ! 403: /* We sent Serial/Reset Query in last refresh hook call ! 404: * and we got Cache Response but didn't get End-Of-Data yet. ! 405: * It could be a trouble with network or only too long synchronization. */ ! 406: if (!rpki_do_we_recv_prefix_pdu_in_last_seconds(cache)) ! 407: { ! 408: CACHE_TRACE(D_EVENTS, cache, "Sync takes more time than refresh interval %us, resetting connection", cache->refresh_interval); ! 409: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT); ! 410: } ! 411: break; ! 412: ! 413: default: ! 414: break; ! 415: } ! 416: ! 417: if (cache->state != RPKI_CS_SHUTDOWN && cache->state != RPKI_CS_ERROR_TRANSPORT) ! 418: rpki_schedule_next_refresh(cache); ! 419: else ! 420: rpki_stop_refresh_timer_event(cache); ! 421: } ! 422: ! 423: /** ! 424: * rpki_retry_hook - control a scheduling of retrying connection to cache server ! 425: * @tm: retry timer with cache connection instance in data ! 426: * ! 427: * This function is periodically called during &ERROR* state cache connection. ! 428: * The first retry schedule is invoked after any &ERROR* state occurred and ! 429: * ends by reaching of &ESTABLISHED state again. ! 430: */ ! 431: static void ! 432: rpki_retry_hook(timer *tm) ! 433: { ! 434: struct rpki_cache *cache = tm->data; ! 435: ! 436: CACHE_DBG(cache, "%s", rpki_cache_state_to_str(cache->state)); ! 437: ! 438: switch (cache->state) ! 439: { ! 440: case RPKI_CS_ESTABLISHED: ! 441: case RPKI_CS_SHUTDOWN: ! 442: break; ! 443: ! 444: case RPKI_CS_CONNECTING: ! 445: case RPKI_CS_SYNC_START: ! 446: case RPKI_CS_SYNC_RUNNING: ! 447: if (!rpki_do_we_recv_prefix_pdu_in_last_seconds(cache)) ! 448: { ! 449: /* We tried to establish a connection in last retry hook call and haven't done ! 450: * yet. It looks like troubles with network. We are aggressive here. */ ! 451: CACHE_TRACE(D_EVENTS, cache, "Sync takes more time than retry interval %us, resetting connection.", cache->retry_interval); ! 452: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT); ! 453: } ! 454: break; ! 455: ! 456: default: ! 457: rpki_cache_change_state(cache, RPKI_CS_CONNECTING); ! 458: break; ! 459: } ! 460: ! 461: if (cache->state != RPKI_CS_ESTABLISHED) ! 462: rpki_schedule_next_retry(cache); ! 463: else ! 464: rpki_stop_retry_timer_event(cache); ! 465: } ! 466: ! 467: /** ! 468: * rpki_expire_hook - control a expiration of ROA entries ! 469: * @tm: expire timer with cache connection instance in data ! 470: * ! 471: * This function is scheduled after received a |End of Data| PDU. ! 472: * A waiting interval is calculated dynamically by last update. ! 473: * If we reach an expiration time then we invoke a restarting ! 474: * of the protocol. ! 475: */ ! 476: static void ! 477: rpki_expire_hook(timer *tm) ! 478: { ! 479: struct rpki_cache *cache = tm->data; ! 480: ! 481: if (!cache->last_update) ! 482: return; ! 483: ! 484: CACHE_DBG(cache, "%s", rpki_cache_state_to_str(cache->state)); ! 485: ! 486: btime t = cache->last_update + cache->expire_interval S - current_time(); ! 487: if (t <= 0) ! 488: { ! 489: CACHE_TRACE(D_EVENTS, cache, "All ROAs expired"); ! 490: rpki_force_restart_proto(cache->p); ! 491: } ! 492: else ! 493: { ! 494: CACHE_DBG(cache, "Remains %t seconds to become ROAs obsolete", t); ! 495: rpki_schedule_next_expire_check(cache); ! 496: } ! 497: } ! 498: ! 499: /** ! 500: * rpki_check_refresh_interval - check validity of refresh interval value ! 501: * @seconds: suggested value ! 502: * ! 503: * This function validates value and should return |NULL|. ! 504: * If the check doesn't pass then returns error message. ! 505: */ ! 506: const char * ! 507: rpki_check_refresh_interval(uint seconds) ! 508: { ! 509: if (seconds < 1) ! 510: return "Minimum allowed refresh interval is 1 second"; ! 511: if (seconds > 86400) ! 512: return "Maximum allowed refresh interval is 86400 seconds"; ! 513: return NULL; ! 514: } ! 515: ! 516: /** ! 517: * rpki_check_retry_interval - check validity of retry interval value ! 518: * @seconds: suggested value ! 519: * ! 520: * This function validates value and should return |NULL|. ! 521: * If the check doesn't pass then returns error message. ! 522: */ ! 523: const char * ! 524: rpki_check_retry_interval(uint seconds) ! 525: { ! 526: if (seconds < 1) ! 527: return "Minimum allowed retry interval is 1 second"; ! 528: if (seconds > 7200) ! 529: return "Maximum allowed retry interval is 7200 seconds"; ! 530: return NULL; ! 531: } ! 532: ! 533: /** ! 534: * rpki_check_expire_interval - check validity of expire interval value ! 535: * @seconds: suggested value ! 536: * ! 537: * This function validates value and should return |NULL|. ! 538: * If the check doesn't pass then returns error message. ! 539: */ ! 540: const char * ! 541: rpki_check_expire_interval(uint seconds) ! 542: { ! 543: if (seconds < 600) ! 544: return "Minimum allowed expire interval is 600 seconds"; ! 545: if (seconds > 172800) ! 546: return "Maximum allowed expire interval is 172800 seconds"; ! 547: return NULL; ! 548: } ! 549: ! 550: ! 551: /* ! 552: * RPKI Cache ! 553: */ ! 554: ! 555: static struct rpki_cache * ! 556: rpki_init_cache(struct rpki_proto *p, struct rpki_config *cf) ! 557: { ! 558: pool *pool = rp_new(p->p.pool, cf->hostname); ! 559: ! 560: struct rpki_cache *cache = mb_allocz(pool, sizeof(struct rpki_cache)); ! 561: ! 562: cache->pool = pool; ! 563: cache->p = p; ! 564: ! 565: cache->state = RPKI_CS_SHUTDOWN; ! 566: cache->request_session_id = 1; ! 567: cache->version = RPKI_MAX_VERSION; ! 568: ! 569: cache->refresh_interval = cf->refresh_interval; ! 570: cache->retry_interval = cf->retry_interval; ! 571: cache->expire_interval = cf->expire_interval; ! 572: cache->refresh_timer = tm_new_init(pool, &rpki_refresh_hook, cache, 0, 0); ! 573: cache->retry_timer = tm_new_init(pool, &rpki_retry_hook, cache, 0, 0); ! 574: cache->expire_timer = tm_new_init(pool, &rpki_expire_hook, cache, 0, 0); ! 575: ! 576: cache->tr_sock = mb_allocz(pool, sizeof(struct rpki_tr_sock)); ! 577: cache->tr_sock->cache = cache; ! 578: ! 579: switch (cf->tr_config.type) ! 580: { ! 581: case RPKI_TR_TCP: rpki_tr_tcp_init(cache->tr_sock); break; ! 582: case RPKI_TR_SSH: rpki_tr_ssh_init(cache->tr_sock); break; ! 583: }; ! 584: ! 585: CACHE_DBG(cache, "Connection object created"); ! 586: ! 587: return cache; ! 588: } ! 589: ! 590: /** ! 591: * rpki_get_cache_ident - give a text representation of cache server name ! 592: * @cache: RPKI connection instance ! 593: * ! 594: * The function converts cache connection into string. ! 595: */ ! 596: const char * ! 597: rpki_get_cache_ident(struct rpki_cache *cache) ! 598: { ! 599: return rpki_tr_ident(cache->tr_sock); ! 600: } ! 601: ! 602: static int ! 603: rpki_open_connection(struct rpki_cache *cache) ! 604: { ! 605: CACHE_TRACE(D_EVENTS, cache, "Opening a connection"); ! 606: ! 607: if (rpki_tr_open(cache->tr_sock) == RPKI_TR_ERROR) ! 608: { ! 609: rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT); ! 610: return RPKI_TR_ERROR; ! 611: } ! 612: ! 613: return RPKI_TR_SUCCESS; ! 614: } ! 615: ! 616: static void ! 617: rpki_close_connection(struct rpki_cache *cache) ! 618: { ! 619: CACHE_TRACE(D_EVENTS, cache, "Closing a connection"); ! 620: rpki_tr_close(cache->tr_sock); ! 621: proto_notify_state(&cache->p->p, PS_START); ! 622: } ! 623: ! 624: static int ! 625: rpki_shutdown(struct proto *P) ! 626: { ! 627: struct rpki_proto *p = (void *) P; ! 628: ! 629: rpki_force_restart_proto(p); ! 630: ! 631: /* Protocol memory pool will be automatically freed */ ! 632: return PS_DOWN; ! 633: } ! 634: ! 635: ! 636: /* ! 637: * RPKI Reconfiguration ! 638: */ ! 639: ! 640: static int ! 641: rpki_try_fast_reconnect(struct rpki_cache *cache) ! 642: { ! 643: if (cache->state == RPKI_CS_ESTABLISHED) ! 644: { ! 645: rpki_cache_change_state(cache, RPKI_CS_FAST_RECONNECT); ! 646: return SUCCESSFUL_RECONF; ! 647: } ! 648: ! 649: return NEED_RESTART; ! 650: } ! 651: ! 652: /** ! 653: * rpki_reconfigure_cache - a cache reconfiguration ! 654: * @p: RPKI protocol instance ! 655: * @cache: a cache connection ! 656: * @new: new RPKI configuration ! 657: * @old: old RPKI configuration ! 658: * ! 659: * This function reconfigures existing single cache server connection with new ! 660: * existing configuration. Generally, a change of time intervals could be ! 661: * reconfigured without restarting and all others changes requires a restart of ! 662: * protocol. Returns |NEED_TO_RESTART| or |SUCCESSFUL_RECONF|. ! 663: */ ! 664: static int ! 665: rpki_reconfigure_cache(struct rpki_proto *p UNUSED, struct rpki_cache *cache, struct rpki_config *new, struct rpki_config *old) ! 666: { ! 667: u8 try_fast_reconnect = 0; ! 668: ! 669: if (strcmp(old->hostname, new->hostname) != 0) ! 670: { ! 671: CACHE_TRACE(D_EVENTS, cache, "Cache server address changed to %s", new->hostname); ! 672: return NEED_RESTART; ! 673: } ! 674: ! 675: if (old->port != new->port) ! 676: { ! 677: CACHE_TRACE(D_EVENTS, cache, "Cache server port changed to %u", new->port); ! 678: return NEED_RESTART; ! 679: } ! 680: ! 681: if (old->tr_config.type != new->tr_config.type) ! 682: { ! 683: CACHE_TRACE(D_EVENTS, cache, "Transport type changed"); ! 684: return NEED_RESTART; ! 685: } ! 686: else if (new->tr_config.type == RPKI_TR_SSH) ! 687: { ! 688: struct rpki_tr_ssh_config *ssh_old = (void *) old->tr_config.spec; ! 689: struct rpki_tr_ssh_config *ssh_new = (void *) new->tr_config.spec; ! 690: if (bstrcmp(ssh_old->bird_private_key, ssh_new->bird_private_key) || ! 691: bstrcmp(ssh_old->cache_public_key, ssh_new->cache_public_key) || ! 692: bstrcmp(ssh_old->user, ssh_new->user)) ! 693: { ! 694: CACHE_TRACE(D_EVENTS, cache, "Settings of SSH transport configuration changed"); ! 695: try_fast_reconnect = 1; ! 696: } ! 697: } ! 698: ! 699: #define TEST_INTERVAL(name, Name) \ ! 700: if (cache->name##_interval != new->name##_interval || \ ! 701: old->keep_##name##_interval != new->keep_##name##_interval) \ ! 702: { \ ! 703: cache->name##_interval = new->name##_interval; \ ! 704: CACHE_TRACE(D_EVENTS, cache, #Name " interval changed to %u seconds %s", cache->name##_interval, (new->keep_##name##_interval ? "and keep it" : "")); \ ! 705: try_fast_reconnect = 1; \ ! 706: } ! 707: TEST_INTERVAL(refresh, Refresh); ! 708: TEST_INTERVAL(retry, Retry); ! 709: TEST_INTERVAL(expire, Expire); ! 710: #undef TEST_INTERVAL ! 711: ! 712: if (try_fast_reconnect) ! 713: return rpki_try_fast_reconnect(cache); ! 714: ! 715: return SUCCESSFUL_RECONF; ! 716: } ! 717: ! 718: /** ! 719: * rpki_reconfigure - a protocol reconfiguration hook ! 720: * @P: a protocol instance ! 721: * @CF: a new protocol configuration ! 722: * ! 723: * This function reconfigures whole protocol. ! 724: * It sets new protocol configuration into a protocol structure. ! 725: * Returns |NEED_TO_RESTART| or |SUCCESSFUL_RECONF|. ! 726: */ ! 727: static int ! 728: rpki_reconfigure(struct proto *P, struct proto_config *CF) ! 729: { ! 730: struct rpki_proto *p = (void *) P; ! 731: struct rpki_config *new = (void *) CF; ! 732: struct rpki_config *old = (void *) p->p.cf; ! 733: struct rpki_cache *cache = p->cache; ! 734: ! 735: if (!proto_configure_channel(&p->p, &p->roa4_channel, proto_cf_find_channel(CF, NET_ROA4)) || ! 736: !proto_configure_channel(&p->p, &p->roa6_channel, proto_cf_find_channel(CF, NET_ROA6))) ! 737: return NEED_RESTART; ! 738: ! 739: if (rpki_reconfigure_cache(p, cache, new, old) != SUCCESSFUL_RECONF) ! 740: return NEED_RESTART; ! 741: ! 742: return SUCCESSFUL_RECONF; ! 743: } ! 744: ! 745: ! 746: /* ! 747: * RPKI Protocol Glue ! 748: */ ! 749: ! 750: static struct proto * ! 751: rpki_init(struct proto_config *CF) ! 752: { ! 753: struct proto *P = proto_new(CF); ! 754: struct rpki_proto *p = (void *) P; ! 755: ! 756: proto_configure_channel(&p->p, &p->roa4_channel, proto_cf_find_channel(CF, NET_ROA4)); ! 757: proto_configure_channel(&p->p, &p->roa6_channel, proto_cf_find_channel(CF, NET_ROA6)); ! 758: ! 759: return P; ! 760: } ! 761: ! 762: static int ! 763: rpki_start(struct proto *P) ! 764: { ! 765: struct rpki_proto *p = (void *) P; ! 766: struct rpki_config *cf = (void *) P->cf; ! 767: ! 768: p->cache = rpki_init_cache(p, cf); ! 769: rpki_start_cache(p->cache); ! 770: ! 771: return PS_START; ! 772: } ! 773: ! 774: static void ! 775: rpki_get_status(struct proto *P, byte *buf) ! 776: { ! 777: struct rpki_proto *p = (struct rpki_proto *) P; ! 778: ! 779: if (P->proto_state == PS_DOWN) ! 780: { ! 781: *buf = 0; ! 782: return; ! 783: } ! 784: ! 785: if (p->cache) ! 786: bsprintf(buf, "%s", rpki_cache_state_to_str(p->cache->state)); ! 787: else ! 788: bsprintf(buf, "No cache server configured"); ! 789: } ! 790: ! 791: static void ! 792: rpki_show_proto_info_timer(const char *name, uint num, timer *t) ! 793: { ! 794: if (tm_active(t)) ! 795: cli_msg(-1006, " %-16s: %t/%u", name, tm_remains(t), num); ! 796: else ! 797: cli_msg(-1006, " %-16s: ---", name); ! 798: } ! 799: ! 800: static void ! 801: rpki_show_proto_info(struct proto *P) ! 802: { ! 803: struct rpki_proto *p = (struct rpki_proto *) P; ! 804: struct rpki_config *cf = (void *) p->p.cf; ! 805: struct rpki_cache *cache = p->cache; ! 806: ! 807: if (P->proto_state == PS_DOWN) ! 808: return; ! 809: ! 810: if (cache) ! 811: { ! 812: const char *transport_name = "---"; ! 813: ! 814: switch (cf->tr_config.type) ! 815: { ! 816: case RPKI_TR_SSH: transport_name = "SSHv2"; break; ! 817: case RPKI_TR_TCP: transport_name = "Unprotected over TCP"; break; ! 818: }; ! 819: ! 820: cli_msg(-1006, " Cache server: %s", rpki_get_cache_ident(cache)); ! 821: cli_msg(-1006, " Status: %s", rpki_cache_state_to_str(cache->state)); ! 822: cli_msg(-1006, " Transport: %s", transport_name); ! 823: cli_msg(-1006, " Protocol version: %u", cache->version); ! 824: ! 825: if (cache->request_session_id) ! 826: cli_msg(-1006, " Session ID: ---"); ! 827: else ! 828: cli_msg(-1006, " Session ID: %u", cache->session_id); ! 829: ! 830: if (cache->last_update) ! 831: { ! 832: cli_msg(-1006, " Serial number: %u", cache->serial_num); ! 833: cli_msg(-1006, " Last update: before %t s", current_time() - cache->last_update); ! 834: } ! 835: else ! 836: { ! 837: cli_msg(-1006, " Serial number: ---"); ! 838: cli_msg(-1006, " Last update: ---"); ! 839: } ! 840: ! 841: rpki_show_proto_info_timer("Refresh timer", cache->refresh_interval, cache->refresh_timer); ! 842: rpki_show_proto_info_timer("Retry timer", cache->retry_interval, cache->retry_timer); ! 843: rpki_show_proto_info_timer("Expire timer", cache->expire_interval, cache->expire_timer); ! 844: ! 845: if (p->roa4_channel) ! 846: channel_show_info(p->roa4_channel); ! 847: else ! 848: cli_msg(-1006, " No roa4 channel"); ! 849: ! 850: if (p->roa6_channel) ! 851: channel_show_info(p->roa6_channel); ! 852: else ! 853: cli_msg(-1006, " No roa6 channel"); ! 854: } ! 855: } ! 856: ! 857: ! 858: /* ! 859: * RPKI Protocol Configuration ! 860: */ ! 861: ! 862: /** ! 863: * rpki_check_config - check and complete configuration of RPKI protocol ! 864: * @cf: RPKI configuration ! 865: * ! 866: * This function is called at the end of parsing RPKI protocol configuration. ! 867: */ ! 868: void ! 869: rpki_check_config(struct rpki_config *cf) ! 870: { ! 871: /* Do not check templates at all */ ! 872: if (cf->c.class == SYM_TEMPLATE) ! 873: return; ! 874: ! 875: if (ipa_zero(cf->ip) && cf->hostname == NULL) ! 876: cf_error("IP address or hostname of cache server must be set"); ! 877: ! 878: /* Set default transport type */ ! 879: if (cf->tr_config.spec == NULL) ! 880: { ! 881: cf->tr_config.spec = cfg_allocz(sizeof(struct rpki_tr_tcp_config)); ! 882: cf->tr_config.type = RPKI_TR_TCP; ! 883: } ! 884: ! 885: if (cf->port == 0) ! 886: { ! 887: /* Set default port numbers */ ! 888: switch (cf->tr_config.type) ! 889: { ! 890: case RPKI_TR_SSH: ! 891: cf->port = RPKI_SSH_PORT; ! 892: break; ! 893: default: ! 894: cf->port = RPKI_TCP_PORT; ! 895: } ! 896: } ! 897: } ! 898: ! 899: static void ! 900: rpki_postconfig(struct proto_config *CF) ! 901: { ! 902: /* Define default channel */ ! 903: if (EMPTY_LIST(CF->channels)) ! 904: channel_config_new(NULL, net_label[CF->net_type], CF->net_type, CF); ! 905: } ! 906: ! 907: static void ! 908: rpki_copy_config(struct proto_config *dest UNUSED, struct proto_config *src UNUSED) ! 909: { ! 910: /* FIXME: Should copy transport */ ! 911: } ! 912: ! 913: struct protocol proto_rpki = { ! 914: .name = "RPKI", ! 915: .template = "rpki%d", ! 916: .class = PROTOCOL_RPKI, ! 917: .preference = DEF_PREF_RPKI, ! 918: .proto_size = sizeof(struct rpki_proto), ! 919: .config_size = sizeof(struct rpki_config), ! 920: .init = rpki_init, ! 921: .start = rpki_start, ! 922: .postconfig = rpki_postconfig, ! 923: .channel_mask = (NB_ROA4 | NB_ROA6), ! 924: .show_proto_info = rpki_show_proto_info, ! 925: .shutdown = rpki_shutdown, ! 926: .copy_config = rpki_copy_config, ! 927: .reconfigure = rpki_reconfigure, ! 928: .get_status = rpki_get_status, ! 929: };