Merge pull request #51 from painless-security/jennifer/monitoring_client_and_server
authormrw42 <margaret@painless-security.com>
Thu, 3 May 2018 20:03:15 +0000 (16:03 -0400)
committerGitHub <noreply@github.com>
Thu, 3 May 2018 20:03:15 +0000 (16:03 -0400)
First functioning monitoring client/server (pull request 3)

33 files changed:
CMakeLists.txt
Makefile.am
common/tests/filt_test.c
common/tr_gss.c
common/tr_gss_client.c [new file with mode: 0644]
common/tr_msg.c
include/mon.h [new file with mode: 0644]
include/mon_internal.h
include/mons_handlers.h [new file with mode: 0644]
include/tid_internal.h
include/tr_gss.h
include/tr_gss_client.h [new file with mode: 0644]
include/tr_mon.h
include/tr_msg.h
include/trust_router/tid.h
mon/mon_common.c
mon/mon_req.c
mon/mon_req_decode.c
mon/mon_resp.c
mon/mon_resp_decode.c [new file with mode: 0644]
mon/mon_resp_encode.c
mon/monc.c [new file with mode: 0644]
mon/mons.c
mon/mons_handlers.c [new file with mode: 0644]
mon/tests/test_mon_req_decode.c
mon/tests/test_mon_resp_encode.c
tid/example/tidc_main.c
tid/tidc.c
tid/tids.c
tr/tr_main.c
tr/trmon_main.c [new file with mode: 0644]
trp/msgtst.c
trp/trps.c

index 2fe9749..f7bff87 100644 (file)
@@ -91,11 +91,13 @@ set(SOURCE_FILES
     trp/trp_upd.c
     trp/trpc.c
     trp/trps.c include/tr_name_internal.h mon/mon_req.c mon/mon_req_encode.c mon/mon_req_decode.c
-        mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c)
+        mon/mon_resp.c mon/mon_common.c mon/mon_resp_encode.c mon/mon_resp_decode.c tr/tr_mon.c mon/mons.c include/tr_socket.h common/tr_gss.c include/tr_gss.h common/tr_config_internal.c mon/mons_handlers.c include/mons_handlers.h)
 
 # Does not actually build!
 add_executable(trust_router ${SOURCE_FILES})
 
+add_executable(trmon mon/monc.c tr/trmon_main.c common/tr_gss_client.c include/tr_gss_client.h)
+
 # Test build targets - for debugging
 add_executable(test_mon_req_encode mon/mon_common.c mon/mon_req.c mon/tests/test_mon_req_encode.c mon/mon_req_encode.c)
 target_link_libraries(test_mon_req_encode jansson talloc glib-2.0)
index 49bf774..c73c623 100644 (file)
@@ -4,7 +4,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
 bin_PROGRAMS= tr/trust_router tr/trpc tid/example/tidc tid/example/tids common/tests/tr_dh_test common/tests/mq_test \
               common/tests/thread_test trp/msgtst trp/test/rtbl_test trp/test/ptbl_test common/tests/cfg_test \
               common/tests/commtest common/tests/name_test common/tests/filt_test mon/tests/test_mon_req_encode \
-              mon/tests/test_mon_req_decode mon/tests/test_mon_resp_encode
+              mon/tests/test_mon_req_decode mon/tests/test_mon_resp_encode tr/trmon
 AM_CPPFLAGS=-I$(srcdir)/include $(GLIB_CFLAGS)
 AM_CFLAGS = -Wall -Werror=missing-prototypes -Werror -Wno-parentheses $(GLIB_CFLAGS)
 SUBDIRS = gsscon 
@@ -21,7 +21,8 @@ common_srcs = common/tr_name.c \
        common/tr_idp.c \
        common/tr_filter.c \
        common/tr_gss_names.c \
-       common/tr_socket.c
+       common/tr_socket.c \
+       $(mon_srcs)
 
 tid_srcs = tid/tid_resp.c \
 tid/tid_req.c \
@@ -39,15 +40,21 @@ common/tr_config.c \
 common/tr_config_internal.c \
 common/tr_mq.c
 
+# general monitoring message sources
 mon_srcs =                   \
-    mon/mons.c               \
     mon/mon_common.c         \
     mon/mon_req.c            \
     mon/mon_req_encode.c     \
     mon/mon_req_decode.c     \
     mon/mon_resp.c           \
+    mon/mon_resp_decode.c    \
     mon/mon_resp_encode.c
 
+# monitoring server sources
+mons_srcs = \
+    mon/mons.c \
+    mon/mons_handlers.c
+
 check_PROGRAMS = common/t_constraint
 TESTS = common/t_constraint
 TEST_CFLAGS = -Wno-missing-prototypes
@@ -82,16 +89,19 @@ tr/tr_tid.c \
 tr/tr_trp.c \
 tr/tr_mon.c \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs) \
-$(mon_srcs) \
-$(common_srcs)
+$(common_srcs) \
+$(mons_srcs)
 
 tr_trust_router_LDFLAGS = $(AM_LDFLAGS) -levent_pthreads -pthread
 tr_trust_router_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
+
 tr_trpc_SOURCES =tr/trpc_main.c \
 tr/tr_trp.c \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(trp_srcs) \
 $(tid_srcs) \
 $(common_srcs)
@@ -99,6 +109,17 @@ $(common_srcs)
 tr_trpc_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
 tr_trpc_LDFLAGS = $(AM_LDFLAGS) -pthread
 
+tr_trmon_SOURCES = tr/trmon_main.c \
+common/tr_gss.c \
+common/tr_gss_client.c \
+$(tid_srcs) \
+$(trp_srcs) \
+$(common_srcs) \
+mon/monc.c
+
+tr_trmon_LDADD = gsscon/libgsscon.la  $(GLIB_LIBS)
+tr_trmon_LDFLAGS = $(AM_LDFLAGS) -pthread
+
 trp_msgtst_SOURCES = trp/msgtst.c \
 $(common_srcs) \
 trp/trp_req.c \
@@ -116,6 +137,7 @@ trp_test_rtbl_test_LDADD =  $(GLIB_LIBS)
 
 trp_test_ptbl_test_SOURCES = trp/test/ptbl_test.c \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs) \
 $(common_srcs)
@@ -124,6 +146,7 @@ trp_test_ptbl_test_LDFLAGS = $(AM_LDFLAGS) -pthread
 
 tid_example_tidc_SOURCES = tid/example/tidc_main.c \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs) \
 $(common_srcs)
@@ -132,6 +155,7 @@ tid_example_tidc_LDFLAGS = $(AM_LDFLAGS) -pthread
 
 tid_example_tids_SOURCES = tid/example/tids_main.c \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs) \
 $(common_srcs)
@@ -151,6 +175,7 @@ common_tests_mq_test_LDFLAGS = $(AM_LDFLAGS) -ltalloc -pthread
 common_tests_cfg_test_SOURCES = common/tests/cfg_test.c \
 $(common_srcs) \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs)
 common_tests_cfg_test_LDADD = gsscon/libgsscon.la  $(GLIB_LIBS)
@@ -163,6 +188,7 @@ common/tests/thread_test.c
 common_tests_commtest_SOURCES = common/tests/commtest.c \
 $(common_srcs) \
 common/tr_gss.c \
+common/tr_gss_client.c \
 $(tid_srcs) \
 $(trp_srcs)
 common_tests_commtest_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
@@ -173,6 +199,7 @@ common_tests_thread_test_LDFLAGS = $(AM_LDFLAGS) -ltalloc -pthread
 common_tests_name_test_SOURCES = common/tests/name_test.c \
               $(common_srcs) \
               common/tr_gss.c \
+              common/tr_gss_client.c \
               $(tid_srcs) \
               $(trp_srcs)
 common_tests_name_test_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
@@ -182,6 +209,7 @@ common_tests_name_test_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
 common_tests_filt_test_SOURCES = common/tests/filt_test.c \
               $(common_srcs) \
               common/tr_gss.c \
+              common/tr_gss_client.c \
               $(tid_srcs) \
               $(trp_srcs)
 common_tests_filt_test_LDADD = gsscon/libgsscon.la $(GLIB_LIBS)
index d7dfe06..342c27b 100644 (file)
@@ -119,7 +119,7 @@ TRP_INFOREC *load_inforec(const char *fname)
   json_decref(decoded);
 
   assert(encoded);
-  assert(msg=tr_msg_decode(encoded, strlen(encoded)));
+  assert(msg= tr_msg_decode(NULL, encoded, strlen(encoded)));
   assert(upd=tr_msg_get_trp_upd(msg));
   assert(inforec=trp_upd_get_inforec(upd));
   /* now remove the inforec from the update context */
@@ -146,7 +146,7 @@ TID_REQ *load_tid_req(const char *fname)
   msglen=fread(msgbuf, 1, MAX_FILE_SIZE, f);
   assert(msglen);
   assert(feof(f));
-  msg=tr_msg_decode(msgbuf, msglen);
+  msg= tr_msg_decode(NULL, msgbuf, msglen);
   free(msgbuf);
   msgbuf=NULL;
 
index 39a13a9..e2483b9 100644 (file)
@@ -221,6 +221,9 @@ void tr_gss_handle_connection(int conn,
   TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   gss_ctx_id_t gssctx = GSS_C_NO_CONTEXT;
   char *req_str = NULL;
+  size_t req_len = 0;
+  TR_MSG *req_msg = NULL;
+  TR_MSG *resp_msg = NULL;
   char *resp_str = NULL;
 
   if (tr_gss_auth_connection(conn,
@@ -236,34 +239,52 @@ void tr_gss_handle_connection(int conn,
   tr_debug("tr_gss_handle_connection: Connection authorized");
 
   // TODO: should there be a timeout on this?
-  while (1) {  /* continue until an error breaks us out */
+  do {
+    /* continue until an error breaks us out */
     // try to read a request
     req_str = tr_gss_read_req(tmp_ctx, conn, gssctx);
 
-    if ( req_str == NULL) {
+    if (req_str == NULL) {
       // an error occurred, give up
       tr_notice("tr_gss_handle_connection: Error reading request");
       goto cleanup;
-    } else if (strlen(req_str) > 0) {
-      // we got a request message, exit the loop and process it
-      break;
     }
 
-    // no error, but no message, keep waiting for one
-    talloc_free(req_str); // this would be cleaned up anyway, but may as well free it
+    req_len = strlen(req_str);
+
+    /* If we got no characters, we will loop again. Free the empty response for the next loop. */
+    if (req_len == 0)
+      talloc_free(req_str);
+
+  } while (req_len == 0);
+
+  /* Decode the request */
+  req_msg = tr_msg_decode(tmp_ctx, req_str, req_len);
+  if (req_msg == NULL) {
+    tr_notice("tr_gss_handle_connection: Error decoding response");
+    goto cleanup;
   }
 
   /* Hand off the request for processing and get the response */
-  resp_str = req_cb(tmp_ctx, req_str, req_cookie);
+  resp_msg = req_cb(tmp_ctx, req_msg, req_cookie);
 
-  if (resp_str == NULL) {
+  if (resp_msg == NULL) {
     // no response, clean up
     goto cleanup;
   }
 
+  /* Encode the response */
+  resp_str = tr_msg_encode(tmp_ctx, resp_msg);
+  if (resp_str == NULL) {
+    /* We apparently can't encode a response, so just return */
+    tr_err("tr_gss_handle_connection: Error encoding response");
+    goto cleanup;
+  }
+
   // send the response
   if (tr_gss_write_resp(conn, gssctx, resp_str)) {
-    tr_notice("tr_gss_handle_connection: Error writing response");
+    tr_err("tr_gss_handle_connection: Error writing response");
+    goto cleanup;
   }
 
 cleanup:
diff --git a/common/tr_gss_client.c b/common/tr_gss_client.c
new file mode 100644 (file)
index 0000000..db9f380
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2012, 2014-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <talloc.h>
+
+#include <trust_router/tr_dh.h>
+#include <tr_msg.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+#include <tr_gss_client.h>
+
+static int tr_gssc_destructor(void *obj)
+{
+  TR_GSSC_INSTANCE *tr_gssc=talloc_get_type_abort(obj, TR_GSSC_INSTANCE);
+  if (NULL!=tr_gssc) {
+    if (NULL!=tr_gssc->client_dh)
+      tr_destroy_dh_params(tr_gssc->client_dh);
+  }
+  return 0;
+}
+
+TR_GSSC_INSTANCE *tr_gssc_instance_new(TALLOC_CTX *mem_ctx)
+{
+  TR_GSSC_INSTANCE *gssc=talloc(NULL, TR_GSSC_INSTANCE);
+  if (gssc != NULL) {
+    gssc->service_name = NULL;
+    gssc->client_dh = NULL;
+    gssc->conn = -1;
+    gssc->gss_ctx = talloc(gssc, gss_ctx_id_t);
+    if (gssc->gss_ctx == NULL) {
+      talloc_free(gssc); /* before the destructor is set */
+      return NULL;
+    }
+    talloc_set_destructor((void *)gssc, tr_gssc_destructor);
+  }
+  return gssc;
+}
+
+void tr_gssc_instance_free(TR_GSSC_INSTANCE *tr_gssc)
+{
+  talloc_free(tr_gssc);
+}
+
+/**
+ * Open a connection to the requested server:port
+ *
+ * @param gssc client instance
+ * @param server server name/address
+ * @param port TCP port to connect
+ * @return 0 on success, -1 on failure
+ */
+int tr_gssc_open_connection(TR_GSSC_INSTANCE *gssc, const char *server, unsigned int port)
+{
+  tr_debug("tr_gssc_open_connection: opening connection to %s:%d", server, port);
+  if (0 != gsscon_connect(server, port, gssc->service_name, &(gssc->conn), gssc->gss_ctx))
+    return -1;
+
+  return 0; /* success */
+}
+
+/**
+ * Send a request message and retrieve a response message
+ *
+ * @param mem_ctx
+ * @param gssc
+ * @param req_msg
+ * @return decoded message, or null on error
+ */
+TR_MSG *tr_gssc_exchange_msgs(TALLOC_CTX *mem_ctx, TR_GSSC_INSTANCE *gssc, TR_MSG *req_msg)
+{
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+  char *req_buf = NULL;
+  char *resp_buf = NULL;
+  size_t resp_buflen = 0;
+  TR_MSG *resp_msg = NULL; /* this is the return value */
+  int err;
+
+  /* Validate inputs */
+  if ((gssc == NULL) || (req_msg == NULL))
+    goto cleanup;
+
+  /* Encode the request into a json string */
+  if (!(req_buf = tr_msg_encode(tmp_ctx, req_msg))) {
+    tr_err("tr_gssc_exchange_msgs: Error encoding request message.\n");
+    goto cleanup;
+  }
+
+  tr_debug( "tr_gssc_exchange_msgs: Sending request message:\n%s\n", req_buf);
+
+  /* Send the request over the connection */
+  err = gsscon_write_encrypted_token(gssc->conn, *(gssc->gss_ctx), req_buf, strlen(req_buf));
+  if (err) {
+    tr_err( "tr_gssc_exchange_msgs: Error sending request.\n");
+    goto cleanup;
+  }
+
+  /* Read the response from the connection */
+  /* TBD -- timeout? */
+  if (gsscon_read_encrypted_token(gssc->conn, *(gssc->gss_ctx), &resp_buf, &resp_buflen))
+    goto cleanup;
+
+  tr_debug( "tr_gssc_exchange_msgs: Response Received (%u bytes).\n%s\n", (unsigned) resp_buflen, resp_buf);
+  resp_msg = tr_msg_decode(mem_ctx, resp_buf, resp_buflen);
+  free(resp_buf);
+
+  if (resp_msg == NULL) {
+    tr_err( "tr_gssc_exchange_msgs: Error decoding response.\n");
+    goto cleanup;
+  }
+
+  /* If we get here, then we decoded the message and resp_msg is not null. Nothing more to do. */
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return resp_msg;
+}
+
+DH * tr_gssc_get_dh(TR_GSSC_INSTANCE *inst)
+{
+  return inst->client_dh;
+}
+
+DH *tr_gssc_set_dh(TR_GSSC_INSTANCE *inst, DH *dh)
+{
+  inst->client_dh = dh;
+  return dh;
+}
index e0e406a..129ea97 100644 (file)
 
 #include <tr_apc.h>
 #include <tr_comm.h>
+#include <mon_internal.h>
+#include <trp_internal.h>
 #include <tr_msg.h>
 #include <tr_name_internal.h>
-#include <trp_internal.h>
 #include <trust_router/tr_constraint.h>
 #include <trust_router/tr_dh.h>
 #include <tr_debug.h>
@@ -101,6 +102,17 @@ void tr_msg_set_msg_type(TR_MSG *msg, enum msg_type type)
   msg->msg_type = type;
 }
 
+/* NOTE: If you are manipulating messages with these getters/setters, the msg_rep
+ * objects are *not* put in the talloc context of the msg. If you are allocating
+ * the message directly with talloc, then you can talloc_steal() the rep into the
+ * message's context, but this is not handled automatically. */
+
+/**
+ * Get a TID_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TID_REQUEST message
+ */
 TID_REQ *tr_msg_get_req(TR_MSG *msg)
 {
   if (msg->msg_type == TID_REQUEST)
@@ -108,12 +120,24 @@ TID_REQ *tr_msg_get_req(TR_MSG *msg)
   return NULL;
 }
 
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
 void tr_msg_set_req(TR_MSG *msg, TID_REQ *req)
 {
   msg->msg_rep = req;
   msg->msg_type = TID_REQUEST;
 }
 
+/**
+ * Get a TID_RESP message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TID_RESPONSE message
+ */
 TID_RESP *tr_msg_get_resp(TR_MSG *msg)
 {
   if (msg->msg_type == TID_RESPONSE)
@@ -121,12 +145,74 @@ TID_RESP *tr_msg_get_resp(TR_MSG *msg)
   return NULL;
 }
 
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
 void tr_msg_set_resp(TR_MSG *msg, TID_RESP *resp)
 {
   msg->msg_rep = resp;
   msg->msg_type = TID_RESPONSE;
 }
 
+/**
+ * Get a MON_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a MON_REQUEST message
+ */
+MON_REQ *tr_msg_get_mon_req(TR_MSG *msg)
+{
+  if (msg->msg_type == MON_REQUEST)
+    return (MON_REQ *)msg->msg_rep;
+  return NULL;
+}
+
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
+void tr_msg_set_mon_req(TR_MSG *msg, MON_REQ *req)
+{
+  msg->msg_rep = req;
+  msg->msg_type = MON_REQUEST;
+}
+
+/**
+ * Get a MON_RESP message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a MON_RESPONSE message
+ */
+MON_RESP *tr_msg_get_mon_resp(TR_MSG *msg)
+{
+  if (msg->msg_type == MON_RESPONSE)
+    return (MON_RESP *)msg->msg_rep;
+  return NULL;
+}
+
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
+void tr_msg_set_mon_resp(TR_MSG *msg, MON_RESP *resp)
+{
+  msg->msg_rep = resp;
+  msg->msg_type = MON_RESPONSE;
+}
+
+/**
+ * Get a TRP_UPD message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TRP_UPDATE message
+ */
 TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg)
 {
   if (msg->msg_type == TRP_UPDATE)
@@ -134,13 +220,24 @@ TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg)
   return NULL;
 }
 
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
 void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *update)
 {
   msg->msg_rep=update;
-  talloc_steal(NULL, update); /* should attach to msg, but TR_MSG not usually talloc'ed */
   msg->msg_type=TRP_UPDATE;
 }
 
+/**
+ * Get a TRP_REQ message payload
+ *
+ * @param msg
+ * @return the message payload, or null if it is not a TRP_REQUEST message
+ */
 TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg)
 {
   if (msg->msg_type == TRP_REQUEST)
@@ -148,6 +245,12 @@ TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg)
   return NULL;
 }
 
+/**
+ * Set message's payload
+ *
+ * Does not manage talloc contexts, works with any means of allocating
+ * the objects.
+ */
 void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req)
 {
   msg->msg_rep=req;
@@ -216,7 +319,8 @@ static json_t * tr_msg_encode_tidreq(TID_REQ *req)
   if ((!req) || (!req->rp_realm) || (!req->realm) || !(req->comm))
     return NULL;
 
-  assert(jreq = json_object());
+  jreq = json_object();
+  assert(jreq);
 
   jstr = tr_name_to_json_string(req->rp_realm);
   json_object_set_new(jreq, "rp_realm", jstr);
@@ -246,7 +350,7 @@ static json_t * tr_msg_encode_tidreq(TID_REQ *req)
   return jreq;
 }
 
-static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
+static TID_REQ *tr_msg_decode_tidreq(TALLOC_CTX *mem_ctx, json_t *jreq)
 {
   TID_REQ *treq = NULL;
   json_t *jrp_realm = NULL;
@@ -261,7 +365,8 @@ static TID_REQ *tr_msg_decode_tidreq(json_t *jreq)
     tr_crit("tr_msg_decode_tidreq(): Error allocating TID_REQ structure.");
     return NULL;
   }
+  talloc_steal(mem_ctx, treq);
+
   /* store required fields from request */
   if ((NULL == (jrp_realm = json_object_get(jreq, "rp_realm"))) ||
       (NULL == (jrealm = json_object_get(jreq, "target_realm"))) ||
@@ -483,7 +588,7 @@ static json_t * tr_msg_encode_tidresp(TID_RESP *resp)
   return jresp;
 }
 
-static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
+static TID_RESP *tr_msg_decode_tidresp(TALLOC_CTX *mem_ctx, json_t *jresp)
 {
   TID_RESP *tresp = NULL;
   json_t *jresult = NULL;
@@ -494,11 +599,10 @@ static TID_RESP *tr_msg_decode_tidresp(json_t *jresp)
   json_t *jservers = NULL;
   json_t *jerr_msg = NULL;
 
-  if (!(tresp=tid_resp_new(NULL))) {
+  if (!(tresp=tid_resp_new(mem_ctx))) {
     tr_crit("tr_msg_decode_tidresp(): Error allocating TID_RESP structure.");
     return NULL;
   }
 
   /* store required fields from response */
   if ((NULL == (jresult = json_object_get(jresp, "result"))) ||
@@ -1154,12 +1258,13 @@ char *tr_msg_encode(TALLOC_CTX *mem_ctx, TR_MSG *msg)
   TID_REQ *tidreq=NULL;
   TRP_UPD *trpupd=NULL;
   TRP_REQ *trpreq=NULL;
+  MON_REQ *monreq=NULL;
+  MON_RESP *monresp=NULL;
 
   /* TBD -- add error handling */
   jmsg = json_object();
 
-  switch (msg->msg_type) 
-    {
+  switch (msg->msg_type) {
     case TID_REQUEST:
       jmsg_type = json_string("tid_request");
       json_object_set_new(jmsg, "msg_type", jmsg_type);
@@ -1188,10 +1293,24 @@ char *tr_msg_encode(TALLOC_CTX *mem_ctx, TR_MSG *msg)
       json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_req(trpreq));
       break;
 
+    case MON_REQUEST:
+      jmsg_type = json_string("mon_request");
+      json_object_set_new(jmsg, "msg_type", jmsg_type);
+      monreq=tr_msg_get_mon_req(msg);
+      json_object_set_new(jmsg, "msg_body", mon_req_encode(monreq));
+      break;
+
+    case MON_RESPONSE:
+      jmsg_type = json_string("mon_response");
+      json_object_set_new(jmsg, "msg_type", jmsg_type);
+      monresp=tr_msg_get_mon_resp(msg);
+      json_object_set_new(jmsg, "msg_body", mon_resp_encode(monresp));
+      break;
+
     default:
       json_decref(jmsg);
       return NULL;
-    }
+  }
 
   /* We should perhaps use json_set_alloc_funcs to automatically use talloc, but for
    * now, we'll encode to a malloc'ed buffer, then copy that to a talloc'ed buffer. */
@@ -1204,7 +1323,7 @@ char *tr_msg_encode(TALLOC_CTX *mem_ctx, TR_MSG *msg)
   return encoded;
 }
 
-TR_MSG *tr_msg_decode(const char *jbuf, size_t buflen)
+TR_MSG *tr_msg_decode(TALLOC_CTX *mem_ctx, const char *jbuf, size_t buflen)
 {
   TR_MSG *msg=NULL;
   json_t *jmsg = NULL;
@@ -1218,14 +1337,12 @@ TR_MSG *tr_msg_decode(const char *jbuf, size_t buflen)
     return NULL;
   }
 
-  if (!(msg = malloc(sizeof(TR_MSG)))) {
+  if (!(msg = talloc_zero(mem_ctx, TR_MSG))) {
     tr_debug("tr_msg_decode(): Error allocating TR_MSG structure.");
     json_decref(jmsg);
     return NULL;
   }
  
-  memset(msg, 0, sizeof(TR_MSG));
-
   if ((NULL == (jtype = json_object_get(jmsg, "msg_type"))) ||
       (NULL == (jbody = json_object_get(jmsg, "msg_body")))) {
     tr_debug("tr_msg_decode(): Error parsing message header.");
@@ -1238,19 +1355,28 @@ TR_MSG *tr_msg_decode(const char *jbuf, size_t buflen)
 
   if (0 == strcmp(mtype, "tid_request")) {
     msg->msg_type = TID_REQUEST;
-    tr_msg_set_req(msg, tr_msg_decode_tidreq(jbody));
+    tr_msg_set_req(msg, tr_msg_decode_tidreq(msg, jbody));
   }
   else if (0 == strcmp(mtype, "tid_response")) {
     msg->msg_type = TID_RESPONSE;
-    tr_msg_set_resp(msg, tr_msg_decode_tidresp(jbody));
+    tr_msg_set_resp(msg, tr_msg_decode_tidresp(msg, jbody));
   }
   else if (0 == strcmp(mtype, "trp_update")) {
     msg->msg_type = TRP_UPDATE;
-    tr_msg_set_trp_upd(msg, tr_msg_decode_trp_upd(NULL, jbody)); /* null talloc context for now */
+    tr_msg_set_trp_upd(msg, tr_msg_decode_trp_upd(msg, jbody));
   }
   else if (0 == strcmp(mtype, "trp_request")) {
     msg->msg_type = TRP_UPDATE;
-    tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(NULL, jbody)); /* null talloc context for now */
+    tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(msg, jbody));
+  }
+  else if (0 == strcmp(mtype, "mon_request")) {
+    msg->msg_type = MON_REQUEST;
+    tr_msg_set_mon_req(msg, mon_req_decode(msg, jbody));
+  }
+  /* We do not currently handle monitoring responses */
+  else if (0 == strcmp(mtype, "mon_response")) {
+    msg->msg_type = MON_RESPONSE;
+    tr_msg_set_mon_resp(msg, mon_resp_decode(msg, jbody));
   }
   else {
     msg->msg_type = TR_UNKNOWN;
@@ -1265,29 +1391,11 @@ TR_MSG *tr_msg_decode(const char *jbuf, size_t buflen)
 void tr_msg_free_encoded(char *jmsg)
 {
   if (jmsg)
-    free (jmsg);
+    talloc_free(jmsg);
 }
 
 void tr_msg_free_decoded(TR_MSG *msg)
 {
-  if (msg) {
-    if (msg->msg_rep!=NULL) {
-      switch (msg->msg_type) {
-        case TID_REQUEST:
-          tid_req_free(tr_msg_get_req(msg));
-          break;
-        case TID_RESPONSE:
-          tid_resp_free(tr_msg_get_resp(msg));
-          break;
-        case TRP_UPDATE:
-          trp_upd_free(tr_msg_get_trp_upd(msg));
-          break;
-        case TRP_REQUEST:
-          trp_req_free(tr_msg_get_trp_req(msg));
-        default:
-          break;
-      }
-    }
-    free (msg);
-  }
+  if (msg)
+    talloc_free(msg);
 }
diff --git a/include/mon.h b/include/mon.h
new file mode 100644 (file)
index 0000000..33b8f4b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef TRUST_ROUTER_MON_H
+#define TRUST_ROUTER_MON_H
+
+#include <gssapi.h>
+#include <trust_router/tr_name.h>
+
+/* Typedefs */
+typedef struct mon_req MON_REQ;
+typedef struct mon_resp MON_RESP;
+
+typedef enum mon_cmd MON_CMD;
+typedef enum mon_resp_code MON_RESP_CODE;
+
+typedef struct mon_opt MON_OPT;
+typedef enum mon_opt_type MON_OPT_TYPE;
+
+typedef enum mon_rc MON_RC;
+
+typedef struct mons_instance MONS_INSTANCE;
+typedef struct monc_instance MONC_INSTANCE;
+
+typedef struct mons_dispatch_table_entry MONS_DISPATCH_TABLE_ENTRY;
+
+typedef int (MONS_REQ_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
+typedef int (MONS_AUTH_FUNC)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
+typedef int (MONC_RESP_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
+
+#endif //TRUST_ROUTER_MON_H
index 171ce18..8e439d2 100644 (file)
 #include <stdint.h>
 #include <jansson.h>
 #include <gmodule.h>
+#include <gssapi.h>
+#include <trust_router/tid.h>
 #include <trp_internal.h>
 #include <tr_gss_names.h>
+#include <tr_gss_client.h>
 #include <tr_name_internal.h>
-#include <gssapi.h>
+#include <trust_router/tr_dh.h>
+#include <mon.h>
 
 /* Typedefs */
 typedef struct mon_req MON_REQ;
@@ -58,9 +62,11 @@ typedef enum mon_opt_type MON_OPT_TYPE;
 typedef enum mon_rc MON_RC;
 
 typedef struct mons_instance MONS_INSTANCE;
+typedef struct monc_instance MONC_INSTANCE;
 
 typedef int (MONS_REQ_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
 typedef int (MONS_AUTH_FUNC)(gss_name_t client_name, TR_NAME *display_name, void *cookie);
+typedef int (MONC_RESP_FUNC)(MONS_INSTANCE *, MON_REQ *, MON_RESP *, void *);
 
 /* Struct and enum definitions */
 enum mon_rc {
@@ -85,6 +91,7 @@ enum mon_resp_code {
 
 enum mon_opt_type {
   OPT_TYPE_UNKNOWN=0,
+  OPT_TYPE_ANY,
 
   // System information
   OPT_TYPE_SHOW_VERSION,
@@ -110,7 +117,6 @@ struct mon_req {
 };
 
 struct mon_resp {
-  MON_REQ *req; // request this responds to
   MON_RESP_CODE code;
   TR_NAME *message;
   json_t *payload;
@@ -126,6 +132,12 @@ struct mons_instance {
   MONS_REQ_FUNC *req_handler;
   MONS_AUTH_FUNC *auth_handler;
   void *cookie;
+  GPtrArray *handlers;
+};
+
+/* Client instance */
+struct monc_instance {
+  TR_GSSC_INSTANCE *gssc;
 };
 
 /* Prototypes */
@@ -146,23 +158,33 @@ MON_OPT *mon_req_opt_index(MON_REQ *req, size_t index);
 json_t *mon_req_encode(MON_REQ *req);
 
 /* mon_req_decode.c */
-MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_json);
+MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, json_t *req_json);
+MON_REQ *mon_req_parse(TALLOC_CTX *mem_ctx, const char *input);
 
 /* mon_resp.c */
-MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
-                          MON_REQ *req,
-                          MON_RESP_CODE code,
-                          const char *msg,
-                          json_t *payload);
+MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx, MON_RESP_CODE code, const char *msg, json_t *payload);
 void mon_resp_free(MON_RESP *resp);
+int mon_resp_set_message(MON_RESP *resp, const char *new_msg);
+void mon_resp_set_payload(MON_RESP *resp, json_t *new_payload);
 
 /* mon_resp_encode.c */
 json_t *mon_resp_encode(MON_RESP *resp);
 
+/* mon_resp_decode.c */
+MON_RESP * mon_resp_decode(TALLOC_CTX *mem_ctx, json_t *resp_json);
+
 /* mons.c */
 MONS_INSTANCE *mons_new(TALLOC_CTX *mem_ctx);
 int mons_get_listener(MONS_INSTANCE *mons, MONS_REQ_FUNC *req_handler, MONS_AUTH_FUNC *auth_handler, const char *hostname,
                       unsigned int port, void *cookie, int *fd_out, size_t max_fd);
 int mons_accept(MONS_INSTANCE *mons, int listen);
 
+/* monc.c */
+MONC_INSTANCE *monc_new(TALLOC_CTX *mem_ctx);
+void monc_free(MONC_INSTANCE *monc);
+DH *monc_get_dh(MONC_INSTANCE *inst);
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh);
+int monc_open_connection(MONC_INSTANCE *monc, const char *server, unsigned int port);
+MON_RESP *monc_send_request(TALLOC_CTX *mem_ctx, MONC_INSTANCE *monc, MON_REQ *req);
+
 #endif //TRUST_ROUTER_MON_REQ_H
diff --git a/include/mons_handlers.h b/include/mons_handlers.h
new file mode 100644 (file)
index 0000000..50bdd43
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#ifndef TRUST_ROUTER_MONS_HANDLERS_H
+#define TRUST_ROUTER_MONS_HANDLERS_H
+
+typedef json_t *(MONS_HANDLER_FUNC)(void *);
+
+struct mons_dispatch_table_entry {
+  MON_CMD command;
+  MON_OPT_TYPE opt_type;
+  MONS_HANDLER_FUNC *handler;
+  void *cookie;
+};
+
+/* mons_handlers.c */
+MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req);
+MON_RC mons_register_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type, MONS_HANDLER_FUNC *f, void *cookie);
+
+#endif //TRUST_ROUTER_MONS_HANDLERS_H
index c5ecdc8..658b2e4 100644 (file)
@@ -39,6 +39,7 @@
 #include <tr_rp.h>
 #include <trust_router/tid.h>
 #include <jansson.h>
+#include "tr_gss_client.h"
 
 struct tid_srvr_blk {
   TID_SRVR_BLK *next;
@@ -82,11 +83,7 @@ struct tid_req {
 };
 
 struct tidc_instance {
-  // TID_REQ *req_list;
-  // TBD -- Do we still need a separate private key */
-  // char *priv_key;
-  // int priv_len;
-  DH *client_dh;                       /* Client's DH struct with priv and pub keys */
+  TR_GSSC_INSTANCE *gssc;
 };
 
 struct tids_instance {
index 30abc6d..d035a4e 100644 (file)
@@ -38,7 +38,7 @@
 #include <tr_msg.h>
 
 typedef int (TR_GSS_AUTH_FN)(gss_name_t, TR_NAME *, void *);
-typedef char *(TR_GSS_HANDLE_REQ_FN)(TALLOC_CTX *, const char *, void *);
+typedef TR_MSG *(TR_GSS_HANDLE_REQ_FN)(TALLOC_CTX *, TR_MSG *, void *);
 
 void tr_gss_handle_connection(int conn, const char *acceptor_name, const char *acceptor_realm, TR_GSS_AUTH_FN auth_cb,
                               void *auth_cookie, TR_GSS_HANDLE_REQ_FN req_cb, void *req_cookie);
diff --git a/include/tr_gss_client.h b/include/tr_gss_client.h
new file mode 100644 (file)
index 0000000..25024a6
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TRUST_ROUTER_TR_GSS_CLIENT_H
+#define TRUST_ROUTER_TR_GSS_CLIENT_H
+
+#include <gssapi.h>
+#include <trust_router/tr_dh.h>
+#include <tr_msg.h>
+
+typedef struct tr_gssc_instance TR_GSSC_INSTANCE;
+
+/* Client instance */
+struct tr_gssc_instance {
+  const char *service_name;
+  DH *client_dh;
+  gss_ctx_id_t *gss_ctx;
+  int conn;
+};
+
+/* tr_gss_client.c */
+TR_GSSC_INSTANCE *tr_gssc_instance_new(TALLOC_CTX *mem_ctx);
+void tr_gssc_instance_free(TR_GSSC_INSTANCE *tr_gssc);
+int tr_gssc_open_connection(TR_GSSC_INSTANCE *gssc, const char *server, unsigned int port);
+TR_MSG *tr_gssc_exchange_msgs(TALLOC_CTX *mem_ctx, TR_GSSC_INSTANCE *gssc, TR_MSG *req_msg);
+DH * tr_gssc_get_dh(TR_GSSC_INSTANCE *inst);
+DH *tr_gssc_set_dh(TR_GSSC_INSTANCE *inst, DH *dh);
+
+#endif //TRUST_ROUTER_TR_GSS_CLIENT_H
index e956db2..15ab640 100644 (file)
@@ -38,6 +38,7 @@
 #include <tr_event.h>
 #include <tr_config.h>
 #include <mon_internal.h>
+#include <mons_handlers.h>
 
 int tr_mons_event_init(struct event_base *base,
                        MONS_INSTANCE *mons,
index 59b7cf7..6605cbd 100644 (file)
@@ -38,6 +38,8 @@
 #include <jansson.h>
 #include <trust_router/tid.h>
 #include <trust_router/trp.h>
+#include <mon.h>
+
 typedef struct tr_msg TR_MSG;
 
 enum msg_type {
@@ -45,7 +47,9 @@ enum msg_type {
   TID_REQUEST,
   TID_RESPONSE,
   TRP_UPDATE,
-  TRP_REQUEST
+  TRP_REQUEST,
+  MON_REQUEST,
+  MON_RESPONSE
 };
 
 /* Union of TR message types to hold message of any type. */
@@ -65,11 +69,15 @@ TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg);
 void tr_msg_set_trp_upd(TR_MSG *msg, TRP_UPD *req);
 TRP_REQ *tr_msg_get_trp_req(TR_MSG *msg);
 void tr_msg_set_trp_req(TR_MSG *msg, TRP_REQ *req);
+MON_REQ *tr_msg_get_mon_req(TR_MSG *msg);
+void tr_msg_set_mon_req(TR_MSG *msg, MON_REQ *req);
+MON_RESP *tr_msg_get_mon_resp(TR_MSG *msg);
+void tr_msg_set_mon_resp(TR_MSG *msg, MON_RESP *resp);
 
 
 /* Encoders/Decoders */
 char *tr_msg_encode(TALLOC_CTX *mem_ctx, TR_MSG *msg);
-TR_MSG *tr_msg_decode(const char *jmsg, size_t len);
+TR_MSG *tr_msg_decode(TALLOC_CTX *mem_ctx, const char *jmsg, size_t len);
 void tr_msg_free_encoded(char *jmsg);
 void tr_msg_free_decoded(TR_MSG *msg);
 
index 91a9816..69a6377 100644 (file)
@@ -137,9 +137,9 @@ TR_EXPORT const TID_PATH *tid_srvr_get_path(const TID_SRVR_BLK *);
 TR_EXPORT int tid_srvr_get_key_expiration(const TID_SRVR_BLK *, struct timeval *tv_out);
 
 #define tid_resp_servers_foreach(RESP, SERVER, INDEX) \
-  for (INDEX=0,SERVER=NULL;                                            \
-       ((INDEX < tid_resp_get_num_servers(RESP))&&(SERVER = tid_resp_get_server(resp, INDEX))); \
-       INDEX++)
+  for ((INDEX)=0,(SERVER)=NULL;                                                \
+       (((INDEX) < tid_resp_get_num_servers(RESP))&&((SERVER) = tid_resp_get_server(resp, (INDEX)))); \
+       (INDEX)++)
 
 
 /* TID Client functions, in tid/tidc.c */
index d0317f7..440a277 100644 (file)
@@ -81,6 +81,7 @@ const char *mon_opt_type_to_string(MON_OPT_TYPE opt_type)
 {
   switch(opt_type) {
     case OPT_TYPE_UNKNOWN:
+    case OPT_TYPE_ANY:
       return NULL;
 
     case OPT_TYPE_SHOW_VERSION:
index dd9de4d..bffa92e 100644 (file)
@@ -112,3 +112,4 @@ MON_OPT *mon_req_opt_index(MON_REQ *req, size_t index)
   MON_OPT *result = &g_array_index(req->options, MON_OPT, index);
   return result;
 }
+
index c1eeed1..0c7e7f4 100644 (file)
@@ -104,15 +104,15 @@ static MON_RC mon_options_decode(json_t *opts_json, MON_REQ *req)
 }
 
 /**
- * Parse JSON for a request
+ * Parse a JSON string into a request
  */
-static json_t *mon_req_parse(const char *input)
+MON_REQ *mon_req_parse(TALLOC_CTX *mem_ctx, const char *input)
 {
   json_t *parsed_json = NULL;
   json_error_t json_error;
 
   parsed_json = json_loads(input, JSON_REJECT_DUPLICATES, &json_error);
-  return parsed_json;
+  return mon_req_decode(mem_ctx, parsed_json);
 }
 
 /**
@@ -132,17 +132,14 @@ static json_t *mon_req_parse(const char *input)
  * @param req_json reference to JSON request object
  * @return decoded request struct or NULL on failure
  */
-MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, const char *req_str)
+MON_REQ *mon_req_decode(TALLOC_CTX *mem_ctx, json_t *req_json)
 {
   TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   MON_REQ *req = NULL;
-  json_t *req_json = NULL;
   json_t *jval = NULL;
   json_t *opts_json = NULL;
   MON_CMD cmd = MON_CMD_UNKNOWN;
 
-  req_json = mon_req_parse(req_str); // TODO: Check errors
-
   if (! json_is_object(req_json))
     goto cleanup;
 
index e1f0761..f0729ad 100644 (file)
@@ -65,11 +65,7 @@ static int mon_resp_destructor(void *object)
  * Makes its own copy of the message, so caller can dispose of
  * that after allocating the response.
  *
- * Steals the reference to the payload JSON object. Does not modify the
- * object. Caller should not modify it after allocating the response or
- * undefined behavior will result. If allocation fails, the stolen reference
- * will be released --- if you need to keep a reference, use incref before
- * calling this.
+ * Increments the reference count of the payload if it is not null.
  *
  * @param mem_ctx talloc context for allocation
  * @param req MON_REQ this response corresponds to
@@ -78,18 +74,17 @@ static int mon_resp_destructor(void *object)
  * @param payload JSON object to be send as payload, or null for no payload
  * @return response allocated in the requested talloc context, null on failure
  */
-MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
-                          MON_REQ *req,
-                          MON_RESP_CODE code,
-                          const char *msg,
-                          json_t *payload)
+MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx, MON_RESP_CODE code, const char *msg, json_t *payload)
 {
   MON_RESP *resp = talloc(mem_ctx, MON_RESP);
   if (resp) {
-    resp->req = req;
     resp->code = code;
     resp->message = tr_new_name(msg);
+
     resp->payload = payload;
+    if (resp->payload)
+      json_incref(resp->payload);
+
     talloc_set_destructor((void *)resp, mon_resp_destructor);
     if (resp->message == NULL) {
       talloc_free(resp); // destructor will be called
@@ -100,6 +95,45 @@ MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
 }
 
 /**
+ * Set or replace the response message
+ *
+ * Does not change the message if it fails
+ *
+ * @param resp
+ * @param new_msg
+ * @return 1 on success, 0 on error
+ */
+int mon_resp_set_message(MON_RESP *resp, const char *new_msg)
+{
+  TR_NAME *n = tr_new_name(new_msg);
+
+  if (n == NULL)
+    return 0; /* failed */
+
+  if (resp->message)
+    tr_free_name(resp->message);
+  resp->message = n;
+  return 1; /* succeeded */
+}
+
+/**
+ * Set or replace the payload
+ *
+ * Manages JSON reference counts
+ *
+ * @param resp
+ * @param new_payload
+ */
+void mon_resp_set_payload(MON_RESP *resp, json_t *new_payload)
+{
+  if (resp->payload)
+    json_decref(resp->payload);
+  resp->payload = new_payload;
+  if (resp->payload)
+    json_incref(new_payload);
+}
+
+/**
  * Free a monitoring response
  *
  * @param resp request to free, must not be null
diff --git a/mon/mon_resp_decode.c b/mon/mon_resp_decode.c
new file mode 100644 (file)
index 0000000..83b0ac3
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <talloc.h>
+#include <jansson.h>
+
+#include <mon_internal.h>
+
+// Monitoring response decoder
+
+/**
+ * Decode a JSON response
+ *
+ * Expected format:
+ * {
+ *   "code": 0,
+ *   "message": "success",
+ *   "payload": {
+ *     "serial": 12345,
+ *     ...
+ *   }
+ * }
+ *
+ * Caller must free the return value with MON_REQ_free().
+ *
+ * @param mem_ctx talloc context for the returned struct
+ * @param resp_json reference to JSON request object
+ * @return decoded request struct or NULL on failure
+ */
+MON_RESP *mon_resp_decode(TALLOC_CTX *mem_ctx, json_t *resp_json)
+{
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+  MON_RESP *resp = NULL;
+  json_t *jcode = NULL;
+  json_t *jmessage = NULL;
+  json_t *jpayload = NULL;
+
+  if (! json_is_object(resp_json))
+    goto cleanup;
+
+  /* Get the response code, which is an integer */
+  jcode = json_object_get(resp_json, "code");
+  if (! json_is_integer(jcode))
+    goto cleanup;
+
+  /* Get the response message, which is a string */
+  jmessage = json_object_get(resp_json, "message");
+  if (! json_is_string(jmessage))
+    goto cleanup;
+
+  /* Get the payload if we have one */
+  jpayload = json_object_get(resp_json, "payload");
+
+  /* Get a response in the tmp_ctx context. The payload may be null. */
+  resp = mon_resp_new(tmp_ctx,
+                      (MON_RESP_CODE) json_integer_value(jcode),
+                      json_string_value(jmessage),
+                      jpayload);
+  if (resp == NULL)
+    goto cleanup;
+
+  /* Success! Put the request in the caller's talloc context */
+  talloc_steal(mem_ctx, resp);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  if (resp_json)
+    json_decref(resp_json);
+
+  return resp;
+}
index 2a6e5fe..23c3dd8 100644 (file)
@@ -66,7 +66,6 @@ json_t *mon_resp_encode(MON_RESP *resp)
 {
   json_t *resp_json = NULL;
   json_t *jval = NULL;
-  const char *cmd_str = NULL;
 
   /* Get a JSON object */
   resp_json = json_object();
@@ -79,8 +78,7 @@ json_t *mon_resp_encode(MON_RESP *resp)
 
   /* If we have a payload, add it */
   if (resp->payload) {
-    cmd_str = mon_cmd_to_string(resp->req->command); // key for the response payload
-    object_set_or_free_and_return(resp_json, jval, cmd_str, resp->payload);
+    object_set_or_free_and_return(resp_json, jval, "payload", resp->payload);
   }
 
   return resp_json;
diff --git a/mon/monc.c b/mon/monc.c
new file mode 100644 (file)
index 0000000..426b447
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012, 2014-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <jansson.h>
+#include <talloc.h>
+
+#include <trust_router/tr_dh.h>
+#include <mon_internal.h>
+#include <tr_msg.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+
+
+MONC_INSTANCE *monc_new(TALLOC_CTX *mem_ctx)
+{
+  MONC_INSTANCE *monc=talloc(mem_ctx, MONC_INSTANCE);
+  if (monc!=NULL) {
+    monc->gssc = tr_gssc_instance_new(monc);
+    if (monc->gssc == NULL) {
+      talloc_free(monc);
+      return NULL;
+    }
+
+    monc->gssc->service_name = "trustmonitor";
+  }
+  return monc;
+}
+
+void monc_free(MONC_INSTANCE *monc)
+{
+  talloc_free(monc);
+}
+
+int monc_open_connection(MONC_INSTANCE *monc,
+                         const char *server,
+                         unsigned int port)
+{
+  return tr_gssc_open_connection(monc->gssc, server, port);
+}
+
+MON_RESP *monc_send_request(TALLOC_CTX *mem_ctx, MONC_INSTANCE *monc, MON_REQ *req)
+{
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+  TR_MSG *msg = NULL;
+  TR_MSG *resp_msg = NULL;
+  MON_RESP *resp = NULL;
+
+  /* Create and populate a msg structure */
+  if (!(msg = talloc_zero(tmp_ctx, TR_MSG)))
+    goto cleanup;
+
+  msg->msg_type = MON_REQUEST;
+  tr_msg_set_mon_req(msg, req);
+
+  resp_msg = tr_gssc_exchange_msgs(tmp_ctx, monc->gssc, msg);
+  if (resp_msg == NULL)
+    goto cleanup;
+
+  resp = tr_msg_get_mon_resp(resp_msg);
+
+  /* if we got a response, steal it from resp_msg's context so we can return it */
+  if (resp)
+    talloc_steal(mem_ctx, resp);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return resp;
+}
+
+DH *monc_get_dh(MONC_INSTANCE *inst)
+{
+  return tr_gssc_get_dh(inst->gssc);
+}
+
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh)
+{
+  return tr_gssc_set_dh(inst->gssc, dh);
+}
index d79cbcb..4d638d6 100644 (file)
 #include <sys/wait.h>
 #include <tr_gss.h>
 
+#include "mons_handlers.h"
+
+static int mons_destructor(void *object)
+{
+  MONS_INSTANCE *mons = talloc_get_type_abort(object, MONS_INSTANCE);
+  if (mons->handlers) {
+    g_ptr_array_unref(mons->handlers);
+  }
+  return 0;
+}
+
 /**
  * Allocate a new MONS_INSTANCE
  *
@@ -62,10 +73,20 @@ MONS_INSTANCE *mons_new(TALLOC_CTX *mem_ctx)
     mons->req_handler = NULL;
     mons->auth_handler = NULL;
     mons->cookie = NULL;
+
+    /* Before any steps that may fail, install the destructor */
+    talloc_set_destructor((void *)mons, mons_destructor);
+
     mons->authorized_gss_names = tr_gss_names_new(mons);
     if (mons->authorized_gss_names == NULL) {
       talloc_free(mons);
-      mons = NULL;
+      return NULL;
+    }
+
+    mons->handlers = g_ptr_array_new();
+    if (mons->handlers == NULL) {
+      talloc_free(mons);
+      return NULL;
     }
   }
   return mons;
@@ -78,9 +99,53 @@ MONS_INSTANCE *mons_new(TALLOC_CTX *mem_ctx)
  * @param data pointer to a MONS_INSTANCE
  * @return pointer to the response string or null to send no response
  */
-static char *mons_req_cb(TALLOC_CTX *mem_ctx, const char *req_str, void *data)
+static TR_MSG *mons_req_cb(TALLOC_CTX *mem_ctx, TR_MSG *req_msg, void *data)
 {
-  return "This is a response.";
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+  MONS_INSTANCE *mons = talloc_get_type_abort(data, MONS_INSTANCE);
+  MON_REQ *req = NULL;
+  MON_RESP *resp = NULL;
+  TR_MSG *resp_msg = NULL; /* This is the response value */
+
+  /* Validate inputs */
+  if (req_msg == NULL)
+    goto cleanup;
+
+  req = tr_msg_get_mon_req(req_msg);
+  if (req == NULL) {
+    /* this is an internal error */
+    tr_err("mons_req_cb: Received incorrect message type (was %d, expected %d)",
+           tr_msg_get_msg_type(req_msg),
+           MON_REQUEST);
+    /* TODO send an error response */
+    goto cleanup;
+  }
+
+  /* Allocate a response message */
+  resp_msg = talloc(tmp_ctx, TR_MSG);
+  if (resp_msg == NULL) {
+    /* can't return a message, just emit an error */
+    tr_crit("mons_req_cb: Error allocating response message.");
+    goto cleanup;
+  }
+
+  /* Handle the request */
+  resp = mons_handle_request(resp_msg, mons, req);
+  if (resp == NULL) {
+    /* error processing the request */
+    /* TODO send back an error */
+    goto cleanup;
+  }
+
+  /* Set the response message payload */
+  tr_msg_set_mon_resp(resp_msg, resp);
+
+  /* Put the response message in the caller's context so it does not get freed when we exit */
+  talloc_steal(mem_ctx, resp_msg);
+
+cleanup:
+  talloc_free(tmp_ctx);
+  return resp_msg;
 }
 
 /**
diff --git a/mon/mons_handlers.c b/mon/mons_handlers.c
new file mode 100644 (file)
index 0000000..b546b89
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Handlers for monitoring requests */
+
+#include <gmodule.h>
+
+#include <tr_debug.h>
+#include <mon_internal.h>
+#include <mons_handlers.h>
+
+
+/* Static Prototypes */
+static int dispatch_entry_matches(MONS_DISPATCH_TABLE_ENTRY *e, MON_CMD command, MON_OPT_TYPE opt_type);
+static MONS_HANDLER_FUNC *mons_find_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type);
+static void request_helper(void *element, void *data);
+
+struct request_helper_data {
+  MON_CMD command;
+  MON_OPT_TYPE opt_type;
+  json_t *payload;
+};
+
+/**
+ * Call the appropriate handler for a request
+ *
+ * TODO: report errors from handlers
+ *
+ * @return a MON_RESP structure or null if there was a processing error
+ */
+MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req)
+{
+  MON_RESP *resp = NULL;
+  json_t *payload = NULL;
+  struct request_helper_data cookie;
+  size_t ii = 0;
+
+  tr_debug("mons_handle_request: Handling a request");
+
+  /* Start off by allocating our response with a generic error message */
+  resp = mon_resp_new(mem_ctx,
+                      MON_RESP_ERROR,
+                      "Error processing show request",
+                      NULL);
+  if (resp == NULL) {
+    /* we can't respond, just return */
+    tr_crit("mons_handle_request: Error allocating response structure.");
+    goto cleanup;
+  }
+
+  /* Now get a JSON object for our return payload */
+  payload = json_object();
+  if (payload == NULL) {
+    tr_crit("mons_handle_request: Error allocating response payload.");
+    goto cleanup; /* This will return the generic error message set earlier */
+  }
+
+  /* Now call handlers */
+  cookie.command = req->command;
+  cookie.payload = payload; /* borrowed reference */
+
+  if (mon_req_opt_count(req) == 0) {
+    /* call every handler that matches the command */
+    cookie.opt_type = OPT_TYPE_ANY;
+    g_ptr_array_foreach(mons->handlers, request_helper, &cookie);
+  } else {
+    /* call only those handlers that match an option */
+    for (ii=0; ii < mon_req_opt_count(req); ii++) {
+      cookie.opt_type = mon_req_opt_index(req, ii)->type;
+      /* Loop over all handlers - we know we can only have one match for each opt type */
+      g_ptr_array_foreach(mons->handlers, request_helper, &cookie);
+    }
+  }
+
+  /* If we get here, then we successfully processed the request. Return a successful reply. */
+  if (mon_resp_set_message(resp, "success") == 0) {
+    /* Failed to set the response message to success - fail ironically */
+    tr_crit("mons_handle_request: Error setting response message to 'success'.");
+    goto cleanup;
+  }
+
+  /* Attach the accumulated payload to the response */
+  if (json_object_size(payload) > 0)
+    mon_resp_set_payload(resp, payload);
+
+  resp->code = MON_RESP_SUCCESS; /* at last... */
+  tr_debug("mons_handle_request: Successfully processed request.");
+
+cleanup:
+  if (payload)
+    json_decref(payload);
+  return resp;
+}
+
+/**
+ * Register a handler for a command/option combination
+ *
+ * @param mons
+ * @param cmd
+ * @param opt_type
+ * @param f
+ * @param cookie
+ * @return
+ */
+MON_RC mons_register_handler(MONS_INSTANCE *mons,
+                             MON_CMD cmd,
+                             MON_OPT_TYPE opt_type,
+                             MONS_HANDLER_FUNC *f,
+                             void *cookie)
+{
+  MONS_DISPATCH_TABLE_ENTRY *entry = NULL;
+
+  if (mons_find_handler(mons, cmd, opt_type) != NULL) {
+    return MON_ERROR;
+  }
+
+  /* Put these in the mons talloc context so we don't have to muck about with
+   * a free function for the GPtrArray */
+  entry = talloc(mons, MONS_DISPATCH_TABLE_ENTRY);
+  if (entry == NULL) {
+    return MON_NOMEM;
+  }
+  entry->command = cmd;
+  entry->opt_type = opt_type;
+  entry->handler = f;
+  entry->cookie = cookie;
+
+  g_ptr_array_add(mons->handlers, entry);
+  return MON_SUCCESS;
+}
+
+/**
+ * Two table entries match if none of the commands or opt_types are unknown,
+ * if the commands match, and if the opt types either match or at least one is
+ * OPT_TYPE_ANY.
+ *
+ * No comparison of the handler pointer is included.
+ *
+ * @return 1 if the two match, 0 if not
+ */
+static int dispatch_entry_matches(MONS_DISPATCH_TABLE_ENTRY *e,
+                                  MON_CMD command,
+                                  MON_OPT_TYPE opt_type)
+{
+  if ((command == MON_CMD_UNKNOWN) || (opt_type == OPT_TYPE_UNKNOWN))
+    return 0; /* request is invalid */
+
+  if ((e->command == MON_CMD_UNKNOWN) || (e->opt_type == OPT_TYPE_UNKNOWN))
+    return 0; /* e1 is invalid */
+
+  if (e->command != command)
+    return 0; /* commands do not match */
+
+  if (e->opt_type == opt_type)
+    return 1; /* exact match */
+
+  if ( (e->opt_type == OPT_TYPE_ANY) || (opt_type == OPT_TYPE_ANY) )
+    return 1; /* one is a wildcard */
+
+  return 0; /* commands matched but opt_types did not */
+}
+
+static MONS_HANDLER_FUNC *mons_find_handler(MONS_INSTANCE *mons, MON_CMD cmd, MON_OPT_TYPE opt_type)
+{
+  guint index;
+
+  for (index=0; index < mons->handlers->len; index++) {
+    if (dispatch_entry_matches(g_ptr_array_index(mons->handlers, index), cmd, opt_type))
+      return g_ptr_array_index(mons->handlers, index);
+  }
+  return NULL;
+}
+
+/**
+ * This calls every request handler that matches a command/opt_type,
+ * gathering their results.
+ *
+ * @param element
+ * @param data
+ */
+static void request_helper(void *element, void *data)
+{
+  MONS_DISPATCH_TABLE_ENTRY *entry = talloc_get_type_abort(element, MONS_DISPATCH_TABLE_ENTRY);
+  struct request_helper_data *helper_data = data;
+
+  if (dispatch_entry_matches(entry, helper_data->command, helper_data->opt_type)) {
+    json_object_set(helper_data->payload,
+                    mon_opt_type_to_string(entry->opt_type),
+                    entry->handler(entry->cookie));
+  }
+}
+
index 63570b9..5391857 100644 (file)
@@ -110,7 +110,7 @@ static int run_test(const char *filename, MON_REQ *(generator)())
   req_json_str = read_file(filename);
   assert(req_json_str);
 
-  req = mon_req_decode(NULL, req_json_str);
+  req = mon_req_parse(NULL, req_json_str);
   assert(req);
   assert(equal(req, expected));
 
index b4ecdfe..081ed2d 100644 (file)
@@ -21,7 +21,7 @@ static char *reconfigure(MON_RESP_CODE code, const char *message)
   req = mon_req_new(NULL, MON_CMD_RECONFIGURE);
   assert(req);
 
-  resp = mon_resp_new(NULL, req, code, message, NULL);
+  resp = mon_resp_new(NULL, code, message, NULL);
   assert(resp);
 
   resp_json = mon_resp_encode(resp);
@@ -76,7 +76,7 @@ static char *show_success()
                                mon_opt_type_to_string(OPT_TYPE_SHOW_TID_REQ_COUNT),
                                json_integer(1432)));
 
