Connect to hard-coded peer and exchange route info. Buggy and incomplete.
authorJennifer Richards <jennifer@painless-security.com>
Wed, 20 Jul 2016 04:02:27 +0000 (00:02 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Wed, 20 Jul 2016 04:02:27 +0000 (00:02 -0400)
17 files changed:
common/tr_config.c
common/tr_msg.c
include/tr_config.h
include/tr_trp.h
include/trp_internal.h
include/trp_ptable.h
include/trp_rtable.h
include/trust_router/trp.h
tr/tr_cfgwatch.c
tr/tr_main.c
tr/tr_trp.c
trp/trp_conn.c
trp/trp_ptable.c
trp/trp_rtable.c
trp/trp_upd.c
trp/trpc.c
trp/trps.c

index 6a3d4dc..4d05d4b 100644 (file)
@@ -98,6 +98,7 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
   json_t *jcfgsettle = NULL;
   json_t *jroutesweep = NULL;
   json_t *jrouteupdate = NULL;
+  json_t *jrouteconnect = NULL;
 
   if ((!trc) || (!jcfg))
     return TR_CFG_BAD_PARAMS;
@@ -165,21 +166,41 @@ 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 (NULL != (jrouteconnect = json_object_get(jint, "trp_connect_interval"))) {
+      if (json_is_number(jrouteconnect)) {
+       trc->internal->trp_connect_interval = json_integer_value(jrouteconnect);
+      } else {
+       tr_debug("tr_cfg_parse_internal: Parsing error, trp_connect_interval is not a number.");
+       return TR_CFG_NOPARSE;
+      }
+    } else {
+      /* if not configured, use the default */
+      trc->internal->trp_connect_interval=TR_DEFAULT_TRP_CONNECT_INTERVAL;
+    }
+
+    if (NULL != (jroutesweep = json_object_get(jint, "trp_sweep_interval"))) {
       if (json_is_number(jroutesweep)) {
-       trc->internal->route_sweep_interval = json_integer_value(jroutesweep);
+       trc->internal->trp_sweep_interval = json_integer_value(jroutesweep);
       } else {
-       tr_debug("tr_cfg_parse_internal: Parsing error, route_sweep_interval is not a number.");
+       tr_debug("tr_cfg_parse_internal: Parsing error, trp_sweep_interval is not a number.");
        return TR_CFG_NOPARSE;
       }
+    } else {
+      /* if not configured, use the default */
+      trc->internal->trp_sweep_interval=TR_DEFAULT_TRP_SWEEP_INTERVAL;
     }
-    if (NULL != (jrouteupdate = json_object_get(jint, "route_update_interval"))) {
+
+    if (NULL != (jrouteupdate = json_object_get(jint, "trp_update_interval"))) {
       if (json_is_number(jrouteupdate)) {
-       trc->internal->route_update_interval = json_integer_value(jrouteupdate);
+       trc->internal->trp_update_interval = json_integer_value(jrouteupdate);
       } else {
-       tr_debug("tr_cfg_parse_internal: Parsing error, route_update_interval is not a number.");
+       tr_debug("tr_cfg_parse_internal: Parsing error, trp_update_interval is not a number.");
        return TR_CFG_NOPARSE;
       }
+    } else {
+      /* if not configured, use the default */
+      trc->internal->trp_update_interval=TR_DEFAULT_TRP_UPDATE_INTERVAL;
     }
 
     if (NULL != (jlog = json_object_get(jint, "logging"))) {
index 6295068..b2964b6 100644 (file)
@@ -717,6 +717,7 @@ static json_t *tr_msg_encode_trp_upd(TRP_UPD *update)
   }
   json_object_set_new(jupdate, "records", jrecords); /* jrecords now a "borrowed" reference */
   for (rec=trp_upd_get_inforec(update); rec!=NULL; rec=trp_inforec_get_next(rec)) {
+    tr_debug("tr_msg_encode_trp_upd: encoding inforec.");
     jrec=tr_msg_encode_inforec(rec);
     if (jrec==NULL) {
       json_decref(jupdate); /* also decs jrecords and any elements */
index 6cffb00..626b20b 100644 (file)
@@ -52,7 +52,9 @@
 #define TR_DEFAULT_TRPS_PORT 12310
 #define TR_DEFAULT_LOG_THRESHOLD LOG_INFO
 #define TR_DEFAULT_CONSOLE_THRESHOLD LOG_NOTICE
-
+#define TR_DEFAULT_TRP_CONNECT_INTERVAL 10
+#define TR_DEFAULT_TRP_UPDATE_INTERVAL 120
+#define TR_DEFAULT_TRP_SWEEP_INTERVAL 30
 typedef enum tr_cfg_rc {
   TR_CFG_SUCCESS = 0,  /* No error */
   TR_CFG_ERROR,                /* General processing error */
@@ -70,8 +72,9 @@ typedef struct tr_cfg_internal {
   int console_threshold;
   unsigned int cfg_poll_interval;
   unsigned int cfg_settle_count;
-  unsigned int route_sweep_interval;
-  unsigned int route_update_interval;
+  unsigned int trp_sweep_interval;
+  unsigned int trp_update_interval;
+  unsigned int trp_connect_interval;
 } TR_CFG_INTERNAL;
 
 typedef struct tr_cfg {
index 53033f6..87f4ce0 100644 (file)
@@ -12,6 +12,7 @@
 typedef struct tr_trps_events {
   struct tr_socket_event *listen_ev;
   struct event *mq_ev;
+  struct event *connect_ev;
   struct event *update_ev;
   struct event *sweep_ev;
 } TR_TRPS_EVENTS;
@@ -20,6 +21,7 @@ typedef struct tr_trps_events {
 TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx);
 TRP_RC tr_trps_event_init(struct event_base *base, TRPS_INSTANCE *trps, TR_CFG_MGR *cfg_mgr,
                        TR_TRPS_EVENTS *trps_ev);
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigned int port);
+TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer);
 void tr_config_changed(TR_CFG *new_cfg, void *cookie);
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps);
 #endif /* TR_TRP_H */
index 5151075..20e54b8 100644 (file)
@@ -76,6 +76,7 @@ typedef client_cb_fn TRP_AUTH_FUNC;
 typedef struct trpc_instance TRPC_INSTANCE;
 struct trpc_instance {
   TRPC_INSTANCE *next;
+  TR_NAME *gssname;
   char *server;
   unsigned int port;
   TRP_CONNECTION *conn;
@@ -95,6 +96,7 @@ struct trps_instance {
   TR_MQ *mq; /* incoming message queue */
   TRP_PTABLE *ptable; /* peer table */
   TRP_RTABLE *rtable; /* route table */
+  struct timeval connect_interval; /* interval between connection refreshes */
   struct timeval update_interval; /* interval between scheduled updates */
   struct timeval sweep_interval; /* interval between route table sweeps */
 };
@@ -132,6 +134,8 @@ TRPC_INSTANCE *trpc_remove(TRPC_INSTANCE *trpc, TRPC_INSTANCE *remove);
 void trpc_append(TRPC_INSTANCE *trpc, TRPC_INSTANCE *new);
 char *trpc_get_server(TRPC_INSTANCE *trpc);
 void trpc_set_server(TRPC_INSTANCE *trpc, char *server);
+TR_NAME *trpc_get_gssname(TRPC_INSTANCE *trpc);
+void trpc_set_gssname(TRPC_INSTANCE *trpc, TR_NAME *gssname);
 unsigned int trpc_get_port(TRPC_INSTANCE *trpc);
 void trpc_set_port(TRPC_INSTANCE *trpc, unsigned int port);
 DH *trpc_get_dh(TRPC_INSTANCE *trpc);
@@ -148,11 +152,14 @@ TRP_RC trpc_send_msg(TRPC_INSTANCE *trpc, const char *msg_content);
 
 TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx);
 void trps_free (TRPS_INSTANCE *trps);
+void trps_set_connect_interval(TRPS_INSTANCE *trps, unsigned int interval);
+unsigned int trps_get_connect_interval(TRPS_INSTANCE *trps);
 void trps_set_update_interval(TRPS_INSTANCE *trps, unsigned int interval);
 unsigned int trps_get_update_interval(TRPS_INSTANCE *trps);
 void trps_set_sweep_interval(TRPS_INSTANCE *trps, unsigned int interval);
 unsigned int trps_get_sweep_interval(TRPS_INSTANCE *trps);
-TRP_RC trps_send_msg (TRPS_INSTANCE *trps, TR_NAME *peer_gssname, const char *msg);
+TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TRP_PEER *peer);
+TRP_RC trps_send_msg (TRPS_INSTANCE *trps, TRP_PEER *peer, const char *msg);
 void trps_add_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *new);
 void trps_remove_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *remove);
 void trps_add_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *trpc);
