]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_misc.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / isisd / isis_misc.c
index 3869159a02f86725ea16bdef52267d843d9885f5..c24917454a8556bb7897cf87fbf15b9ebc2f4039 100644 (file)
@@ -3,17 +3,17 @@
  *                             Miscellanous routines
  *
  * Copyright (C) 2001,2002   Sampo Saaristo
- *                           Tampere University of Technology      
+ *                           Tampere University of Technology
  *                           Institute of Communications Engineering
  *
- * This program is free software; you can redistribute it and/or modify it 
- * under the terms of the GNU General Public Licenseas published by the Free 
- * Software Foundation; either version 2 of the License, or (at your option) 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public Licenseas published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * This program is distributed in the hope that it will be useful,but WITHOUT 
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
+ * This program is distributed in the hope that it will be useful,but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  * more details.
  *
  * You should have received a copy of the GNU General Public License along
@@ -28,6 +28,7 @@
 #include "hash.h"
 #include "if.h"
 #include "command.h"
+#include "log_int.h"
 
 #include "isisd/dict.h"
 #include "isisd/isis_constants.h"
@@ -38,7 +39,6 @@
 #include "isisd/isisd.h"
 #include "isisd/isis_misc.h"
 
-#include "isisd/isis_tlv.h"
 #include "isisd/isis_lsp.h"
 #include "isisd/isis_constants.h"
 #include "isisd/isis_adjacency.h"
 
 /* staticly assigned vars for printing purposes */
 struct in_addr new_prefix;
-/* len of xxxx.xxxx.xxxx + place for #0 termination */
-char sysid[15];
-/* len of xxxx.xxxx.xxxx + place for #0 termination */
-char snpa[15];
 /* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
-char isonet[51];
 /* + place for #0 termination */
-/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
-char lspid[21];
+char isonet[51];
 /* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
 char datestring[20];
 char nlpidstring[30];
@@ -62,428 +56,337 @@ char nlpidstring[30];
 /*
  * This converts the isonet to its printable format
  */
