From 3d175240ef0a8e0b465994e881ef98548a39091a Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Tue, 17 Apr 2018 14:15:53 -0400 Subject: [PATCH] First functional monitoring server - can return the trust router version --- CMakeLists.txt | 2 +- Makefile.am | 3 +- include/mon_internal.h | 2 + mon/mon_resp.c | 39 +++++++++++ mon/mons_handlers.c | 16 ++--- mon/mons_handlers.h | 4 ++ mon/mons_handlers_show.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 226 insertions(+), 11 deletions(-) create mode 100644 mon/mons_handlers_show.c diff --git a/CMakeLists.txt b/CMakeLists.txt index abc00c6..c970f02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ 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 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 mon/mons_handlers.h) + 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 mon/mons_handlers.h mon/mons_handlers_show.c) # Does not actually build! add_executable(trust_router ${SOURCE_FILES}) diff --git a/Makefile.am b/Makefile.am index c73c623..2df06b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,7 +53,8 @@ mon_srcs = \ # monitoring server sources mons_srcs = \ mon/mons.c \ - mon/mons_handlers.c + mon/mons_handlers.c \ + mon/mons_handlers_show.c check_PROGRAMS = common/t_constraint TESTS = common/t_constraint diff --git a/include/mon_internal.h b/include/mon_internal.h index 27fc00e..d2d1572 100644 --- a/include/mon_internal.h +++ b/include/mon_internal.h @@ -162,6 +162,8 @@ 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_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); diff --git a/mon/mon_resp.c b/mon/mon_resp.c index ee59069..f0729ad 100644 --- a/mon/mon_resp.c +++ b/mon/mon_resp.c @@ -95,6 +95,45 @@ MON_RESP *mon_resp_new(TALLOC_CTX *mem_ctx, MON_RESP_CODE code, const char *msg, } /** + * 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/mons_handlers.c b/mon/mons_handlers.c index 5bee3e5..68abd48 100644 --- a/mon/mons_handlers.c +++ b/mon/mons_handlers.c @@ -34,14 +34,13 @@ /* Handlers for monitoring requests */ +#include #include - #include "mons_handlers.h" typedef MON_RESP *(MONS_HANDLER_FUNC)(TALLOC_CTX *, MONS_INSTANCE *, MON_REQ *); /* Prototypes for the dispatch table */ -static MON_RESP *mons_handle_show(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req); static MON_RESP *mons_handle_reconfigure(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req); @@ -65,25 +64,24 @@ MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ { struct dispatch_table_entry *entry = dispatch_table; + tr_debug("mons_handle_request: Handling a request"); + /* Find the handler */ while ((entry->command != req->command) && (entry->command != MON_CMD_UNKNOWN)) { entry++; } /* See if we found a handler */ - if (entry->command == MON_CMD_UNKNOWN) + if (entry->command == MON_CMD_UNKNOWN) { + tr_info("mons_handle_request: Unknown or unsupported monitoring request received"); return NULL; + } /* Call the handler */ + tr_debug("mons_handle_request: Calling handler for %s command", mon_cmd_to_string(entry->command)); return entry->handler(mem_ctx, mons, req); } -static MON_RESP *mons_handle_show(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req) -{ - MON_RESP *resp = mon_resp_new(mem_ctx, MON_RESP_SUCCESS, "success", NULL); - return resp; -} - static MON_RESP *mons_handle_reconfigure(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req) { return NULL; diff --git a/mon/mons_handlers.h b/mon/mons_handlers.h index 2f13ff9..03e2847 100644 --- a/mon/mons_handlers.h +++ b/mon/mons_handlers.h @@ -36,6 +36,10 @@ #ifndef TRUST_ROUTER_MONS_HANDLERS_H #define TRUST_ROUTER_MONS_HANDLERS_H +/* mons_handlers.c */ MON_RESP *mons_handle_request(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req); +/* mons_handlers_show.c */ +MON_RESP *mons_handle_show(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req); + #endif //TRUST_ROUTER_MONS_HANDLERS_H diff --git a/mon/mons_handlers_show.c b/mon/mons_handlers_show.c new file mode 100644 index 0000000..e4d4d22 --- /dev/null +++ b/mon/mons_handlers_show.c @@ -0,0 +1,171 @@ +/* + * 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 "show" requests */ + +#include +#include + +#include +#include +#include "mons_handlers.h" + +typedef json_t *(MONS_SHOW_FUNC)(MONS_INSTANCE *mons); + +/* prototypes for the dispatch table */ +static json_t *handle_show_version(MONS_INSTANCE *mons); + +struct dispatch_table_entry { + MON_OPT_TYPE opt_type; + MONS_SHOW_FUNC *handler; +}; + +struct dispatch_table_entry dispatch_table[] = { + {OPT_TYPE_SHOW_VERSION, handle_show_version}, + {OPT_TYPE_SHOW_SERIAL, NULL}, + {OPT_TYPE_SHOW_UPTIME, NULL}, + {OPT_TYPE_SHOW_TID_REQ_COUNT, NULL}, + {OPT_TYPE_SHOW_TID_REQ_PENDING, NULL}, + {OPT_TYPE_SHOW_ROUTES, NULL}, + {OPT_TYPE_SHOW_COMMUNITIES, NULL}, + {OPT_TYPE_UNKNOWN} /* must be the last entry */ +}; + +/** + * Should we include this opt_type in our response to this request? + * + * Returns 1 if the opt_type is in the options list, or if the options list + * is empty. + * + * @param opt_type + * @param req + * @return 1 if the opt_type should be included, else 0 + */ +static int opt_requested(MON_OPT_TYPE opt_type, MON_REQ *req) +{ + size_t ii; + + /* empty options list is a wildcard - return everything */ + if (mon_req_opt_count(req) == 0) + return 1; + + /* check whether this opt_type is in the list */ + for (ii=0; iitype) + return 1; + } + return 0; +} + +MON_RESP *mons_handle_show(TALLOC_CTX *mem_ctx, MONS_INSTANCE *mons, MON_REQ *req) +{ + struct dispatch_table_entry *entry = NULL; + MON_RESP *resp = NULL; + json_t *payload = NULL; /* entire payload */ + json_t *payload_item = NULL; /* payload for a single option */ + + tr_debug("mons_handle_show: 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_show: 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_show: Error allocating response payload."); + goto cleanup; /* This will return the generic error message set earlier */ + } + + tr_debug("mons_handle_show: Processing options"); + + /* Now step through the dispatch table. Call each requested option type. */ + for (entry = dispatch_table; entry->opt_type != OPT_TYPE_UNKNOWN; entry++) { + if (! opt_requested(entry->opt_type, req)) { + tr_debug("mons_handle_show: Not including %s in response", + mon_opt_type_to_string(entry->opt_type)); + } else { + /* This option is needed. Add its response to our payload. */ + if (entry->handler == NULL) { + tr_debug("mons_handle_show: Would include %s in response, but its handler is null", + mon_opt_type_to_string(entry->opt_type)); + continue; + } + + tr_debug("mons_handle_show: Including %s in response", + mon_opt_type_to_string(entry->opt_type)); + + payload_item = entry->handler(mons); + if (payload_item == NULL) { + tr_err("mons_handle_show: Error processing option %s", mon_opt_type_to_string(entry->opt_type)); + goto cleanup; + } + /* this steals the reference to payload_item */ + json_object_set_new(payload, + mon_opt_type_to_string(entry->opt_type), + payload_item); + } + } + + /* 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_show: 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... */ + +cleanup: + if (payload) + json_decref(payload); + return resp; +} + + +static json_t *handle_show_version(MONS_INSTANCE *mons) +{ + return json_string(PACKAGE_VERSION); +} \ No newline at end of file -- 2.1.4