zserv: get rid of code duplication in nexthop_lookup[_mrib] functions

z[send/read]_ipv4_nexthop_lookup functions have been duplicated for multicast mrib lookup. The mrib versions are identical to the unicast versions except for a couple of places. The differences do not justify duplicating two functions and 80 lines of codes. Code refactoring and an if statement with a few lines of code are enough to handle the differences with a lot less and cleaner code.

Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com>
Tested-by: NetDEF CI System <cisystem@netdef.org>
diff --git a/zebra/zserv.c b/zebra/zserv.c
index f0e8d12..2c0c5b4 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -585,6 +585,7 @@
 	      }
 	    num++;
 	  }
+
       stream_putc_at (s, nump, num);
     }
   else
@@ -599,9 +600,14 @@
 }
 #endif /* HAVE_IPV6 */
 
+/*
+  In the case of ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
+    query unicast rib if nexthop is not found on mrib
+    and return both route metric and protocol distance.
+*/
 static int
 zsend_ipv4_nexthop_lookup (struct zserv *client, struct in_addr addr,
-    vrf_id_t vrf_id)
+			   int cmd, vrf_id_t vrf_id)
 {
   struct stream *s;
   struct rib *rib;
@@ -609,94 +615,34 @@
   u_char num;
   struct nexthop *nexthop;
 
-  /* Lookup nexthop - eBGP excluded */
-  rib = rib_match_ipv4_safi (addr, SAFI_UNICAST, 1, NULL, vrf_id);
-
   /* Get output stream. */
   s = client->obuf;
   stream_reset (s);
 
   /* Fill in result. */
-  zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP, vrf_id);
+  zserv_create_header (s, cmd, vrf_id);
   stream_put_in_addr (s, &addr);
 
+  /* Lookup nexthop - eBGP excluded */
+  if (cmd == ZEBRA_IPV4_NEXTHOP_LOOKUP)
+    rib = rib_match_ipv4_safi (addr, SAFI_UNICAST, 1, NULL, vrf_id);
+  else  /* ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB */
+    {
+      rib = rib_match_ipv4_multicast (addr, NULL, vrf_id);
+      /* handle the distance field here since
+       * it is only needed for MRIB command */
+      if (rib)
+	stream_putc (s, rib->distance);
+      else
+        stream_putc (s, 0); /* distance */
+    }
+
   if (rib)
     {
       if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
         zlog_debug("%s: Matching rib entry found.", __func__);
       stream_putl (s, rib->metric);
       num = 0;
-      nump = stream_get_endp(s);
-      stream_putc (s, 0);
-      /* Only non-recursive routes are elegible to resolve the nexthop we
-       * are looking up. Therefore, we will just iterate over the top
-       * chain of nexthops. */
-      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
-	if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
-	  {
-	    stream_putc (s, nexthop->type);
-	    switch (nexthop->type)
-	      {
-	      case ZEBRA_NEXTHOP_IPV4:
-		stream_put_in_addr (s, &nexthop->gate.ipv4);
-		break;
-	      case ZEBRA_NEXTHOP_IPV4_IFINDEX:
-		stream_put_in_addr (s, &nexthop->gate.ipv4);
-		stream_putl (s, nexthop->ifindex);
-		break;
-	      case ZEBRA_NEXTHOP_IFINDEX:
-	      case ZEBRA_NEXTHOP_IFNAME:
-		stream_putl (s, nexthop->ifindex);
-		break;
-	      default:
-                /* do nothing */
-		break;
-	      }
-	    num++;
-	  }
-      stream_putc_at (s, nump, num);
-    }
-  else
-    {
-      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
-        zlog_debug("%s: No matching rib entry found.", __func__);
-      stream_putl (s, 0);
-      stream_putc (s, 0);
-    }
-
-  stream_putw_at (s, 0, stream_get_endp (s));
-  
-  return zebra_server_send_message(client);
-}
-
-/*
-  Modified version of zsend_ipv4_nexthop_lookup():
-  Query unicast rib if nexthop is not found on mrib.
-  Returns both route metric and protocol distance.
-*/
-static int
-zsend_ipv4_nexthop_lookup_mrib (struct zserv *client, struct in_addr addr,
-				struct rib *rib)
-{
-  struct stream *s;
-  unsigned long nump;
-  u_char num;
-  struct nexthop *nexthop;
-
-  /* Get output stream. */
-  s = client->obuf;
-  stream_reset (s);
-
-  /* Fill in result. */
-  zserv_create_header (s, ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB, 
-		       rib ? rib->vrf_id : VRF_DEFAULT);
-  stream_put_in_addr (s, &addr);
-
-  if (rib)
-    {
-      stream_putc (s, rib->distance);
-      stream_putl (s, rib->metric);
-      num = 0;
       nump = stream_get_endp(s); /* remember position for nexthop_num */
       stream_putc (s, 0);        /* reserve room for nexthop_num */
       /* Only non-recursive routes are elegible to resolve the nexthop we
@@ -725,12 +671,13 @@
 	      }
 	    num++;
 	  }
-    
+
       stream_putc_at (s, nump, num); /* store nexthop_num */
     }
   else
     {
-      stream_putc (s, 0); /* distance */
+      if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV)
+        zlog_debug("%s: No matching rib entry found.", __func__);
       stream_putl (s, 0); /* metric */
       stream_putc (s, 0); /* nexthop_num */
     }
@@ -1143,7 +1090,7 @@
 
 /* Nexthop lookup for IPv4. */
 static int
-zread_ipv4_nexthop_lookup (struct zserv *client, u_short length,
+zread_ipv4_nexthop_lookup (int cmd, struct zserv *client, u_short length,
     vrf_id_t vrf_id)
 {
   struct in_addr addr;
@@ -1153,20 +1100,8 @@
   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);
-}
 
-/* MRIB Nexthop lookup for IPv4. */
-static int
-zread_ipv4_nexthop_lookup_mrib (struct zserv *client, u_short length,
-    vrf_id_t vrf_id)
-{
-  struct in_addr addr;
-  struct rib *rib;
-
-  addr.s_addr = stream_get_ipv4 (client->ibuf);
-  rib = rib_match_ipv4_multicast (addr, NULL, vrf_id);
-  return zsend_ipv4_nexthop_lookup_mrib (client, addr, rib);
+  return zsend_ipv4_nexthop_lookup (client, addr, cmd, vrf_id);
 }
 
 /* Nexthop lookup for IPv4. */
@@ -1695,10 +1630,8 @@
       zebra_redistribute_default_delete (command, client, length, vrf_id);
       break;
     case ZEBRA_IPV4_NEXTHOP_LOOKUP:
-      zread_ipv4_nexthop_lookup (client, length, vrf_id);
-      break;
     case ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB:
-      zread_ipv4_nexthop_lookup_mrib (client, length, vrf_id);
+      zread_ipv4_nexthop_lookup (command, client, length, vrf_id);
       break;
 #ifdef HAVE_IPV6
     case ZEBRA_IPV6_NEXTHOP_LOOKUP: