Fix memory freeing bugs. Seems stable, even through loss of connections.
authorJennifer Richards <jennifer@painless-security.com>
Tue, 2 Aug 2016 15:29:12 +0000 (11:29 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Tue, 2 Aug 2016 15:29:12 +0000 (11:29 -0400)
18 files changed:
common/tr_config.c
common/tr_name.c
include/tr.h
include/tr_cfgwatch.h
include/tr_config.h
include/tr_trp.h
include/trp_internal.h
include/trp_rtable.h
include/trust_router/trp.h
tr/tr.c
tr/tr_main.c
tr/tr_trp.c
tr/trpc_main.c
trp/trp_conn.c
trp/trp_ptable.c
trp/trp_rtable.c
trp/trpc.c
trp/trps.c

index 4d05d4b..514a300 100644 (file)
 #include <dirent.h>
 #include <talloc.h>
 
+#include <tr_cfgwatch.h>
 #include <tr_config.h>
 #include <tr_debug.h>
-#include <tr.h>
 #include <tr_filter.h>
 #include <trust_router/tr_constraint.h>
+#include <tr.h>
 
 void tr_print_config (FILE *stream, TR_CFG *cfg) {
   fprintf(stream, "tr_print_config: Not yet implemented.");
@@ -157,14 +158,19 @@ static TR_CFG_RC tr_cfg_parse_internal (TR_CFG *trc, json_t *jcfg) {
        tr_debug("tr_cfg_parse_internal: Parsing error, cfg_poll_interval is not a number.");
        return TR_CFG_NOPARSE;
       }
+    } else {
+      trc->internal->cfg_poll_interval = TR_CFGWATCH_DEFAULT_POLL;
     }
-    if (NULL != (jcfgsettle = json_object_get(jint, "cfg_settle_count"))) {
+
+    if (NULL != (jcfgsettle = json_object_get(jint, "cfg_settling_time"))) {
       if (json_is_number(jcfgsettle)) {
-       trc->internal->cfg_settle_count = json_integer_value(jcfgsettle);
+       trc->internal->cfg_settling_time = json_integer_value(jcfgsettle);
       } else {
-       tr_debug("tr_cfg_parse_internal: Parsing error, cfg_settle_count is not a number.");
+       tr_debug("tr_cfg_parse_internal: Parsing error, cfg_settling_time is not a number.");
        return TR_CFG_NOPARSE;
       }
+    } else {
+      trc->internal->cfg_settling_time = TR_CFGWATCH_DEFAULT_SETTLE;
     }
 
     if (NULL != (jrouteconnect = json_object_get(jint, "trp_connect_interval"))) {
index 41cad47..e048731 100644 (file)
@@ -55,6 +55,9 @@ TR_NAME *tr_new_name (char *name)
     new->len = strlen(name);
     if (new->buf = malloc((new->len)+1)) {
       strcpy(new->buf, name);
+    } else {
+      free(new);
+      new=NULL;
     }
   }
   return new;
@@ -120,4 +123,3 @@ char * tr_name_strdup(TR_NAME *src)
   return s;
 }
 
-  
index 8878161..bd55176 100644 (file)
 #include <tr_cfgwatch.h>
 #include <tr_config.h>
 
-typedef struct tr_instance {
-  TR_CFG_MGR *cfg_mgr;
-  TIDS_INSTANCE *tids;
-  TRPS_INSTANCE *trps;
-  TR_CFGWATCH *cfgwatch;
-} TR_INSTANCE;
+/* struct defined in tr_trp.h */
+typedef struct tr_instance TR_INSTANCE;
 
 TR_INSTANCE *tr_create(TALLOC_CTX *mem_ctx);
 void tr_destroy(TR_INSTANCE *tr);
index b8a873e..3d26048 100644 (file)
@@ -5,6 +5,12 @@
 #include <time.h>
 #include <sys/time.h>
 
+#include <tr_config.h>
+#include <tr_event.h>
+/* interval in seconds */
+#define TR_CFGWATCH_DEFAULT_POLL 1
+#define TR_CFGWATCH_DEFAULT_SETTLE 5
+/* note: settling time is minimum - only checked on poll intervals */
 
 struct tr_fstat {
   char *name;
index 626b20b..448e3e4 100644 (file)
@@ -71,7 +71,7 @@ typedef struct tr_cfg_internal {
   int log_threshold;
   int console_threshold;
   unsigned int cfg_poll_interval;
-  unsigned int cfg_settle_count;
+  unsigned int cfg_settling_time;
   unsigned int trp_sweep_interval;
   unsigned int trp_update_interval;
   unsigned int trp_connect_interval;
index 2e5e00d..bb055fc 100644 (file)
@@ -5,11 +5,14 @@
 #include <talloc.h>
 #include <pthread.h>
 
+#include <tr.h>
 #include <trp_internal.h>
 #include <tr_config.h>
+#include <tr_cfgwatch.h>
 #include <tr_event.h>
 
 typedef struct tr_trps_events {
+  struct event *trps_ev;
   struct tr_socket_event *listen_ev;
   struct event *mq_ev;
   struct event *connect_ev;
@@ -17,7 +20,17 @@ typedef struct tr_trps_events {
   struct event *sweep_ev;
 } TR_TRPS_EVENTS;
 
+/* typedef'ed as TR_INSTANCE in tr.h */
+struct tr_instance {
+  TR_CFG_MGR *cfg_mgr;
+  TIDS_INSTANCE *tids;
+  TRPS_INSTANCE *trps;
+  TR_CFGWATCH *cfgwatch;
+  TR_TRPS_EVENTS *events;
+};
+
 /* messages between threads */
+#define TR_MQMSG_MSG_RECEIVED "msg received"
 #define TR_MQMSG_TRPC_DISCONNECTED "trpc disconnected"
 #define TR_MQMSG_TRPC_CONNECTED "trpc connected"
 #define TR_MQMSG_TRPS_DISCONNECTED "trps disconnected"
@@ -25,11 +38,9 @@ typedef struct tr_trps_events {
 #define TR_MQMSG_ABORT "abort"
 
 /* prototypes */
-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);
+TRP_RC tr_trps_event_init(struct event_base *base, struct tr_instance *tr);
 TRP_RC tr_add_local_routes(TRPS_INSTANCE *trps, TR_CFG *cfg);
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer);
+TRP_RC 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 6bb827e..943e4cd 100644 (file)
@@ -5,7 +5,6 @@
 #include <talloc.h>
 
 #include <gsscon.h>
-#include <trust_router/tr_dh.h>
 #include <tr_mq.h>
 #include <tr_msg.h>
 #include <trp_ptable.h>
@@ -51,7 +50,9 @@ struct trp_req {
 typedef struct trps_instance TRPS_INSTANCE;
 
 typedef enum trp_connection_status {
-  TRP_CONNECTION_DOWN=0,
+  TRP_CONNECTION_CLOSED=0,
+  TRP_CONNECTION_DOWN,  
+  TRP_CONNECTION_AUTHORIZING,  
   TRP_CONNECTION_UP,
   TRP_CONNECTION_UNKNOWN,
 } TRP_CONNECTION_STATUS;
@@ -63,7 +64,7 @@ struct trp_connection {
   pthread_t *thread; /* thread servicing this connection */
   int fd;
   TR_NAME *gssname;
-  TR_NAME *peer;
+  TR_NAME *peer; /* TODO: why is there a peer and a gssname? jlr */
   gss_ctx_id_t *gssctx;
   TRP_CONNECTION_STATUS status;
   void (*status_change_cb)(TRP_CONNECTION *conn, void *cookie);
@@ -84,7 +85,6 @@ struct trpc_instance {
   unsigned int port;
   TRP_CONNECTION *conn;
   TR_MQ *mq; /* msgs from master to trpc */
-  DH *dh;                      /* Client's DH struct with priv and pub keys */
 };
 
 /* TRP Server Instance Data */
@@ -145,8 +145,6 @@ 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);
-void trpc_set_dh(TRPC_INSTANCE *trpc, DH *dh);
 TRP_CONNECTION_STATUS trpc_get_status(TRPC_INSTANCE *trpc);
 TR_MQ *trpc_get_mq(TRPC_INSTANCE *trpc);
 void trpc_set_mq(TRPC_INSTANCE *trpc, TR_MQ *mq);
@@ -184,11 +182,11 @@ void trps_mq_append(TRPS_INSTANCE *trps, TR_MQ_MSG *msg);
 void trps_handle_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *conn);
 TRP_RC trps_update_active_routes(TRPS_INSTANCE *trps);
 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);
+TRP_ROUTE *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer);
+TRP_ROUTE *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);
-TRP_RC trps_add_route(TRPS_INSTANCE *trps, TRP_RENTRY *route);
+TRP_RC trps_add_route(TRPS_INSTANCE *trps, TRP_ROUTE *route);
 TRP_RC trps_add_peer(TRPS_INSTANCE *trps, TRP_PEER *peer);
 TRP_PEER *trps_get_peer(TRPS_INSTANCE *trps, TR_NAME *gssname);
 TRP_RC trps_update(TRPS_INSTANCE *trps, TRP_UPDATE_TYPE type);
index 1dde034..7ccbfb3 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <trp_internal.h>
 
-typedef struct trp_rentry {
+typedef struct trp_route {
   TR_NAME *apc;
   TR_NAME *realm;
   TR_NAME *peer;
@@ -17,57 +17,60 @@ typedef struct trp_rentry {
   int selected;
   unsigned int interval; /* interval from route update */
   struct timespec *expiry;
+  int local; /* is this a local route? */
   int triggered;
-} TRP_RENTRY;
+} TRP_ROUTE;
 
 typedef GHashTable TRP_RTABLE;
 
 TRP_RTABLE *trp_rtable_new(void);
 void trp_rtable_free(TRP_RTABLE *rtbl);
-void trp_rtable_add(TRP_RTABLE *rtbl, TRP_RENTRY *entry); /* adds or updates */
-void trp_rtable_remove(TRP_RTABLE *rtbl, TRP_RENTRY *entry);
+void trp_rtable_add(TRP_RTABLE *rtbl, TRP_ROUTE *entry); /* adds or updates */
+void trp_rtable_remove(TRP_RTABLE *rtbl, TRP_ROUTE *entry);
 void trp_rtable_clear(TRP_RTABLE *rtbl);
 size_t trp_rtable_size(TRP_RTABLE *rtbl);
 size_t trp_rtable_apc_size(TRP_RTABLE *rtbl, TR_NAME *apc);
 size_t trp_rtable_realm_size(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm);
-TRP_RENTRY **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out);
+TRP_ROUTE **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out);
 TR_NAME **trp_rtable_get_apcs(TRP_RTABLE *rtbl, size_t *n_out);
-TRP_RENTRY **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out);
+TRP_ROUTE **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out);
 TR_NAME **trp_rtable_get_apc_realms(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out);
-TRP_RENTRY **trp_rtable_get_realm_entries(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out);
+TRP_ROUTE **trp_rtable_get_realm_entries(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out);
 TR_NAME **trp_rtable_get_apc_realm_peers(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out);
