# Does not actually build!
add_executable(trust_router ${SOURCE_FILES})
+add_executable(trmon mon/monc.c tr/trmon_main.c)
+
# 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)
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
mon_srcs = \
mon/mons.c \
+ mon/monc.c \
mon/mon_common.c \
mon/mon_req.c \
mon/mon_req_encode.c \
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 \
+$(tid_srcs) \
+$(trp_srcs) \
+$(mon_srcs) \
+$(common_srcs)
+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 \
#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>
msg->msg_type = TID_RESPONSE;
}
+MON_REQ *tr_msg_get_mon_req(TR_MSG *msg)
+{
+ if (msg->msg_type == MON_REQUEST)
+ return (MON_REQ *)msg->msg_rep;
+ return NULL;
+}
+
+void tr_msg_set_mon_req(TR_MSG *msg, MON_REQ *req)
+{
+ msg->msg_rep = req;
+ msg->msg_type = MON_REQUEST;
+}
+
+MON_RESP *tr_msg_get_mon_resp(TR_MSG *msg)
+{
+ if (msg->msg_type == MON_RESPONSE)
+ return (MON_RESP *)msg->msg_rep;
+ return NULL;
+}
+
+void tr_msg_set_mon_resp(TR_MSG *msg, MON_RESP *resp)
+{
+ msg->msg_rep = resp;
+ msg->msg_type = MON_RESPONSE;
+}
+
TRP_UPD *tr_msg_get_trp_upd(TR_MSG *msg)
{
if (msg->msg_type == TRP_UPDATE)
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();
json_object_set_new(jmsg, "msg_body", tr_msg_encode_tidresp(tidresp));
break;
- case TRP_UPDATE:
- jmsg_type = json_string("trp_update");
- json_object_set_new(jmsg, "msg_type", jmsg_type);
- trpupd=tr_msg_get_trp_upd(msg);
- json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_upd(trpupd));
- break;
-
- case TRP_REQUEST:
- jmsg_type = json_string("trp_request");
- json_object_set_new(jmsg, "msg_type", jmsg_type);
- trpreq=tr_msg_get_trp_req(msg);
- json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_req(trpreq));
- break;
-
- default:
+ case TRP_UPDATE:
+ jmsg_type = json_string("trp_update");
+ json_object_set_new(jmsg, "msg_type", jmsg_type);
+ trpupd=tr_msg_get_trp_upd(msg);
+ json_object_set_new(jmsg, "msg_body", tr_msg_encode_trp_upd(trpupd));
+ break;
+
+ case TRP_REQUEST:
+ jmsg_type = json_string("trp_request");
+ json_object_set_new(jmsg, "msg_type", jmsg_type);
+ trpreq=tr_msg_get_trp_req(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;
}
msg->msg_type = TRP_UPDATE;
tr_msg_set_trp_req(msg, tr_msg_decode_trp_req(NULL, jbody)); /* null talloc context for now */
}
+ else if (0 == strcmp(mtype, "mon_request")) {
+ msg->msg_type = MON_REQUEST;
+ tr_msg_set_mon_req(msg, mon_req_decode(NULL, 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(NULL, jbody));
+// }
else {
msg->msg_type = TR_UNKNOWN;
msg->msg_rep = NULL;
trp_req_free(tr_msg_get_trp_req(msg));
default:
break;
+ case MON_REQUEST:
+ mon_req_free(tr_msg_get_mon_req(msg));
+ break;
+ case MON_RESPONSE:
+ mon_resp_free(tr_msg_get_mon_resp(msg));
+ break;
}
}
free (msg);
#include <stdint.h>
#include <jansson.h>
#include <gmodule.h>
-#include <trp_internal.h>
+//#include <trp_internal.h>
#include <tr_gss_names.h>
#include <tr_name_internal.h>
#include <gssapi.h>
+#include <trust_router/tr_dh.h>
/* Typedefs */
typedef struct mon_req MON_REQ;
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 {
const char *hostname;
unsigned int port;
TR_GSS_NAMES *authorized_gss_names;
- TIDS_INSTANCE *tids;
- TRPS_INSTANCE *trps;
+ void *tids; // TODO sort out header file cycles and use typed pointers
+ void *trps; // TODO sort out header file cycles and use typed pointers
MONS_REQ_FUNC *req_handler;
MONS_AUTH_FUNC *auth_handler;
void *cookie;
};
+/* Monitoring client instance */
+struct monc_instance {
+ DH *client_dh;
+};
+
/* Prototypes */
/* tr_mon.c */
const char *mon_cmd_to_string(MON_CMD cmd);
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_resp.c */
MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx,
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_create(void);
+void monc_destroy(MONC_INSTANCE *monc);
+int monc_open_connection (MONC_INSTANCE *monc, const char *server, unsigned int port, gss_ctx_id_t *gssctx);
+int monc_send_request (MONC_INSTANCE *monc, int conn, gss_ctx_id_t gssctx, MONC_RESP_FUNC *resp_handler,
+ void *cookie);
+int monc_fwd_request(MONC_INSTANCE *monc, int conn, gss_ctx_id_t gssctx, MON_REQ *mon_req,
+ MONC_RESP_FUNC *resp_handler, void *cookie);
+DH * monc_get_dh(MONC_INSTANCE *inst);
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh);
+
#endif //TRUST_ROUTER_MON_REQ_H
#include <jansson.h>
#include <trust_router/tid.h>
#include <trust_router/trp.h>
+#include <mon_internal.h>
+
typedef struct tr_msg TR_MSG;
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. */
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 */
/**
* Parse JSON for a request
*/
-static json_t *mon_req_parse(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;
-}
+//static json_t *mon_req_parse(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;
+//}
/**
* Decode a JSON request
* @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) //const char *req_str)
{
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
+ //req_json = mon_req_parse(req_str); // TODO: Check errors
if (! json_is_object(req_json))
goto cleanup;
--- /dev/null
+/*
+ * 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>
+
+
+static int monc_destructor(void *obj)
+{
+ MONC_INSTANCE *monc=talloc_get_type_abort(obj, MONC_INSTANCE);
+ if (NULL!=monc) {
+ if (NULL!=monc->client_dh)
+ tr_destroy_dh_params(monc->client_dh);
+ }
+ return 0;
+}
+
+/* creates struct in talloc null context */
+MONC_INSTANCE *monc_create(void)
+{
+ MONC_INSTANCE *monc=talloc(NULL, MONC_INSTANCE);
+ if (monc!=NULL) {
+ monc->client_dh=NULL;
+ talloc_set_destructor((void *)monc, monc_destructor);
+ }
+ return monc;
+}
+
+void monc_destroy(MONC_INSTANCE *monc)
+{
+ talloc_free(monc);
+}
+
+int monc_open_connection (MONC_INSTANCE *monc,
+ const char *server,
+ unsigned int port,
+ gss_ctx_id_t *gssctx)
+{
+ int err = 0;
+ int conn = -1;
+
+ tr_debug("monc_open_connection: opening monc connection to %s:%d", server, port);
+ err = gsscon_connect(server, port, "trustmonitor", &conn, gssctx);
+
+ if (!err)
+ return conn;
+ else
+ return -1;
+}
+
+int monc_send_request (MONC_INSTANCE *monc,
+ int conn,
+ gss_ctx_id_t gssctx,
+ MONC_RESP_FUNC *resp_handler,
+ void *cookie)
+{
+ MON_REQ *mon_req = NULL;
+ int rc;
+
+ /* Create and populate a MON req structure */
+ if (!(mon_req = mon_req_new(NULL, MON_CMD_SHOW))) // TODO accept command as a parameter
+ goto error;
+
+ rc = monc_fwd_request(monc, conn, gssctx, mon_req, resp_handler, cookie);
+ goto cleanup;
+error:
+ rc = -1;
+cleanup:
+ mon_req_free(mon_req);
+ return rc;
+}
+
+int monc_fwd_request(MONC_INSTANCE *monc,
+ int conn,
+ gss_ctx_id_t gssctx,
+ MON_REQ *mon_req,
+ MONC_RESP_FUNC *resp_handler,
+ void *cookie)
+{
+ char *req_buf = NULL;
+ char *resp_buf = NULL;
+ size_t resp_buflen = 0;
+ TR_MSG *msg = NULL;
+ TR_MSG *resp_msg = NULL;
+ int err;
+ int rc = 0;
+
+ /* Create and populate a MON msg structure */
+ if (!(msg = talloc_zero(mon_req, TR_MSG)))
+ goto error;
+
+ msg->msg_type = MON_REQUEST;
+ tr_msg_set_mon_req(msg, mon_req);
+
+ /* store the response function and cookie */
+ // mon_req->resp_func = resp_handler;
+ // mon_req->cookie = cookie;
+
+
+ /* Encode the request into a json string */
+ if (!(req_buf = tr_msg_encode(NULL, msg))) {
+ tr_err("monc_fwd_request: Error encoding MON request.\n");
+ goto error;
+ }
+
+ tr_debug( "monc_fwd_request: Sending MON request:\n");
+ tr_debug( "%s\n", req_buf);
+
+ /* Send the request over the connection */
+ err = gsscon_write_encrypted_token (conn, gssctx, req_buf, strlen(req_buf));
+ if (err) {
+ tr_err( "monc_fwd_request: Error sending request over connection.\n");
+ 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(conn, gssctx, &resp_buf, &resp_buflen)) {
+ if (resp_buf)
+ free(resp_buf);
+ goto error;
+ }
+
+ tr_debug( "monc_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( "monc_fwd_request: Error decoding response.\n");
+// goto error;
+// }
+//
+// /* TBD -- Check if this is actually a valid response */
+// if (MON_RESPONSE != tr_msg_get_msg_type(resp_msg)) {
+// tr_err( "monc_fwd_request: Error, no response in the response!\n");
+// goto error;
+// }
+//
+// if (resp_handler) {
+// /* Call the caller's response function. It must copy any data it needs before returning. */
+// tr_debug("monc_fwd_request: calling response callback function.");
+// (*resp_handler)(monc, mon_req, tr_msg_get_resp(resp_msg), cookie);
+// }
+
+ goto cleanup;
+
+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);
+ return rc;
+}
+
+
+DH * monc_get_dh(MONC_INSTANCE *inst)
+{
+ return inst->client_dh;
+}
+
+DH *monc_set_dh(MONC_INSTANCE *inst, DH *dh)
+{
+ inst->client_dh = dh;
+ return dh;
+}
--- /dev/null
+/*
+ * 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;
+ 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)
+{
+ /* 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
+ arguments->repeat=strtol(arg, NULL, 10);
+ 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:
+ arguments->port=strtol(arg, NULL, 10); /* optional */
+ 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;
+ struct cmdline_args opts;
+ int rc;
+ int conn;
+ gss_ctx_id_t gssctx;
+
+ /* 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_create();
+ if (NULL == (monc->client_dh = tr_create_dh_params(main_ctx, 0))) {
+ printf("Error creating client DH params.\n");
+ return 1;
+ }
+
+ /* Set-up MON connection */
+ if (-1 == (conn = monc_open_connection(monc, opts.server, opts.port, &gssctx))) {
+ /* Handle error */
+ printf("Error in monc_open_connection.\n");
+ return 1;
+ };
+
+ /* Send a MON request */
+ if (0 > (rc = monc_send_request(monc, conn, gssctx, NULL, NULL))) {
+ /* Handle error */
+ printf("Error in monc_send_request, rc = %d.\n", rc);
+ return 1;
+ }
+
+ /* Clean-up the MON client instance, and exit */
+ monc_destroy(monc);
+ talloc_free(main_ctx);
+ return 0;
+}
+