index 23d729d..ec14824 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _TRP_PTABLE_H_
 #define _TRP_PTABLE_H_
 
+#include <time.h>
 #include <talloc.h>
 
 #include <trust_router/tr_name.h>
@@ -8,10 +9,11 @@
 
 typedef struct trp_peer TRP_PEER;
 struct trp_peer {
+  TRP_PEER *next; /* for making a linked list */
   char *server;
   unsigned int port;
   unsigned int linkcost;
-  TRP_PEER *next; /* for making a linked list */
+  struct timespec last_conn_attempt;
 };
 
 typedef struct trp_ptable {
@@ -41,6 +43,8 @@ TR_NAME *trp_peer_get_gssname(TRP_PEER *peer);
 unsigned int trp_peer_get_port(TRP_PEER *peer);
 void trp_peer_set_port(TRP_PEER *peer, unsigned int port);
 unsigned int trp_peer_get_linkcost(TRP_PEER *peer);
+struct timespec *trp_peer_get_last_conn_attempt(TRP_PEER *peer);
+void trp_peer_set_last_conn_attempt(TRP_PEER *peer, struct timespec *time);
 void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost);
 char *trp_peer_to_str(TALLOC_CTX *memctx, TRP_PEER *peer, const char *sep);
 
index 2cf60e3..e9ebd6f 100644 (file)
@@ -42,16 +42,21 @@ TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx);
 void trp_rentry_free(TRP_RENTRY *entry);
 void trp_rentry_set_apc(TRP_RENTRY *entry, TR_NAME *apc);
 TR_NAME *trp_rentry_get_apc(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_apc(TRP_RENTRY *entry);
 void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm);
 TR_NAME *trp_rentry_get_realm(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_realm(TRP_RENTRY *entry);
 void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr);
 TR_NAME *trp_rentry_get_trust_router(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_trust_router(TRP_RENTRY *entry);
 void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer);
 TR_NAME *trp_rentry_get_peer(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_peer(TRP_RENTRY *entry);
 void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric);
 unsigned int trp_rentry_get_metric(TRP_RENTRY *entry);
 void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop);
 TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_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);
