Annotation of embedaddon/bird2/proto/rpki/rpki.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:  *     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: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>