-  resp = mon_resp_new(NULL, req, MON_RESP_SUCCESS, "success", payload);
+  resp = mon_resp_new(NULL, MON_RESP_SUCCESS, "success", payload);
   assert(resp);
 
   resp_json = mon_resp_encode(resp);
index 26fb994..02cd1db 100644 (file)
@@ -210,7 +210,8 @@ int main (int argc,
  
   /* Create a TID client instance & the client DH */
   tidc = tidc_create();
-  if (NULL == (tidc->client_dh = tr_create_dh_params(NULL, 0))) {
+  tidc_set_dh(tidc, tr_create_dh_params(NULL, 0));
+  if (tidc_get_dh(tidc) == NULL) {
     printf("Error creating client DH params.\n");
     return 1;
   }
index 648107a..94cd98d 100644 (file)
 #include <jansson.h>
 #include <talloc.h>
 
+#include <gsscon.h>
 #include <trust_router/tr_dh.h>
 #include <tid_internal.h>
 #include <tr_msg.h>
-#include <gsscon.h>
 #include <tr_debug.h>
 
 
 int tmp_len = 32;
 
-static int tidc_destructor(void *obj)
-{
-  TIDC_INSTANCE *tidc=talloc_get_type_abort(obj, TIDC_INSTANCE);
-  if (NULL!=tidc) {
-    if (NULL!=tidc->client_dh)
-      tr_destroy_dh_params(tidc->client_dh);
-  }
-  return 0;
-}
-
 /* creates struct in talloc null context */
 TIDC_INSTANCE *tidc_create(void)
 {
   TIDC_INSTANCE *tidc=talloc(NULL, TIDC_INSTANCE);
   if (tidc!=NULL) {
-    tidc->client_dh=NULL;
-    talloc_set_destructor((void *)tidc, tidc_destructor);
+    tidc->gssc = tr_gssc_instance_new(tidc);
+    if (tidc->gssc == NULL) {
+      talloc_free(tidc);
+      return NULL;
+    }
+
+    tidc->gssc->service_name = "trustidentity";
   }
   return tidc;
 }
@@ -72,43 +67,55 @@ void tidc_destroy(TIDC_INSTANCE *tidc)
 }
 
 int tidc_open_connection (TIDC_INSTANCE *tidc, 
-                         const char *server,
-                         unsigned int port,
-                         gss_ctx_id_t *gssctx)
+                          const char *server,
+                          unsigned int port,
+                          gss_ctx_id_t *gssctx)
 {
-  int err = 0;
-  int conn = -1;
   unsigned int use_port = 0;
+  tidc->gssc->gss_ctx = gssctx;
 
   if (0 == port)
     use_port = TID_PORT;
   else
     use_port = port;
 
-  tr_debug("tidc_open_connection: opening tidc connection to %s:%d", server, port);
-  err = gsscon_connect(server, use_port, "trustidentity", &conn, gssctx);
-
-  if (!err)
-    return conn;
+  tr_debug("tidc_open_connection: opening tidc connection to %s:%d", server, use_port);
+  if (0 == tr_gssc_open_connection(tidc->gssc, server, use_port))
+    return tidc->gssc->conn;
   else
     return -1;
 }
 
 int tidc_send_request (TIDC_INSTANCE *tidc,
-                      int conn,
-                      gss_ctx_id_t gssctx,
-                      const char *rp_realm,
-                      const char *realm, 
-                      const char *comm,
-                      TIDC_RESP_FUNC *resp_handler,
-                      void *cookie)
+                       int conn,
+                       gss_ctx_id_t gssctx,
+                       const char *rp_realm,
+                       const char *realm,
+                       const char *comm,
+                       TIDC_RESP_FUNC *resp_handler,
+                       void *cookie)
 {
   TID_REQ *tid_req = NULL;
   int rc;
+  int orig_conn = 0;
+  gss_ctx_id_t *orig_gss_ctx = NULL;
+
+  /* For ABI compatibility, replace the generic GSS client parameters
+   * with the arguments we were passed. */
+  orig_conn = tidc->gssc->conn; /* save to restore later */
+  if (conn != tidc->gssc->conn) {
+    tr_warning("tidc_send_request: WARNING: socket connection FD does not match FD opened by tidc_open_connection()");
+    tidc->gssc->conn = conn;
+  }
+  orig_gss_ctx = tidc->gssc->gss_ctx; /* save to restore later */
+  if (gssctx != *(tidc->gssc->gss_ctx)) {
+    tr_warning("tidc_send_request: WARNING: sending request with different GSS context than used for tidc_open_connection()");
+    *tidc->gssc->gss_ctx = gssctx;
+  }
 
   /* Create and populate a TID req structure */
   if (!(tid_req = tid_req_new()))
-    return -1;
+    goto error;
 
   tid_req->conn = conn;
   tid_req->gssctx = gssctx;
@@ -120,75 +127,45 @@ int tidc_send_request (TIDC_INSTANCE *tidc,
     goto error;
   }
 
-  tid_req->tidc_dh = tr_dh_dup(tidc->client_dh);
+  tid_req->tidc_dh = tr_dh_dup(tidc->gssc->client_dh);
 
   rc = tidc_fwd_request(tidc, tid_req, resp_handler, cookie);
   goto cleanup;
  error:
   rc = -1;
  cleanup:
-  tid_req_free(tid_req);
+  if (tid_req)
+    tid_req_free(tid_req);
+
+  tidc->gssc->conn = orig_conn;
+  tidc->gssc->gss_ctx = orig_gss_ctx;
   return rc;
 }
 
 int tidc_fwd_request(TIDC_INSTANCE *tidc,
                      TID_REQ *tid_req,
-                    TIDC_RESP_FUNC *resp_handler,
+                     TIDC_RESP_FUNC *resp_handler,
                      void *cookie)
 {
-  char *req_buf = NULL;
-  char *resp_buf = NULL;
-  size_t resp_buflen = 0;
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   TR_MSG *msg = NULL;
   TR_MSG *resp_msg = NULL;
-  int err;
   int rc = 0;
 
   /* Create and populate a TID msg structure */
-  if (!(msg = talloc_zero(tid_req, TR_MSG)))
+  if (!(msg = talloc_zero(tmp_ctx, TR_MSG)))
     goto error;
 
   msg->msg_type = TID_REQUEST;
   tr_msg_set_req(msg, tid_req);
 
-  /* store the response function and cookie */
-  // tid_req->resp_func = resp_handler;
-  // tid_req->cookie = cookie;
 
-
-  /* Encode the request into a json string */
-  if (!(req_buf = tr_msg_encode(NULL, msg))) {
-    tr_err("tidc_fwd_request: Error encoding TID request.\n");
-    goto error;
-  }
-
-  tr_debug( "tidc_fwd_request: Sending TID request:\n");
-  tr_debug( "%s\n", req_buf);
+  tr_debug( "tidc_fwd_request: Sending TID request\n");
 
   /* Send the request over the connection */
-  if (err = gsscon_write_encrypted_token (tid_req->conn, tid_req->gssctx, req_buf,
-                                         strlen(req_buf))) {
-    tr_err( "tidc_fwd_request: Error sending request over connection.\n");
+  resp_msg = tr_gssc_exchange_msgs(tmp_ctx, tidc->gssc, msg);
+  if (resp_msg == NULL)
     goto error;
-  }
-
-  /* TBD -- queue request on instance, read resps in separate thread */
-
-  /* Read the response from the connection */
-  /* TBD -- timeout? */
-  if (err = gsscon_read_encrypted_token(tid_req->conn, tid_req->gssctx, &resp_buf, &resp_buflen)) {
-    if (resp_buf)
-      free(resp_buf);
-    goto error;
-  }
-
-  tr_debug( "tidc_fwd_request: Response Received (%u bytes).\n", (unsigned) resp_buflen);
-  tr_debug( "%s\n", resp_buf);
-
-  if (NULL == (resp_msg = tr_msg_decode(resp_buf, resp_buflen))) {
-    tr_err( "tidc_fwd_request: Error decoding response.\n");
-    goto error;
-  }
 
   /* TBD -- Check if this is actually a valid response */
   if (TID_RESPONSE != tr_msg_get_msg_type(resp_msg)) {
@@ -207,25 +184,17 @@ int tidc_fwd_request(TIDC_INSTANCE *tidc,
  error:
   rc = -1;
  cleanup:
-  if (msg)
-    talloc_free(msg);
-  if (req_buf)
-    free(req_buf);
-  if (resp_buf)
-    free(resp_buf);
-  if (resp_msg)
-    tr_msg_free_decoded(resp_msg);
+  talloc_free(tmp_ctx);
   return rc;
 }
 
 
 DH * tidc_get_dh(TIDC_INSTANCE *inst)
 {
-  return inst->client_dh;
+  return tr_gssc_get_dh(inst->gssc);
 }
 
 DH *tidc_set_dh(TIDC_INSTANCE *inst, DH *dh)
 {
-  inst->client_dh = dh;
-  return dh;
+  return tr_gssc_set_dh(inst->gssc, dh);
 }
index 4abc6ca..2e5dbea 100644 (file)
@@ -255,41 +255,45 @@ int tids_send_response (TIDS_INSTANCE *tids, TID_REQ *req, TID_RESP *resp)
  * @param data pointer to a TIDS_INSTANCE
  * @return pointer to the response string or null to send no response
  */
-static char *tids_req_cb(TALLOC_CTX *mem_ctx, const char *req_str, void *data)
+static TR_MSG *tids_req_cb(TALLOC_CTX *mem_ctx, TR_MSG *mreq, void *data)
 {
+  TALLOC_CTX *tmp_ctx = talloc_new(NULL);
   TIDS_INSTANCE *tids = talloc_get_type_abort(data, TIDS_INSTANCE);
-  TR_MSG *mreq = NULL;
   TID_REQ *req = NULL;
   TID_RESP *resp = NULL;
-  char *resp_str = NULL;
+  TR_MSG *resp_msg = NULL; /* this is the return value */
   int rc = 0;
 
-  mreq = tr_msg_decode(req_str, strlen(req_str)); // allocates memory on success!
-  if (mreq == NULL) {
-    tr_debug("tids_req_cb: Error decoding request.");
-    return NULL;
-  }
-
   /* If this isn't a TID Request, just drop it. */
   if (mreq->msg_type != TID_REQUEST) {
-    tr_msg_free_decoded(mreq);
     tr_debug("tids_req_cb: Not a TID request, dropped.");
-    return NULL;
+    goto cleanup;
   }
 
   /* Get a handle on the request itself. Don't free req - it belongs to mreq */
   req = tr_msg_get_req(mreq);
 
-  /* Allocate a response structure and populate common fields. The resp is in req's talloc context,
-   * which will be cleaned up when mreq is freed. */
-  resp = tids_create_response(req, req);
+  /* Allocate a response message */
+  resp_msg = talloc(tmp_ctx, TR_MSG);
+  if (resp_msg == NULL) {
+    /* We cannot create a response message, so all we can really do is emit
+     * an error message and return. */
+    tr_crit("tids_req_cb: Error allocating response message.");
+    goto cleanup;
+  }
+
+  /* Allocate a response structure and populate common fields. Put it in the
+   * response message's talloc context. */
+  resp = tids_create_response(resp_msg, req);
   if (resp == NULL) {
     /* If we were unable to create a response, we cannot reply. Log an
      * error if we can, then drop the request. */
-    tr_msg_free_decoded(mreq);
     tr_crit("tids_req_cb: Error creating response structure.");
-    return NULL;
+    resp_msg = NULL; /* the contents are in tmp_ctx, so they will still be cleaned up */
+    goto cleanup;
   }
+  /* Now officially assign the response to the message. */
+  tr_msg_set_resp(resp_msg, resp);
 
   /* Handle the request and fill in resp */
   rc = tids_handle_request(tids, req, resp);
@@ -298,12 +302,12 @@ static char *tids_req_cb(TALLOC_CTX *mem_ctx, const char *req_str, void *data)
     /* Fall through, to send the response, either way */
   }
 
-  /* Convert the completed response into an encoded response */
-  resp_str = tids_encode_response(mem_ctx, resp);
+  /* put the response message in the caller's context */
+  talloc_steal(mem_ctx, resp_msg);
 
-  /* Finished; free the request and return */
-  tr_msg_free_decoded(mreq); // this frees req and resp, too
-  return resp_str;
+cleanup:
+  talloc_free(tmp_ctx);
+  return resp_msg;
 }
 
 TIDS_INSTANCE *tids_new(TALLOC_CTX *mem_ctx)
index 8c8202d..1968bde 100644 (file)
@@ -38,6 +38,7 @@
 #include <event2/event.h>
 #include <talloc.h>
 #include <signal.h>
+#include <time.h>
 
 #include <tid_internal.h>
 #include <mon_internal.h>
@@ -150,6 +151,18 @@ static void configure_signals(void)
   pthread_sigmask(SIG_BLOCK, &signals, NULL);
 }
 
+/* TODO move this function */
+static json_t *tr_mon_handle_version(void *cookie)
+{
+  return json_string(PACKAGE_VERSION);
+}
+
+static json_t *tr_mon_handle_uptime(void *cookie)
+{
+  time_t *start_time = cookie;
+  return json_integer(time(NULL) - (*start_time));
+}
+
 int main(int argc, char *argv[])
 {
   TALLOC_CTX *main_ctx=NULL;
@@ -161,6 +174,8 @@ int main(int argc, char *argv[])
   struct tr_socket_event mon_ev = {0};
   struct event *cfgwatch_ev;
 
+  time_t start_time = time(NULL); /* TODO move this? */
+
   configure_signals();
 
   /* we're going to be multithreaded, so disable null context tracking */
@@ -219,6 +234,10 @@ int main(int argc, char *argv[])
   tr->mons->tids = tr->tids;
   tr->mons->trps = tr->trps;
 
+  /* TODO do this more systematically */
+  mons_register_handler(tr->mons, MON_CMD_SHOW, OPT_TYPE_SHOW_VERSION, tr_mon_handle_version, NULL);
+  mons_register_handler(tr->mons, MON_CMD_SHOW, OPT_TYPE_SHOW_UPTIME, tr_mon_handle_uptime, &start_time);
+
   /***** process configuration *****/
   tr->cfgwatch=tr_cfgwatch_create(tr);
   if (tr->cfgwatch == NULL) {
diff --git a/tr/trmon_main.c b/tr/trmon_main.c
new file mode 100644 (file)
index 0000000..909f78b
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2012-2018, JANET(UK)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of JANET(UK) nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <talloc.h>
+#include <argp.h>
+#include <unistd.h>
+
+#include <mon_internal.h>
+#include <gsscon.h>
+#include <tr_debug.h>
+#include <trust_router/tr_dh.h>
+
+
+/* command-line option setup */
+
+/* argp global parameters */
+const char *argp_program_bug_address=PACKAGE_BUGREPORT; /* bug reporting address */
+
+/* doc strings */
+static const char doc[]=PACKAGE_NAME " - TR Monitoring Client";
+static const char arg_doc[]="<message> <server> [<port>]"; /* string describing arguments, if any */
+
+/* define the options here. Fields are:
+ * { long-name, short-name, variable name, options, help description } */
+static const struct argp_option cmdline_options[] = {
+  { "repeat", 'r', "N", OPTION_ARG_OPTIONAL, "Repeat message until terminated, or N times." },
+  {NULL}
+};
+
+/* structure for communicating with option parser */
+struct cmdline_args {
+  char *msg;
+  char *server;
+  unsigned int port; /* optional */
+  int repeat; /* how many times to repeat, or -1 for infinite */
+};
+
+/* parser for individual options - fills in a struct cmdline_args */
+static error_t parse_option(int key, char *arg, struct argp_state *state)
+{
+  long tmp_l = 0;
+
+  /* get a shorthand to the command line argument structure, part of state */
+  struct cmdline_args *arguments=state->input;
+
+  switch (key) {
+    case 'r':
+      if (arg==NULL)
+        arguments->repeat=-1;
+      else
+        tmp_l = strtol(arg, NULL, 10);
+      if ((errno == 0) && (tmp_l > 0) && (tmp_l < INT_MAX))
+        arguments->repeat = (int) tmp_l;
+      else
+        argp_usage(state);
+      break;
+
+    case ARGP_KEY_ARG: /* handle argument (not option) */
+      switch (state->arg_num) {
+        case 0:
+          arguments->msg=arg;
+          break;
+
+        case 1:
+          arguments->server=arg;
+          break;
+
+        case 2:
+          tmp_l = strtol(arg, NULL, 10);
+          if (errno || (tmp_l < 0) || (tmp_l > 65535)) /* max valid port */
+            argp_usage(state);
+
+          arguments->port=(unsigned int) tmp_l;
+          break;
+
+        default:
+          /* too many arguments */
+          argp_usage(state);
+      }
+      break;
+
+    case ARGP_KEY_END: /* no more arguments */
+      if (state->arg_num < 2) {
+        /* not enough arguments encountered */
+        argp_usage(state);
+      }
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+  }
+
+  return 0; /* success */
+}
+
+
+/* assemble the argp parser */
+static struct argp argp = {cmdline_options, parse_option, arg_doc, doc};
+
+int main(int argc, char *argv[])
+{
+  TALLOC_CTX *main_ctx=talloc_new(NULL);
+  MONC_INSTANCE *monc = NULL;
+  MON_REQ *req = NULL;
+  MON_RESP *resp = NULL;
+
+  struct cmdline_args opts;
+  int retval=1; /* exit with an error status unless this gets set to zero */
+
+  /* parse the command line*/
+  /* set defaults */
+  opts.msg=NULL;
+  opts.server=NULL;
+  opts.port=TRP_PORT;
+  opts.repeat=1;
+
+  argp_parse(&argp, argc, argv, 0, 0, &opts);
+
+  /* Use standalone logging */
+  tr_log_open();
+
+  /* set logging levels */
+  talloc_set_log_stderr();
+  tr_log_threshold(LOG_CRIT);
+  tr_console_threshold(LOG_DEBUG);
+
+  printf("TR Monitor:\nServer = %s, port = %i\n", opts.server, opts.port);
+
+  /* Create a MON client instance & the client DH */
+  monc = monc_new(main_ctx);
+  if (monc == NULL) {
+    printf("Error allocating client instance.\n");
+    goto cleanup;
+  }
+
+
+  /* fill in the DH parameters */
+  monc_set_dh(monc, tr_create_dh_params(NULL, 0));
+  if (monc_get_dh(monc) == NULL) {
+    printf("Error creating client DH params.\n");
+    goto cleanup;
+  }
+
+  /* Set-up MON connection */
+  if (0 != monc_open_connection(monc, opts.server, opts.port)) {
+    /* Handle error */
+    printf("Error opening connection to %s:%d.\n", opts.server, opts.port);
+    goto cleanup;
+  };
+
+  req = mon_req_new(main_ctx, MON_CMD_SHOW);
+
+  /* Send a MON request and get the response */
+  resp = monc_send_request(main_ctx, monc, req);
+
+  if (resp == NULL) {
+    /* Handle error */
+    printf("Error executing monitoring request.\n");
+    goto cleanup;
+  }
+
+  /* success */
+  retval = 0;
+
+  /* Clean-up the MON client instance, and exit */
+cleanup:
+  talloc_free(main_ctx);
+  return retval;
+}
+
index 512e92e..7a6a585 100644 (file)
@@ -81,7 +81,7 @@ int main(int argc, const char *argv[])
   if (buflen>=MAX_MSG_LEN)
     printf("Warning: file may exceed maximum message length (%d bytes).\n", MAX_MSG_LEN);
 
-  msg=tr_msg_decode(buf, buflen);
+  msg= tr_msg_decode(NULL, buf, buflen);
 
 /*  if (rc==TRP_SUCCESS)
     trp_msg_print(msg);*/
index 11c6ddf..193faaa 100644 (file)
@@ -336,7 +336,7 @@ static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MS
   tr_debug("trps_read_message: message received, %u bytes.", (unsigned) buflen);
   tr_debug("trps_read_message: %.*s", buflen, buf);
 
-  *msg=tr_msg_decode(buf, buflen);
+  *msg= tr_msg_decode(NULL, buf, buflen);
   free(buf);
   if (*msg==NULL)
     return TRP_NOPARSE;