]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_debug.c
bgpd: fix invalid memory access in peer_free()
[mirror_frr.git] / bgpd / bgp_debug.c
index 27d7e69782c2d202a6bda9eb05274847516a09ca..4d9ff60e92c72ee3bd9c751bd20f5650e30ea3e1 100644 (file)
@@ -30,6 +30,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "sockunion.h"
 #include "memory.h"
 #include "queue.h"
+#include "filter.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_aspath.h"
@@ -46,7 +47,9 @@ unsigned long conf_bgp_debug_packet;
 unsigned long conf_bgp_debug_filter;
 unsigned long conf_bgp_debug_keepalive;
 unsigned long conf_bgp_debug_update;
+unsigned long conf_bgp_debug_bestpath;
 unsigned long conf_bgp_debug_zebra;
+unsigned long conf_bgp_debug_allow_martians;
 unsigned long conf_bgp_debug_nht;
 unsigned long conf_bgp_debug_update_groups;
 
@@ -57,7 +60,9 @@ unsigned long term_bgp_debug_packet;
 unsigned long term_bgp_debug_filter;
 unsigned long term_bgp_debug_keepalive;
 unsigned long term_bgp_debug_update;
+unsigned long term_bgp_debug_bestpath;
 unsigned long term_bgp_debug_zebra;
+unsigned long term_bgp_debug_allow_martians;
 unsigned long term_bgp_debug_nht;
 unsigned long term_bgp_debug_update_groups;
 
@@ -66,6 +71,7 @@ struct list *bgp_debug_keepalive_peers = NULL;
 struct list *bgp_debug_update_out_peers = NULL;
 struct list *bgp_debug_update_in_peers = NULL;
 struct list *bgp_debug_update_prefixes = NULL;
+struct list *bgp_debug_bestpath_prefixes = NULL;
 struct list *bgp_debug_zebra_prefixes = NULL;
 
 /* messages for BGP-4 status */
@@ -180,13 +186,21 @@ bgp_find_peer (struct vty *vty, const char *peer_str)
   int ret;
   union sockunion su;
   struct bgp *bgp;
+  struct peer *peer;
 
   bgp = vty->index;
   ret = str2sockunion (peer_str, &su);
 
   /* 'swpX' string */
   if (ret < 0)
-    return peer_lookup_by_conf_if (bgp, peer_str);
+    {
+      peer = peer_lookup_by_conf_if (bgp, peer_str);
+
+      if (!peer)
+        peer = peer_lookup_by_hostname (bgp, peer_str);
+
+      return peer;
+    }
   else
     return peer_lookup (bgp, &su);
 }
@@ -205,8 +219,8 @@ bgp_debug_list_free(struct list *list)
         if (filter->p)
           prefix_free(filter->p);
 
-        if (filter->peer)
-          peer_unlock (filter->peer);
+        if (filter->host)
+          XFREE (MTYPE_BGP_DEBUG_STR, filter->host);
 
         XFREE (MTYPE_BGP_DEBUG_FILTER, filter);
       }
@@ -228,8 +242,8 @@ bgp_debug_list_print (struct vty *vty, const char *desc, struct list *list)
       vty_out (vty, " for");
       for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
         {
-          if (filter->peer)
-            vty_out (vty, " %s", filter->peer->host);
+          if (filter->host)
+            vty_out (vty, " %s", filter->host);
 
           if (filter->p)
             vty_out (vty, " %s/%d",
@@ -241,22 +255,62 @@ bgp_debug_list_print (struct vty *vty, const char *desc, struct list *list)
   vty_out (vty, "%s", VTY_NEWLINE);
 }
 
+/* Print the command to enable the debug for each peer/prefix this debug is
+ * enabled for
+ */
+static int
+bgp_debug_list_conf_print (struct vty *vty, const char *desc, struct list *list)
+{
+  struct bgp_debug_filter *filter;
+  struct listnode *node, *nnode;
+  char buf[INET6_ADDRSTRLEN];
+  int write = 0;
+
+  if (list && !list_isempty(list))
+    {
+      for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
+        {
+          if (filter->host)
+            {
+              vty_out (vty, "%s %s%s", desc, filter->host, VTY_NEWLINE);
+              write++;
+            }
+
+
+          if (filter->p)
+            {
+              vty_out (vty, "%s %s/%d%s", desc,
+                       inet_ntop (filter->p->family, &filter->p->u.prefix, buf, INET6_ADDRSTRLEN),
+                       filter->p->prefixlen, VTY_NEWLINE);
+              write++;
+            }
+        }
+    }
+
+    if (!write)
+      {
+        vty_out (vty, "%s%s", desc, VTY_NEWLINE);
+        write++;
+      }
+
+    return write;
+}
+
 static void
-bgp_debug_list_add_entry(struct list *list, struct peer *peer, struct prefix *p)
+bgp_debug_list_add_entry(struct list *list, const char *host, struct prefix *p)
 {
   struct bgp_debug_filter *filter;
 
   filter = XCALLOC (MTYPE_BGP_DEBUG_FILTER, sizeof (struct bgp_debug_filter));
 
-  if (peer)
+  if (host)
     {
-      peer_lock (peer);
-      filter->peer = peer;
+      filter->host = XSTRDUP (MTYPE_BGP_DEBUG_STR, host);
       filter->p = NULL;
     }
   else if (p)
     {
-      filter->peer = NULL;
+      filter->host = NULL;
       filter->p = p;
     }
 
@@ -264,17 +318,17 @@ bgp_debug_list_add_entry(struct list *list, struct peer *peer, struct prefix *p)
 }
 
 static int
-bgp_debug_list_remove_entry(struct list *list, struct peer *peer, struct prefix *p)
+bgp_debug_list_remove_entry(struct list *list, const char *host, struct prefix *p)
 {
   struct bgp_debug_filter *filter;
   struct listnode *node, *nnode;
 
   for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
     {
-      if (peer && filter->peer == peer)
+      if (host && strcmp (filter->host, host) == 0)
         {
           listnode_delete (list, filter);
-          peer_unlock (filter->peer);
+          XFREE (MTYPE_BGP_DEBUG_STR, filter->host);
           XFREE (MTYPE_BGP_DEBUG_FILTER, filter);
           return 1;
         }
@@ -291,16 +345,16 @@ bgp_debug_list_remove_entry(struct list *list, struct peer *peer, struct prefix
 }
 
 static int
-bgp_debug_list_has_entry(struct list *list, struct peer *peer, struct prefix *p)
+bgp_debug_list_has_entry(struct list *list, const char *host, struct prefix *p)
 {
   struct bgp_debug_filter *filter;
   struct listnode *node, *nnode;
 
   for (ALL_LIST_ELEMENTS (list, node, nnode, filter))
     {
-      if (peer)
+      if (host)
         {
-          if (filter->peer == peer)
+          if (strcmp (filter->host, host) == 0)
             {
               return 1;
             }
@@ -318,9 +372,9 @@ bgp_debug_list_has_entry(struct list *list, struct peer *peer, struct prefix *p)
 }
 
 int
-bgp_debug_peer_updout_enabled(struct peer *peer)
+bgp_debug_peer_updout_enabled(char *host)
 {
-  return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, peer, NULL));
+  return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL));
 }
 
 /* Dump attribute. */
@@ -343,13 +397,13 @@ bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
       char addrbuf[BUFSIZ];
 
       /* Add MP case. */
-      if (attr->extra->mp_nexthop_len == 16 
-          || attr->extra->mp_nexthop_len == 32)
+      if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
+          || attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
         snprintf (buf + strlen (buf), size - strlen (buf), ", mp_nexthop %s",
                   inet_ntop (AF_INET6, &attr->extra->mp_nexthop_global, 
                              addrbuf, BUFSIZ));
 
-      if (attr->extra->mp_nexthop_len == 32)
+      if (attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
         snprintf (buf + strlen (buf), size - strlen (buf), "(%s)",
                   inet_ntop (AF_INET6, &attr->extra->mp_nexthop_local, 
                              addrbuf, BUFSIZ));
@@ -400,52 +454,60 @@ bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
     return 0;
 }
 
-/* dump notify packet */
-void
-bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify, 
-                 const char *direct)
+const char *
+bgp_notify_code_str (char code)
 {
-  const char *subcode_str;
-  const char *code_str;
+  return LOOKUP_DEF (bgp_notify_msg, code, "Unrecognized Error Code");
+}
 
