]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: Fix zebra_rnh_register crash
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 Apr 2016 20:12:29 +0000 (16:12 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 Apr 2016 20:17:14 +0000 (16:17 -0400)
Zebra is crashing inside of zserv_rnh_register when it attempts to
lookup a vrf that was just deleted:

Imagine this series of events:

Pre (A): ifdown -a -X eth0
(A) zebra notification from kernel that vrf is goneroo
(B) zebra notifies all daemons
(C) bgpd is churning because we have been removing interfaces and we
have an new path and it hasn't handled the vrf goneroo event yet from
zebra so it sends to zebra a new rnh with an old vrf_id.
(D) zebra attempts to lookup the zvrf and crashes because of pointer
dereference.

zebra handles all callbacks in one function. Convert that function to
check to see if we have a valid zvrf. If so make the callback

Ticket: CM-10482
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Reviewed-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
zebra/redistribute.c
zebra/redistribute.h
zebra/redistribute_null.c
zebra/zebra_ptm.c
zebra/zebra_ptm.h
zebra/zserv.c

index dcda0b5152353927d7feaa03633810c96d3d8748..40fae82f7bcddbf9180ae843f1500f499a49b34c 100644 (file)
@@ -321,7 +321,7 @@ redistribute_delete (struct prefix *p, struct rib *rib)
 
 void
 zebra_redistribute_add (int command, struct zserv *client, int length,
-    vrf_id_t vrf_id)
+                       struct zebra_vrf *zvrf)
 {
   afi_t afi;
   int type;
@@ -337,19 +337,19 @@ zebra_redistribute_add (int command, struct zserv *client, int length,
   if (instance && !redist_check_instance(&client->mi_redist[afi][type], instance))
     {
       redist_add_instance(&client->mi_redist[afi][type], instance);
-      zebra_redistribute (client, type, instance, vrf_id);
+      zebra_redistribute (client, type, instance, zvrf->vrf_id);
     }
   else
-    if (! vrf_bitmap_check (client->redist[afi][type], vrf_id))
+    if (! vrf_bitmap_check (client->redist[afi][type], zvrf->vrf_id))
       {
-        vrf_bitmap_set (client->redist[afi][type], vrf_id);
-        zebra_redistribute (client, type, 0, vrf_id);
+        vrf_bitmap_set (client->redist[afi][type], zvrf->vrf_id);
+        zebra_redistribute (client, type, 0, zvrf->vrf_id);
       }
 }
 
 void
 zebra_redistribute_delete (int command, struct zserv *client, int length,
-    vrf_id_t vrf_id)
+                          struct zebra_vrf *zvrf)
 {
   afi_t afi;
   int type;
@@ -367,22 +367,22 @@ zebra_redistribute_delete (int command, struct zserv *client, int length,
       redist_del_instance(&client->mi_redist[afi][type], instance);
       //Pending: why no reaction here?
     }
-  vrf_bitmap_unset (client->redist[afi][type], vrf_id);
+  vrf_bitmap_unset (client->redist[afi][type], zvrf->vrf_id);
 }
 
 void
 zebra_redistribute_default_add (int command, struct zserv *client, int length,
-    vrf_id_t vrf_id)
+                               struct zebra_vrf *zvrf)
 {
-  vrf_bitmap_set (client->redist_default, vrf_id);
-  zebra_redistribute_default (client, vrf_id);
+  vrf_bitmap_set (client->redist_default, zvrf->vrf_id);
+  zebra_redistribute_default (client, zvrf->vrf_id);
 }     
 
 void
 zebra_redistribute_default_delete (int command, struct zserv *client,
-    int length, vrf_id_t vrf_id)
+                                  int length, struct zebra_vrf *zvrf)
 {
-  vrf_bitmap_unset (client->redist_default, vrf_id);
+  vrf_bitmap_unset (client->redist_default, zvrf->vrf_id);
 }     
 
 /* Interface up information. */