index a267fd1..f1032a2 100644 (file)
@@ -20,6 +20,7 @@ typedef enum trp_rc {
   TRP_BADTYPE, /* typing error */
   TRP_UNSUPPORTED, /* unsupported feature */
   TRP_BADARG, /* bad argument */
+  TRP_CLOCKERR, /* error reading time */
 } TRP_RC;
 
 typedef enum trp_inforec_type {
@@ -48,12 +49,16 @@ void trp_inforec_set_next(TRP_INFOREC *rec, TRP_INFOREC *next_rec);
 TR_EXPORT TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec);
 void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type);
 TR_EXPORT TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_comm(TRP_INFOREC *rec);
 TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm);
 TR_EXPORT TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_realm(TRP_INFOREC *rec);
 TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm);
 TR_EXPORT TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec);
 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router);
 TR_EXPORT TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec);
 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop);
 TR_EXPORT unsigned int trp_inforec_get_metric(TRP_INFOREC *rec);
 TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric);
index ff5eb77..e6ec7ec 100644 (file)
@@ -195,6 +195,11 @@ int tr_read_and_apply_config(TR_CFGWATCH *cfgwatch)
     retval=1; goto cleanup;
   }
 
+  /* call callback to notify system of new configuration */
+  tr_debug("tr_read_and_apply_config: calling update callback function.");
+  if (cfgwatch->update_cb!=NULL)
+    cfgwatch->update_cb(cfgwatch->cfg_mgr->active, cfgwatch->update_cookie);
+
   /* give ownership of the new_fstat_list to caller's context */
   if (cfgwatch->fstat_list != NULL) {
     /* free the old one */
@@ -236,11 +241,8 @@ static void tr_cfgwatch_event_cb(int listener, short event, void *arg)
       tr_notice("Configuration file change settled, attempting to update configuration.");
       if (0 != tr_read_and_apply_config(cfg_status))
         tr_warning("Configuration file update failed. Using previous configuration.");
-      else {
-        if (cfg_status->update_cb!=NULL)
-          cfg_status->update_cb(cfg_status->cfg_mgr->active, cfg_status->update_cookie);
+      else
         tr_notice("Configuration updated successfully.");
-      }
       cfg_status->change_detected=0;
     }
   }
index 411ee04..2df7ff5 100644 (file)
@@ -211,6 +211,18 @@ int main(int argc, char *argv[])
     return 1;
   }
 
+  /***** initialize the trust path query server instance *****/
+  if (NULL == (tr->tids = tids_create (tr))) {
+    tr_crit("Error initializing Trust Path Query Server instance.");
+    return 1;
+  }
+
+  /***** initialize the trust router protocol server instance *****/
+  if (NULL == (tr->trps = trps_new(tr))) {
+    tr_crit("Error initializing Trust Router Protocol Server instance.");
+    return 1;
+  }
+
   /***** process configuration *****/
   tr->cfgwatch=tr_cfgwatch_create(tr);
   if (tr->cfgwatch == NULL) {
@@ -219,24 +231,12 @@ int main(int argc, char *argv[])
   }
   tr->cfgwatch->config_dir=opts.config_dir;
   tr->cfgwatch->cfg_mgr=tr->cfg_mgr;
+  tr->cfgwatch->update_cb=tr_config_changed; /* handle configuration changes */
+  tr->cfgwatch->update_cookie=(void *)(tr->trps);
   if (0 != tr_read_and_apply_config(tr->cfgwatch)) {
     tr_crit("Error reading configuration, exiting.");
     return 1;
   }
-  tr->cfgwatch->update_cb=tr_config_changed; /* handle configuration changes */
-  tr->cfgwatch->update_cookie=(void *)tr;
-
-  /***** initialize the trust path query server instance *****/
-  if (NULL == (tr->tids = tids_create (tr))) {
-    tr_crit("Error initializing Trust Path Query Server instance.");
-    return 1;
-  }
-
-  /***** initialize the trust router protocol server instance *****/
-  if (NULL == (tr->trps = trps_new(tr))) {
-    tr_crit("Error initializing Trust Router Protocol Server instance.");
-    return 1;
-  }
 
   /***** Set up the event loop *****/
   ev_base=tr_event_loop_init(); /* Set up the event loop */
index db66571..67a5c88 100644 (file)
@@ -6,10 +6,13 @@
 #include <unistd.h>
 #include <string.h>
 #include <sys/time.h>
+#include <time.h>
 
 #include <gsscon.h>
 #include <tr_rp.h>
 #include <trp_internal.h>
+#include <trp_ptable.h>
+#include <trp_rtable.h>
 #include <tr_config.h>
 #include <tr_event.h>
 #include <tr_msg.h>
@@ -149,11 +152,33 @@ static void tr_trps_event_cb(int listener, short event, void *arg)
   talloc_free(tmp_ctx);
 }
 
