Real syslog support for trust router
authorSam Hartman <hartmans@debian.org>
Tue, 10 Mar 2015 00:45:38 +0000 (20:45 -0400)
committerSam Hartman <hartmans@debian.org>
Tue, 10 Mar 2015 00:45:38 +0000 (20:45 -0400)
Merge branch 'logging_changes' of https://github.com/adam-bishop/trust_router

Conflicts:
common/tr_config.c
common/tr_msg.c
tr/tr_main.c

1  2 
Makefile.am
common/tr_config.c
common/tr_msg.c
configure.ac
tid/tid_req.c
tr/tr_main.c

diff --combined Makefile.am
@@@ -1,14 -1,15 +1,15 @@@
  DISTCHECK_CONFIGURE_FLAGS = \
        --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
  bin_PROGRAMS= tr/trust_router tid/example/tidc tid/example/tids common/dh_test/tr_dh_test
 -AM_CPPFLAGS=-I$(srcdir)/include
 -AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses
 +AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
 +AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
  SUBDIRS = gsscon 
  common_srcs = common/tr_name.c \
        common/tr_constraint.c \
        common/jansson_iterators.h \
        common/tr_msg.c \
        common/tr_dh.c \
+         common/tr_debug.c \
        common/tr_util.c
  
  check_PROGRAMS = common/t_constraint
@@@ -28,33 -29,34 +29,34 @@@ common/tr_filter.c 
  common/tr_rp.c \
  tr/tr.c
  
 -tr_trust_router_LDADD = gsscon/libgsscon.la libtr_tid.la
 +tr_trust_router_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
  
  tid_example_tidc_SOURCES = tid/example/tidc_main.c 
  
 -tid_example_tidc_LDADD = gsscon/libgsscon.la libtr_tid.la
 +tid_example_tidc_LDADD = gsscon/libgsscon.la libtr_tid.la $(GLIB_LIBS)
  
  tid_example_tids_SOURCES = tid/example/tids_main.c 
  
  tid_example_tids_LDADD = gsscon/libgsscon.la libtr_tid.la
  
  common_dh_test_tr_dh_test_SOURCES = common/tr_dh.c \
+ common/tr_debug.c \
  common/dh_test/dh_test.c
  
  libtr_tid_la_SOURCES = tid/tids.c tid/tidc.c tid/tid_req.c tid/tid_resp.c \
  $(common_srcs)
  
  libtr_tid_la_CFLAGS = $(AM_CFLAGS) -fvisibility=hidden
 -libtr_tid_la_LIBADD = gsscon/libgsscon.la
 +libtr_tid_la_LIBADD = gsscon/libgsscon.la $(GLIB_LIBS)
  libtr_tid_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2 -no-undefined
  
  pkginclude_HEADERS = include/trust_router/tid.h include/trust_router/tr_name.h \
+       include/tr_debug.h \
        include/trust_router/tr_dh.h \
        include/trust_router/tr_constraint.h \
        include/trust_router/tr_versioning.h 
  
  noinst_HEADERS = include/gsscon.h include/tr_config.h \
-       include/tr_debug.h \
        include/tr_msg.h include/tr.h \
        include/tr_idp.h include/tr_rp.h \
        include/tr_comm.h include/tr_apc.h \
diff --combined common/tr_config.c
  #include <talloc.h>
  
  #include <tr_config.h>
+ #include <tr_debug.h>
  #include <tr.h>
  #include <tr_filter.h>
  #include <trust_router/tr_constraint.h>
  
  void tr_print_config (FILE *stream, TR_CFG *cfg) {
-   fprintf(stream, "tr_print_config: Not yet implemented.\n");
+   fprintf(stream, "tr_print_config: Not yet implemented.");
    return;
  }
  
@@@ -61,6 -62,10 +62,10 @@@ TR_CFG_RC tr_apply_new_config (TR_INSTA
      tr_cfg_free(tr->active_cfg);
  
    tr->active_cfg = tr->new_cfg;
+   tr_log_threshold(tr->active_cfg->internal->log_threshold);
+   tr_console_threshold(tr->active_cfg->internal->console_threshold);
    return TR_CFG_SUCCESS;
  }
  
@@@ -69,6 -74,9 +74,9 @@@ static TR_CFG_RC tr_cfg_parse_internal 
    json_t *jmtd = NULL;
    json_t *jtp = NULL;
    json_t *jhname = NULL;
+   json_t *jlog = NULL;
+   json_t *jconthres = NULL;
+   json_t *jlogthres = NULL;
  
    if ((!trc) || (!jcfg))
      return TR_CFG_BAD_PARAMS;
@@@ -85,7 -93,7 +93,7 @@@
        if (json_is_number(jmtd)) {
        trc->internal->max_tree_depth = json_integer_value(jmtd);
        } else {
-       fprintf(stderr,"tr_cfg_parse_internal: Parsing error, max_tree_depth is not a number.\n");
+       tr_debug("tr_cfg_parse_internal: Parsing error, max_tree_depth is not a number.");
        return TR_CFG_NOPARSE;
        }
      } else {
        if (json_is_number(jtp)) {
        trc->internal->tids_port = json_integer_value(jtp);
        } else {
-       fprintf(stderr,"tr_cfg_parse_internal: Parsing error, port is not a number.\n");
+       tr_debug("tr_cfg_parse_internal: Parsing error, port is not a number.");
        return TR_CFG_NOPARSE;
        }
      } else {
        if (json_is_string(jhname)) {
        trc->internal->hostname = json_string_value(jhname);
        } else {
-       fprintf(stderr,"tr_cfg_parse_internal: Parsing error, hostname is not a string.\n");
+       tr_debug("tr_cfg_parse_internal: Parsing error, hostname is not a string.");
        return TR_CFG_NOPARSE;
        }
      }
-     fprintf(stderr, "tr_cfg_parse_internal: Internal config parsed.\n");
+     if (NULL != (jlog = json_object_get(jcfg, "logging"))) {
+       if (NULL != (jlogthres = json_object_get(jint, "log_threshold"))) {
+         if (json_is_string(jlogthres)) {
+                 trc->internal->log_threshold = str2sev(json_string_value(jlogthres));
+         } else {
+           tr_debug("tr_cfg_parse_internal: Parsing error, log_threshold is not a string.");
+           return TR_CFG_NOPARSE;
+         }
+       } else {
+         /* If not configured, use the default */
+         trc->internal->log_threshold = TR_DEFAULT_LOG_THRESHOLD;
+       }
+       if (NULL != (jconthres = json_object_get(jint, "console_threshold"))) {
+         if (json_is_string(jconthres)) {
+             trc->internal->console_threshold = str2sev(json_string_value(jconthres));
+         } else {
+           tr_debug("tr_cfg_parse_internal: Parsing error, console_threshold is not a string.");
+           return TR_CFG_NOPARSE;
+         }
+       } else {
+         /* If not configured, use the default */
+         trc->internal->console_threshold = TR_DEFAULT_CONSOLE_THRESHOLD;
+       }
+     } else {
+         /* If not configured, use the default */
+         trc->internal->console_threshold = TR_DEFAULT_CONSOLE_THRESHOLD;
+         trc->internal->log_threshold = TR_DEFAULT_LOG_THRESHOLD;
+     }
+     tr_debug("tr_cfg_parse_internal: Internal config parsed.");
      return TR_CFG_SUCCESS;
    }
    return TR_CFG_SUCCESS;