index 47fa4c2928c01c57e2396954861077dbb6d5f0a4..702fff43f989332923d2e6b3f4ebbf774d1acee8 100644 (file)
 #include "vty.h"
 #include "vrf.h"
 
-extern void zebra_redistribute_add (int, struct zserv *, int, vrf_id_t);
-extern void zebra_redistribute_delete (int, struct zserv *, int, vrf_id_t);
+extern void zebra_redistribute_add (int, struct zserv *, int, struct zebra_vrf *zvrf);
+extern void zebra_redistribute_delete (int, struct zserv *, int, struct zebra_vrf *zvrf);
 
 extern void zebra_redistribute_default_add (int, struct zserv *, int,
-    vrf_id_t);
+                                           struct zebra_vrf *zvrf);
 extern void zebra_redistribute_default_delete (int, struct zserv *, int,
-    vrf_id_t);
+                                              struct zebra_vrf *zvrf);
 
 extern void redistribute_update (struct prefix *, struct rib *, struct rib *);
 extern void redistribute_delete (struct prefix *, struct rib *);
index 27223c609a5025f0b3fb3d6d11ed7ce123f1c31b..17248cdf55cd9716077258323a761c03c043c84a 100644 (file)
@@ -5,7 +5,7 @@
 #include "zebra/redistribute.h"
 
 void zebra_redistribute_add (int a, struct zserv *b, int c,
-    vrf_id_t vrf_id)
+                            struct zebra_vrf *zvrf)
 { return; }
 #ifdef HAVE_SYS_WEAK_ALIAS_PRAGMA
 #pragma weak zebra_redistribute_delete = zebra_redistribute_add
@@ -13,13 +13,13 @@ void zebra_redistribute_add (int a, struct zserv *b, int c,
 #pragma weak zebra_redistribute_default_delete = zebra_redistribute_add
 #else
 void zebra_redistribute_delete  (int a, struct zserv *b, int c,
-    vrf_id_t vrf_id)
+                                struct zebra_vrf *zvrf)
 { return; }
 void zebra_redistribute_default_add (int a, struct zserv *b, int c,
-    vrf_id_t vrf_id)
+                                    struct zebra_vrf *zvrf)
 { return; }
 void zebra_redistribute_default_delete (int a, struct zserv *b, int c,
-    vrf_id_t vrf_id)
+                                       struct zebra_vrf *zvrf)
 { return; }
 #endif
 
index 364c1c9fa93a8bf9c45c6a384d59fbbe0ae63a7d..a124f739da0bc7ea34613dff62b7dc7d1b6d4469 100644 (file)
@@ -558,7 +558,7 @@ zebra_ptm_sock_read (struct thread *thread)
 /* BFD peer/dst register/update */
 int
 zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
-                              int command, vrf_id_t vrf_id)
+                           int command, struct zebra_vrf *zvrf)
 {
   struct stream *s;
   struct prefix src_p;
@@ -574,7 +574,6 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
   char buf[INET6_ADDRSTRLEN];
   char tmp_buf[64];
   int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
-  struct zebra_vrf *zvrf;
   unsigned int pid;
 
   if (command == ZEBRA_BFD_DEST_UPDATE)
@@ -674,13 +673,8 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
       ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD,
                           tmp_buf);
 
-      if (vrf_id)
-        {
-          zvrf = vrf_info_lookup (vrf_id);
-          if (zvrf)
-            ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
-                            zvrf->name);
-        }
+      ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
+                        zvrf->name);
     }
   else
     {
@@ -733,7 +727,7 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
 /* BFD peer/dst deregister */
 int
 zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
-                              vrf_id_t vrf_id)
+                              struct zebra_vrf *zvrf)
 {
   struct stream *s;
   struct prefix src_p;
@@ -745,7 +739,6 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
   char tmp_buf[64];
   int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
   void *out_ctxt;
-  struct zebra_vrf *zvrf;
   unsigned int pid;
 
   client->bfd_peer_del_cnt++;
@@ -826,13 +819,8 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length,
                               ZEBRA_PTM_BFD_SRC_IP_FIELD, buf);
         }
 #endif /* HAVE_IPV6 */
-      if (vrf_id)
-        {
-          zvrf = vrf_info_lookup (vrf_id);
-          if (zvrf)
-            ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
-                                zvrf->name);
-        }
+      ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_VRF_NAME_FIELD,
+                        zvrf->name);
     }
   else
     {
index 4914fc03514fb231d1c1e9f345376cffb2ad9700..dec1fe31af7ab15bee947d4bea84b924d08f9c0f 100644 (file)
@@ -57,9 +57,9 @@ void zebra_ptm_write (struct vty *vty);
 int zebra_ptm_get_enable_state(void);
 
 int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
-                                  int command, vrf_id_t vrf_id);
+                                  int command, struct zebra_vrf *zvrf);
 int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock,
-                                  u_short length, vrf_id_t vrf_id);
+                                  u_short length, struct zebra_vrf *zvrf);
 void
 zebra_ptm_show_status(struct vty *vty, struct interface *ifp);
 int zebra_ptm_bfd_client_register (struct zserv *client, int sock,
index da66ba4bba88ec47ffe07050bcad4289f8c9eb66..6db922e4a69c09e46650b9693677b638e315c3ff 100644 (file)
@@ -876,7 +876,7 @@ zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr,
 /* Nexthop register */
 static int
 zserv_rnh_register (struct zserv *client, int sock, u_short length,
-                   rnh_type_t type, vrf_id_t vrf_id)
+                   rnh_type_t type, struct zebra_vrf *zvrf)
 {
   struct rnh *rnh;
   struct stream *s;
@@ -915,7 +915,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
                   p.family);
          return -1;
        }
-      rnh = zebra_add_rnh(&p, vrf_id, type);
+      rnh = zebra_add_rnh(&p, zvrf->vrf_id, type);
       if (type == RNH_NEXTHOP_TYPE)
        {
          if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
@@ -931,9 +931,9 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
            UNSET_FLAG(rnh->flags, ZEBRA_NHT_EXACT_MATCH);
        }
 
-      zebra_add_rnh_client(rnh, client, type, vrf_id);
+      zebra_add_rnh_client(rnh, client, type, zvrf->vrf_id);
       /* Anything not AF_INET/INET6 has been filtered out above */
-      zebra_evaluate_rnh(vrf_id, p.family, 1, type, &p);
+      zebra_evaluate_rnh(zvrf->vrf_id, p.family, 1, type, &p);
     }
   return 0;
 }
@@ -941,7 +941,7 @@ zserv_rnh_register (struct zserv *client, int sock, u_short length,
 /* Nexthop register */
 static int
 zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
-                     rnh_type_t type, vrf_id_t vrf_id)
+                     rnh_type_t type, struct zebra_vrf *zvrf)
 {
   struct rnh *rnh;
   struct stream *s;
@@ -976,7 +976,7 @@ zserv_rnh_unregister (struct zserv *client, int sock, u_short length,
                   p.family);
          return -1;
        }
-      rnh = zebra_lookup_rnh(&p, vrf_id, type);
+      rnh = zebra_lookup_rnh(&p, zvrf->vrf_id, type);
       if (rnh)
        {
          client->nh_dereg_time = quagga_time(NULL);
@@ -1082,15 +1082,15 @@ zsend_router_id_update (struct zserv *client, struct prefix *p,
 /* Register zebra server interface information.  Send current all
    interface and address information. */
 static int
-zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_interface_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   struct listnode *ifnode, *ifnnode;
   struct interface *ifp;
 
   /* Interface information is needed. */
-  vrf_bitmap_set (client->ifinfo, vrf_id);
+  vrf_bitmap_set (client->ifinfo, zvrf->vrf_id);
 
-  for (ALL_LIST_ELEMENTS (vrf_iflist (vrf_id), ifnode, ifnnode, ifp))
+  for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), ifnode, ifnnode, ifp))
     {
       /* Skip pseudo interface. */
       if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
@@ -1107,9 +1107,9 @@ zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
 
 /* Unregister zebra server interface information. */
 static int
-zread_interface_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_interface_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
-  vrf_bitmap_unset (client->ifinfo, vrf_id);
+  vrf_bitmap_unset (client->ifinfo, zvrf->vrf_id);
   return 0;
 }
 