-TRP_RENTRY *trp_rtable_get_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, TR_NAME *peer);
-TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm);
+TRP_ROUTE *trp_rtable_get_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, TR_NAME *peer);
+TRP_ROUTE *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm);
 void trp_rtable_clear_triggered(TRP_RTABLE *rtbl);
 char *trp_rtable_to_str(TALLOC_CTX *mem_ctx, TRP_RTABLE *rtbl, const char *sep, const char *lineterm);
 
-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);
-int trp_rentry_get_interval(TRP_RENTRY *entry);
-void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp);
-struct timespec *trp_rentry_get_expiry(TRP_RENTRY *entry);
-void trp_rentry_set_triggered(TRP_RENTRY *entry, int trig);
-int trp_rentry_get_triggered(TRP_RENTRY *entry);
-char *trp_rentry_to_str(TALLOC_CTX *mem_ctx, TRP_RENTRY *entry, const char *sep);
+TRP_ROUTE *trp_route_new(TALLOC_CTX *mem_ctx);
+void trp_route_free(TRP_ROUTE *entry);
+void trp_route_set_apc(TRP_ROUTE *entry, TR_NAME *apc);
+TR_NAME *trp_route_get_apc(TRP_ROUTE *entry);
+TR_NAME *trp_route_dup_apc(TRP_ROUTE *entry);
+void trp_route_set_realm(TRP_ROUTE *entry, TR_NAME *realm);
+TR_NAME *trp_route_get_realm(TRP_ROUTE *entry);
+TR_NAME *trp_route_dup_realm(TRP_ROUTE *entry);
+void trp_route_set_trust_router(TRP_ROUTE *entry, TR_NAME *tr);
+TR_NAME *trp_route_get_trust_router(TRP_ROUTE *entry);
+TR_NAME *trp_route_dup_trust_router(TRP_ROUTE *entry);
+void trp_route_set_peer(TRP_ROUTE *entry, TR_NAME *peer);
+TR_NAME *trp_route_get_peer(TRP_ROUTE *entry);
+TR_NAME *trp_route_dup_peer(TRP_ROUTE *entry);
+void trp_route_set_metric(TRP_ROUTE *entry, unsigned int metric);
+unsigned int trp_route_get_metric(TRP_ROUTE *entry);
+void trp_route_set_next_hop(TRP_ROUTE *entry, TR_NAME *next_hop);
+TR_NAME *trp_route_get_next_hop(TRP_ROUTE *entry);
+TR_NAME *trp_route_dup_next_hop(TRP_ROUTE *entry);
+void trp_route_set_selected(TRP_ROUTE *entry, int sel);
+int trp_route_is_selected(TRP_ROUTE *entry);
+void trp_route_set_interval(TRP_ROUTE *entry, int interval);
+int trp_route_get_interval(TRP_ROUTE *entry);
+void trp_route_set_expiry(TRP_ROUTE *entry, struct timespec *exp);
+struct timespec *trp_route_get_expiry(TRP_ROUTE *entry);
+void trp_route_set_local(TRP_ROUTE *entry, int local);
+int trp_route_is_local(TRP_ROUTE *entry);
+void trp_route_set_triggered(TRP_ROUTE *entry, int trig);
+int trp_route_is_triggered(TRP_ROUTE *entry);
+char *trp_route_to_str(TALLOC_CTX *mem_ctx, TRP_ROUTE *entry, const char *sep);
 
 #endif /* _TRP_RTABLE_H_ */
index c544f9f..0d998d1 100644 (file)
@@ -12,6 +12,8 @@
 #define trp_metric_is_invalid(x) (((x)>TRP_METRIC_INFINITY) || ((x)==TRP_METRIC_INVALID))
 #define TRP_INTERVAL_INVALID 0
 
+#define TRP_LINKCOST_DEFAULT 1
+
 typedef enum trp_rc {
   TRP_SUCCESS=0,
   TRP_ERROR, /* generic error */
diff --git a/tr/tr.c b/tr/tr.c
index bd3ce0a..d79ca76 100644 (file)
--- a/tr/tr.c
+++ b/tr/tr.c
@@ -35,8 +35,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <talloc.h>
-#include <tr.h>
 #include <tr_config.h>
+#include <tr.h>
 
 TR_INSTANCE *tr_create(TALLOC_CTX *mem_ctx) {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
index f022fa7..5989f0b 100644 (file)
 #include <event2/event.h>
 #include <talloc.h>
 #include <sys/time.h>
+#include <signal.h>
+#include <pthread.h>
 
-#include <tr.h>
 #include <tid_internal.h>
 #include <tr_tid.h>
 #include <tr_trp.h>
 #include <tr_config.h>
 #include <tr_event.h>
 #include <tr_cfgwatch.h>
+#include <tr.h>
 #include <tr_debug.h>
 
 #define TALLOC_DEBUG_ENABLE 1
@@ -168,6 +170,15 @@ static void debug_ping(evutil_socket_t fd, short what, void *arg)
 }
 #endif /* DEBUG_PING_SELF */
 
+static void configure_signals(void)
+{
+  sigset_t signals;
+  /* ignore SIGPIPE */
+  sigemptyset(&signals);
+  sigaddset(&signals, SIGPIPE);
+  pthread_sigmask(SIG_BLOCK, &signals, NULL);
+}
+
 int main(int argc, char *argv[])
 {
   TALLOC_CTX *main_ctx=NULL;
@@ -176,14 +187,16 @@ int main(int argc, char *argv[])
   struct cmdline_args opts;
   struct event_base *ev_base;
   struct tr_socket_event tids_ev;
-  TR_TRPS_EVENTS *trps_ev;
   struct event *cfgwatch_ev;
+
 #if DEBUG_PING_SELF
   struct event *debug_ping_ev;
   struct timeval notime={0, 0};
   struct thingy thingy={NULL};
 #endif /* DEBUG_PING_SELF */
 
+  configure_signals();
+
   /* we're going to be multithreaded, so disable null context tracking */
   talloc_set_abort_fn(tr_abort);
   talloc_disable_null_tracking();
@@ -232,7 +245,7 @@ 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);
+  tr->cfgwatch->update_cookie=(void *)tr;
   if (0 != tr_read_and_apply_config(tr->cfgwatch)) {
     tr_crit("Error reading configuration, exiting.");
     return 1;
@@ -245,11 +258,6 @@ int main(int argc, char *argv[])
     return 1;
   }
 
-  /* install configuration file watching events */
-  tr->cfgwatch->poll_interval=(struct timeval) {1,0}; /* set poll interval in {sec, usec} */
-  tr->cfgwatch->settling_time=(struct timeval) {5,0}; /* delay for changes to settle before updating */
-  /* TODO: pull these settings out of the configuration files */
-
   /* already set config_dir, fstat_list and n_files earlier */
   if (0 != tr_cfgwatch_event_init(ev_base, tr->cfgwatch, &cfgwatch_ev)) {
     tr_crit("Error initializing configuration file watcher.");
@@ -268,11 +276,7 @@ int main(int argc, char *argv[])
   }
 
   /* install TRP handler events */
-  trps_ev=tr_trps_events_new(main_ctx);
-  if (0 != tr_trps_event_init(ev_base,
-                              tr->trps,
-                              tr->cfg_mgr,
-                              trps_ev)) {
+  if (TRP_SUCCESS != tr_trps_event_init(ev_base, tr)) {
     tr_crit("Error initializing Trust Path Query Server instance.");
     return 1;
   }
@@ -305,6 +309,19 @@ int main(int argc, char *argv[])
       return 1;
     }
 
+    hc_peer=trp_peer_new(main_ctx); /* will later be stolen by ptable context */
+    if (hc_peer==NULL) {
+      tr_crit("Unable to allocate new peer. Aborting.");
+      return 1;
+    }
+    trp_peer_set_server(hc_peer, "epsilon.vmnet");
+    trp_peer_set_gssname(hc_peer, tr_new_name("trpc@apc.painless-security.com"));
+    trp_peer_set_port(hc_peer, 10002); /* not really used */
+    if (TRP_SUCCESS != trps_add_peer(tr->trps, hc_peer)) {
+      tr_crit("Unable to add peer.");
+      return 1;
+    }
+    
     s=trp_ptable_to_str(main_ctx, tr->trps->ptable, NULL, NULL);
     tr_debug("Peer Table:\n%s\n", s);
     talloc_free(s);
index 91b9dd7..ed07918 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdio.h>  /* TODO: remove this --jlr */
 #include <pthread.h>
 #include <fcntl.h>
 #include <event2/event.h>
@@ -9,6 +10,7 @@
 #include <time.h>
 
 #include <gsscon.h>
+#include <tr.h>
 #include <tr_rp.h>
 #include <trp_internal.h>
 #include <trp_ptable.h>
@@ -48,7 +50,7 @@ static TRP_RC tr_trps_msg_handler(TRPS_INSTANCE *trps,
   /* n.b., conn is available here, but do not hold onto the reference
    * because it may be cleaned up if the originating connection goes
    * down before the message is processed */
-  mq_msg=tr_mq_msg_new(tmp_ctx, "tr_msg");
+  mq_msg=tr_mq_msg_new(tmp_ctx, TR_MQMSG_MSG_RECEIVED);
   if (mq_msg==NULL) {
     return TRP_NOMEM;
   }
@@ -89,7 +91,7 @@ struct trps_thread_data {
   TRP_CONNECTION *conn;
   TRPS_INSTANCE *trps;
 };
-/* thread to handle GSS connections to peers */
+/* thread to handle GSS connections from peers */
 static void *tr_trps_thread(void *arg)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
@@ -141,9 +143,8 @@ static void tr_trps_event_cb(int listener, short event, void *arg)
       }
       thread_data->conn=conn;
       thread_data->trps=trps;
-      pthread_create(trp_connection_get_thread(conn), NULL, tr_trps_thread, thread_data);
-      pthread_detach(*(trp_connection_get_thread(conn))); /* we will not rejoin the thread */
       trps_add_connection(trps, conn); /* remember the connection */
+      pthread_create(trp_connection_get_thread(conn), NULL, tr_trps_thread, thread_data);
     }
   }
   talloc_free(tmp_ctx);
@@ -153,30 +154,20 @@ 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 */
+  tr_debug("tr_trps_cleanup_conn: freeing %p", conn);
+/*  pthread_join(*trp_connection_get_thread(conn), NULL); -- removed while debugging, put back!!! --jlr */
   trps_remove_connection(trps, conn);
+  talloc_report_full(conn, stderr);
   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, TR_MQMSG_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 */
-  
+  tr_debug("tr_trps_cleanup_conn: deleted connection");
 }
-#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 */
+  pthread_join(*trp_connection_get_thread(trpc_get_conn(trpc)), NULL);
   trps_remove_trpc(trps, trpc);
   trpc_free(trpc);
-  tr_debug("Deleted connection");
+  tr_debug("tr_trps_cleanup_trpc: deleted connection");
 }
 
 static void tr_trps_print_route_table(TRPS_INSTANCE *trps, FILE *f)