-  subcode_str = "";
-  code_str = LOOKUP_DEF (bgp_notify_msg, bgp_notify->code,
-                         "Unrecognized Error Code");
+const char *
+bgp_notify_subcode_str (char code, char subcode)
+{
 
-  switch (bgp_notify->code)
+  switch (code)
     {
     case BGP_NOTIFY_HEADER_ERR:
-      subcode_str = LOOKUP_DEF (bgp_notify_head_msg, bgp_notify->subcode,
-                                "Unrecognized Error Subcode");
-      break;
+      return LOOKUP_DEF (bgp_notify_head_msg, subcode,
+                         "Unrecognized Error Subcode");
     case BGP_NOTIFY_OPEN_ERR:
-      subcode_str = LOOKUP_DEF (bgp_notify_open_msg, bgp_notify->subcode,
-                                "Unrecognized Error Subcode");
-      break;
+      return LOOKUP_DEF (bgp_notify_open_msg, subcode,
+                         "Unrecognized Error Subcode");
     case BGP_NOTIFY_UPDATE_ERR:
-      subcode_str = LOOKUP_DEF (bgp_notify_update_msg, bgp_notify->subcode,
-                                "Unrecognized Error Subcode");
-      break;
+      return LOOKUP_DEF (bgp_notify_update_msg, subcode,
+                         "Unrecognized Error Subcode");
     case BGP_NOTIFY_HOLD_ERR:
       break;
     case BGP_NOTIFY_FSM_ERR:
       break;
     case BGP_NOTIFY_CEASE:
-      subcode_str = LOOKUP_DEF (bgp_notify_cease_msg, bgp_notify->subcode,
-                                "Unrecognized Error Subcode");
-      break;
+      return LOOKUP_DEF (bgp_notify_cease_msg, subcode,
+                         "Unrecognized Error Subcode");
     case BGP_NOTIFY_CAPABILITY_ERR:
-      subcode_str = LOOKUP_DEF (bgp_notify_capability_msg, bgp_notify->subcode,
-                                "Unrecognized Error Subcode");
-      break;
+      return LOOKUP_DEF (bgp_notify_capability_msg, subcode,
+                         "Unrecognized Error Subcode");
     }
+  return "";
+}
+
+/* dump notify packet */
+void
+bgp_notify_print(struct peer *peer, struct bgp_notify *bgp_notify,
+                 const char *direct)
+{
+  const char *subcode_str;
+  const char *code_str;
 
   if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS) || bgp_flag_check (peer->bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
-    zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s",
-              strcmp (direct, "received") == 0 ? "received from" : "sent to",
-              peer->host, bgp_notify->code, bgp_notify->subcode,
-              code_str, subcode_str, bgp_notify->length,
-              bgp_notify->data ? bgp_notify->data : "");
+    {
+      code_str = bgp_notify_code_str(bgp_notify->code);
+      subcode_str = bgp_notify_subcode_str(bgp_notify->code, bgp_notify->subcode);
+
+      zlog_info ("%%NOTIFICATION: %s neighbor %s %d/%d (%s%s) %d bytes %s",
+                 strcmp (direct, "received") == 0 ? "received from" : "sent to",
+                 peer->host, bgp_notify->code, bgp_notify->subcode,
+                 code_str, subcode_str, bgp_notify->length,
+                 bgp_notify->data ? bgp_notify->data : "");
+    }
 }
 
 static void
