]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/ferr.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / lib / ferr.c
index 6625749c3f44cb4d74becede455834933b1a45d4..e18597afb07c0a92537c26909516b1b4faa47983 100644 (file)
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <pthread.h>
 #include <signal.h>
+#include <inttypes.h>
 
 #include "ferr.h"
 #include "vty.h"
@@ -26,6 +31,8 @@
 #include "memory.h"
 #include "hash.h"
 #include "command.h"
+#include "json.h"
+#include "linklist.h"
 
 DEFINE_MTYPE_STATIC(LIB, ERRINFO, "error information")
 
@@ -57,22 +64,22 @@ static void err_key_fini(void)
 pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER;
 struct hash *refs;
 
-static int ferr_hash_cmp(const void *a, const void *b)
+static bool ferr_hash_cmp(const void *a, const void *b)
 {
-       const struct ferr_ref *f_a = a;
-       const struct ferr_ref *f_b = b;
+       const struct log_ref *f_a = a;
+       const struct log_ref *f_b = b;
 
        return f_a->code == f_b->code;
 }
 
 static inline unsigned int ferr_hash_key(void *a)
 {
-       struct ferr_ref *f = a;
+       struct log_ref *f = a;
 
        return f->code;
 }
 
-void ferr_ref_add(struct ferr_ref *ref)
+void log_ref_add(struct log_ref *ref)
 {
        uint32_t i = 0;
 
@@ -86,10 +93,10 @@ void ferr_ref_add(struct ferr_ref *ref)
        pthread_mutex_unlock(&refs_mtx);
 }
 
-struct ferr_ref *ferr_ref_get(uint32_t code)
+struct log_ref *log_ref_get(uint32_t code)
 {
-       struct ferr_ref holder;
-       struct ferr_ref *ref;
+       struct log_ref holder;
+       struct log_ref *ref;
 
        holder.code = code;
        pthread_mutex_lock(&refs_mtx);
@@ -101,35 +108,88 @@ struct ferr_ref *ferr_ref_get(uint32_t code)
        return ref;
 }
 
-void ferr_ref_display(struct vty *vty, uint32_t code)
+void log_ref_display(struct vty *vty, uint32_t code, bool json)
 {
-       struct ferr_ref *ref = ferr_ref_get(code);
+       struct log_ref *ref;
+       struct json_object *top = NULL, *obj = NULL;
+       struct list *errlist;
+       struct listnode *ln;
+
+       if (json)
+               top = json_object_new_object();
+
+       pthread_mutex_lock(&refs_mtx);
+       {
+               errlist = code ? list_new() : hash_to_list(refs);
+       }
+       pthread_mutex_unlock(&refs_mtx);
 
-       if (!ref) {
-               vty_out(vty, "Code %d - Unknown\n", code);
-               return;
+       if (code) {
+               ref = log_ref_get(code);
+               if (!ref) {
+                       vty_out(vty, "Code %"PRIu32" - Unknown\n", code);
+                       return;
+               }
+               listnode_add(errlist, ref);
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(errlist, ln, ref)) {
+               if (json) {
+                       char key[11];
+
+                       snprintf(key, sizeof(key), "%"PRIu32, ref->code);
+                       obj = json_object_new_object();
+                       json_object_string_add(obj, "title", ref->title);
+                       json_object_string_add(obj, "description",
+                                              ref->description);
+                       json_object_string_add(obj, "suggestion",
+                                              ref->suggestion);
+                       json_object_object_add(top, key, obj);
+               } else {
+                       char pbuf[256];
+                       char ubuf[256];
+
+                       snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s",
+                                ref->code, ref->title);
+                       memset(ubuf, '=', strlen(pbuf));
+                       ubuf[strlen(pbuf)] = '\0';
+
+                       vty_out(vty, "%s\n%s\n", pbuf, ubuf);
+                       vty_out(vty, "Description:\n%s\n\n", ref->description);
+                       vty_out(vty, "Recommendation:\n%s\n", ref->suggestion);
+               }
        }
 
-       vty_out(vty, "Error Code %d - %s\n", code, ref->title);
-       vty_out(vty, "--------------------------------------\n");
-       vty_out(vty, "\nDescription:\n%s\n\nRecommendation:\n%s\n\n",
-               ref->description, ref->suggestion);
+       if (json) {
+               const char *str = json_object_to_json_string_ext(
+                       top, JSON_C_TO_STRING_PRETTY);
+               vty_out(vty, "%s\n", str);
+               json_object_free(top);
+       }
+
+       list_delete(&errlist);
 }
 
 DEFUN_NOSH(show_error_code,
           show_error_code_cmd,
-          "show error (0-4294967296)",
+          "show error <(1-4294967296)|all> [json]",
           SHOW_STR
           "Information on errors\n"
-          "Error code to get info about\n")
+          "Error code to get info about\n"
+          "Information on all errors\n"
+          JSON_STR)
 {
-       uint32_t arg = strtoul(argv[2]->arg, NULL, 10);
+       bool json = strmatch(argv[argc-1]->text, "json");
+       uint32_t arg = 0;
+
+       if (!strmatch(argv[2]->text, "all"))
+               arg = strtoul(argv[2]->arg, NULL, 10);
 
-       ferr_ref_display(vty, arg);
+       log_ref_display(vty, arg, json);
        return CMD_SUCCESS;
 }
 
-void ferr_ref_init(void)
+void log_ref_init(void)
 {
        pthread_mutex_lock(&refs_mtx);
        {
@@ -141,10 +201,11 @@ void ferr_ref_init(void)
        install_element(VIEW_NODE, &show_error_code_cmd);
 }
 
-void ferr_ref_fini(void)
+void log_ref_fini(void)
 {
        pthread_mutex_lock(&refs_mtx);
        {
+               hash_clean(refs, NULL);
                hash_free(refs);
                refs = NULL;
        }