Sweep for expired routes. Sweeps every two seconds for now, not yet configurable.
authorJennifer Richards <jennifer@painless-security.com>
Thu, 14 Jul 2016 19:54:50 +0000 (15:54 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Thu, 14 Jul 2016 19:54:50 +0000 (15:54 -0400)
common/tr_config.c
include/tr_config.h
include/tr_trp.h
include/trp_internal.h
include/trp_rtable.h
tr/tr_trp.c
trp/trp_rtable.c
trp/trps.c

index 0625790..59fd409 100644 (file)
@@ -96,6 +96,7 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
   json_t *jlogthres = NULL;
   json_t *jcfgpoll = NULL;
   json_t *jcfgsettle = NULL;
+  json_t *jroutesweep = NULL;
 
   if ((!trc) || (!jcfg))
     return TR_CFG_BAD_PARAMS;
@@ -163,6 +164,14 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
        return TR_CFG_NOPARSE;
       }
     }
+    if (NULL != (jroutesweep = json_object_get(jint, "route_sweep_interval"))) {
+      if (json_is_number(jroutesweep)) {
+       trc->internal->route_sweep_interval = json_integer_value(jroutesweep);
+      } else {
+       tr_debug("tr_cfg_parse_internal: Parsing error, route_sweep_interval is not a number.");
+       return TR_CFG_NOPARSE;
+      }
+    }
 
     if (NULL != (jlog = json_object_get(jint, "logging"))) {
       if (NULL != (jlogthres = json_object_get(jlog, "log_threshold"))) {
index af58db9..737da4b 100644 (file)
@@ -69,6 +69,7 @@ typedef struct tr_cfg_internal {
   int console_threshold;
   unsigned int cfg_poll_interval;
   unsigned int cfg_settle_count;
+  unsigned int route_sweep_interval;
 } TR_CFG_INTERNAL;
 
 typedef struct tr_cfg {
index 66222d3..7b12672 100644 (file)
@@ -12,6 +12,7 @@
 typedef struct tr_trps_events {
   struct tr_socket_event *listen_ev;
   struct event *mq_ev;
+  struct event *sweep_ev;
 } TR_TRPS_EVENTS;
 
 /* prototypes */
index 5289980..fb2eaef 100644 (file)
@@ -162,5 +162,6 @@ TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg);
 TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer);
 TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm);
 TR_NAME *trps_get_next_hop(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm);
+TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps);
 
 #endif /* TRP_INTERNAL_H */
index ec3d778..0f6966e 100644 (file)
@@ -15,6 +15,7 @@ typedef struct trp_rentry {
   TR_NAME *trust_router;
   TR_NAME *next_hop;
   int selected;
+  unsigned int interval; /* interval from route update */
   struct timespec *expiry;
 } TRP_RENTRY;
 
@@ -52,6 +53,8 @@ void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop);
 TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry);
 void trp_rentry_set_selected(TRP_RENTRY *entry, int sel);
 int trp_rentry_get_selected(TRP_RENTRY *entry);
+void trp_rentry_set_interval(TRP_RENTRY *entry, int interval);
+int trp_rentry_get_interval(TRP_RENTRY *entry);
 void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp);
 TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm);
 struct timespec *trp_rentry_get_expiry(TRP_RENTRY *entry);
index ac9f905..492fc5d 100644 (file)
@@ -5,6 +5,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <string.h>
+#include <sys/time.h>
 
 #include <gsscon.h>
 #include <tr_rp.h>
@@ -195,11 +196,20 @@ static void tr_trps_process_mq(int socket, short event, void *arg)
   }
 }
 
+static void tr_trps_sweep(int listener, short event, void *arg)
+{
+  TRPS_INSTANCE *trps=talloc_get_type_abort(arg, TRPS_INSTANCE);
+  tr_debug("tr_trps_sweep: sweeping routes");
+  trps_sweep_routes(trps);
+}
+
 static int tr_trps_events_destructor(void *obj)
 {
   TR_TRPS_EVENTS *ev=talloc_get_type_abort(obj, TR_TRPS_EVENTS);
   if (ev->mq_ev!=NULL)
     event_free(ev->mq_ev);
+  if (ev->sweep_ev!=NULL)
+    event_free(ev->sweep_ev);
   return 0;
 }
 TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
