aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/cli/hicnc.c
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/hicn/cli/hicnc.c')
-rw-r--r--hicn-light/src/hicn/cli/hicnc.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/hicn-light/src/hicn/cli/hicnc.c b/hicn-light/src/hicn/cli/hicnc.c
new file mode 100644
index 000000000..ed8d4ed97
--- /dev/null
+++ b/hicn-light/src/hicn/cli/hicnc.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2021 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h> // LONG_MAX, LONG_MIN
+#include <signal.h>
+#include <hicn/ctrl.h>
+
+#ifndef _WIN32
+#include <getopt.h>
+#endif
+
+#include "color.h"
+#include <hicn/ctrl/parse.h>
+#include <hicn/ctrl/hicn-light.h>
+#include <hicn/util/log.h>
+#include <hicn/util/sstrncpy.h>
+
+#define PORT 9695
+
+/*
+ * Duplicated from hicn_light_ng_api.c while is only available as a module in
+ * libhicnctrl
+ */
+const char *command_type_str[] = {
+#define _(l, u) [COMMAND_TYPE_##u] = STRINGIZE(u),
+ foreach_command_type
+#undef _
+};
+
+static struct option longFormOptions[] = {{"help", no_argument, 0, 'h'},
+ {"server", required_argument, 0, 'S'},
+ {"port", required_argument, 0, 'P'},
+ {0, 0, 0, 0}};
+
+static void usage(char *prog) {
+ printf("%s: portable hICN forwarder\n", prog);
+ printf("\n");
+ printf("Usage: %s COMMAND [PARAMETERS]\n", prog);
+ printf("\n");
+ printf(" %s -h This help screen.\n", prog);
+ printf(" %s help Obtain a list of available commands.\n", prog);
+ printf("\n");
+}
+
+static bool stop = false;
+void signal_handler(int sig) {
+ fprintf(stderr, "Received ^C... quitting !\n");
+ stop = true;
+}
+
+int main(int argc, char *const *argv) {
+ log_conf.log_level = LOG_INFO;
+
+ // Handle termination signal
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = signal_handler;
+ sigaction(SIGINT, &sa, NULL);
+
+ /* Parse commandline */
+ char *server_ip = NULL;
+ uint16_t server_port = 0;
+
+ for (;;) {
+ // getopt_long stores the option index here.
+ int optind = 0;
+
+ int c = getopt_long(argc, argv, "dhS:P:", longFormOptions, &optind);
+ if (c == -1) break;
+
+ switch (c) {
+ case 'd':
+ log_conf.log_level = LOG_DEBUG;
+ break;
+ case 'S':
+ server_ip = optarg;
+ break;
+
+ case 'P': {
+ char *endptr;
+ long val = strtol(optarg, &endptr, 10);
+
+ errno = 0; /* To distinguish success/failure after call */
+
+ if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) ||
+ (errno != 0 && val == 0)) {
+ perror("strtol");
+ exit(EXIT_FAILURE);
+ }
+
+ if (endptr == optarg) {
+ fprintf(stderr, "No digits were found.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (*endptr != '\0') {
+ fprintf(stderr, "Spurious characters after number: %s.\n", endptr);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((val < 1) || (val > 65535)) {
+ fprintf(stderr, "Invalid port number: %ld.\n", val);
+ exit(EXIT_FAILURE);
+ }
+
+ server_port = val;
+ break;
+ }
+
+ case 'h':
+ usage(argv[0]);
+ exit(EXIT_SUCCESS);
+
+ default:
+ fprintf(stderr, "Invalid argument.\n");
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* Parse */
+ char *param = argv[optind];
+ for (; optind < argc - 1; optind++) {
+ char *arg = argv[optind];
+ arg[strlen(arg)] = ' ';
+ }
+
+ if (!param) {
+ usage(argv[0]);
+ goto ERR_PARAM;
+ }
+
+ if (strncmp(param, "help", 4) == 0) {
+ if (help(param) < 0) {
+ usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ hc_command_t command = {};
+ if (parse(param, &command) < 0) {
+ fprintf(stderr, "Error parsing command : '%s'\n", param);
+ goto ERR_PARSE;
+ }
+
+ hc_sock_t *s;
+ if (server_ip) {
+ if (server_port == 0) server_port = PORT;
+#define BUFSIZE 255
+ char url[BUFSIZE];
+ snprintf(url, BUFSIZE, "tcp://%s:%d/", server_ip, server_port);
+ s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, url);
+ } else {
+ s = hc_sock_create(FORWARDER_TYPE_HICNLIGHT, NULL);
+ }
+ if (!s) {
+ fprintf(stderr, "Could not create socket.\n");
+ goto ERR_SOCKET;
+ }
+
+ if (hc_sock_connect(s) < 0) {
+ fprintf(stderr, "Could not establish connection to forwarder.\n");
+ goto ERR_CONNECT;
+ }
+
+ if (!IS_VALID_OBJECT_TYPE(command.object_type) ||
+ !IS_VALID_ACTION(command.action)) {
+ fprintf(stderr, "Unsupported command");
+ goto ERR_PARAM;
+ }
+
+ int rc = UNSUPPORTED_CMD_ERROR;
+ hc_data_t *data = NULL;
+
+ rc = hc_execute(s, command.action, command.object_type, &command.object,
+ &data);
+
+ if (rc < 0) {
+ switch (rc) {
+ case INPUT_ERROR:
+ ERROR("Wrong input parameters");
+ break;
+ case UNSUPPORTED_CMD_ERROR:
+ ERROR("Unsupported command");
+ break;
+ default:
+ ERROR("Error executing command");
+ break;
+ }
+ goto ERR_COMMAND;
+ }
+
+ if (!data) goto ERR_QUERY;
+ if (!hc_data_get_result(data)) goto ERR_DATA;
+
+ if (command.action == ACTION_LIST) {
+ char buf[MAXSZ_HC_OBJECT];
+ hc_data_foreach(data, obj, {
+ rc = hc_object_snprintf(buf, MAXSZ_HC_OBJECT, command.object_type, obj);
+ if (rc < 0)
+ WARN("Display error");
+ else if (rc >= MAXSZ_HC_OBJECT)
+ WARN("Output truncated");
+ else
+ printf("%s\n", buf);
+ });
+ }
+
+ hc_data_free(data);
+ hc_sock_free(s);
+ return EXIT_SUCCESS;
+
+ERR_DATA:
+ hc_data_free(data);
+ERR_QUERY:
+ERR_COMMAND:
+ERR_CONNECT:
+ hc_sock_free(s);
+ERR_SOCKET:
+ERR_PARSE:
+ERR_PARAM:
+ ERROR("Error");
+ return EXIT_FAILURE;
+}