@@ -1131,7 +1131,7 @@ zserv_nexthop_num_warn (const char *caller, const struct prefix *p, const u_char
  * add kernel route. 
  */
 static int
-zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_ipv4_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   struct rib *rib;
@@ -1166,7 +1166,7 @@ zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
 
   /* VRF ID */
-  rib->vrf_id = vrf_id;
+  rib->vrf_id = zvrf->vrf_id;
 
   /* Nexthop parse. */
   if (CHECK_FLAG (message, ZAPI_MESSAGE_NEXTHOP))
@@ -1218,18 +1218,8 @@ zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
     rib->tag = 0;
 
   /* Table */
-  if (vrf_id)
-    {
-      struct zebra_vrf *zvrf;
+  rib->table = zvrf->table_id;
 
-      zvrf = vrf_info_lookup (vrf_id);
-      if (zvrf)
-        rib->table = zvrf->table_id;
-    }
-  else
-    {
-      rib->table=zebrad.rtm_table_default;
-    }
   ret = rib_add_ipv4_multipath (&p, rib, safi);
 
   /* Stats */
@@ -1242,7 +1232,7 @@ zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
 
 /* Zebra server IPv4 prefix delete function. */
 static int
-zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_ipv4_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   struct stream *s;
@@ -1253,8 +1243,6 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
   u_char nexthop_num;
   u_char nexthop_type;
   u_int32_t table_id;
-  
-  table_id = client->rtm_table;
 
   s = client->ibuf;
   ifindex = 0;
@@ -1322,21 +1310,10 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
   else
     api.tag = 0;
 
-  if (vrf_id)
-    {
-      struct zebra_vrf *zvrf;
-
-      zvrf = vrf_info_lookup (vrf_id);
-      if (zvrf)
-        table_id = zvrf->table_id;
-    }
-  else
-    {
-      table_id = client->rtm_table;
-    }
+  table_id = zvrf->table_id;
 
   rib_delete_ipv4 (api.type, api.instance, api.flags, &p, nexthop_p, ifindex,
-                  vrf_id, table_id, api.safi);
+                  zvrf->vrf_id, table_id, api.safi);
   client->v4_route_del_cnt++;
   return 0;
 }
@@ -1344,7 +1321,7 @@ zread_ipv4_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
 /* Nexthop lookup for IPv4. */
 static int
 zread_ipv4_nexthop_lookup (struct zserv *client, u_short length,
-    vrf_id_t vrf_id)
+                          struct zebra_vrf *zvrf)
 {
   struct in_addr addr;
   char buf[BUFSIZ];
@@ -1353,13 +1330,13 @@ zread_ipv4_nexthop_lookup (struct zserv *client, u_short length,
   if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
     zlog_debug("%s: looking up %s", __func__,
                inet_ntop (AF_INET, &addr, buf, BUFSIZ));
-  return zsend_ipv4_nexthop_lookup (client, addr, vrf_id);
+  return zsend_ipv4_nexthop_lookup (client, addr, zvrf->vrf_id);
 }
 
 /* Nexthop lookup for IPv4. */
 static int
 zread_ipv4_import_lookup (struct zserv *client, u_short length,
-    vrf_id_t vrf_id)
+                         struct zebra_vrf *zvrf)
 {
   struct prefix_ipv4 p;
 
@@ -1367,13 +1344,12 @@ zread_ipv4_import_lookup (struct zserv *client, u_short length,
   p.prefixlen = stream_getc (client->ibuf);
   p.prefix.s_addr = stream_get_ipv4 (client->ibuf);
 
-  return zsend_ipv4_import_lookup (client, &p, vrf_id);
+  return zsend_ipv4_import_lookup (client, &p, zvrf->vrf_id);
 }
 
-#ifdef HAVE_IPV6
 /* Zebra server IPv6 prefix add function. */
 static int
-zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   struct stream *s;
@@ -1413,7 +1389,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, vrf_id_
   stream_get (&p.prefix, s, PSIZE (p.prefixlen));
 
   /* VRF ID */
-  rib->vrf_id = vrf_id;
+  rib->vrf_id = zvrf->vrf_id;
 
   /* We need to give nh-addr, nh-ifindex with the same next-hop object
    * to the rib to ensure that IPv6 multipathing works; need to coalesce
@@ -1484,18 +1460,8 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, vrf_id_
     rib->tag = 0;
 
   /* Table */
-  if (vrf_id)
-    {
-      struct zebra_vrf *zvrf;
+  rib->table = zvrf->table_id;
 
-      zvrf = vrf_info_lookup (vrf_id);
-      if (zvrf)
-        rib->table = zvrf->table_id;
-    }
-  else
-    {
-      rib->table=zebrad.rtm_table_default;
-    }
   ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex);
   /* Stats */
   if (ret > 0)