-static void tr_trps_cleanup_thread(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
+static void tr_trps_cleanup_conn(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
 {
   /* everything belonging to the thread is in the TRP_CONNECTION
    * associated with it */
   trps_remove_connection(trps, conn);
+  trp_connection_free(conn);
+  tr_debug("Deleted connection");
+}
+
+#if 0
+static void tr_trpc_abort(TRPC_INSTANCE *trpc)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TR_MQ_MSG *msg=tr_mq_msg_new(tmp_ctx, "trpc_abort");
+  tr_mq_msg_set_payload(msg, (void *)conn, NULL); /* do not pass a free routine */
+  trpc_mq_append(msg); /* gives msg over to the queue to manage */
+  
+}
+#endif
+
+static void tr_trps_cleanup_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *trpc)
+{
+  /* everything belonging to the thread is in the TRP_CONNECTION
+   * associated with it */
+/*  tr_trpc_abort(trpc); */ /* tell trpc to abort */
+  trps_remove_trpc(trps, trpc);
+  trpc_free(trpc);
   tr_debug("Deleted connection");
 }
 
@@ -178,10 +203,17 @@ static void tr_trps_process_mq(int socket, short event, void *arg)
   while (msg!=NULL) {
     s=tr_mq_msg_get_message(msg);
     if (0==strcmp(s, "trps_thread_exit")) {
-      tr_trps_cleanup_thread(trps,
-                             talloc_get_type_abort(tr_mq_msg_get_payload(msg),
-                                                   TRP_CONNECTION));
+      tr_trps_cleanup_conn(trps,
+                           talloc_get_type_abort(tr_mq_msg_get_payload(msg),
+                                                 TRP_CONNECTION));
     }
+    else if (0==strcmp(s, "trpc_thread_exit")) {
+      /* trpc connection died */
+      tr_trps_cleanup_trpc(trps,
+                           talloc_get_type_abort(tr_mq_msg_get_payload(msg),
+                                                 TRPC_INSTANCE));
+    }
+
     else if (0==strcmp(s, "tr_msg")) {
       if (trps_handle_tr_msg(trps, tr_mq_msg_get_payload(msg))!=TRP_SUCCESS)
         tr_notice("tr_trps_process_mq: error handling message.");
@@ -214,17 +246,33 @@ static void tr_trps_sweep(int listener, short event, void *arg)
   TRPS_INSTANCE *trps=cookie->trps;
   struct event *ev=cookie->ev;
 
-  tr_debug("tr_trps_sweep: sweeping routes");
+  tr_debug("tr_trps_sweep: sweeping routes.");
   trps_sweep_routes(trps);
   /* schedule the event to run again */
   event_add(ev, &(trps->sweep_interval));
 }
 
+static void tr_connection_update(int listener, short event, void *arg)
+{
+  struct tr_trps_event_cookie *cookie=talloc_get_type_abort(arg, struct tr_trps_event_cookie);
+  TRPS_INSTANCE *trps=cookie->trps;
+  struct event *ev=cookie->ev;
+
+  tr_debug("tr_connection_update: checking peer connections.");
+  tr_connect_to_peers(trps);
+  /* schedule the event to run again */
+  event_add(ev, &(trps->connect_interval));
+}
+
 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->connect_ev!=NULL)
+    event_free(ev->connect_ev);
+  if (ev->update_ev!=NULL)
+    event_free(ev->update_ev);
   if (ev->sweep_ev!=NULL)
     event_free(ev->sweep_ev);
   return 0;
@@ -235,6 +283,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->connect_ev=NULL;
     ev->update_ev=NULL;
     ev->sweep_ev=NULL;
     if (ev->listen_ev==NULL) {
@@ -256,6 +305,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 *trps_cookie=NULL;
+  struct tr_trps_event_cookie *connection_cookie=NULL;
   struct tr_trps_event_cookie *update_cookie=NULL;
   struct tr_trps_event_cookie *sweep_cookie=NULL;
   TRP_RC retval=TRP_ERROR;
@@ -312,6 +362,20 @@ 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 peer connection timer event */
+  connection_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  if (connection_cookie == NULL) {
+    tr_debug("tr_trps_event_init: Unable to allocate connection_cookie.");
+    retval=TRP_NOMEM;
+    goto cleanup;
+  }
+  connection_cookie->trps=trps;
+  connection_cookie->cfg_mgr=cfg_mgr;
+  talloc_steal(trps, connection_cookie);
+  trps_ev->connect_ev=event_new(base, -1, EV_TIMEOUT, tr_connection_update, (void *)connection_cookie);
+  connection_cookie->ev=trps_ev->connect_ev; /* in case it needs to frob the event */
+  event_add(trps_ev->connect_ev, &(trps->connect_interval));
+
   /* now set up the route update timer event */
   update_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
   if (update_cookie == NULL) {
@@ -451,7 +515,7 @@ static void *tr_trpc_thread(void *arg)
 }
 
 /* starts a trpc thread to connect to server:port */
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigned int port)
+TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TRPC_INSTANCE *trpc=NULL;
@@ -472,8 +536,9 @@ TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigne
     goto cleanup;
   }
   trpc_set_conn(trpc, conn);