@@ -546,6 +608,8 @@ DEFUN (debug_bgp_neighbor_events,
        BGP_STR
        "BGP Neighbor Events\n")
 {
+  bgp_debug_list_free(bgp_debug_neighbor_events_peers);
+
   if (vty->node == CONFIG_NODE)
     DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
   else
@@ -566,32 +630,25 @@ DEFUN (debug_bgp_neighbor_events_peer,
        "BGP IPv6 neighbor to debug\n"
        "BGP neighbor on interface to debug\n")
 {
-  struct peer *peer;
-
-  peer = bgp_find_peer (vty, argv[0]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  const char *host = argv[0];
 
   if (!bgp_debug_neighbor_events_peers)
     bgp_debug_neighbor_events_peers = list_new ();
 
-  if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, peer, NULL))
+  if (bgp_debug_list_has_entry(bgp_debug_neighbor_events_peers, host, NULL))
     {
-      vty_out (vty, "BGP neighbor-events debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+      vty_out (vty, "BGP neighbor-events debugging is already enabled for %s%s", host, VTY_NEWLINE);
       return CMD_SUCCESS;
     }
 
-  bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, peer, NULL);
+  bgp_debug_list_add_entry(bgp_debug_neighbor_events_peers, host, NULL);
 
   if (vty->node == CONFIG_NODE)
     DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
   else
     {
       TERM_DEBUG_ON (neighbor_events, NEIGHBOR_EVENTS);
-      vty_out (vty, "BGP neighbor-events debugging is on for %s%s", argv[0], VTY_NEWLINE);
+      vty_out (vty, "BGP neighbor-events debugging is on for %s%s", host, VTY_NEWLINE);
     }
   return CMD_SUCCESS;
 }