@@ -1507,7 +1473,7 @@ zread_ipv4_route_ipv6_nexthop_add (struct zserv *client, u_short length, vrf_id_
 }
 
 static int
-zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_ipv6_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   struct stream *s;
@@ -1612,21 +1578,9 @@ zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
     rib->tag = 0;
 
   /* VRF ID */
-  rib->vrf_id = vrf_id;
+  rib->vrf_id = zvrf->vrf_id;
+  rib->table = zvrf->table_id;
 
-  /* Table */
-  if (vrf_id)
-    {
-      struct zebra_vrf *zvrf;
-
-      zvrf = vrf_info_lookup (vrf_id);
-      if (zvrf)
-        rib->table = zvrf->table_id;
-    }
-  else
-    {
-      rib->table=zebrad.rtm_table_default;
-    }
   ret = rib_add_ipv6_multipath ((struct prefix *)&p, rib, safi, ifindex);
   /* Stats */
   if (ret > 0)
@@ -1639,7 +1593,7 @@ zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
 
 /* Zebra server IPv6 prefix delete function. */
 static int
-zread_ipv6_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_ipv6_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   struct stream *s;
@@ -1707,10 +1661,10 @@ zread_ipv6_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
 
   if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
     rib_delete_ipv6 (api.type, api.instance, api.flags, &p, NULL, ifindex,
-                     vrf_id, client->rtm_table, api.safi);
+                     zvrf->vrf_id, client->rtm_table, api.safi);
   else
     rib_delete_ipv6 (api.type, api.instance, api.flags, &p, &nexthop, ifindex,
-                     vrf_id, client->rtm_table, api.safi);
+                     zvrf->vrf_id, client->rtm_table, api.safi);
 
   client->v6_route_del_cnt++;
   return 0;