@@ -196,6 +187,7 @@ static void tr_trps_process_mq(int socket, short event, void *arg)
   TR_MQ_MSG *msg=NULL;
   const char *s=NULL;
 
+  talloc_report_full(trps->mq, stderr);
   msg=trps_mq_pop(trps);
   while (msg!=NULL) {
     s=tr_mq_msg_get_message(msg);
@@ -211,7 +203,7 @@ static void tr_trps_process_mq(int socket, short event, void *arg)
                                                  TRPC_INSTANCE));
     }
 
-    else if (0==strcmp(s, "tr_msg")) {
+    else if (0==strcmp(s, TR_MQMSG_MSG_RECEIVED)) {
       if (trps_handle_tr_msg(trps, tr_mq_msg_get_payload(msg))!=TRP_SUCCESS)
         tr_notice("tr_trps_process_mq: error handling message.");
       else {
@@ -245,6 +237,7 @@ static void tr_trps_sweep(int listener, short event, void *arg)
 
   tr_debug("tr_trps_sweep: sweeping routes.");
   trps_sweep_routes(trps);
+  tr_trps_print_route_table(trps, stderr);
   /* schedule the event to run again */
   event_add(ev, &(trps->sweep_interval));
 }
@@ -274,7 +267,7 @@ static int tr_trps_events_destructor(void *obj)
     event_free(ev->sweep_ev);
   return 0;
 }
-TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
+static TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
 {
   TR_TRPS_EVENTS *ev=talloc(mem_ctx, TR_TRPS_EVENTS);
   if (ev!=NULL) {
@@ -286,18 +279,21 @@ TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
     if (ev->listen_ev==NULL) {
       talloc_free(ev);
       ev=NULL;
+    } else {
+      talloc_set_destructor((void *)ev, tr_trps_events_destructor);
     }
-    talloc_set_destructor((void *)ev, tr_trps_events_destructor);
   }
   return ev;
 }
 
+static void tr_trps_events_free(TR_TRPS_EVENTS *ev)
+{
+  talloc_free(ev);
+}
+
 /* Configure the trps instance and set up its event handler.
  * Fills in trps_ev, which should be allocated by caller. */
-TRP_RC tr_trps_event_init(struct event_base *base,
-                       TRPS_INSTANCE *trps,
-                       TR_CFG_MGR *cfg_mgr,
-                       TR_TRPS_EVENTS *trps_ev)
+TRP_RC tr_trps_event_init(struct event_base *base, TR_INSTANCE *tr)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   struct tr_socket_event *listen_ev=NULL;
@@ -305,39 +301,49 @@ TRP_RC tr_trps_event_init(struct event_base *base,
   struct tr_trps_event_cookie *connection_cookie=NULL;
   struct tr_trps_event_cookie *update_cookie=NULL;
   struct tr_trps_event_cookie *sweep_cookie=NULL;
+  struct timeval zero_time={0,0};
   TRP_RC retval=TRP_ERROR;
 
-  if (trps_ev == NULL) {
-    tr_debug("tr_trps_event_init: Null trps_ev.");
-    retval=TRP_BADARG;
+  if (tr->events != NULL) {
+    tr_notice("tr_trps_event_init: tr->events was not null. Freeing before reallocating..");
+    tr_trps_events_free(tr->events);
+  }
+
+  tr->events=tr_trps_events_new(tmp_ctx);
+  if (tr->events == NULL) {
+    tr_debug("tr_trps_event_init: unable to allocate event handles.");
+    retval=TRP_NOMEM;
     goto cleanup;
   }
 
   /* get convenient handles */
-  listen_ev=trps_ev->listen_ev;
+  listen_ev=tr->events->listen_ev;
 
-  /* Create the cookie for callbacks. It is part of the trps context, so it will
+  /* Create the cookie for callbacks. It will end up part of the trps context, so it will
    * be cleaned up when trps is freed by talloc_free. */
-  trps_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  trps_cookie=talloc(tr->events, struct tr_trps_event_cookie);
   if (trps_cookie == NULL) {
     tr_debug("tr_trps_event_init: Unable to allocate trps_cookie.");
     retval=TRP_NOMEM;
+    tr_trps_events_free(tr->events);
+    tr->events=NULL;
     goto cleanup;
   }
-  trps_cookie->trps=trps;
-  trps_cookie->cfg_mgr=cfg_mgr;
-  talloc_steal(trps, trps_cookie);
+  trps_cookie->trps=tr->trps;
+  trps_cookie->cfg_mgr=tr->cfg_mgr;
 
   /* get a trps listener */
-  listen_ev->sock_fd=trps_get_listener(trps,
+  listen_ev->sock_fd=trps_get_listener(tr->trps,
                                        tr_trps_msg_handler,
                                        tr_trps_gss_handler,
-                                       cfg_mgr->active->internal->hostname,
-                                       cfg_mgr->active->internal->trps_port,
+                                       tr->cfg_mgr->active->internal->hostname,
+                                       tr->cfg_mgr->active->internal->trps_port,
                                        (void *)trps_cookie);
   if (listen_ev->sock_fd < 0) {
     tr_crit("Error opening TRP server socket.");
     retval=TRP_ERROR;
+    tr_trps_events_free(tr->events);
+    tr->events=NULL;
     goto cleanup;
   }
   trps_cookie->ev=listen_ev->ev; /* in case it needs to frob the event */
@@ -347,60 +353,65 @@ TRP_RC tr_trps_event_init(struct event_base *base,
                           listen_ev->sock_fd,
                           EV_READ|EV_PERSIST,
                           tr_trps_event_cb,
-                          (void *)trps);
+                          (void *)(tr->trps));
   event_add(listen_ev->ev, NULL);
   
   /* now set up message queue processing event, only triggered by
    * tr_trps_mq_cb() */
-  trps_ev->mq_ev=event_new(base,
-                           0,
-                           EV_PERSIST,
-                           tr_trps_process_mq,
-                           (void *)trps);
-  tr_mq_set_notify_cb(trps->mq, tr_trps_mq_cb, trps_ev->mq_ev);
+  tr->events->mq_ev=event_new(base,
+                              0,
+                              EV_PERSIST,
+                              tr_trps_process_mq,
+                              (void *)(tr->trps));
+  tr_mq_set_notify_cb(tr->trps->mq, tr_trps_mq_cb, tr->events->mq_ev);
 
   /* now set up the peer connection timer event */
-  connection_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  connection_cookie=talloc(tr->events, struct tr_trps_event_cookie);
   if (connection_cookie == NULL) {
     tr_debug("tr_trps_event_init: Unable to allocate connection_cookie.");
     retval=TRP_NOMEM;
+    tr_trps_events_free(tr->events);
+    tr->events=NULL;
     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));
+  connection_cookie->trps=tr->trps;
+  connection_cookie->cfg_mgr=tr->cfg_mgr;
+  tr->events->connect_ev=event_new(base, -1, EV_TIMEOUT, tr_connection_update, (void *)connection_cookie);
+  connection_cookie->ev=tr->events->connect_ev; /* in case it needs to frob the event */
+  /* The first time, do this immediately. Thereafter, it will retrigger every trps->connect_interval */
+  event_add(tr->events->connect_ev, &zero_time);
 
   /* now set up the route update timer event */
-  update_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  update_cookie=talloc(tr->events, struct tr_trps_event_cookie);
   if (update_cookie == NULL) {
     tr_debug("tr_trps_event_init: Unable to allocate update_cookie.");
     retval=TRP_NOMEM;
+    tr_trps_events_free(tr->events);
+    tr->events=NULL;
     goto cleanup;
   }
-  update_cookie->trps=trps;
-  update_cookie->cfg_mgr=cfg_mgr;
-  talloc_steal(trps, update_cookie);
-  trps_ev->update_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_update, (void *)update_cookie);
-  update_cookie->ev=trps_ev->update_ev; /* in case it needs to frob the event */
-  event_add(trps_ev->update_ev, &(trps->update_interval));
+  update_cookie->trps=tr->trps;
+  update_cookie->cfg_mgr=tr->cfg_mgr;
+  tr->events->update_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_update, (void *)update_cookie);
+  update_cookie->ev=tr->events->update_ev; /* in case it needs to frob the event */
+  event_add(tr->events->update_ev, &(tr->trps->update_interval));
 
   /* now set up the route table sweep timer event */
-  sweep_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+  sweep_cookie=talloc(tr->events, struct tr_trps_event_cookie);
   if (sweep_cookie == NULL) {
     tr_debug("tr_trps_event_init: Unable to allocate sweep_cookie.");
     retval=TRP_NOMEM;
+    tr_trps_events_free(tr->events);
+    tr->events=NULL;
     goto cleanup;
   }
-  sweep_cookie->trps=trps;
-  sweep_cookie->cfg_mgr=cfg_mgr;
-  talloc_steal(trps, sweep_cookie);
-  trps_ev->sweep_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_sweep, (void *)sweep_cookie);
-  sweep_cookie->ev=trps_ev->sweep_ev; /* in case it needs to frob the event */
-  event_add(trps_ev->sweep_ev, &(trps->sweep_interval));
+  sweep_cookie->trps=tr->trps;
+  sweep_cookie->cfg_mgr=tr->cfg_mgr;
+  tr->events->sweep_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_sweep, (void *)sweep_cookie);
+  sweep_cookie->ev=tr->events->sweep_ev; /* in case it needs to frob the event */
+  event_add(tr->events->sweep_ev, &(tr->trps->sweep_interval));
 
+  talloc_steal(tr, tr->events);
   retval=TRP_SUCCESS;
 
 cleanup:
@@ -456,10 +467,13 @@ static void *tr_trpc_thread(void *arg)
   tr_mq_unlock(trpc->mq);
 
   rc=trpc_connect(trpc);
+/*  talloc_report_full(trpc, stderr);*/
   if (rc!=TRP_SUCCESS) {
-    tr_notice("tr_trpc_thread: failed to initiate connection to %s:%d.",
-              trpc_get_server(trpc),
-              trpc_get_port(trpc));
+    /* was tr_notice --jlr */
+    fprintf(stderr, "tr_trpc_thread: failed to initiate connection to %s:%d.",
+            trpc_get_server(trpc),
+            trpc_get_port(trpc));
+    fflush(stderr);
   } else {
     tr_debug("tr_trpc_thread: connected to peer %s", trpc->conn->peer->buf);
     while (1) {
@@ -501,6 +515,7 @@ static void *tr_trpc_thread(void *arg)
     }
   }
 
+  tr_debug("tr_trpc_thread: exiting.");
   msg=tr_mq_msg_new(tmp_ctx, TR_MQMSG_TRPC_DISCONNECTED);
   tr_mq_msg_set_payload(msg, (void *)trpc, NULL); /* do not pass a free routine */
   if (msg==NULL)
@@ -513,15 +528,15 @@ static void *tr_trpc_thread(void *arg)
 }
 
 /* convert an IDP realm into routing table entries. Outputs number in *n_routes */
