Fix bugs in community flooding and TID forwarding.
authorJennifer Richards <jennifer@painless-security.com>
Mon, 19 Dec 2016 21:57:39 +0000 (16:57 -0500)
committerJennifer Richards <jennifer@painless-security.com>
Mon, 19 Dec 2016 21:57:39 +0000 (16:57 -0500)
Now uses "hostname:port" as the peer label instead of the gss credential
name. This allows the same label to be used to identify the local
trust router when avoiding community loops. Fixes several bugs that
prevented TID forwarding from working reliably, notably by properly
initializing the next pointer in a TR_AAA_SERVER structure to null.

Makefile.am
common/tr_comm.c
common/tr_idp.c
include/trp_ptable.h
include/trust_router/trp.h
tid/tids.c
tr/tr_main.c
tr/tr_tid.c
trp/trp_ptable.c
trp/trp_upd.c
trp/trps.c

index a1ae178..aa266a0 100644 (file)
@@ -30,33 +30,22 @@ trp/trp_ptable.c \
 trp/trp_rtable.c \
 trp/trp_req.c \
 trp/trp_upd.c \
-tid/tid_resp.c \
-tid/tid_req.c \
-common/tr_gss.c \
 common/tr_config.c \
-common/tr_idp.c \
-common/tr_apc.c \
-common/tr_comm.c \
-common/tr_filter.c \
-common/tr_rp.c \
-common/tr_msg.c \
-common/tr_constraint.c \
-common/tr_name.c \
 common/tr_mq.c
 
 check_PROGRAMS = common/t_constraint
 TESTS = common/t_constraint
 
-lib_LTLIBRARIES = libtr_tid.la
+#lib_LTLIBRARIES = libtr_tid.la
 
-libtr_tid_la_SOURCES = $(tid_srcs) \
-$(common_srcs) \
-trp/trp_req.c \
-trp/trp_upd.c
-
-libtr_tid_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
-libtr_tid_la_LIBADD = gsscon/libgsscon.la $(GLIB_LIBS)
-libtr_tid_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2 -no-undefined
+libtr_tid_la_SOURCES = $(tid_srcs) \
+$(common_srcs) \
+trp/trp_req.c \
+trp/trp_upd.c
+# 
+libtr_tid_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
+libtr_tid_la_LIBADD = gsscon/libgsscon.la $(GLIB_LIBS)
+libtr_tid_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2 -no-undefined
 
 common_t_constraint_SOURCES = common/t_constraint.c \
 common/tr_debug.c \
@@ -74,11 +63,14 @@ tr/tr_event.c \
 tr/tr_cfgwatch.c \
 tr/tr_tid.c \
 tr/tr_trp.c \
-$(trp_srcs)
+$(tid_srcs) \
+$(trp_srcs) \
+$(common_srcs)
 
 tr_trust_router_CFLAGS = $(AM_CFLAGS) -pthread
 tr_trust_router_LDFLAGS = $(AM_LDFLAGS) -levent_pthreads -pthread
-tr_trust_router_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
+#tr_trust_router_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
+tr_trust_router_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
 
 tr_trpc_SOURCES =tr/trpc_main.c \
 tr/tr_trp.c \
@@ -142,11 +134,11 @@ common/tests/thread_test.c
 common_tests_thread_test_CFLAGS = -pthread
 common_tests_thread_test_LDFLAGS = $(AM_LDFLAGS) -ltalloc
 
-common_tests_commtest_SOURCES = common/tests/commtest.c \
-$(trp_srcs)
-common_tests_commtest_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
-common_tests_commtest_CFLAGS = -pthread
-common_test_commtest_LDFLAGS = $(AM_LDFLAGS) -ltalloc
+common_tests_commtest_SOURCES = common/tests/commtest.c \
+$(trp_srcs)
+common_tests_commtest_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
+common_tests_commtest_CFLAGS = -pthread
+common_test_commtest_LDFLAGS = $(AM_LDFLAGS) -ltalloc
 
 pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
        include/tr_debug.h \
index 0a0fd93..750651f 100644 (file)
@@ -1404,6 +1404,18 @@ TR_REALM_ROLE tr_realm_role_from_str(const char *s)
   return TR_ROLE_UNKNOWN;
 }
 