@@ -1718,7 +1672,7 @@ zread_ipv6_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
 
 static int
 zread_ipv6_nexthop_lookup (struct zserv *client, u_short length,
-    vrf_id_t vrf_id)
+                          struct zebra_vrf *zvrf)
 {
   struct in6_addr addr;
   char buf[BUFSIZ];
@@ -1728,29 +1682,28 @@ zread_ipv6_nexthop_lookup (struct zserv *client, u_short length,
     zlog_debug("%s: looking up %s", __func__,
                inet_ntop (AF_INET6, &addr, buf, BUFSIZ));
 
-  return zsend_ipv6_nexthop_lookup (client, &addr, vrf_id);
+  return zsend_ipv6_nexthop_lookup (client, &addr, zvrf->vrf_id);
 }
-#endif /* HAVE_IPV6 */
 
 /* Register zebra server router-id information.  Send current router-id */
 static int
-zread_router_id_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_router_id_add (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   struct prefix p;
 
   /* Router-id information is needed. */
-  vrf_bitmap_set (client->ridinfo, vrf_id);
+  vrf_bitmap_set (client->ridinfo, zvrf->vrf_id);
 
-  router_id_get (&p, vrf_id);
+  router_id_get (&p, zvrf->vrf_id);
 
-  return zsend_router_id_update (client, &p, vrf_id);
+  return zsend_router_id_update (client, &p, zvrf->vrf_id);
 }
 
 /* Unregister zebra server router-id information. */
 static int
-zread_router_id_delete (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_router_id_delete (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
-  vrf_bitmap_unset (client->ridinfo, vrf_id);
+  vrf_bitmap_unset (client->ridinfo, zvrf->vrf_id);
   return 0;
 }
 
@@ -1781,17 +1734,17 @@ zread_hello (struct zserv *client)
 
 /* Unregister all information in a VRF. */
 static int
-zread_vrf_unregister (struct zserv *client, u_short length, vrf_id_t vrf_id)
+zread_vrf_unregister (struct zserv *client, u_short length, struct zebra_vrf *zvrf)
 {
   int i;
   afi_t afi;
 
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
-      vrf_bitmap_unset (client->redist[afi][i], vrf_id);
-  vrf_bitmap_unset (client->redist_default, vrf_id);
-  vrf_bitmap_unset (client->ifinfo, vrf_id);
-  vrf_bitmap_unset (client->ridinfo, vrf_id);
+      vrf_bitmap_unset (client->redist[afi][i], zvrf->vrf_id);
+  vrf_bitmap_unset (client->redist_default, zvrf->vrf_id);
+  vrf_bitmap_unset (client->ifinfo, zvrf->vrf_id);
+  vrf_bitmap_unset (client->ridinfo, zvrf->vrf_id);
 
   return 0;
 }
@@ -1902,6 +1855,7 @@ zebra_client_read (struct thread *thread)
   uint16_t length, command;
   uint8_t marker, version;
   vrf_id_t vrf_id;
+  struct zebra_vrf *zvrf;
 
   /* Get thread data.  Reset reading thread because I'm running. */
   sock = THREAD_FD (thread);
@@ -2002,84 +1956,88 @@ zebra_client_read (struct thread *thread)
   client->last_read_time = quagga_time(NULL);
   client->last_read_cmd = command;
 
+  zvrf = zebra_vrf_lookup (vrf_id);
+  if (!zvrf)
+    {
+      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+        zlog_debug ("zebra received unknown VRF[%u]", vrf_id);
+      goto zclient_read_out;
+    }
+
   switch (command) 
     {
     case ZEBRA_ROUTER_ID_ADD:
-      zread_router_id_add (client, length, vrf_id);
+      zread_router_id_add (client, length, zvrf);
       break;
     case ZEBRA_ROUTER_ID_DELETE:
-      zread_router_id_delete (client, length, vrf_id);
+      zread_router_id_delete (client, length, zvrf);
       break;
     case ZEBRA_INTERFACE_ADD:
-      zread_interface_add (client, length, vrf_id);
+      zread_interface_add (client, length, zvrf);
       break;
     case ZEBRA_INTERFACE_DELETE:
-      zread_interface_delete (client, length, vrf_id);
+      zread_interface_delete (client, length, zvrf);
       break;
     case ZEBRA_IPV4_ROUTE_ADD:
-      zread_ipv4_add (client, length, vrf_id);
+      zread_ipv4_add (client, length, zvrf);
       break;
     case ZEBRA_IPV4_ROUTE_DELETE:
-      zread_ipv4_delete (client, length, vrf_id);
+      zread_ipv4_delete (client, length, zvrf);
       break;
-#ifdef HAVE_IPV6
     case ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD:
-      zread_ipv4_route_ipv6_nexthop_add (client, length, vrf_id);
+      zread_ipv4_route_ipv6_nexthop_add (client, length, zvrf);
       break;
     case ZEBRA_IPV6_ROUTE_ADD:
-      zread_ipv6_add (client, length, vrf_id);
+      zread_ipv6_add (client, length, zvrf);
       break;
     case ZEBRA_IPV6_ROUTE_DELETE:
-      zread_ipv6_delete (client, length, vrf_id);
+      zread_ipv6_delete (client, length, zvrf);
       break;
-#endif /* HAVE_IPV6 */
     case ZEBRA_REDISTRIBUTE_ADD:
-      zebra_redistribute_add (command, client, length, vrf_id);
+      zebra_redistribute_add (command, client, length, zvrf);
       break;
     case ZEBRA_REDISTRIBUTE_DELETE:
-      zebra_redistribute_delete (command, client, length, vrf_id);
+      zebra_redistribute_delete (command, client, length, zvrf);
       break;
     case ZEBRA_REDISTRIBUTE_DEFAULT_ADD:
-      zebra_redistribute_default_add (command, client, length, vrf_id);
+      zebra_redistribute_default_add (command, client, length, zvrf);
       break;
     case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE:
-      zebra_redistribute_default_delete (command, client, length, vrf_id);
+      zebra_redistribute_default_delete (command, client, length, zvrf);
       break;
     case ZEBRA_IPV4_NEXTHOP_LOOKUP:
-      zread_ipv4_nexthop_lookup (client, length, vrf_id);
+      zread_ipv4_nexthop_lookup (client, length, zvrf);
       break;
-#ifdef HAVE_IPV6
     case ZEBRA_IPV6_NEXTHOP_LOOKUP:
-      zread_ipv6_nexthop_lookup (client, length, vrf_id);
+      zread_ipv6_nexthop_lookup (client, length, zvrf);
       break;
-#endif /* HAVE_IPV6 */
     case ZEBRA_IPV4_IMPORT_LOOKUP:
-      zread_ipv4_import_lookup (client, length, vrf_id);
+      zread_ipv4_import_lookup (client, length, zvrf);
       break;
     case ZEBRA_HELLO:
       zread_hello (client);
       break;
     case ZEBRA_NEXTHOP_REGISTER:
-      zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, vrf_id);
+      zserv_rnh_register(client, sock, length, RNH_NEXTHOP_TYPE, zvrf);
       break;
     case ZEBRA_NEXTHOP_UNREGISTER:
-      zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, vrf_id);
+      zserv_rnh_unregister(client, sock, length, RNH_NEXTHOP_TYPE, zvrf);
       break;
     case ZEBRA_IMPORT_ROUTE_REGISTER:
-      zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id);
+      zserv_rnh_register(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf);
       break;
     case ZEBRA_IMPORT_ROUTE_UNREGISTER:
-      zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, vrf_id);
+      zserv_rnh_unregister(client, sock, length, RNH_IMPORT_CHECK_TYPE, zvrf);
       break;
     case ZEBRA_BFD_DEST_UPDATE:
     case ZEBRA_BFD_DEST_REGISTER:
-      zebra_ptm_bfd_dst_register(client, sock, length, command, vrf_id);
+      zebra_ptm_bfd_dst_register(client, sock, length, command, zvrf);
       break;
     case ZEBRA_BFD_DEST_DEREGISTER:
-      zebra_ptm_bfd_dst_deregister(client, sock, length, vrf_id);
+      zebra_ptm_bfd_dst_deregister(client, sock, length, zvrf);
       break;
     case ZEBRA_VRF_UNREGISTER:
-      zread_vrf_unregister (client, length, vrf_id);
+      zread_vrf_unregister (client, length, zvrf);
       break;
     case ZEBRA_BFD_CLIENT_REGISTER:
       zebra_ptm_bfd_client_register(client, sock, length);
@@ -2096,6 +2054,7 @@ zebra_client_read (struct thread *thread)
       return -1;
     }
 
+ zclient_read_out:
   stream_reset (client->ibuf);
   zebra_event (ZEBRA_READ, sock, client);
   return 0;