@@@ -127,13 -166,13 +166,13 @@@ static TR_CONSTRAINT *tr_cfg_parse_one_
        (0 >= json_array_size(jc)) ||
        (TR_MAX_CONST_MATCHES < json_array_size(jc)) ||
        (!json_is_string(json_array_get(jc, 0)))) {
-     fprintf(stderr, "tr_cfg_parse_one_constraint: config error.\n");
+     tr_debug("tr_cfg_parse_one_constraint: config error.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (NULL == (cons = talloc(trc, TR_CONSTRAINT))) {
-     fprintf(stderr, "tr_cfg_parse_one_constraint: Out of memory (cons).\n");
+     tr_debug("tr_cfg_parse_one_constraint: Out of memory (cons).");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
    memset(cons, 0, sizeof(TR_CONSTRAINT));
  
    if (NULL == (cons->type = tr_new_name(ctype))) {
-     fprintf(stderr, "tr_cfg_parse_one_constraint: Out of memory (type).\n");
+     tr_debug("tr_cfg_parse_one_constraint: Out of memory (type).");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
@@@ -168,26 -207,26 +207,26 @@@ static TR_FILTER *tr_cfg_parse_one_filt
  
    if ((NULL == (jftype = json_object_get(jfilt, "type"))) ||
        (!json_is_string(jftype))) {
-     fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter type.\n");
+     tr_debug("tr_cfg_parse_one_filter: Error parsing filter type.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if ((NULL == (jfls = json_object_get(jfilt, "filter_lines"))) ||
        (!json_is_array(jfls))) {
-     fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter type.\n");
+     tr_debug("tr_cfg_parse_one_filter: Error parsing filter type.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (TR_MAX_FILTER_LINES < json_array_size(jfls)) {
-     fprintf(stderr, "tr_cfg_parse_one_filter: Filter has too many filter_lines, maximimum of %d.\n", TR_MAX_FILTER_LINES);
+     tr_debug("tr_cfg_parse_one_filter: Filter has too many filter_lines, maximimum of %d.", TR_MAX_FILTER_LINES);
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (NULL == (filt = talloc(trc, TR_FILTER))) {
-     fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
+     tr_debug("tr_cfg_parse_one_filter: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
      filt->type = TR_FILTER_TYPE_RP_PERMITTED;
    }
    else {
-     fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter type, unknown type '%s'.\n", json_string_value(jftype));
+     tr_debug("tr_cfg_parse_one_filter: Error parsing filter type, unknown type '%s'.", json_string_value(jftype));
      *rc = TR_CFG_NOPARSE;
      tr_filter_free(filt);
      return NULL;
  
      if ((NULL == (jfaction = json_object_get(json_array_get(jfls, i), "action"))) ||
        (!json_is_string(jfaction))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter action.\n");
+       tr_debug("tr_cfg_parse_one_filter: Error parsing filter action.");
        *rc = TR_CFG_NOPARSE;
        tr_filter_free(filt);
        return NULL;
      if ((NULL == (jfspecs = json_object_get(json_array_get(jfls, i), "filter_specs"))) ||
        (!json_is_array(jfspecs)) ||
        (0 == json_array_size(jfspecs))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter specs.\n");
+       tr_debug("tr_cfg_parse_one_filter: Error parsing filter specs.");
        *rc = TR_CFG_NOPARSE;
        tr_filter_free(filt);
        return NULL;
      }
    
      if (TR_MAX_FILTER_SPECS < json_array_size(jfspecs)) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Filter has too many filter_specs, maximimum of %d.\n", TR_MAX_FILTER_SPECS);
+       tr_debug("tr_cfg_parse_one_filter: Filter has too many filter_specs, maximimum of %d.", TR_MAX_FILTER_SPECS);
        *rc = TR_CFG_NOPARSE;
        tr_filter_free(filt);
        return NULL;
      }
  
      if (NULL == (filt->lines[i] = talloc(trc, TR_FLINE))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory (fline).\n");
+       tr_debug("tr_cfg_parse_one_filter: Out of memory (fline).");
        *rc = TR_CFG_NOMEM;
        tr_filter_free(filt);
        return NULL;
        filt->lines[i]->action = TR_FILTER_ACTION_REJECT;
      }
      else {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing filter action, unknown action' %s'.\n", json_string_value(jfaction));
+       tr_debug("tr_cfg_parse_one_filter: Error parsing filter action, unknown action' %s'.", json_string_value(jfaction));
        *rc = TR_CFG_NOPARSE;
        tr_filter_free(filt);
        return NULL;
        (TR_MAX_CONST_MATCHES >= json_array_size(jrc))) {
  
        if (NULL == (filt->lines[i]->realm_cons = tr_cfg_parse_one_constraint(trc, "realm", jrc, rc))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing realm constraint");
+       tr_debug("tr_cfg_parse_one_filter: Error parsing realm constraint");
        tr_filter_free(filt);
        return NULL;
        }
        (TR_MAX_CONST_MATCHES >= json_array_size(jdc))) {
  
        if (NULL == (filt->lines[i]->domain_cons = tr_cfg_parse_one_constraint(trc, "domain", jdc, rc))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Error parsing domain constraint");
+       tr_debug("tr_cfg_parse_one_filter: Error parsing domain constraint");
        tr_filter_free(filt);
        return NULL;
        }
          (!json_is_string(jffield)) ||
          (NULL == (jfmatch = json_object_get(json_array_get(jfspecs, j), "match"))) ||
          (!json_is_string(jfmatch))) {
-       fprintf (stderr, "tr_cfg_parse_one_filter: Error parsing filter field and match for filter spec %d, filter line %d.\n", i, j);
+       tr_debug("tr_cfg_parse_one_filter: Error parsing filter field and match for filter spec %d, filter line %d.", i, j);
        *rc = TR_CFG_NOPARSE;
        tr_filter_free(filt);
        return NULL;
        }
  
        if (NULL == (filt->lines[i]->specs[j] = talloc(trc, TR_FSPEC))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
+       tr_debug("tr_cfg_parse_one_filter: Out of memory.");
        *rc = TR_CFG_NOMEM;
        tr_filter_free(filt);
        return NULL;
      
        if ((NULL == (filt->lines[i]->specs[j]->field = tr_new_name((char *)json_string_value(jffield)))) ||
          (NULL == (filt->lines[i]->specs[j]->match = tr_new_name((char *)json_string_value(jfmatch))))) {
-       fprintf(stderr, "tr_cfg_parse_one_filter: Out of memory.\n");
+       tr_debug("tr_cfg_parse_one_filter: Out of memory.");
        *rc = TR_CFG_NOMEM;
        tr_filter_free(filt);
        return NULL;
@@@ -321,7 -360,7 +360,7 @@@ static TR_RP_CLIENT *tr_cfg_parse_one_r
    int i = 0;
  
    if ((!trc) || (!jrp) || (!rc)) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_realm: Bad parameters.\n");
+     tr_debug("tr_cfg_parse_one_rp_realm: Bad parameters.");
      if (rc)
        *rc = TR_CFG_BAD_PARAMS;
      return NULL;
  
    if ((NULL == (jgns = json_object_get(jrp, "gss_names"))) ||
        (!json_is_array(jgns))) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no GSS names.\n");
+     tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no GSS names.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    /* TBD -- Support more than one filter per RP client? */
    if (NULL == (jfilt = json_object_get(jrp, "filter"))) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no filter.\n");
+     tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client configuration, no filter.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
    if ((NULL == (jftype = json_object_get(jfilt, "type"))) ||
        (!json_is_string(jftype)) ||
        (strcmp(json_string_value(jftype), "rp_permitted"))) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_client: Error parsing RP client filter type.\n");
+     tr_debug("tr_cfg_parse_one_rp_client: Error parsing RP client filter type.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (TR_MAX_GSS_NAMES < json_array_size(jgns)) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_client: RP Client has too many GSS Names.\n");
+     tr_debug("tr_cfg_parse_one_rp_client: RP Client has too many GSS Names.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (NULL == (rp = talloc(trc, TR_RP_CLIENT))) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_realm: Out of memory.\n");
+     tr_debug("tr_cfg_parse_one_rp_realm: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
  
    /* TBD -- support more than one filter entry per RP Client? */
    if (NULL == (rp->filter = tr_cfg_parse_one_filter(trc, jfilt, rc))) {
-     fprintf(stderr, "tr_cfg_parse_one_rp_client: Error parsing filter.\n");
+     tr_debug("tr_cfg_parse_one_rp_client: Error parsing filter.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
      
    for (i = 0; i < json_array_size(jgns); i++) {
      if (NULL == (rp->gss_names[i] = tr_new_name ((char *)json_string_value(json_array_get(jgns, i))))) {
-       fprintf(stderr, "tr_cfg_parse_one_rp_client: No memory for GSS Name.\n");
+       tr_debug("tr_cfg_parse_one_rp_client: No memory for GSS Name.");
        *rc = TR_CFG_NOMEM;
        return NULL;
      }
@@@ -403,7 -442,7 +442,7 @@@ static TR_CFG_RC tr_cfg_parse_rp_client
                                                   &rc))) {
        return rc;
        }
-       fprintf(stderr, "tr_cfg_parse_rp_clients: RP client configured -- first gss: %s\n", rp->gss_names[0]->buf);
+       tr_debug("tr_cfg_parse_rp_clients: RP client configured -- first gss: %s", rp->gss_names[0]->buf);
        rp->next = trc->rp_clients;
        trc->rp_clients = rp;
      }
@@@ -415,13 -454,13 +454,13 @@@ static TR_AAA_SERVER *tr_cfg_parse_one_
    TR_AAA_SERVER *aaa = NULL;
  
    if ((!trc) || (!jaddr) || (!json_is_string(jaddr))) {
-     fprintf(stderr, "tr_cfg_parse_one_aaa_server: Bad parameters.\n");
+     tr_debug("tr_cfg_parse_one_aaa_server: Bad parameters.");
      *rc = TR_CFG_BAD_PARAMS;
      return NULL;
    }
  
    if (NULL == (aaa = talloc(trc, TR_AAA_SERVER))) {
-     fprintf(stderr, "tr_cfg_parse_one_aaa_server: Out of memory.\n");
+     tr_debug("tr_cfg_parse_one_aaa_server: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
@@@ -444,7 -483,7 +483,7 @@@ static TR_AAA_SERVER *tr_cfg_parse_aaa_
        return NULL;
      }
      /* TBD -- IPv6 addresses */
-     //    fprintf(stderr, "tr_cfg_parse_aaa_servers: Configuring AAA Server: ip_addr = %s.\n", inet_ntoa(temp_aaa->aaa_server_addr));
+     //    tr_debug("tr_cfg_parse_aaa_servers: Configuring AAA Server: ip_addr = %s.", inet_ntoa(temp_aaa->aaa_server_addr));
      temp_aaa->next = aaa;
      aaa = temp_aaa;
    }
@@@ -458,14 -497,14 +497,14 @@@ static TR_APC *tr_cfg_parse_apcs (TR_CF
    *rc = TR_CFG_SUCCESS;               /* presume success */
  
    if ((!trc) || (!japcs) || (!rc)) {
-     fprintf(stderr, "tr_cfg_parse_apcs: Bad parameters.\n");
+     tr_debug("tr_cfg_parse_apcs: Bad parameters.");
      if (rc) 
        *rc = TR_CFG_BAD_PARAMS;
      return NULL;
    }
  
    if (NULL == (apc = talloc(trc, TR_APC))) {
-     fprintf (stderr, "tr_cfg_parse_apcs: Out of memory.\n");
+     tr_debug("tr_cfg_parse_apcs: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
      return NULL;
  
    if (NULL == (apc->id = tr_new_name((char *)json_string_value(json_array_get(japcs, 0))))) {
-     fprintf(stderr, "tr_cfg_parse_apcs: No memory for APC name.\n");
+     tr_debug("tr_cfg_parse_apcs: No memory for APC name.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
@@@ -494,14 -533,14 +533,14 @@@ static TR_IDP_REALM *tr_cfg_parse_one_i
    json_t *japcs = NULL;
  
    if ((!trc) || (!jidp) || (!rc)) {
-     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Bad parameters.\n");
+     tr_debug("tr_cfg_parse_one_idp_realm: Bad parameters.");
      if (rc)
        *rc = TR_CFG_BAD_PARAMS;
      return NULL;
    }
  
    if (NULL == (idp = talloc(trc, TR_IDP_REALM))) {
-     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Out of memory.\n");
+     tr_debug("tr_cfg_parse_one_idp_realm: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
        (!json_is_string(jscfg)) ||
        (NULL == (jsrvrs = json_object_get(jidp, "aaa_servers"))) ||
        (!json_is_array(jsrvrs))) {
-     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Error parsing IDP realm configuration.\n");
+     tr_debug("tr_cfg_parse_one_idp_realm: Error parsing IDP realm configuration.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
    }
  
    if (NULL == (idp->realm_id = tr_new_name((char *)json_string_value(jrid)))) {
-     fprintf(stderr, "tr_cfg_parse_one_idp_realm: No memory for realm id.\n");
+     tr_debug("tr_cfg_parse_one_idp_realm: No memory for realm id.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
  
    if (NULL == (idp->aaa_servers = tr_cfg_parse_aaa_servers(trc, jsrvrs, rc))) {
-     fprintf(stderr, "tr_cfg_parse_one_idp_realm: Can't parse AAA servers for realm %s.\n", idp->realm_id->buf);
+     tr_debug("tr_cfg_parse_one_idp_realm: Can't parse AAA servers for realm %s.", idp->realm_id->buf);
      tr_free_name(idp->realm_id);
      return NULL;
    }
    if ((NULL != (japcs = json_object_get(jidp, "apcs"))) &&
        (json_is_array(japcs))) {
      if (NULL == (idp->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
-       fprintf(stderr, "tr_cfg_parse_one_idp_realm: Can't parse APCs for realm %s .\n", idp->realm_id->buf);
+       tr_debug("tr_cfg_parse_one_idp_realm: Can't parse APCs for realm %s .", idp->realm_id->buf);
        tr_free_name(idp->realm_id);
        /* TBD -- free aaa_servers */;
        return NULL;
@@@ -570,7 -609,7 +609,7 @@@ static TR_CFG_RC tr_cfg_parse_default_s
                                                  &rc))) {
        return rc;
        }
-       fprintf(stderr, "tr_cfg_parse_default_servers: Default server configured: %s\n", ds->hostname->buf);
+       tr_debug("tr_cfg_parse_default_servers: Default server configured: %s", ds->hostname->buf);
        ds->next = trc->default_servers;
        trc->default_servers = ds;
      }
@@@ -598,7 -637,7 +637,7 @@@ static TR_CFG_RC tr_cfg_parse_idp_realm
                                                    &rc))) {
        return rc;
        }
-       fprintf(stderr, "tr_cfg_parse_idp_realms: IDP realm configured: %s.\n", idp->realm_id->buf);
+       tr_debug("tr_cfg_parse_idp_realms: IDP realm configured: %s.", idp->realm_id->buf);
        idp->next = trc->idp_realms;
        trc->idp_realms = idp;
      }
@@@ -625,7 -664,7 +664,7 @@@ static TR_IDP_REALM *tr_cfg_parse_comm_
      if (NULL == (temp_idp = (tr_cfg_find_idp(trc, 
                                             tr_new_name((char *)json_string_value(json_array_get(jidps, i))), 
                                             rc)))) {
-       fprintf(stderr, "tr_cfg_parse_comm_idps: Unknown IDP %s.\n", 
+       tr_debug("tr_cfg_parse_comm_idps: Unknown IDP %s.", 
              (char *)json_string_value(json_array_get(jidps, i)));
        return NULL;
      }
@@@ -653,7 -692,7 +692,7 @@@ static TR_RP_REALM *tr_cfg_parse_comm_r
  
    for (i = (json_array_size(jrps)-1); i >= 0; i--) {
      if (NULL == (temp_rp = talloc(trc, TR_RP_REALM))) {
-       fprintf(stderr, "tr_cfg_parse_comm_rps: Can't allocate memory for RP Realm.\n");
+       tr_debug("tr_cfg_parse_comm_rps: Can't allocate memory for RP Realm.");
        if (rc)
        *rc = TR_CFG_NOMEM;
        return NULL;
      memset (temp_rp, 0, sizeof(TR_RP_REALM));
  
      if (NULL == (temp_rp->realm_name = tr_new_name((char *)json_string_value(json_array_get(jrps, i))))) {
-       fprintf(stderr, "tr_cfg_parse_comm_rps: No memory for RP Realm Name.\n");
+       tr_debug("tr_cfg_parse_comm_rps: No memory for RP Realm Name.");
        if (rc)
        *rc = TR_CFG_NOMEM;
        return NULL;
@@@ -683,18 -722,19 +722,18 @@@ static TR_COMM *tr_cfg_parse_one_comm (
    json_t *jrps = NULL;
  
    if ((!trc) || (!jcomm) || (!rc)) {
-     fprintf(stderr, "tr_cfg_parse_one_comm: Bad parameters.\n");
+     tr_debug("tr_cfg_parse_one_comm: Bad parameters.");
      if (rc)
        *rc = TR_CFG_BAD_PARAMS;
      return NULL;
    }
  
 -  if (NULL == (comm = talloc(trc, TR_COMM))) {
 -    tr_debug("tr_cfg_parse_one_comm: Out of memory.");
 +  if (NULL == (comm = talloc_zero(trc, TR_COMM))) {
-     fprintf(stderr, "tr_cfg_parse_one_comm: Out of memory.\n");
++    tr_crit("tr_cfg_parse_one_comm: Out of memory.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
  
 -  memset(comm, 0, sizeof(TR_COMM));
  
    if ((NULL == (jid = json_object_get(jcomm, "community_id"))) ||
        (!json_is_string(jid)) ||
        (!json_is_array(jidps)) ||
        (NULL == (jrps = json_object_get(jcomm, "rp_realms"))) ||
        (!json_is_array(jrps))) {
-     fprintf(stderr, "tr_cfg_parse_one_comm: Error parsing Communities configuration.\n");
+     tr_debug("tr_cfg_parse_one_comm: Error parsing Communities configuration.");
      *rc = TR_CFG_NOPARSE;
      return NULL;
    }
  
    if (NULL == (comm->id = tr_new_name((char *)json_string_value(jid)))) {
-     fprintf(stderr, "tr_cfg_parse_one_comm: No memory for community id.\n");
+     tr_debug("tr_cfg_parse_one_comm: No memory for community id.");
      *rc = TR_CFG_NOMEM;
      return NULL;
    }
    } else if (0 == strcmp(json_string_value(jtype), "coi")) {
      comm->type = TR_COMM_COI;
      if (NULL == (comm->apcs = tr_cfg_parse_apcs(trc, japcs, rc))) {
-       fprintf(stderr, "tr_cfg_parse_one_comm: Can't parse APCs for COI %s.\n", comm->id->buf);
+       tr_debug("tr_cfg_parse_one_comm: Can't parse APCs for COI %s.", comm->id->buf);
        tr_free_name(comm->id);
        return NULL;
      }
    } else {
-     fprintf(stderr, "tr_cfg_parse_one_comm: Invalid community type, comm = %s, type = %s\n", comm->id->buf, json_string_value(jtype));
+     tr_debug("tr_cfg_parse_one_comm: Invalid community type, comm = %s, type = %s", comm->id->buf, json_string_value(jtype));
      tr_free_name(comm->id);
      *rc = TR_CFG_NOPARSE;
      return NULL;
  
    comm->idp_realms = tr_cfg_parse_comm_idps(trc, jidps, rc);
    if (TR_CFG_SUCCESS != *rc) {
-     fprintf(stderr, "tr_cfg_parse_one_comm: Can't parse IDP realms for comm %s.\n", comm->id->buf);
+     tr_debug("tr_cfg_parse_one_comm: Can't parse IDP realms for comm %s.", comm->id->buf);
      tr_free_name(comm->id);
      return NULL;
    }
  
    comm->rp_realms = tr_cfg_parse_comm_rps(trc, jrps, rc);
    if (TR_CFG_SUCCESS != *rc) {
-     fprintf(stderr, "tr_cfg_parse_comm: Can't parse RP realms for comm %s .\n", comm->id->buf);
+     tr_debug("tr_cfg_parse_comm: Can't parse RP realms for comm %s .", comm->id->buf);
      tr_free_name(comm->id);
 -    /* TBD -- free idps? */;
      return NULL;
    }
  
 +  if (TR_COMM_APC == comm->type) {
 +    json_t *jexpire  = json_object_get(jcomm, "expiration_interval");
 +    comm->expiration_interval = 43200; /*30 days*/
 +    if (jexpire) {
 +      if (!json_is_integer(jexpire)) {
 +        fprintf(stderr, "tr_parse_comm: expirae_interval is not an integer\n");
 +        return NULL;
 +      }
 +      comm->expiration_interval = json_integer_value(jexpire);
 +      if (comm->expiration_interval <= 10)
 +        comm->expiration_interval = 11; /* Freeradius waits 10 minutes between successful TR queries*/
 +      if (comm->expiration_interval > 129600) /* 90 days*/
 +      comm->expiration_interval = 129600;
 +    }
 +  }
 +  
    return comm;
  }
  
@@@ -774,7 -799,7 +813,7 @@@ static TR_CFG_RC tr_cfg_parse_comms (TR
    int i = 0;
  
    if ((!trc) || (!jcfg)) {
-     fprintf(stderr, "tr_cfg_parse_comms: Bad Parameters.\n");
+     tr_debug("tr_cfg_parse_comms: Bad Parameters.");
      return TR_CFG_BAD_PARAMS;
    }
  
                                                &rc))) {
        return rc;
        }
-       fprintf(stderr, "tr_cfg_parse_comms: Community configured: %s.\n", comm->id->buf);
+       tr_debug("tr_cfg_parse_comms: Community configured: %s.", comm->id->buf);
        comm->next = trc->comms;
        trc->comms = comm;
      }
@@@ -805,22 -830,22 +844,22 @@@ TR_CFG_RC tr_cfg_validate (TR_CFG *trc
  
    if ((NULL == trc->internal)||
        (NULL == trc->internal->hostname)) {
-     fprintf(stderr, "tr_cfg_validate: Error: No internal configuration, or no hostname.\n");
+     tr_debug("tr_cfg_validate: Error: No internal configuration, or no hostname.");
      rc = TR_CFG_ERROR;
    }
  
    if (NULL == trc->rp_clients) {
-     fprintf(stderr, "tr_cfg_validate: Error: No RP Clients configured\n");
+     tr_debug("tr_cfg_validate: Error: No RP Clients configured");
      rc = TR_CFG_ERROR;
    }
  
    if (NULL == trc->comms) {
-     fprintf(stderr, "tr_cfg_validate: Error: No Communities configured\n");
+     tr_debug("tr_cfg_validate: Error: No Communities configured");
      rc = TR_CFG_ERROR;
    }
  
    if ((NULL == trc->default_servers) && (NULL == trc->idp_realms)) {
-     fprintf(stderr, "tr_cfg_validate: Error: No default servers or IDPs configured.\n");
+     tr_debug("tr_cfg_validate: Error: No default servers or IDPs configured.");
      rc = TR_CFG_ERROR;
    }
    
@@@ -845,10 -870,10 +884,10 @@@ TR_CFG_RC tr_parse_config (TR_INSTANCE 
  
    /* Parse configuration information from each config file */
    while (n--) {
-     fprintf(stderr, "tr_read_config: Parsing %s.\n", cfg_files[n]->d_name);
+     tr_debug("tr_read_config: Parsing %s.", cfg_files[n]->d_name);
      if (NULL == (jcfg = json_load_file(cfg_files[n]->d_name, 
                                       JSON_DISABLE_EOF_CHECK, &rc))) {
-       fprintf (stderr, "tr_read_config: Error parsing config file %s.\n", 
+       tr_debug("tr_read_config: Error parsing config file %s.", 
               cfg_files[n]->d_name);
        return TR_CFG_NOPARSE;
      }
  
    /* make sure we got a complete, consistent configuration */
    if (TR_CFG_SUCCESS != tr_cfg_validate(tr->new_cfg)) {
-     fprintf(stderr, "tr_parse_config: Error: INVALID CONFIGURATION, EXITING\n");
+     tr_debug("tr_parse_config: Error: INVALID CONFIGURATION, EXITING");
      return TR_CFG_ERROR;
    }
  
@@@ -885,7 -910,7 +924,7 @@@ TR_IDP_REALM *tr_cfg_find_idp (TR_CFG *
  
    for (cfg_idp = tr_cfg->idp_realms; NULL != cfg_idp; cfg_idp = cfg_idp->next) {
      if (!tr_name_cmp (idp_id, cfg_idp->realm_id)) {
-       fprintf(stderr, "tr_cfg_find_idp: Found %s.\n", idp_id->buf);
+       tr_debug("tr_cfg_find_idp: Found %s.", idp_id->buf);
        return cfg_idp;
      }
    }
@@@ -907,7 -932,7 +946,7 @@@ TR_RP_CLIENT *tr_cfg_find_rp (TR_CFG *t
    for (cfg_rp = tr_cfg->rp_clients; NULL != cfg_rp; cfg_rp = cfg_rp->next) {
      for (i = 0; i < TR_MAX_GSS_NAMES; i++) {
        if (!tr_name_cmp (rp_gss, cfg_rp->gss_names[i])) {
-       fprintf(stderr, "tr_cfg_find_rp: Found %s.\n", rp_gss->buf);
+       tr_debug("tr_cfg_find_rp: Found %s.", rp_gss->buf);
        return cfg_rp;
        }
      }
@@@ -936,18 -961,18 +975,18 @@@ int tr_find_config_files (struct diren
  
    if (n < 0) {
      perror("scandir");
-     fprintf(stderr, "tr_find_config: scandir error.\n");
+     tr_debug("tr_find_config: scandir error.");
      return 0;
    }
  
    if (n == 0) {
-     fprintf (stderr, "tr_find_config: No config files found.\n");
+     tr_debug("tr_find_config: No config files found.");
      return 0;
    }
  
    i = n;
    while(i--) {
-     fprintf(stderr, "tr_find_config: Config file found (%s).\n", (*cfg_files)[i]->d_name);
+     tr_debug("tr_find_config: Config file found (%s).", (*cfg_files)[i]->d_name);
    }
      
    return n;
diff --combined common/tr_msg.c
@@@ -113,7 -113,7 +113,7 @@@ static DH *tr_msg_decode_dh(json_t *jdh
    json_t *jpub_key = NULL;
  
    if (!(dh = malloc(sizeof(DH)))) {
-     fprintf (stderr, "tr_msg_decode_dh(): Error allocating DH structure.\n");
+     tr_crit("tr_msg_decode_dh(): Error allocating DH structure.");
      return NULL;
    }
   
    if ((NULL == (jp = json_object_get(jdh, "dh_p"))) ||
        (NULL == (jg = json_object_get(jdh, "dh_g"))) ||
        (NULL == (jpub_key = json_object_get(jdh, "dh_pub_key")))) {
-     fprintf (stderr, "tr_msg_decode_dh(): Error parsing dh_info.\n");
+     tr_debug("tr_msg_decode_dh(): Error parsing dh_info.");
      free(dh);
      return NULL;
    }
@@@ -177,7 -177,7 +177,7 @@@ static TID_REQ *tr_msg_decode_tidreq(js
    json_t *jdh = NULL;
  
    if (!(treq =tid_req_new())) {
-     fprintf (stderr, "tr_msg_decode_tidreq(): Error allocating TID_REQ structure.\n");
+     tr_crit("tr_msg_decode_tidreq(): Error allocating TID_REQ structure.");
      return NULL;
    }
   
    if ((NULL == (jrp_realm = json_object_get(jreq, "rp_realm"))) ||
        (NULL == (jrealm = json_object_get(jreq, "target_realm"))) ||
        (NULL == (jcomm = json_object_get(jreq, "community")))) {
-     fprintf (stderr, "tr_msg_decode(): Error parsing required fields.\n");
+     tr_debug("tr_msg_decode(): Error parsing required fields.");
      tid_req_free(treq);
      return NULL;
    }
  
    /* Get DH Info from the request */
    if (NULL == (jdh = json_object_get(jreq, "dh_info"))) {
-     fprintf (stderr, "tr_msg_decode(): Error parsing dh_info.\n");
+     tr_debug("tr_msg_decode(): Error parsing dh_info.");
      tid_req_free(treq);
      return NULL;
    }
    treq->cons = (TR_CONSTRAINT_SET *) json_object_get(jreq, "constraints");
    if (treq->cons) {
      if (!tr_constraint_set_validate(treq->cons)) {
-       tr_debug("Constraint set validation failed\n");
+       tr_debug("Constraint set validation failed");
      tid_req_free(treq);
      return NULL;
      }
@@@ -224,9 -224,8 +224,9 @@@ static json_t *tr_msg_encode_one_server
  {
    json_t *jsrvr = NULL;
    json_t *jstr = NULL;
 +  gchar *time_str = g_time_val_to_iso8601(&srvr->key_expiration);
  
-   fprintf(stderr, "Encoding one server.\n");
+   tr_debug("Encoding one server.");
  
    jsrvr = json_object();
  
    jstr = json_string(inet_ntoa(srvr->aaa_server_addr));
    json_object_set_new(jsrvr, "server_addr", jstr);
  
 +  json_object_set_new(jsrvr,
 +                    "key_expiration", json_string(time_str));
 +  g_free(time_str);
    /* Server DH Block */
    jstr = json_string(srvr->key_name->buf);
    json_object_set_new(jsrvr, "key_name", jstr);
    json_object_set_new(jsrvr, "server_dh", tr_msg_encode_dh(srvr->aaa_server_dh));
 -  
 -  //  tr_debug("tr_msg_encode_one_server(): jsrvr contains:");
 -  //  tr_debug("%s", json_dumps(jsrvr, 0));
 +  if (srvr->path)
 +    /* The path is owned by the srvr, so grab an extra ref*/
 +    json_object_set(jsrvr, "path", srvr->path);
-   //  fprintf(stderr,"tr_msg_encode_one_server(): jsrvr contains:\n");
-   //  fprintf(stderr,"%s\n", json_dumps(jsrvr, 0));
    return jsrvr;
  }
  
@@@ -262,7 -256,7 +260,7 @@@ static int tr_msg_decode_one_server(jso
    if ((NULL == (jsrvr_addr = json_object_get(jsrvr, "server_addr"))) ||
        (NULL == (jsrvr_kn = json_object_get(jsrvr, "key_name"))) ||
        (NULL == (jsrvr_dh = json_object_get(jsrvr, "server_dh")))) {
-     tr_debug("tr_msg_decode_one_server(): Error parsing required fields.\n");
+     tr_debug("tr_msg_decode_one_server(): Error parsing required fields.");
      return -1;
    }
    
@@@ -289,8 -283,8 +287,8 @@@ static json_t *tr_msg_encode_servers(TI
      }
    }
  
-   //  fprintf(stderr,"tr_msg_encode_servers(): servers contains:\n");
-   //  fprintf(stderr,"%s\n", json_dumps(jservers, 0));
+   //  tr_debug("tr_msg_encode_servers(): servers contains:");
+   //  tr_debug("%s", json_dumps(jservers, 0));
    return jservers;
  }
  
@@@ -301,13 -295,13 +299,13 @@@ static TID_SRVR_BLK *tr_msg_decode_serv
    size_t i, num_servers;
  
    num_servers = json_array_size(jservers);
-   fprintf(stderr, "tr_msg_decode_servers(): Number of servers = %u.\n", (unsigned) num_servers);
+   tr_debug("tr_msg_decode_servers(): Number of servers = %u.", (unsigned) num_servers);
    
    if (0 == num_servers) {
-     fprintf(stderr, "tr_msg_decode_servers(): Server array is empty.\n"); 
+     tr_debug("tr_msg_decode_servers(): Server array is empty."); 
      return NULL;
    }
-     servers = talloc_zero_array(ctx, TID_SRVR_BLK, num_servers);
+   servers = talloc_zero_array(ctx, TID_SRVR_BLK, num_servers);
  
    for (i = 0; i < num_servers; i++) {
      jsrvr = json_array_get(jservers, i);
@@@ -361,7 -355,7 +359,7 @@@ static json_t * tr_msg_encode_tidresp(T
    }
  
    if (NULL == resp->servers) {
-     fprintf(stderr, "tr_msg_encode_tidresp(): No servers to encode.\n");
+     tr_debug("tr_msg_encode_tidresp(): No servers to encode.");
      return jresp;
    }
    jservers = tr_msg_encode_servers(resp);
@@@ -382,7 -376,7 +380,7 @@@ static TID_RESP *tr_msg_decode_tidresp(
    json_t *jerr_msg = NULL;
  
    if (!(tresp = talloc_zero(NULL, TID_RESP))) {
-     fprintf (stderr, "tr_msg_decode_tidresp(): Error allocating TID_RESP structure.\n");
+     tr_crit("tr_msg_decode_tidresp(): Error allocating TID_RESP structure.");
      return NULL;
    }
   
        (!json_is_string(jrealm)) ||
        (NULL == (jcomm = json_object_get(jresp, "comm"))) ||
        (!json_is_string(jcomm))) {
-     fprintf (stderr, "tr_msg_decode_tidresp(): Error parsing response.\n");
+     tr_debug("tr_msg_decode_tidresp(): Error parsing response.");
      talloc_free(tresp);
      return NULL;
    }
  
    if (0 == (strcmp(json_string_value(jresult), "success"))) {
-     fprintf(stderr, "tr_msg_decode_tidresp(): Success! result = %s.\n", json_string_value(jresult));
+     tr_debug("tr_msg_decode_tidresp(): Success! result = %s.", json_string_value(jresult));
      if ((NULL != (jservers = json_object_get(jresp, "servers"))) ||
        (!json_is_array(jservers))) {
        tresp->servers = tr_msg_decode_servers(tresp, jservers, &tresp->num_servers); 
    }
    else {
      tresp->result = TID_ERROR;
-     fprintf(stderr, "tr_msg_decode_tidresp(): Error! result = %s.\n", json_string_value(jresult));
+     tr_debug("tr_msg_decode_tidresp(): Error! result = %s.", json_string_value(jresult));
      if ((NULL != (jerr_msg = json_object_get(jresp, "err_msg"))) ||
        (!json_is_string(jerr_msg))) {
        tresp->err_msg = tr_new_name((char *)json_string_value(jerr_msg));
@@@ -477,12 -471,12 +475,12 @@@ TR_MSG *tr_msg_decode(char *jbuf, size_
    const char *mtype = NULL;
  
    if (NULL == (jmsg = json_loadb(jbuf, buflen, JSON_DISABLE_EOF_CHECK, &rc))) {
-     fprintf (stderr, "tr_msg_decode(): error loading object\n");
+     tr_debug("tr_msg_decode(): error loading object");
      return NULL;
    }
  
    if (!(msg = malloc(sizeof(TR_MSG)))) {
-     fprintf (stderr, "tr_msg_decode(): Error allocating TR_MSG structure.\n");
+     tr_debug("tr_msg_decode(): Error allocating TR_MSG structure.");
      json_decref(jmsg);
      return NULL;
    }
  
    if ((NULL == (jtype = json_object_get(jmsg, "msg_type"))) ||
        (NULL == (jbody = json_object_get(jmsg, "msg_body")))) {
-     fprintf (stderr, "tr_msg_decode(): Error parsing message header.\n");
+     tr_debug("tr_msg_decode(): Error parsing message header.");
      json_decref(jmsg);
      tr_msg_free_decoded(msg);
      return NULL;
diff --combined configure.ac
@@@ -18,7 -18,6 +18,7 @@@ AC_PROG_C
                     AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
             fi
             AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
 +PKG_CHECK_MODULES([GLIB], [glib-2.0])
  
  AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context])
  AC_CHECK_LIB([com_err], [error_message])
@@@ -28,6 -27,6 +28,6 @@@ AC_CHECK_LIB([sqlite3], [sqlite3_open],
      [AC_MSG_ERROR([Please install sqlite3 development])])
  AC_CHECK_LIB([jansson], [json_object])
  AC_CHECK_LIB([crypto], [DH_new])
- AC_CHECK_HEADERS(gssapi.h gssapi_ext.h jansson.h talloc.h openssl/dh.h openssl/bn.h)
+ AC_CHECK_HEADERS(gssapi.h gssapi_ext.h jansson.h talloc.h openssl/dh.h openssl/bn.h syslog.h)
  AC_CONFIG_FILES([Makefile gsscon/Makefile])
  AC_OUTPUT
diff --combined tid/tid_req.c
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * Copyright (c) 2012, JANET(UK)
 + * Copyright (c) 2012, 2014-2015, JANET(UK)
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
  #include <talloc.h>
  
  #include <tid_internal.h>
+ #include <tr_debug.h>
  #include <jansson.h>
  
  static int destroy_tid_req(TID_REQ *req)
  {
 +  OM_uint32 minor;
    if (req->json_references)
      json_decref(req->json_references);
 +  if (req->gssctx)
 +    gss_delete_sec_context( &minor, &req->gssctx, NULL);
    return 0;
  }
  
@@@ -177,7 -176,7 +179,7 @@@ TID_REQ *tid_dup_req (TID_REQ *orig_req
    TID_REQ *new_req = NULL;
  
    if (NULL == (new_req = malloc(sizeof(TID_REQ)))) {
-     fprintf(stderr, "tid_dup_req: Can't allocated duplicate request.\n");
+     tr_crit("tid_dup_req: Can't allocated duplicate request.");
      return NULL;
    }
  
    if ((NULL == (new_req->rp_realm = tr_dup_name(orig_req->rp_realm))) ||
        (NULL == (new_req->realm = tr_dup_name(orig_req->realm))) ||
        (NULL == (new_req->comm = tr_dup_name(orig_req->comm)))) {
-       fprintf(stderr, "tid_dup_req: Can't duplicate request (names).\n");
+       tr_crit("tid_dup_req: Can't duplicate request (names).");
    }
  
    if (orig_req->orig_coi) {
      if (NULL == (new_req->orig_coi = tr_dup_name(orig_req->orig_coi))) {
-       fprintf(stderr, "tid_dup_req: Can't duplicate request (orig_coi).\n");
+       tr_crit("tid_dup_req: Can't duplicate request (orig_coi).");
      }
    }
    
@@@ -211,21 -210,6 +213,21 @@@ void tid_req_free(TID_REQ *req
    talloc_free(req);
  }
  
 +int tid_req_add_path(TID_REQ *req,
 +                   const char *this_system, unsigned port)
 +{
 +  char *path_element = talloc_asprintf(req, "%s:%u",
 +                                     this_system, port);
 +  if (!req->path) {
 +    req->path = json_array();
 +    if (!req->path)
 +      return -1;
 +    tid_req_cleanup_json(req, req->path);
 +  }
 +  return json_array_append( req->path, json_string(path_element));
 +}
 +
 +
  
  void tid_srvr_get_address(const TID_SRVR_BLK *blk,
                          const struct sockaddr **out_addr,
diff --combined tr/tr_main.c
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * Copyright (c) 2012, JANET(UK)
 + * Copyright (c) 2012, 2015, JANET(UK)
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
@@@ -42,6 -42,7 +42,7 @@@
  #include <tr_comm.h>
  #include <tr_idp.h>
  #include <tr_rp.h>
+ #include <tr_debug.h>
  
  /* Structure to hold TR instance and original request in one cookie */
  typedef struct tr_resp_cookie {
@@@ -55,7 -56,7 +56,7 @@@ static void tr_tidc_resp_handler (TIDC_
                        TID_RESP *resp, 
                        void *resp_cookie) 
  {
-   fprintf(stderr, "tr_tidc_resp_handler: Response received (conn = %d)! Realm = %s, Community = %s.\n", ((TR_RESP_COOKIE *)resp_cookie)->orig_req->conn, resp->realm->buf, resp->comm->buf);
+   tr_debug("tr_tidc_resp_handler: Response received (conn = %d)! Realm = %s, Community = %s.", ((TR_RESP_COOKIE *)resp_cookie)->orig_req->conn, resp->realm->buf, resp->comm->buf);
    req->resp_rcvd = 1;
  
    /* TBD -- handle concatentation of multiple responses to single req */
@@@ -69,7 -70,7 +70,7 @@@
  static int tr_tids_req_handler (TIDS_INSTANCE *tids,
                      TID_REQ *orig_req, 
                      TID_RESP *resp,
 -                    void *tr)
 +                    void *tr_in)
  {
    TIDC_INSTANCE *tidc = NULL;
    TR_RESP_COOKIE resp_cookie;
    TID_REQ *fwd_req = NULL;
    TR_COMM *cfg_comm = NULL;
    TR_COMM *cfg_apc = NULL;
 +  TR_INSTANCE *tr = (TR_INSTANCE *) tr_in;
    int oaction = TR_FILTER_ACTION_REJECT;
    int rc = 0;
  
    if ((!tids) || (!orig_req) || (!resp) ||  (!tr)) {
-     fprintf(stderr, "tids_req_handler: Bad parameters\n");
+     tr_debug("tr_tids_req_handler: Bad parameters");
      return -1;
    }
  
-   fprintf(stdout, "tr_tids_req_handler: Request received (conn = %d)! Realm = %s, Comm = %s\n", orig_req->conn, 
+   tr_debug("tr_tids_req_handler: Request received (conn = %d)! Realm = %s, Comm = %s", orig_req->conn, 
         orig_req->realm->buf, orig_req->comm->buf);
    if (tids)
      tids->req_count++;
  
    /* Duplicate the request, so we can modify and forward it */
    if (NULL == (fwd_req = tid_dup_req(orig_req))) {
-     fprintf(stderr, "tr_tids_req_handler: Unable to duplicate request.\n");
+     tr_debug("tr_tids_req_handler: Unable to duplicate request.");
      return -1;
    }
  
 -  if (NULL == (cfg_comm = tr_comm_lookup((TR_INSTANCE *)tids->cookie, orig_req->comm))) {
 +  if (NULL == (cfg_comm = tr_comm_lookup(tids->cookie, orig_req->comm))) {
-     fprintf(stderr, "tr_tids_req_hander: Request for unknown comm: %s.\n", orig_req->comm->buf);
+     tr_notice("tr_tids_req_hander: Request for unknown comm: %s.", orig_req->comm->buf);
      tids_send_err_response(tids, orig_req, "Unknown community");
      return -1;
    }
    /* Check that the rp_realm matches the filter for the GSS name that 
     * was received. */
  
 -  if ((!((TR_INSTANCE *)tr)->rp_gss) || 
 -      (!((TR_INSTANCE *)tr)->rp_gss->filter)) {
 +  if ((!(tr)->rp_gss) || 
 +      (!(tr)->rp_gss->filter)) {
-     fprintf(stderr, "tr_tids_req_handler: No GSS name for incoming request.\n");
+     tr_notice("tr_tids_req_handler: No GSS name for incoming request.");
      tids_send_err_response(tids, orig_req, "No GSS name for request");
      return -1;
    }
  
 -  if ((TR_FILTER_NO_MATCH == tr_filter_process_rp_permitted(orig_req->rp_realm, ((TR_INSTANCE *)tr)->rp_gss->filter, orig_req->cons, &fwd_req->cons, &oaction)) ||
 +  if ((TR_FILTER_NO_MATCH == tr_filter_process_rp_permitted(orig_req->rp_realm, (tr)->rp_gss->filter, orig_req->cons, &fwd_req->cons, &oaction)) ||
        (TR_FILTER_ACTION_REJECT == oaction)) {
-     fprintf(stderr, "tr_tids_req_handler: RP realm (%s) does not match RP Realm filter for GSS name\n", orig_req->rp_realm->buf);
+     tr_notice("tr_tids_req_handler: RP realm (%s) does not match RP Realm filter for GSS name", orig_req->rp_realm->buf);
      tids_send_err_response(tids, orig_req, "RP Realm filter error");
      return -1;
    }
    /* Check that the rp_realm is a member of the community in the request */
    if (NULL == (tr_find_comm_rp(cfg_comm, orig_req->rp_realm))) {
-     fprintf(stderr, "tr_tids_req_handler: RP Realm (%s) not member of community (%s).\n", orig_req->rp_realm->buf, orig_req->comm->buf);
+     tr_notice("tr_tids_req_handler: RP Realm (%s) not member of community (%s).", orig_req->rp_realm->buf, orig_req->comm->buf);
      tids_send_err_response(tids, orig_req, "RP COI membership error");
      return -1;
    }
  
    /* Map the comm in the request from a COI to an APC, if needed */
    if (TR_COMM_COI == cfg_comm->type) {
-     fprintf(stderr, "tr_tids_req_handler: Community was a COI, switching.\n");
+     tr_debug("tr_tids_req_handler: Community was a COI, switching.");
      /* TBD -- In theory there can be more than one?  How would that work? */
      if ((!cfg_comm->apcs) || (!cfg_comm->apcs->id)) {
-       fprintf(stderr, "No valid APC for COI %s.\n", orig_req->comm->buf);
+       tr_notice("No valid APC for COI %s.", orig_req->comm->buf);
        tids_send_err_response(tids, orig_req, "No valid APC for community");
        return -1;
      }
      apc = tr_dup_name(cfg_comm->apcs->id);
  
      /* Check that the APC is configured */
 -    if (NULL == (cfg_apc = tr_comm_lookup((TR_INSTANCE *)tids->cookie, apc))) {
 +    if (NULL == (cfg_apc = tr_comm_lookup(tids->cookie, apc))) {
-       fprintf(stderr, "tr_tids_req_hander: Request for unknown comm: %s.\n", apc->buf);
+       tr_notice("tr_tids_req_hander: Request for unknown comm: %s.", apc->buf);
        tids_send_err_response(tids, orig_req, "Unknown APC");
        return -1;
      }
  
      /* Check that rp_realm is a  member of this APC */
      if (NULL == (tr_find_comm_rp(cfg_apc, orig_req->rp_realm))) {
-       fprintf(stderr, "tr_tids_req_hander: RP Realm (%s) not member of community (%s).\n", orig_req->rp_realm->buf, orig_req->comm->buf);
+       tr_notice("tr_tids_req_hander: RP Realm (%s) not member of community (%s).", orig_req->rp_realm->buf, orig_req->comm->buf);
        tids_send_err_response(tids, orig_req, "RP APC membership error");
        return -1;
      }
    if (NULL == (aaa_servers = tr_idp_aaa_server_lookup((TR_INSTANCE *)tids->cookie, 
                                                      orig_req->realm, 
                                                      orig_req->comm))) {
-       fprintf(stderr, "tr_tids_req_handler: No AAA Servers for realm %s, defaulting.\n", orig_req->realm->buf);
+       tr_debug("tr_tids_req_handler: No AAA Servers for realm %s, defaulting.", orig_req->realm->buf);
        if (NULL == (aaa_servers = tr_default_server_lookup ((TR_INSTANCE *)tids->cookie,
                                                           orig_req->comm))) {
-       fprintf(stderr, "tr_tids_req_handler: No default AAA servers, discarded.\n");
-       tids_send_err_response(tids, orig_req, "No path to AAA Server(s) for realm");
-       return -1;
+       tr_notice("tr_tids_req_handler: No default AAA servers, discarded.");
+         tids_send_err_response(tids, orig_req, "No path to AAA Server(s) for realm");
+         return -1;
        }
    } else {
      /* if we aren't defaulting, check idp coi and apc membership */
      if (NULL == (tr_find_comm_idp(cfg_comm, fwd_req->realm))) {
-       fprintf(stderr, "tr_tids_req_handler: IDP Realm (%s) not member of community (%s).\n", orig_req->realm->buf, orig_req->comm->buf);
+       tr_notice("tr_tids_req_handler: IDP Realm (%s) not member of community (%s).", orig_req->realm->buf, orig_req->comm->buf);
        tids_send_err_response(tids, orig_req, "IDP community membership error");
        return -1;
      }
      if ( cfg_apc && (NULL == (tr_find_comm_idp(cfg_apc, fwd_req->realm)))) {
-       fprintf(stderr, "tr_tids_req_handler: IDP Realm (%s) not member of APC (%s).\n", orig_req->realm->buf, orig_req->comm->buf);
+       tr_notice("tr_tids_req_handler: IDP Realm (%s) not member of APC (%s).", orig_req->realm->buf, orig_req->comm->buf);
        tids_send_err_response(tids, orig_req, "IDP APC membership error");
        return -1;
      }
    /* send a TID request to the AAA server(s), and get the answer(s) */
    /* TBD -- Handle multiple servers */
  
 +  if (cfg_apc)
 +    fwd_req->expiration_interval = cfg_apc->expiration_interval;
 +  else fwd_req->expiration_interval = cfg_comm->expiration_interval;
    /* Create a TID client instance */
    if (NULL == (tidc = tidc_create())) {
-     fprintf(stderr, "tr_tids_req_hander: Unable to allocate TIDC instance.\n");
+     tr_crit("tr_tids_req_hander: Unable to allocate TIDC instance.");
      tids_send_err_response(tids, orig_req, "Memory allocation failure");
      return -1;
    }
                                                  aaa_servers->hostname->buf,
                                                  TID_PORT,
                                              &(fwd_req->gssctx)))) {
-     fprintf(stderr, "tr_tids_req_handler: Error in tidc_open_connection.\n");
+     tr_notice("tr_tids_req_handler: Error in tidc_open_connection.");
      tids_send_err_response(tids, orig_req, "Can't open connection to next hop TIDS");
      return -1;
    };
  
    /* Send a TID request */
    if (0 > (rc = tidc_fwd_request(tidc, fwd_req, &tr_tidc_resp_handler, (void *)&resp_cookie))) {
-     fprintf(stderr, "Error from tidc_fwd_request, rc = %d.\n", rc);
+     tr_notice("Error from tidc_fwd_request, rc = %d.", rc);
      tids_send_err_response(tids, orig_req, "Can't forward request to next hop TIDS");
      return -1;
    }
  }
  
  static int tr_tids_gss_handler(gss_name_t client_name, TR_NAME *gss_name,
 -                      void *tr)
 +                      void *tr_in)
  {
    TR_RP_CLIENT *rp;
 +  TR_INSTANCE *tr = (TR_INSTANCE *) tr_in;
  
    if ((!client_name) || (!gss_name) || (!tr)) {
-     fprintf(stderr, "tr_tidc_gss_handler: Bad parameters.\n");
+     tr_debug("tr_tidc_gss_handler: Bad parameters.");
      return -1;
    }
    
    /* look up the RP client matching the GSS name */
    if ((NULL == (rp = tr_rp_client_lookup(tr, gss_name)))) {
-     fprintf(stderr, "tr_tids_gss_handler: Unknown GSS name %s\n", gss_name->buf);
+     tr_debug("tr_tids_gss_handler: Unknown GSS name %s", gss_name->buf);
      return -1;
    }
  
    /* Store the rp client in the TR_INSTANCE structure for now... 
     * TBD -- fix me for new tasking model. */
 -  ((TR_INSTANCE *)tr)->rp_gss = rp;
 +  (tr)->rp_gss = rp;
-   fprintf( stderr, "Client's GSS Name: %s\n", gss_name->buf);
+   tr_debug("Client's GSS Name: %s", gss_name->buf);
++
    return 0;
  }
  
@@@ -258,36 -254,36 +260,36 @@@ int main (int argc, const char *argv[]
  
    /* create a Trust Router instance */
    if (NULL == (tr = tr_create())) {
-     fprintf(stderr, "Unable to create Trust Router instance, exiting.\n");
+     tr_crit("Unable to create Trust Router instance, exiting.");
      return 1;
    }
  
    /* find the configuration files */
    if (0 == (n = tr_find_config_files(&cfg_files))) {
-     fprintf (stderr, "Can't locate configuration files, exiting.\n");
+     tr_crit("Can't locate configuration files, exiting.");
      exit(1);
    }
  
    if (TR_CFG_SUCCESS != tr_parse_config(tr, n, cfg_files)) {
-     fprintf (stderr, "Error decoding configuration information, exiting.\n");
+     tr_crit("Error decoding configuration information, exiting.");
      exit(1);
    }
  
    /* apply initial configuration */
    if (TR_CFG_SUCCESS != (rc = tr_apply_new_config(tr))) {
-     fprintf (stderr, "Error applying configuration, rc = %d.\n", rc);
+     tr_crit("Error applying configuration, rc = %d.", rc);
      exit(1);
    }
  
    /* initialize the trust path query server instance */
    if (0 == (tr->tids = tids_create ())) {
-     fprintf (stderr, "Error initializing Trust Path Query Server instance.\n");
+     tr_crit("Error initializing Trust Path Query Server instance.");
      exit(1);
    }
  
    /* start the trust path query server, won't return unless fatal error. */
    if (0 != (err = tids_start(tr->tids, &tr_tids_req_handler, &tr_tids_gss_handler, tr->active_cfg->internal->hostname, tr->active_cfg->internal->tids_port, (void *)tr))) {
-     fprintf (stderr, "Error from Trust Path Query Server, err = %d.\n", err);
+     tr_crit("Error from Trust Path Query Server, err = %d.", err);
      exit(err);
    }