-static TRP_RENTRY **tr_make_local_routes(TALLOC_CTX *mem_ctx,
+static TRP_ROUTE **tr_make_local_routes(TALLOC_CTX *mem_ctx,
                                          TR_IDP_REALM *realm,
                                          char *trust_router,
                                          size_t *n_routes)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_APC *apc=NULL;
-  TRP_RENTRY *new_entry=NULL;
-  TRP_RENTRY **entries=NULL;
+  TRP_ROUTE *new_entry=NULL;
+  TRP_ROUTE **entries=NULL;
   size_t n_apcs=0, ii=0;
 
   *n_routes=0;
@@ -532,22 +547,21 @@ static TRP_RENTRY **tr_make_local_routes(TALLOC_CTX *mem_ctx,
   /* count apcs */
   for (apc=realm->apcs, n_apcs=0; apc!=NULL; apc=apc->next,n_apcs++) {}
 
-  entries=talloc_array(tmp_ctx, TRP_RENTRY *, n_apcs);
+  entries=talloc_array(tmp_ctx, TRP_ROUTE *, n_apcs);
   for (apc=realm->apcs,ii=0; apc!=NULL; apc=apc->next, ii++) {
-    new_entry=trp_rentry_new(entries);
+    new_entry=trp_route_new(entries);
     if (new_entry==NULL) {
       tr_crit("tr_make_local_routes: unable to allocate entry.");
       talloc_free(entries);
       goto cleanup;
     }
-    trp_rentry_set_apc(new_entry, tr_dup_name(apc->id));
-    trp_rentry_set_realm(new_entry, tr_dup_name(realm->realm_id));
-    trp_rentry_set_peer(new_entry, tr_new_name("")); /* no peer, it's us */
-    trp_rentry_set_metric(new_entry, 0);
-    trp_rentry_set_trust_router(new_entry, tr_new_name(trust_router));
-    trp_rentry_set_next_hop(new_entry, tr_new_name(""));
-    /* we do not set selected (tbd later) or expiry/interval (not needed for
-     * local routes) */
+    trp_route_set_apc(new_entry, tr_dup_name(apc->id));
+    trp_route_set_realm(new_entry, tr_dup_name(realm->realm_id));
+    trp_route_set_peer(new_entry, tr_new_name("")); /* no peer, it's us */
+    trp_route_set_metric(new_entry, 0);
+    trp_route_set_trust_router(new_entry, tr_new_name(trust_router));
+    trp_route_set_next_hop(new_entry, tr_new_name(""));
+    trp_route_set_local(new_entry, 1);
     entries[ii]=new_entry;
   }
 
@@ -566,8 +580,6 @@ struct tr_trpc_status_change_cookie {
 static void tr_trpc_status_change(TRP_CONNECTION *conn, void *cookie)
 {
   struct tr_trpc_status_change_cookie *cook=talloc_get_type_abort(cookie, struct tr_trpc_status_change_cookie);
-  /*TRPS_INSTANCE *trps=cook->trps;*/
-  /* TRPC_INSTANCE *trpc=cook->trpc;*/
   TRP_PEER *peer=cook->peer;
   TR_NAME *gssname=trp_peer_get_gssname(peer);
 
@@ -578,18 +590,20 @@ static void tr_trpc_status_change(TRP_CONNECTION *conn, void *cookie)
 }
 
 /* starts a trpc thread to connect to server:port */
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
+TRP_RC tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TRPC_INSTANCE *trpc=NULL;
   TRP_CONNECTION *conn=NULL;
   struct trpc_thread_data *thread_data=NULL;
   struct tr_trpc_status_change_cookie *status_change_cookie=NULL;
+  TRP_RC rc=TRP_ERROR;
 
   tr_debug("tr_trpc_initiate entered");
   trpc=trpc_new(tmp_ctx);
   if (trpc==NULL) {
     tr_crit("tr_trpc_initiate: could not allocate TRPC_INSTANCE.");
+    rc=TRP_NOMEM;
     goto cleanup;
   }
   tr_debug("tr_trpc_initiate: allocated trpc");
@@ -597,12 +611,14 @@ TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
   conn=trp_connection_new(trpc);
   if (conn==NULL) {
     tr_crit("tr_trpc_initiate: could not allocate TRP_CONNECTION.");
+    rc=TRP_NOMEM;
     goto cleanup;
   }
 
   status_change_cookie=talloc(conn, struct tr_trpc_status_change_cookie);
   if (status_change_cookie==NULL) {
     tr_crit("tr_trpc_initiate: could not allocate connection status cookie.");
+    rc=TRP_NOMEM;
     goto cleanup;
   }
   status_change_cookie->trps=trps;
@@ -622,20 +638,22 @@ TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
   thread_data=talloc(trpc, struct trpc_thread_data);
   if (thread_data==NULL) {
     tr_crit("tr_trpc_initiate: could not allocate struct trpc_thread_data.");
+    rc=TRP_NOMEM;
     goto cleanup;
   }
   thread_data->trpc=trpc;
   thread_data->trps=trps;
 
+  trps_add_trpc(trps, trpc); /* must add before starting thread */
   pthread_create(trp_connection_get_thread(conn), NULL, tr_trpc_thread, thread_data);
-  pthread_detach(*(trp_connection_get_thread(conn))); /* we will not rejoin the thread */
 
   tr_debug("tr_trpc_initiate: started trpc thread");
-  trps_add_trpc(trps, trpc);
+  rc=TRP_SUCCESS;
 
  cleanup:
+  talloc_report_full(tmp_ctx, stderr);
   talloc_free(tmp_ctx);
-  return trpc;
+  return rc;
 }
 
 /* Add local routes to the route table. */
@@ -643,7 +661,7 @@ TRP_RC tr_add_local_routes(TRPS_INSTANCE *trps, TR_CFG *cfg)
 {
   TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_IDP_REALM *cur=NULL;
-  TRP_RENTRY **local_routes=NULL;
+  TRP_ROUTE **local_routes=NULL;
   size_t n_routes=0;
   size_t ii=0;
   char *trust_router_name=talloc_asprintf(tmp_ctx, "%s:%d", cfg->internal->hostname, cfg->internal->trps_port);
@@ -678,7 +696,6 @@ 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;
 
@@ -698,8 +715,7 @@ TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps)
       /* 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) {
+        if (tr_trpc_initiate(trps, peer)!=TRP_SUCCESS) {
           tr_err("tr_connect_to_peers: unable to initiate TRP connection to %s:%u.",
                  trp_peer_get_server(peer),
                  trp_peer_get_port(peer));
@@ -720,7 +736,15 @@ cleanup:
  * 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);
+  TR_INSTANCE *tr=talloc_get_type_abort(cookie, TR_INSTANCE);
+  TRPS_INSTANCE *trps=tr->trps;
+
+  tr->cfgwatch->poll_interval.tv_sec=new_cfg->internal->cfg_poll_interval;
+  tr->cfgwatch->poll_interval.tv_usec=0;
+
+  tr->cfgwatch->settling_time.tv_sec=new_cfg->internal->cfg_settling_time;
+  tr->cfgwatch->settling_time.tv_usec=0;
+
   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 e9e0de6..f04b4dd 100644 (file)
@@ -41,7 +41,6 @@
 #include <gsscon.h>
 #include <tr_debug.h>
 #include <tr_trp.h>
-#include <trust_router/tr_dh.h>
 
 
 /* command-line option setup */
@@ -124,9 +123,7 @@ int main (int argc,
 {
   TALLOC_CTX *main_ctx=talloc_new(NULL);
   TRPC_INSTANCE *trpc=NULL;
-  int conn = 0;
-  int rc;
-  gss_ctx_id_t gssctx;
+  TRP_CONNECTION *conn=NULL;
   struct cmdline_args opts;
 
   /* parse the command line*/
@@ -137,7 +134,6 @@ int main (int argc,
   opts.repeat=1;
 
   argp_parse(&argp, argc, argv, 0, 0, &opts);
-  /* TBD -- validity checking, dealing with quotes, etc. */
 
   /* Use standalone logging */
   tr_log_open();
@@ -149,25 +145,27 @@ int main (int argc,
 
   printf("TRPC Client:\nServer = %s, port = %i\n", opts.server, opts.port);
  
-  /* Create a TRP client instance & the client DH */
-  trpc = trpc_new(main_ctx);
-  if (NULL == (trpc->client_dh = tr_create_dh_params(NULL, 0))) {
-    printf("Error creating client DH params.\n");
+  conn=trp_connection_new(trpc);
+  if (conn==NULL) {
+    printf("Could not allocate TRP_CONNECTION.\n");
     return 1;
   }
-
+  trpc = trpc_new(main_ctx);
+  trpc_set_server(trpc, opts.server);
+  trpc_set_port(trpc, opts.port);
+  trpc_set_conn(trpc, conn);
   /* Set-up TRP connection */
-  if (-1 == (conn = trpc_open_connection(trpc, opts.server, opts.port, &gssctx))) {
+  if (TRP_SUCCESS != trpc_connect(trpc)) {
     /* Handle error */
-    printf("Error in trpc_open_connection.\n");
+    printf("Error in trpc_connect.\n");
     return 1;
-  };
+  }
 
   /* Send a TRP message */
   while ((opts.repeat==-1) || (opts.repeat-->0)) {
-    if (0 > (rc = trpc_send_msg(trpc, conn, gssctx, opts.msg, NULL, NULL))) {
+    if (TRP_SUCCESS != trpc_send_msg(trpc, opts.msg)) {
       /* Handle error */
-      printf("Error in trpc_send_request, rc = %d.\n", rc);
+      printf("Error in trpc_send_request.");
       return 1;
     }
     usleep(1000000);
index 5d38de4..99d8593 100644 (file)
@@ -205,7 +205,7 @@ static void trp_connection_mutex_init(TRP_CONNECTION *conn)
 static int trp_connection_destructor(void *object)
 {
   TRP_CONNECTION *conn=talloc_get_type_abort(object, TRP_CONNECTION); /* aborts on wrong type */
-  if ((trp_connection_get_status(conn)!=TRP_CONNECTION_DOWN)
+  if ((trp_connection_get_status(conn)!=TRP_CONNECTION_CLOSED)
      && (trp_connection_get_fd(conn)!=-1))
     close(trp_connection_get_fd(conn));
   if (conn->peer!=NULL)
@@ -230,7 +230,7 @@ TRP_CONNECTION *trp_connection_new(TALLOC_CTX *mem_ctx)
     new_conn->peer=NULL; /* no true set function for this */
     new_conn->status_change_cb=NULL;
     new_conn->status_change_cookie=NULL;
-    new_conn->status=TRP_CONNECTION_DOWN; /* set directly in the constructor */
+    new_conn->status=TRP_CONNECTION_CLOSED;
 
     thread=talloc(new_conn, pthread_t);
     if (thread==NULL) {
@@ -271,13 +271,17 @@ int trp_connection_auth(TRP_CONNECTION *conn, TRP_AUTH_FUNC auth_callback, void
   gss_ctx_id_t *gssctx=trp_connection_get_gssctx(conn);
 
   nameBuffer.length = trp_connection_get_gssname(conn)->len;
-  nameBuffer.value = trp_connection_get_gssname(conn)->buf;
+  nameBuffer.value = tr_name_strdup(trp_connection_get_gssname(conn));
 
   tr_debug("trp_connection_auth: beginning passive authentication");
+  if (trp_connection_get_status(conn)!=TRP_CONNECTION_AUTHORIZING)
+    tr_warning("trp_connection_auth: warning: connection was not in TRP_CONNECTION_AUTHORIZING state.");
+
   rc = gsscon_passive_authenticate(trp_connection_get_fd(conn), nameBuffer, gssctx, auth_callback, callback_data);
   gss_release_buffer(NULL, &nameBuffer);
   if (rc!=0) {
     tr_debug("trp_connection_auth: Error from gsscon_passive_authenticate(), rc = 0x%08X.", rc);
+    trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
     return -1;
   }
 
@@ -285,6 +289,7 @@ int trp_connection_auth(TRP_CONNECTION *conn, TRP_AUTH_FUNC auth_callback, void
   if (rc = gsscon_authorize(*gssctx, &auth, &autherr)) {
     tr_debug("trp_connection_auth: Error from gsscon_authorize, rc = %d, autherr = %d.", 
              rc, autherr);
+    trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
     return -1;
   }
 
@@ -314,6 +319,7 @@ TRP_CONNECTION *trp_connection_accept(TALLOC_CTX *mem_ctx, int listen, TR_NAME *
   conn=trp_connection_new(mem_ctx);
   trp_connection_set_fd(conn, conn_fd);
   trp_connection_set_gssname(conn, gssname);
+  trp_connection_set_status(conn, TRP_CONNECTION_AUTHORIZING);
   return conn;
 }
 
@@ -344,7 +350,6 @@ TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, char *server, unsigned int
                        trp_connection_get_gssctx(conn));
   if (err) {
     tr_debug("trp_connection_initiate: connection failed.");
-    talloc_free(conn);
     return TRP_ERROR;
   } else {
     tr_debug("trp_connection_initiate: connected.");
index afee7ef..557bc0d 100644 (file)
@@ -21,7 +21,7 @@ TRP_PEER *trp_peer_new(TALLOC_CTX *memctx)
     peer->server=NULL;
     peer->gssname=NULL;
     peer->port=0;
-    peer->linkcost=TRP_METRIC_INFINITY;
+    peer->linkcost=TRP_LINKCOST_DEFAULT;
     peer->last_conn_attempt=(struct timespec){0,0};
     talloc_set_destructor((void *)peer, trp_peer_destructor);
   }
index 7a519bb..69f845c 100644 (file)
@@ -11,9 +11,9 @@
 
 /* Note: be careful mixing talloc with glib. */
 
-static int trp_rentry_destructor(void *obj)
+static int trp_route_destructor(void *obj)
 {
-  TRP_RENTRY *entry=talloc_get_type_abort(obj, TRP_RENTRY);
+  TRP_ROUTE *entry=talloc_get_type_abort(obj, TRP_ROUTE);
   if (entry->apc!=NULL)
     tr_free_name(entry->apc);
   if (entry->realm!=NULL)
@@ -27,9 +27,9 @@ static int trp_rentry_destructor(void *obj)
   return 0;
 }
 
-TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx)
+TRP_ROUTE *trp_route_new(TALLOC_CTX *mem_ctx)
 {
-  TRP_RENTRY *entry=talloc(mem_ctx, TRP_RENTRY);
+  TRP_ROUTE *entry=talloc(mem_ctx, TRP_ROUTE);
   if (entry!=NULL) {
     entry->apc=NULL;
     entry->realm=NULL;
@@ -43,140 +43,163 @@ TRP_RENTRY *trp_rentry_new(TALLOC_CTX *mem_ctx)
       talloc_free(entry);
       return NULL;
     }
-    talloc_set_destructor((void *)entry, trp_rentry_destructor);
+    *(entry->expiry)=(struct timespec){0,0};
+    entry->local=0;
+    entry->triggered=0;
+    talloc_set_destructor((void *)entry, trp_route_destructor);
   }
   return entry;
 }
 
-void trp_rentry_free(TRP_RENTRY *entry)
+void trp_route_free(TRP_ROUTE *entry)
 {
   if (entry!=NULL)
     talloc_free(entry);
 }
 
-void trp_rentry_set_apc(TRP_RENTRY *entry, TR_NAME *apc)
+void trp_route_set_apc(TRP_ROUTE *entry, TR_NAME *apc)
 {
+  if (entry->apc!=NULL)
+    tr_free_name(entry->apc);
   entry->apc=apc;
 }
 
-TR_NAME *trp_rentry_get_apc(TRP_RENTRY *entry)
+TR_NAME *trp_route_get_apc(TRP_ROUTE *entry)
 {
   return entry->apc;
 }
 
-TR_NAME *trp_rentry_dup_apc(TRP_RENTRY *entry)
+TR_NAME *trp_route_dup_apc(TRP_ROUTE *entry)
 {
-  return tr_dup_name(trp_rentry_get_apc(entry));
+  return tr_dup_name(trp_route_get_apc(entry));
 }
 
-void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm)
+void trp_route_set_realm(TRP_ROUTE *entry, TR_NAME *realm)
 {
+  if (entry->realm!=NULL)
+    tr_free_name(entry->realm);
   entry->realm=realm;
 }
 
-TR_NAME *trp_rentry_get_realm(TRP_RENTRY *entry)
+TR_NAME *trp_route_get_realm(TRP_ROUTE *entry)
 {
   return entry->realm;
 }
 
-TR_NAME *trp_rentry_dup_realm(TRP_RENTRY *entry)
+TR_NAME *trp_route_dup_realm(TRP_ROUTE *entry)
 {
-  return tr_dup_name(trp_rentry_get_realm(entry));
+  return tr_dup_name(trp_route_get_realm(entry));
 }
 
-void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr)
+void trp_route_set_trust_router(TRP_ROUTE *entry, TR_NAME *tr)
 {
+  if (entry->trust_router!=NULL)
+    tr_free_name(entry->trust_router);
   entry->trust_router=tr;
 }
 
-TR_NAME *trp_rentry_get_trust_router(TRP_RENTRY *entry)
+TR_NAME *trp_route_get_trust_router(TRP_ROUTE *entry)
 {
   return entry->trust_router;
 }
 
-TR_NAME *trp_rentry_dup_trust_router(TRP_RENTRY *entry)
+TR_NAME *trp_route_dup_trust_router(TRP_ROUTE *entry)
 {
-  return tr_dup_name(trp_rentry_get_trust_router(entry));
+  return tr_dup_name(trp_route_get_trust_router(entry));
 }
 
-void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer)
+void trp_route_set_peer(TRP_ROUTE *entry, TR_NAME *peer)
 {
+  if (entry->peer!=NULL)
+    tr_free_name(entry->peer);
   entry->peer=peer;
 }
 
-TR_NAME *trp_rentry_get_peer(TRP_RENTRY *entry)
+TR_NAME *trp_route_get_peer(TRP_ROUTE *entry)
 {
   return entry->peer;
 }
 
-TR_NAME *trp_rentry_dup_peer(TRP_RENTRY *entry)
+TR_NAME *trp_route_dup_peer(TRP_ROUTE *entry)
 {
-  return tr_dup_name(trp_rentry_get_peer(entry));
+  return tr_dup_name(trp_route_get_peer(entry));
 }
 
-void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric)
+void trp_route_set_metric(TRP_ROUTE *entry, unsigned int metric)
 {
   entry->metric=metric;
 }
 
-unsigned int trp_rentry_get_metric(TRP_RENTRY *entry)
+unsigned int trp_route_get_metric(TRP_ROUTE *entry)
 {
   return entry->metric;
 }
 
-void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop)
+void trp_route_set_next_hop(TRP_ROUTE *entry, TR_NAME *next_hop)
 {
+  if (entry->next_hop!=NULL)
+    tr_free_name(entry->next_hop);
   entry->next_hop=next_hop;
 }
 
-TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry)
+TR_NAME *trp_route_get_next_hop(TRP_ROUTE *entry)
 {
   return entry->next_hop;
 }
 
-TR_NAME *trp_rentry_dup_next_hop(TRP_RENTRY *entry)
+TR_NAME *trp_route_dup_next_hop(TRP_ROUTE *entry)
 {
-  return tr_dup_name(trp_rentry_get_next_hop(entry));
+  return tr_dup_name(trp_route_get_next_hop(entry));
 }
 
-void trp_rentry_set_selected(TRP_RENTRY *entry, int sel)
+void trp_route_set_selected(TRP_ROUTE *entry, int sel)
 {
   entry->selected=sel;
 }
 
-int trp_rentry_get_selected(TRP_RENTRY *entry)
+int trp_route_is_selected(TRP_ROUTE *entry)
 {
   return entry->selected;
 }
 
-void trp_rentry_set_interval(TRP_RENTRY *entry, int interval)
+void trp_route_set_interval(TRP_ROUTE *entry, int interval)
 {
   entry->interval=interval;
 }
 
-int trp_rentry_get_interval(TRP_RENTRY *entry)
+int trp_route_get_interval(TRP_ROUTE *entry)
 {
   return entry->interval;
 }
 
 /* copies incoming value, does not assume responsibility for freeing */
-void trp_rentry_set_expiry(TRP_RENTRY *entry, struct timespec *exp)
+void trp_route_set_expiry(TRP_ROUTE *entry, struct timespec *exp)
 {
   entry->expiry->tv_sec=exp->tv_sec;
   entry->expiry->tv_nsec=exp->tv_nsec;
 }
 
-struct timespec *trp_rentry_get_expiry(TRP_RENTRY *entry)
+struct timespec *trp_route_get_expiry(TRP_ROUTE *entry)
 {
   return entry->expiry;
 }
 
-void trp_rentry_set_triggered(TRP_RENTRY *entry, int trig)
+void trp_route_set_local(TRP_ROUTE *entry, int local)
+{
+  entry->local=local;
+}
+
+int trp_route_is_local(TRP_ROUTE *entry)
+{
+  return entry->local;
+}
+
+void trp_route_set_triggered(TRP_ROUTE *entry, int trig)
 {
   entry->triggered=trig;
 }
 
-int trp_rentry_get_triggered(TRP_RENTRY *entry)
+int trp_route_is_triggered(TRP_ROUTE *entry)
 {
   return entry->triggered;
 }
@@ -186,6 +209,8 @@ int trp_rentry_get_triggered(TRP_RENTRY *entry)
 static gchar *tr_name_to_g_str(const TR_NAME *n)
 {
   gchar *s=g_strndup(n->buf, n->len);
+  if (s==NULL)
+    tr_debug("tr_name_to_g_str: allocation failure.");
   return s;
 }
 
@@ -220,7 +245,7 @@ static void trp_rtable_destroy_table(gpointer data)
 
 static void trp_rtable_destroy_rentry(gpointer data)
 {
-  trp_rentry_free(data);
+  trp_route_free(data);
 }
 
 static void trp_rtable_destroy_tr_name(gpointer data)
@@ -257,7 +282,7 @@ static GHashTable *trp_rtbl_get_or_add_table(GHashTable *tbl, TR_NAME *key, GDes
   return val_tbl;
 }
 
-void trp_rtable_add(TRP_RTABLE *rtbl, TRP_RENTRY *entry)
+void trp_rtable_add(TRP_RTABLE *rtbl, TRP_ROUTE *entry)
 {
   GHashTable *apc_tbl=NULL;
   GHashTable *realm_tbl=NULL;
@@ -270,7 +295,7 @@ void trp_rtable_add(TRP_RTABLE *rtbl, TRP_RENTRY *entry)
 }
 
 /* note: the entry pointer passed in is invalid after calling this because the entry is freed */
-void trp_rtable_remove(TRP_RTABLE *rtbl, TRP_RENTRY *entry)
+void trp_rtable_remove(TRP_RTABLE *rtbl, TRP_ROUTE *entry)
 {
   GHashTable *apc_tbl=NULL;
   GHashTable *realm_tbl=NULL;
@@ -361,15 +386,15 @@ size_t trp_rtable_realm_size(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm)
                                realm));
 }
 
-/* Returns an array of pointers to TRP_RENTRY, length of array in n_out.
+/* Returns an array of pointers to TRP_ROUTE, length of array in n_out.
  * Caller must free the array (in the talloc NULL context), but must
  * not free its contents. */
-TRP_RENTRY **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out)
+TRP_ROUTE **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out)
 {
-  TRP_RENTRY **ret=NULL;
+  TRP_ROUTE **ret=NULL;
   TR_NAME **apc=NULL;
   size_t n_apc=0;
-  TRP_RENTRY **apc_entries=NULL;
+  TRP_ROUTE **apc_entries=NULL;
   size_t n_entries=0;
   size_t ii_ret=0;
 
@@ -377,7 +402,7 @@ TRP_RENTRY **trp_rtable_get_entries(TRP_RTABLE *rtbl, size_t *n_out)
   if (*n_out==0)
     return NULL;
 
-  ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
+  ret=talloc_array(NULL, TRP_ROUTE *, *n_out);
   if (ret==NULL) {
     tr_crit("trp_rtable_get_entries: unable to allocate return array.");
     *n_out=0;
@@ -461,21 +486,21 @@ TR_NAME **trp_rtable_get_apc_realms(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_ou
 /* Get all entries in an apc. Returns an array of pointers in NULL talloc context.
  * Caller must free this list with talloc_free, but must not free the entries in the
  * list.. */
-TRP_RENTRY **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out)
+TRP_ROUTE **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *n_out)
 {
   size_t ii=0, jj=0;
   TR_NAME **realm=NULL;
   size_t n_realms=0;
-  TRP_RENTRY **realm_entries=NULL;
+  TRP_ROUTE **realm_entries=NULL;
   size_t n_entries=0;
-  TRP_RENTRY **ret=NULL;
+  TRP_ROUTE **ret=NULL;
   size_t ii_ret=0;
 
   *n_out=trp_rtable_apc_size(rtbl, apc);
   if (*n_out==0)
     return NULL;
 
-  ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
+  ret=talloc_array(NULL, TRP_ROUTE *, *n_out);
   if (ret==NULL) {
     tr_crit("trp_rtable_get_apc_entries: could not allocate return array.");
     *n_out=0;
@@ -505,14 +530,14 @@ TRP_RENTRY **trp_rtable_get_apc_entries(TRP_RTABLE *rtbl, TR_NAME *apc, size_t *
 /* Get all entries in an apc/realm. Returns an array of pointers in NULL talloc context.
  * Caller must free this list with talloc_free, but must not free the entries in the
  * list.. */
-TRP_RENTRY **trp_rtable_get_realm_entries(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out)
+TRP_ROUTE **trp_rtable_get_realm_entries(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, size_t *n_out)
 {
   size_t ii=0;
-  TRP_RENTRY **ret=NULL;
+  TRP_ROUTE **ret=NULL;
   TR_NAME **peer=NULL;
 
   peer=trp_rtable_get_apc_realm_peers(rtbl, apc, realm, n_out);
-  ret=talloc_array(NULL, TRP_RENTRY *, *n_out);
+  ret=talloc_array(NULL, TRP_ROUTE *, *n_out);
   if (ret==NULL) {
     tr_crit("trp_rtable_get_realm_entries: could not allocate return array.");
     talloc_free(peer);
@@ -551,7 +576,7 @@ TR_NAME **trp_rtable_get_apc_realm_peers(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME
 }
 
 /* Gets a single entry. Do not free it. */
-TRP_RENTRY *trp_rtable_get_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, TR_NAME *peer)
+TRP_ROUTE *trp_rtable_get_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm, TR_NAME *peer)
 {
   GHashTable *realm_tbl=NULL;
 
@@ -581,16 +606,16 @@ static char *timespec_to_str(struct timespec *ts)
   return s;
 }
 
-TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm)
+TRP_ROUTE *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm)
 {
   size_t n=0;
-  TRP_RENTRY **entry=trp_rtable_get_realm_entries(rtbl, apc, realm, &n);
-  TRP_RENTRY *selected=NULL;
+  TRP_ROUTE **entry=trp_rtable_get_realm_entries(rtbl, apc, realm, &n);
+  TRP_ROUTE *selected=NULL;
 
   if (n==0)
     return NULL;
 
-  while(n-- && !trp_rentry_get_selected(entry[n])) { }
+  while(n-- && !trp_route_is_selected(entry[n])) { }
   selected=entry[n];
   talloc_free(entry);
   return selected;
@@ -598,7 +623,7 @@ TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAM
 
 /* Pretty print a route table entry to a newly allocated string. If sep is NULL,
  * returns comma+space separated string. */
-char *trp_rentry_to_str(TALLOC_CTX *mem_ctx, TRP_RENTRY *entry, const char *sep)
+char *trp_route_to_str(TALLOC_CTX *mem_ctx, TRP_ROUTE *entry, const char *sep)
 {
   char *apc=tr_name_strdup(entry->apc);
   char *realm=tr_name_strdup(entry->realm);
@@ -612,7 +637,7 @@ char *trp_rentry_to_str(TALLOC_CTX *mem_ctx, TRP_RENTRY *entry, const char *sep)
     sep=", ";
 
   result=talloc_asprintf(mem_ctx,
-                         "%s%s%s%s%s%s%u%s%s%s%s%s%d%s%s",
+                         "%s%s%s%s%s%s%u%s%s%s%s%s%u%s%u%s%s%s%u",
                          apc, sep,
                          realm, sep,
                          peer, sep,
@@ -620,7 +645,9 @@ char *trp_rentry_to_str(TALLOC_CTX *mem_ctx, TRP_RENTRY *entry, const char *sep)
                          trust_router, sep,
                          next_hop, sep,
                          entry->selected, sep,
-                         expiry);
+                         entry->local, sep,
+                         expiry, sep,
+                         entry->triggered);
   free(apc);
   free(realm);
   free(peer);
@@ -633,12 +660,12 @@ char *trp_rentry_to_str(TALLOC_CTX *mem_ctx, TRP_RENTRY *entry, const char *sep)
 void trp_rtable_clear_triggered(TRP_RTABLE *rtbl)
 {
   size_t n_entries=0;
-  TRP_RENTRY **entries=trp_rtable_get_entries(rtbl, &n_entries);
+  TRP_ROUTE **entries=trp_rtable_get_entries(rtbl, &n_entries);
   size_t ii=0;
 
   if (entries!=NULL) {
     for (ii=0; ii<n_entries; ii++)
-      trp_rentry_set_triggered(entries[ii], 0);
+      trp_route_set_triggered(entries[ii], 0);
     talloc_free(entries);
   }
 }
@@ -662,7 +689,7 @@ char *trp_rtable_to_str(TALLOC_CTX *mem_ctx, TRP_RTABLE *rtbl, const char *sep,
   size_t n_apcs=0;
   TR_NAME **realms=NULL;
   size_t n_realms=0;
-  TRP_RENTRY **entries=NULL;
+  TRP_ROUTE **entries=NULL;
   size_t n_entries=0;
   char **tbl_strings=NULL;
   size_t ii_tbl=0; /* counts tbl_strings */
@@ -700,7 +727,7 @@ char *trp_rtable_to_str(TALLOC_CTX *mem_ctx, TRP_RTABLE *rtbl, const char *sep,
       entries=trp_rtable_get_realm_entries(rtbl, apcs[ii], realms[jj], &n_entries);
       talloc_steal(tmp_ctx, entries);
       for (kk=0; kk<n_entries; kk++) {
-        tbl_strings[ii_tbl]=trp_rentry_to_str(tmp_ctx, entries[kk], sep);
+        tbl_strings[ii_tbl]=trp_route_to_str(tmp_ctx, entries[kk], sep);
         len+=strlen(tbl_strings[ii_tbl]);
         ii_tbl++;
       }
index 9fd079f..58e8061 100644 (file)
@@ -25,7 +25,6 @@ TRPC_INSTANCE *trpc_new (TALLOC_CTX *mem_ctx)
     trpc->server=NULL;
     trpc->port=0;
     trpc->conn=NULL;
-    trpc->dh=NULL;
     trpc->mq=tr_mq_new(trpc);
     if (trpc->mq==NULL) {
       talloc_free(trpc);
@@ -135,16 +134,6 @@ void trpc_set_conn(TRPC_INSTANCE *trpc, TRP_CONNECTION *conn)
   trpc->conn=conn;
 }
 
-DH *trpc_get_dh(TRPC_INSTANCE *trpc)
-{
-  return trpc->dh;
-}
-
-void trpc_set_dh(TRPC_INSTANCE *trpc, DH *dh)
-{
-  trpc->dh=dh;
-}
-
 TRP_CONNECTION_STATUS trpc_get_status(TRPC_INSTANCE *trpc)
 {
   return trp_connection_get_status(trpc_get_conn(trpc));
index 03567dd..ec4ada5 100644 (file)
@@ -252,12 +252,12 @@ int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName, void *data)
 #endif 
 
 /* get the currently selected route if available */
-TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer)
+TRP_ROUTE *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer)
 {
   return trp_rtable_get_entry(trps->rtable, comm, realm, peer);
 }
 
-TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm)
+TRP_ROUTE *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm)
 {
   return trp_rtable_get_selected_entry(trps->rtable, comm, realm);
 }
@@ -265,24 +265,25 @@ TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME
 /* copy the result if you want to keep it */
 TR_NAME *trps_get_next_hop(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm)
 {
-  TRP_RENTRY *route=trps_get_selected_route(trps, comm, realm);
+  TRP_ROUTE *route=trps_get_selected_route(trps, comm, realm);
   if (route==NULL)
     return NULL;
 
-  return trp_rentry_get_next_hop(route);
+  return trp_route_get_next_hop(route);
 }
 
 
 /* mark a route as retracted */
-static void trps_retract_route(TRPS_INSTANCE *trps, TRP_RENTRY *entry)
+static void trps_retract_route(TRPS_INSTANCE *trps, TRP_ROUTE *entry)
 {
-  trp_rentry_set_metric(entry, TRP_METRIC_INFINITY);
+  trp_route_set_metric(entry, TRP_METRIC_INFINITY);
+  trp_route_set_triggered(entry, 1);
 }
 
 /* is this route retracted? */
-static int trps_route_retracted(TRPS_INSTANCE *trps, TRP_RENTRY *entry)
+static int trps_route_retracted(TRPS_INSTANCE *trps, TRP_ROUTE *entry)
 {
-  return (trp_metric_is_infinite(trp_rentry_get_metric(entry)));
+  return (trp_metric_is_infinite(trp_route_get_metric(entry)));
 }
 
 static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MSG **msg)
@@ -376,36 +377,35 @@ int trps_get_listener(TRPS_INSTANCE *trps,
 
 void trps_handle_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
 {
-  TALLOC_CTX *tmp_ctx=talloc_new(NULL);
   TR_MSG *msg=NULL;
   TRP_RC rc=TRP_ERROR;
 
   /* try to establish a GSS context */
   if (0!=trp_connection_auth(conn, trps->auth_handler, trps->cookie)) {
     tr_notice("tr_trps_conn_thread: failed to authorize connection");
-    pthread_exit(NULL);
-  }
-  tr_notice("trps_handle_connection: authorized connection");
+    trp_connection_close(conn);
+  } else {
+    tr_notice("trps_handle_connection: authorized connection");
   
-  /* loop as long as the connection exists */
-  while (trp_connection_get_status(conn)==TRP_CONNECTION_UP) {
-    rc=trps_read_message(trps, conn, &msg);
-    switch(rc) {
-    case TRP_SUCCESS:
-      trps->msg_handler(trps, conn, msg); /* send the TR_MSG off to the callback */
-      break;
-
-    case TRP_ERROR:
-      trp_connection_close(conn);
-      break;
-
-    default:
-      tr_debug("trps_handle_connection: trps_read_message failed (%d)", rc);
+    /* loop as long as the connection exists */
+    while (trp_connection_get_status(conn)==TRP_CONNECTION_UP) {
+      rc=trps_read_message(trps, conn, &msg);
+      switch(rc) {
+      case TRP_SUCCESS:
+        trps->msg_handler(trps, conn, msg); /* send the TR_MSG off to the callback */
+        break;
+
+      case TRP_ERROR:
+        trp_connection_close(conn);
+        break;
+
+      default:
+        tr_debug("trps_handle_connection: trps_read_message failed (%d)", rc);
+      }
     }
-  }
 
-  tr_debug("trps_handle_connection: connection closed.");
-  talloc_free(tmp_ctx);
+    tr_debug("trps_handle_connection: connection closed.");
+  }
 }
 
 static TRP_RC trps_validate_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
@@ -465,10 +465,10 @@ static unsigned int trps_cost(TRPS_INSTANCE *trps, TR_NAME *peer)
 
 static unsigned int trps_advertised_metric(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer)
 {
-  TRP_RENTRY *entry=trp_rtable_get_entry(trps->rtable, comm, realm, peer);
+  TRP_ROUTE *entry=trp_rtable_get_entry(trps->rtable, comm, realm, peer);
   if (entry==NULL)
     return TRP_METRIC_INFINITY;
-  return trp_rentry_get_metric(entry) + trps_cost(trps, peer);
+  return trp_route_get_metric(entry) + trps_cost(trps, peer);
 }
 
 static int trps_check_feasibility(TRPS_INSTANCE *trps, TRP_INFOREC *rec)
@@ -524,32 +524,32 @@ static struct timespec *trps_compute_expiry(TRPS_INSTANCE *trps, unsigned int in
 
 static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec)
 {
-  TRP_RENTRY *entry=NULL;
+  TRP_ROUTE *entry=NULL;
 
   entry=trp_rtable_get_entry(trps->rtable,
                              trp_inforec_get_comm(rec),
                              trp_inforec_get_realm(rec),
                              trp_inforec_get_next_hop(rec));
   if (entry==NULL) {
-    entry=trp_rentry_new(NULL);
+    entry=trp_route_new(NULL);
     if (entry==NULL) {
       tr_err("trps_accept_update: unable to allocate new entry.");
       return TRP_NOMEM;
     }
 
-    trp_rentry_set_apc(entry, tr_dup_name(trp_inforec_get_comm(rec)));
-    trp_rentry_set_realm(entry, tr_dup_name(trp_inforec_get_realm(rec)));
-    trp_rentry_set_peer(entry, tr_dup_name(trp_inforec_get_next_hop(rec)));
-    trp_rentry_set_trust_router(entry, tr_dup_name(trp_inforec_get_trust_router(rec)));
-    trp_rentry_set_next_hop(entry, tr_dup_name(trp_inforec_get_next_hop(rec)));
-    if ((trp_rentry_get_apc(entry)==NULL)
-       ||(trp_rentry_get_realm(entry)==NULL)
-       ||(trp_rentry_get_peer(entry)==NULL)
-       ||(trp_rentry_get_trust_router(entry)==NULL)
-       ||(trp_rentry_get_next_hop(entry)==NULL)) {
+    trp_route_set_apc(entry, tr_dup_name(trp_inforec_get_comm(rec)));
+    trp_route_set_realm(entry, tr_dup_name(trp_inforec_get_realm(rec)));
+    trp_route_set_peer(entry, tr_dup_name(trp_inforec_get_next_hop(rec)));
+    trp_route_set_trust_router(entry, tr_dup_name(trp_inforec_get_trust_router(rec)));
+    trp_route_set_next_hop(entry, tr_dup_name(trp_inforec_get_next_hop(rec)));
+    if ((trp_route_get_apc(entry)==NULL)
+       ||(trp_route_get_realm(entry)==NULL)
+       ||(trp_route_get_peer(entry)==NULL)
+       ||(trp_route_get_trust_router(entry)==NULL)
+       ||(trp_route_get_next_hop(entry)==NULL)) {
       /* at least one field could not be allocated */
       tr_err("trps_accept_update: unable to allocate all fields for entry.");
-      trp_rentry_free(entry);
+      trp_route_free(entry);
       return TRP_NOMEM;
     }
     trp_rtable_add(trps->rtable, entry);
@@ -560,13 +560,22 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec)
    * route (we never accept retractions as new routes), so there is no risk of leaving the expiry
    * 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));
+  trp_route_set_metric(entry, trp_inforec_get_metric(rec));
+  trp_route_set_interval(entry, trp_inforec_get_interval(rec));
+
+  /* check whether the trust router has changed */
+  if (0!=tr_name_cmp(trp_route_get_trust_router(entry),
+                     trp_inforec_get_trust_router(rec))) {
+    /* The name changed. Set this route as triggered. */
+    tr_debug("trps_accept_update: trust router for route changed.");
+    trp_route_set_triggered(entry, 1);
+    trp_route_set_trust_router(entry, trp_inforec_dup_trust_router(rec)); /* frees old name */
+  }
   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_rentry_get_interval(entry),
-                                                     trp_rentry_get_expiry(entry)));
+    trp_route_set_expiry(entry, trps_compute_expiry(trps,
+                                                     trp_route_get_interval(entry),
+                                                     trp_route_get_expiry(entry)));
   }
   return TRP_SUCCESS;
 }
