/* * Copyright (c) 2020 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 #include #include #include #include #include /* VPP API client includes */ #include #include #include "vat2.h" uword *function_by_name; bool debug = false; char *vat2_plugin_path; static void vat2_find_plugin_path () { char *p, path[PATH_MAX]; int rv; u8 *s; /* find executable path */ if ((rv = readlink ("/proc/self/exe", path, PATH_MAX - 1)) == -1) return; /* readlink doesn't provide null termination */ path[rv] = 0; /* strip filename */ if ((p = strrchr (path, '/')) == 0) return; *p = 0; /* strip bin/ */ if ((p = strrchr (path, '/')) == 0) return; *p = 0; s = format (0, "%s/lib/" CLIB_TARGET_TRIPLET "/vat2_plugins:" "%s/lib/vat2_plugins", path, path); vec_add1 (s, 0); vat2_plugin_path = (char *) s; } void vac_callback (unsigned char *data, int len) { u16 result_msg_id = ntohs(*((u16 *)data)); DBG("Received something async: %d\n", result_msg_id); } int vat2_load_plugins (char *path, char *filter, int *loaded); static int register_function (void) { int loaded; vat2_find_plugin_path(); DBG("Plugin Path %s\n", vat2_plugin_path); int rv = vat2_load_plugins(vat2_plugin_path, 0, &loaded); DBG("Loaded %u plugins\n", loaded); return rv; } void vat2_register_function(char *name, cJSON (*f)(cJSON *)) { hash_set_mem(function_by_name, name, f); } int main (int argc, char **argv) { /* Create a heap of 64MB */ clib_mem_init (0, 64 << 20); char *filename = 0; int index; int c; opterr = 0; cJSON *o = 0; uword *p = 0; while ((c = getopt (argc, argv, "df:")) != -1) { switch (c) { case 'd': debug = true; break; case 'f': filename = optarg; break; case '?': if (optopt == 'f') fprintf (stderr, "Option -%c requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: abort (); } } DBG("debug = %d, filename = %s\n", debug, filename); for (index = optind; index < argc; index++) DBG ("Non-option argument %s\n", argv[index]); index = optind; /* Load plugins */ function_by_name = hash_create_string (0, sizeof (uword)); int res = register_function(); if (res < 0) { fprintf(stderr, "%s: loading plugins failed\n", argv[0]); exit(-1); } if (argc > index + 2) { fprintf(stderr, "%s: Too many arguments\n", argv[0]); exit(-1); } /* Read JSON from stdin, command line or file */ if (argc >= (index + 1)) { p = hash_get_mem (function_by_name, argv[index]); if (p == 0) { fprintf(stderr, "%s: Unknown command: %s\n", argv[0], argv[index]); exit(-1); } } if (argc == (index + 2)) { o = cJSON_Parse(argv[index+1]); if (!o) { fprintf(stderr, "%s: Failed parsing JSON input: %s\n", argv[0], cJSON_GetErrorPtr()); exit(-1); } } if (filename) { if (argc > index + 1) { fprintf(stderr, "%s: Superfluous arguments when filename given\n", argv[0]); exit(-1); } FILE *f = fopen(filename, "r"); size_t bufsize = 1024; size_t n_read = 0; size_t n; if (!f) { fprintf(stderr, "%s: can't open file: %s\n", argv[0], filename); exit(-1); } char *buf = malloc(bufsize); while ((n = fread(buf, 1, bufsize, f))) { n_read += n; if (n == bufsize) buf = realloc(buf, bufsize); } fclose(f); if (n_read) { o = cJSON_Parse(buf); free(buf); if (!o) { fprintf(stderr, "%s: Failed parsing JSON input: %s\n", argv[0], cJSON_GetErrorPtr()); exit(-1); } } } if (!o) { fprintf(stderr, "%s: Failed parsing JSON input\n", argv[0]); exit(-1); } if (vac_connect("vat2", 0, 0, 1024)) { fprintf(stderr, "Failed connecting to VPP\n"); exit(-1); } if (!p) { fprintf(stderr, "No such command\n"); exit(-1); } cJSON * (*fp) (cJSON *); fp = (void *) p[0]; cJSON *r = (*fp) (o); if (o) cJSON_Delete(o); if (r) { char *output = cJSON_Print(r); cJSON_Delete(r); printf("%s\n", output); free(output); } else { fprintf(stderr, "Call failed\n"); exit(-1); } vac_disconnect(); exit (0); }