-const char *
-isonet_print (const u_char * from, int len)
+const char *isonet_print(const uint8_t *from, int len)
 {
-  int i = 0;
-  char *pos = isonet;
-
-  if (!from)
-    return "unknown";
-
-  while (i < len)
-    {
-      if (i & 1)
-       {
-         sprintf (pos, "%02x", *(from + i));
-         pos += 2;
-       }
-      else
-       {
-         if (i == (len - 1))
-           {                   /* No dot at the end of address */
-             sprintf (pos, "%02x", *(from + i));
-             pos += 2;
-           }
-         else
-           {
-             sprintf (pos, "%02x.", *(from + i));
-             pos += 3;
-           }
+       int i = 0;
+       char *pos = isonet;
+
+       if (!from)
+               return "unknown";
+
+       while (i < len) {
+               if (i & 1) {
+                       sprintf(pos, "%02x", *(from + i));
+                       pos += 2;
+               } else {
+                       if (i == (len - 1)) { /* No dot at the end of address */
+                               sprintf(pos, "%02x", *(from + i));
+                               pos += 2;
+                       } else {
+                               sprintf(pos, "%02x.", *(from + i));
+                               pos += 3;
+                       }
+               }
+               i++;
        }
-      i++;
-    }
-  *(pos) = '\0';
-  return isonet;
+       *(pos) = '\0';
+       return isonet;
 }
 
 /*
  * Returns 0 on error, length of buff on ok
- * extract dot from the dotted str, and insert all the number in a buff 
+ * extract dot from the dotted str, and insert all the number in a buff
  */
-int
-dotformat2buff (u_char * buff, const char * dotted)
+int dotformat2buff(uint8_t *buff, const char *dotted)
 {
-  int dotlen, len = 0;
-  const char *pos = dotted;
-  u_char number[3];
-  int nextdotpos = 2;
-
-  number[2] = '\0';
-  dotlen = strlen(dotted);
-  if (dotlen > 50)
-    {
-      /* this can't be an iso net, its too long */
-      return 0;
-    }
-
-  while ((pos - dotted) < dotlen && len < 20)
-    {
-      if (*pos == '.')
-       {
-         /* we expect the . at 2, and than every 5 */
-         if ((pos - dotted) != nextdotpos)
-           {
-             len = 0;
-             break;
-           }
-         nextdotpos += 5;
-         pos++;
-         continue;
-       }
-      /* we must have at least two chars left here */
-      if (dotlen - (pos - dotted) < 2)
-       {
-         len = 0;
-         break;
+       int dotlen, len = 0;
+       const char *pos = dotted;
+       uint8_t number[3];
+       int nextdotpos = 2;
+
+       number[2] = '\0';
+       dotlen = strlen(dotted);
+       if (dotlen > 50) {
+               /* this can't be an iso net, its too long */
+               return 0;
        }
 
-      if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
-       {
-         memcpy (number, pos, 2);
-         pos += 2;
-       }
-      else
-       {
-         len = 0;
-         break;
+       while ((pos - dotted) < dotlen && len < 20) {
+               if (*pos == '.') {
+                       /* we expect the . at 2, and than every 5 */
+                       if ((pos - dotted) != nextdotpos) {
+                               len = 0;
+                               break;
+                       }
+                       nextdotpos += 5;
+                       pos++;
+                       continue;
+               }
+               /* we must have at least two chars left here */
+               if (dotlen - (pos - dotted) < 2) {
+                       len = 0;
+                       break;
+               }
+
+               if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) {
+                       memcpy(number, pos, 2);
+                       pos += 2;
+               } else {
+                       len = 0;
+                       break;
+               }
+
+               *(buff + len) = (char)strtol((char *)number, NULL, 16);
+               len++;
        }
 
-      *(buff + len) = (char) strtol ((char *)number, NULL, 16);
-      len++;
-    }
-
-  return len;
+       return len;
 }
 
 /*
  * conversion of XXXX.XXXX.XXXX to memory
  */
-int
-sysid2buff (u_char * buff, const char * dotted)
+int sysid2buff(uint8_t *buff, const char *dotted)
 {
-  int len = 0;
-  const char *pos = dotted;
-  u_char number[3];
-
-  number[2] = '\0';
-  // surely not a sysid_string if not 14 length
-  if (strlen (dotted) != 14)
-    {
-      return 0;
-    }
-
-  while (len < ISIS_SYS_ID_LEN)
-    {
-      if (*pos == '.')
-       {
-         /* the . is not positioned correctly */
-         if (((pos - dotted) != 4) && ((pos - dotted) != 9))
-           {
-             len = 0;
-             break;
-           }
-         pos++;
-         continue;
+       int len = 0;
+       const char *pos = dotted;
+       uint8_t number[3];
+
+       number[2] = '\0';
+       // surely not a sysid_string if not 14 length
+       if (strlen(dotted) != 14) {
+               return 0;
        }
-      if ((isxdigit ((int) *pos)) && (isxdigit ((int) *(pos + 1))))
-       {
-         memcpy (number, pos, 2);
-         pos += 2;
-       }
-      else
-       {
-         len = 0;
-         break;
-       }
-
-      *(buff + len) = (char) strtol ((char *)number, NULL, 16);
-      len++;
-    }
 
-  return len;
+       while (len < ISIS_SYS_ID_LEN) {
+               if (*pos == '.') {
+                       /* the . is not positioned correctly */
+                       if (((pos - dotted) != 4) && ((pos - dotted) != 9)) {
+                               len = 0;
+                               break;
+                       }
+                       pos++;
+                       continue;
+               }
+               if ((isxdigit((int)*pos)) && (isxdigit((int)*(pos + 1)))) {
+                       memcpy(number, pos, 2);
+                       pos += 2;
+               } else {
+                       len = 0;
+                       break;
+               }
+
+               *(buff + len) = (char)strtol((char *)number, NULL, 16);
+               len++;
+       }
 
+       return len;
 }
 
-/*
- * converts the nlpids struct (filled by TLV #129)
- * into a string
- */
-
-char *
-nlpid2string (struct nlpids *nlpids)
+const char *nlpid2str(uint8_t nlpid)
 {
-  char *pos = nlpidstring;
-  int i;
-
-  for (i = 0; i < nlpids->count; i++)
-    {
-      switch (nlpids->nlpids[i])
-       {
+       static char buf[4];
+       switch (nlpid) {
        case NLPID_IP:
-         pos += sprintf (pos, "IPv4");
-         break;
+               return "IPv4";
        case NLPID_IPV6:
-         pos += sprintf (pos, "IPv6");
-         break;
+               return "IPv6";
        case NLPID_SNAP:
-         pos += sprintf (pos, "SNAP");
-         break;
+               return "SNAP";
        case NLPID_CLNP:
-         pos += sprintf (pos, "CLNP");
-         break;
+               return "CLNP";
        case NLPID_ESIS:
-         pos += sprintf (pos, "ES-IS");
-         break;
+               return "ES-IS";
        default:
-         pos += sprintf (pos, "unknown");
-         break;
+               snprintf(buf, sizeof(buf), "%" PRIu8, nlpid);
+               return buf;
        }
-      if (nlpids->count - i > 1)
-       pos += sprintf (pos, ", ");
-
-    }
-
-  *(pos) = '\0';
-
-  return nlpidstring;
 }
 
 /*
- *  supports the given af ?
+ * converts the nlpids struct (filled by TLV #129)
+ * into a string
  */
-int
-speaks (struct nlpids *nlpids, int family)
+
+char *nlpid2string(struct nlpids *nlpids)
 {
-  int i, speaks = 0;
-
-  if (nlpids == (struct nlpids *) NULL)
-    return speaks;
-  for (i = 0; i < nlpids->count; i++)
-    {
-      if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
-       speaks = 1;
-      if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
-       speaks = 1;
-    }
-
-  return speaks;
+       char *pos = nlpidstring;
+       int i;
+
+       for (i = 0; i < nlpids->count; i++) {
+               pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
+               if (nlpids->count - i > 1)
+                       pos += sprintf(pos, ", ");
+       }
+
+       *(pos) = '\0';
+
+       return nlpidstring;
 }
 
 /*
  * Returns 0 on error, IS-IS Circuit Type on ok
  */
-int
-string2circuit_t (const char * str)
+int string2circuit_t(const char *str)
 {
 
-  if (!str)
-    return 0;
+       if (!str)
+               return 0;
 
-  if (!strcmp (str, "level-1"))
-    return IS_LEVEL_1;
+       if (!strcmp(str, "level-1"))
+               return IS_LEVEL_1;
 
-  if (!strcmp (str, "level-2-only") || !strcmp (str, "level-2"))
-    return IS_LEVEL_2;
+       if (!strcmp(str, "level-2-only") || !strcmp(str, "level-2"))
+               return IS_LEVEL_2;
 
-  if (!strcmp (str, "level-1-2"))
-    return IS_LEVEL_1_AND_2;
+       if (!strcmp(str, "level-1-2"))
+               return IS_LEVEL_1_AND_2;
 
-  return 0;
+       return 0;
 }
 
-const char *
-circuit_state2string (int state)
+const char *circuit_state2string(int state)
 {
 
-  switch (state)
-    {
-    case C_STATE_INIT:
-      return "Init";
-    case C_STATE_CONF:
-      return "Config";
-    case C_STATE_UP:
-      return "Up";
-    default:
-      return "Unknown";
-    }
-  return NULL;
+       switch (state) {
+       case C_STATE_INIT:
+               return "Init";
+       case C_STATE_CONF:
+               return "Config";
+       case C_STATE_UP:
+               return "Up";
+       default:
+               return "Unknown";
+       }
+       return NULL;
 }
 
-const char *
-circuit_type2string (int type)
+const char *circuit_type2string(int type)
 {
 
-  switch (type)
-    {
-    case CIRCUIT_T_P2P:
-      return "p2p";
-    case CIRCUIT_T_BROADCAST:
-      return "lan";
-    case CIRCUIT_T_LOOPBACK:
-      return "loopback";
-    default:
-      return "Unknown";
-    }
-  return NULL;
+       switch (type) {
+       case CIRCUIT_T_P2P:
+               return "p2p";
+       case CIRCUIT_T_BROADCAST:
+               return "lan";
+       case CIRCUIT_T_LOOPBACK:
+               return "loopback";
+       default:
+               return "Unknown";
+       }
+       return NULL;
 }
 
-const char *
-circuit_t2string (int circuit_t)
+const char *circuit_t2string(int circuit_t)
 {
-  switch (circuit_t)
-    {
-    case IS_LEVEL_1:
-      return "L1";
-    case IS_LEVEL_2:
-      return "L2";
-    case IS_LEVEL_1_AND_2:
-      return "L1L2";
-    default:
-      return "??";
-    }
-
-  return NULL;                 /* not reached */
+       switch (circuit_t) {
+       case IS_LEVEL_1:
+               return "L1";
+       case IS_LEVEL_2:
+               return "L2";
+       case IS_LEVEL_1_AND_2:
+               return "L1L2";
+       default:
+               return "??";
+       }
+
+       return NULL; /* not reached */
 }
 
-const char *
-syst2string (int type)
+const char *syst2string(int type)
 {
-  switch (type)
-    {
-    case ISIS_SYSTYPE_ES:
-      return "ES";
-    case ISIS_SYSTYPE_IS:
-      return "IS";
-    case ISIS_SYSTYPE_L1_IS:
-      return "1";
-    case ISIS_SYSTYPE_L2_IS:
-      return "2";
-    default:
-      return "??";
-    }
-
-  return NULL;                 /* not reached */
+       switch (type) {
+       case ISIS_SYSTYPE_ES:
+               return "ES";
+       case ISIS_SYSTYPE_IS:
+               return "IS";
+       case ISIS_SYSTYPE_L1_IS:
+               return "1";
+       case ISIS_SYSTYPE_L2_IS:
+               return "2";
+       default:
+               return "??";
+       }
+
+       return NULL; /* not reached */
 }
 
 /*
  * Print functions - we print to static vars
  */
-const char *
-snpa_print (const u_char * from)
+const char *snpa_print(const uint8_t *from)
 {
-  int i = 0;
-  u_char *pos = (u_char *)snpa;
-
-  if (!from)
-    return "unknown";
-
-  while (i < ETH_ALEN - 1)
-    {
-      if (i & 1)
-       {
-         sprintf ((char *)pos, "%02x.", *(from + i));
-         pos += 3;
-       }
-      else
-       {
-         sprintf ((char *)pos, "%02x", *(from + i));
-         pos += 2;
-
-       }
-      i++;
-    }
+       return isis_format_id(from, ISIS_SYS_ID_LEN);
+}
 
-  sprintf ((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
-  pos += 2;
-  *(pos) = '\0';
+const char *sysid_print(const uint8_t *from)
+{
+       return isis_format_id(from, ISIS_SYS_ID_LEN);
+}
 
-  return snpa;
+const char *rawlspid_print(const uint8_t *from)
+{
+       return isis_format_id(from, 8);
 }
 
-const char *
-sysid_print (const u_char * from)
+#define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00")
+const char *isis_format_id(const uint8_t *id, size_t len)
 {
-  int i = 0;
-  char *pos = sysid;
-
-  if (!from)
-    return "unknown";
-
-  while (i < ISIS_SYS_ID_LEN - 1)
-    {
-      if (i & 1)
-       {
-         sprintf (pos, "%02x.", *(from + i));
-         pos += 3;
+#define FORMAT_BUF_COUNT 4
+       static char buf_ring[FORMAT_BUF_COUNT][FORMAT_ID_SIZE];
+       static size_t cur_buf = 0;
+
+       char *rv;
+
+       cur_buf++;
+       if (cur_buf >= FORMAT_BUF_COUNT)
+               cur_buf = 0;
+
+       rv = buf_ring[cur_buf];
+
+       if (!id) {
+               snprintf(rv, FORMAT_ID_SIZE, "unknown");
+               return rv;
        }
-      else
-       {
-         sprintf (pos, "%02x", *(from + i));
-         pos += 2;
 
+       if (len < 6) {
+               snprintf(rv, FORMAT_ID_SIZE, "Short ID");
+               return rv;
        }
-      i++;
-    }
 
-  sprintf (pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
-  pos += 2;
-  *(pos) = '\0';
+       snprintf(rv, FORMAT_ID_SIZE, "%02x%02x.%02x%02x.%02x%02x", id[0], id[1],
+                id[2], id[3], id[4], id[5]);
 
-  return sysid;
-}
+       if (len > 6)
+               snprintf(rv + 14, FORMAT_ID_SIZE - 14, ".%02x", id[6]);
+       if (len > 7)
+               snprintf(rv + 17, FORMAT_ID_SIZE - 17, "-%02x", id[7]);
 
-const char *
-rawlspid_print (const u_char * from)
-{
-  char *pos = lspid;
-  if (!from)
-    return "unknown";
-  memcpy (pos, sysid_print (from), 15);
-  pos += 14;
-  sprintf (pos, ".%02x", LSP_PSEUDO_ID (from));
-  pos += 3;
-  sprintf (pos, "-%02x", LSP_FRAGMENT (from));
-  pos += 3;
-
-  *(pos) = '\0';
-
-  return lspid;
+       return rv;
 }
 
-const char *
-time2string (u_int32_t time)
+const char *time2string(uint32_t time)
 {
-  char *pos = datestring;
-  u_int32_t rest;
-
-  if (time == 0)
-    return "-";
-
-  if (time / SECS_PER_YEAR)
-    pos += sprintf (pos, "%uY", time / SECS_PER_YEAR);
-  rest = time % SECS_PER_YEAR;
-  if (rest / SECS_PER_MONTH)
-    pos += sprintf (pos, "%uM", rest / SECS_PER_MONTH);
-  rest = rest % SECS_PER_MONTH;
-  if (rest / SECS_PER_WEEK)
-    pos += sprintf (pos, "%uw", rest / SECS_PER_WEEK);
-  rest = rest % SECS_PER_WEEK;
-  if (rest / SECS_PER_DAY)
-    pos += sprintf (pos, "%ud", rest / SECS_PER_DAY);
-  rest = rest % SECS_PER_DAY;
-  if (rest / SECS_PER_HOUR)
-    pos += sprintf (pos, "%uh", rest / SECS_PER_HOUR);
-  rest = rest % SECS_PER_HOUR;
-  if (rest / SECS_PER_MINUTE)
-    pos += sprintf (pos, "%um", rest / SECS_PER_MINUTE);
-  rest = rest % SECS_PER_MINUTE;
-  if (rest)
-    pos += sprintf (pos, "%us", rest);
-
-  *(pos) = 0;
-
-  return datestring;
+       char *pos = datestring;
+       uint32_t rest;
+
+       if (time == 0)
+               return "-";
+
+       if (time / SECS_PER_YEAR)
+               pos += sprintf(pos, "%uY", time / SECS_PER_YEAR);
+       rest = time % SECS_PER_YEAR;
+       if (rest / SECS_PER_MONTH)
+               pos += sprintf(pos, "%uM", rest / SECS_PER_MONTH);
+       rest = rest % SECS_PER_MONTH;
+       if (rest / SECS_PER_WEEK)
+               pos += sprintf(pos, "%uw", rest / SECS_PER_WEEK);
+       rest = rest % SECS_PER_WEEK;
+       if (rest / SECS_PER_DAY)
+               pos += sprintf(pos, "%ud", rest / SECS_PER_DAY);
+       rest = rest % SECS_PER_DAY;
+       if (rest / SECS_PER_HOUR)
+               pos += sprintf(pos, "%uh", rest / SECS_PER_HOUR);
+       rest = rest % SECS_PER_HOUR;
+       if (rest / SECS_PER_MINUTE)
+               pos += sprintf(pos, "%um", rest / SECS_PER_MINUTE);
+       rest = rest % SECS_PER_MINUTE;
+       if (rest)
+               pos += sprintf(pos, "%us", rest);
+
+       *(pos) = 0;
+
+       return datestring;
 }
 
 /*
@@ -493,141 +396,209 @@ time2string (u_int32_t time)
  * first argument is the timer and the second is
  * the jitter
  */
-unsigned long
-isis_jitter (unsigned long timer, unsigned long jitter)
+unsigned long isis_jitter(unsigned long timer, unsigned long jitter)
 {
-  int j, k;
+       int j, k;
 
-  if (jitter >= 100)
-    return timer;
+       if (jitter >= 100)
+               return timer;
 
-  if (timer == 1)
-    return timer;
-  /* 
-   * randomizing just the percent value provides
-   * no good random numbers - hence the spread
-   * to RANDOM_SPREAD (100000), which is ok as
-   * most IS-IS timers are no longer than 16 bit
-   */
+       if (timer == 1)
+               return timer;
+       /*
+        * randomizing just the percent value provides
+        * no good random numbers - hence the spread
+        * to RANDOM_SPREAD (100000), which is ok as
+        * most IS-IS timers are no longer than 16 bit
+        */
 
-  j = 1 + (int) ((RANDOM_SPREAD * random ()) / (RAND_MAX + 1.0));
+       j = 1 + (int)((RANDOM_SPREAD * random()) / (RAND_MAX + 1.0));
 
-  k = timer - (timer * (100 - jitter)) / 100;
+       k = timer - (timer * (100 - jitter)) / 100;
 
-  timer = timer - (k * j / RANDOM_SPREAD);
+       timer = timer - (k * j / RANDOM_SPREAD);
 
-  return timer;
+       return timer;
 }
 
-struct in_addr
-newprefix2inaddr (u_char * prefix_start, u_char prefix_masklen)
+struct in_addr newprefix2inaddr(uint8_t *prefix_start, uint8_t prefix_masklen)
 {
-  memset (&new_prefix, 0, sizeof (new_prefix));
-  memcpy (&new_prefix, prefix_start, (prefix_masklen & 0x3F) ?
-         ((((prefix_masklen & 0x3F) - 1) >> 3) + 1) : 0);
-  return new_prefix;
+       memset(&new_prefix, 0, sizeof(new_prefix));
+       memcpy(&new_prefix, prefix_start,
+              (prefix_masklen & 0x3F)
+                      ? ((((prefix_masklen & 0x3F) - 1) >> 3) + 1)
+                      : 0);
+       return new_prefix;
 }
 
 /*
- * Returns host.name if any, otherwise
- * it returns the system hostname.
+ * Returns the dynamic hostname associated with the passed system ID.
+ * If no dynamic hostname found then returns formatted system ID.
  */
-const char *
-unix_hostname (void)
+const char *print_sys_hostname(const uint8_t *sysid)
 {
-  static struct utsname names;
-  const char *hostname;
+       struct isis_dynhn *dyn;
+
+       if (!sysid)
+               return "nullsysid";
+
+       /* For our system ID return our host name */
+       if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
+               return cmd_hostname_get();
 
-  hostname = host.name;
-  if (!hostname)
-    {
-      uname (&names);
-      hostname = names.nodename;
-    }
+       dyn = dynhn_find_by_id(sysid);
+       if (dyn)
+               return dyn->hostname;
 
-  return hostname;
+       return sysid_print(sysid);
 }
 
 /*
- * Returns the dynamic hostname associated with the passed system ID.
- * If no dynamic hostname found then returns formatted system ID.
+ * This function is a generic utility that logs data of given length.
+ * Move this to a shared lib so that any protocol can use it.
  */
-const char *
-print_sys_hostname (const u_char *sysid)
+void zlog_dump_data(void *data, int len)
 {
-  struct isis_dynhn *dyn;
+       int i;
+       unsigned char *p;
+       unsigned char c;
+       char bytestr[4];
+       char addrstr[10];
+       char hexstr[16 * 3 + 5];
+       char charstr[16 * 1 + 5];
+
+       p = data;
+       memset(bytestr, 0, sizeof(bytestr));
+       memset(addrstr, 0, sizeof(addrstr));
+       memset(hexstr, 0, sizeof(hexstr));
+       memset(charstr, 0, sizeof(charstr));
+
+       for (i = 1; i <= len; i++) {
+               c = *p;
+               if (isalnum(c) == 0)
+                       c = '.';
+
+               /* store address for this line */
+               if ((i % 16) == 1)
+                       snprintf(addrstr, sizeof(addrstr), "%p", p);
+
+               /* store hex str (for left side) */
+               snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
+               strncat(hexstr, bytestr, sizeof(hexstr) - strlen(hexstr) - 1);
+
+               /* store char str (for right side) */
+               snprintf(bytestr, sizeof(bytestr), "%c", c);
+               strncat(charstr, bytestr,
+                       sizeof(charstr) - strlen(charstr) - 1);
+
+               if ((i % 16) == 0) {
+                       /* line completed */
+                       zlog_debug("[%8.8s]   %-50.50s  %s", addrstr, hexstr,
+                                  charstr);
+                       hexstr[0] = 0;
+                       charstr[0] = 0;
+               } else if ((i % 8) == 0) {
+                       /* half line: add whitespaces */
+                       strncat(hexstr, "  ",
+                               sizeof(hexstr) - strlen(hexstr) - 1);
+                       strncat(charstr, " ",
+                               sizeof(charstr) - strlen(charstr) - 1);
+               }
+               p++; /* next byte */
+       }
 
-  if (!sysid)
-    return "nullsysid";
+       /* print rest of buffer if not empty */
+       if (strlen(hexstr) > 0)
+               zlog_debug("[%8.8s]   %-50.50s  %s", addrstr, hexstr, charstr);
+       return;
+}
+
+static char *qasprintf(const char *format, va_list ap)
+{
+       va_list aq;
+       va_copy(aq, ap);
 
-  /* For our system ID return our host name */
-  if (memcmp(sysid, isis->sysid, ISIS_SYS_ID_LEN) == 0)
-    return unix_hostname();
+       int size = 0;
+       char *p = NULL;
 
-  dyn = dynhn_find_by_id (sysid);
-  if (dyn)
-    return (const char *)dyn->name.name;
+       size = vsnprintf(p, size, format, ap);
 
-  return sysid_print (sysid);
+       if (size < 0) {
+               va_end(aq);
+               return NULL;
+       }
+
+       size++;
+       p = XMALLOC(MTYPE_TMP, size);
+
+       size = vsnprintf(p, size, format, aq);
+       va_end(aq);
+
+       if (size < 0) {
+               XFREE(MTYPE_TMP, p);
+               return NULL;
+       }
+
+       return p;
 }
 
-/*
- * This function is a generic utility that logs data of given length.
- * Move this to a shared lib so that any protocol can use it.
- */
-void
-zlog_dump_data (void *data, int len)
+void log_multiline(int priority, const char *prefix, const char *format, ...)
+{
+       va_list ap;
+       char *p;
+
+       va_start(ap, format);
+       p = qasprintf(format, ap);
+       va_end(ap);
+
+       if (!p)
+               return;
+
+       char *saveptr = NULL;
+       for (char *line = strtok_r(p, "\n", &saveptr); line;
+            line = strtok_r(NULL, "\n", &saveptr)) {
+               zlog(priority, "%s%s", prefix, line);
+       }
+
+       XFREE(MTYPE_TMP, p);
+}
+
+void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
+{
+       va_list ap;
+       char *p;
+
+       va_start(ap, format);
+       p = qasprintf(format, ap);
+       va_end(ap);
+
+       if (!p)
+               return;
+
+       char *saveptr = NULL;
+       for (char *line = strtok_r(p, "\n", &saveptr); line;
+            line = strtok_r(NULL, "\n", &saveptr)) {
+               vty_out(vty, "%s%s\n", prefix, line);
+       }
+
+       XFREE(MTYPE_TMP, p);
+}
+
+void vty_out_timestr(struct vty *vty, time_t uptime)
 {
-  int i;
-  unsigned char *p;
-  unsigned char c;
-  char bytestr[4];
-  char addrstr[10];
-  char hexstr[ 16*3 + 5];
-  char charstr[16*1 + 5];
-
-  p = data;
-  memset (bytestr, 0, sizeof(bytestr));
-  memset (addrstr, 0, sizeof(addrstr));
-  memset (hexstr, 0, sizeof(hexstr));
-  memset (charstr, 0, sizeof(charstr));
-
-  for (i = 1; i <= len; i++)
-  {
-    c = *p;
-    if (isalnum (c) == 0)
-      c = '.';
-
-    /* store address for this line */
-    if ((i % 16) == 1)
-      snprintf (addrstr, sizeof(addrstr), "%p", p);
-
-    /* store hex str (for left side) */
-    snprintf (bytestr, sizeof (bytestr), "%02X ", *p);
-    strncat (hexstr, bytestr, sizeof (hexstr) - strlen (hexstr) - 1);
-
-    /* store char str (for right side) */
-    snprintf (bytestr, sizeof (bytestr), "%c", c);
-    strncat (charstr, bytestr, sizeof (charstr) - strlen (charstr) - 1);
-
-    if ((i % 16) == 0)
-    {
-      /* line completed */
-      zlog_debug ("[%8.8s]   %-50.50s  %s", addrstr, hexstr, charstr);
-      hexstr[0] = 0;
-      charstr[0] = 0;
-    }
-    else if ((i % 8) == 0)
-    {
-      /* half line: add whitespaces */
-      strncat (hexstr, "  ", sizeof (hexstr) - strlen (hexstr) - 1);
-      strncat (charstr, " ", sizeof (charstr) - strlen (charstr) - 1);
-    }
-    p++; /* next byte */
-  }
-
-  /* print rest of buffer if not empty */
-  if (strlen (hexstr) > 0)
-    zlog_debug ("[%8.8s]   %-50.50s  %s", addrstr, hexstr, charstr);
-  return;
+       struct tm *tm;
+       time_t difftime = time(NULL);
+       difftime -= uptime;
+       tm = gmtime(&difftime);
+
+       if (difftime < ONE_DAY_SECOND)
+               vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
+                       tm->tm_sec);
+       else if (difftime < ONE_WEEK_SECOND)
+               vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
+                       tm->tm_min);
+       else
+               vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
+                       tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
+       vty_out(vty, " ago");
 }