+static void tr_comm_table_print_provenance(FILE *f, json_t *prov)
+{
+  const char *s=NULL;
+  size_t ii=0;
+
+  for (ii=0; ii<json_array_size(prov); ii++) {
+    s=json_string_value(json_array_get(prov, ii));
+    if (s!=NULL)
+      fprintf(f, "%s%s", s, ((ii+1)==json_array_size(prov))?"":", ");
+  }
+}
+
 void tr_comm_table_print(FILE *f, TR_COMM_TABLE *ctab)
 {
   TR_COMM_MEMB *p1=NULL; /* for walking the main list */
@@ -1411,16 +1423,20 @@ void tr_comm_table_print(FILE *f, TR_COMM_TABLE *ctab)
 
   fprintf(f, ">> Membership table start <<\n");
   for (p1=ctab->memberships; p1!=NULL; p1=p1->next) {
-    fprintf(f, "* %s %s/%s\n  %s (%p)\n",
+    fprintf(f, "* %s %s/%s\n  %s (%p) - prov: ",
             tr_realm_role_to_str(tr_comm_memb_get_role(p1)),
             tr_comm_memb_get_realm_id(p1)->buf,
             tr_comm_get_id(tr_comm_memb_get_comm(p1))->buf,
             (tr_comm_memb_get_origin(p1)==NULL)?"null origin":(tr_comm_memb_get_origin(p1)->buf),
             p1);
+    tr_comm_table_print_provenance(f, p1->provenance);
+    fprintf(f, "\n");
     for (p2=p1->origin_next; p2!=NULL; p2=p2->origin_next) {
-      fprintf(f, "  %s (%p)\n",
+      fprintf(f, "  %s (%p) - prov: ",
               (tr_comm_memb_get_origin(p2)==NULL)?"null origin":(tr_comm_memb_get_origin(p2)->buf),
               p2);
+      tr_comm_table_print_provenance(f, p2->provenance);
+      fprintf(f, "\n");
     }
     fprintf(f, "\n");
   }
index fc325dc..10bb2c3 100644 (file)
@@ -52,6 +52,7 @@ TR_AAA_SERVER *tr_aaa_server_new(TALLOC_CTX *mem_ctx, TR_NAME *hostname)
 {
   TR_AAA_SERVER *aaa=talloc(mem_ctx, TR_AAA_SERVER);
   if (aaa!=NULL) {
+    aaa->next=NULL;
     aaa->hostname=hostname;
     talloc_set_destructor((void *)aaa, tr_aaa_server_destructor);
   }
index 42c9688..a0d17b3 100644 (file)
@@ -50,6 +50,7 @@ typedef enum trp_peer_conn_status {
 typedef struct trp_peer TRP_PEER;
 struct trp_peer {
   TRP_PEER *next; /* for making a linked list */
+  TR_NAME *label; /* often null, set on first call to trp_peer_get_label or dup_label */
   char *server;
   TR_GSS_NAMES *gss_names;
   TR_NAME *servicename;
index f174c95..7e524af 100644 (file)
@@ -89,6 +89,7 @@ TR_EXPORT TR_NAME *trp_upd_get_peer(TRP_UPD *upd);
 TR_NAME *trp_upd_dup_peer(TRP_UPD *upd);
 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer);
 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port);
+void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name);
 
 /* Functions for TRP_REQ structures */
 TR_EXPORT TRP_REQ *trp_req_new(TALLOC_CTX *mem_ctx);
index 64c7764..77714cd 100644 (file)
@@ -96,15 +96,17 @@ static int tids_listen(TIDS_INSTANCE *tids, int port, int *fd_out, size_t max_fd
                          .ai_protocol=IPPROTO_TCP};
   char *port_str=NULL;
   size_t n_opened=0;
-  
+
+  tr_debug("tids_listen: started!");
   port_str=talloc_asprintf(NULL, "%d", port);
   if (port_str==NULL) {
     tr_debug("tids_listen: unable to allocate port.");
     return -1;
   }
 
-  getaddrinfo(NULL, port_str, &hints, &ai_head);
+  tr_debug("getaddrinfo()=%d", getaddrinfo(NULL, port_str, &hints, &ai_head));
   talloc_free(port_str);
+  tr_debug("tids_listen: got address info");
 
   /* TODO: listen on all ports */
   for (ai=ai_head,n_opened=0; (ai!=NULL)&&(n_opened<max_fd); ai=ai->ai_next) {
index 7df04ee..1ff56da 100644 (file)
@@ -216,6 +216,7 @@ int main(int argc, char *argv[])
   /*tr_status_event_init();*/ /* install status reporting events */
 
   /* install TID server events */
+  tr_debug("Initializing TID server events.");
   if (0 != tr_tids_event_init(ev_base,
                               tr->tids,
                               tr->cfg_mgr,
@@ -226,11 +227,13 @@ int main(int argc, char *argv[])
   }
 
   /* install TRP handler events */
+  tr_debug("Initializing Dynamic Trust Router Protocol events.");
   if (TRP_SUCCESS != tr_trps_event_init(ev_base, tr)) {
     tr_crit("Error initializing Trust Path Query Server instance.");
     return 1;
   }
 
+  tr_debug("Starting event loop.");
   tr_event_loop_run(ev_base); /* does not return until we are done */
 
   tr_destroy(tr); /* thanks to talloc, should destroy everything */
index 9c96d97..32d7b37 100644 (file)
@@ -69,10 +69,13 @@ static void tr_tidc_resp_handler(TIDC_INSTANCE *tidc,
 {
   TR_RESP_COOKIE *cookie=talloc_get_type_abort(resp_cookie, TR_RESP_COOKIE);
 
-  tr_debug("tr_tidc_resp_handler: Response received! Realm = %s, Community = %s.",
+  tr_debug("tr_tidc_resp_handler: Response received! Realm = %s, Community = %s, result = %s.",
            resp->realm->buf,
-           resp->comm->buf);
-  
+           resp->comm->buf,
+           (TID_SUCCESS==resp->result)?"success":"error");
+
+  if (resp->error_path!=NULL)
+    tr_debug("tr_tids_resp_handler: error_path is set.");
   cookie->resp=tid_resp_dup(cookie, resp);
 }
 
@@ -143,6 +146,7 @@ static void *tr_tids_req_fwd_thread(void *arg)
     goto cleanup;
   }
   cookie->thread_id=args->thread_id;
+  tr_debug("tr_tids_req_fwd_thread: thread %d started.", cookie->thread_id);
 
   /* Create a TID client instance */
   if (tidc==NULL) {
@@ -164,6 +168,9 @@ static void *tr_tids_req_fwd_thread(void *arg)
     success=0;
     goto cleanup;
   };
+  tr_debug("tr_tids_req_fwd_thread: thread %d opened TID connection to %s.",
+           cookie->thread_id,
+           args->aaa_hostname->buf);
 
   /* Send a TID request. */
   if (0 > (rc = tidc_fwd_request(tidc, args->fwd_req, tr_tidc_resp_handler, (void *)cookie))) {
@@ -173,26 +180,29 @@ static void *tr_tids_req_fwd_thread(void *arg)
   }
   /* cookie->resp should now contain our copy of the response */
   success=1;
+  tr_debug("tr_tids_req_fwd_thread: thread %d received response.");
 
 cleanup:
   /* Notify parent thread of the response, if it's still listening. */
   if (0!=tr_tids_fwd_get_mutex(args)) {
-    tr_notice("tr_tids_req_fwd_thread: Error acquiring mutex.");
+    tr_notice("tr_tids_req_fwd_thread: thread %d unable to acquire mutex.", cookie->thread_id);
   } else if (NULL!=args->mq) {
     /* mq is still valid, so we can queue our response */
+    tr_debug("tr_tids_req_fwd_thread: thread %d using valid msg queue.", cookie->thread_id);
     if (success)
       msg=tr_mq_msg_new(tmp_ctx, TR_TID_MQMSG_SUCCESS, TR_MQ_PRIO_NORMAL);
     else
       msg=tr_mq_msg_new(tmp_ctx, TR_TID_MQMSG_FAILURE, TR_MQ_PRIO_NORMAL);
 
     if (msg==NULL)
-      tr_notice("tr_tids_req_fwd_thread: unable to allocate response msg.");
+      tr_notice("tr_tids_req_fwd_thread: thread %d unable to allocate response msg.", cookie->thread_id);
 
     tr_mq_msg_set_payload(msg, (void *)cookie, NULL);
     if (NULL!=cookie)
       talloc_steal(msg, cookie); /* attach this to the msg so we can forget about it */
     tr_mq_add(args->mq, msg);
     talloc_steal(NULL, args); /* take out of our tmp_ctx; master thread now responsible for freeing */
+    tr_debug("tr_tids_req_fwd_thread: thread %d queued response message.", cookie->thread_id);
     if (0!=tr_tids_fwd_release_mutex(args))
       tr_notice("tr_tids_req_fwd_thread: Error releasing mutex.");
   }
@@ -398,6 +408,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
   }
 
   /* send a TID request to the AAA server(s), and get the answer(s) */
+  tr_debug("tr_tids_req_handler: sending TID request(s).");
   if (cfg_apc)
     expiration_interval = cfg_apc->expiration_interval;
   else expiration_interval = cfg_comm->expiration_interval;
@@ -412,6 +423,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
     retval=-1;
     goto cleanup;
   }
+  tr_debug("tr_tids_req_handler: message queue allocated.");
 
   /* start threads */
   aaa_iter=tr_aaa_server_iter_new(tmp_ctx);
@@ -423,6 +435,8 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
   for (n_aaa=0, this_aaa=tr_aaa_server_iter_first(aaa_iter, aaa_servers);
        this_aaa!=NULL;
        n_aaa++, this_aaa=tr_aaa_server_iter_next(aaa_iter)) {
+    tr_debug("tr_tids_req_handler: Preparing to start thread %d.", n_aaa);
+
     aaa_cookie[n_aaa]=talloc(tmp_ctx, struct tr_tids_fwd_cookie);
     if (aaa_cookie[n_aaa]==NULL) {
       tr_notice("tr_tids_req_handler: unable to allocate cookie for AAA thread %d.", n_aaa);
@@ -442,9 +456,12 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
     aaa_cookie[n_aaa]->aaa_hostname=tr_dup_name(this_aaa->hostname);
     aaa_cookie[n_aaa]->dh_params=tr_dh_dup(orig_req->tidc_dh);
     aaa_cookie[n_aaa]->fwd_req=tid_dup_req(aaa_cookie[n_aaa], fwd_req);
+    tr_debug("tr_tids_req_handler: cookie %d initialized.", n_aaa);
 
     /* Take the cookie out of tmp_ctx before starting thread. If thread starts, it becomes
-     * responsible for freeing it until it queues a response. */
+     * responsible for freeing it until it queues a response. If we did not do this, the possibility
+     * exists that this function exits, freeing the cookie, before the thread takes the cookie
+     * out of our tmp_ctx. This would cause a segfault or talloc error in the thread. */
     talloc_steal(NULL, aaa_cookie[n_aaa]);
     if (0!=pthread_create(&(aaa_thread[n_aaa]), NULL, tr_tids_req_fwd_thread, aaa_cookie[n_aaa])) {
       talloc_steal(tmp_ctx, aaa_cookie[n_aaa]); /* thread start failed; steal this back */
@@ -452,8 +469,9 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
       retval=-1;
       goto cleanup;
     }
+    tr_debug("tr_tids_req_handler: thread %d started.", n_aaa);
   }
+
   /* determine expiration time */
   if (0!=tr_mq_pop_timeout(cfg_mgr->active->internal->tid_req_timeout, &ts_abort)) {
     tr_notice("tr_tids_req_handler: unable to read clock for timeout.");
@@ -462,6 +480,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
   }
 
   /* wait for responses */
+  tr_debug("tr_tids_req_handler: waiting for response(s).");
   n_responses=0;
   n_failed=0;
   while (((n_responses+n_failed)<n_aaa) &&
@@ -469,6 +488,7 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
     /* process message */
     if (0==strcmp(tr_mq_msg_get_message(msg), TR_TID_MQMSG_SUCCESS)) {
       payload=talloc_get_type_abort(tr_mq_msg_get_payload(msg), TR_RESP_COOKIE);
+      talloc_steal(tmp_ctx, payload); /* put this back in our context */
       aaa_resp[payload->thread_id]=payload->resp; /* save pointers to these */
 
       if (payload->resp->result==TID_SUCCESS) {
@@ -485,7 +505,9 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
       /* failure */
       n_failed++;
       payload=talloc_get_type(tr_mq_msg_get_payload(msg), TR_RESP_COOKIE);
-      if (payload==NULL) {
+      if (payload!=NULL) 
+        talloc_steal(tmp_ctx, payload); /* put this back in our context */
+      else {
         /* this means the thread was unable to allocate a response cookie, and we thus cannot determine which thread it was. This is bad and should never happen in a working system.. Give up. */
         tr_notice("tr_tids_req_handler: TID request thread sent invalid reply. Aborting!");
         retval=-1;
@@ -500,8 +522,9 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
       goto cleanup;
     }
     
-    /* Now free the cookie for this thread. Null it so we know we've dealt with it. */
-    talloc_free(aaa_cookie[payload->thread_id]);
+    /* Set the cookie pointer to NULL so we know we've dealt with this one. The
+     * cookie itself is in our tmp_ctx, which we'll free before exiting. Let it hang
+     * around in case we are still using pointers to elements of the cookie. */
     aaa_cookie[payload->thread_id]=NULL;
 
     tr_mq_msg_free(msg);
@@ -512,6 +535,8 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
       break;
   }
 
+  tr_debug("tr_tids_req_handler: done waiting for responses. %d responses, %d failures.",
+           n_responses, n_failed);
   /* Inform any remaining threads that we will no longer handle their responses. */
   for (ii=0; ii<n_aaa; ii++) {
     if (aaa_cookie[ii]!=NULL) {
@@ -529,11 +554,13 @@ static int tr_tids_req_handler(TIDS_INSTANCE *tids,
    * reply (by setting their mq pointer to null). However, some may have responded by placing
    * a message on the mq after we last checked but before we set their mq pointer to null. These
    * will not know that we gave up on them, so we must free their cookies for them. We can just
-   * go through any remaining messages on the mq to identify these threads. */
+   * go through any remaining messages on the mq to identify these threads. By putting them in
+   * our context instead of freeing them directly, we ensure we don't accidentally invalidate
+   * any of our own pointers into the structure before this function exits. */
   while (NULL!=(msg=tr_mq_pop(mq, NULL))) {
     payload=(TR_RESP_COOKIE *)tr_mq_msg_get_payload(msg);
     if (aaa_cookie[payload->thread_id]!=NULL)
-      talloc_free(aaa_cookie[payload->thread_id]);
+      talloc_steal(tmp_ctx, aaa_cookie[payload->thread_id]);
 
     tr_mq_msg_free(msg);
   }
index 8b16abd..f5ea1fb 100644 (file)
@@ -44,6 +44,8 @@
 static int trp_peer_destructor(void *object)
 {
   TRP_PEER *peer=talloc_get_type_abort(object, TRP_PEER);
+  if (peer->label!=NULL)
+    tr_free_name(peer->label);
   if (peer->servicename!=NULL)
     tr_free_name(peer->servicename);
   return 0;
@@ -53,6 +55,7 @@ TRP_PEER *trp_peer_new(TALLOC_CTX *memctx)
   TRP_PEER *peer=talloc(memctx, TRP_PEER);
   if (peer!=NULL) {
     peer->next=NULL;
+    peer->label=NULL;
     peer->server=NULL;
     peer->servicename=NULL;
     peer->gss_names=NULL;
@@ -86,15 +89,16 @@ static TRP_PEER *trp_peer_tail(TRP_PEER *peer)
  * Do not modify or free the label. */
 TR_NAME *trp_peer_get_label(TRP_PEER *peer)
 {
-  TR_GSS_NAMES_ITER *iter=tr_gss_names_iter_new(NULL);
-  TR_NAME *name=NULL;
+  char *s=NULL;
 
-  /* for now, use the first gss name */
-  if (iter!=NULL) {
-    name=tr_gss_names_iter_first(iter, peer->gss_names);
-    talloc_free(iter);
+  if (peer->label==NULL) {
+    s=talloc_asprintf(NULL, "%s:%u", peer->server, peer->port);
+    if (s!=NULL) {
+      peer->label=tr_new_name(s);
+      talloc_free(s);
+    }
   }
-  return name;
+  return peer->label;
 }
 
 /* Get a name that identifies this peer for display to the user, etc. 
index ee627a9..98898ff 100644 (file)
@@ -544,27 +544,27 @@ TRP_RC trp_inforec_set_provenance(TRP_INFOREC *rec, json_t *prov)
   return TRP_ERROR;
 }
 
-static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *peer)
+static TRP_RC trp_inforec_add_to_provenance(TRP_INFOREC *rec, TR_NAME *name)
 {
-  json_t *jpeer=NULL;
+  json_t *jname=NULL;
 
   switch (rec->type) {
   case TRP_INFOREC_TYPE_ROUTE:
     /* no provenance list */
     break;
   case TRP_INFOREC_TYPE_COMMUNITY:
-    jpeer=tr_name_to_json_string(peer);
-    if (jpeer==NULL)
+    jname=tr_name_to_json_string(name);
+    if (jname==NULL)
       return TRP_ERROR;
     if (rec->data->comm->provenance==NULL) {
       rec->data->comm->provenance=json_array();
       if (rec->data->comm->provenance==NULL) {
-        json_decref(jpeer);
+        json_decref(jname);
         return TRP_ERROR;
       }
     }
-    if (0!=json_array_append_new(rec->data->comm->provenance, jpeer)) {
-      json_decref(jpeer);
+    if (0!=json_array_append_new(rec->data->comm->provenance, jname)) {
+      json_decref(jname);
       return TRP_ERROR;
     }
     break;
@@ -723,18 +723,7 @@ TR_NAME *trp_upd_dup_peer(TRP_UPD *upd)
 
 void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer)
 {
-  TRP_INFOREC *rec=NULL;
-  TR_NAME *cpy=NULL;
-
   upd->peer=peer;
-
-  /* add to provenance list of any records that need it */
-  for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
-    if (trp_inforec_add_to_provenance(rec, cpy=tr_dup_name(peer)) != TRP_SUCCESS) {
-      tr_err("trp_upd_set_peer: error adding peer to provenance list.");
-      tr_free_name(cpy);
-    }
-  }
 }
 
 void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
@@ -750,6 +739,17 @@ void trp_upd_set_next_hop(TRP_UPD *upd, const char *hostname, unsigned int port)
   }
 }
 
+void trp_upd_add_to_provenance(TRP_UPD *upd, TR_NAME *name)
+{
+  TRP_INFOREC *rec=NULL;
+
+  /* add it to all inforecs */
+  for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) {
+    if (TRP_SUCCESS!=trp_inforec_add_to_provenance(rec, name))
+      tr_err("trp_upd_set_peer: error adding peer to provenance list.");
+  }
+}
+
 /* pretty print */
 static void trp_inforec_route_print(TRP_INFOREC_DATA *data)
 {
index b28a8d2..e5fd7e1 100644 (file)
@@ -168,6 +168,8 @@ void trps_set_ctable(TRPS_INSTANCE *trps, TR_COMM_TABLE *comm)
 
 void trps_set_ptable(TRPS_INSTANCE *trps, TRP_PTABLE *ptable)
 {
+  if (trps->ptable!=NULL)
+    trp_ptable_free(trps->ptable);
   trps->ptable=ptable;
 }
 
@@ -430,6 +432,8 @@ static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MS
   case TRP_UPDATE:
     trp_upd_set_peer(tr_msg_get_trp_upd(*msg), tr_dup_name(conn_peer));
     trp_upd_set_next_hop(tr_msg_get_trp_upd(*msg), trp_peer_get_server(peer), 0); /* TODO: 0 should be the configured TID port */
+    /* update provenance if necessary */
+    trp_upd_add_to_provenance(tr_msg_get_trp_upd(*msg), trp_peer_get_label(peer));
     break;
 
   case TRP_REQUEST:
@@ -1026,6 +1030,9 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd)
       tr_debug("trps_handle_update: handling community inforec.");
       if (TRP_SUCCESS!=trps_handle_inforec_comm(trps, upd, rec))
         tr_notice("trps_handle_update: error handling community inforec.");
+      else
+        tr_comm_table_print(stdout, trps->ctable); /* for debugging TODO remove */
+
       break;
     default:
       tr_notice("trps_handle_update: unsupported inforec in TRP update.");