@@ -576,15 +585,14 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
 {
   unsigned int feas=0;
   TRP_INFOREC *rec=NULL;
-  TRP_RENTRY *route=NULL;
+  TRP_ROUTE *route=NULL;
 
   if (trps_validate_update(trps, upd) != TRP_SUCCESS) {
     tr_notice("trps_handle_update: received invalid TRP update.");
     return TRP_ERROR;
   }
 
-  rec=trp_upd_get_inforec(upd);
-  for (;rec!=NULL; rec=trp_inforec_get_next(rec)) {
+  for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
     /* validate/sanity check the record update */
     if (trps_validate_inforec(trps, rec) != TRP_SUCCESS) {
       tr_notice("trps_handle_update: invalid record in TRP update.");
@@ -596,7 +604,10 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
     tr_debug("trps_handle_update: record feasibility=%d", feas);
 
     /* do we have an existing route? */
-    route=trps_get_route(trps, trp_inforec_get_comm(rec), trp_inforec_get_realm(rec), trp_inforec_get_next_hop(rec));
+    route=trps_get_route(trps,
+                         trp_inforec_get_comm(rec),
+                         trp_inforec_get_realm(rec),
+                         trp_inforec_get_next_hop(rec));
     if (route!=NULL) {
       /* there was a route table entry already */
       tr_debug("trps_handle_updates: route entry already exists.");
@@ -605,7 +616,7 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
         trps_accept_update(trps, rec);
       } else {
         /* Update is infeasible. Ignore it unless the trust router has changed. */
-        if (0!=tr_name_cmp(trp_rentry_get_trust_router(route),
+        if (0!=tr_name_cmp(trp_route_get_trust_router(route),
                            trp_inforec_get_trust_router(rec))) {
           /* the trust router associated with the route has changed, treat update as a retraction */
           trps_retract_route(trps, route);
@@ -622,10 +633,13 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
 }
 
 /* choose the best route to comm/realm, optionally excluding routes to a particular peer */
-static TRP_RENTRY *trps_find_best_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *exclude_peer)
+static TRP_ROUTE *trps_find_best_route(TRPS_INSTANCE *trps,
+                                        TR_NAME *comm,
+                                        TR_NAME *realm,
+                                        TR_NAME *exclude_peer)
 {
-  TRP_RENTRY **entry=NULL;
-  TRP_RENTRY *best=NULL;
+  TRP_ROUTE **entry=NULL;
+  TRP_ROUTE *best=NULL;
   size_t n_entry=0;
   unsigned int kk=0;
   unsigned int kk_min=0;
@@ -633,15 +647,15 @@ static TRP_RENTRY *trps_find_best_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_N
 
   entry=trp_rtable_get_realm_entries(trps->rtable, comm, realm, &n_entry);
   for (kk=0; kk<n_entry; kk++) {
-    if (trp_rentry_get_metric(entry[kk]) < min_metric) {
-      if ((exclude_peer==NULL) || (0!=tr_name_cmp(trp_rentry_get_peer(entry[kk]),
+    if (trp_route_get_metric(entry[kk]) < min_metric) {
+      if ((exclude_peer==NULL) || (0!=tr_name_cmp(trp_route_get_peer(entry[kk]),
                                                   exclude_peer))) {
         kk_min=kk;
-        min_metric=trp_rentry_get_metric(entry[kk]);
-      }
+        min_metric=trp_route_get_metric(entry[kk]);
+      } 
     }
   }
-  if (trp_metric_is_finite(min_metric));
+  if (trp_metric_is_finite(min_metric))
     best=entry[kk_min];
   
   talloc_free(entry);
@@ -656,7 +670,7 @@ TRP_RC trps_update_active_routes(TRPS_INSTANCE *trps)
   TR_NAME **apc=trp_rtable_get_apcs(trps->rtable, &n_apc);
   size_t n_realm=0, jj=0;
   TR_NAME **realm=NULL;
-  TRP_RENTRY *best_route=NULL, *cur_route=NULL;
+  TRP_ROUTE *best_route=NULL, *cur_route=NULL;
   unsigned int best_metric=0, cur_metric=0;
 
   for (ii=0; ii<n_apc; ii++) {
@@ -666,25 +680,20 @@ TRP_RC trps_update_active_routes(TRPS_INSTANCE *trps)
       if (best_route==NULL)
         best_metric=TRP_METRIC_INFINITY;
       else
-        best_metric=trp_rentry_get_metric(best_route);
+        best_metric=trp_route_get_metric(best_route);
 
       cur_route=trps_get_selected_route(trps, apc[ii], realm[jj]);
       if (cur_route!=NULL) {
-        cur_metric=trp_rentry_get_metric(cur_route);
+        cur_metric=trp_route_get_metric(cur_route);
         if ((best_metric < cur_metric) && (trp_metric_is_finite(best_metric))) {
           /* The new route has a lower metric than the previous, and is finite. Accept. */
-          trp_rentry_set_selected(cur_route, 0);
-          trp_rentry_set_selected(best_route, 1);
-          /* Check whether we just changed trust routers for this destination. If so,
-           * we must send a triggered update. (We should probably try to avoid changing
-           * trust routers, perhaps accepting a slightly worse metric, but that is todo.) */
-          if (0!=tr_name_cmp(trp_rentry_get_trust_router(cur_route),
-                             trp_rentry_get_trust_router(best_route)))
-            trp_rentry_set_triggered(best_route, 1); /* need to send a triggered update for this route */
+          trp_route_set_selected(cur_route, 0);
+          trp_route_set_selected(best_route, 1);
         } else if (!trp_metric_is_finite(cur_metric)) /* rejects infinite or invalid metrics */
-          trp_rentry_set_selected(cur_route, 0);
-      } else if (trp_metric_is_finite(best_metric))
-        trp_rentry_set_selected(best_route, 1);
+          trp_route_set_selected(cur_route, 0);
+      } else if (trp_metric_is_finite(best_metric)) {
+        trp_route_set_selected(best_route, 1);
+      }
     }
     if (realm!=NULL)
       talloc_free(realm);
@@ -732,7 +741,7 @@ static int trps_expired(struct timespec *expiry, struct timespec *curtime)
 TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps)
 {
   struct timespec sweep_time={0,0};
-  TRP_RENTRY **entry=NULL;
+  TRP_ROUTE **entry=NULL;
   size_t n_entry=0;
   size_t ii=0;
 
@@ -748,9 +757,9 @@ TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps)
 
   /* loop over the entries */
   for (ii=0; ii<n_entry; ii++) {
-    if (trps_expired(trp_rentry_get_expiry(entry[ii]), &sweep_time)) {
+    if (!trp_route_is_local(entry[ii]) && trps_expired(trp_route_get_expiry(entry[ii]), &sweep_time)) {
       tr_debug("trps_sweep_routes: route expired.");
-      if (!trp_metric_is_finite(trp_rentry_get_metric(entry[ii]))) {
+      if (!trp_metric_is_finite(trp_route_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 */
@@ -758,10 +767,10 @@ TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps)
       } 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])));
+        trp_route_set_metric(entry[ii], TRP_METRIC_INFINITY);
+        trp_route_set_expiry(entry[ii], trps_compute_expiry(trps,
+                                                             trp_route_get_interval(entry[ii]),
+                                                             trp_route_get_expiry(entry[ii])));
       }
     }
   }
@@ -771,9 +780,9 @@ TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps)
 }
 
 /* select the correct route to comm/realm to be announced to peer */
-static TRP_RENTRY *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer_gssname)
+static TRP_ROUTE *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer_gssname)
 {
-  TRP_RENTRY *route;
+  TRP_ROUTE *route;
 
   /* Take the currently selected route unless it is through the peer we're sending the update to.
    * I.e., enforce the split horizon rule. */
@@ -784,12 +793,12 @@ static TRP_RENTRY *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm,
     return NULL;
   }
   tr_debug("trps_select_realm_update: %s vs %s", peer_gssname->buf,
-           trp_rentry_get_peer(route)->buf);
-  if (0==tr_name_cmp(peer_gssname, trp_rentry_get_peer(route))) {
+           trp_route_get_peer(route)->buf);
+  if (0==tr_name_cmp(peer_gssname, trp_route_get_peer(route))) {
     tr_debug("trps_select_realm_update: matched, finding alternate route");
     /* the selected entry goes through the peer we're reporting to, choose an alternate */
     route=trps_find_best_route(trps, comm, realm, peer_gssname);
-    if ((route==NULL) || (!trp_metric_is_finite(trp_rentry_get_metric(route))))
+    if ((route==NULL) || (!trp_metric_is_finite(trp_route_get_metric(route))))
       return NULL; /* don't advertise a nonexistent or retracted route */
   }
   return route;