-  trpc_set_server(trpc, talloc_strdup(trpc, server));
-  trpc_set_port(trpc, port);
+  trpc_set_server(trpc, talloc_strdup(trpc, trp_peer_get_server(peer)));
+  trpc_set_port(trpc, trp_peer_get_port(peer));
+  trpc_set_gssname(trpc, trp_peer_get_gssname(peer));
   tr_debug("tr_trpc_initiate: allocated connection");
   
   /* start thread */
@@ -491,19 +556,68 @@ TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigne
   tr_debug("tr_trpc_initiate: started trpc thread");
   trps_add_trpc(trps, trpc);
 
-  talloc_report_full(trps, stderr);
-  talloc_report_full(tmp_ctx, stderr);
-
  cleanup:
   talloc_free(tmp_ctx);
   return trpc;
 }
 
+/* decide how often to attempt to connect to a peer */
+static int tr_conn_attempt_due(TRPS_INSTANCE *trps, TRP_PEER *peer, struct timespec *when)
+{
+  return 1; /* currently make an attempt every cycle */
+}
+
+/* open missing connections to peers */
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps)
+{
+  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+  TRP_PTABLE_ITER *iter=trp_ptable_iter_new(tmp_ctx);
+  TRP_PEER *peer=NULL;
+  TRPC_INSTANCE *trpc=NULL;
+  struct timespec curtime={0,0};
+  TRP_RC rc=TRP_ERROR;
+
+  if (clock_gettime(CLOCK_REALTIME, &curtime)) {
+    tr_err("tr_connect_to_peers: failed to read time.");
+    rc=TRP_CLOCKERR;
+    goto cleanup;
+  }
+
+  for (peer=trp_ptable_iter_first(iter, trps->ptable);
+       peer!=NULL;
+       peer=trp_ptable_iter_next(iter))
+  {
+    if (trps_find_trpc(trps, peer)==NULL) {
+      tr_debug("tr_connect_to_peers: %.*s missing connection.",
+               trp_peer_get_gssname(peer)->len, trp_peer_get_gssname(peer)->buf);
+      /* has it been long enough since we last tried? */
+      if (tr_conn_attempt_due(trps, peer, &curtime)) {
+        trp_peer_set_last_conn_attempt(peer, &curtime); /* we are trying again now */
+        trpc=tr_trpc_initiate(trps, peer);
+        if (trpc==NULL) {
+          tr_err("tr_connect_to_peers: unable to initiate TRP connection to %s:%u.",
+                 trp_peer_get_server(peer),
+                 trp_peer_get_port(peer));
+        }
+      }
+    }
+  }
+  rc=TRP_SUCCESS;
+    
+cleanup:
+  trp_ptable_iter_free(iter);
+  talloc_free(tmp_ctx);
+  return rc;
+}
+
+
 /* Called by the config manager after a change to the active configuration.
  * Updates configuration of objects that do not know about the config manager. */
 void tr_config_changed(TR_CFG *new_cfg, void *cookie)
 {
   TRPS_INSTANCE *trps=talloc_get_type_abort(cookie, TRPS_INSTANCE);
-  trps_set_update_interval(trps, new_cfg->internal->route_update_interval);
-  trps_set_sweep_interval(trps, new_cfg->internal->route_sweep_interval);
+  trps_set_connect_interval(trps, new_cfg->internal->trp_connect_interval);
+  trps_set_update_interval(trps, new_cfg->internal->trp_update_interval);
+  trps_set_sweep_interval(trps, new_cfg->internal->trp_sweep_interval);
 }
+
index 53b0a0d..dc3c961 100644 (file)
@@ -224,6 +224,7 @@ TRP_CONNECTION *trp_connection_new(TALLOC_CTX *mem_ctx)
     trp_connection_set_gssname(new_conn, NULL);
     trp_connection_mutex_init(new_conn);
     trp_connection_set_status(new_conn, TRP_CONNECTION_DOWN);
+    new_conn->peer=NULL; /* no true set function for this */
     thread=talloc(new_conn, pthread_t);
     gssctx=talloc(new_conn, gss_ctx_id_t);
     if (gssctx==NULL) {
@@ -334,12 +335,12 @@ TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, char *server, unsigned int
                        "trustrouter",
                       &fd,
                        trp_connection_get_gssctx(conn));
-  tr_debug("trp_connection_initiate: connected");
-
   if (err) {
+    tr_debug("trp_connection_initiate: connection failed.");
     talloc_free(conn);
     return TRP_ERROR;
   } else {
+    tr_debug("trp_connection_initiate: connected.");
     trp_connection_set_fd(conn, fd);
     trp_connection_set_peer(conn);
     trp_connection_set_status(conn, TRP_CONNECTION_UP);
index 8355a8b..4a276d5 100644 (file)
@@ -1,3 +1,4 @@
+#include <time.h>
 #include <talloc.h>
 
 #include <trust_router/tr_name.h>
@@ -9,10 +10,11 @@ TRP_PEER *trp_peer_new(TALLOC_CTX *memctx)
 {
   TRP_PEER *peer=talloc(memctx, TRP_PEER);
   if (peer!=NULL) {
+    peer->next=NULL;
     peer->server=NULL;
     peer->port=0;
     peer->linkcost=TRP_METRIC_INFINITY;
-    peer->next=NULL;
+    peer->last_conn_attempt=(struct timespec){0,0};
   }
   return peer;
 }
@@ -68,7 +70,10 @@ void trp_peer_set_port(TRP_PEER *peer, unsigned int port)
 
 unsigned int trp_peer_get_linkcost(TRP_PEER *peer)
 {
-  return peer->linkcost;
+  if (peer!=NULL)
+    return peer->linkcost;
+  else
+    return 1;
 }
 
 void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost)
