lib: Add zlog_hexdump() for debugging

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
diff --git a/lib/log.c b/lib/log.c
index f02e4c7..10a771e 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1001,3 +1001,45 @@
     }
   return -1;
 }
+
+void
+zlog_hexdump (void *mem, unsigned int len) {
+  unsigned long i = 0;
+  unsigned int j = 0;
+  unsigned int columns = 8;
+  char buf[(len * 4) + ((len/4) * 20) + 30];
+  char *s = buf;
+
+  for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0); i++)
+    {
+      /* print offset */
+      if (i % columns == 0)
+        s += sprintf(s, "0x%016lx: ", (unsigned long)mem + i);
+
+      /* print hex data */
+      if (i < len)
+        s += sprintf(s, "%02x ", 0xFF & ((char*)mem)[i]);
+
+      /* end of block, just aligning for ASCII dump */
+      else
+        s += sprintf(s, "   ");
+
+      /* print ASCII dump */
+      if (i % columns == (columns - 1))
+        {
+          for (j = i - (columns - 1); j <= i; j++)
+            {
+              if (j >= len) /* end of block, not really printing */
+                s += sprintf(s, " ");
+
+              else if(isprint(((char*)mem)[j])) /* printable char */
+                s += sprintf(s, "%c", 0xFF & ((char*)mem)[j]);
+
+              else /* other char */
+                s += sprintf(s, ".");
+            }
+          s += sprintf(s, "\n");
+        }
+    }
+    zlog_debug("\n%s", buf);
+}
diff --git a/lib/log.h b/lib/log.h
index 77cd53b..514884c 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -189,6 +189,8 @@
 extern size_t quagga_timestamp(int timestamp_precision /* # subsecond digits */,
 			       char *buf, size_t buflen);
 
+extern void zlog_hexdump(void *mem, unsigned int len);
+
 /* structure useful for avoiding repeated rendering of the same timestamp */
 struct timestamp_control {
    size_t len;		/* length of rendered timestamp */