@@ -798,7 +807,7 @@ static TRP_RENTRY *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm,
 /* returns an array of pointers to updates (*not* an array of updates). Returns number of entries
  * via n_update parameter. (The allocated space will generally be larger than required, see note in
  * the code.) If triggered is set, sends only triggered updates. */
-static TRP_RENTRY **trps_select_updates_for_peer(TALLOC_CTX *memctx,
+static TRP_ROUTE **trps_select_updates_for_peer(TALLOC_CTX *memctx,
                                                  TRPS_INSTANCE *trps,
                                                  TR_NAME *peer_gssname,
                                                  int triggered,
@@ -809,15 +818,15 @@ static TRP_RENTRY **trps_select_updates_for_peer(TALLOC_CTX *memctx,
   TR_NAME **realm=NULL;
   size_t n_realm=0;
   size_t ii=0, jj=0;
-  TRP_RENTRY *best=NULL;
-  TRP_RENTRY **result=NULL;
+  TRP_ROUTE *best=NULL;
+  TRP_ROUTE **result=NULL;
   size_t n_used=0;
 
   /* Need to allocate space for the results. For simplicity, we just allocate a block
    * with space for every route table entry to be returned. This is guaranteed to be large
    * enough. If the routing table gets very large, this may be wasteful, but that seems
    * unlikely to be significant in the near future. */
-  result=talloc_array(memctx, TRP_RENTRY *, trp_rtable_size(trps->rtable));
+  result=talloc_array(memctx, TRP_ROUTE *, trp_rtable_size(trps->rtable));
   if (result==NULL) {
     talloc_free(apc);
     *n_update=0;
@@ -830,7 +839,7 @@ static TRP_RENTRY **trps_select_updates_for_peer(TALLOC_CTX *memctx,
       best=trps_select_realm_update(trps, apc[ii], realm[jj], peer_gssname);
       /* If we found a route, add it to the list. If triggered!=0, then only
        * add triggered routes. */
-      if ((best!=NULL) && ((!triggered) || trp_rentry_get_triggered(best)))
+      if ((best!=NULL) && ((!triggered) || trp_route_is_triggered(best)))
         result[n_used++]=best;
     }
     if (realm!=NULL)
@@ -845,24 +854,45 @@ static TRP_RENTRY **trps_select_updates_for_peer(TALLOC_CTX *memctx,
   return result;
 }
 
+/* add metrics */
+static unsigned int trps_metric_add(unsigned int m1, unsigned int m2)
+{
+  if (trp_metric_is_invalid(m1) || trp_metric_is_invalid(m2))
+    return TRP_METRIC_INVALID;
+
+  if (trp_metric_is_infinite(m1) || trp_metric_is_infinite(m2))
+    return TRP_METRIC_INFINITY;
+
+  if (trp_metric_is_finite(m1+m2))
+    return m1+m2;
+  else
+    return TRP_METRIC_INFINITY;
+}
+
 /* convert an rentry into a new trp update info record */
-static TRP_INFOREC *trps_rentry_to_inforec(TALLOC_CTX *mem_ctx, TRPS_INSTANCE *trps, TRP_RENTRY *entry)
+static TRP_INFOREC *trps_route_to_inforec(TALLOC_CTX *mem_ctx, TRPS_INSTANCE *trps, TRP_ROUTE *route)
 {
   TRP_INFOREC *rec=trp_inforec_new(mem_ctx, TRP_INFOREC_TYPE_ROUTE);
   unsigned int linkcost=0;
 
   if (rec!=NULL) {
-    linkcost=trp_peer_get_linkcost(trps_get_peer(trps,
-                                                 trp_rentry_get_next_hop(entry)));
+    if (trp_route_is_local(route))
+      linkcost=0;
+    else {
+      linkcost=trp_peer_get_linkcost(trps_get_peer(trps,
+                                                   trp_route_get_next_hop(route)));
+    }
 
     /* 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_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)
+    if ((trp_inforec_set_comm(rec, trp_route_dup_apc(route)) != TRP_SUCCESS)
+       ||(trp_inforec_set_realm(rec, trp_route_dup_realm(route)) != TRP_SUCCESS)
+       ||(trp_inforec_set_trust_router(rec, trp_route_dup_trust_router(route)) != TRP_SUCCESS)
+       ||(trp_inforec_set_metric(rec,
+                                 trps_metric_add(trp_route_get_metric(route),
+                                                 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.");
+      tr_err("trps_route_to_inforec: error creating route update.");
       talloc_free(rec);
       rec=NULL;
     }
@@ -877,7 +907,7 @@ TRP_RC trps_update(TRPS_INSTANCE *trps, TRP_UPDATE_TYPE triggered)
   TRP_PEER *peer=NULL;
   TR_MSG msg; /* not a pointer! */
   TRP_UPD *upd=NULL;
-  TRP_RENTRY **update_list=NULL;
+  TRP_ROUTE **update_list=NULL;
   TRP_INFOREC *rec=NULL;
   size_t n_updates=0, ii=0;
   char *encoded=NULL;
@@ -918,7 +948,7 @@ TRP_RC trps_update(TRPS_INSTANCE *trps, TRP_UPDATE_TYPE triggered)
       upd=trp_upd_new(tmp_ctx);
 
       for (ii=0; ii<n_updates; ii++) {
-        rec=trps_rentry_to_inforec(tmp_ctx, trps, update_list[ii]);
+        rec=trps_route_to_inforec(tmp_ctx, trps, update_list[ii]);
         if (rec==NULL) {
           tr_err("trps_update: could not create all update records.");
           rc=TRP_ERROR;
@@ -958,12 +988,13 @@ cleanup:
   return rc;
 }        
 
-TRP_RC trps_add_route(TRPS_INSTANCE *trps, TRP_RENTRY *route)
+TRP_RC trps_add_route(TRPS_INSTANCE *trps, TRP_ROUTE *route)
 {
   trp_rtable_add(trps->rtable, route); /* should return status */
   return TRP_SUCCESS; 
 }
 
+/* steals the peer object */
 TRP_RC trps_add_peer(TRPS_INSTANCE *trps, TRP_PEER *peer)
 {
   return trp_ptable_add(trps->ptable, peer);