@@ -82,6 +87,16 @@ void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost)
   peer->linkcost=linkcost;
 }
 
+struct timespec *trp_peer_get_last_conn_attempt(TRP_PEER *peer)
+{
+  return &(peer->last_conn_attempt);
+}
+
+void trp_peer_set_last_conn_attempt(TRP_PEER *peer, struct timespec *time)
+{
+  peer->last_conn_attempt=*time;
+}
+
 TRP_PTABLE *trp_ptable_new(TALLOC_CTX *memctx)
 {
   TRP_PTABLE *ptbl=talloc(memctx, TRP_PTABLE);
@@ -185,8 +200,7 @@ TRP_PEER *trp_ptable_iter_first(TRP_PTABLE_ITER *iter, TRP_PTABLE *ptbl)
 
 TRP_PEER *trp_ptable_iter_next(TRP_PTABLE_ITER *iter)
 {
-  if ((*iter)->next!=NULL)
-    *iter=(*iter)->next;
+  *iter=(*iter)->next;
   return *iter;
 }
 
index 20caef7..6fbbd6f 100644 (file)
@@ -64,6 +64,11 @@ TR_NAME *trp_rentry_get_apc(TRP_RENTRY *entry)
   return entry->apc;
 }
 
+TR_NAME *trp_rentry_dup_apc(TRP_RENTRY *entry)
+{
+  return tr_dup_name(trp_rentry_get_apc(entry));
+}
+
 void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm)
 {
   entry->realm=realm;
@@ -74,6 +79,11 @@ TR_NAME *trp_rentry_get_realm(TRP_RENTRY *entry)
   return entry->realm;
 }
 
+TR_NAME *trp_rentry_dup_realm(TRP_RENTRY *entry)
+{
+  return tr_dup_name(trp_rentry_get_realm(entry));
+}
+
 void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr)
 {
   entry->trust_router=tr;
@@ -84,6 +94,11 @@ TR_NAME *trp_rentry_get_trust_router(TRP_RENTRY *entry)
   return entry->trust_router;
 }
 
+TR_NAME *trp_rentry_dup_trust_router(TRP_RENTRY *entry)
+{
+  return tr_dup_name(trp_rentry_get_trust_router(entry));
+}
+
 void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer)
 {
   entry->peer=peer;
@@ -94,6 +109,11 @@ TR_NAME *trp_rentry_get_peer(TRP_RENTRY *entry)
   return entry->peer;
 }
 
+TR_NAME *trp_rentry_dup_peer(TRP_RENTRY *entry)
+{
+  return tr_dup_name(trp_rentry_get_peer(entry));
+}
+
 void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric)
 {
   entry->metric=metric;
@@ -114,6 +134,11 @@ TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry)
   return entry->next_hop;
 }
 
+TR_NAME *trp_rentry_dup_next_hop(TRP_RENTRY *entry)
+{
+  return tr_dup_name(trp_rentry_get_next_hop(entry));
+}
+
 void trp_rentry_set_selected(TRP_RENTRY *entry, int sel)
 {
   entry->selected=sel;
index ec829ec..4ef9d41 100644 (file)
@@ -111,7 +111,7 @@ TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec)
 
 static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
 {
-  while (rec!=NULL)
+  while ((rec->next)!=NULL)
     rec=trp_inforec_get_next(rec);
   return rec;
 }
@@ -149,6 +149,11 @@ TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec)
   return NULL;
 }
 
+TR_NAME *trp_inforec_dup_comm(TRP_INFOREC *rec)
+{
+  return tr_dup_name(trp_inforec_get_comm(rec));
+}
+
 TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm)
 {
   switch (rec->type) {
@@ -177,6 +182,11 @@ TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec)
   return NULL;
 }
 
+TR_NAME *trp_inforec_dup_realm(TRP_INFOREC *rec)
+{
+  return tr_dup_name(trp_inforec_get_realm(rec));
+}
+
 TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm)
 {
   switch (rec->type) {
@@ -205,6 +215,11 @@ TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec)
   return NULL;
 }
 
+TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
+{
+  return tr_dup_name(trp_inforec_get_trust_router(rec));
+}
+
 TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
 {
   switch (rec->type) {
@@ -233,6 +248,11 @@ TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec)
   return NULL;
 }
 
+TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
+{
+  return tr_dup_name(trp_inforec_get_next_hop(rec));
+}
+
 TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
 {
   switch (rec->type) {
@@ -387,6 +407,7 @@ void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
 
 void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
 {
+  tr_debug("trp_upd_add_inforec: adding record.");
   if (upd->records==NULL)
     upd->records=rec;
   else
index 4913455..9fd079f 100644 (file)
@@ -8,6 +8,13 @@
 #include <tr_debug.h>
 #include <trp_internal.h>
 
+static int trpc_destructor(void *object)
+{
+  TRPC_INSTANCE *trpc=talloc_get_type_abort(object, TRPC_INSTANCE);
+  if (trpc->gssname!=NULL)
+    tr_free_name(trpc->gssname);
+  return 0;
+}
 
 /* also allocates the incoming mq */
 TRPC_INSTANCE *trpc_new (TALLOC_CTX *mem_ctx)
@@ -23,7 +30,9 @@ TRPC_INSTANCE *trpc_new (TALLOC_CTX *mem_ctx)
     if (trpc->mq==NULL) {
       talloc_free(trpc);
       trpc=NULL;
-    }
+    } else
+      talloc_set_destructor((void *)trpc, trpc_destructor);
+    
   }
   return trpc;
 }
@@ -95,6 +104,17 @@ void trpc_set_server(TRPC_INSTANCE *trpc, char *server)
   trpc->server=server;
 }
 
+TR_NAME *trpc_get_gssname(TRPC_INSTANCE *trpc)
+{
+  return trpc->gssname;
+}
+
+/* takes responsibility for freeing gssname */
+void trpc_set_gssname(TRPC_INSTANCE *trpc, TR_NAME *gssname)
+{
+  trpc->gssname=gssname;
+}
+
 unsigned int trpc_get_port(TRPC_INSTANCE *trpc)
 {
   return trpc->port;
index 6bddc66..ae177eb 100644 (file)
@@ -75,6 +75,17 @@ void trps_mq_append(TRPS_INSTANCE *trps, TR_MQ_MSG *msg)
   tr_mq_append(trps->mq, msg);
 }
 
+unsigned int trps_get_connect_interval(TRPS_INSTANCE *trps)
+{
+  return trps->connect_interval.tv_sec;
+}
+
+void trps_set_connect_interval(TRPS_INSTANCE *trps, unsigned int interval)
+{
+  trps->connect_interval.tv_sec=interval;
+  trps->connect_interval.tv_usec=0;
+}
+
 unsigned int trps_get_update_interval(TRPS_INSTANCE *trps)
 {
   return trps->update_interval.tv_sec;
@@ -97,15 +108,19 @@ void trps_set_sweep_interval(TRPS_INSTANCE *trps, unsigned int interval)
   trps->sweep_interval.tv_usec=0;
 }
 
-static TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TR_NAME *peer_gssname)
+TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TRP_PEER *peer)
 {
   TRPC_INSTANCE *cur=NULL;
+  TR_NAME *name=NULL;
+  TR_NAME *peer_gssname=trp_peer_get_gssname(peer);
+
   for (cur=trps->trpc; cur!=NULL; cur=trpc_get_next(cur)) {
-    if (0==tr_name_cmp(peer_gssname,
-                       trp_connection_get_gssname(trpc_get_conn(cur)))) {
+    name=trpc_get_gssname(cur);
+    if ((name!=NULL) && (0==tr_name_cmp(peer_gssname, name))) {
       break;
     }
   }
+  tr_free_name(peer_gssname);
   return cur;
 }
 
@@ -143,7 +158,7 @@ void trps_remove_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *remove)
   trps->trpc=trpc_remove(trps->trpc, remove);
 }
 