@@ -628,18 +685,11 @@ DEFUN (no_debug_bgp_neighbor_events_peer,
        "BGP neighbor on interface to debug\n")
 {
   int found_peer = 0;
-  struct peer *peer;
-
-  peer = bgp_find_peer (vty, argv[0]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  const char *host = argv[0];
 
   if (bgp_debug_neighbor_events_peers && !list_isempty(bgp_debug_neighbor_events_peers))
     {
-      found_peer = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, peer, NULL);
+      found_peer = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, host, NULL);
 
       if (list_isempty(bgp_debug_neighbor_events_peers))
         {
@@ -651,9 +701,9 @@ DEFUN (no_debug_bgp_neighbor_events_peer,
     }
 
   if (found_peer)
-    vty_out (vty, "BGP neighbor-events debugging is off for %s%s", argv[0], VTY_NEWLINE);
+    vty_out (vty, "BGP neighbor-events debugging is off for %s%s", host, VTY_NEWLINE);
   else
-    vty_out (vty, "BGP neighbor-events debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+    vty_out (vty, "BGP neighbor-events debugging was not enabled for %s%s", host, VTY_NEWLINE);
 
   return CMD_SUCCESS;
 }
@@ -702,6 +752,8 @@ DEFUN (debug_bgp_keepalive,
        BGP_STR
        "BGP keepalives\n")
 {
+  bgp_debug_list_free(bgp_debug_keepalive_peers);
+
   if (vty->node == CONFIG_NODE)
     DEBUG_ON (keepalive, KEEPALIVE);
   else
@@ -722,32 +774,25 @@ DEFUN (debug_bgp_keepalive_peer,
        "BGP IPv6 neighbor to debug\n"
        "BGP neighbor on interface to debug\n")
 {
-  struct peer *peer;
-
-  peer = bgp_find_peer (vty, argv[0]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  const char *host = argv[0];
 
   if (!bgp_debug_keepalive_peers)
     bgp_debug_keepalive_peers = list_new ();
 
-  if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, peer, NULL))
+  if (bgp_debug_list_has_entry(bgp_debug_keepalive_peers, host, NULL))
     {
-      vty_out (vty, "BGP keepalive debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+      vty_out (vty, "BGP keepalive debugging is already enabled for %s%s", host, VTY_NEWLINE);
       return CMD_SUCCESS;
     }
 
-  bgp_debug_list_add_entry(bgp_debug_keepalive_peers, peer, NULL);
+  bgp_debug_list_add_entry(bgp_debug_keepalive_peers, host, NULL);
 
   if (vty->node == CONFIG_NODE)
     DEBUG_ON (keepalive, KEEPALIVE);
   else
     {
       TERM_DEBUG_ON (keepalive, KEEPALIVE);
-      vty_out (vty, "BGP keepalives debugging is on for %s%s", argv[0], VTY_NEWLINE);
+      vty_out (vty, "BGP keepalives debugging is on for %s%s", host, VTY_NEWLINE);
     }
   return CMD_SUCCESS;
 }
@@ -784,18 +829,11 @@ DEFUN (no_debug_bgp_keepalive_peer,
        "BGP neighbor on interface to debug\n")
 {
   int found_peer = 0;
-  struct peer *peer;
-
-  peer = bgp_find_peer (vty, argv[0]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[0], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  const char *host = argv[0];
 
   if (bgp_debug_keepalive_peers && !list_isempty(bgp_debug_keepalive_peers))
     {
-      found_peer = bgp_debug_list_remove_entry(bgp_debug_keepalive_peers, peer, NULL);
+      found_peer = bgp_debug_list_remove_entry(bgp_debug_keepalive_peers, host, NULL);
 
       if (list_isempty(bgp_debug_keepalive_peers))
         {
@@ -807,13 +845,131 @@ DEFUN (no_debug_bgp_keepalive_peer,
     }
 
   if (found_peer)
-    vty_out (vty, "BGP keepalives debugging is off for %s%s", argv[0], VTY_NEWLINE);
+    vty_out (vty, "BGP keepalives debugging is off for %s%s", host, VTY_NEWLINE);
+  else
+    vty_out (vty, "BGP keepalives debugging was not enabled for %s%s", host, VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+/* debug bgp bestpath */
+DEFUN (debug_bgp_bestpath_prefix,
+       debug_bgp_bestpath_prefix_cmd,
+       "debug bgp bestpath (A.B.C.D/M|X:X::X:X/M)",
+       DEBUG_STR
+       BGP_STR
+       "BGP bestpath\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "IPv6 prefix <network>/<length>\n")
+
+{
+  struct prefix *argv_p;
+  int ret;
+
+  argv_p = prefix_new();
+  ret = str2prefix (argv[0], argv_p);
+  if (!ret)
+    {
+      prefix_free(argv_p);
+      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+
+  if (!bgp_debug_bestpath_prefixes)
+    bgp_debug_bestpath_prefixes = list_new ();
+
+  if (bgp_debug_list_has_entry(bgp_debug_bestpath_prefixes, NULL, argv_p))
+    {
+      vty_out (vty, "BGP bestptah debugging is already enabled for %s%s", argv[0], VTY_NEWLINE);
+      return CMD_SUCCESS;
+    }
+
+  bgp_debug_list_add_entry(bgp_debug_bestpath_prefixes, NULL, argv_p);
+
+  if (vty->node == CONFIG_NODE)
+    {
+      DEBUG_ON (bestpath, BESTPATH);
+    }
   else
-    vty_out (vty, "BGP keepalives debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+    {
+      TERM_DEBUG_ON (bestpath, BESTPATH);
+      vty_out (vty, "BGP bestpath debugging is on for %s%s", argv[0], VTY_NEWLINE);
+    }
 
   return CMD_SUCCESS;
 }
 
+DEFUN (no_debug_bgp_bestpath_prefix,
+       no_debug_bgp_bestpath_prefix_cmd,
+       "no debug bgp bestpath (A.B.C.D/M|X:X::X:X/M)",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP bestpath\n"
+       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
+       "IPv6 prefix <network>/<length>\n")
+
+{
+  struct prefix *argv_p;
+  int found_prefix = 0;
+  int ret;
+
+  argv_p = prefix_new();
+  ret = str2prefix (argv[0], argv_p);
+  if (!ret)
+    {
+      prefix_free(argv_p);
+      vty_out (vty, "%% Malformed Prefix%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  if (bgp_debug_bestpath_prefixes && !list_isempty(bgp_debug_bestpath_prefixes))
+    {
+      found_prefix = bgp_debug_list_remove_entry(bgp_debug_bestpath_prefixes, NULL, argv_p);
+
+      if (list_isempty(bgp_debug_bestpath_prefixes))
+        {
+          if (vty->node == CONFIG_NODE)
+            {
+              DEBUG_OFF (bestpath, BESTPATH);
+            }
+          else
+            {
+              TERM_DEBUG_OFF (bestpath, BESTPATH);
+              vty_out (vty, "BGP bestpath debugging (per prefix) is off%s", VTY_NEWLINE);
+            }
+        }
+    }
+
+  if (found_prefix)
+    vty_out (vty, "BGP bestpath debugging is off for %s%s", argv[0], VTY_NEWLINE);
+  else
+    vty_out (vty, "BGP bestpath debugging was not enabled for %s%s", argv[0], VTY_NEWLINE);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_bestpath,
+       no_debug_bgp_bestpath_cmd,
+       "no debug bgp bestpath",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP bestpath\n")
+{
+  bgp_debug_list_free(bgp_debug_bestpath_prefixes);
+
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (bestpath, BESTPATH);
+  else
+    {
+      TERM_DEBUG_OFF (bestpath, BESTPATH);
+      vty_out (vty, "BGP bestpath debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
 /* debug bgp updates */
 DEFUN (debug_bgp_update,
        debug_bgp_update_cmd,
@@ -822,6 +978,10 @@ DEFUN (debug_bgp_update,
        BGP_STR
        "BGP updates\n")
 {
+  bgp_debug_list_free(bgp_debug_update_in_peers);
+  bgp_debug_list_free(bgp_debug_update_out_peers);
+  bgp_debug_list_free(bgp_debug_update_prefixes);
+
   if (vty->node == CONFIG_NODE)
     {
       DEBUG_ON (update, UPDATE_IN);
@@ -845,30 +1005,28 @@ DEFUN (debug_bgp_update_direct,
        "Inbound updates\n"
        "Outbound updates\n")
 {
+
+  if (strncmp ("i", argv[0], 1) == 0)
+    bgp_debug_list_free(bgp_debug_update_in_peers);
+  else
+    bgp_debug_list_free(bgp_debug_update_out_peers);
+
   if (vty->node == CONFIG_NODE)
     {
       if (strncmp ("i", argv[0], 1) == 0)
-       {
-         DEBUG_OFF (update, UPDATE_OUT);
-         DEBUG_ON (update, UPDATE_IN);
-       }
+        DEBUG_ON (update, UPDATE_IN);
       else
-       {       
-         DEBUG_OFF (update, UPDATE_IN);
-         DEBUG_ON (update, UPDATE_OUT);
-       }
+        DEBUG_ON (update, UPDATE_OUT);
     }
   else
     {
       if (strncmp ("i", argv[0], 1) == 0)
        {
-         TERM_DEBUG_OFF (update, UPDATE_OUT);
          TERM_DEBUG_ON (update, UPDATE_IN);
          vty_out (vty, "BGP updates debugging is on (inbound)%s", VTY_NEWLINE);
        }
       else
        {
-         TERM_DEBUG_OFF (update, UPDATE_IN);
          TERM_DEBUG_ON (update, UPDATE_OUT);
          vty_out (vty, "BGP updates debugging is on (outbound)%s", VTY_NEWLINE);
        }
@@ -888,17 +1046,9 @@ DEFUN (debug_bgp_update_direct_peer,
        "BGP IPv6 neighbor to debug\n"
        "BGP neighbor on interface to debug\n")
 {
-  struct peer *peer;
+  const char *host = argv[1];
   int inbound;
 
-  peer = bgp_find_peer (vty, argv[1]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
-
-
   if (!bgp_debug_update_in_peers)
     bgp_debug_update_in_peers = list_new ();
 
@@ -912,35 +1062,45 @@ DEFUN (debug_bgp_update_direct_peer,
 
   if (inbound)
     {
-      if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, peer, NULL))
+      if (bgp_debug_list_has_entry(bgp_debug_update_in_peers, host, NULL))
         {
-          vty_out (vty, "BGP inbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+          vty_out (vty, "BGP inbound update debugging is already enabled for %s%s", host, VTY_NEWLINE);
           return CMD_SUCCESS;
         }
     }
 
   else
     {
-      if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, peer, NULL))
+      if (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL))
         {
-          vty_out (vty, "BGP outbound update debugging is already enabled for %s%s", peer->host, VTY_NEWLINE);
+          vty_out (vty, "BGP outbound update debugging is already enabled for %s%s", host, VTY_NEWLINE);
           return CMD_SUCCESS;
         }
     }
 
   if (inbound)
-    bgp_debug_list_add_entry(bgp_debug_update_in_peers, peer, NULL);
+    bgp_debug_list_add_entry(bgp_debug_update_in_peers, host, NULL);
   else
     {
+      struct peer *peer;
       struct peer_af *paf;
-      int af;
+      int afidx;
+
+      bgp_debug_list_add_entry(bgp_debug_update_out_peers, host, NULL);
+      peer = bgp_find_peer (vty, host);
 
-      bgp_debug_list_add_entry(bgp_debug_update_out_peers, peer, NULL);
-      PEERAF_FOREACH (peer, paf, af)
+      if (peer)
         {
-          if (PAF_SUBGRP (paf))
+          for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
             {
-              UPDGRP_PEER_DBG_EN(PAF_SUBGRP(paf)->update_group);
+              paf = peer->peer_af_array[afidx];
+              if (paf != NULL)
+                {
+                  if (PAF_SUBGRP (paf))
+                    {
+                      UPDGRP_PEER_DBG_EN(PAF_SUBGRP(paf)->update_group);
+                    }
+                }
             }
         }
     }
@@ -948,27 +1108,19 @@ DEFUN (debug_bgp_update_direct_peer,
   if (vty->node == CONFIG_NODE)
     {
       if (inbound)
-       {
-         DEBUG_OFF (update, UPDATE_OUT);
-         DEBUG_ON (update, UPDATE_IN);
-       }
+       DEBUG_ON (update, UPDATE_IN);
       else
-       {
-         DEBUG_OFF (update, UPDATE_IN);
-         DEBUG_ON (update, UPDATE_OUT);
-       }
+       DEBUG_ON (update, UPDATE_OUT);
     }
   else
     {
       if (inbound)
        {
-         TERM_DEBUG_OFF (update, UPDATE_OUT);
          TERM_DEBUG_ON (update, UPDATE_IN);
          vty_out (vty, "BGP updates debugging is on (inbound) for %s%s", argv[1], VTY_NEWLINE);
        }
       else
        {
-         TERM_DEBUG_OFF (update, UPDATE_IN);
          TERM_DEBUG_ON (update, UPDATE_OUT);
          vty_out (vty, "BGP updates debugging is on (outbound) for %s%s", argv[1], VTY_NEWLINE);
        }
@@ -976,6 +1128,48 @@ DEFUN (debug_bgp_update_direct_peer,
   return CMD_SUCCESS;
 }
 
+DEFUN (no_debug_bgp_update_direct,
+       no_debug_bgp_update_direct_cmd,
+       "no debug bgp updates (in|out)",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP updates\n"
+       "Inbound updates\n"
+       "Outbound updates\n")
+{
+  if (strncmp ("i", argv[0], 1) == 0)
+    {
+      bgp_debug_list_free(bgp_debug_update_in_peers);
+
+      if (vty->node == CONFIG_NODE)
+        {
+          DEBUG_OFF (update, UPDATE_IN);
+        }
+      else
+        {
+          TERM_DEBUG_OFF (update, UPDATE_IN);
+          vty_out (vty, "BGP updates debugging is off (inbound)%s", VTY_NEWLINE);
+        }
+    }
+  else
+    {
+      bgp_debug_list_free(bgp_debug_update_out_peers);
+
+      if (vty->node == CONFIG_NODE)
+        {
+          DEBUG_OFF (update, UPDATE_OUT);
+        }
+      else
+        {
+          TERM_DEBUG_OFF (update, UPDATE_OUT);
+          vty_out (vty, "BGP updates debugging is off (outbound)%s", VTY_NEWLINE);
+        }
+    }
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (no_debug_bgp_update_direct_peer,
        no_debug_bgp_update_direct_peer_cmd,
        "no debug bgp updates (in|out) (A.B.C.D|X:X::X:X|WORD)",
@@ -991,14 +1185,7 @@ DEFUN (no_debug_bgp_update_direct_peer,
 {
   int inbound;
   int found_peer = 0;
-  struct peer *peer;
-
-  peer = bgp_find_peer (vty, argv[1]);
-  if (!peer)
-    {
-      vty_out (vty, "%s is not a configured peer%s", argv[1], VTY_NEWLINE);
-      return CMD_WARNING;
-    }
+  const char *host = argv[1];
 
   if (strncmp ("i", argv[0], 1) == 0)
     inbound = 1;
@@ -1008,7 +1195,7 @@ DEFUN (no_debug_bgp_update_direct_peer,
   if (inbound && bgp_debug_update_in_peers &&
       !list_isempty(bgp_debug_update_in_peers))
     {
-      found_peer = bgp_debug_list_remove_entry(bgp_debug_update_in_peers, peer, NULL);
+      found_peer = bgp_debug_list_remove_entry(bgp_debug_update_in_peers, host, NULL);
 
       if (list_isempty(bgp_debug_update_in_peers))
         {
@@ -1025,7 +1212,7 @@ DEFUN (no_debug_bgp_update_direct_peer,
   if (!inbound && bgp_debug_update_out_peers &&
       !list_isempty(bgp_debug_update_out_peers))
     {
-      found_peer = bgp_debug_list_remove_entry(bgp_debug_update_out_peers, peer, NULL);
+      found_peer = bgp_debug_list_remove_entry(bgp_debug_update_out_peers, host, NULL);
 
       if (list_isempty(bgp_debug_update_out_peers))
         {
@@ -1038,16 +1225,22 @@ DEFUN (no_debug_bgp_update_direct_peer,
             }
         }
 
-      if (found_peer)
-        {
-          struct peer_af *paf;
-          int af;
+      struct peer *peer;
+      struct peer_af *paf;
+      int afidx;
+      peer = bgp_find_peer (vty, host);
 
-          PEERAF_FOREACH (peer, paf, af)
+      if (peer)
+        {
+          for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
             {
-              if (PAF_SUBGRP (paf))
+              paf = peer->peer_af_array[afidx];
+              if (paf != NULL)
                 {
-                  UPDGRP_PEER_DBG_DIS(PAF_SUBGRP(paf)->update_group);
+                  if (PAF_SUBGRP (paf))
+                    {
+                      UPDGRP_PEER_DBG_DIS(PAF_SUBGRP(paf)->update_group);
+                    }
                 }
             }
         }
@@ -1055,14 +1248,14 @@ DEFUN (no_debug_bgp_update_direct_peer,
 
   if (found_peer)
     if (inbound)
-      vty_out (vty, "BGP updates debugging (inbound) is off for %s%s", argv[1], VTY_NEWLINE);
+      vty_out (vty, "BGP updates debugging (inbound) is off for %s%s", host, VTY_NEWLINE);
     else
-      vty_out (vty, "BGP updates debugging (outbound) is off for %s%s", argv[1], VTY_NEWLINE);
+      vty_out (vty, "BGP updates debugging (outbound) is off for %s%s", host, VTY_NEWLINE);
   else
     if (inbound)
-      vty_out (vty, "BGP updates debugging (inbound) was not enabled for %s%s", argv[1], VTY_NEWLINE);
+      vty_out (vty, "BGP updates debugging (inbound) was not enabled for %s%s", host, VTY_NEWLINE);
     else
-      vty_out (vty, "BGP updates debugging (outbound) was not enabled for %s%s", argv[1], VTY_NEWLINE);
+      vty_out (vty, "BGP updates debugging (outbound) was not enabled for %s%s", host, VTY_NEWLINE);
 
   return CMD_SUCCESS;
 }
@@ -1306,7 +1499,7 @@ DEFUN (no_debug_bgp_zebra_prefix,
 
   if (bgp_debug_zebra_prefixes && !list_isempty(bgp_debug_zebra_prefixes))
     {
-      found_prefix = bgp_debug_list_remove_entry(bgp_debug_neighbor_events_peers, NULL, argv_p);
+      found_prefix = bgp_debug_list_remove_entry(bgp_debug_zebra_prefixes, NULL, argv_p);
 
       if (list_isempty(bgp_debug_zebra_prefixes))
         {
@@ -1328,6 +1521,48 @@ DEFUN (no_debug_bgp_zebra_prefix,
   return CMD_SUCCESS;
 }
 
+DEFUN (debug_bgp_allow_martians,
+       debug_bgp_allow_martians_cmd,
+       "debug bgp allow-martians",
+       DEBUG_STR
+       BGP_STR
+       "BGP allow martian next hops\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_ON (allow_martians, ALLOW_MARTIANS);
+  else
+    {
+      TERM_DEBUG_ON (allow_martians, ALLOW_MARTIANS);
+      vty_out (vty, "BGP allow_martian next hop debugging is on%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_debug_bgp_allow_martians,
+       no_debug_bgp_allow_martians_cmd,
+       "no debug bgp allow-martians",
+       NO_STR
+       DEBUG_STR
+       BGP_STR
+       "BGP allow martian next hops\n")
+{
+  if (vty->node == CONFIG_NODE)
+    DEBUG_OFF (allow_martians, ALLOW_MARTIANS);
+  else
+    {
+      TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS);
+      vty_out (vty, "BGP allow martian next hop debugging is off%s", VTY_NEWLINE);
+    }
+  return CMD_SUCCESS;
+}
+
+ALIAS (no_debug_bgp_allow_martians,
+       undebug_bgp_allow_martians_cmd,
+       "undebug bgp allow-martians",
+       UNDEBUG_STR
+       BGP_STR
+       "BGP allow martian next hops\n")
+
 /* debug bgp update-groups */
 DEFUN (debug_bgp_update_groups,
        debug_bgp_update_groups_cmd,
@@ -1376,6 +1611,7 @@ DEFUN (no_debug_bgp,
   bgp_debug_list_free(bgp_debug_update_in_peers);
   bgp_debug_list_free(bgp_debug_update_out_peers);
   bgp_debug_list_free(bgp_debug_update_prefixes);
+  bgp_debug_list_free(bgp_debug_bestpath_prefixes);
   bgp_debug_list_free(bgp_debug_zebra_prefixes);
 
   bgp_debug_clear_updgrp_update_dbg(vty->index);
@@ -1384,10 +1620,12 @@ DEFUN (no_debug_bgp,
   TERM_DEBUG_OFF (update, UPDATE_IN);
   TERM_DEBUG_OFF (update, UPDATE_OUT);
   TERM_DEBUG_OFF (update, UPDATE_PREFIX);
+  TERM_DEBUG_OFF (bestpath, BESTPATH);
   TERM_DEBUG_OFF (as4, AS4);
   TERM_DEBUG_OFF (as4, AS4_SEGMENT);
   TERM_DEBUG_OFF (neighbor_events, NEIGHBOR_EVENTS);
   TERM_DEBUG_OFF (zebra, ZEBRA);
+  TERM_DEBUG_OFF (allow_martians, ALLOW_MARTIANS);
   vty_out (vty, "All possible debugging has been turned off%s", VTY_NEWLINE);
       
   return CMD_SUCCESS;
@@ -1408,19 +1646,26 @@ DEFUN (show_debugging_bgp,
   if (BGP_DEBUG (as4, AS4_SEGMENT))
     vty_out (vty, "  BGP as4 aspath segment debugging is on%s", VTY_NEWLINE);
 
-  if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
-    bgp_debug_list_print (vty, "  BGP neighbor-events debugging is on",
-                          bgp_debug_neighbor_events_peers);
+  if (BGP_DEBUG (bestpath, BESTPATH))
+    bgp_debug_list_print (vty, "  BGP bestpath debugging is on",
+                          bgp_debug_bestpath_prefixes);
 
   if (BGP_DEBUG (keepalive, KEEPALIVE))
     bgp_debug_list_print (vty, "  BGP keepalives debugging is on",
                           bgp_debug_keepalive_peers);
 
+  if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
+    bgp_debug_list_print (vty, "  BGP neighbor-events debugging is on",
+                          bgp_debug_neighbor_events_peers);
+
   if (BGP_DEBUG (nht, NHT))
     vty_out (vty, "  BGP next-hop tracking debugging is on%s", VTY_NEWLINE);
 
+  if (BGP_DEBUG (update_groups, UPDATE_GROUPS))
+    vty_out (vty, "  BGP update-groups debugging is on%s", VTY_NEWLINE);
+
   if (BGP_DEBUG (update, UPDATE_PREFIX))
-    bgp_debug_list_print (vty, "  BGP updates debugging is on for",
+    bgp_debug_list_print (vty, "  BGP updates debugging is on",
                           bgp_debug_update_prefixes);
 
   if (BGP_DEBUG (update, UPDATE_IN))
@@ -1435,13 +1680,56 @@ DEFUN (show_debugging_bgp,
     bgp_debug_list_print (vty, "  BGP zebra debugging is on",
                           bgp_debug_zebra_prefixes);
 
-  if (BGP_DEBUG (update_groups, UPDATE_GROUPS))
-    vty_out (vty, "  BGP update-groups debugging is on%s", VTY_NEWLINE);
-
+  if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS))
+    vty_out (vty, "  BGP allow martian next hop debugging is on%s", VTY_NEWLINE);
   vty_out (vty, "%s", VTY_NEWLINE);
   return CMD_SUCCESS;
 }
 
+/* return count of number of debug flags set */
+int 
+bgp_debug_count(void) 
+{
+  int ret = 0;
+  if (BGP_DEBUG (as4, AS4))
+    ret++;
+
+  if (BGP_DEBUG (as4, AS4_SEGMENT))
+    ret++;
+
+  if (BGP_DEBUG (bestpath, BESTPATH))
+    ret++;
+
+  if (BGP_DEBUG (keepalive, KEEPALIVE))
+    ret++;
+
+  if (BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
+    ret++;
+
+  if (BGP_DEBUG (nht, NHT))
+    ret++;
+
+  if (BGP_DEBUG (update_groups, UPDATE_GROUPS))
+    ret++;
+
+  if (BGP_DEBUG (update, UPDATE_PREFIX))
+    ret++;
+
+  if (BGP_DEBUG (update, UPDATE_IN))
+    ret++;
+
+  if (BGP_DEBUG (update, UPDATE_OUT))
+    ret++;
+
+  if (BGP_DEBUG (zebra, ZEBRA))
+    ret++;
+
+  if (BGP_DEBUG (allow_martians, ALLOW_MARTIANS))
+    ret++;
+
+  return ret;
+}
+
 static int
 bgp_config_write_debug (struct vty *vty)
 {
@@ -1459,49 +1747,71 @@ bgp_config_write_debug (struct vty *vty)
       write++;
     }
 
+  if (CONF_BGP_DEBUG (bestpath, BESTPATH))
+    {
+      write += bgp_debug_list_conf_print (vty, "debug bgp bestpath",
+                                          bgp_debug_bestpath_prefixes);
+    }
+
   if (CONF_BGP_DEBUG (keepalive, KEEPALIVE))
     {
-      vty_out (vty, "debug bgp keepalives%s", VTY_NEWLINE);
-      write++;
+      write += bgp_debug_list_conf_print (vty, "debug bgp keepalives",
+                                          bgp_debug_keepalive_peers);
     }
 
-  if (CONF_BGP_DEBUG (update, UPDATE_IN) && CONF_BGP_DEBUG (update, UPDATE_OUT))
+  if (CONF_BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
     {
-      vty_out (vty, "debug bgp updates%s", VTY_NEWLINE);
-      write++;
+      write += bgp_debug_list_conf_print (vty, "debug bgp neighbor-events",
+                                          bgp_debug_neighbor_events_peers);
     }
-  else if (CONF_BGP_DEBUG (update, UPDATE_IN))
+
+  if (CONF_BGP_DEBUG (nht, NHT))
     {
-      vty_out (vty, "debug bgp updates in%s", VTY_NEWLINE);
+      vty_out (vty, "debug bgp nht%s", VTY_NEWLINE);
       write++;
     }
-  else if (CONF_BGP_DEBUG (update, UPDATE_OUT))
+
+  if (CONF_BGP_DEBUG (update_groups, UPDATE_GROUPS))
     {
-      vty_out (vty, "debug bgp updates out%s", VTY_NEWLINE);
+      vty_out (vty, "debug bgp update-groups%s", VTY_NEWLINE);
       write++;
     }
 
-  if (CONF_BGP_DEBUG (neighbor_events, NEIGHBOR_EVENTS))
+  if (CONF_BGP_DEBUG (update, UPDATE_PREFIX))
     {
-      vty_out (vty, "debug bgp neighbor-events%s", VTY_NEWLINE);
-      write++;
+      write += bgp_debug_list_conf_print (vty, "debug bgp updates prefix",
+                                          bgp_debug_update_prefixes);
     }
 
-  if (CONF_BGP_DEBUG (zebra, ZEBRA))
+  if (CONF_BGP_DEBUG (update, UPDATE_IN))
     {
-      vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
-      write++;
+      write += bgp_debug_list_conf_print (vty, "debug bgp updates in",
+                                          bgp_debug_update_in_peers);
     }
 
-    if (CONF_BGP_DEBUG (nht, NHT))
+  if (CONF_BGP_DEBUG (update, UPDATE_OUT))
     {
-      vty_out (vty, "debug bgp nht%s", VTY_NEWLINE);
-      write++;
+      write += bgp_debug_list_conf_print (vty, "debug bgp updates out",
+                                          bgp_debug_update_out_peers);
     }
 
-    if (CONF_BGP_DEBUG (update_groups, UPDATE_GROUPS))
+  if (CONF_BGP_DEBUG (zebra, ZEBRA))
     {
-      vty_out (vty, "debug bgp update-groups%s", VTY_NEWLINE);
+      if (!bgp_debug_zebra_prefixes || list_isempty(bgp_debug_zebra_prefixes))
+        {
+          vty_out (vty, "debug bgp zebra%s", VTY_NEWLINE);
+          write++;
+        }
+      else
+        {
+          write += bgp_debug_list_conf_print (vty, "debug bgp zebra prefix",
+                                              bgp_debug_zebra_prefixes);
+        }
+    }
+
+  if (CONF_BGP_DEBUG (allow_martians, ALLOW_MARTIANS))
+    {
+      vty_out (vty, "debug bgp allow-martians%s", VTY_NEWLINE);
       write++;
     }
 
@@ -1535,26 +1845,34 @@ bgp_debug_init (void)
   install_element (CONFIG_NODE, &debug_bgp_keepalive_cmd);
   install_element (ENABLE_NODE, &debug_bgp_update_cmd);
   install_element (CONFIG_NODE, &debug_bgp_update_cmd);
-  install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd);
-  install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
   install_element (ENABLE_NODE, &debug_bgp_zebra_cmd);
   install_element (CONFIG_NODE, &debug_bgp_zebra_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_allow_martians_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_allow_martians_cmd);
   install_element (ENABLE_NODE, &debug_bgp_update_groups_cmd);
   install_element (CONFIG_NODE, &debug_bgp_update_groups_cmd);
+  install_element (ENABLE_NODE, &debug_bgp_bestpath_prefix_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_bestpath_prefix_cmd);
 
-  /* deb bgp updates [in|out] A.B.C.D */
+  /* debug bgp updates (in|out) */
+  install_element (ENABLE_NODE, &debug_bgp_update_direct_cmd);
+  install_element (CONFIG_NODE, &debug_bgp_update_direct_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_update_direct_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_update_direct_cmd);
+
+  /* debug bgp updates (in|out) A.B.C.D */
   install_element (ENABLE_NODE, &debug_bgp_update_direct_peer_cmd);
   install_element (CONFIG_NODE, &debug_bgp_update_direct_peer_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_update_direct_peer_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_update_direct_peer_cmd);
 
-  /* deb bgp updates prefix A.B.C.D/M */
+  /* debug bgp updates prefix A.B.C.D/M */
   install_element (ENABLE_NODE, &debug_bgp_update_prefix_cmd);
   install_element (CONFIG_NODE, &debug_bgp_update_prefix_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_update_prefix_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_update_prefix_cmd);
 
-  /* deb bgp zebra prefix A.B.C.D/M */
+  /* debug bgp zebra prefix A.B.C.D/M */
   install_element (ENABLE_NODE, &debug_bgp_zebra_prefix_cmd);
   install_element (CONFIG_NODE, &debug_bgp_zebra_prefix_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_zebra_prefix_cmd);
@@ -1565,13 +1883,13 @@ bgp_debug_init (void)
   install_element (ENABLE_NODE, &no_debug_bgp_as4_segment_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_as4_segment_cmd);
 
-  /* deb bgp neighbor-events A.B.C.D */
+  /* debug bgp neighbor-events A.B.C.D */
   install_element (ENABLE_NODE, &debug_bgp_neighbor_events_peer_cmd);
   install_element (CONFIG_NODE, &debug_bgp_neighbor_events_peer_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_neighbor_events_peer_cmd);
 
-  /* deb bgp keepalive A.B.C.D */
+  /* debug bgp keepalive A.B.C.D */
   install_element (ENABLE_NODE, &debug_bgp_keepalive_peer_cmd);
   install_element (CONFIG_NODE, &debug_bgp_keepalive_peer_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_keepalive_peer_cmd);
@@ -1587,9 +1905,16 @@ bgp_debug_init (void)
   install_element (CONFIG_NODE, &no_debug_bgp_update_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_zebra_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_zebra_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_allow_martians_cmd);
+  install_element (ENABLE_NODE, &undebug_bgp_allow_martians_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_allow_martians_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_update_groups_cmd);
   install_element (CONFIG_NODE, &no_debug_bgp_update_groups_cmd);
   install_element (ENABLE_NODE, &no_debug_bgp_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_bestpath_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_bestpath_cmd);
+  install_element (ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd);
+  install_element (CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd);
 }
 
 /* Return true if this prefix is on the per_prefix_list of prefixes to debug
@@ -1628,7 +1953,7 @@ bgp_debug_per_prefix (struct prefix *p, unsigned long term_bgp_debug_type,
  * for BGP_DEBUG_TYPE
  */
 static int
-bgp_debug_per_peer(struct peer *peer, unsigned long term_bgp_debug_type,
+bgp_debug_per_peer(char *host, unsigned long term_bgp_debug_type,
                    unsigned int BGP_DEBUG_TYPE, struct list *per_peer_list)
 {
   struct bgp_debug_filter *filter;
@@ -1642,11 +1967,11 @@ bgp_debug_per_peer(struct peer *peer, unsigned long term_bgp_debug_type,
 
       else
         {
-          if (!peer)
+          if (!host)
             return 0;
 
           for (ALL_LIST_ELEMENTS (per_peer_list, node, nnode, filter))
-            if (filter->peer == peer)
+            if (strcmp (filter->host, host) == 0)
               return 1;
 
           return 0;
@@ -1659,7 +1984,12 @@ bgp_debug_per_peer(struct peer *peer, unsigned long term_bgp_debug_type,
 int
 bgp_debug_neighbor_events (struct peer *peer)
 {
-  return bgp_debug_per_peer (peer,
+  char *host = NULL;
+
+  if (peer)
+    host = peer->host;
+
+  return bgp_debug_per_peer (host,
                              term_bgp_debug_neighbor_events,
                              BGP_DEBUG_NEIGHBOR_EVENTS,
                              bgp_debug_neighbor_events_peers);
@@ -1668,7 +1998,12 @@ bgp_debug_neighbor_events (struct peer *peer)
 int
 bgp_debug_keepalive (struct peer *peer)
 {
-  return bgp_debug_per_peer (peer,
+  char *host = NULL;
+
+  if (peer)
+    host = peer->host;
+
+  return bgp_debug_per_peer (host,
                              term_bgp_debug_keepalive,
                              BGP_DEBUG_KEEPALIVE,
                              bgp_debug_keepalive_peers);
@@ -1678,9 +2013,14 @@ int
 bgp_debug_update (struct peer *peer, struct prefix *p,
                   struct update_group *updgrp, unsigned int inbound)
 {
+  char *host = NULL;
+
+  if (peer)
+    host = peer->host;
+
   if (inbound)
     {
-      if (bgp_debug_per_peer (peer, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN,
+      if (bgp_debug_per_peer (host, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN,
                               bgp_debug_update_in_peers))
         return 1;
     }
@@ -1688,7 +2028,7 @@ bgp_debug_update (struct peer *peer, struct prefix *p,
   /* outbound */
   else
     {
-      if (bgp_debug_per_peer (peer, term_bgp_debug_update,
+      if (bgp_debug_per_peer (host, term_bgp_debug_update,
                               BGP_DEBUG_UPDATE_OUT,
                               bgp_debug_update_out_peers))
         return 1;
@@ -1710,6 +2050,20 @@ bgp_debug_update (struct peer *peer, struct prefix *p,
   return 0;
 }
 
+int
+bgp_debug_bestpath (struct prefix *p)
+{
+  if (BGP_DEBUG (bestpath, BESTPATH))
+    {
+      if (bgp_debug_per_prefix (p, term_bgp_debug_bestpath,
+                                BGP_DEBUG_BESTPATH,
+                                bgp_debug_bestpath_prefixes))
+        return 1;
+    }
+
+  return 0;
+}
+
 int
 bgp_debug_zebra (struct prefix *p)
 {