@@ -208,6 +218,7 @@ TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
   if (ev!=NULL) {
     ev->listen_ev=talloc(ev, struct tr_socket_event);
     ev->mq_ev=NULL;
+    ev->sweep_ev=NULL;
     if (ev->listen_ev==NULL) {
       talloc_free(ev);
       ev=NULL;
@@ -227,6 +238,7 @@ TRP_RC tr_trps_event_init(struct event_base *base,
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   struct tr_socket_event *listen_ev=NULL;
   struct tr_trps_event_cookie *cookie;
+  struct timeval two_secs={2, 0};
   TRP_RC retval=TRP_ERROR;
 
   if (trps_ev == NULL) {
@@ -280,6 +292,11 @@ TRP_RC tr_trps_event_init(struct event_base *base,
                            (void *)trps);
   tr_mq_set_notify_cb(trps->mq, tr_trps_mq_cb, trps_ev->mq_ev);
 
+  /* now set up the route table sweep timer event */
+  trps_ev->sweep_ev=event_new(base, -1, EV_TIMEOUT|EV_PERSIST, tr_trps_sweep, (void *)trps);
+  /* todo: event_add(trps_ev->sweep_ev, &(cfg_mgr->active->internal->route_sweep_interval)); */
+  event_add(trps_ev->sweep_ev, &two_secs);
+
   retval=TRP_SUCCESS;
 
 cleanup:
index 6cc8e18..20caef7 100644 (file)
@@ -37,6 +37,7 @@ TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx)
     entry->peer=NULL;
     entry->next_hop=NULL;
     entry->selected=0;
+    entry->interval=0;
     entry->expiry=talloc(entry, struct timespec);
     if (entry->expiry==NULL) {
       talloc_free(entry);
@@ -123,6 +124,16 @@ int trp_rentry_get_selected(TRP_RENTRY *entry)
   return entry->selected;
 }
 
+void trp_rentry_set_interval(TRP_RENTRY *entry, int interval)
+{
+  entry->interval=interval;
+}
+
+int trp_rentry_get_interval(TRP_RENTRY *entry)
+{
+  return entry->interval;
+}
+
 /* copies incoming value, does not assume responsibility for freeing */
 void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp)
 {
index aa6a834..5134645 100644 (file)
@@ -488,10 +488,11 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec)
    * time unset on a new route entry. */
   tr_debug("trps_accept_update: accepting route update.");
   trp_rentry_set_metric(entry, trp_inforec_get_metric(rec));
+  trp_rentry_set_interval(entry, trp_inforec_get_interval(rec));
   if (!trps_route_retracted(trps, entry)) {
     tr_debug("trps_accept_update: route not retracted, setting expiry timer.");
     trp_rentry_set_expiry(entry, trps_compute_expiry(trps,
-                                                     trp_inforec_get_interval(rec),
+                                                     trp_rentry_get_interval(entry),
                                                      trp_rentry_get_expiry(entry)));
   }
   return TRP_SUCCESS;
@@ -613,3 +614,54 @@ TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg)
     return TRP_ERROR;
   }
 }
+
+/* true if curtime >= expiry */
+static int trps_expired(struct timespec *expiry, struct timespec *curtime)
+{
+  return ((curtime->tv_sec > expiry->tv_sec)
+         || ((curtime->tv_sec == expiry->tv_sec)
+            &&(curtime->tv_nsec > expiry->tv_nsec)));
+}
+
+/* Sweep for expired routes. For each expired route, if its metric is infinite, the route is flushed.
+ * If its metric is finite, the metric is set to infinite and the route's expiration time is updated. */
+TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps)
+{
+  struct timespec sweep_time={0,0};
+  TRP_RENTRY **entry=NULL;
+  size_t n_entry=0;
+  size_t ii=0;
+
+  /* use a single time for the entire sweep */
+  if (0!=clock_gettime(CLOCK_REALTIME, &sweep_time)) {
+    tr_err("trps_sweep_routes: could not read realtime clock.");
+    sweep_time.tv_sec=0;
+    sweep_time.tv_nsec=0;
+    return TRP_ERROR;
+  }
+
+  entry=trp_rtable_get_entries(trps->rtable, &n_entry); /* must talloc_free *entry */
+
+  /* loop over the entries */
+  for (ii=0; ii<n_entry; ii++) {
+    if (trps_expired(trp_rentry_get_expiry(entry[ii]), &sweep_time)) {
+      tr_debug("trps_sweep_routes: route expired.");
+      if (TRP_METRIC_INFINITY==trp_rentry_get_metric(entry[ii])) {
+        /* flush route */
+        tr_debug("trps_sweep_routes: metric was infinity, flushing route.");
+        trp_rtable_remove(trps->rtable, entry[ii]); /* entry[ii] is no longer valid */
+        entry[ii]=NULL;
+      } else {
+        /* set metric to infinity and reset timer */
+        tr_debug("trps_sweep_routes: setting metric to infinity and resetting expiry.");
+        trp_rentry_set_metric(entry[ii], TRP_METRIC_INFINITY);
+        trp_rentry_set_expiry(entry[ii], trps_compute_expiry(trps,
+                                                             trp_rentry_get_interval(entry[ii]),
+                                                             trp_rentry_get_expiry(entry[ii])));
+      }
+    }
+  }
+
+  talloc_free(entry);
+  return TRP_SUCCESS;
+}