-TRP_RC trps_send_msg(TRPS_INSTANCE *trps, TR_NAME *peer_gssname, const char *msg)
+TRP_RC trps_send_msg(TRPS_INSTANCE *trps, TRP_PEER *peer, const char *msg)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_MQ_MSG *mq_msg=NULL;
@@ -152,7 +167,7 @@ TRP_RC trps_send_msg(TRPS_INSTANCE *trps, TR_NAME *peer_gssname, const char *msg
   TRPC_INSTANCE *trpc=NULL;
 
   /* get the connection for this peer */
-  trpc=trps_find_trpc(trps, peer_gssname);
+  trpc=trps_find_trpc(trps, peer);
   if ((trpc==NULL) || (trpc_get_status(trps->trpc)!=TRP_CONNECTION_UP)) {
     /* We could just let these sit on the queue in the hopes that a connection
      * is eventually established. However, we'd then have to ensure the queue
@@ -403,8 +418,8 @@ static TRP_RC trps_validate_inforec(TRPS_INSTANCE *trps, TRP_INFOREC *rec)
     }
 
     /* check for valid metric */
-    if (trp_metric_is_valid(trp_inforec_get_metric(rec))) {
-      tr_debug("trps_validate_inforec: invalid metric.");
+    if (trp_metric_is_invalid(trp_inforec_get_metric(rec))) {
+      tr_debug("trps_validate_inforec: invalid metric (%u).", trp_inforec_get_metric(rec));
       return TRP_ERROR;
     }
 
@@ -766,6 +781,7 @@ static TRP_RENTRY **trps_select_updates_for_peer(TALLOC_CTX *memctx, TRPS_INSTAN
   result=talloc_array(memctx, TRP_RENTRY *, trp_rtable_size(trps->rtable));
   if (result==NULL) {
     talloc_free(apc);
+    *n_update=0;
     return NULL;
   }
   
@@ -800,9 +816,9 @@ static TRP_INFOREC *trps_rentry_to_inforec(TALLOC_CTX *mem_ctx, TRPS_INSTANCE *t
 
     /* Note that we leave the next hop empty since the recipient fills that in.
      * This is where we add the link cost (currently always 1) to the next peer. */
-    if ((trp_inforec_set_comm(rec, trp_rentry_get_apc(entry)) != TRP_SUCCESS)
-       ||(trp_inforec_set_realm(rec, trp_rentry_get_realm(entry)) != TRP_SUCCESS)
-       ||(trp_inforec_set_trust_router(rec, trp_rentry_get_trust_router(entry)) != TRP_SUCCESS)
+    if ((trp_inforec_set_comm(rec, trp_rentry_dup_apc(entry)) != TRP_SUCCESS)
+       ||(trp_inforec_set_realm(rec, trp_rentry_dup_realm(entry)) != TRP_SUCCESS)
+       ||(trp_inforec_set_trust_router(rec, trp_rentry_dup_trust_router(entry)) != TRP_SUCCESS)
        ||(trp_inforec_set_metric(rec, trp_rentry_get_metric(entry)+linkcost) != TRP_SUCCESS)
        ||(trp_inforec_set_interval(rec, trps_get_update_interval(trps)) != TRP_SUCCESS)) {
       tr_err("trps_rentry_to_inforec: error creating route update.");
@@ -825,6 +841,7 @@ TRP_RC trps_scheduled_update(TRPS_INSTANCE *trps)
   size_t n_updates=0, ii=0;
   char *encoded=NULL;
   TRP_RC rc=TRP_ERROR;
+  TR_NAME *peer_gssname=NULL;
 
   if (iter==NULL) {
     tr_err("trps_scheduled_update: failed to allocate peer table iterator.");
@@ -836,44 +853,48 @@ TRP_RC trps_scheduled_update(TRPS_INSTANCE *trps)
        peer!=NULL;
        peer=trp_ptable_iter_next(iter))
   {
-    tr_debug("trps_scheduled_update: preparing scheduled route update for %.*%s",
-             trp_peer_get_gssname(peer)->len, trp_peer_get_gssname(peer)->buf);
-    upd=trp_upd_new(tmp_ctx);
+    peer_gssname=trp_peer_get_gssname(peer);
+    tr_debug("trps_scheduled_update: preparing scheduled route update for %.*s",
+             peer_gssname->len, peer_gssname->buf);
     /* do not fill in peer, recipient does that */
-    update_list=trps_select_updates_for_peer(tmp_ctx, trps, trp_peer_get_gssname(peer), &n_updates);
-    for (ii=0; ii<n_updates; ii++) {
-      rec=trps_rentry_to_inforec(tmp_ctx, trps, update_list[ii]);
-      if (rec==NULL) {
-        tr_err("trps_scheduled_update: could not create all update records.");
+    update_list=trps_select_updates_for_peer(tmp_ctx, trps, peer_gssname, &n_updates);
+    tr_free_name(peer_gssname); peer_gssname=NULL;
+    if ((n_updates>0) && (update_list!=NULL)) {
+      tr_debug("trps_scheduled_update: sending %u update records.", (unsigned int)n_updates);
+      upd=trp_upd_new(tmp_ctx);
+
+      for (ii=0; ii<n_updates; ii++) {
+        rec=trps_rentry_to_inforec(tmp_ctx, trps, update_list[ii]);
+        if (rec==NULL) {
+          tr_err("trps_scheduled_update: could not create all update records.");
+          rc=TRP_ERROR;
+          goto cleanup;
+        }
+        trp_upd_add_inforec(upd, rec);
+      }
+      talloc_free(update_list);
+      update_list=NULL;
+
+      /* now encode the update message */
+      tr_msg_set_trp_upd(&msg, upd);
+      encoded=tr_msg_encode(&msg);
+      if (encoded==NULL) {
+        tr_err("trps_scheduled_update: error encoding update.");
         rc=TRP_ERROR;
         goto cleanup;
       }
-      trp_upd_add_inforec(upd, rec);
-    }
-    talloc_free(update_list);
-    update_list=NULL;
-
-    /* now encode the update message */
-    tr_msg_set_trp_upd(&msg, upd);
-    encoded=tr_msg_encode(&msg);
-    if (encoded==NULL) {
-      tr_err("trps_scheduled_update: error encoding update.");
-      rc=TRP_ERROR;
-      goto cleanup;
-    }
-    tr_debug("trps_scheduled_update: adding message to queue.");
-    if (trps_send_msg(trps, trp_peer_get_gssname(peer), encoded) != TRP_SUCCESS) {
-      tr_err("trps_scheduled_update: error queueing update.");
-      rc=TRP_ERROR;
-      tr_msg_free_encoded(encoded);
+
+      tr_debug("trps_scheduled_update: adding message to queue.");
+      if (trps_send_msg(trps, peer, encoded) != TRP_SUCCESS)
+        tr_err("trps_scheduled_update: error queueing update.");
+      else
+        tr_debug("trps_scheduled_update: update queued successfully.");
+
       encoded=NULL;
-      goto cleanup;
+      tr_msg_free_encoded(encoded);
+      trp_upd_free(upd);
+      upd=NULL;
     }
-    tr_debug("trps_scheduled_update: message queued successfully.");
-    tr_msg_free_encoded(encoded);
-    encoded=NULL;
-    trp_upd_free(upd);
-    upd=NULL;
   }
   
 cleanup: