]> git.proxmox.com Git - mirror_frr.git/blobdiff - ripd/ripd.c
Merge pull request #1677 from chiragshah6/ospfv3_dev
[mirror_frr.git] / ripd / ripd.c
index 780efcc9442a62b6cf3823f1c1479cf712f242b7..b5cbc96bc35bb595f4c5cbf0f2c972ca309f2e54 100644 (file)
@@ -49,9 +49,6 @@ DEFINE_QOBJ_TYPE(rip)
 /* UDP receive buffer size */
 #define RIP_UDP_RCV_BUF 41600
 
-/* privileges global */
-extern struct zebra_privs_t ripd_privs;
-
 /* RIP Structure. */
 struct rip *rip = NULL;
 
@@ -65,187 +62,170 @@ long rip_global_route_changes = 0;
 long rip_global_queries = 0;
 
 /* Prototypes. */
-static void rip_event (enum rip_event, int);
-static void rip_output_process (struct connected *, struct sockaddr_in *, int, u_char);
-static int rip_triggered_update (struct thread *);
-static int rip_update_jitter (unsigned long);
+static void rip_event(enum rip_event, int);
+static void rip_output_process(struct connected *, struct sockaddr_in *, int,
+                              u_char);
+static int rip_triggered_update(struct thread *);
+static int rip_update_jitter(unsigned long);
 
 /* RIP output routes type. */
-enum
-{
-  rip_all_route,
-  rip_changed_route
-};
+enum { rip_all_route, rip_changed_route };
 
 /* RIP command strings. */
-static const struct message rip_msg[] =
-{
-  {RIP_REQUEST,    "REQUEST"},
-  {RIP_RESPONSE,   "RESPONSE"},
-  {RIP_TRACEON,    "TRACEON"},
-  {RIP_TRACEOFF,   "TRACEOFF"},
-  {RIP_POLL,       "POLL"},
-  {RIP_POLL_ENTRY, "POLL ENTRY"},
-  { 0 }
-};
+static const struct message rip_msg[] = {{RIP_REQUEST, "REQUEST"},
+                                        {RIP_RESPONSE, "RESPONSE"},
+                                        {RIP_TRACEON, "TRACEON"},
+                                        {RIP_TRACEOFF, "TRACEOFF"},
+                                        {RIP_POLL, "POLL"},
+                                        {RIP_POLL_ENTRY, "POLL ENTRY"},
+                                        {0}};
 
 /* Utility function to set boradcast option to the socket. */
-static int
-sockopt_broadcast (int sock)
+static int sockopt_broadcast(int sock)
 {
-  int ret;
-  int on = 1;
+       int ret;
+       int on = 1;
 
-  ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);
-  if (ret < 0)
-    {
-      zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);
-      return -1;
-    }
-  return 0;
+       ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,
+                        sizeof on);
+       if (ret < 0) {
+               zlog_warn("can't set sockopt SO_BROADCAST to socket %d", sock);
+               return -1;
+       }
+       return 0;
 }
 
-static int
-rip_route_rte (struct rip_info *rinfo)
+static int rip_route_rte(struct rip_info *rinfo)
 {
-  return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);
+       return (rinfo->type == ZEBRA_ROUTE_RIP
+               && rinfo->sub_type == RIP_ROUTE_RTE);
 }
 
-static struct rip_info *
-rip_info_new (void)
+static struct rip_info *rip_info_new(void)
 {
-  return XCALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));
+       return XCALLOC(MTYPE_RIP_INFO, sizeof(struct rip_info));
 }
 
-void
-rip_info_free (struct rip_info *rinfo)
+void rip_info_free(struct rip_info *rinfo)
 {
-  XFREE (MTYPE_RIP_INFO, rinfo);
+       XFREE(MTYPE_RIP_INFO, rinfo);
 }
 
 /* RIP route garbage collect timer. */
-static int
-rip_garbage_collect (struct thread *t)
+static int rip_garbage_collect(struct thread *t)
 {
-  struct rip_info *rinfo;
-  struct route_node *rp;
+       struct rip_info *rinfo;
+       struct route_node *rp;
+
+       rinfo = THREAD_ARG(t);
+       rinfo->t_garbage_collect = NULL;
 
-  rinfo = THREAD_ARG (t);
-  rinfo->t_garbage_collect = NULL;
+       /* Off timeout timer. */
+       RIP_TIMER_OFF(rinfo->t_timeout);
 
-  /* Off timeout timer. */
-  RIP_TIMER_OFF (rinfo->t_timeout);
-  
-  /* Get route_node pointer. */
-  rp = rinfo->rp;
+       /* Get route_node pointer. */
+       rp = rinfo->rp;
 
-  /* Unlock route_node. */
-  listnode_delete (rp->info, rinfo);
-  if (list_isempty ((struct list *)rp->info))
-    {
-      list_free (rp->info);
-      rp->info = NULL;
-      route_unlock_node (rp);
-    }
+       /* Unlock route_node. */
+       listnode_delete(rp->info, rinfo);
+       if (list_isempty((struct list *)rp->info)) {
+               list_delete_and_null((struct list **)&rp->info);
+               route_unlock_node(rp);
+       }
 
-  /* Free RIP routing information. */
-  rip_info_free (rinfo);
+       /* Free RIP routing information. */
+       rip_info_free(rinfo);
 
-  return 0;
+       return 0;
 }
 
-static void rip_timeout_update (struct rip_info *rinfo);
+static void rip_timeout_update(struct rip_info *rinfo);
 
 /* Add new route to the ECMP list.
  * RETURN: the new entry added in the list, or NULL if it is not the first
  *         entry and ECMP is not allowed.
  */
-struct rip_info *
-rip_ecmp_add (struct rip_info *rinfo_new)
+struct rip_info *rip_ecmp_add(struct rip_info *rinfo_new)
 {
-  struct route_node *rp = rinfo_new->rp;
-  struct rip_info *rinfo = NULL;
-  struct list *list = NULL;
+       struct route_node *rp = rinfo_new->rp;
+       struct rip_info *rinfo = NULL;
+       struct list *list = NULL;
 
-  if (rp->info == NULL)
-    rp->info = list_new ();
-  list = (struct list *)rp->info;
+       if (rp->info == NULL)
+               rp->info = list_new();
+       list = (struct list *)rp->info;
 
-  /* If ECMP is not allowed and some entry already exists in the list,
-   * do nothing. */
-  if (listcount (list) && !rip->ecmp)
-    return NULL;
+       /* If ECMP is not allowed and some entry already exists in the list,
+        * do nothing. */
+       if (listcount(list) && !rip->ecmp)
+               return NULL;
 
-  rinfo = rip_info_new ();
-  memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
-  listnode_add (list, rinfo);
+       rinfo = rip_info_new();
+       memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
+       listnode_add(list, rinfo);
 
-  if (rip_route_rte (rinfo))
-    {
-      rip_timeout_update (rinfo);
-      rip_zebra_ipv4_add (rp);
-    }
+       if (rip_route_rte(rinfo)) {
+               rip_timeout_update(rinfo);
+               rip_zebra_ipv4_add(rp);
+       }
 
-  /* Set the route change flag on the first entry. */
-  rinfo = listgetdata (listhead (list));
-  SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
+       /* Set the route change flag on the first entry. */
+       rinfo = listgetdata(listhead(list));
+       SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
 
-  /* Signal the output process to trigger an update (see section 2.5). */
-  rip_event (RIP_TRIGGERED_UPDATE, 0);
+       /* Signal the output process to trigger an update (see section 2.5). */
+       rip_event(RIP_TRIGGERED_UPDATE, 0);
 
-  return rinfo;
+       return rinfo;
 }
 
 /* Replace the ECMP list with the new route.
  * RETURN: the new entry added in the list
  */
-struct rip_info *
-rip_ecmp_replace (struct rip_info *rinfo_new)
-{
-  struct route_node *rp = rinfo_new->rp;
-  struct list *list = (struct list *)rp->info;
-  struct rip_info *rinfo = NULL, *tmp_rinfo = NULL;
-  struct listnode *node = NULL, *nextnode = NULL;
-
-  if (list == NULL || listcount (list) == 0)
-    return rip_ecmp_add (rinfo_new);
-
-  /* Get the first entry */
-  rinfo = listgetdata (listhead (list));
-
-  /* Learnt route replaced by a local one. Delete it from zebra. */
-  if (rip_route_rte (rinfo) && !rip_route_rte (rinfo_new))
-    if (CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
-      rip_zebra_ipv4_delete (rp);
-
-  /* Re-use the first entry, and delete the others. */
-  for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
-    if (tmp_rinfo != rinfo)
-      {
-        RIP_TIMER_OFF (tmp_rinfo->t_timeout);
-        RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
-        list_delete_node (list, node);
-        rip_info_free (tmp_rinfo);
-      }
+struct rip_info *rip_ecmp_replace(struct rip_info *rinfo_new)
+{
+       struct route_node *rp = rinfo_new->rp;
+       struct list *list = (struct list *)rp->info;
+       struct rip_info *rinfo = NULL, *tmp_rinfo = NULL;
+       struct listnode *node = NULL, *nextnode = NULL;
+
+       if (list == NULL || listcount(list) == 0)
+               return rip_ecmp_add(rinfo_new);
+
+       /* Get the first entry */
+       rinfo = listgetdata(listhead(list));
+
+       /* Learnt route replaced by a local one. Delete it from zebra. */
+       if (rip_route_rte(rinfo) && !rip_route_rte(rinfo_new))
+               if (CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
+                       rip_zebra_ipv4_delete(rp);
+
+       /* Re-use the first entry, and delete the others. */
+       for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo))
+               if (tmp_rinfo != rinfo) {
+                       RIP_TIMER_OFF(tmp_rinfo->t_timeout);
+                       RIP_TIMER_OFF(tmp_rinfo->t_garbage_collect);
+                       list_delete_node(list, node);
+                       rip_info_free(tmp_rinfo);
+               }
 
-  RIP_TIMER_OFF (rinfo->t_timeout);
-  RIP_TIMER_OFF (rinfo->t_garbage_collect);
-  memcpy (rinfo, rinfo_new, sizeof (struct rip_info));
+       RIP_TIMER_OFF(rinfo->t_timeout);
+       RIP_TIMER_OFF(rinfo->t_garbage_collect);
+       memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
 
-  if (rip_route_rte (rinfo))
-    {
-      rip_timeout_update (rinfo);
-      /* The ADD message implies an update. */
-      rip_zebra_ipv4_add (rp);
-    }
+       if (rip_route_rte(rinfo)) {
+               rip_timeout_update(rinfo);
+               /* The ADD message implies an update. */
+               rip_zebra_ipv4_add(rp);
+       }
 
-  /* Set the route change flag. */
-  SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
+       /* Set the route change flag. */
+       SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
 
-  /* Signal the output process to trigger an update (see section 2.5). */
-  rip_event (RIP_TRIGGERED_UPDATE, 0);
+       /* Signal the output process to trigger an update (see section 2.5). */
+       rip_event(RIP_TRIGGERED_UPDATE, 0);
 
-  return rinfo;
+       return rinfo;
 }
 
 /* Delete one route from the ECMP list.
@@ -254,692 +234,696 @@ rip_ecmp_replace (struct rip_info *rinfo_new)
  *  the entry - the entry is the last one in the list; its metric is set
  *              to INFINITY, and the garbage collector is started for it
  */
-struct rip_info *
-rip_ecmp_delete (struct rip_info *rinfo)
-{
-  struct route_node *rp = rinfo->rp;
-  struct list *list = (struct list *)rp->info;
-
-  RIP_TIMER_OFF (rinfo->t_timeout);
-
-  if (listcount (list) > 1)
-    {
-      /* Some other ECMP entries still exist. Just delete this entry. */
-      RIP_TIMER_OFF (rinfo->t_garbage_collect);
-      listnode_delete (list, rinfo);
-      if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
-        /* The ADD message implies the update. */
-        rip_zebra_ipv4_add (rp);
-      rip_info_free (rinfo);
-      rinfo = NULL;
-    }
-  else
-    {
-      assert (rinfo == listgetdata (listhead (list)));
-
-      /* This is the only entry left in the list. We must keep it in
-       * the list for garbage collection time, with INFINITY metric. */
-
-      rinfo->metric = RIP_METRIC_INFINITY;
-      RIP_TIMER_ON (rinfo->t_garbage_collect,
-                    rip_garbage_collect, rip->garbage_time);
-
-      if (rip_route_rte (rinfo) && CHECK_FLAG (rinfo->flags, RIP_RTF_FIB))
-        rip_zebra_ipv4_delete (rp);
-    }
+struct rip_info *rip_ecmp_delete(struct rip_info *rinfo)
+{
+       struct route_node *rp = rinfo->rp;
+       struct list *list = (struct list *)rp->info;
+
+       RIP_TIMER_OFF(rinfo->t_timeout);
+
+       if (listcount(list) > 1) {
+               /* Some other ECMP entries still exist. Just delete this entry.
+                */
+               RIP_TIMER_OFF(rinfo->t_garbage_collect);
+               listnode_delete(list, rinfo);
+               if (rip_route_rte(rinfo)
+                   && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
+                       /* The ADD message implies the update. */
+                       rip_zebra_ipv4_add(rp);
+               rip_info_free(rinfo);
+               rinfo = NULL;
+       } else {
+               assert(rinfo == listgetdata(listhead(list)));
+
+               /* This is the only entry left in the list. We must keep it in
+                * the list for garbage collection time, with INFINITY metric.
+                */
+
+               rinfo->metric = RIP_METRIC_INFINITY;
+               RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect,
+                            rip->garbage_time);
+
+               if (rip_route_rte(rinfo)
+                   && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
+                       rip_zebra_ipv4_delete(rp);
+       }
 
-  /* Set the route change flag on the first entry. */
-  rinfo = listgetdata (listhead (list));
-  SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
+       /* Set the route change flag on the first entry. */
+       rinfo = listgetdata(listhead(list));
+       SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
 
-  /* Signal the output process to trigger an update (see section 2.5). */
-  rip_event (RIP_TRIGGERED_UPDATE, 0);
+       /* Signal the output process to trigger an update (see section 2.5). */
+       rip_event(RIP_TRIGGERED_UPDATE, 0);
 
-  return rinfo;
+       return rinfo;
 }
 
 /* Timeout RIP routes. */
-static int
-rip_timeout (struct thread *t)
+static int rip_timeout(struct thread *t)
+{
+       rip_ecmp_delete((struct rip_info *)THREAD_ARG(t));
+       return 0;
+}
+
+static void rip_timeout_update(struct rip_info *rinfo)
 {
-  rip_ecmp_delete ((struct rip_info *)THREAD_ARG (t));
-  return 0;
+       if (rinfo->metric != RIP_METRIC_INFINITY) {
+               RIP_TIMER_OFF(rinfo->t_timeout);
+               RIP_TIMER_ON(rinfo->t_timeout, rip_timeout, rip->timeout_time);
+       }
 }
 
-static void
-rip_timeout_update (struct rip_info *rinfo)
-{
-  if (rinfo->metric != RIP_METRIC_INFINITY)
-    {
-      RIP_TIMER_OFF (rinfo->t_timeout);
-      RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);
-    }
-}
-
-static int
-rip_filter (int rip_distribute, struct prefix_ipv4 *p, struct rip_interface *ri)
-{
-  struct distribute *dist;
-  struct access_list *alist;
-  struct prefix_list *plist;
-  int distribute = rip_distribute == RIP_FILTER_OUT ?
-      DISTRIBUTE_V4_OUT : DISTRIBUTE_V4_IN;
-  const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in";
-
-  /* Input distribute-list filtering. */
-  if (ri->list[rip_distribute])
-    {
-      if (access_list_apply (ri->list[rip_distribute],
-                            (struct prefix *) p) == FILTER_DENY)
-       {
-         if (IS_RIP_DEBUG_PACKET)
-           zlog_debug ("%s/%d filtered by distribute %s",
-                        inet_ntoa (p->prefix), p->prefixlen, inout);
-                 return -1;
+static int rip_filter(int rip_distribute, struct prefix_ipv4 *p,
+                     struct rip_interface *ri)
+{
+       struct distribute *dist;
+       struct access_list *alist;
+       struct prefix_list *plist;
+       int distribute = rip_distribute == RIP_FILTER_OUT ? DISTRIBUTE_V4_OUT
+                                                         : DISTRIBUTE_V4_IN;
+       const char *inout = rip_distribute == RIP_FILTER_OUT ? "out" : "in";
+
+       /* Input distribute-list filtering. */
+       if (ri->list[rip_distribute]) {
+               if (access_list_apply(ri->list[rip_distribute],
+                                     (struct prefix *)p)
+                   == FILTER_DENY) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug("%s/%d filtered by distribute %s",
+                                          inet_ntoa(p->prefix), p->prefixlen,
+                                          inout);
+                       return -1;
                }
-           }
-  if (ri->prefix[rip_distribute])
-{
-      if (prefix_list_apply (ri->prefix[rip_distribute],
-                            (struct prefix *) p) == PREFIX_DENY)
-       {
-         if (IS_RIP_DEBUG_PACKET)
-           zlog_debug ("%s/%d filtered by prefix-list %s",
-                        inet_ntoa (p->prefix), p->prefixlen, inout);
-         return -1;
-       }
-    }
-
-  /* All interface filter check. */
-  dist = distribute_lookup (NULL);
-  if (dist)
-    {
-      if (dist->list[distribute])
-       {
-         alist = access_list_lookup (AFI_IP, dist->list[distribute]);
-           
-         if (alist)
-           {
-             if (access_list_apply (alist, (struct prefix *) p) == FILTER_DENY)
-               {
-                 if (IS_RIP_DEBUG_PACKET)
-                   zlog_debug ("%s/%d filtered by distribute %s",
-                                inet_ntoa (p->prefix), p->prefixlen, inout);
-                 return -1;
+       }
+       if (ri->prefix[rip_distribute]) {
+               if (prefix_list_apply(ri->prefix[rip_distribute],
+                                     (struct prefix *)p)
+                   == PREFIX_DENY) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug("%s/%d filtered by prefix-list %s",
+                                          inet_ntoa(p->prefix), p->prefixlen,
+                                          inout);
+                       return -1;
                }
-           }
        }
-      if (dist->prefix[distribute])
-       {
-         plist = prefix_list_lookup (AFI_IP, dist->prefix[distribute]);
-         
-         if (plist)
-           {
-             if (prefix_list_apply (plist,
-                                    (struct prefix *) p) == PREFIX_DENY)
-               {
-                 if (IS_RIP_DEBUG_PACKET)
-                   zlog_debug ("%s/%d filtered by prefix-list %s",
-                                inet_ntoa (p->prefix), p->prefixlen, inout);
-                 return -1;
+
+       /* All interface filter check. */
+       dist = distribute_lookup(NULL);
+       if (dist) {
+               if (dist->list[distribute]) {
+                       alist = access_list_lookup(AFI_IP,
+                                                  dist->list[distribute]);
+
+                       if (alist) {
+                               if (access_list_apply(alist, (struct prefix *)p)
+                                   == FILTER_DENY) {
+                                       if (IS_RIP_DEBUG_PACKET)
+                                               zlog_debug(
+                                                       "%s/%d filtered by distribute %s",
+                                                       inet_ntoa(p->prefix),
+                                                       p->prefixlen, inout);
+                                       return -1;
+                               }
+                       }
+               }
+               if (dist->prefix[distribute]) {
+                       plist = prefix_list_lookup(AFI_IP,
+                                                  dist->prefix[distribute]);
+
+                       if (plist) {
+                               if (prefix_list_apply(plist, (struct prefix *)p)
+                                   == PREFIX_DENY) {
+                                       if (IS_RIP_DEBUG_PACKET)
+                                               zlog_debug(
+                                                       "%s/%d filtered by prefix-list %s",
+                                                       inet_ntoa(p->prefix),
+                                                       p->prefixlen, inout);
+                                       return -1;
+                               }
+                       }
                }
-           }
        }
-    }
-  return 0;
+       return 0;
 }
 
 /* Check nexthop address validity. */
-static int
-rip_nexthop_check (struct in_addr *addr)
+static int rip_nexthop_check(struct in_addr *addr)
 {
-  struct listnode *node;
-  struct listnode *cnode;
-  struct interface *ifp;
-  struct connected *ifc;
-  struct prefix *p;
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct interface *ifp;
+       struct listnode *cnode;
+       struct connected *ifc;
+       struct prefix *p;
 
-  /* If nexthop address matches local configured address then it is
-     invalid nexthop. */
+       /* If nexthop address matches local configured address then it is
+          invalid nexthop. */
 
-  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
-    {
-      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
-       {           
-         p = ifc->address;
+       FOR_ALL_INTERFACES (vrf, ifp) {
+               for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
+                       p = ifc->address;
 
-         if (p->family == AF_INET
-             && IPV4_ADDR_SAME (&p->u.prefix4, addr))
-           return -1;
+                       if (p->family == AF_INET
+                           && IPV4_ADDR_SAME(&p->u.prefix4, addr))
+                               return -1;
+               }
        }
-    }
-  return 0;
+       return 0;
 }
 
 /* RIP add route to routing table. */
-static void
-rip_rte_process (struct rte *rte, struct sockaddr_in *from,
-                 struct interface *ifp)
-{
-  int ret;
-  struct prefix_ipv4 p;
-  struct route_node *rp;
-  struct rip_info *rinfo = NULL, newinfo;
-  struct rip_interface *ri;
-  struct in_addr *nexthop;
-  int same = 0;
-  unsigned char old_dist, new_dist;
-  struct list *list = NULL;
-  struct listnode *node = NULL;
-
-  /* Make prefix structure. */
-  memset (&p, 0, sizeof (struct prefix_ipv4));
-  p.family = AF_INET;
-  p.prefix = rte->prefix;
-  p.prefixlen = ip_masklen (rte->mask);
-
-  /* Make sure mask is applied. */
-  apply_mask_ipv4 (&p);
-
-  /* Apply input filters. */
-  ri = ifp->info;
-
-  ret = rip_filter (RIP_FILTER_IN, &p, ri);
-  if (ret < 0)
-    return;
-
-  memset (&newinfo, 0, sizeof (newinfo));
-  newinfo.type = ZEBRA_ROUTE_RIP;
-  newinfo.sub_type = RIP_ROUTE_RTE;
-  newinfo.nexthop = rte->nexthop;
-  newinfo.from = from->sin_addr;
-  newinfo.ifindex = ifp->ifindex;
-  newinfo.metric = rte->metric;
-  newinfo.metric_out = rte->metric; /* XXX */
-  newinfo.tag = ntohs (rte->tag);   /* XXX */
-
-  /* Modify entry according to the interface routemap. */
-  if (ri->routemap[RIP_FILTER_IN])
-    {
-      int ret;
-
-      /* The object should be of the type of rip_info */
-      ret = route_map_apply (ri->routemap[RIP_FILTER_IN],
-                             (struct prefix *) &p, RMAP_RIP, &newinfo);
-
-      if (ret == RMAP_DENYMATCH)
-        {
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIP %s/%d is filtered by route-map in",
-                       inet_ntoa (p.prefix), p.prefixlen);
-          return;
-        }
-
-      /* Get back the object */
-      rte->nexthop = newinfo.nexthop_out;
-      rte->tag = htons (newinfo.tag_out);       /* XXX */
-      rte->metric = newinfo.metric_out; /* XXX: the routemap uses the metric_out field */
-    }
-
-  /* Once the entry has been validated, update the metric by
-     adding the cost of the network on wich the message
-     arrived. If the result is greater than infinity, use infinity
-     (RFC2453 Sec. 3.9.2) */
-  /* Zebra ripd can handle offset-list in. */
-  ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);
-
-  /* If offset-list does not modify the metric use interface's
-     metric. */
-  if (!ret)
-    rte->metric += ifp->metric ? ifp->metric : 1;
-
-  if (rte->metric > RIP_METRIC_INFINITY)
-    rte->metric = RIP_METRIC_INFINITY;
-
-  /* Set nexthop pointer. */
-  if (rte->nexthop.s_addr == 0)
-    nexthop = &from->sin_addr;
-  else
-    nexthop = &rte->nexthop;
-
-  /* Check if nexthop address is myself, then do nothing. */
-  if (rip_nexthop_check (nexthop) < 0)
-    {
-      if (IS_RIP_DEBUG_PACKET)
-        zlog_debug ("Nexthop address %s is myself", inet_ntoa (*nexthop));
-      return;
-    }
-
-  /* Get index for the prefix. */
-  rp = route_node_get (rip->table, (struct prefix *) &p);
-
-  newinfo.rp = rp;
-  newinfo.nexthop = *nexthop;
-  newinfo.metric = rte->metric;
-  newinfo.tag = ntohs (rte->tag);
-  newinfo.distance = rip_distance_apply (&newinfo);
-
-  new_dist = newinfo.distance ? newinfo.distance : ZEBRA_RIP_DISTANCE_DEFAULT;
-
-  /* Check to see whether there is already RIP route on the table. */
-  if ((list = rp->info) != NULL)
-    for (ALL_LIST_ELEMENTS_RO (list, node, rinfo))
-      {
-        /* Need to compare with redistributed entry or local entry */
-        if (!rip_route_rte (rinfo))
-          break;
-
-        if (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr) &&
-            IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))
-          break;
-
-        if (!listnextnode (node))
-          {
-            /* Not found in the list */
-
-            if (rte->metric > rinfo->metric)
-              {
-                /* New route has a greater metric. Discard it. */
-                route_unlock_node (rp);
-                return;
-              }
-
-            if (rte->metric < rinfo->metric)
-              /* New route has a smaller metric. Replace the ECMP list
-               * with the new one in below. */
-              break;
-
-            /* Metrics are same. We compare the distances. */
-            old_dist = rinfo->distance ? \
-                       rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
-
-            if (new_dist > old_dist)
-              {
-                /* New route has a greater distance. Discard it. */
-                route_unlock_node (rp);
-                return;
-              }
-
-            if (new_dist < old_dist)
-              /* New route has a smaller distance. Replace the ECMP list
-               * with the new one in below. */
-              break;
-
-            /* Metrics and distances are both same. Keep "rinfo" null and
-             * the new route is added in the ECMP list in below. */
-          }
-      }
-
-  if (rinfo)
-    {
-      /* Local static route. */
-      if (rinfo->type == ZEBRA_ROUTE_RIP
-          && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
-              (rinfo->sub_type == RIP_ROUTE_DEFAULT))
-          && rinfo->metric != RIP_METRIC_INFINITY)
-        {
-          route_unlock_node (rp);
-          return;
-        }
-
-      /* Redistributed route check. */
-      if (rinfo->type != ZEBRA_ROUTE_RIP
-          && rinfo->metric != RIP_METRIC_INFINITY)
-        {
-          old_dist = rinfo->distance;
-          /* Only routes directly connected to an interface (nexthop == 0)
-          * may have a valid NULL distance */
-          if (rinfo->nexthop.s_addr != 0)
-            old_dist = old_dist ? old_dist : ZEBRA_RIP_DISTANCE_DEFAULT;
-          /* If imported route does not have STRICT precedence, 
-             mark it as a ghost */
-          if (new_dist <= old_dist && rte->metric != RIP_METRIC_INFINITY)
-            rip_ecmp_replace (&newinfo);
-
-          route_unlock_node (rp);
-          return;
-        }
-    }
-
-  if (!rinfo)
-    {
-      if (rp->info)
-        route_unlock_node (rp);
-
-      /* Now, check to see whether there is already an explicit route
-         for the destination prefix.  If there is no such route, add
-         this route to the routing table, unless the metric is
-         infinity (there is no point in adding a route which
-         unusable). */
-      if (rte->metric != RIP_METRIC_INFINITY)
-        rip_ecmp_add (&newinfo);
-    }
-  else
-    {
-      /* Route is there but we are not sure the route is RIP or not. */
-
-      /* If there is an existing route, compare the next hop address
-         to the address of the router from which the datagram came.
-         If this datagram is from the same router as the existing
-         route, reinitialize the timeout.  */
-      same = (IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr)
-              && (rinfo->ifindex == ifp->ifindex));
-
-      old_dist = rinfo->distance ? \
-                 rinfo->distance : ZEBRA_RIP_DISTANCE_DEFAULT;
-
-      /* Next, compare the metrics.  If the datagram is from the same
-         router as the existing route, and the new metric is different
-         than the old one; or, if the new metric is lower than the old
-         one, or if the tag has been changed; or if there is a route
-         with a lower administrave distance; or an update of the
-         distance on the actual route; do the following actions: */
-      if ((same && rinfo->metric != rte->metric)
-          || (rte->metric < rinfo->metric)
-          || ((same)
-              && (rinfo->metric == rte->metric)
-              && (newinfo.tag != rinfo->tag))
-          || (old_dist > new_dist)
-          || ((old_dist != new_dist) && same))
-        {
-          if (listcount (list) == 1)
-            {
-              if (newinfo.metric != RIP_METRIC_INFINITY)
-                rip_ecmp_replace (&newinfo);
-              else
-                rip_ecmp_delete (rinfo);
-            }
-          else
-            {
-              if (newinfo.metric < rinfo->metric)
-                rip_ecmp_replace (&newinfo);
-              else if (newinfo.metric > rinfo->metric)
-                rip_ecmp_delete (rinfo);
-              else if (new_dist < old_dist)
-                rip_ecmp_replace (&newinfo);
-              else if (new_dist > old_dist)
-                rip_ecmp_delete (rinfo);
-              else
-                {
-                  int update = CHECK_FLAG (rinfo->flags, RIP_RTF_FIB) ? 1 : 0;
-
-                  assert (newinfo.metric != RIP_METRIC_INFINITY);
-
-                  RIP_TIMER_OFF (rinfo->t_timeout);
-                  RIP_TIMER_OFF (rinfo->t_garbage_collect);
-                  memcpy (rinfo, &newinfo, sizeof (struct rip_info));
-                  rip_timeout_update (rinfo);
-
-                  if (update)
-                    rip_zebra_ipv4_add (rp);
-
-                  /* - Set the route change flag on the first entry. */
-                  rinfo = listgetdata (listhead (list));
-                  SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
-                  rip_event (RIP_TRIGGERED_UPDATE, 0);
-                }
-            }
-        }
-      else /* same & no change */
-        rip_timeout_update (rinfo);
-
-      /* Unlock tempolary lock of the route. */
-      route_unlock_node (rp);
-    }
-}
+static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
+                           struct interface *ifp)
+{
+       int ret;
+       struct prefix_ipv4 p;
+       struct route_node *rp;
+       struct rip_info *rinfo = NULL, newinfo;
+       struct rip_interface *ri;
+       struct in_addr *nexthop;
+       int same = 0;
+       unsigned char old_dist, new_dist;
+       struct list *list = NULL;
+       struct listnode *node = NULL;
+
+       /* Make prefix structure. */
+       memset(&p, 0, sizeof(struct prefix_ipv4));
+       p.family = AF_INET;
+       p.prefix = rte->prefix;
+       p.prefixlen = ip_masklen(rte->mask);
+
+       /* Make sure mask is applied. */
+       apply_mask_ipv4(&p);
+
+       /* Apply input filters. */
+       ri = ifp->info;
 
-/* Dump RIP packet */
-static void
-rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv)
-{
-  caddr_t lim;
-  struct rte *rte;
-  const char *command_str;
-  char pbuf[BUFSIZ], nbuf[BUFSIZ];
-  u_char netmask = 0;
-  u_char *p;
-
-  /* Set command string. */
-  if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
-    command_str = lookup_msg (rip_msg, packet->command, NULL);
-  else
-    command_str = "unknown";
-
-  /* Dump packet header. */
-  zlog_debug ("%s %s version %d packet size %d",
-            sndrcv, command_str, packet->version, size);
-
-  /* Dump each routing table entry. */
-  rte = packet->rte;
-  
-  for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
-    {
-      if (packet->version == RIPv2)
-       {
-         netmask = ip_masklen (rte->mask);
+       ret = rip_filter(RIP_FILTER_IN, &p, ri);
+       if (ret < 0)
+               return;
+
+       memset(&newinfo, 0, sizeof(newinfo));
+       newinfo.type = ZEBRA_ROUTE_RIP;
+       newinfo.sub_type = RIP_ROUTE_RTE;
+       newinfo.nh.gate.ipv4 = rte->nexthop;
+       newinfo.from = from->sin_addr;
+       newinfo.nh.ifindex = ifp->ifindex;
+       newinfo.nh.type = NEXTHOP_TYPE_IPV4_IFINDEX;
+       newinfo.metric = rte->metric;
+       newinfo.metric_out = rte->metric; /* XXX */
+       newinfo.tag = ntohs(rte->tag);    /* XXX */
+
+       /* Modify entry according to the interface routemap. */
+       if (ri->routemap[RIP_FILTER_IN]) {
+               int ret;
+
+               /* The object should be of the type of rip_info */
+               ret = route_map_apply(ri->routemap[RIP_FILTER_IN],
+                                     (struct prefix *)&p, RMAP_RIP, &newinfo);
+
+               if (ret == RMAP_DENYMATCH) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug(
+                                       "RIP %s/%d is filtered by route-map in",
+                                       inet_ntoa(p.prefix), p.prefixlen);
+                       return;
+               }
+
+               /* Get back the object */
+               rte->nexthop = newinfo.nexthop_out;
+               rte->tag = htons(newinfo.tag_out); /* XXX */
+               rte->metric =
+                       newinfo.metric_out; /* XXX: the routemap uses the
+                                              metric_out field */
+       }
 
-          if (rte->family == htons (RIP_FAMILY_AUTH))
-            {
-              if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))
-               {
-                 p = (u_char *)&rte->prefix;
+       /* Once the entry has been validated, update the metric by
+          adding the cost of the network on wich the message
+          arrived. If the result is greater than infinity, use infinity
+          (RFC2453 Sec. 3.9.2) */
+       /* Zebra ripd can handle offset-list in. */
+       ret = rip_offset_list_apply_in(&p, ifp, &rte->metric);
 
-                 zlog_debug ("  family 0x%X type %d auth string: %s",
-                            ntohs (rte->family), ntohs (rte->tag), p);
+       /* If offset-list does not modify the metric use interface's
+          metric. */
+       if (!ret)
+               rte->metric += ifp->metric ? ifp->metric : 1;
+
+       if (rte->metric > RIP_METRIC_INFINITY)
+               rte->metric = RIP_METRIC_INFINITY;
+
+       /* Set nexthop pointer. */
+       if (rte->nexthop.s_addr == 0)
+               nexthop = &from->sin_addr;
+       else
+               nexthop = &rte->nexthop;
+
+       /* Check if nexthop address is myself, then do nothing. */
+       if (rip_nexthop_check(nexthop) < 0) {
+               if (IS_RIP_DEBUG_PACKET)
+                       zlog_debug("Nexthop address %s is myself",
+                                  inet_ntoa(*nexthop));
+               return;
+       }
+
+       /* Get index for the prefix. */
+       rp = route_node_get(rip->table, (struct prefix *)&p);
+
+       newinfo.rp = rp;
+       newinfo.nh.gate.ipv4 = *nexthop;
+       newinfo.nh.type = NEXTHOP_TYPE_IPV4;
+       newinfo.metric = rte->metric;
+       newinfo.tag = ntohs(rte->tag);
+       newinfo.distance = rip_distance_apply(&newinfo);
+
+       new_dist = newinfo.distance ? newinfo.distance
+                                   : ZEBRA_RIP_DISTANCE_DEFAULT;
+
+       /* Check to see whether there is already RIP route on the table. */
+       if ((list = rp->info) != NULL)
+               for (ALL_LIST_ELEMENTS_RO(list, node, rinfo)) {
+                       /* Need to compare with redistributed entry or local
+                        * entry */
+                       if (!rip_route_rte(rinfo))
+                               break;
+
+                       if (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
+                           && IPV4_ADDR_SAME(&rinfo->nh.gate.ipv4, nexthop))
+                               break;
+
+                       if (!listnextnode(node)) {
+                               /* Not found in the list */
+
+                               if (rte->metric > rinfo->metric) {
+                                       /* New route has a greater metric.
+                                        * Discard it. */
+                                       route_unlock_node(rp);
+                                       return;
+                               }
+
+                               if (rte->metric < rinfo->metric)
+                                       /* New route has a smaller metric.
+                                        * Replace the ECMP list
+                                        * with the new one in below. */
+                                       break;
+
+                               /* Metrics are same. We compare the distances.
+                                */
+                               old_dist = rinfo->distance
+                                                  ? rinfo->distance
+                                                  : ZEBRA_RIP_DISTANCE_DEFAULT;
+
+                               if (new_dist > old_dist) {
+                                       /* New route has a greater distance.
+                                        * Discard it. */
+                                       route_unlock_node(rp);
+                                       return;
+                               }
+
+                               if (new_dist < old_dist)
+                                       /* New route has a smaller distance.
+                                        * Replace the ECMP list
+                                        * with the new one in below. */
+                                       break;
+
+                               /* Metrics and distances are both same. Keep
+                                * "rinfo" null and
+                                * the new route is added in the ECMP list in
+                                * below. */
+                       }
                }
-              else if (rte->tag == htons (RIP_AUTH_MD5))
-               {
-                 struct rip_md5_info *md5;
-
-                 md5 = (struct rip_md5_info *) &packet->rte;
-
-                 zlog_debug ("  family 0x%X type %d (MD5 authentication)",
-                            ntohs (md5->family), ntohs (md5->type));
-                 zlog_debug ("    RIP-2 packet len %d Key ID %d"
-                             " Auth Data len %d",
-                             ntohs (md5->packet_len), md5->keyid,
-                             md5->auth_len);
-                  zlog_debug ("    Sequence Number %ld",
-                             (u_long) ntohl (md5->sequence));
+
+       if (rinfo) {
+               /* Local static route. */
+               if (rinfo->type == ZEBRA_ROUTE_RIP
+                   && ((rinfo->sub_type == RIP_ROUTE_STATIC)
+                       || (rinfo->sub_type == RIP_ROUTE_DEFAULT))
+                   && rinfo->metric != RIP_METRIC_INFINITY) {
+                       route_unlock_node(rp);
+                       return;
                }
-              else if (rte->tag == htons (RIP_AUTH_DATA))
-               {
-                 p = (u_char *)&rte->prefix;
-
-                 zlog_debug ("  family 0x%X type %d (MD5 data)",
-                            ntohs (rte->family), ntohs (rte->tag));
-                 zlog_debug ("    MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
-                            "%02X%02X%02X%02X%02X%02X%02X%02X",
-                             p[0], p[1], p[2], p[3], p[4], p[5], p[6],
-                             p[7], p[8], p[9], p[10], p[11], p[12], p[13],
-                             p[14], p[15]);
+
+               /* Redistributed route check. */
+               if (rinfo->type != ZEBRA_ROUTE_RIP
+                   && rinfo->metric != RIP_METRIC_INFINITY) {
+                       old_dist = rinfo->distance;
+                       /* Only routes directly connected to an interface
+                        * (nexthop == 0)
+                        * may have a valid NULL distance */
+                       if (rinfo->nh.gate.ipv4.s_addr != 0)
+                               old_dist = old_dist
+                                                  ? old_dist
+                                                  : ZEBRA_RIP_DISTANCE_DEFAULT;
+                       /* If imported route does not have STRICT precedence,
+                          mark it as a ghost */
+                       if (new_dist <= old_dist
+                           && rte->metric != RIP_METRIC_INFINITY)
+                               rip_ecmp_replace(&newinfo);
+
+                       route_unlock_node(rp);
+                       return;
                }
-             else
-               {
-                 zlog_debug ("  family 0x%X type %d (Unknown auth type)",
-                            ntohs (rte->family), ntohs (rte->tag));
+       }
+
+       if (!rinfo) {
+               if (rp->info)
+                       route_unlock_node(rp);
+
+               /* Now, check to see whether there is already an explicit route
+                  for the destination prefix.  If there is no such route, add
+                  this route to the routing table, unless the metric is
+                  infinity (there is no point in adding a route which
+                  unusable). */
+               if (rte->metric != RIP_METRIC_INFINITY)
+                       rip_ecmp_add(&newinfo);
+       } else {
+               /* Route is there but we are not sure the route is RIP or not.
+                */
+
+               /* If there is an existing route, compare the next hop address
+                  to the address of the router from which the datagram came.
+                  If this datagram is from the same router as the existing
+                  route, reinitialize the timeout.  */
+               same = (IPV4_ADDR_SAME(&rinfo->from, &from->sin_addr)
+                       && (rinfo->nh.ifindex == ifp->ifindex));
+
+               old_dist = rinfo->distance ? rinfo->distance
+                                          : ZEBRA_RIP_DISTANCE_DEFAULT;
+
+               /* Next, compare the metrics.  If the datagram is from the same
+                  router as the existing route, and the new metric is different
+                  than the old one; or, if the new metric is lower than the old
+                  one, or if the tag has been changed; or if there is a route
+                  with a lower administrave distance; or an update of the
+                  distance on the actual route; do the following actions: */
+               if ((same && rinfo->metric != rte->metric)
+                   || (rte->metric < rinfo->metric)
+                   || ((same) && (rinfo->metric == rte->metric)
+                       && (newinfo.tag != rinfo->tag))
+                   || (old_dist > new_dist)
+                   || ((old_dist != new_dist) && same)) {
+                       if (listcount(list) == 1) {
+                               if (newinfo.metric != RIP_METRIC_INFINITY)
+                                       rip_ecmp_replace(&newinfo);
+                               else
+                                       rip_ecmp_delete(rinfo);
+                       } else {
+                               if (newinfo.metric < rinfo->metric)
+                                       rip_ecmp_replace(&newinfo);
+                               else if (newinfo.metric > rinfo->metric)
+                                       rip_ecmp_delete(rinfo);
+                               else if (new_dist < old_dist)
+                                       rip_ecmp_replace(&newinfo);
+                               else if (new_dist > old_dist)
+                                       rip_ecmp_delete(rinfo);
+                               else {
+                                       int update = CHECK_FLAG(rinfo->flags,
+                                                               RIP_RTF_FIB)
+                                                            ? 1
+                                                            : 0;
+
+                                       assert(newinfo.metric
+                                              != RIP_METRIC_INFINITY);
+
+                                       RIP_TIMER_OFF(rinfo->t_timeout);
+                                       RIP_TIMER_OFF(rinfo->t_garbage_collect);
+                                       memcpy(rinfo, &newinfo,
+                                              sizeof(struct rip_info));
+                                       rip_timeout_update(rinfo);
+
+                                       if (update)
+                                               rip_zebra_ipv4_add(rp);
+
+                                       /* - Set the route change flag on the
+                                        * first entry. */
+                                       rinfo = listgetdata(listhead(list));
+                                       SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
+                                       rip_event(RIP_TRIGGERED_UPDATE, 0);
+                               }
+                       }
+               } else /* same & no change */
+                       rip_timeout_update(rinfo);
+
+               /* Unlock tempolary lock of the route. */
+               route_unlock_node(rp);
+       }
+}
+
+/* Dump RIP packet */
+static void rip_packet_dump(struct rip_packet *packet, int size,
+                           const char *sndrcv)
+{
+       caddr_t lim;
+       struct rte *rte;
+       const char *command_str;
+       char pbuf[BUFSIZ], nbuf[BUFSIZ];
+       u_char netmask = 0;
+       u_char *p;
+
+       /* Set command string. */
+       if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)
+               command_str = lookup_msg(rip_msg, packet->command, NULL);
+       else
+               command_str = "unknown";
+
+       /* Dump packet header. */
+       zlog_debug("%s %s version %d packet size %d", sndrcv, command_str,
+                  packet->version, size);
+
+       /* Dump each routing table entry. */
+       rte = packet->rte;
+
+       for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) {
+               if (packet->version == RIPv2) {
+                       netmask = ip_masklen(rte->mask);
+
+                       if (rte->family == htons(RIP_FAMILY_AUTH)) {
+                               if (rte->tag
+                                   == htons(RIP_AUTH_SIMPLE_PASSWORD)) {
+                                       p = (u_char *)&rte->prefix;
+
+                                       zlog_debug(
+                                               "  family 0x%X type %d auth string: %s",
+                                               ntohs(rte->family),
+                                               ntohs(rte->tag), p);
+                               } else if (rte->tag == htons(RIP_AUTH_MD5)) {
+                                       struct rip_md5_info *md5;
+
+                                       md5 = (struct rip_md5_info *)&packet
+                                                     ->rte;
+
+                                       zlog_debug(
+                                               "  family 0x%X type %d (MD5 authentication)",
+                                               ntohs(md5->family),
+                                               ntohs(md5->type));
+                                       zlog_debug(
+                                               "    RIP-2 packet len %d Key ID %d"
+                                               " Auth Data len %d",
+                                               ntohs(md5->packet_len),
+                                               md5->keyid, md5->auth_len);
+                                       zlog_debug(
+                                               "    Sequence Number %ld",
+                                               (u_long)ntohl(md5->sequence));
+                               } else if (rte->tag == htons(RIP_AUTH_DATA)) {
+                                       p = (u_char *)&rte->prefix;
+
+                                       zlog_debug(
+                                               "  family 0x%X type %d (MD5 data)",
+                                               ntohs(rte->family),
+                                               ntohs(rte->tag));
+                                       zlog_debug(
+                                               "    MD5: %02X%02X%02X%02X%02X%02X%02X%02X"
+                                               "%02X%02X%02X%02X%02X%02X%02X%02X",
+                                               p[0], p[1], p[2], p[3], p[4],
+                                               p[5], p[6], p[7], p[8], p[9],
+                                               p[10], p[11], p[12], p[13],
+                                               p[14], p[15]);
+                               } else {
+                                       zlog_debug(
+                                               "  family 0x%X type %d (Unknown auth type)",
+                                               ntohs(rte->family),
+                                               ntohs(rte->tag));
+                               }
+                       } else
+                               zlog_debug(
+                                       "  %s/%d -> %s family %d tag %" ROUTE_TAG_PRI
+                                       " metric %ld",
+                                       inet_ntop(AF_INET, &rte->prefix, pbuf,
+                                                 BUFSIZ),
+                                       netmask,
+                                       inet_ntop(AF_INET, &rte->nexthop, nbuf,
+                                                 BUFSIZ),
+                                       ntohs(rte->family),
+                                       (route_tag_t)ntohs(rte->tag),
+                                       (u_long)ntohl(rte->metric));
+               } else {
+                       zlog_debug(
+                               "  %s family %d tag %" ROUTE_TAG_PRI
+                               " metric %ld",
+                               inet_ntop(AF_INET, &rte->prefix, pbuf, BUFSIZ),
+                               ntohs(rte->family),
+                               (route_tag_t)ntohs(rte->tag),
+                               (u_long)ntohl(rte->metric));
                }
-            }
-         else
-           zlog_debug ("  %s/%d -> %s family %d tag %"ROUTE_TAG_PRI" metric %ld",
-                       inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
-                       netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf,
-                                           BUFSIZ), ntohs (rte->family),
-                       (route_tag_t)ntohs (rte->tag),
-                       (u_long) ntohl (rte->metric));
-       }
-      else
-       {
-         zlog_debug ("  %s family %d tag %"ROUTE_TAG_PRI" metric %ld", 
-                    inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),
-                    ntohs (rte->family), (route_tag_t)ntohs (rte->tag),
-                    (u_long)ntohl (rte->metric));
        }
-    }
 }
 
 /* Check if the destination address is valid (unicast; not net 0
    or 127) (RFC2453 Section 3.9.2 - Page 26).  But we don't
    check net 0 because we accept default route. */
-static int
-rip_destination_check (struct in_addr addr)
+static int rip_destination_check(struct in_addr addr)
 {
-  u_int32_t destination;
+       u_int32_t destination;
 
-  /* Convert to host byte order. */
-  destination = ntohl (addr.s_addr);
+       /* Convert to host byte order. */
+       destination = ntohl(addr.s_addr);
 
-  if (IPV4_NET127 (destination))
-    return 0;
+       if (IPV4_NET127(destination))
+               return 0;
 
-  /* Net 0 may match to the default route. */
-  if (IPV4_NET0 (destination) && destination != 0)
-    return 0;
+       /* Net 0 may match to the default route. */
+       if (IPV4_NET0(destination) && destination != 0)
+               return 0;
 
-  /* Unicast address must belong to class A, B, C. */
-  if (IN_CLASSA (destination))
-    return 1;
-  if (IN_CLASSB (destination))
-    return 1;
-  if (IN_CLASSC (destination))
-    return 1;
+       /* Unicast address must belong to class A, B, C. */
+       if (IN_CLASSA(destination))
+               return 1;
+       if (IN_CLASSB(destination))
+               return 1;
+       if (IN_CLASSC(destination))
+               return 1;
 
-  return 0;
+       return 0;
 }
 
 /* RIP version 2 authentication. */
-static int
-rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,
-                         struct interface *ifp)
-{
-  struct rip_interface *ri;
-  char *auth_str = (char *) &rte->prefix;
-  int i;
-
-  /* reject passwords with zeros in the middle of the string */
-  for (i = strlen (auth_str); i < 16; i++)
-    {
-      if (auth_str[i] != '\0')
-       return 0;
-    }
-
-  if (IS_RIP_DEBUG_EVENT)
-    zlog_debug ("RIPv2 simple password authentication from %s",
-              inet_ntoa (from->sin_addr));
-
-  ri = ifp->info;
-
-  if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
-      || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
-    return 0;
-
-  /* Simple password authentication. */
-  if (ri->auth_str)
-    {
-      if (strncmp (auth_str, ri->auth_str, 16) == 0)
-       return 1;
-    }
-  if (ri->key_chain)
-    {
-      struct keychain *keychain;
-      struct key *key;
-
-      keychain = keychain_lookup (ri->key_chain);
-      if (keychain == NULL)
-       return 0;
+static int rip_auth_simple_password(struct rte *rte, struct sockaddr_in *from,
+                                   struct interface *ifp)
+{
+       struct rip_interface *ri;
+       char *auth_str = (char *)&rte->prefix;
+       int i;
+
+       /* reject passwords with zeros in the middle of the string */
+       for (i = strlen(auth_str); i < 16; i++) {
+               if (auth_str[i] != '\0')
+                       return 0;
+       }
+
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("RIPv2 simple password authentication from %s",
+                          inet_ntoa(from->sin_addr));
+
+       ri = ifp->info;
 
-      key = key_match_for_accept (keychain, auth_str);
-      if (key)
-       return 1;
-    }
-  return 0;
+       if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD
+           || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))
+               return 0;
+
+       /* Simple password authentication. */
+       if (ri->auth_str) {
+               if (strncmp(auth_str, ri->auth_str, 16) == 0)
+                       return 1;
+       }
+       if (ri->key_chain) {
+               struct keychain *keychain;
+               struct key *key;
+
+               keychain = keychain_lookup(ri->key_chain);
+               if (keychain == NULL)
+                       return 0;
+
+               key = key_match_for_accept(keychain, auth_str);
+               if (key)
+                       return 1;
+       }
+       return 0;
 }
 
 /* RIP version 2 authentication with MD5. */
-static int
-rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
-              int length, struct interface *ifp)
-{
-  struct rip_interface *ri;
-  struct rip_md5_info *md5;
-  struct rip_md5_data *md5data;
-  struct keychain *keychain;
-  struct key *key;
-  MD5_CTX ctx;
-  u_char digest[RIP_AUTH_MD5_SIZE];
-  u_int16_t packet_len;
-  char auth_str[RIP_AUTH_MD5_SIZE];
-  
-  if (IS_RIP_DEBUG_EVENT)
-    zlog_debug ("RIPv2 MD5 authentication from %s",
-               inet_ntoa (from->sin_addr));
-
-  ri = ifp->info;
-  md5 = (struct rip_md5_info *) &packet->rte;
-
-  /* Check auth type. */
-  if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
-    return 0;
-
-  /* If the authentication length is less than 16, then it must be wrong for
-   * any interpretation of rfc2082. Some implementations also interpret
-   * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.
-   */
-  if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE)
-         || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
-    {
-      if (IS_RIP_DEBUG_EVENT)
-        zlog_debug ("RIPv2 MD5 authentication, strange authentication "
-                   "length field %d", md5->auth_len);
-    return 0;
-    }
-
-  /* grab and verify check packet length */
-  packet_len = ntohs (md5->packet_len);
-
-  if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE))
-    {
-      if (IS_RIP_DEBUG_EVENT)
-        zlog_debug ("RIPv2 MD5 authentication, packet length field %d "
-                   "greater than received length %d!",
-                   md5->packet_len, length);
-      return 0;
-    }
-
-  /* retrieve authentication data */
-  md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
-  
-  memset (auth_str, 0, RIP_AUTH_MD5_SIZE);
-
-  if (ri->key_chain)
-    {
-      keychain = keychain_lookup (ri->key_chain);
-      if (keychain == NULL)
-       return 0;
+static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
+                       int length, struct interface *ifp)
+{
+       struct rip_interface *ri;
+       struct rip_md5_info *md5;
+       struct rip_md5_data *md5data;
+       struct keychain *keychain;
+       struct key *key;
+       MD5_CTX ctx;
+       u_char digest[RIP_AUTH_MD5_SIZE];
+       u_int16_t packet_len;
+       char auth_str[RIP_AUTH_MD5_SIZE];
+
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("RIPv2 MD5 authentication from %s",
+                          inet_ntoa(from->sin_addr));
 
-      key = key_lookup_for_accept (keychain, md5->keyid);
-      if (key == NULL)
-       return 0;
+       ri = ifp->info;
+       md5 = (struct rip_md5_info *)&packet->rte;
+
+       /* Check auth type. */
+       if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))
+               return 0;
+
+       /* If the authentication length is less than 16, then it must be wrong
+        * for
+        * any interpretation of rfc2082. Some implementations also interpret
+        * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka
+        * RIP_AUTH_MD5_COMPAT_SIZE.
+        */
+       if (!((md5->auth_len == RIP_AUTH_MD5_SIZE)
+             || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE))) {
+               if (IS_RIP_DEBUG_EVENT)
+                       zlog_debug(
+                               "RIPv2 MD5 authentication, strange authentication "
+                               "length field %d",
+                               md5->auth_len);
+               return 0;
+       }
+
+       /* grab and verify check packet length */
+       packet_len = ntohs(md5->packet_len);
 
-      strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE);
-    }
-  else if (ri->auth_str)
-    strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
-
-  if (auth_str[0] == 0)
-    return 0;
-  
-  /* MD5 digest authentication. */
-  memset (&ctx, 0, sizeof(ctx));
-  MD5Init(&ctx);
-  MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
-  MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
-  MD5Final(digest, &ctx);
-  
-  if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
-    return packet_len;
-  else
-    return 0;
+       if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) {
+               if (IS_RIP_DEBUG_EVENT)
+                       zlog_debug(
+                               "RIPv2 MD5 authentication, packet length field %d "
+                               "greater than received length %d!",
+                               md5->packet_len, length);
+               return 0;
+       }
+
+       /* retrieve authentication data */
+       md5data = (struct rip_md5_data *)(((u_char *)packet) + packet_len);
+
+       memset(auth_str, 0, RIP_AUTH_MD5_SIZE);
+
+       if (ri->key_chain) {
+               keychain = keychain_lookup(ri->key_chain);
+               if (keychain == NULL)
+                       return 0;
+
+               key = key_lookup_for_accept(keychain, md5->keyid);
+               if (key == NULL)
+                       return 0;
+
+               strncpy(auth_str, key->string, RIP_AUTH_MD5_SIZE);
+       } else if (ri->auth_str)
+               strncpy(auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
+
+       if (auth_str[0] == 0)
+               return 0;
+
+       /* MD5 digest authentication. */
+       memset(&ctx, 0, sizeof(ctx));
+       MD5Init(&ctx);
+       MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
+       MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
+       MD5Final(digest, &ctx);
+
+       if (memcmp(md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
+               return packet_len;
+       else
+               return 0;
 }
 
 /* Pick correct auth string for sends, prepare auth_str buffer for use.
@@ -950,39 +934,37 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
  * zero padded.
  *
  */
-static void
-rip_auth_prepare_str_send (struct rip_interface *ri, struct key *key, 
-                           char *auth_str, int len)
+static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key,
+                                     char *auth_str, int len)
 {
-  assert (ri || key);
+       assert(ri || key);
 
-  memset (auth_str, 0, len);
-  if (key && key->string)
-    strncpy (auth_str, key->string, len);
-  else if (ri->auth_str)
-    strncpy (auth_str, ri->auth_str, len);
+       memset(auth_str, 0, len);
+       if (key && key->string)
+               strncpy(auth_str, key->string, len);
+       else if (ri->auth_str)
+               strncpy(auth_str, ri->auth_str, len);
 
-  return;
+       return;
 }
 
 /* Write RIPv2 simple password authentication information
  *
- * auth_str is presumed to be 2 bytes and correctly prepared 
+ * auth_str is presumed to be 2 bytes and correctly prepared
  * (left justified and zero padded).
  */
-static void
-rip_auth_simple_write (struct stream *s, char *auth_str, int len)
+static void rip_auth_simple_write(struct stream *s, char *auth_str, int len)
 {
-  assert (s && len == RIP_AUTH_SIMPLE_SIZE);
-  
-  stream_putw (s, RIP_FAMILY_AUTH);
-  stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);
-  stream_put (s, auth_str, RIP_AUTH_SIMPLE_SIZE);
-  
-  return;
+       assert(s && len == RIP_AUTH_SIMPLE_SIZE);
+
+       stream_putw(s, RIP_FAMILY_AUTH);
+       stream_putw(s, RIP_AUTH_SIMPLE_PASSWORD);
+       stream_put(s, auth_str, RIP_AUTH_SIMPLE_SIZE);
+
+       return;
 }
 
-/* write RIPv2 MD5 "authentication header" 
+/* write RIPv2 MD5 "authentication header"
  * (uses the auth key data field)
  *
  * Digest offset field is set to 0.
@@ -990,1814 +972,1810 @@ rip_auth_simple_write (struct stream *s, char *auth_str, int len)
  * returns: offset of the digest offset field, which must be set when
  * length to the auth-data MD5 digest is known.
  */
-static size_t
-rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri, 
-                       struct key *key)
-{
-  size_t doff = 0;
-
-  assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
-
-  /* MD5 authentication. */
-  stream_putw (s, RIP_FAMILY_AUTH);
-  stream_putw (s, RIP_AUTH_MD5);
-
-  /* MD5 AH digest offset field.
-   *
-   * Set to placeholder value here, to true value when RIP-2 Packet length
-   * is known.  Actual value is set in .....().
-   */
-  doff = stream_get_endp(s);
-  stream_putw (s, 0);
-
-  /* Key ID. */
-  if (key)
-    stream_putc (s, key->index % 256);
-  else
-    stream_putc (s, 1);
-
-  /* Auth Data Len.  Set 16 for MD5 authentication data. Older ripds 
-   * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this
-   * to be configurable. 
-   */
-  stream_putc (s, ri->md5_auth_len);
-
-  /* Sequence Number (non-decreasing). */
-  /* RFC2080: The value used in the sequence number is
-     arbitrary, but two suggestions are the time of the
-     message's creation or a simple message counter. */
-  stream_putl (s, time (NULL));
-             
-  /* Reserved field must be zero. */
-  stream_putl (s, 0);
-  stream_putl (s, 0);
-
-  return doff;
+static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri,
+                                   struct key *key)
+{
+       size_t doff = 0;
+
+       assert(s && ri && ri->auth_type == RIP_AUTH_MD5);
+
+       /* MD5 authentication. */
+       stream_putw(s, RIP_FAMILY_AUTH);
+       stream_putw(s, RIP_AUTH_MD5);
+
+       /* MD5 AH digest offset field.
+        *
+        * Set to placeholder value here, to true value when RIP-2 Packet length
+        * is known.  Actual value is set in .....().
+        */
+       doff = stream_get_endp(s);
+       stream_putw(s, 0);
+
+       /* Key ID. */
+       if (key)
+               stream_putc(s, key->index % 256);
+       else
+               stream_putc(s, 1);
+
+       /* Auth Data Len.  Set 16 for MD5 authentication data. Older ripds
+        * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for
+        * this
+        * to be configurable.
+        */
+       stream_putc(s, ri->md5_auth_len);
+
+       /* Sequence Number (non-decreasing). */
+       /* RFC2080: The value used in the sequence number is
+          arbitrary, but two suggestions are the time of the
+          message's creation or a simple message counter. */
+       stream_putl(s, time(NULL));
+
+       /* Reserved field must be zero. */
+       stream_putl(s, 0);
+       stream_putl(s, 0);
+
+       return doff;
 }
 
 /* If authentication is in used, write the appropriate header
  * returns stream offset to which length must later be written
  * or 0 if this is not required
  */
-static size_t
-rip_auth_header_write (struct stream *s, struct rip_interface *ri, 
-                       struct key *key, char *auth_str, int len)
-{
-  assert (ri->auth_type != RIP_NO_AUTH);
-  
-  switch (ri->auth_type)
-    {
-      case RIP_AUTH_SIMPLE_PASSWORD:
-        rip_auth_prepare_str_send (ri, key, auth_str, len);
-        rip_auth_simple_write (s, auth_str, len);
-        return 0;
-      case RIP_AUTH_MD5:
-        return rip_auth_md5_ah_write (s, ri, key);
-    }
-  assert (1);
-  return 0;
+static size_t rip_auth_header_write(struct stream *s, struct rip_interface *ri,
+                                   struct key *key, char *auth_str, int len)
+{
+       assert(ri->auth_type != RIP_NO_AUTH);
+
+       switch (ri->auth_type) {
+       case RIP_AUTH_SIMPLE_PASSWORD:
+               rip_auth_prepare_str_send(ri, key, auth_str, len);
+               rip_auth_simple_write(s, auth_str, len);
+               return 0;
+       case RIP_AUTH_MD5:
+               return rip_auth_md5_ah_write(s, ri, key);
+       }
+       assert(1);
+       return 0;
 }
 
 /* Write RIPv2 MD5 authentication data trailer */
-static void
-rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
-                  char *auth_str, int authlen)
-{
-  unsigned long len;
-  MD5_CTX ctx;
-  unsigned char digest[RIP_AUTH_MD5_SIZE];
-
-  /* Make it sure this interface is configured as MD5
-     authentication. */
-  assert ((ri->auth_type == RIP_AUTH_MD5) && (authlen == RIP_AUTH_MD5_SIZE));
-  assert (doff > 0);
-  
-  /* Get packet length. */
-  len = stream_get_endp(s);
-
-  /* Check packet length. */
-  if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))
-    {
-      zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);
-      return;
-    }
-
-  /* Set the digest offset length in the header */
-  stream_putw_at (s, doff, len);
-  
-  /* Set authentication data. */
-  stream_putw (s, RIP_FAMILY_AUTH);
-  stream_putw (s, RIP_AUTH_DATA);
-
-  /* Generate a digest for the RIP packet. */
-  memset(&ctx, 0, sizeof(ctx));
-  MD5Init(&ctx);
-  MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s));
-  MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
-  MD5Final(digest, &ctx);
-
-  /* Copy the digest to the packet. */
-  stream_write (s, digest, RIP_AUTH_MD5_SIZE);
+static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri,
+                            size_t doff, char *auth_str, int authlen)
+{
+       unsigned long len;
+       MD5_CTX ctx;
+       unsigned char digest[RIP_AUTH_MD5_SIZE];
+
+       /* Make it sure this interface is configured as MD5
+          authentication. */
+       assert((ri->auth_type == RIP_AUTH_MD5)
+              && (authlen == RIP_AUTH_MD5_SIZE));
+       assert(doff > 0);
+
+       /* Get packet length. */
+       len = stream_get_endp(s);
+
+       /* Check packet length. */
+       if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) {
+               zlog_err(
+                       "rip_auth_md5_set(): packet length %ld is less than minimum length.",
+                       len);
+               return;
+       }
+
+       /* Set the digest offset length in the header */
+       stream_putw_at(s, doff, len);
+
+       /* Set authentication data. */
+       stream_putw(s, RIP_FAMILY_AUTH);
+       stream_putw(s, RIP_AUTH_DATA);
+
+       /* Generate a digest for the RIP packet. */
+       memset(&ctx, 0, sizeof(ctx));
+       MD5Init(&ctx);
+       MD5Update(&ctx, STREAM_DATA(s), stream_get_endp(s));
+       MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
+       MD5Final(digest, &ctx);
+
+       /* Copy the digest to the packet. */
+       stream_write(s, digest, RIP_AUTH_MD5_SIZE);
 }
 
 /* RIP routing information. */
-static void
-rip_response_process (struct rip_packet *packet, int size, 
-                     struct sockaddr_in *from, struct connected *ifc)
-{
-  caddr_t lim;
-  struct rte *rte;
-  struct prefix_ipv4 ifaddr;
-  struct prefix_ipv4 ifaddrclass;
-  int subnetted;
-
-  memset(&ifaddr, 0, sizeof(ifaddr));
-  /* We don't know yet. */
-  subnetted = -1;
-
-  /* The Response must be ignored if it is not from the RIP
-     port. (RFC2453 - Sec. 3.9.2)*/
-  if (from->sin_port != htons(RIP_PORT_DEFAULT))
-    {
-      zlog_info ("response doesn't come from RIP port: %d",
-                from->sin_port);
-      rip_peer_bad_packet (from);
-      return;
-    }
-
-  /* The datagram's IPv4 source address should be checked to see
-     whether the datagram is from a valid neighbor; the source of the
-     datagram must be on a directly connected network (RFC2453 - Sec. 3.9.2) */
-  if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT) == NULL)
-    {
-      zlog_info ("This datagram doesn't came from a valid neighbor: %s",
-                inet_ntoa (from->sin_addr));
-      rip_peer_bad_packet (from);
-      return;
-    }
-
-  /* It is also worth checking to see whether the response is from one
-     of the router's own addresses. */
-
-  ; /* Alredy done in rip_read () */
-
-  /* Update RIP peer. */
-  rip_peer_update (from, packet->version);
-
-  /* Set RTE pointer. */
-  rte = packet->rte;
-
-  for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)
-    {
-      /* RIPv2 authentication check. */
-      /* If the Address Family Identifier of the first (and only the
-        first) entry in the message is 0xFFFF, then the remainder of
-        the entry contains the authentication. */
-      /* If the packet gets here it means authentication enabled */
-      /* Check is done in rip_read(). So, just skipping it */
-      if (packet->version == RIPv2 &&
-         rte == packet->rte &&
-         rte->family == htons(RIP_FAMILY_AUTH))
-       continue;
-
-      if (rte->family != htons(AF_INET))
-       {
-         /* Address family check.  RIP only supports AF_INET. */
-         zlog_info ("Unsupported family %d from %s.",
-                    ntohs (rte->family), inet_ntoa (from->sin_addr));
-         continue;
-       }
-
-      /* - is the destination address valid (e.g., unicast; not net 0
-         or 127) */
-      if (! rip_destination_check (rte->prefix))
-        {
-         zlog_info ("Network is net 0 or net 127 or it is not unicast network");
-         rip_peer_bad_route (from);
-         continue;
-       } 
-
-      /* Convert metric value to host byte order. */
-      rte->metric = ntohl (rte->metric);
-
-      /* - is the metric valid (i.e., between 1 and 16, inclusive) */
-      if (! (rte->metric >= 1 && rte->metric <= 16))
-       {
-         zlog_info ("Route's metric is not in the 1-16 range.");
-         rip_peer_bad_route (from);
-         continue;
+static void rip_response_process(struct rip_packet *packet, int size,
+                                struct sockaddr_in *from,
+                                struct connected *ifc)
+{
+       caddr_t lim;
+       struct rte *rte;
+       struct prefix_ipv4 ifaddr;
+       struct prefix_ipv4 ifaddrclass;
+       int subnetted;
+
+       memset(&ifaddr, 0, sizeof(ifaddr));
+       /* We don't know yet. */
+       subnetted = -1;
+
+       /* The Response must be ignored if it is not from the RIP
+          port. (RFC2453 - Sec. 3.9.2)*/
+       if (from->sin_port != htons(RIP_PORT_DEFAULT)) {
+               zlog_info("response doesn't come from RIP port: %d",
+                         from->sin_port);
+               rip_peer_bad_packet(from);
+               return;
        }
 
-      /* RIPv1 does not have nexthop value. */
-      if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)
-       {
-         zlog_info ("RIPv1 packet with nexthop value %s",
-                    inet_ntoa (rte->nexthop));
-         rip_peer_bad_route (from);
-         continue;
+       /* The datagram's IPv4 source address should be checked to see
+          whether the datagram is from a valid neighbor; the source of the
+          datagram must be on a directly connected network (RFC2453 - Sec.
+          3.9.2) */
+       if (if_lookup_address((void *)&from->sin_addr, AF_INET, VRF_DEFAULT)
+           == NULL) {
+               zlog_info(
+                       "This datagram doesn't came from a valid neighbor: %s",
+                       inet_ntoa(from->sin_addr));
+               rip_peer_bad_packet(from);
+               return;
        }
 
-      /* That is, if the provided information is ignored, a possibly
-        sub-optimal, but absolutely valid, route may be taken.  If
-        the received Next Hop is not directly reachable, it should be
-        treated as 0.0.0.0. */
-      if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)
-       {
-         u_int32_t addrval;
-
-         /* Multicast address check. */
-         addrval = ntohl (rte->nexthop.s_addr);
-         if (IN_CLASSD (addrval))
-           {
-             zlog_info ("Nexthop %s is multicast address, skip this rte",
-                        inet_ntoa (rte->nexthop));
-             continue;
-           }
-
-         if (! if_lookup_address ((void *)&rte->nexthop, AF_INET, VRF_DEFAULT))
-           {
-             struct route_node *rn;
-             struct rip_info *rinfo;
-
-             rn = route_node_match_ipv4 (rip->table, &rte->nexthop);
-
-             if (rn)
-               {
-                 rinfo = rn->info;
-
-                 if (rinfo->type == ZEBRA_ROUTE_RIP
-                     && rinfo->sub_type == RIP_ROUTE_RTE)
-                   {
-                     if (IS_RIP_DEBUG_EVENT)
-                       zlog_debug ("Next hop %s is on RIP network.  Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));
-                     rte->nexthop = rinfo->from;
-                   }
-                 else
-                   {
-                     if (IS_RIP_DEBUG_EVENT)
-                       zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
-                     rte->nexthop.s_addr = 0;
-                   }
-
-                 route_unlock_node (rn);
+       /* It is also worth checking to see whether the response is from one
+          of the router's own addresses. */
+
+       ; /* Alredy done in rip_read () */
+
+       /* Update RIP peer. */
+       rip_peer_update(from, packet->version);
+
+       /* Set RTE pointer. */
+       rte = packet->rte;
+
+       for (lim = (caddr_t)packet + size; (caddr_t)rte < lim; rte++) {
+               /* RIPv2 authentication check. */
+               /* If the Address Family Identifier of the first (and only the
+                  first) entry in the message is 0xFFFF, then the remainder of
+                  the entry contains the authentication. */
+               /* If the packet gets here it means authentication enabled */
+               /* Check is done in rip_read(). So, just skipping it */
+               if (packet->version == RIPv2 && rte == packet->rte
+                   && rte->family == htons(RIP_FAMILY_AUTH))
+                       continue;
+
+               if (rte->family != htons(AF_INET)) {
+                       /* Address family check.  RIP only supports AF_INET. */
+                       zlog_info("Unsupported family %d from %s.",
+                                 ntohs(rte->family),
+                                 inet_ntoa(from->sin_addr));
+                       continue;
                }
-             else
-               {
-                 if (IS_RIP_DEBUG_EVENT)
-                   zlog_debug ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));
-                 rte->nexthop.s_addr = 0;
+
+               /* - is the destination address valid (e.g., unicast; not net 0
+                  or 127) */
+               if (!rip_destination_check(rte->prefix)) {
+                       zlog_info(
+                               "Network is net 0 or net 127 or it is not unicast network");
+                       rip_peer_bad_route(from);
+                       continue;
                }
 
-           }
-       }
+               /* Convert metric value to host byte order. */
+               rte->metric = ntohl(rte->metric);
 
-     /* For RIPv1, there won't be a valid netmask.  
+               /* - is the metric valid (i.e., between 1 and 16, inclusive) */
+               if (!(rte->metric >= 1 && rte->metric <= 16)) {
+                       zlog_info("Route's metric is not in the 1-16 range.");
+                       rip_peer_bad_route(from);
+                       continue;
+               }
 
-       This is a best guess at the masks.  If everyone was using old
-       Ciscos before the 'ip subnet zero' option, it would be almost
-       right too :-)
-      
-       Cisco summarize ripv1 advertisments to the classful boundary
-       (/16 for class B's) except when the RIP packet does to inside
-       the classful network in question.  */
+               /* RIPv1 does not have nexthop value. */
+               if (packet->version == RIPv1 && rte->nexthop.s_addr != 0) {
+                       zlog_info("RIPv1 packet with nexthop value %s",
+                                 inet_ntoa(rte->nexthop));
+                       rip_peer_bad_route(from);
+                       continue;
+               }
 
-      if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) 
-         || (packet->version == RIPv2 
-             && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))
-       {
-         u_int32_t destination;
-
-         if (subnetted == -1)
-            {
-              memcpy (&ifaddr, ifc->address, sizeof (struct prefix_ipv4));
-              memcpy (&ifaddrclass, &ifaddr, sizeof (struct prefix_ipv4));
-              apply_classful_mask_ipv4 (&ifaddrclass);
-              subnetted = 0;
-              if (ifaddr.prefixlen > ifaddrclass.prefixlen)
-                subnetted = 1;
-            }
-
-         destination = ntohl (rte->prefix.s_addr);
-
-         if (IN_CLASSA (destination))
-             masklen2ip (8, &rte->mask);
-         else if (IN_CLASSB (destination))
-             masklen2ip (16, &rte->mask);
-         else if (IN_CLASSC (destination))
-             masklen2ip (24, &rte->mask);
-
-         if (subnetted == 1)
-           masklen2ip (ifaddrclass.prefixlen,
-                       (struct in_addr *) &destination);
-         if ((subnetted == 1) && ((rte->prefix.s_addr & destination) ==
-             ifaddrclass.prefix.s_addr))
-           {
-             masklen2ip (ifaddr.prefixlen, &rte->mask);
-             if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
-               masklen2ip (32, &rte->mask);
-             if (IS_RIP_DEBUG_EVENT)
-               zlog_debug ("Subnetted route %s", inet_ntoa (rte->prefix));
-           }
-         else
-           {
-             if ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr)
-               continue;
-           }
-
-         if (IS_RIP_DEBUG_EVENT)
-           {
-             zlog_debug ("Resultant route %s", inet_ntoa (rte->prefix));
-             zlog_debug ("Resultant mask %s", inet_ntoa (rte->mask));
-           }
-       }
-
-      /* In case of RIPv2, if prefix in RTE is not netmask applied one
-         ignore the entry.  */
-      if ((packet->version == RIPv2) 
-         && (rte->mask.s_addr != 0) 
-         && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))
-       {
-         zlog_warn ("RIPv2 address %s is not mask /%d applied one",
-                    inet_ntoa (rte->prefix), ip_masklen (rte->mask));
-         rip_peer_bad_route (from);
-         continue;
-       }
+               /* That is, if the provided information is ignored, a possibly
+                  sub-optimal, but absolutely valid, route may be taken.  If
+                  the received Next Hop is not directly reachable, it should be
+                  treated as 0.0.0.0. */
+               if (packet->version == RIPv2 && rte->nexthop.s_addr != 0) {
+                       u_int32_t addrval;
+
+                       /* Multicast address check. */
+                       addrval = ntohl(rte->nexthop.s_addr);
+                       if (IN_CLASSD(addrval)) {
+                               zlog_info(
+                                       "Nexthop %s is multicast address, skip this rte",
+                                       inet_ntoa(rte->nexthop));
+                               continue;
+                       }
+
+                       if (!if_lookup_address((void *)&rte->nexthop, AF_INET,
+                                              VRF_DEFAULT)) {
+                               struct route_node *rn;
+                               struct rip_info *rinfo;
+
+                               rn = route_node_match_ipv4(rip->table,
+                                                          &rte->nexthop);
+
+                               if (rn) {
+                                       rinfo = rn->info;
+
+                                       if (rinfo->type == ZEBRA_ROUTE_RIP
+                                           && rinfo->sub_type
+                                                      == RIP_ROUTE_RTE) {
+                                               if (IS_RIP_DEBUG_EVENT)
+                                                       zlog_debug(
+                                                               "Next hop %s is on RIP network.  Set nexthop to the packet's originator",
+                                                               inet_ntoa(
+                                                                       rte->nexthop));
+                                               rte->nexthop = rinfo->from;
+                                       } else {
+                                               if (IS_RIP_DEBUG_EVENT)
+                                                       zlog_debug(
+                                                               "Next hop %s is not directly reachable. Treat it as 0.0.0.0",
+                                                               inet_ntoa(
+                                                                       rte->nexthop));
+                                               rte->nexthop.s_addr = 0;
+                                       }
+
+                                       route_unlock_node(rn);
+                               } else {
+                                       if (IS_RIP_DEBUG_EVENT)
+                                               zlog_debug(
+                                                       "Next hop %s is not directly reachable. Treat it as 0.0.0.0",
+                                                       inet_ntoa(
+                                                               rte->nexthop));
+                                       rte->nexthop.s_addr = 0;
+                               }
+                       }
+               }
 
-      /* Default route's netmask is ignored. */
-      if (packet->version == RIPv2
-         && (rte->prefix.s_addr == 0)
-         && (rte->mask.s_addr != 0))
-       {
-         if (IS_RIP_DEBUG_EVENT)
-           zlog_debug ("Default route with non-zero netmask.  Set zero to netmask");
-         rte->mask.s_addr = 0;
+               /* For RIPv1, there won't be a valid netmask.
+
+                  This is a best guess at the masks.  If everyone was using old
+                  Ciscos before the 'ip subnet zero' option, it would be almost
+                  right too :-)
+
+                  Cisco summarize ripv1 advertisments to the classful boundary
+                  (/16 for class B's) except when the RIP packet does to inside
+                  the classful network in question.  */
+
+               if ((packet->version == RIPv1 && rte->prefix.s_addr != 0)
+                   || (packet->version == RIPv2
+                       && (rte->prefix.s_addr != 0
+                           && rte->mask.s_addr == 0))) {
+                       u_int32_t destination;
+
+                       if (subnetted == -1) {
+                               memcpy(&ifaddr, ifc->address,
+                                      sizeof(struct prefix_ipv4));
+                               memcpy(&ifaddrclass, &ifaddr,
+                                      sizeof(struct prefix_ipv4));
+                               apply_classful_mask_ipv4(&ifaddrclass);
+                               subnetted = 0;
+                               if (ifaddr.prefixlen > ifaddrclass.prefixlen)
+                                       subnetted = 1;
+                       }
+
+                       destination = ntohl(rte->prefix.s_addr);
+
+                       if (IN_CLASSA(destination))
+                               masklen2ip(8, &rte->mask);
+                       else if (IN_CLASSB(destination))
+                               masklen2ip(16, &rte->mask);
+                       else if (IN_CLASSC(destination))
+                               masklen2ip(24, &rte->mask);
+
+                       if (subnetted == 1)
+                               masklen2ip(ifaddrclass.prefixlen,
+                                          (struct in_addr *)&destination);
+                       if ((subnetted == 1)
+                           && ((rte->prefix.s_addr & destination)
+                               == ifaddrclass.prefix.s_addr)) {
+                               masklen2ip(ifaddr.prefixlen, &rte->mask);
+                               if ((rte->prefix.s_addr & rte->mask.s_addr)
+                                   != rte->prefix.s_addr)
+                                       masklen2ip(32, &rte->mask);
+                               if (IS_RIP_DEBUG_EVENT)
+                                       zlog_debug("Subnetted route %s",
+                                                  inet_ntoa(rte->prefix));
+                       } else {
+                               if ((rte->prefix.s_addr & rte->mask.s_addr)
+                                   != rte->prefix.s_addr)
+                                       continue;
+                       }
+
+                       if (IS_RIP_DEBUG_EVENT) {
+                               zlog_debug("Resultant route %s",
+                                          inet_ntoa(rte->prefix));
+                               zlog_debug("Resultant mask %s",
+                                          inet_ntoa(rte->mask));
+                       }
+               }
+
+               /* In case of RIPv2, if prefix in RTE is not netmask applied one
+                  ignore the entry.  */
+               if ((packet->version == RIPv2) && (rte->mask.s_addr != 0)
+                   && ((rte->prefix.s_addr & rte->mask.s_addr)
+                       != rte->prefix.s_addr)) {
+                       zlog_warn(
+                               "RIPv2 address %s is not mask /%d applied one",
+                               inet_ntoa(rte->prefix), ip_masklen(rte->mask));
+                       rip_peer_bad_route(from);
+                       continue;
+               }
+
+               /* Default route's netmask is ignored. */
+               if (packet->version == RIPv2 && (rte->prefix.s_addr == 0)
+                   && (rte->mask.s_addr != 0)) {
+                       if (IS_RIP_DEBUG_EVENT)
+                               zlog_debug(
+                                       "Default route with non-zero netmask.  Set zero to netmask");
+                       rte->mask.s_addr = 0;
+               }
+
+               /* Routing table updates. */
+               rip_rte_process(rte, from, ifc->ifp);
        }
-         
-      /* Routing table updates. */
-      rip_rte_process (rte, from, ifc->ifp);
-    }
 }
 
 /* Make socket for RIP protocol. */
-static int 
-rip_create_socket (void)
-{
-  int ret;
-  int sock;
-  struct sockaddr_in addr;
-  
-  memset (&addr, 0, sizeof (struct sockaddr_in));
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = INADDR_ANY;
+static int rip_create_socket(void)
+{
+       int ret;
+       int sock;
+       struct sockaddr_in addr;
+
+       memset(&addr, 0, sizeof(struct sockaddr_in));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = INADDR_ANY;
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-  addr.sin_len = sizeof (struct sockaddr_in);
+       addr.sin_len = sizeof(struct sockaddr_in);
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
-  /* sending port must always be the RIP port */
-  addr.sin_port = htons (RIP_PORT_DEFAULT);
-  
-  /* Make datagram socket. */
-  sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
-  if (sock < 0) 
-    {
-      zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
-      exit (1);
-    }
-
-  sockopt_broadcast (sock);
-  sockopt_reuseaddr (sock);
-  sockopt_reuseport (sock);
-  setsockopt_ipv4_multicast_loop (sock, 0);
+       /* sending port must always be the RIP port */
+       addr.sin_port = htons(RIP_PORT_DEFAULT);
+
+       /* Make datagram socket. */
+       sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (sock < 0) {
+               zlog_err("Cannot create UDP socket: %s", safe_strerror(errno));
+               exit(1);
+       }
+
+       sockopt_broadcast(sock);
+       sockopt_reuseaddr(sock);
+       sockopt_reuseport(sock);
+       setsockopt_ipv4_multicast_loop(sock, 0);
 #ifdef RIP_RECVMSG
-  setsockopt_pktinfo (sock);
+       setsockopt_pktinfo(sock);
 #endif /* RIP_RECVMSG */
 #ifdef IPTOS_PREC_INTERNETCONTROL
-  setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
+       setsockopt_ipv4_tos(sock, IPTOS_PREC_INTERNETCONTROL);
 #endif
 
-  if (ripd_privs.change (ZPRIVS_RAISE))
-      zlog_err ("rip_create_socket: could not raise privs");
-  setsockopt_so_recvbuf (sock, RIP_UDP_RCV_BUF);
-  if ( (ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr))) < 0)
-  
-    {
-      int save_errno = errno;
-      if (ripd_privs.change (ZPRIVS_LOWER))
-        zlog_err ("rip_create_socket: could not lower privs");
-      
-      zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
-              sock, inet_ntoa(addr.sin_addr), 
-              (int) ntohs(addr.sin_port), 
-              safe_strerror(save_errno));
-      
-      close (sock);
-      return ret;
-    }
-  
-  if (ripd_privs.change (ZPRIVS_LOWER))
-      zlog_err ("rip_create_socket: could not lower privs");
-      
-  return sock;
+       if (ripd_privs.change(ZPRIVS_RAISE))
+               zlog_err("rip_create_socket: could not raise privs");
+       setsockopt_so_recvbuf(sock, RIP_UDP_RCV_BUF);
+       if ((ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr))) < 0)
+
+       {
+               int save_errno = errno;
+               if (ripd_privs.change(ZPRIVS_LOWER))
+                       zlog_err("rip_create_socket: could not lower privs");
+
+               zlog_err("%s: Can't bind socket %d to %s port %d: %s", __func__,
+                        sock, inet_ntoa(addr.sin_addr),
+                        (int)ntohs(addr.sin_port), safe_strerror(save_errno));
+
+               close(sock);
+               return ret;
+       }
+
+       if (ripd_privs.change(ZPRIVS_LOWER))
+               zlog_err("rip_create_socket: could not lower privs");
+
+       return sock;
 }
 
 /* RIP packet send to destination address, on interface denoted by
  * by connected argument. NULL to argument denotes destination should be
  * should be RIP multicast group
  */
-static int
-rip_send_packet (u_char * buf, int size, struct sockaddr_in *to,
-                 struct connected *ifc)
-{
-  int ret;
-  struct sockaddr_in sin;
-  
-  assert (ifc != NULL);
-  
-  if (IS_RIP_DEBUG_PACKET)
-    {
+static int rip_send_packet(u_char *buf, int size, struct sockaddr_in *to,
+                          struct connected *ifc)
+{
+       int ret;
+       struct sockaddr_in sin;
+
+       assert(ifc != NULL);
+
+       if (IS_RIP_DEBUG_PACKET) {
 #define ADDRESS_SIZE 20
-      char dst[ADDRESS_SIZE];
-      dst[ADDRESS_SIZE - 1] = '\0';
-      
-      if (to)
-        {
-          strncpy (dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
-        }
-      else
-        {
-          sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
-          strncpy (dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
-        }
+               char dst[ADDRESS_SIZE];
+               dst[ADDRESS_SIZE - 1] = '\0';
+
+               if (to) {
+                       strncpy(dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
+               } else {
+                       sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
+                       strncpy(dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
+               }
 #undef ADDRESS_SIZE
-      zlog_debug("rip_send_packet %s > %s (%s)",
-                inet_ntoa(ifc->address->u.prefix4),
-                dst, ifc->ifp->name);
-    }
-  
-  if ( CHECK_FLAG (ifc->flags, ZEBRA_IFA_SECONDARY) )
-    {
-      /*
-       * ZEBRA_IFA_SECONDARY is set on linux when an interface is configured
-       * with multiple addresses on the same subnet: the first address
-       * on the subnet is configured "primary", and all subsequent addresses
-       * on that subnet are treated as "secondary" addresses. 
-       * In order to avoid routing-table bloat on other rip listeners, 
-       * we do not send out RIP packets with ZEBRA_IFA_SECONDARY source addrs.
-       * XXX Since Linux is the only system for which the ZEBRA_IFA_SECONDARY
-       * flag is set, we would end up sending a packet for a "secondary"
-       * source address on non-linux systems.  
-       */
-      if (IS_RIP_DEBUG_PACKET)
-        zlog_debug("duplicate dropped");
-      return 0;
-    }
-
-  /* Make destination address. */
-  memset (&sin, 0, sizeof (struct sockaddr_in));
-  sin.sin_family = AF_INET;
+               zlog_debug("rip_send_packet %s > %s (%s)",
+                          inet_ntoa(ifc->address->u.prefix4), dst,
+                          ifc->ifp->name);
+       }
+
+       if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
+               /*
+                * ZEBRA_IFA_SECONDARY is set on linux when an interface is
+                * configured
+                * with multiple addresses on the same subnet: the first address
+                * on the subnet is configured "primary", and all subsequent
+                * addresses
+                * on that subnet are treated as "secondary" addresses.
+                * In order to avoid routing-table bloat on other rip listeners,
+                * we do not send out RIP packets with ZEBRA_IFA_SECONDARY
+                * source addrs.
+                * XXX Since Linux is the only system for which the
+                * ZEBRA_IFA_SECONDARY
+                * flag is set, we would end up sending a packet for a
+                * "secondary"
+                * source address on non-linux systems.
+                */
+               if (IS_RIP_DEBUG_PACKET)
+                       zlog_debug("duplicate dropped");
+               return 0;
+       }
+
+       /* Make destination address. */
+       memset(&sin, 0, sizeof(struct sockaddr_in));
+       sin.sin_family = AF_INET;
 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
-  sin.sin_len = sizeof (struct sockaddr_in);
+       sin.sin_len = sizeof(struct sockaddr_in);
 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
 
-  /* When destination is specified, use it's port and address. */
-  if (to)
-    {
-      sin.sin_port = to->sin_port;
-      sin.sin_addr = to->sin_addr;
-    }
-  else
-    {
-      sin.sin_port = htons (RIP_PORT_DEFAULT);
-      sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);
+       /* When destination is specified, use it's port and address. */
+       if (to) {
+               sin.sin_port = to->sin_port;
+               sin.sin_addr = to->sin_addr;
+       } else {
+               sin.sin_port = htons(RIP_PORT_DEFAULT);
+               sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
 
-      rip_interface_multicast_set (rip->sock, ifc);
-    }
+               rip_interface_multicast_set(rip->sock, ifc);
+       }
 
-  ret = sendto (rip->sock, buf, size, 0, (struct sockaddr *)&sin,
-               sizeof (struct sockaddr_in));
+       ret = sendto(rip->sock, buf, size, 0, (struct sockaddr *)&sin,
+                    sizeof(struct sockaddr_in));
 
-  if (IS_RIP_DEBUG_EVENT)
-      zlog_debug ("SEND to  %s.%d", inet_ntoa(sin.sin_addr), 
-                  ntohs (sin.sin_port));
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("SEND to  %s.%d", inet_ntoa(sin.sin_addr),
+                          ntohs(sin.sin_port));
 
-  if (ret < 0)
-    zlog_warn ("can't send packet : %s", safe_strerror (errno));
+       if (ret < 0)
+               zlog_warn("can't send packet : %s", safe_strerror(errno));
 
-  return ret;
+       return ret;
 }
 
 /* Add redistributed route to RIP table. */
-void
-rip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, 
-                     ifindex_t ifindex, struct in_addr *nexthop,
-                      unsigned int metric, unsigned char distance,
-                      route_tag_t tag)
-{
-  int ret;
-  struct route_node *rp = NULL;
-  struct rip_info *rinfo = NULL, newinfo;
-  struct list *list = NULL;
+void rip_redistribute_add(int type, int sub_type, struct prefix_ipv4 *p,
+                         struct nexthop *nh,
+                         unsigned int metric, unsigned char distance,
+                         route_tag_t tag)
+{
+       int ret;
+       struct route_node *rp = NULL;
+       struct rip_info *rinfo = NULL, newinfo;
+       struct list *list = NULL;
+
+       /* Redistribute route  */
+       ret = rip_destination_check(p->prefix);
+       if (!ret)
+               return;
+
+       rp = route_node_get(rip->table, (struct prefix *)p);
+
+       memset(&newinfo, 0, sizeof(struct rip_info));
+       newinfo.type = type;
+       newinfo.sub_type = sub_type;
+       newinfo.metric = 1;
+       newinfo.external_metric = metric;
+       newinfo.distance = distance;
+       if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */
+               newinfo.tag = tag;
+       newinfo.rp = rp;
+       newinfo.nh = *nh;
+
+       if ((list = rp->info) != NULL && listcount(list) != 0) {
+               rinfo = listgetdata(listhead(list));
+
+               if (rinfo->type == ZEBRA_ROUTE_CONNECT
+                   && rinfo->sub_type == RIP_ROUTE_INTERFACE
+                   && rinfo->metric != RIP_METRIC_INFINITY) {
+                       route_unlock_node(rp);
+                       return;
+               }
 
-  /* Redistribute route  */
-  ret = rip_destination_check (p->prefix);
-  if (! ret)
-    return;
-
-  rp = route_node_get (rip->table, (struct prefix *) p);
-
-  memset (&newinfo, 0, sizeof (struct rip_info));
-  newinfo.type = type;
-  newinfo.sub_type = sub_type;
-  newinfo.ifindex = ifindex;
-  newinfo.metric = 1;
-  newinfo.external_metric = metric;
-  newinfo.distance = distance;
-  if (tag <= UINT16_MAX) /* RIP only supports 16 bit tags */
-    newinfo.tag = tag;
-  newinfo.rp = rp;
-  if (nexthop)
-    newinfo.nexthop = *nexthop;
-
-  if ((list = rp->info) != NULL && listcount (list) != 0)
-    {
-      rinfo = listgetdata (listhead (list));
-
-      if (rinfo->type == ZEBRA_ROUTE_CONNECT 
-         && rinfo->sub_type == RIP_ROUTE_INTERFACE
-         && rinfo->metric != RIP_METRIC_INFINITY)
-       {
-         route_unlock_node (rp);
-         return;
+               /* Manually configured RIP route check. */
+               if (rinfo->type == ZEBRA_ROUTE_RIP
+                   && ((rinfo->sub_type == RIP_ROUTE_STATIC)
+                       || (rinfo->sub_type == RIP_ROUTE_DEFAULT))) {
+                       if (type != ZEBRA_ROUTE_RIP
+                           || ((sub_type != RIP_ROUTE_STATIC)
+                               && (sub_type != RIP_ROUTE_DEFAULT))) {
+                               route_unlock_node(rp);
+                               return;
+                       }
+               }
+
+               (void)rip_ecmp_replace(&newinfo);
+               route_unlock_node(rp);
+       } else
+               (void)rip_ecmp_add(&newinfo);
+
+       if (IS_RIP_DEBUG_EVENT) {
+               zlog_debug(
+                       "Redistribute new prefix %s/%d",
+                       inet_ntoa(p->prefix), p->prefixlen);
        }
 
-      /* Manually configured RIP route check. */
-      if (rinfo->type == ZEBRA_ROUTE_RIP 
-         && ((rinfo->sub_type == RIP_ROUTE_STATIC) ||
-             (rinfo->sub_type == RIP_ROUTE_DEFAULT)) )
-       {
-         if (type != ZEBRA_ROUTE_RIP || ((sub_type != RIP_ROUTE_STATIC) &&
-                                         (sub_type != RIP_ROUTE_DEFAULT)))
-           {
-             route_unlock_node (rp);
-             return;
-           }
-       }
-
-      rinfo = rip_ecmp_replace (&newinfo);
-      route_unlock_node (rp);
-    }
-  else
-    rinfo = rip_ecmp_add (&newinfo);
-
-  if (IS_RIP_DEBUG_EVENT) {
-    if (!nexthop)
-      zlog_debug ("Redistribute new prefix %s/%d on the interface %s",
-                  inet_ntoa(p->prefix), p->prefixlen,
-                  ifindex2ifname(ifindex, VRF_DEFAULT));
-    else
-      zlog_debug ("Redistribute new prefix %s/%d with nexthop %s on the interface %s",
-                  inet_ntoa(p->prefix), p->prefixlen, inet_ntoa(rinfo->nexthop),
-                  ifindex2ifname(ifindex, VRF_DEFAULT));
-  }
-
-  rip_event (RIP_TRIGGERED_UPDATE, 0);
+       rip_event(RIP_TRIGGERED_UPDATE, 0);
 }
 
 /* Delete redistributed route from RIP table. */
-void
-rip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, 
-                        ifindex_t ifindex)
-{
-  int ret;
-  struct route_node *rp;
-  struct rip_info *rinfo;
-
-  ret = rip_destination_check (p->prefix);
-  if (! ret)
-    return;
-
-  rp = route_node_lookup (rip->table, (struct prefix *) p);
-  if (rp)
-    {
-      struct list *list = rp->info;
-
-      if (list != NULL && listcount (list) != 0)
-        {
-          rinfo = listgetdata (listhead (list));
-          if (rinfo != NULL
-              && rinfo->type == type
-              && rinfo->sub_type == sub_type
-              && rinfo->ifindex == ifindex)
-            {
-              /* Perform poisoned reverse. */
-              rinfo->metric = RIP_METRIC_INFINITY;
-              RIP_TIMER_ON (rinfo->t_garbage_collect,
-                            rip_garbage_collect, rip->garbage_time);
-              RIP_TIMER_OFF (rinfo->t_timeout);
-              rinfo->flags |= RIP_RTF_CHANGED;
-
-              if (IS_RIP_DEBUG_EVENT)
-                zlog_debug ("Poisone %s/%d on the interface %s with an "
-                            "infinity metric [delete]",
-                            inet_ntoa(p->prefix), p->prefixlen,
-                            ifindex2ifname(ifindex, VRF_DEFAULT));
-
-              rip_event (RIP_TRIGGERED_UPDATE, 0);
-            }
-        }
-      route_unlock_node (rp);
-    }
+void rip_redistribute_delete(int type, int sub_type, struct prefix_ipv4 *p,
+                            ifindex_t ifindex)
+{
+       int ret;
+       struct route_node *rp;
+       struct rip_info *rinfo;
+
+       ret = rip_destination_check(p->prefix);
+       if (!ret)
+               return;
+
+       rp = route_node_lookup(rip->table, (struct prefix *)p);
+       if (rp) {
+               struct list *list = rp->info;
+
+               if (list != NULL && listcount(list) != 0) {
+                       rinfo = listgetdata(listhead(list));
+                       if (rinfo != NULL && rinfo->type == type
+                           && rinfo->sub_type == sub_type
+                           && rinfo->nh.ifindex == ifindex) {
+                               /* Perform poisoned reverse. */
+                               rinfo->metric = RIP_METRIC_INFINITY;
+                               RIP_TIMER_ON(rinfo->t_garbage_collect,
+                                            rip_garbage_collect,
+                                            rip->garbage_time);
+                               RIP_TIMER_OFF(rinfo->t_timeout);
+                               rinfo->flags |= RIP_RTF_CHANGED;
+
+                               if (IS_RIP_DEBUG_EVENT)
+                                       zlog_debug(
+                                               "Poison %s/%d on the interface %s with an "
+                                               "infinity metric [delete]",
+                                               inet_ntoa(p->prefix),
+                                               p->prefixlen,
+                                               ifindex2ifname(ifindex,
+                                                              VRF_DEFAULT));
+
+                               rip_event(RIP_TRIGGERED_UPDATE, 0);
+                       }
+               }
+               route_unlock_node(rp);
+       }
 }
 
 /* Response to request called from rip_read ().*/
-static void
-rip_request_process (struct rip_packet *packet, int size, 
-                    struct sockaddr_in *from, struct connected *ifc)
-{
-  caddr_t lim;
-  struct rte *rte;
-  struct prefix_ipv4 p;
-  struct route_node *rp;
-  struct rip_info *rinfo;
-  struct rip_interface *ri;
-
-  /* Does not reponse to the requests on the loopback interfaces */
-  if (if_is_loopback (ifc->ifp))
-    return;
-
-  /* Check RIP process is enabled on this interface. */
-  ri = ifc->ifp->info;
-  if (! ri->running)
-    return;
-
-  /* When passive interface is specified, suppress responses */
-  if (ri->passive)
-    return;
-  
-  /* RIP peer update. */
-  rip_peer_update (from, packet->version);
-
-  lim = ((caddr_t) packet) + size;
-  rte = packet->rte;
-
-  /* The Request is processed entry by entry.  If there are no
-     entries, no response is given. */
-  if (lim == (caddr_t) rte)
-    return;
-
-  /* There is one special case.  If there is exactly one entry in the
-     request, and it has an address family identifier of zero and a
-     metric of infinity (i.e., 16), then this is a request to send the
-     entire routing table. */
-  if (lim == ((caddr_t) (rte + 1)) &&
-      ntohs (rte->family) == 0 &&
-      ntohl (rte->metric) == RIP_METRIC_INFINITY)
-    {  
-      /* All route with split horizon */
-      rip_output_process (ifc, from, rip_all_route, packet->version);
-    }
-  else
-    {
-      if (ntohs (rte->family) != AF_INET)
-       return;
+static void rip_request_process(struct rip_packet *packet, int size,
+                               struct sockaddr_in *from, struct connected *ifc)
+{
+       caddr_t lim;
+       struct rte *rte;
+       struct prefix_ipv4 p;
+       struct route_node *rp;
+       struct rip_info *rinfo;
+       struct rip_interface *ri;
+
+       /* Does not reponse to the requests on the loopback interfaces */
+       if (if_is_loopback(ifc->ifp))
+               return;
+
+       /* Check RIP process is enabled on this interface. */
+       ri = ifc->ifp->info;
+       if (!ri->running)
+               return;
+
+       /* When passive interface is specified, suppress responses */
+       if (ri->passive)
+               return;
+
+       /* RIP peer update. */
+       rip_peer_update(from, packet->version);
+
+       lim = ((caddr_t)packet) + size;
+       rte = packet->rte;
+
+       /* The Request is processed entry by entry.  If there are no
+          entries, no response is given. */
+       if (lim == (caddr_t)rte)
+               return;
+
+       /* There is one special case.  If there is exactly one entry in the
+          request, and it has an address family identifier of zero and a
+          metric of infinity (i.e., 16), then this is a request to send the
+          entire routing table. */
+       if (lim == ((caddr_t)(rte + 1)) && ntohs(rte->family) == 0
+           && ntohl(rte->metric) == RIP_METRIC_INFINITY) {
+               /* All route with split horizon */
+               rip_output_process(ifc, from, rip_all_route, packet->version);
+       } else {
+               if (ntohs(rte->family) != AF_INET)
+                       return;
+
+               /* Examine the list of RTEs in the Request one by one.  For each
+                  entry, look up the destination in the router's routing
+                  database and, if there is a route, put that route's metric in
+                  the metric field of the RTE.  If there is no explicit route
+                  to the specified destination, put infinity in the metric
+                  field.  Once all the entries have been filled in, change the
+                  command from Request to Response and send the datagram back
+                  to the requestor. */
+               p.family = AF_INET;
+
+               for (; ((caddr_t)rte) < lim; rte++) {
+                       p.prefix = rte->prefix;
+                       p.prefixlen = ip_masklen(rte->mask);
+                       apply_mask_ipv4(&p);
+
+                       rp = route_node_lookup(rip->table, (struct prefix *)&p);
+                       if (rp) {
+                               rinfo = listgetdata(
+                                       listhead((struct list *)rp->info));
+                               rte->metric = htonl(rinfo->metric);
+                               route_unlock_node(rp);
+                       } else
+                               rte->metric = htonl(RIP_METRIC_INFINITY);
+               }
+               packet->command = RIP_RESPONSE;
 
-      /* Examine the list of RTEs in the Request one by one.  For each
-        entry, look up the destination in the router's routing
-        database and, if there is a route, put that route's metric in
-        the metric field of the RTE.  If there is no explicit route
-        to the specified destination, put infinity in the metric
-        field.  Once all the entries have been filled in, change the
-        command from Request to Response and send the datagram back
-        to the requestor. */
-      p.family = AF_INET;
-
-      for (; ((caddr_t) rte) < lim; rte++)
-       {
-         p.prefix = rte->prefix;
-         p.prefixlen = ip_masklen (rte->mask);
-         apply_mask_ipv4 (&p);
-         
-         rp = route_node_lookup (rip->table, (struct prefix *) &p);
-         if (rp)
-           {
-             rinfo = listgetdata (listhead ((struct list *)rp->info));
-             rte->metric = htonl (rinfo->metric);
-             route_unlock_node (rp);
-           }
-         else
-           rte->metric = htonl (RIP_METRIC_INFINITY);
-       }
-      packet->command = RIP_RESPONSE;
-
-      rip_send_packet ((u_char *)packet, size, from, ifc);
-    }
-  rip_global_queries++;
+               rip_send_packet((u_char *)packet, size, from, ifc);
+       }
+       rip_global_queries++;
 }
 
 #if RIP_RECVMSG
 /* Set IPv6 packet info to the socket. */
-static int
-setsockopt_pktinfo (int sock)
+static int setsockopt_pktinfo(int sock)
 {
-  int ret;
-  int val = 1;
-    
-  ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
-  if (ret < 0)
-    zlog_warn ("Can't setsockopt IP_PKTINFO : %s", safe_strerror (errno));
-  return ret;
+       int ret;
+       int val = 1;
+
+       ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));
+       if (ret < 0)
+               zlog_warn("Can't setsockopt IP_PKTINFO : %s",
+                         safe_strerror(errno));
+       return ret;
 }
 
 /* Read RIP packet by recvmsg function. */
-int
-rip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,
-            ifindex_t *ifindex)
-{
-  int ret;
-  struct msghdr msg;
-  struct iovec iov;
-  struct cmsghdr *ptr;
-  char adata[1024];
-
-  msg.msg_name = (void *) from;
-  msg.msg_namelen = sizeof (struct sockaddr_in);
-  msg.msg_iov = &iov;
-  msg.msg_iovlen = 1;
-  msg.msg_control = (void *) adata;
-  msg.msg_controllen = sizeof adata;
-  iov.iov_base = buf;
-  iov.iov_len = size;
-
-  ret = recvmsg (sock, &msg, 0);
-  if (ret < 0)
-    return ret;
-
-  for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))
-    if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO) 
-      {
-       struct in_pktinfo *pktinfo;
-       int i;
+int rip_recvmsg(int sock, u_char *buf, int size, struct sockaddr_in *from,
+               ifindex_t *ifindex)
+{
+       int ret;
+       struct msghdr msg;
+       struct iovec iov;
+       struct cmsghdr *ptr;
+       char adata[1024];
+
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_name = (void *)from;
+       msg.msg_namelen = sizeof(struct sockaddr_in);
+       msg.msg_iov = &iov;
+       msg.msg_iovlen = 1;
+       msg.msg_control = (void *)adata;
+       msg.msg_controllen = sizeof adata;
+       iov.iov_base = buf;
+       iov.iov_len = size;
+
+       ret = recvmsg(sock, &msg, 0);
+       if (ret < 0)
+               return ret;
 
-       pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);
-       i = pktinfo->ipi_ifindex;
-      }
-  return ret;
+       for (ptr = ZCMSG_FIRSTHDR(&msg); ptr != NULL;
+            ptr = CMSG_NXTHDR(&msg, ptr))
+               if (ptr->cmsg_level == IPPROTO_IP
+                   && ptr->cmsg_type == IP_PKTINFO) {
+                       struct in_pktinfo *pktinfo;
+                       int i;
+
+                       pktinfo = (struct in_pktinfo *)CMSG_DATA(ptr);
+                       i = pktinfo->ipi_ifindex;
+               }
+       return ret;
 }
 
 /* RIP packet read function. */
-int
-rip_read_new (struct thread *t)
-{
-  int ret;
-  int sock;
-  char buf[RIP_PACKET_MAXSIZ];
-  struct sockaddr_in from;
-  ifindex_t ifindex;
-  
-  /* Fetch socket then register myself. */
-  sock = THREAD_FD (t);
-  rip_event (RIP_READ, sock);
-
-  /* Read RIP packet. */
-  ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
-  if (ret < 0)
-    {
-      zlog_warn ("Can't read RIP packet: %s", safe_strerror (errno));
-      return ret;
-    }
-
-  return ret;
+int rip_read_new(struct thread *t)
+{
+       int ret;
+       int sock;
+       char buf[RIP_PACKET_MAXSIZ];
+       struct sockaddr_in from;
+       ifindex_t ifindex;
+
+       /* Fetch socket then register myself. */
+       sock = THREAD_FD(t);
+       rip_event(RIP_READ, sock);
+
+       /* Read RIP packet. */
+       ret = rip_recvmsg(sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);
+       if (ret < 0) {
+               zlog_warn("Can't read RIP packet: %s", safe_strerror(errno));
+               return ret;
+       }
+
+       return ret;
 }
 #endif /* RIP_RECVMSG */
 
 /* First entry point of RIP packet. */
-static int
-rip_read (struct thread *t)
-{
-  int sock;
-  int ret;
-  int rtenum;
-  union rip_buf rip_buf;
-  struct rip_packet *packet;
-  struct sockaddr_in from;
-  int len;
-  int vrecv;
-  socklen_t fromlen;
-  struct interface *ifp = NULL;
-  struct connected *ifc;
-  struct rip_interface *ri;
-  struct prefix p;
-
-  /* Fetch socket then register myself. */
-  sock = THREAD_FD (t);
-  rip->t_read = NULL;
-
-  /* Add myself to tne next event */
-  rip_event (RIP_READ, sock);
-
-  /* RIPd manages only IPv4. */
-  memset (&from, 0, sizeof (struct sockaddr_in));
-  fromlen = sizeof (struct sockaddr_in);
-
-  len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0, 
-                 (struct sockaddr *) &from, &fromlen);
-  if (len < 0) 
-    {
-      zlog_info ("recvfrom failed: %s", safe_strerror (errno));
-      return len;
-    }
-
-  /* Check is this packet comming from myself? */
-  if (if_check_address (from.sin_addr)) 
-    {
-      if (IS_RIP_DEBUG_PACKET)
-       zlog_debug ("ignore packet comes from myself");
-      return -1;
-    }
-
-  /* Which interface is this packet comes from. */
-  ifc = if_lookup_address ((void *)&from.sin_addr, AF_INET, VRF_DEFAULT);
-  if (ifc)
-    ifp = ifc->ifp;
-
-  /* RIP packet received */
-  if (IS_RIP_DEBUG_EVENT)
-    zlog_debug ("RECV packet from %s port %d on %s",
-              inet_ntoa (from.sin_addr), ntohs (from.sin_port),
-              ifp ? ifp->name : "unknown");
-
-  /* If this packet come from unknown interface, ignore it. */
-  if (ifp == NULL)
-    {
-      zlog_info ("rip_read: cannot find interface for packet from %s port %d",
-                inet_ntoa(from.sin_addr), ntohs (from.sin_port));
-      return -1;
-    }
-
-  p.family = AF_INET;
-  p.u.prefix4 = from.sin_addr;
-  p.prefixlen = IPV4_MAX_BITLEN;
-
-  ifc = connected_lookup_prefix (ifp, &p);
-  
-  if (ifc == NULL)
-    {
-      zlog_info ("rip_read: cannot find connected address for packet from %s "
-                "port %d on interface %s",
-                inet_ntoa(from.sin_addr), ntohs (from.sin_port), ifp->name);
-      return -1;
-    }
-
-  /* Packet length check. */
-  if (len < RIP_PACKET_MINSIZ)
-    {
-      zlog_warn ("packet size %d is smaller than minimum size %d",
-                len, RIP_PACKET_MINSIZ);
-      rip_peer_bad_packet (&from);
-      return len;
-    }
-  if (len > RIP_PACKET_MAXSIZ)
-    {
-      zlog_warn ("packet size %d is larger than max size %d",
-                len, RIP_PACKET_MAXSIZ);
-      rip_peer_bad_packet (&from);
-      return len;
-    }
-
-  /* Packet alignment check. */
-  if ((len - RIP_PACKET_MINSIZ) % 20)
-    {
-      zlog_warn ("packet size %d is wrong for RIP packet alignment", len);
-      rip_peer_bad_packet (&from);
-      return len;
-    }
-
-  /* Set RTE number. */
-  rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
-
-  /* For easy to handle. */
-  packet = &rip_buf.rip_packet;
-
-  /* RIP version check. */
-  if (packet->version == 0)
-    {
-      zlog_info ("version 0 with command %d received.", packet->command);
-      rip_peer_bad_packet (&from);
-      return -1;
-    }
-
-  /* Dump RIP packet. */
-  if (IS_RIP_DEBUG_RECV)
-    rip_packet_dump (packet, len, "RECV");
-
-  /* RIP version adjust.  This code should rethink now.  RFC1058 says
-     that "Version 1 implementations are to ignore this extra data and
-     process only the fields specified in this document.". So RIPv3
-     packet should be treated as RIPv1 ignoring must be zero field. */
-  if (packet->version > RIPv2)
-    packet->version = RIPv2;
-
-  /* Is RIP running or is this RIP neighbor ?*/
-  ri = ifp->info;
-  if (! ri->running && ! rip_neighbor_lookup (&from))
-    {
-      if (IS_RIP_DEBUG_EVENT)
-       zlog_debug ("RIP is not enabled on interface %s.", ifp->name);
-      rip_peer_bad_packet (&from);
-      return -1;
-    }
-
-  /* RIP Version check. RFC2453, 4.6 and 5.1 */
-  vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ?
-           rip->version_recv : ri->ri_receive);
-  if (vrecv == RI_RIP_VERSION_NONE ||
-      ((packet->version == RIPv1) && !(vrecv & RIPv1)) ||
-      ((packet->version == RIPv2) && !(vrecv & RIPv2)))
-    {
-      if (IS_RIP_DEBUG_PACKET)
-        zlog_debug ("  packet's v%d doesn't fit to if version spec", 
-                   packet->version);
-      rip_peer_bad_packet (&from);
-      return -1;
-    }
-  
-  /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
-     messages, then RIP-1 and unauthenticated RIP-2 messages will be
-     accepted; authenticated RIP-2 messages shall be discarded.  */
-  if ((ri->auth_type == RIP_NO_AUTH) 
-      && rtenum 
-      && (packet->version == RIPv2) 
-      && (packet->rte->family == htons(RIP_FAMILY_AUTH)))
-    {
-      if (IS_RIP_DEBUG_EVENT)
-       zlog_debug ("packet RIPv%d is dropped because authentication disabled", 
-                  packet->version);
-      rip_peer_bad_packet (&from);
-      return -1;
-    }
-  
-  /* RFC:
-     If the router is configured to authenticate RIP-2 messages, then
-     RIP-1 messages and RIP-2 messages which pass authentication
-     testing shall be accepted; unauthenticated and failed
-     authentication RIP-2 messages shall be discarded.  For maximum
-     security, RIP-1 messages should be ignored when authentication is
-     in use (see section 4.1); otherwise, the routing information from
-     authenticated messages will be propagated by RIP-1 routers in an
-     unauthenticated manner. 
-  */
-  /* We make an exception for RIPv1 REQUEST packets, to which we'll
-   * always reply regardless of authentication settings, because:
-   *
-   * - if there other authorised routers on-link, the REQUESTor can
-   *   passively obtain the routing updates anyway
-   * - if there are no other authorised routers on-link, RIP can
-   *   easily be disabled for the link to prevent giving out information
-   *   on state of this routers RIP routing table..
-   *
-   * I.e. if RIPv1 has any place anymore these days, it's as a very
-   * simple way to distribute routing information (e.g. to embedded
-   * hosts / appliances) and the ability to give out RIPv1
-   * routing-information freely, while still requiring RIPv2
-   * authentication for any RESPONSEs might be vaguely useful.
-   */
-  if (ri->auth_type != RIP_NO_AUTH 
-      && packet->version == RIPv1)
-    {
-      /* Discard RIPv1 messages other than REQUESTs */
-      if (packet->command != RIP_REQUEST)
-        {
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIPv1" " dropped because authentication enabled");
-          rip_peer_bad_packet (&from);
-          return -1;
-        }
-    }
-  else if (ri->auth_type != RIP_NO_AUTH)
-    {
-      const char *auth_desc;
-      
-      if (rtenum == 0)
-        {
-          /* There definitely is no authentication in the packet. */
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIPv2 authentication failed: no auth RTE in packet");
-          rip_peer_bad_packet (&from);
-          return -1;
-        }
-      
-      /* First RTE must be an Authentication Family RTE */
-      if (packet->rte->family != htons(RIP_FAMILY_AUTH))
-        {
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIPv2" " dropped because authentication enabled");
-         rip_peer_bad_packet (&from);
-         return -1;
-        }
-      
-      /* Check RIPv2 authentication. */
-      switch (ntohs(packet->rte->tag))
-        {
-          case RIP_AUTH_SIMPLE_PASSWORD:
-            auth_desc = "simple";
-            ret = rip_auth_simple_password (packet->rte, &from, ifp);
-            break;
-          
-          case RIP_AUTH_MD5:
-            auth_desc = "MD5";
-            ret = rip_auth_md5 (packet, &from, len, ifp);
-            /* Reset RIP packet length to trim MD5 data. */
-            len = ret;
-            break;
-          
-          default:
-            ret = 0;
-            auth_desc = "unknown type";
-            if (IS_RIP_DEBUG_PACKET)
-              zlog_debug ("RIPv2 Unknown authentication type %d",
-                          ntohs (packet->rte->tag));
-        }
-      
-      if (ret)
-        {
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIPv2 %s authentication success", auth_desc);
-        }
-      else
-        {
-          if (IS_RIP_DEBUG_PACKET)
-            zlog_debug ("RIPv2 %s authentication failure", auth_desc);
-          rip_peer_bad_packet (&from);
-          return -1;
-        }
-    }
-  
-  /* Process each command. */
-  switch (packet->command)
-    {
-    case RIP_RESPONSE:
-      rip_response_process (packet, len, &from, ifc);
-      break;
-    case RIP_REQUEST:
-    case RIP_POLL:
-      rip_request_process (packet, len, &from, ifc);
-      break;
-    case RIP_TRACEON:
-    case RIP_TRACEOFF:
-      zlog_info ("Obsolete command %s received, please sent it to routed", 
-                lookup_msg (rip_msg, packet->command, NULL));
-      rip_peer_bad_packet (&from);
-      break;
-    case RIP_POLL_ENTRY:
-      zlog_info ("Obsolete command %s received", 
-                lookup_msg (rip_msg, packet->command, NULL));
-      rip_peer_bad_packet (&from);
-      break;
-    default:
-      zlog_info ("Unknown RIP command %d received", packet->command);
-      rip_peer_bad_packet (&from);
-      break;
-    }
-
-  return len;
+static int rip_read(struct thread *t)
+{
+       int sock;
+       int ret;
+       int rtenum;
+       union rip_buf rip_buf;
+       struct rip_packet *packet;
+       struct sockaddr_in from;
+       int len;
+       int vrecv;
+       socklen_t fromlen;
+       struct interface *ifp = NULL;
+       struct connected *ifc;
+       struct rip_interface *ri;
+       struct prefix p;
+
+       /* Fetch socket then register myself. */
+       sock = THREAD_FD(t);
+       rip->t_read = NULL;
+
+       /* Add myself to tne next event */
+       rip_event(RIP_READ, sock);
+
+       /* RIPd manages only IPv4. */
+       memset(&from, 0, sizeof(struct sockaddr_in));
+       fromlen = sizeof(struct sockaddr_in);
+
+       len = recvfrom(sock, (char *)&rip_buf.buf, sizeof(rip_buf.buf), 0,
+                      (struct sockaddr *)&from, &fromlen);
+       if (len < 0) {
+               zlog_info("recvfrom failed: %s", safe_strerror(errno));
+               return len;
+       }
+
+       /* Check is this packet comming from myself? */
+       if (if_check_address(from.sin_addr)) {
+               if (IS_RIP_DEBUG_PACKET)
+                       zlog_debug("ignore packet comes from myself");
+               return -1;
+       }
+
+       /* Which interface is this packet comes from. */
+       ifc = if_lookup_address((void *)&from.sin_addr, AF_INET, VRF_DEFAULT);
+       if (ifc)
+               ifp = ifc->ifp;
+
+       /* RIP packet received */
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("RECV packet from %s port %d on %s",
+                          inet_ntoa(from.sin_addr), ntohs(from.sin_port),
+                          ifp ? ifp->name : "unknown");
+
+       /* If this packet come from unknown interface, ignore it. */
+       if (ifp == NULL) {
+               zlog_info(
+                       "rip_read: cannot find interface for packet from %s port %d",
+                       inet_ntoa(from.sin_addr), ntohs(from.sin_port));
+               return -1;
+       }
+
+       p.family = AF_INET;
+       p.u.prefix4 = from.sin_addr;
+       p.prefixlen = IPV4_MAX_BITLEN;
+
+       ifc = connected_lookup_prefix(ifp, &p);
+
+       if (ifc == NULL) {
+               zlog_info(
+                       "rip_read: cannot find connected address for packet from %s "
+                       "port %d on interface %s",
+                       inet_ntoa(from.sin_addr), ntohs(from.sin_port),
+                       ifp->name);
+               return -1;
+       }
+
+       /* Packet length check. */
+       if (len < RIP_PACKET_MINSIZ) {
+               zlog_warn("packet size %d is smaller than minimum size %d", len,
+                         RIP_PACKET_MINSIZ);
+               rip_peer_bad_packet(&from);
+               return len;
+       }
+       if (len > RIP_PACKET_MAXSIZ) {
+               zlog_warn("packet size %d is larger than max size %d", len,
+                         RIP_PACKET_MAXSIZ);
+               rip_peer_bad_packet(&from);
+               return len;
+       }
+
+       /* Packet alignment check. */
+       if ((len - RIP_PACKET_MINSIZ) % 20) {
+               zlog_warn("packet size %d is wrong for RIP packet alignment",
+                         len);
+               rip_peer_bad_packet(&from);
+               return len;
+       }
+
+       /* Set RTE number. */
+       rtenum = ((len - RIP_PACKET_MINSIZ) / 20);
+
+       /* For easy to handle. */
+       packet = &rip_buf.rip_packet;
+
+       /* RIP version check. */
+       if (packet->version == 0) {
+               zlog_info("version 0 with command %d received.",
+                         packet->command);
+               rip_peer_bad_packet(&from);
+               return -1;
+       }
+
+       /* Dump RIP packet. */
+       if (IS_RIP_DEBUG_RECV)
+               rip_packet_dump(packet, len, "RECV");
+
+       /* RIP version adjust.  This code should rethink now.  RFC1058 says
+          that "Version 1 implementations are to ignore this extra data and
+          process only the fields specified in this document.". So RIPv3
+          packet should be treated as RIPv1 ignoring must be zero field. */
+       if (packet->version > RIPv2)
+               packet->version = RIPv2;
+
+       /* Is RIP running or is this RIP neighbor ?*/
+       ri = ifp->info;
+       if (!ri->running && !rip_neighbor_lookup(&from)) {
+               if (IS_RIP_DEBUG_EVENT)
+                       zlog_debug("RIP is not enabled on interface %s.",
+                                  ifp->name);
+               rip_peer_bad_packet(&from);
+               return -1;
+       }
+
+       /* RIP Version check. RFC2453, 4.6 and 5.1 */
+       vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv
+                                                  : ri->ri_receive);
+       if (vrecv == RI_RIP_VERSION_NONE
+           || ((packet->version == RIPv1) && !(vrecv & RIPv1))
+           || ((packet->version == RIPv2) && !(vrecv & RIPv2))) {
+               if (IS_RIP_DEBUG_PACKET)
+                       zlog_debug(
+                               "  packet's v%d doesn't fit to if version spec",
+                               packet->version);
+               rip_peer_bad_packet(&from);
+               return -1;
+       }
+
+       /* RFC2453 5.2 If the router is not configured to authenticate RIP-2
+          messages, then RIP-1 and unauthenticated RIP-2 messages will be
+          accepted; authenticated RIP-2 messages shall be discarded.  */
+       if ((ri->auth_type == RIP_NO_AUTH) && rtenum
+           && (packet->version == RIPv2)
+           && (packet->rte->family == htons(RIP_FAMILY_AUTH))) {
+               if (IS_RIP_DEBUG_EVENT)
+                       zlog_debug(
+                               "packet RIPv%d is dropped because authentication disabled",
+                               packet->version);
+               rip_peer_bad_packet(&from);
+               return -1;
+       }
+
+       /* RFC:
+          If the router is configured to authenticate RIP-2 messages, then
+          RIP-1 messages and RIP-2 messages which pass authentication
+          testing shall be accepted; unauthenticated and failed
+          authentication RIP-2 messages shall be discarded.  For maximum
+          security, RIP-1 messages should be ignored when authentication is
+          in use (see section 4.1); otherwise, the routing information from
+          authenticated messages will be propagated by RIP-1 routers in an
+          unauthenticated manner.
+       */
+       /* We make an exception for RIPv1 REQUEST packets, to which we'll
+        * always reply regardless of authentication settings, because:
+        *
+        * - if there other authorised routers on-link, the REQUESTor can
+        *   passively obtain the routing updates anyway
+        * - if there are no other authorised routers on-link, RIP can
+        *   easily be disabled for the link to prevent giving out information
+        *   on state of this routers RIP routing table..
+        *
+        * I.e. if RIPv1 has any place anymore these days, it's as a very
+        * simple way to distribute routing information (e.g. to embedded
+        * hosts / appliances) and the ability to give out RIPv1
+        * routing-information freely, while still requiring RIPv2
+        * authentication for any RESPONSEs might be vaguely useful.
+        */
+       if (ri->auth_type != RIP_NO_AUTH && packet->version == RIPv1) {
+               /* Discard RIPv1 messages other than REQUESTs */
+               if (packet->command != RIP_REQUEST) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug(
+                                       "RIPv1"
+                                       " dropped because authentication enabled");
+                       rip_peer_bad_packet(&from);
+                       return -1;
+               }
+       } else if (ri->auth_type != RIP_NO_AUTH) {
+               const char *auth_desc;
+
+               if (rtenum == 0) {
+                       /* There definitely is no authentication in the packet.
+                        */
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug(
+                                       "RIPv2 authentication failed: no auth RTE in packet");
+                       rip_peer_bad_packet(&from);
+                       return -1;
+               }
+
+               /* First RTE must be an Authentication Family RTE */
+               if (packet->rte->family != htons(RIP_FAMILY_AUTH)) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug(
+                                       "RIPv2"
+                                       " dropped because authentication enabled");
+                       rip_peer_bad_packet(&from);
+                       return -1;
+               }
+
+               /* Check RIPv2 authentication. */
+               switch (ntohs(packet->rte->tag)) {
+               case RIP_AUTH_SIMPLE_PASSWORD:
+                       auth_desc = "simple";
+                       ret = rip_auth_simple_password(packet->rte, &from, ifp);
+                       break;
+
+               case RIP_AUTH_MD5:
+                       auth_desc = "MD5";
+                       ret = rip_auth_md5(packet, &from, len, ifp);
+                       /* Reset RIP packet length to trim MD5 data. */
+                       len = ret;
+                       break;
+
+               default:
+                       ret = 0;
+                       auth_desc = "unknown type";
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug(
+                                       "RIPv2 Unknown authentication type %d",
+                                       ntohs(packet->rte->tag));
+               }
+
+               if (ret) {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug("RIPv2 %s authentication success",
+                                          auth_desc);
+               } else {
+                       if (IS_RIP_DEBUG_PACKET)
+                               zlog_debug("RIPv2 %s authentication failure",
+                                          auth_desc);
+                       rip_peer_bad_packet(&from);
+                       return -1;
+               }
+       }
+
+       /* Process each command. */
+       switch (packet->command) {
+       case RIP_RESPONSE:
+               rip_response_process(packet, len, &from, ifc);
+               break;
+       case RIP_REQUEST:
+       case RIP_POLL:
+               rip_request_process(packet, len, &from, ifc);
+               break;
+       case RIP_TRACEON:
+       case RIP_TRACEOFF:
+               zlog_info(
+                       "Obsolete command %s received, please sent it to routed",
+                       lookup_msg(rip_msg, packet->command, NULL));
+               rip_peer_bad_packet(&from);
+               break;
+       case RIP_POLL_ENTRY:
+               zlog_info("Obsolete command %s received",
+                         lookup_msg(rip_msg, packet->command, NULL));
+               rip_peer_bad_packet(&from);
+               break;
+       default:
+               zlog_info("Unknown RIP command %d received", packet->command);
+               rip_peer_bad_packet(&from);
+               break;
+       }
+
+       return len;
 }
 
 /* Write routing table entry to the stream and return next index of
    the routing table entry in the stream. */
-static int
-rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,
-               u_char version, struct rip_info *rinfo)
-{
-  struct in_addr mask;
-
-  /* Write routing table entry. */
-  if (version == RIPv1)
-    {
-      stream_putw (s, AF_INET);
-      stream_putw (s, 0);
-      stream_put_ipv4 (s, p->prefix.s_addr);
-      stream_put_ipv4 (s, 0);
-      stream_put_ipv4 (s, 0);
-      stream_putl (s, rinfo->metric_out);
-    }
-  else
-    {
-      masklen2ip (p->prefixlen, &mask);
-
-      stream_putw (s, AF_INET);
-      stream_putw (s, rinfo->tag_out);
-      stream_put_ipv4 (s, p->prefix.s_addr);
-      stream_put_ipv4 (s, mask.s_addr);
-      stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);
-      stream_putl (s, rinfo->metric_out);
-    }
-
-  return ++num;
+static int rip_write_rte(int num, struct stream *s, struct prefix_ipv4 *p,
+                        u_char version, struct rip_info *rinfo)
+{
+       struct in_addr mask;
+
+       /* Write routing table entry. */
+       if (version == RIPv1) {
+               stream_putw(s, AF_INET);
+               stream_putw(s, 0);
+               stream_put_ipv4(s, p->prefix.s_addr);
+               stream_put_ipv4(s, 0);
+               stream_put_ipv4(s, 0);
+               stream_putl(s, rinfo->metric_out);
+       } else {
+               masklen2ip(p->prefixlen, &mask);
+
+               stream_putw(s, AF_INET);
+               stream_putw(s, rinfo->tag_out);
+               stream_put_ipv4(s, p->prefix.s_addr);
+               stream_put_ipv4(s, mask.s_addr);
+               stream_put_ipv4(s, rinfo->nexthop_out.s_addr);
+               stream_putl(s, rinfo->metric_out);
+       }
+
+       return ++num;
 }
 
 /* Send update to the ifp or spcified neighbor. */
-void
-rip_output_process (struct connected *ifc, struct sockaddr_in *to, 
-                    int route_type, u_char version)
-{
-  int ret;
-  struct stream *s;
-  struct route_node *rp;
-  struct rip_info *rinfo;
-  struct rip_interface *ri;
-  struct prefix_ipv4 *p;
-  struct prefix_ipv4 classfull;
-  struct prefix_ipv4 ifaddrclass;
-  struct key *key = NULL;
-  /* this might need to made dynamic if RIP ever supported auth methods
-     with larger key string sizes */
-  char auth_str[RIP_AUTH_SIMPLE_SIZE];
-  size_t doff = 0; /* offset of digest offset field */
-  int num = 0;
-  int rtemax;
-  int subnetted = 0;
-  struct list *list = NULL;
-  struct listnode *listnode = NULL;
+void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
+                       int route_type, u_char version)
+{
+       int ret;
+       struct stream *s;
+       struct route_node *rp;
+       struct rip_info *rinfo;
+       struct rip_interface *ri;
+       struct prefix_ipv4 *p;
+       struct prefix_ipv4 classfull;
+       struct prefix_ipv4 ifaddrclass;
+       struct key *key = NULL;
+       /* this might need to made dynamic if RIP ever supported auth methods
+          with larger key string sizes */
+       char auth_str[RIP_AUTH_SIMPLE_SIZE];
+       size_t doff = 0; /* offset of digest offset field */
+       int num = 0;
+       int rtemax;
+       int subnetted = 0;
+       struct list *list = NULL;
+       struct listnode *listnode = NULL;
+
+       /* Logging output event. */
+       if (IS_RIP_DEBUG_EVENT) {
+               if (to)
+                       zlog_debug("update routes to neighbor %s",
+                                  inet_ntoa(to->sin_addr));
+               else
+                       zlog_debug("update routes on interface %s ifindex %d",
+                                  ifc->ifp->name, ifc->ifp->ifindex);
+       }
 
-  /* Logging output event. */
-  if (IS_RIP_DEBUG_EVENT)
-    {
-      if (to)
-       zlog_debug ("update routes to neighbor %s", inet_ntoa (to->sin_addr));
-      else
-       zlog_debug ("update routes on interface %s ifindex %d",
-                  ifc->ifp->name, ifc->ifp->ifindex);
-    }
-
-  /* Set output stream. */
-  s = rip->obuf;
-
-  /* Reset stream and RTE counter. */
-  stream_reset (s);
-  rtemax = RIP_MAX_RTE;
-
-  /* Get RIP interface. */
-  ri = ifc->ifp->info;
-    
-  /* If output interface is in simple password authentication mode, we
-     need space for authentication data.  */
-  if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
-    rtemax -= 1;
-
-  /* If output interface is in MD5 authentication mode, we need space
-     for authentication header and data. */
-  if (ri->auth_type == RIP_AUTH_MD5)
-    rtemax -= 2;
-
-  /* If output interface is in simple password authentication mode
-     and string or keychain is specified we need space for auth. data */
-  if (ri->auth_type != RIP_NO_AUTH)
-    {
-      if (ri->key_chain)
-       {
-         struct keychain *keychain;
-
-         keychain = keychain_lookup (ri->key_chain);
-         if (keychain)
-           key = key_lookup_for_send (keychain);
-       }
-      /* to be passed to auth functions later */
-      rip_auth_prepare_str_send (ri, key, auth_str, RIP_AUTH_SIMPLE_SIZE);
-    }
-
-  if (version == RIPv1)
-    {
-      memcpy (&ifaddrclass, ifc->address, sizeof (struct prefix_ipv4));
-      apply_classful_mask_ipv4 (&ifaddrclass);
-      subnetted = 0;
-      if (ifc->address->prefixlen > ifaddrclass.prefixlen)
-        subnetted = 1;
-    }
-
-  for (rp = route_top (rip->table); rp; rp = route_next (rp))
-    if ((list = rp->info) != NULL && listcount (list) != 0)
-      {
-        rinfo = listgetdata (listhead (list));
-       /* For RIPv1, if we are subnetted, output subnets in our network    */
-       /* that have the same mask as the output "interface". For other     */
-       /* networks, only the classfull version is output.                  */
-       
-       if (version == RIPv1)
-         {
-           p = (struct prefix_ipv4 *) &rp->p;
-
-           if (IS_RIP_DEBUG_PACKET)
-             zlog_debug("RIPv1 mask check, %s/%d considered for output",
-                       inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
-
-           if (subnetted &&
-               prefix_match ((struct prefix *) &ifaddrclass, &rp->p))
-             {
-               if ((ifc->address->prefixlen != rp->p.prefixlen) &&
-                   (rp->p.prefixlen != 32))
-                 continue;
-             }
-           else
-             {
-               memcpy (&classfull, &rp->p, sizeof(struct prefix_ipv4));
-               apply_classful_mask_ipv4(&classfull);
-               if (rp->p.u.prefix4.s_addr != 0 &&
-                   classfull.prefixlen != rp->p.prefixlen)
-                 continue;
-             }
-           if (IS_RIP_DEBUG_PACKET)
-             zlog_debug("RIPv1 mask check, %s/%d made it through",
-                       inet_ntoa (rp->p.u.prefix4), rp->p.prefixlen);
-         }
-       else 
-         p = (struct prefix_ipv4 *) &rp->p;
-
-       /* Apply output filters. */
-       ret = rip_filter (RIP_FILTER_OUT, p, ri);
-       if (ret < 0)
-         continue;
-
-       /* Changed route only output. */
-       if (route_type == rip_changed_route &&
-           (! (rinfo->flags & RIP_RTF_CHANGED)))
-         continue;
-
-       /* Split horizon. */
-       /* if (split_horizon == rip_split_horizon) */
-       if (ri->split_horizon == RIP_SPLIT_HORIZON)
-         {
-           /* 
-            * We perform split horizon for RIP and connected route. 
-            * For rip routes, we want to suppress the route if we would
-             * end up sending the route back on the interface that we
-             * learned it from, with a higher metric. For connected routes,
-             * we suppress the route if the prefix is a subset of the
-             * source address that we are going to use for the packet 
-             * (in order to handle the case when multiple subnets are
-             * configured on the same interface).
-             */
-           int suppress = 0;
-           struct rip_info *tmp_rinfo = NULL;
-
-           for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
-             if (tmp_rinfo->type == ZEBRA_ROUTE_RIP &&
-                 tmp_rinfo->ifindex == ifc->ifp->ifindex)
-               {
-                 suppress = 1;
-                 break;
-               }
-
-           if (!suppress && rinfo->type == ZEBRA_ROUTE_CONNECT &&
-                 prefix_match((struct prefix *)p, ifc->address))
-             suppress = 1;
-
-           if (suppress)
-             continue;
-         }
-
-       /* Preparation for route-map. */
-       rinfo->metric_set = 0;
-       rinfo->nexthop_out.s_addr = 0;
-       rinfo->metric_out = rinfo->metric;
-       rinfo->tag_out = rinfo->tag;
-       rinfo->ifindex_out = ifc->ifp->ifindex;
-
-       /* In order to avoid some local loops,
-        * if the RIP route has a nexthop via this interface, keep the nexthop,
-        * otherwise set it to 0. The nexthop should not be propagated
-        * beyond the local broadcast/multicast area in order
-        * to avoid an IGP multi-level recursive look-up.
-        * see (4.4)
-        */
-       if (rinfo->ifindex == ifc->ifp->ifindex)
-         rinfo->nexthop_out = rinfo->nexthop;
-
-       /* Interface route-map */
-       if (ri->routemap[RIP_FILTER_OUT])
-         {
-           ret = route_map_apply (ri->routemap[RIP_FILTER_OUT], 
-                                    (struct prefix *) p, RMAP_RIP, 
-                                    rinfo);
-
-           if (ret == RMAP_DENYMATCH)
-             {
-               if (IS_RIP_DEBUG_PACKET)
-                 zlog_debug ("RIP %s/%d is filtered by route-map out",
-                              inet_ntoa (p->prefix), p->prefixlen);
-                continue;
-             }
-         }
-           
-       /* Apply redistribute route map - continue, if deny */
-       if (rip->route_map[rinfo->type].name
-           && rinfo->sub_type != RIP_ROUTE_INTERFACE)
-         {
-           ret = route_map_apply (rip->route_map[rinfo->type].map,
-                                  (struct prefix *)p, RMAP_RIP, rinfo);
-
-           if (ret == RMAP_DENYMATCH) 
-             {
-               if (IS_RIP_DEBUG_PACKET)
-                 zlog_debug ("%s/%d is filtered by route-map",
-                            inet_ntoa (p->prefix), p->prefixlen);
-               continue;
-             }
-         }
-
-       /* When route-map does not set metric. */
-       if (! rinfo->metric_set)
-         {
-           /* If redistribute metric is set. */
-           if (rip->route_map[rinfo->type].metric_config
-               && rinfo->metric != RIP_METRIC_INFINITY)
-             {
-               rinfo->metric_out = rip->route_map[rinfo->type].metric;
-             }
-           else
-             {
-               /* If the route is not connected or localy generated
-                  one, use default-metric value*/
-               if (rinfo->type != ZEBRA_ROUTE_RIP 
-                   && rinfo->type != ZEBRA_ROUTE_CONNECT
-                   && rinfo->metric != RIP_METRIC_INFINITY)
-                 rinfo->metric_out = rip->default_metric;
-             }
-         }
-
-       /* Apply offset-list */
-       if (rinfo->metric != RIP_METRIC_INFINITY)
-         rip_offset_list_apply_out (p, ifc->ifp, &rinfo->metric_out);
-
-       if (rinfo->metric_out > RIP_METRIC_INFINITY)
-         rinfo->metric_out = RIP_METRIC_INFINITY;
-
-       /* Perform split-horizon with poisoned reverse 
-        * for RIP and connected routes.
-        **/
-       if (ri->split_horizon == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
-           /* 
-            * We perform split horizon for RIP and connected route. 
-            * For rip routes, we want to suppress the route if we would
-             * end up sending the route back on the interface that we
-             * learned it from, with a higher metric. For connected routes,
-             * we suppress the route if the prefix is a subset of the
-             * source address that we are going to use for the packet 
-             * (in order to handle the case when multiple subnets are
-             * configured on the same interface).
-             */
-         struct rip_info *tmp_rinfo = NULL;
-
-         for (ALL_LIST_ELEMENTS_RO (list, listnode, tmp_rinfo))
-           if (tmp_rinfo->type == ZEBRA_ROUTE_RIP  &&
-               tmp_rinfo->ifindex == ifc->ifp->ifindex)
-             rinfo->metric_out = RIP_METRIC_INFINITY;
-         if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT &&
-              prefix_match((struct prefix *)p, ifc->address))
-           rinfo->metric_out = RIP_METRIC_INFINITY;
-       }
-       
-       /* Prepare preamble, auth headers, if needs be */
-       if (num == 0)
-         {
-           stream_putc (s, RIP_RESPONSE);
-           stream_putc (s, version);
-           stream_putw (s, 0);
-           
-           /* auth header for !v1 && !no_auth */
-            if ( (ri->auth_type != RIP_NO_AUTH) && (version != RIPv1) )
-              doff = rip_auth_header_write (s, ri, key, auth_str, 
-                                              RIP_AUTH_SIMPLE_SIZE);
-          }
-        
-       /* Write RTE to the stream. */
-       num = rip_write_rte (num, s, p, version, rinfo);
-       if (num == rtemax)
-         {
-           if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
-              rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
-
-           ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),
-                                  to, ifc);
-
-           if (ret >= 0 && IS_RIP_DEBUG_SEND)
-             rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
-                              stream_get_endp(s), "SEND");
-           num = 0;
-           stream_reset (s);
-         }
-      }
-
-  /* Flush unwritten RTE. */
-  if (num != 0)
-    {
-      if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
-        rip_auth_md5_set (s, ri, doff, auth_str, RIP_AUTH_SIMPLE_SIZE);
-
-      ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifc);
-
-      if (ret >= 0 && IS_RIP_DEBUG_SEND)
-       rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),
-                        stream_get_endp (s), "SEND");
-      stream_reset (s);
-    }
-
-  /* Statistics updates. */
-  ri->sent_updates++;
+       /* Set output stream. */
+       s = rip->obuf;
+
+       /* Reset stream and RTE counter. */
+       stream_reset(s);
+       rtemax = RIP_MAX_RTE;
+
+       /* Get RIP interface. */
+       ri = ifc->ifp->info;
+
+       /* If output interface is in simple password authentication mode, we
+          need space for authentication data.  */
+       if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)
+               rtemax -= 1;
+
+       /* If output interface is in MD5 authentication mode, we need space
+          for authentication header and data. */
+       if (ri->auth_type == RIP_AUTH_MD5)
+               rtemax -= 2;
+
+       /* If output interface is in simple password authentication mode
+          and string or keychain is specified we need space for auth. data */
+       if (ri->auth_type != RIP_NO_AUTH) {
+               if (ri->key_chain) {
+                       struct keychain *keychain;
+
+                       keychain = keychain_lookup(ri->key_chain);
+                       if (keychain)
+                               key = key_lookup_for_send(keychain);
+               }
+               /* to be passed to auth functions later */
+               rip_auth_prepare_str_send(ri, key, auth_str,
+                                         RIP_AUTH_SIMPLE_SIZE);
+       }
+
+       if (version == RIPv1) {
+               memcpy(&ifaddrclass, ifc->address, sizeof(struct prefix_ipv4));
+               apply_classful_mask_ipv4(&ifaddrclass);
+               subnetted = 0;
+               if (ifc->address->prefixlen > ifaddrclass.prefixlen)
+                       subnetted = 1;
+       }
+
+       for (rp = route_top(rip->table); rp; rp = route_next(rp))
+               if ((list = rp->info) != NULL && listcount(list) != 0) {
+                       rinfo = listgetdata(listhead(list));
+                       /* For RIPv1, if we are subnetted, output subnets in our
+                        * network    */
+                       /* that have the same mask as the output "interface".
+                        * For other     */
+                       /* networks, only the classfull version is output. */
+
+                       if (version == RIPv1) {
+                               p = (struct prefix_ipv4 *)&rp->p;
+
+                               if (IS_RIP_DEBUG_PACKET)
+                                       zlog_debug(
+                                               "RIPv1 mask check, %s/%d considered for output",
+                                               inet_ntoa(rp->p.u.prefix4),
+                                               rp->p.prefixlen);
+
+                               if (subnetted
+                                   && prefix_match(
+                                              (struct prefix *)&ifaddrclass,
+                                              &rp->p)) {
+                                       if ((ifc->address->prefixlen
+                                            != rp->p.prefixlen)
+                                           && (rp->p.prefixlen != 32))
+                                               continue;
+                               } else {
+                                       memcpy(&classfull, &rp->p,
+                                              sizeof(struct prefix_ipv4));
+                                       apply_classful_mask_ipv4(&classfull);
+                                       if (rp->p.u.prefix4.s_addr != 0
+                                           && classfull.prefixlen
+                                                      != rp->p.prefixlen)
+                                               continue;
+                               }
+                               if (IS_RIP_DEBUG_PACKET)
+                                       zlog_debug(
+                                               "RIPv1 mask check, %s/%d made it through",
+                                               inet_ntoa(rp->p.u.prefix4),
+                                               rp->p.prefixlen);
+                       } else
+                               p = (struct prefix_ipv4 *)&rp->p;
+
+                       /* Apply output filters. */
+                       ret = rip_filter(RIP_FILTER_OUT, p, ri);
+                       if (ret < 0)
+                               continue;
+
+                       /* Changed route only output. */
+                       if (route_type == rip_changed_route
+                           && (!(rinfo->flags & RIP_RTF_CHANGED)))
+                               continue;
+
+                       /* Split horizon. */
+                       /* if (split_horizon == rip_split_horizon) */
+                       if (ri->split_horizon == RIP_SPLIT_HORIZON) {
+                               /*
+                                * We perform split horizon for RIP and
+                                * connected route.
+                                * For rip routes, we want to suppress the route
+                                * if we would
+                                * end up sending the route back on the
+                                * interface that we
+                                * learned it from, with a higher metric. For
+                                * connected routes,
+                                * we suppress the route if the prefix is a
+                                * subset of the
+                                * source address that we are going to use for
+                                * the packet
+                                * (in order to handle the case when multiple
+                                * subnets are
+                                * configured on the same interface).
+                                */
+                               int suppress = 0;
+                               struct rip_info *tmp_rinfo = NULL;
+
+                               for (ALL_LIST_ELEMENTS_RO(list, listnode,
+                                                         tmp_rinfo))
+                                       if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
+                                           && tmp_rinfo->nh.ifindex
+                                                      == ifc->ifp->ifindex) {
+                                               suppress = 1;
+                                               break;
+                                       }
+
+                               if (!suppress
+                                   && rinfo->type == ZEBRA_ROUTE_CONNECT
+                                   && prefix_match((struct prefix *)p,
+                                                   ifc->address))
+                                       suppress = 1;
+
+                               if (suppress)
+                                       continue;
+                       }
+
+                       /* Preparation for route-map. */
+                       rinfo->metric_set = 0;
+                       rinfo->nexthop_out.s_addr = 0;
+                       rinfo->metric_out = rinfo->metric;
+                       rinfo->tag_out = rinfo->tag;
+                       rinfo->ifindex_out = ifc->ifp->ifindex;
+
+                       /* In order to avoid some local loops,
+                        * if the RIP route has a nexthop via this interface,
+                        * keep the nexthop,
+                        * otherwise set it to 0. The nexthop should not be
+                        * propagated
+                        * beyond the local broadcast/multicast area in order
+                        * to avoid an IGP multi-level recursive look-up.
+                        * see (4.4)
+                        */
+                       if (rinfo->nh.ifindex == ifc->ifp->ifindex)
+                               rinfo->nexthop_out = rinfo->nh.gate.ipv4;
+
+                       /* Interface route-map */
+                       if (ri->routemap[RIP_FILTER_OUT]) {
+                               ret = route_map_apply(
+                                       ri->routemap[RIP_FILTER_OUT],
+                                       (struct prefix *)p, RMAP_RIP, rinfo);
+
+                               if (ret == RMAP_DENYMATCH) {
+                                       if (IS_RIP_DEBUG_PACKET)
+                                               zlog_debug(
+                                                       "RIP %s/%d is filtered by route-map out",
+                                                       inet_ntoa(p->prefix),
+                                                       p->prefixlen);
+                                       continue;
+                               }
+                       }
+
+                       /* Apply redistribute route map - continue, if deny */
+                       if (rip->route_map[rinfo->type].name
+                           && rinfo->sub_type != RIP_ROUTE_INTERFACE) {
+                               ret = route_map_apply(
+                                       rip->route_map[rinfo->type].map,
+                                       (struct prefix *)p, RMAP_RIP, rinfo);
+
+                               if (ret == RMAP_DENYMATCH) {
+                                       if (IS_RIP_DEBUG_PACKET)
+                                               zlog_debug(
+                                                       "%s/%d is filtered by route-map",
+                                                       inet_ntoa(p->prefix),
+                                                       p->prefixlen);
+                                       continue;
+                               }
+                       }
+
+                       /* When route-map does not set metric. */
+                       if (!rinfo->metric_set) {
+                               /* If redistribute metric is set. */
+                               if (rip->route_map[rinfo->type].metric_config
+                                   && rinfo->metric != RIP_METRIC_INFINITY) {
+                                       rinfo->metric_out =
+                                               rip->route_map[rinfo->type]
+                                                       .metric;
+                               } else {
+                                       /* If the route is not connected or
+                                          localy generated
+                                          one, use default-metric value*/
+                                       if (rinfo->type != ZEBRA_ROUTE_RIP
+                                           && rinfo->type
+                                                      != ZEBRA_ROUTE_CONNECT
+                                           && rinfo->metric
+                                                      != RIP_METRIC_INFINITY)
+                                               rinfo->metric_out =
+                                                       rip->default_metric;
+                               }
+                       }
+
+                       /* Apply offset-list */
+                       if (rinfo->metric != RIP_METRIC_INFINITY)
+                               rip_offset_list_apply_out(p, ifc->ifp,
+                                                         &rinfo->metric_out);
+
+                       if (rinfo->metric_out > RIP_METRIC_INFINITY)
+                               rinfo->metric_out = RIP_METRIC_INFINITY;
+
+                       /* Perform split-horizon with poisoned reverse
+                        * for RIP and connected routes.
+                        **/
+                       if (ri->split_horizon
+                           == RIP_SPLIT_HORIZON_POISONED_REVERSE) {
+                               /*
+                                * We perform split horizon for RIP and
+                                * connected route.
+                                * For rip routes, we want to suppress the route
+                                * if we would
+                                * end up sending the route back on the
+                                * interface that we
+                                * learned it from, with a higher metric. For
+                                * connected routes,
+                                * we suppress the route if the prefix is a
+                                * subset of the
+                                * source address that we are going to use for
+                                * the packet
+                                * (in order to handle the case when multiple
+                                * subnets are
+                                * configured on the same interface).
+                                */
+                               struct rip_info *tmp_rinfo = NULL;
+
+                               for (ALL_LIST_ELEMENTS_RO(list, listnode,
+                                                         tmp_rinfo))
+                                       if (tmp_rinfo->type == ZEBRA_ROUTE_RIP
+                                           && tmp_rinfo->nh.ifindex
+                                                      == ifc->ifp->ifindex)
+                                               rinfo->metric_out =
+                                                       RIP_METRIC_INFINITY;
+                               if (tmp_rinfo->type == ZEBRA_ROUTE_CONNECT
+                                   && prefix_match((struct prefix *)p,
+                                                   ifc->address))
+                                       rinfo->metric_out = RIP_METRIC_INFINITY;
+                       }
+
+                       /* Prepare preamble, auth headers, if needs be */
+                       if (num == 0) {
+                               stream_putc(s, RIP_RESPONSE);
+                               stream_putc(s, version);
+                               stream_putw(s, 0);
+
+                               /* auth header for !v1 && !no_auth */
+                               if ((ri->auth_type != RIP_NO_AUTH)
+                                   && (version != RIPv1))
+                                       doff = rip_auth_header_write(
+                                               s, ri, key, auth_str,
+                                               RIP_AUTH_SIMPLE_SIZE);
+                       }
+
+                       /* Write RTE to the stream. */
+                       num = rip_write_rte(num, s, p, version, rinfo);
+                       if (num == rtemax) {
+                               if (version == RIPv2
+                                   && ri->auth_type == RIP_AUTH_MD5)
+                                       rip_auth_md5_set(s, ri, doff, auth_str,
+                                                        RIP_AUTH_SIMPLE_SIZE);
+
+                               ret = rip_send_packet(STREAM_DATA(s),
+                                                     stream_get_endp(s), to,
+                                                     ifc);
+
+                               if (ret >= 0 && IS_RIP_DEBUG_SEND)
+                                       rip_packet_dump((struct rip_packet *)
+                                                               STREAM_DATA(s),
+                                                       stream_get_endp(s),
+                                                       "SEND");
+                               num = 0;
+                               stream_reset(s);
+                       }
+               }
+
+       /* Flush unwritten RTE. */
+       if (num != 0) {
+               if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)
+                       rip_auth_md5_set(s, ri, doff, auth_str,
+                                        RIP_AUTH_SIMPLE_SIZE);
+
+               ret = rip_send_packet(STREAM_DATA(s), stream_get_endp(s), to,
+                                     ifc);
+
+               if (ret >= 0 && IS_RIP_DEBUG_SEND)
+                       rip_packet_dump((struct rip_packet *)STREAM_DATA(s),
+                                       stream_get_endp(s), "SEND");
+               stream_reset(s);
+       }
+
+       /* Statistics updates. */
+       ri->sent_updates++;
 }
 
 /* Send RIP packet to the interface. */
-static void
-rip_update_interface (struct connected *ifc, u_char version, int route_type)
-{
-  struct interface *ifp = ifc->ifp;
-  struct rip_interface *ri = ifp->info;
-  struct sockaddr_in to;
-
-  /* When RIP version is 2 and multicast enable interface. */
-  if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast (ifp))
-    {
-      if (IS_RIP_DEBUG_EVENT)
-       zlog_debug ("multicast announce on %s ", ifp->name);
-
-      rip_output_process (ifc, NULL, route_type, version);
-      return;
-    }
-  
-  /* If we can't send multicast packet, send it with unicast. */
-  if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))
-    {
-      if (ifc->address->family == AF_INET)
-        {
-          /* Destination address and port setting. */
-          memset (&to, 0, sizeof (struct sockaddr_in));
-          if (ifc->destination)
-            /* use specified broadcast or peer destination addr */
-            to.sin_addr = ifc->destination->u.prefix4;
-          else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
-            /* calculate the appropriate broadcast address */
-            to.sin_addr.s_addr =
-              ipv4_broadcast_addr(ifc->address->u.prefix4.s_addr,
-                                  ifc->address->prefixlen);
-         else
-           /* do not know where to send the packet */
-           return;
-          to.sin_port = htons (RIP_PORT_DEFAULT);
-
-          if (IS_RIP_DEBUG_EVENT)
-            zlog_debug("%s announce to %s on %s",
-                      CONNECTED_PEER(ifc) ? "unicast" : "broadcast",
-                      inet_ntoa (to.sin_addr), ifp->name);
-
-          rip_output_process (ifc, &to, route_type, version);
-        }
-    }
+static void rip_update_interface(struct connected *ifc, u_char version,
+                                int route_type)
+{
+       struct interface *ifp = ifc->ifp;
+       struct rip_interface *ri = ifp->info;
+       struct sockaddr_in to;
+
+       /* When RIP version is 2 and multicast enable interface. */
+       if (version == RIPv2 && !ri->v2_broadcast && if_is_multicast(ifp)) {
+               if (IS_RIP_DEBUG_EVENT)
+                       zlog_debug("multicast announce on %s ", ifp->name);
+
+               rip_output_process(ifc, NULL, route_type, version);
+               return;
+       }
+
+       /* If we can't send multicast packet, send it with unicast. */
+       if (if_is_broadcast(ifp) || if_is_pointopoint(ifp)) {
+               if (ifc->address->family == AF_INET) {
+                       /* Destination address and port setting. */
+                       memset(&to, 0, sizeof(struct sockaddr_in));
+                       if (ifc->destination)
+                               /* use specified broadcast or peer destination
+                                * addr */
+                               to.sin_addr = ifc->destination->u.prefix4;
+                       else if (ifc->address->prefixlen < IPV4_MAX_PREFIXLEN)
+                               /* calculate the appropriate broadcast address
+                                */
+                               to.sin_addr.s_addr = ipv4_broadcast_addr(
+                                       ifc->address->u.prefix4.s_addr,
+                                       ifc->address->prefixlen);
+                       else
+                               /* do not know where to send the packet */
+                               return;
+                       to.sin_port = htons(RIP_PORT_DEFAULT);
+
+                       if (IS_RIP_DEBUG_EVENT)
+                               zlog_debug("%s announce to %s on %s",
+                                          CONNECTED_PEER(ifc) ? "unicast"
+                                                              : "broadcast",
+                                          inet_ntoa(to.sin_addr), ifp->name);
+
+                       rip_output_process(ifc, &to, route_type, version);
+               }
+       }
 }
 
 /* Update send to all interface and neighbor. */
-static void
-rip_update_process (int route_type)
-{
-  struct listnode *node;
-  struct listnode *ifnode, *ifnnode;
-  struct connected *connected;
-  struct interface *ifp;
-  struct rip_interface *ri;
-  struct route_node *rp;
-  struct sockaddr_in to;
-  struct prefix *p;
-
-  /* Send RIP update to each interface. */
-  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
-    {
-      if (if_is_loopback (ifp))
-       continue;
-
-      if (! if_is_operative (ifp))
-       continue;
-
-      /* Fetch RIP interface information. */
-      ri = ifp->info;
-
-      /* When passive interface is specified, suppress announce to the
-         interface. */
-      if (ri->passive)
-       continue;
-
-      if (ri->running)
-       {
-         /* 
-          * If there is no version configuration in the interface,
-          * use rip's version setting. 
-          */
-         int vsend = ((ri->ri_send == RI_RIP_UNSPEC) ?
-                      rip->version_send : ri->ri_send);
-
-         if (IS_RIP_DEBUG_EVENT) 
-           zlog_debug("SEND UPDATE to %s ifindex %d",
-                      ifp->name, ifp->ifindex);
-
-          /* send update on each connected network */
-         for (ALL_LIST_ELEMENTS (ifp->connected, ifnode, ifnnode, connected))
-           {
-             if (connected->address->family == AF_INET)
-               {
-                 if (vsend & RIPv1)
-                   rip_update_interface (connected, RIPv1, route_type);
-                 if ((vsend & RIPv2) && if_is_multicast(ifp))
-                   rip_update_interface (connected, RIPv2, route_type);
+static void rip_update_process(int route_type)
+{
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct listnode *ifnode, *ifnnode;
+       struct connected *connected;
+       struct interface *ifp;
+       struct rip_interface *ri;
+       struct route_node *rp;
+       struct sockaddr_in to;
+       struct prefix *p;
+
+       /* Send RIP update to each interface. */
+       FOR_ALL_INTERFACES (vrf, ifp) {
+               if (if_is_loopback(ifp))
+                       continue;
+
+               if (!if_is_operative(ifp))
+                       continue;
+
+               /* Fetch RIP interface information. */
+               ri = ifp->info;
+
+               /* When passive interface is specified, suppress announce to the
+                  interface. */
+               if (ri->passive)
+                       continue;
+
+               if (ri->running) {
+                       /*
+                        * If there is no version configuration in the
+                        * interface,
+                        * use rip's version setting.
+                        */
+                       int vsend = ((ri->ri_send == RI_RIP_UNSPEC)
+                                            ? rip->version_send
+                                            : ri->ri_send);
+
+                       if (IS_RIP_DEBUG_EVENT)
+                               zlog_debug("SEND UPDATE to %s ifindex %d",
+                                          ifp->name, ifp->ifindex);
+
+                       /* send update on each connected network */
+                       for (ALL_LIST_ELEMENTS(ifp->connected, ifnode, ifnnode,
+                                              connected)) {
+                               if (connected->address->family == AF_INET) {
+                                       if (vsend & RIPv1)
+                                               rip_update_interface(
+                                                       connected, RIPv1,
+                                                       route_type);
+                                       if ((vsend & RIPv2)
+                                           && if_is_multicast(ifp))
+                                               rip_update_interface(
+                                                       connected, RIPv2,
+                                                       route_type);
+                               }
+                       }
+               }
+       }
+
+       /* RIP send updates to each neighbor. */
+       for (rp = route_top(rip->neighbor); rp; rp = route_next(rp))
+               if (rp->info != NULL) {
+                       p = &rp->p;
+
+                       connected = if_lookup_address(&p->u.prefix4, AF_INET,
+                                                     VRF_DEFAULT);
+                       if (!connected) {
+                               zlog_warn(
+                                       "Neighbor %s doesnt have connected interface!",
+                                       inet_ntoa(p->u.prefix4));
+                               continue;
+                       }
+
+                       /* Set destination address and port */
+                       memset(&to, 0, sizeof(struct sockaddr_in));
+                       to.sin_addr = p->u.prefix4;
+                       to.sin_port = htons(RIP_PORT_DEFAULT);
+
+                       /* RIP version is rip's configuration. */
+                       rip_output_process(connected, &to, route_type,
+                                          rip->version_send);
                }
-           }
-       }
-    }
-
-  /* RIP send updates to each neighbor. */
-  for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
-    if (rp->info != NULL)
-      {
-       p = &rp->p;
-
-       connected = if_lookup_address (&p->u.prefix4, AF_INET, VRF_DEFAULT);
-       if (! connected)
-         {
-           zlog_warn ("Neighbor %s doesnt have connected interface!",
-                      inet_ntoa (p->u.prefix4));
-           continue;
-         }
-        
-       /* Set destination address and port */
-       memset (&to, 0, sizeof (struct sockaddr_in));
-       to.sin_addr = p->u.prefix4;
-       to.sin_port = htons (RIP_PORT_DEFAULT);
-
-       /* RIP version is rip's configuration. */
-       rip_output_process (connected, &to, route_type, rip->version_send);
-      }
 }
 
 /* RIP's periodical timer. */
-static int
-rip_update (struct thread *t)
+static int rip_update(struct thread *t)
 {
-  /* Clear timer pointer. */
-  rip->t_update = NULL;
+       /* Clear timer pointer. */
+       rip->t_update = NULL;
 
-  if (IS_RIP_DEBUG_EVENT)
-    zlog_debug ("update timer fire!");
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("update timer fire!");
 
-  /* Process update output. */
-  rip_update_process (rip_all_route);
+       /* Process update output. */
+       rip_update_process(rip_all_route);
 
-  /* Triggered updates may be suppressed if a regular update is due by
-     the time the triggered update would be sent. */
-  RIP_TIMER_OFF (rip->t_triggered_interval);
-  rip->trigger = 0;
+       /* Triggered updates may be suppressed if a regular update is due by
+          the time the triggered update would be sent. */
+       RIP_TIMER_OFF(rip->t_triggered_interval);
+       rip->trigger = 0;
 
-  /* Register myself. */
-  rip_event (RIP_UPDATE_EVENT, 0);
+       /* Register myself. */
+       rip_event(RIP_UPDATE_EVENT, 0);
 
-  return 0;
+       return 0;
 }
 
 /* Walk down the RIP routing table then clear changed flag. */
-static void
-rip_clear_changed_flag (void)
+static void rip_clear_changed_flag(void)
 {
-  struct route_node *rp;
-  struct rip_info *rinfo = NULL;
-  struct list *list = NULL;
-  struct listnode *listnode = NULL;
+       struct route_node *rp;
+       struct rip_info *rinfo = NULL;
+       struct list *list = NULL;
+       struct listnode *listnode = NULL;
 
-  for (rp = route_top (rip->table); rp; rp = route_next (rp))
-    if ((list = rp->info) != NULL)
-      for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
-        {
-          UNSET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
-          /* This flag can be set only on the first entry. */
-          break;
-        }
+       for (rp = route_top(rip->table); rp; rp = route_next(rp))
+               if ((list = rp->info) != NULL)
+                       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+                               UNSET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
+                               /* This flag can be set only on the first entry.
+                                */
+                               break;
+                       }
 }
 
 /* Triggered update interval timer. */
-static int
-rip_triggered_interval (struct thread *t)
+static int rip_triggered_interval(struct thread *t)
 {
-  int rip_triggered_update (struct thread *);
+       int rip_triggered_update(struct thread *);
 
-  rip->t_triggered_interval = NULL;
+       rip->t_triggered_interval = NULL;
 
-  if (rip->trigger)
-    {
-      rip->trigger = 0;
-      rip_triggered_update (t);
-    }
-  return 0;
-}     
+       if (rip->trigger) {
+               rip->trigger = 0;
+               rip_triggered_update(t);
+       }
+       return 0;
+}
 
 /* Execute triggered update. */
-static int
-rip_triggered_update (struct thread *t)
+static int rip_triggered_update(struct thread *t)
 {
-  int interval;
+       int interval;
 
-  /* Clear thred pointer. */
-  rip->t_triggered_update = NULL;
+       /* Clear thred pointer. */
+       rip->t_triggered_update = NULL;
 
-  /* Cancel interval timer. */
-  RIP_TIMER_OFF (rip->t_triggered_interval);
-  rip->trigger = 0;
+       /* Cancel interval timer. */
+       RIP_TIMER_OFF(rip->t_triggered_interval);
+       rip->trigger = 0;
 
-  /* Logging triggered update. */
-  if (IS_RIP_DEBUG_EVENT)
-    zlog_debug ("triggered update!");
+       /* Logging triggered update. */
+       if (IS_RIP_DEBUG_EVENT)
+               zlog_debug("triggered update!");
 
-  /* Split Horizon processing is done when generating triggered
-     updates as well as normal updates (see section 2.6). */
-  rip_update_process (rip_changed_route);
+       /* Split Horizon processing is done when generating triggered
+          updates as well as normal updates (see section 2.6). */
+       rip_update_process(rip_changed_route);
 
-  /* Once all of the triggered updates have been generated, the route
-     change flags should be cleared. */
-  rip_clear_changed_flag ();
+       /* Once all of the triggered updates have been generated, the route
+          change flags should be cleared. */
+       rip_clear_changed_flag();
 
-  /* After a triggered update is sent, a timer should be set for a
-   random interval between 1 and 5 seconds.  If other changes that
-   would trigger updates occur before the timer expires, a single
-   update is triggered when the timer expires. */
-  interval = (random () % 5) + 1;
+       /* After a triggered update is sent, a timer should be set for a
+        random interval between 1 and 5 seconds.  If other changes that
+        would trigger updates occur before the timer expires, a single
+        update is triggered when the timer expires. */
+       interval = (random() % 5) + 1;
 
-  rip->t_triggered_interval = NULL;
-  thread_add_timer(master, rip_triggered_interval, NULL, interval,
-                   &rip->t_triggered_interval);
+       rip->t_triggered_interval = NULL;
+       thread_add_timer(master, rip_triggered_interval, NULL, interval,
+                        &rip->t_triggered_interval);
 
-  return 0;
+       return 0;
 }
 
 /* Withdraw redistributed route. */
-void
-rip_redistribute_withdraw (int type)
+void rip_redistribute_withdraw(int type)
+{
+       struct route_node *rp;
+       struct rip_info *rinfo = NULL;
+       struct list *list = NULL;
+
+       if (!rip)
+               return;
+
+       for (rp = route_top(rip->table); rp; rp = route_next(rp))
+               if ((list = rp->info) != NULL) {
+                       rinfo = listgetdata(listhead(list));
+                       if (rinfo->type == type
+                           && rinfo->sub_type != RIP_ROUTE_INTERFACE) {
+                               /* Perform poisoned reverse. */
+                               rinfo->metric = RIP_METRIC_INFINITY;
+                               RIP_TIMER_ON(rinfo->t_garbage_collect,
+                                            rip_garbage_collect,
+                                            rip->garbage_time);
+                               RIP_TIMER_OFF(rinfo->t_timeout);
+                               rinfo->flags |= RIP_RTF_CHANGED;
+
+                               if (IS_RIP_DEBUG_EVENT) {
+                                       struct prefix_ipv4 *p =
+                                               (struct prefix_ipv4 *)&rp->p;
+
+                                       zlog_debug(
+                                               "Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
+                                               inet_ntoa(p->prefix),
+                                               p->prefixlen,
+                                               ifindex2ifname(
+                                                       rinfo->nh.ifindex,
+                                                       VRF_DEFAULT));
+                               }
+
+                               rip_event(RIP_TRIGGERED_UPDATE, 0);
+                       }
+               }
+}
+
+/* Create new RIP instance and set it to global variable. */
+static int rip_create(void)
 {
-  struct route_node *rp;
-  struct rip_info *rinfo = NULL;
-  struct list *list = NULL;
+       rip = XCALLOC(MTYPE_RIP, sizeof(struct rip));
 
-  if (!rip)
-    return;
+       /* Set initial value. */
+       rip->version_send = RI_RIP_VERSION_2;
+       rip->version_recv = RI_RIP_VERSION_1_AND_2;
+       rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
+       rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
+       rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
+       rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
 
-  for (rp = route_top (rip->table); rp; rp = route_next (rp))
-    if ((list = rp->info) != NULL)
-      {
-       rinfo = listgetdata (listhead (list));
-       if (rinfo->type == type
-           && rinfo->sub_type != RIP_ROUTE_INTERFACE)
-         {
-           /* Perform poisoned reverse. */
-           rinfo->metric = RIP_METRIC_INFINITY;
-           RIP_TIMER_ON (rinfo->t_garbage_collect, 
-                         rip_garbage_collect, rip->garbage_time);
-           RIP_TIMER_OFF (rinfo->t_timeout);
-           rinfo->flags |= RIP_RTF_CHANGED;
+       /* Initialize RIP routig table. */
+       rip->table = route_table_init();
+       rip->route = route_table_init();
+       rip->neighbor = route_table_init();
 
-           if (IS_RIP_DEBUG_EVENT) {
-              struct prefix_ipv4 *p = (struct prefix_ipv4 *) &rp->p;
+       /* Make output stream. */
+       rip->obuf = stream_new(1500);
 
-              zlog_debug ("Poisone %s/%d on the interface %s with an infinity metric [withdraw]",
-                          inet_ntoa(p->prefix), p->prefixlen,
-                          ifindex2ifname(rinfo->ifindex, VRF_DEFAULT));
-           }
+       /* Make socket. */
+       rip->sock = rip_create_socket();
+       if (rip->sock < 0)
+               return rip->sock;
 
-           rip_event (RIP_TRIGGERED_UPDATE, 0);
-         }
-      }
-}
+       /* Create read and timer thread. */
+       rip_event(RIP_READ, rip->sock);
+       rip_event(RIP_UPDATE_EVENT, 1);
 
-/* Create new RIP instance and set it to global variable. */
-static int
-rip_create (void)
-{
-  rip = XCALLOC (MTYPE_RIP, sizeof (struct rip));
+       QOBJ_REG(rip, rip);
 
-  /* Set initial value. */
-  rip->version_send = RI_RIP_VERSION_2;
-  rip->version_recv = RI_RIP_VERSION_1_AND_2;
-  rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
-  rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
-  rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
-  rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
-
-  /* Initialize RIP routig table. */
-  rip->table = route_table_init ();
-  rip->route = route_table_init ();
-  rip->neighbor = route_table_init ();
+       return 0;
+}
 
-  /* Make output stream. */
-  rip->obuf = stream_new (1500);
+/* Sned RIP request to the destination. */
+int rip_request_send(struct sockaddr_in *to, struct interface *ifp,
+                    u_char version, struct connected *connected)
+{
+       struct rte *rte;
+       struct rip_packet rip_packet;
+       struct listnode *node, *nnode;
+
+       memset(&rip_packet, 0, sizeof(rip_packet));
+
+       rip_packet.command = RIP_REQUEST;
+       rip_packet.version = version;
+       rte = rip_packet.rte;
+       rte->metric = htonl(RIP_METRIC_INFINITY);
+
+       if (connected) {
+               /*
+                * connected is only sent for ripv1 case, or when
+                * interface does not support multicast.  Caller loops
+                * over each connected address for this case.
+                */
+               if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet),
+                                   to, connected)
+                   != sizeof(rip_packet))
+                       return -1;
+               else
+                       return sizeof(rip_packet);
+       }
 
-  /* Make socket. */
-  rip->sock = rip_create_socket ();
-  if (rip->sock < 0)
-    return rip->sock;
+       /* send request on each connected network */
+       for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
+               struct prefix_ipv4 *p;
 
-  /* Create read and timer thread. */
-  rip_event (RIP_READ, rip->sock);
-  rip_event (RIP_UPDATE_EVENT, 1);
+               p = (struct prefix_ipv4 *)connected->address;
 
-  QOBJ_REG (rip, rip);
+               if (p->family != AF_INET)
+                       continue;
 
-  return 0;
+               if (rip_send_packet((u_char *)&rip_packet, sizeof(rip_packet),
+                                   to, connected)
+                   != sizeof(rip_packet))
+                       return -1;
+       }
+       return sizeof(rip_packet);
 }
 
-/* Sned RIP request to the destination. */
-int
-rip_request_send (struct sockaddr_in *to, struct interface *ifp,
-                 u_char version, struct connected *connected)
-{
-  struct rte *rte;
-  struct rip_packet rip_packet;
-  struct listnode *node, *nnode;
-
-  memset (&rip_packet, 0, sizeof (rip_packet));
-
-  rip_packet.command = RIP_REQUEST;
-  rip_packet.version = version;
-  rte = rip_packet.rte;
-  rte->metric = htonl (RIP_METRIC_INFINITY);
-
-  if (connected) 
-    {
-      /* 
-       * connected is only sent for ripv1 case, or when
-       * interface does not support multicast.  Caller loops
-       * over each connected address for this case.
-       */
-      if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), 
-                            to, connected) != sizeof (rip_packet))
-        return -1;
-      else
-        return sizeof (rip_packet);
-    }
-       
-  /* send request on each connected network */
-  for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
-    {
-      struct prefix_ipv4 *p;
-
-      p = (struct prefix_ipv4 *) connected->address;
-
-      if (p->family != AF_INET)
-        continue;
-
-      if (rip_send_packet ((u_char *) &rip_packet, sizeof (rip_packet), 
-                            to, connected) != sizeof (rip_packet))
-        return -1;
-    }
-  return sizeof (rip_packet);
-}
-
-static int
-rip_update_jitter (unsigned long time)
+static int rip_update_jitter(unsigned long time)
 {
 #define JITTER_BOUND 4
-  /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
-     Given that, we cannot let time be less than JITTER_BOUND seconds.
-     The RIPv2 RFC says jitter should be small compared to
-     update_time.  We consider 1/JITTER_BOUND to be small.
-  */
-  
-  int jitter_input = time;
-  int jitter;
-  
-  if (jitter_input < JITTER_BOUND)
-    jitter_input = JITTER_BOUND;
-  
-  jitter = (((random () % ((jitter_input * 2) + 1)) - jitter_input));
-
-  return jitter/JITTER_BOUND;
-}
-
-void
-rip_event (enum rip_event event, int sock)
-{
-  int jitter = 0;
-
-  switch (event)
-    {
-    case RIP_READ:
-      rip->t_read = NULL;
-      thread_add_read(master, rip_read, NULL, sock, &rip->t_read);
-      break;
-    case RIP_UPDATE_EVENT:
-      RIP_TIMER_OFF (rip->t_update);
-      jitter = rip_update_jitter (rip->update_time);
-      thread_add_timer(master, rip_update, NULL, sock ? 2 : rip->update_time + jitter,
-                       &rip->t_update);
-      break;
-    case RIP_TRIGGERED_UPDATE:
-      if (rip->t_triggered_interval)
-        rip->trigger = 1;
-      else thread_add_event(master, rip_triggered_update, NULL, 0,
-                            &rip->t_triggered_update);
-      break;
-    default:
-      break;
-    }
+       /* We want to get the jitter to +/- 1/JITTER_BOUND the interval.
+          Given that, we cannot let time be less than JITTER_BOUND seconds.
+          The RIPv2 RFC says jitter should be small compared to
+          update_time.  We consider 1/JITTER_BOUND to be small.
+       */
+
+       int jitter_input = time;
+       int jitter;
+
+       if (jitter_input < JITTER_BOUND)
+               jitter_input = JITTER_BOUND;
+
+       jitter = (((random() % ((jitter_input * 2) + 1)) - jitter_input));
+
+       return jitter / JITTER_BOUND;
+}
+
+void rip_event(enum rip_event event, int sock)
+{
+       int jitter = 0;
+
+       switch (event) {
+       case RIP_READ:
+               rip->t_read = NULL;
+               thread_add_read(master, rip_read, NULL, sock, &rip->t_read);
+               break;
+       case RIP_UPDATE_EVENT:
+               RIP_TIMER_OFF(rip->t_update);
+               jitter = rip_update_jitter(rip->update_time);
+               thread_add_timer(master, rip_update, NULL,
+                                sock ? 2 : rip->update_time + jitter,
+                                &rip->t_update);
+               break;
+       case RIP_TRIGGERED_UPDATE:
+               if (rip->t_triggered_interval)
+                       rip->trigger = 1;
+               else
+                       thread_add_event(master, rip_triggered_update, NULL, 0,
+                                        &rip->t_triggered_update);
+               break;
+       default:
+               break;
+       }
 }
 
 DEFUN_NOSH (router_rip,
@@ -2806,21 +2784,19 @@ DEFUN_NOSH (router_rip,
        "Enable a routing process\n"
        "Routing Information Protocol (RIP)\n")
 {
-  int ret;
+       int ret;
 
-  /* If rip is not enabled before. */
-  if (! rip)
-    {
-      ret = rip_create ();
-      if (ret < 0)
-       {
-         zlog_info ("Can't create RIP");
-          return CMD_WARNING_CONFIG_FAILED;
+       /* If rip is not enabled before. */
+       if (!rip) {
+               ret = rip_create();
+               if (ret < 0) {
+                       zlog_info("Can't create RIP");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
        }
-    }
-  VTY_PUSH_CONTEXT(RIP_NODE, rip);
+       VTY_PUSH_CONTEXT(RIP_NODE, rip);
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_router_rip,
@@ -2830,9 +2806,9 @@ DEFUN (no_router_rip,
        "Enable a routing process\n"
        "Routing Information Protocol (RIP)\n")
 {
-  if (rip)
-    rip_clean ();
-  return CMD_SUCCESS;
+       if (rip)
+               rip_clean();
+       return CMD_SUCCESS;
 }
 
 DEFUN (rip_version,
@@ -2841,19 +2817,18 @@ DEFUN (rip_version,
        "Set routing protocol version\n"
        "version\n")
 {
-  int idx_number = 1;
-  int version;
+       int idx_number = 1;
+       int version;
 
-  version = atoi (argv[idx_number]->arg);
-  if (version != RIPv1 && version != RIPv2)
-    {
-      vty_outln (vty, "invalid rip version %d",version);
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-  rip->version_send = version;
-  rip->version_recv = version;
+       version = atoi(argv[idx_number]->arg);
+       if (version != RIPv1 && version != RIPv2) {
+               vty_out(vty, "invalid rip version %d\n", version);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       rip->version_send = version;
+       rip->version_recv = version;
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_version,
@@ -2863,11 +2838,11 @@ DEFUN (no_rip_version,
        "Set routing protocol version\n"
        "Version\n")
 {
-  /* Set RIP version to the default. */
-  rip->version_send = RI_RIP_VERSION_2;
-  rip->version_recv = RI_RIP_VERSION_1_AND_2;
+       /* Set RIP version to the default. */
+       rip->version_send = RI_RIP_VERSION_2;
+       rip->version_recv = RI_RIP_VERSION_1_AND_2;
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 
@@ -2877,34 +2852,37 @@ DEFUN (rip_route,
        "RIP static route configuration\n"
        "IP prefix <network>/<length>\n")
 {
-  int idx_ipv4_prefixlen = 1;
-  int ret;
-  struct prefix_ipv4 p;
-  struct route_node *node;
+       int idx_ipv4_prefixlen = 1;
+       int ret;
+       struct nexthop nh;
+       struct prefix_ipv4 p;
+       struct route_node *node;
+
+       memset(&nh, 0, sizeof(nh));
+       nh.type = NEXTHOP_TYPE_IPV4;
 
-  ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p);
-  if (ret < 0)
-    {
-      vty_outln (vty, "Malformed address");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-  apply_mask_ipv4 (&p);
+       ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
+       if (ret < 0) {
+               vty_out(vty, "Malformed address\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       apply_mask_ipv4(&p);
 
-  /* For router rip configuration. */
-  node = route_node_get (rip->route, (struct prefix *) &p);
+       /* For router rip configuration. */
+       node = route_node_get(rip->route, (struct prefix *)&p);
 
-  if (node->info)
-    {
-      vty_outln (vty, "There is already same static route.");
-      route_unlock_node (node);
-      return CMD_WARNING_CONFIG_FAILED;
-    }
+       if (node->info) {
+               vty_out(vty, "There is already same static route.\n");
+               route_unlock_node(node);
+               return CMD_WARNING;
+       }
 
-  node->info = (void *)1;
+       node->info = (void *)1;
 
-  rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0, NULL, 0, 0, 0);
+       rip_redistribute_add(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, &nh, 0,
+                            0, 0);
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_route,
@@ -2914,34 +2892,33 @@ DEFUN (no_rip_route,
        "RIP static route configuration\n"
        "IP prefix <network>/<length>\n")
 {
-  int idx_ipv4_prefixlen = 2;
-  int ret;
-  struct prefix_ipv4 p;
-  struct route_node *node;
-
-  ret = str2prefix_ipv4 (argv[idx_ipv4_prefixlen]->arg, &p);
-  if (ret < 0)
-    {
-      vty_outln (vty, "Malformed address");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-  apply_mask_ipv4 (&p);
+       int idx_ipv4_prefixlen = 2;
+       int ret;
+       struct prefix_ipv4 p;
+       struct route_node *node;
 
-  /* For router rip configuration. */
-  node = route_node_lookup (rip->route, (struct prefix *) &p);
-  if (! node)
-    {
-      vty_outln (vty, "Can't find route %s.",argv[idx_ipv4_prefixlen]->arg);
-      return CMD_WARNING_CONFIG_FAILED;
-    }
+       ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
+       if (ret < 0) {
+               vty_out(vty, "Malformed address\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       apply_mask_ipv4(&p);
+
+       /* For router rip configuration. */
+       node = route_node_lookup(rip->route, (struct prefix *)&p);
+       if (!node) {
+               vty_out(vty, "Can't find route %s.\n",
+                       argv[idx_ipv4_prefixlen]->arg);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-  rip_redistribute_delete (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
-  route_unlock_node (node);
+       rip_redistribute_delete(ZEBRA_ROUTE_RIP, RIP_ROUTE_STATIC, &p, 0);
+       route_unlock_node(node);
 
-  node->info = NULL;
-  route_unlock_node (node);
+       node->info = NULL;
+       route_unlock_node(node);
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 #if 0
@@ -2967,13 +2944,12 @@ DEFUN (rip_default_metric,
        "Set a metric of redistribute routes\n"
        "Default metric\n")
 {
-  int idx_number = 1;
-  if (rip)
-    {
-      rip->default_metric = atoi (argv[idx_number]->arg);
-      /* rip_update_default_metric (); */
-    }
-  return CMD_SUCCESS;
+       int idx_number = 1;
+       if (rip) {
+               rip->default_metric = atoi(argv[idx_number]->arg);
+               /* rip_update_default_metric (); */
+       }
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_default_metric,
@@ -2983,12 +2959,11 @@ DEFUN (no_rip_default_metric,
        "Set a metric of redistribute routes\n"
        "Default metric\n")
 {
-  if (rip)
-    {
-      rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
-      /* rip_update_default_metric (); */
-    }
-  return CMD_SUCCESS;
+       if (rip) {
+               rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;
+               /* rip_update_default_metric (); */
+       }
+       return CMD_SUCCESS;
 }
 
 
@@ -3001,46 +2976,46 @@ DEFUN (rip_timers,
        "Routing information timeout timer. Default is 180.\n"
        "Garbage collection timer. Default is 120.\n")
 {
-  int idx_number = 2;
-  int idx_number_2 = 3;
-  int idx_number_3 = 4;
-  unsigned long update;
-  unsigned long timeout;
-  unsigned long garbage;
-  char *endptr = NULL;
-  unsigned long RIP_TIMER_MAX = 2147483647;
-  unsigned long RIP_TIMER_MIN = 5;
-
-  update = strtoul (argv[idx_number]->arg, &endptr, 10);
-  if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN || *endptr != '\0')  
-    {
-      vty_outln (vty, "update timer value error");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-  
-  timeout = strtoul (argv[idx_number_2]->arg, &endptr, 10);
-  if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN || *endptr != '\0') 
-    {
-      vty_outln (vty, "timeout timer value error");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-  
-  garbage = strtoul (argv[idx_number_3]->arg, &endptr, 10);
-  if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN || *endptr != '\0') 
-    {
-      vty_outln (vty, "garbage timer value error");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-
-  /* Set each timer value. */
-  rip->update_time = update;
-  rip->timeout_time = timeout;
-  rip->garbage_time = garbage;
-
-  /* Reset update timer thread. */
-  rip_event (RIP_UPDATE_EVENT, 0);
-
-  return CMD_SUCCESS;
+       int idx_number = 2;
+       int idx_number_2 = 3;
+       int idx_number_3 = 4;
+       unsigned long update;
+       unsigned long timeout;
+       unsigned long garbage;
+       char *endptr = NULL;
+       unsigned long RIP_TIMER_MAX = 2147483647;
+       unsigned long RIP_TIMER_MIN = 5;
+
+       update = strtoul(argv[idx_number]->arg, &endptr, 10);
+       if (update > RIP_TIMER_MAX || update < RIP_TIMER_MIN
+           || *endptr != '\0') {
+               vty_out(vty, "update timer value error\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       timeout = strtoul(argv[idx_number_2]->arg, &endptr, 10);
+       if (timeout > RIP_TIMER_MAX || timeout < RIP_TIMER_MIN
+           || *endptr != '\0') {
+               vty_out(vty, "timeout timer value error\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       garbage = strtoul(argv[idx_number_3]->arg, &endptr, 10);
+       if (garbage > RIP_TIMER_MAX || garbage < RIP_TIMER_MIN
+           || *endptr != '\0') {
+               vty_out(vty, "garbage timer value error\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       /* Set each timer value. */
+       rip->update_time = update;
+       rip->timeout_time = timeout;
+       rip->garbage_time = garbage;
+
+       /* Reset update timer thread. */
+       rip_event(RIP_UPDATE_EVENT, 0);
+
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_timers,
@@ -3053,210 +3028,193 @@ DEFUN (no_rip_timers,
        "Routing information timeout timer. Default is 180.\n"
        "Garbage collection timer. Default is 120.\n")
 {
-  /* Set each timer value to the default. */
-  rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
-  rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
-  rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
+       /* Set each timer value to the default. */
+       rip->update_time = RIP_UPDATE_TIMER_DEFAULT;
+       rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;
+       rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;
 
-  /* Reset update timer thread. */
-  rip_event (RIP_UPDATE_EVENT, 0);
+       /* Reset update timer thread. */
+       rip_event(RIP_UPDATE_EVENT, 0);
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
 
-
 struct route_table *rip_distance_table;
 
-struct rip_distance
-{
-  /* Distance value for the IP source prefix. */
-  u_char distance;
+struct rip_distance {
+       /* Distance value for the IP source prefix. */
+       u_char distance;
 
-  /* Name of the access-list to be matched. */
-  char *access_list;
+       /* Name of the access-list to be matched. */
+       char *access_list;
 };
 
-static struct rip_distance *
-rip_distance_new (void)
+static struct rip_distance *rip_distance_new(void)
 {
-  return XCALLOC (MTYPE_RIP_DISTANCE, sizeof (struct rip_distance));
+       return XCALLOC(MTYPE_RIP_DISTANCE, sizeof(struct rip_distance));
 }
 
-static void
-rip_distance_free (struct rip_distance *rdistance)
-{
-  XFREE (MTYPE_RIP_DISTANCE, rdistance);
-}
-
-static int
-rip_distance_set (struct vty *vty, const char *distance_str, const char *ip_str,
-                 const char *access_list_str)
-{
-  int ret;
-  struct prefix_ipv4 p;
-  u_char distance;
-  struct route_node *rn;
-  struct rip_distance *rdistance;
-
-  ret = str2prefix_ipv4 (ip_str, &p);
-  if (ret == 0)
-    {
-      vty_outln (vty, "Malformed prefix");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-
-  distance = atoi (distance_str);
-
-  /* Get RIP distance node. */
-  rn = route_node_get (rip_distance_table, (struct prefix *) &p);
-  if (rn->info)
-    {
-      rdistance = rn->info;
-      route_unlock_node (rn);
-    }
-  else
-    {
-      rdistance = rip_distance_new ();
-      rn->info = rdistance;
-    }
-
-  /* Set distance value. */
-  rdistance->distance = distance;
-
-  /* Reset access-list configuration. */
-  if (rdistance->access_list)
-    {
-      free (rdistance->access_list);
-      rdistance->access_list = NULL;
-    }
-  if (access_list_str)
-    rdistance->access_list = strdup (access_list_str);
-
-  return CMD_SUCCESS;
-}
-
-static int
-rip_distance_unset (struct vty *vty, const char *distance_str,
-                   const char *ip_str, const char *access_list_str)
-{
-  int ret;
-  struct prefix_ipv4 p;
-  struct route_node *rn;
-  struct rip_distance *rdistance;
-
-  ret = str2prefix_ipv4 (ip_str, &p);
-  if (ret == 0)
-    {
-      vty_outln (vty, "Malformed prefix");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-
-  rn = route_node_lookup (rip_distance_table, (struct prefix *)&p);
-  if (! rn)
-    {
-      vty_outln (vty, "Can't find specified prefix");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
-
-  rdistance = rn->info;
-
-  if (rdistance->access_list)
-    free (rdistance->access_list);
-  rip_distance_free (rdistance);
-
-  rn->info = NULL;
-  route_unlock_node (rn);
-  route_unlock_node (rn);
-
-  return CMD_SUCCESS;
+static void rip_distance_free(struct rip_distance *rdistance)
+{
+       XFREE(MTYPE_RIP_DISTANCE, rdistance);
 }
 
-static void
-rip_distance_reset (void)
+static int rip_distance_set(struct vty *vty, const char *distance_str,
+                           const char *ip_str, const char *access_list_str)
 {
-  struct route_node *rn;
-  struct rip_distance *rdistance;
+       int ret;
+       struct prefix_ipv4 p;
+       u_char distance;
+       struct route_node *rn;
+       struct rip_distance *rdistance;
+
+       ret = str2prefix_ipv4(ip_str, &p);
+       if (ret == 0) {
+               vty_out(vty, "Malformed prefix\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       distance = atoi(distance_str);
+
+       /* Get RIP distance node. */
+       rn = route_node_get(rip_distance_table, (struct prefix *)&p);
+       if (rn->info) {
+               rdistance = rn->info;
+               route_unlock_node(rn);
+       } else {
+               rdistance = rip_distance_new();
+               rn->info = rdistance;
+       }
+
+       /* Set distance value. */
+       rdistance->distance = distance;
+
+       /* Reset access-list configuration. */
+       if (rdistance->access_list) {
+               free(rdistance->access_list);
+               rdistance->access_list = NULL;
+       }
+       if (access_list_str)
+               rdistance->access_list = strdup(access_list_str);
+
+       return CMD_SUCCESS;
+}
+
+static int rip_distance_unset(struct vty *vty, const char *distance_str,
+                             const char *ip_str, const char *access_list_str)
+{
+       int ret;
+       struct prefix_ipv4 p;
+       struct route_node *rn;
+       struct rip_distance *rdistance;
+
+       ret = str2prefix_ipv4(ip_str, &p);
+       if (ret == 0) {
+               vty_out(vty, "Malformed prefix\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       rn = route_node_lookup(rip_distance_table, (struct prefix *)&p);
+       if (!rn) {
+               vty_out(vty, "Can't find specified prefix\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       rdistance = rn->info;
 
-  for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
-    if ((rdistance = rn->info) != NULL)
-      {
        if (rdistance->access_list)
-         free (rdistance->access_list);
-       rip_distance_free (rdistance);
+               free(rdistance->access_list);
+       rip_distance_free(rdistance);
+
        rn->info = NULL;
-       route_unlock_node (rn);
-      }
+       route_unlock_node(rn);
+       route_unlock_node(rn);
+
+       return CMD_SUCCESS;
 }
 
-/* Apply RIP information to distance method. */
-u_char
-rip_distance_apply (struct rip_info *rinfo)
-{
-  struct route_node *rn;
-  struct prefix_ipv4 p;
-  struct rip_distance *rdistance;
-  struct access_list *alist;
-
-  if (! rip)
-    return 0;
-
-  memset (&p, 0, sizeof (struct prefix_ipv4));
-  p.family = AF_INET;
-  p.prefix = rinfo->from;
-  p.prefixlen = IPV4_MAX_BITLEN;
-
-  /* Check source address. */
-  rn = route_node_match (rip_distance_table, (struct prefix *) &p);
-  if (rn)
-    {
-      rdistance = rn->info;
-      route_unlock_node (rn);
-
-      if (rdistance->access_list)
-       {
-         alist = access_list_lookup (AFI_IP, rdistance->access_list);
-         if (alist == NULL)
-           return 0;
-         if (access_list_apply (alist, &rinfo->rp->p) == FILTER_DENY)
-           return 0;
+static void rip_distance_reset(void)
+{
+       struct route_node *rn;
+       struct rip_distance *rdistance;
+
+       for (rn = route_top(rip_distance_table); rn; rn = route_next(rn))
+               if ((rdistance = rn->info) != NULL) {
+                       if (rdistance->access_list)
+                               free(rdistance->access_list);
+                       rip_distance_free(rdistance);
+                       rn->info = NULL;
+                       route_unlock_node(rn);
+               }
+}
 
-         return rdistance->distance;
+/* Apply RIP information to distance method. */
+u_char rip_distance_apply(struct rip_info *rinfo)
+{
+       struct route_node *rn;
+       struct prefix_ipv4 p;
+       struct rip_distance *rdistance;
+       struct access_list *alist;
+
+       if (!rip)
+               return 0;
+
+       memset(&p, 0, sizeof(struct prefix_ipv4));
+       p.family = AF_INET;
+       p.prefix = rinfo->from;
+       p.prefixlen = IPV4_MAX_BITLEN;
+
+       /* Check source address. */
+       rn = route_node_match(rip_distance_table, (struct prefix *)&p);
+       if (rn) {
+               rdistance = rn->info;
+               route_unlock_node(rn);
+
+               if (rdistance->access_list) {
+                       alist = access_list_lookup(AFI_IP,
+                                                  rdistance->access_list);
+                       if (alist == NULL)
+                               return 0;
+                       if (access_list_apply(alist, &rinfo->rp->p)
+                           == FILTER_DENY)
+                               return 0;
+
+                       return rdistance->distance;
+               } else
+                       return rdistance->distance;
        }
-      else
-       return rdistance->distance;
-    }
 
-  if (rip->distance)
-    return rip->distance;
+       if (rip->distance)
+               return rip->distance;
 
-  return 0;
+       return 0;
 }
 
-static void
-rip_distance_show (struct vty *vty)
-{
-  struct route_node *rn;
-  struct rip_distance *rdistance;
-  int header = 1;
-  char buf[BUFSIZ];
-  
-  vty_outln (vty, "  Distance: (default is %d)",
-          rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT);
-
-  for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
-    if ((rdistance = rn->info) != NULL)
-      {
-       if (header)
-         {
-           vty_outln (vty,"    Address           Distance  List");
-           header = 0;
-         }
-       sprintf (buf, "%s/%d", inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen);
-       vty_outln (vty, "    %-20s  %4d  %s",
-                buf, rdistance->distance,
-                rdistance->access_list ? rdistance->access_list : "");
-      }
+static void rip_distance_show(struct vty *vty)
+{
+       struct route_node *rn;
+       struct rip_distance *rdistance;
+       int header = 1;
+       char buf[BUFSIZ];
+
+       vty_out(vty, "  Distance: (default is %d)\n",
+               rip->distance ? rip->distance : ZEBRA_RIP_DISTANCE_DEFAULT);
+
+       for (rn = route_top(rip_distance_table); rn; rn = route_next(rn))
+               if ((rdistance = rn->info) != NULL) {
+                       if (header) {
+                               vty_out(vty,
+                                       "    Address           Distance  List\n");
+                               header = 0;
+                       }
+                       sprintf(buf, "%s/%d", inet_ntoa(rn->p.u.prefix4),
+                               rn->p.prefixlen);
+                       vty_out(vty, "    %-20s  %4d  %s\n", buf,
+                               rdistance->distance,
+                               rdistance->access_list ? rdistance->access_list
+                                                      : "");
+               }
 }
 
 DEFUN (rip_distance,
@@ -3265,9 +3223,9 @@ DEFUN (rip_distance,
        "Administrative distance\n"
        "Distance value\n")
 {
-  int idx_number = 1;
-  rip->distance = atoi (argv[idx_number]->arg);
-  return CMD_SUCCESS;
+       int idx_number = 1;
+       rip->distance = atoi(argv[idx_number]->arg);
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_distance,
@@ -3277,8 +3235,8 @@ DEFUN (no_rip_distance,
        "Administrative distance\n"
        "Distance value\n")
 {
-  rip->distance = 0;
-  return CMD_SUCCESS;
+       rip->distance = 0;
+       return CMD_SUCCESS;
 }
 
 DEFUN (rip_distance_source,
@@ -3288,10 +3246,11 @@ DEFUN (rip_distance_source,
        "Distance value\n"
        "IP source prefix\n")
 {
-  int idx_number = 1;
-  int idx_ipv4_prefixlen = 2;
-  rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
-  return CMD_SUCCESS;
+       int idx_number = 1;
+       int idx_ipv4_prefixlen = 2;
+       rip_distance_set(vty, argv[idx_number]->arg,
+                        argv[idx_ipv4_prefixlen]->arg, NULL);
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_distance_source,
@@ -3302,10 +3261,11 @@ DEFUN (no_rip_distance_source,
        "Distance value\n"
        "IP source prefix\n")
 {
-  int idx_number = 2;
-  int idx_ipv4_prefixlen = 3;
-  rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, NULL);
-  return CMD_SUCCESS;
+       int idx_number = 2;
+       int idx_ipv4_prefixlen = 3;
+       rip_distance_unset(vty, argv[idx_number]->arg,
+                          argv[idx_ipv4_prefixlen]->arg, NULL);
+       return CMD_SUCCESS;
 }
 
 DEFUN (rip_distance_source_access_list,
@@ -3316,11 +3276,12 @@ DEFUN (rip_distance_source_access_list,
        "IP source prefix\n"
        "Access list name\n")
 {
-  int idx_number = 1;
-  int idx_ipv4_prefixlen = 2;
-  int idx_word = 3;
-  rip_distance_set (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
-  return CMD_SUCCESS;
+       int idx_number = 1;
+       int idx_ipv4_prefixlen = 2;
+       int idx_word = 3;
+       rip_distance_set(vty, argv[idx_number]->arg,
+                        argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_distance_source_access_list,
@@ -3332,51 +3293,50 @@ DEFUN (no_rip_distance_source_access_list,
        "IP source prefix\n"
        "Access list name\n")
 {
-  int idx_number = 2;
-  int idx_ipv4_prefixlen = 3;
-  int idx_word = 4;
-  rip_distance_unset (vty, argv[idx_number]->arg, argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
-  return CMD_SUCCESS;
+       int idx_number = 2;
+       int idx_ipv4_prefixlen = 3;
+       int idx_word = 4;
+       rip_distance_unset(vty, argv[idx_number]->arg,
+                          argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
+       return CMD_SUCCESS;
 }
 
 /* Update ECMP routes to zebra when ECMP is disabled. */
-static void
-rip_ecmp_disable (void)
-{
-  struct route_node *rp;
-  struct rip_info *rinfo, *tmp_rinfo;
-  struct list *list;
-  struct listnode *node, *nextnode;
-
-  if (!rip)
-    return;
-
-  for (rp = route_top (rip->table); rp; rp = route_next (rp))
-    if ((list = rp->info) != NULL && listcount (list) > 1)
-      {
-        rinfo = listgetdata (listhead (list));
-        if (!rip_route_rte (rinfo))
-          continue;
-
-        /* Drop all other entries, except the first one. */
-        for (ALL_LIST_ELEMENTS (list, node, nextnode, tmp_rinfo))
-          if (tmp_rinfo != rinfo)
-            {
-              RIP_TIMER_OFF (tmp_rinfo->t_timeout);
-              RIP_TIMER_OFF (tmp_rinfo->t_garbage_collect);
-              list_delete_node (list, node);
-              rip_info_free (tmp_rinfo);
-            }
-
-        /* Update zebra. */
-        rip_zebra_ipv4_add (rp);
-
-        /* Set the route change flag. */
-        SET_FLAG (rinfo->flags, RIP_RTF_CHANGED);
-
-        /* Signal the output process to trigger an update. */
-        rip_event (RIP_TRIGGERED_UPDATE, 0);
-      }
+static void rip_ecmp_disable(void)
+{
+       struct route_node *rp;
+       struct rip_info *rinfo, *tmp_rinfo;
+       struct list *list;
+       struct listnode *node, *nextnode;
+
+       if (!rip)
+               return;
+
+       for (rp = route_top(rip->table); rp; rp = route_next(rp))
+               if ((list = rp->info) != NULL && listcount(list) > 1) {
+                       rinfo = listgetdata(listhead(list));
+                       if (!rip_route_rte(rinfo))
+                               continue;
+
+                       /* Drop all other entries, except the first one. */
+                       for (ALL_LIST_ELEMENTS(list, node, nextnode, tmp_rinfo))
+                               if (tmp_rinfo != rinfo) {
+                                       RIP_TIMER_OFF(tmp_rinfo->t_timeout);
+                                       RIP_TIMER_OFF(
+                                               tmp_rinfo->t_garbage_collect);
+                                       list_delete_node(list, node);
+                                       rip_info_free(tmp_rinfo);
+                               }
+
+                       /* Update zebra. */
+                       rip_zebra_ipv4_add(rp);
+
+                       /* Set the route change flag. */
+                       SET_FLAG(rinfo->flags, RIP_RTF_CHANGED);
+
+                       /* Signal the output process to trigger an update. */
+                       rip_event(RIP_TRIGGERED_UPDATE, 0);
+               }
 }
 
 DEFUN (rip_allow_ecmp,
@@ -3384,15 +3344,14 @@ DEFUN (rip_allow_ecmp,
        "allow-ecmp",
        "Allow Equal Cost MultiPath\n")
 {
-  if (rip->ecmp)
-    {
-      vty_outln (vty, "ECMP is already enabled.");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
+       if (rip->ecmp) {
+               vty_out(vty, "ECMP is already enabled.\n");
+               return CMD_WARNING;
+       }
 
-  rip->ecmp = 1;
-  zlog_info ("ECMP is enabled.");
-  return CMD_SUCCESS;
+       rip->ecmp = 1;
+       zlog_info("ECMP is enabled.");
+       return CMD_SUCCESS;
 }
 
 DEFUN (no_rip_allow_ecmp,
@@ -3401,62 +3360,55 @@ DEFUN (no_rip_allow_ecmp,
        NO_STR
        "Allow Equal Cost MultiPath\n")
 {
-  if (!rip->ecmp)
-    {
-      vty_outln (vty, "ECMP is already disabled.");
-      return CMD_WARNING_CONFIG_FAILED;
-    }
+       if (!rip->ecmp) {
+               vty_out(vty, "ECMP is already disabled.\n");
+               return CMD_WARNING;
+       }
 
-  rip->ecmp = 0;
-  zlog_info ("ECMP is disabled.");
-  rip_ecmp_disable ();
-  return CMD_SUCCESS;
+       rip->ecmp = 0;
+       zlog_info("ECMP is disabled.");
+       rip_ecmp_disable();
+       return CMD_SUCCESS;
 }
 
 /* Print out routes update time. */
-static void
-rip_vty_out_uptime (struct vty *vty, struct rip_info *rinfo)
+static void rip_vty_out_uptime(struct vty *vty, struct rip_info *rinfo)
 {
-  time_t clock;
-  struct tm *tm;
+       time_t clock;
+       struct tm *tm;
 #define TIME_BUF 25
-  char timebuf [TIME_BUF];
-  struct thread *thread;
-
-  if ((thread = rinfo->t_timeout) != NULL)
-    {
-      clock = thread_timer_remain_second (thread);
-      tm = gmtime (&clock);
-      strftime (timebuf, TIME_BUF, "%M:%S", tm);
-      vty_out (vty, "%5s", timebuf);
-    }
-  else if ((thread = rinfo->t_garbage_collect) != NULL)
-    {
-      clock = thread_timer_remain_second (thread);
-      tm = gmtime (&clock);
-      strftime (timebuf, TIME_BUF, "%M:%S", tm);
-      vty_out (vty, "%5s", timebuf);
-    }
-}
-
-static const char *
-rip_route_type_print (int sub_type)
-{
-  switch (sub_type)
-    {
-      case RIP_ROUTE_RTE:
-       return "n";
-      case RIP_ROUTE_STATIC:
-       return "s";
-      case RIP_ROUTE_DEFAULT:
-       return "d";
-      case RIP_ROUTE_REDISTRIBUTE:
-       return "r";
-      case RIP_ROUTE_INTERFACE:
-       return "i";
-      default:
-       return "?";
-    }
+       char timebuf[TIME_BUF];
+       struct thread *thread;
+
+       if ((thread = rinfo->t_timeout) != NULL) {
+               clock = thread_timer_remain_second(thread);
+               tm = gmtime(&clock);
+               strftime(timebuf, TIME_BUF, "%M:%S", tm);
+               vty_out(vty, "%5s", timebuf);
+       } else if ((thread = rinfo->t_garbage_collect) != NULL) {
+               clock = thread_timer_remain_second(thread);
+               tm = gmtime(&clock);
+               strftime(timebuf, TIME_BUF, "%M:%S", tm);
+               vty_out(vty, "%5s", timebuf);
+       }
+}
+
+static const char *rip_route_type_print(int sub_type)
+{
+       switch (sub_type) {
+       case RIP_ROUTE_RTE:
+               return "n";
+       case RIP_ROUTE_STATIC:
+               return "s";
+       case RIP_ROUTE_DEFAULT:
+               return "d";
+       case RIP_ROUTE_REDISTRIBUTE:
+               return "r";
+       case RIP_ROUTE_INTERFACE:
+               return "i";
+       default:
+               return "?";
+       }
 }
 
 DEFUN (show_ip_rip,
@@ -3466,77 +3418,99 @@ DEFUN (show_ip_rip,
        IP_STR
        "Show RIP routes\n")
 {
-  struct route_node *np;
-  struct rip_info *rinfo = NULL;
-  struct list *list = NULL;
-  struct listnode *listnode = NULL;
-
-  if (! rip)
-    return CMD_SUCCESS;
-
-  vty_outln (vty, "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP%s"
-          "Sub-codes:%s"
-           "      (n) - normal, (s) - static, (d) - default, (r) - redistribute,%s"
-          "      (i) - interface%s%s"
-          "     Network            Next Hop         Metric From            Tag Time",
-          VTYNL, VTYNL,  VTYNL, VTYNL, VTYNL);
-  
-  for (np = route_top (rip->table); np; np = route_next (np))
-    if ((list = np->info) != NULL)
-      for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
-      {
-       int len;
-
-       len = vty_out (vty, "%c(%s) %s/%d",
-                      /* np->lock, For debugging. */
-                      zebra_route_char(rinfo->type),
-                      rip_route_type_print (rinfo->sub_type),
-                      inet_ntoa (np->p.u.prefix4), np->p.prefixlen);
-       
-       len = 24 - len;
-
-       if (len > 0)
-         vty_out (vty, "%*s", len, " ");
-
-        if (rinfo->nexthop.s_addr) 
-         vty_out (vty, "%-20s %2d ", inet_ntoa (rinfo->nexthop),
-                  rinfo->metric);
-        else
-         vty_out (vty, "0.0.0.0              %2d ", rinfo->metric);
-
-       /* Route which exist in kernel routing table. */
-       if ((rinfo->type == ZEBRA_ROUTE_RIP) && 
-           (rinfo->sub_type == RIP_ROUTE_RTE))
-         {
-           vty_out (vty, "%-15s ", inet_ntoa (rinfo->from));
-           vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag);
-           rip_vty_out_uptime (vty, rinfo);
-         }
-       else if (rinfo->metric == RIP_METRIC_INFINITY)
-         {
-           vty_out (vty, "self            ");
-           vty_out (vty, "%3"ROUTE_TAG_PRI" ", (route_tag_t)rinfo->tag);
-           rip_vty_out_uptime (vty, rinfo);
-         }
-       else
-         {
-           if (rinfo->external_metric)
-             {
-               len = vty_out (vty, "self (%s:%d)", 
-                              zebra_route_string(rinfo->type),
-                              rinfo->external_metric);
-               len = 16 - len;
-               if (len > 0)
-                 vty_out (vty, "%*s", len, " ");
-             }
-           else
-             vty_out (vty, "self            ");
-           vty_out (vty, "%3"ROUTE_TAG_PRI, (route_tag_t)rinfo->tag);
-         }
-
-       vty_out (vty, VTYNL);
-      }
-  return CMD_SUCCESS;
+       struct route_node *np;
+       struct rip_info *rinfo = NULL;
+       struct list *list = NULL;
+       struct listnode *listnode = NULL;
+
+       if (!rip)
+               return CMD_SUCCESS;
+
+       vty_out(vty,
+               "Codes: R - RIP, C - connected, S - Static, O - OSPF, B - BGP\n"
+               "Sub-codes:\n"
+               "      (n) - normal, (s) - static, (d) - default, (r) - redistribute,\n"
+               "      (i) - interface\n\n"
+               "     Network            Next Hop         Metric From            Tag Time\n");
+
+       for (np = route_top(rip->table); np; np = route_next(np))
+               if ((list = np->info) != NULL)
+                       for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
+                               int len;
+
+                               len = vty_out(
+                                       vty, "%c(%s) %s/%d",
+                                       /* np->lock, For debugging. */
+                                       zebra_route_char(rinfo->type),
+                                       rip_route_type_print(rinfo->sub_type),
+                                       inet_ntoa(np->p.u.prefix4),
+                                       np->p.prefixlen);
+
+                               len = 24 - len;
+
+                               if (len > 0)
+                                       vty_out(vty, "%*s", len, " ");
+
+                               switch(rinfo->nh.type) {
+                               case NEXTHOP_TYPE_IPV4:
+                               case NEXTHOP_TYPE_IPV4_IFINDEX:
+                                       vty_out(vty, "%-20s %2d ",
+                                               inet_ntoa(rinfo->nh.gate.ipv4),
+                                               rinfo->metric);
+                                       break;
+                               case NEXTHOP_TYPE_IFINDEX:
+                                       vty_out(vty,
+                                               "0.0.0.0              %2d ",
+                                               rinfo->metric);
+                                       break;
+                               case NEXTHOP_TYPE_BLACKHOLE:
+                                       vty_out(vty,
+                                               "blackhole            %2d ",
+                                               rinfo->metric);
+                                       break;
+                               case NEXTHOP_TYPE_IPV6:
+                               case NEXTHOP_TYPE_IPV6_IFINDEX:
+                                       vty_out(vty,
+                                               "V6 Address Hidden    %2d ",
+                                               rinfo->metric);
+                                       break;
+                               }
+
+                               /* Route which exist in kernel routing table. */
+                               if ((rinfo->type == ZEBRA_ROUTE_RIP)
+                                   && (rinfo->sub_type == RIP_ROUTE_RTE)) {
+                                       vty_out(vty, "%-15s ",
+                                               inet_ntoa(rinfo->from));
+                                       vty_out(vty, "%3" ROUTE_TAG_PRI " ",
+                                               (route_tag_t)rinfo->tag);
+                                       rip_vty_out_uptime(vty, rinfo);
+                               } else if (rinfo->metric
+                                          == RIP_METRIC_INFINITY) {
+                                       vty_out(vty, "self            ");
+                                       vty_out(vty, "%3" ROUTE_TAG_PRI " ",
+                                               (route_tag_t)rinfo->tag);
+                                       rip_vty_out_uptime(vty, rinfo);
+                               } else {
+                                       if (rinfo->external_metric) {
+                                               len = vty_out(
+                                                       vty, "self (%s:%d)",
+                                                       zebra_route_string(
+                                                               rinfo->type),
+                                                       rinfo->external_metric);
+                                               len = 16 - len;
+                                               if (len > 0)
+                                                       vty_out(vty, "%*s", len,
+                                                               " ");
+                                       } else
+                                               vty_out(vty,
+                                                       "self            ");
+                                       vty_out(vty, "%3" ROUTE_TAG_PRI,
+                                               (route_tag_t)rinfo->tag);
+                               }
+
+                               vty_out(vty, "\n");
+                       }
+       return CMD_SUCCESS;
 }
 
 /* Vincent: formerly, it was show_ip_protocols_rip: "show ip protocols" */
@@ -3548,534 +3522,509 @@ DEFUN (show_ip_rip_status,
        "Show RIP routes\n"
        "IP routing protocol process parameters and statistics\n")
 {
-  struct listnode *node;
-  struct interface *ifp;
-  struct rip_interface *ri;
-  extern const struct message ri_version_msg[];
-  const char *send_version;
-  const char *receive_version;
-
-  if (! rip)
-    return CMD_SUCCESS;
-
-  vty_outln (vty, "Routing Protocol is \"rip\"");
-  vty_out (vty, "  Sending updates every %ld seconds with +/-50%%,",
-          rip->update_time);
-  vty_outln (vty, " next due in %lu seconds", 
-          thread_timer_remain_second(rip->t_update));
-  vty_out (vty, "  Timeout after %ld seconds,", rip->timeout_time);
-  vty_outln (vty, " garbage collect after %ld seconds",rip->garbage_time);
-
-  /* Filtering status show. */
-  config_show_distribute (vty);
-                
-  /* Default metric information. */
-  vty_outln (vty, "  Default redistribution metric is %d",
-          rip->default_metric);
-
-  /* Redistribute information. */
-  vty_out (vty, "  Redistributing:");
-  config_write_rip_redistribute (vty, 0);
-  vty_out (vty, VTYNL);
-
-  vty_out (vty, "  Default version control: send version %s,",
-          lookup_msg(ri_version_msg,rip->version_send, NULL));
-  if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
-    vty_outln (vty, " receive any version ");
-  else
-    vty_outln (vty, " receive version %s ",
-              lookup_msg(ri_version_msg,rip->version_recv, NULL));
-
-  vty_outln (vty, "    Interface        Send  Recv   Key-chain");
-
-  for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
-    {
-      ri = ifp->info;
-
-      if (!ri->running)
-       continue;
-
-      if (ri->enable_network || ri->enable_interface)
-       {
-         if (ri->ri_send == RI_RIP_UNSPEC)
-           send_version = lookup_msg(ri_version_msg, rip->version_send, NULL);
-         else
-           send_version = lookup_msg(ri_version_msg, ri->ri_send, NULL);
-
-         if (ri->ri_receive == RI_RIP_UNSPEC)
-           receive_version = lookup_msg(ri_version_msg, rip->version_recv, NULL);
-         else
-           receive_version = lookup_msg(ri_version_msg, ri->ri_receive, NULL);
-       
-         vty_outln (vty, "    %-17s%-3s   %-3s    %s", ifp->name,
-                  send_version,
-                  receive_version,
-                  ri->key_chain ? ri->key_chain : "");
-       }
-    }
-
-  vty_outln (vty, "  Routing for Networks:");
-  config_write_rip_network (vty, 0);  
-
-  {
-    int found_passive = 0;
-    for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT), node, ifp))
-      {
-       ri = ifp->info;
-
-       if ((ri->enable_network || ri->enable_interface) && ri->passive)
-         {
-           if (!found_passive)
-             {
-               vty_outln (vty, "  Passive Interface(s):");
-               found_passive = 1;
-             }
-           vty_outln (vty, "    %s", ifp->name);
-         }
-      }
-  }
-
-  vty_outln (vty, "  Routing Information Sources:");
-  vty_outln (vty,
-             "    Gateway          BadPackets BadRoutes  Distance Last Update");
-  rip_peer_display (vty);
-
-  rip_distance_show (vty);
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct interface *ifp;
+       struct rip_interface *ri;
+       extern const struct message ri_version_msg[];
+       const char *send_version;
+       const char *receive_version;
+
+       if (!rip)
+               return CMD_SUCCESS;
+
+       vty_out(vty, "Routing Protocol is \"rip\"\n");
+       vty_out(vty, "  Sending updates every %ld seconds with +/-50%%,",
+               rip->update_time);
+       vty_out(vty, " next due in %lu seconds\n",
+               thread_timer_remain_second(rip->t_update));
+       vty_out(vty, "  Timeout after %ld seconds,", rip->timeout_time);
+       vty_out(vty, " garbage collect after %ld seconds\n", rip->garbage_time);
+
+       /* Filtering status show. */
+       config_show_distribute(vty);
+
+       /* Default metric information. */
+       vty_out(vty, "  Default redistribution metric is %d\n",
+               rip->default_metric);
+
+       /* Redistribute information. */
+       vty_out(vty, "  Redistributing:");
+       config_write_rip_redistribute(vty, 0);
+       vty_out(vty, "\n");
+
+       vty_out(vty, "  Default version control: send version %s,",
+               lookup_msg(ri_version_msg, rip->version_send, NULL));
+       if (rip->version_recv == RI_RIP_VERSION_1_AND_2)
+               vty_out(vty, " receive any version \n");
+       else
+               vty_out(vty, " receive version %s \n",
+                       lookup_msg(ri_version_msg, rip->version_recv, NULL));
+
+       vty_out(vty, "    Interface        Send  Recv   Key-chain\n");
+
+       FOR_ALL_INTERFACES (vrf, ifp) {
+               ri = ifp->info;
+
+               if (!ri->running)
+                       continue;
+
+               if (ri->enable_network || ri->enable_interface) {
+                       if (ri->ri_send == RI_RIP_UNSPEC)
+                               send_version =
+                                       lookup_msg(ri_version_msg,
+                                                  rip->version_send, NULL);
+                       else
+                               send_version = lookup_msg(ri_version_msg,
+                                                         ri->ri_send, NULL);
+
+                       if (ri->ri_receive == RI_RIP_UNSPEC)
+                               receive_version =
+                                       lookup_msg(ri_version_msg,
+                                                  rip->version_recv, NULL);
+                       else
+                               receive_version = lookup_msg(
+                                       ri_version_msg, ri->ri_receive, NULL);
+
+                       vty_out(vty, "    %-17s%-3s   %-3s    %s\n", ifp->name,
+                               send_version, receive_version,
+                               ri->key_chain ? ri->key_chain : "");
+               }
+       }
 
-  return CMD_SUCCESS;
-}
+       vty_out(vty, "  Routing for Networks:\n");
+       config_write_rip_network(vty, 0);
 
-/* RIP configuration write function. */
-static int
-config_write_rip (struct vty *vty)
-{
-  int write = 0;
-  struct route_node *rn;
-  struct rip_distance *rdistance;
-
-  if (rip)
-    {
-      /* Router RIP statement. */
-      vty_outln (vty, "router rip");
-      write++;
-  
-      /* RIP version statement.  Default is RIP version 2. */
-      if (rip->version_send != RI_RIP_VERSION_2
-         || rip->version_recv != RI_RIP_VERSION_1_AND_2)
-       vty_outln (vty, " version %d",rip->version_send);
-      /* RIP timer configuration. */
-      if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT 
-         || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT 
-         || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
-       vty_outln (vty, " timers basic %lu %lu %lu",
-                rip->update_time,
-                rip->timeout_time,
-                rip->garbage_time);
-
-      /* Default information configuration. */
-      if (rip->default_information)
        {
-         if (rip->default_information_route_map)
-           vty_outln (vty, " default-information originate route-map %s",
-                    rip->default_information_route_map);
-         else
-           vty_outln (vty," default-information originate");
+               int found_passive = 0;
+               FOR_ALL_INTERFACES (vrf, ifp) {
+                       ri = ifp->info;
+
+                       if ((ri->enable_network || ri->enable_interface)
+                           && ri->passive) {
+                               if (!found_passive) {
+                                       vty_out(vty,
+                                               "  Passive Interface(s):\n");
+                                       found_passive = 1;
+                               }
+                               vty_out(vty, "    %s\n", ifp->name);
+                       }
+               }
        }
 
-      /* Redistribute configuration. */
-      config_write_rip_redistribute (vty, 1);
-
-      /* RIP offset-list configuration. */
-      config_write_rip_offset_list (vty);
+       vty_out(vty, "  Routing Information Sources:\n");
+       vty_out(vty,
+               "    Gateway          BadPackets BadRoutes  Distance Last Update\n");
+       rip_peer_display(vty);
 
-      /* RIP enabled network and interface configuration. */
-      config_write_rip_network (vty, 1);
-                       
-      /* RIP default metric configuration */
-      if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
-        vty_outln (vty, " default-metric %d",
-                rip->default_metric);
+       rip_distance_show(vty);
 
-      /* Distribute configuration. */
-      write += config_write_distribute (vty);
+       return CMD_SUCCESS;
+}
 
-      /* Interface routemap configuration */
-      write += config_write_if_rmap (vty);
+/* RIP configuration write function. */
+static int config_write_rip(struct vty *vty)
+{
+       int write = 0;
+       struct route_node *rn;
+       struct rip_distance *rdistance;
+
+       if (rip) {
+               /* Router RIP statement. */
+               vty_out(vty, "router rip\n");
+               write++;
+
+               /* RIP version statement.  Default is RIP version 2. */
+               if (rip->version_send != RI_RIP_VERSION_2
+                   || rip->version_recv != RI_RIP_VERSION_1_AND_2)
+                       vty_out(vty, " version %d\n", rip->version_send);
+
+               /* RIP timer configuration. */
+               if (rip->update_time != RIP_UPDATE_TIMER_DEFAULT
+                   || rip->timeout_time != RIP_TIMEOUT_TIMER_DEFAULT
+                   || rip->garbage_time != RIP_GARBAGE_TIMER_DEFAULT)
+                       vty_out(vty, " timers basic %lu %lu %lu\n",
+                               rip->update_time, rip->timeout_time,
+                               rip->garbage_time);
+
+               /* Default information configuration. */
+               if (rip->default_information) {
+                       if (rip->default_information_route_map)
+                               vty_out(vty,
+                                       " default-information originate route-map %s\n",
+                                       rip->default_information_route_map);
+                       else
+                               vty_out(vty,
+                                       " default-information originate\n");
+               }
 
-      /* Distance configuration. */
-      if (rip->distance)
-       vty_outln (vty, " distance %d", rip->distance);
+               /* Redistribute configuration. */
+               config_write_rip_redistribute(vty, 1);
+
+               /* RIP offset-list configuration. */
+               config_write_rip_offset_list(vty);
+
+               /* RIP enabled network and interface configuration. */
+               config_write_rip_network(vty, 1);
+
+               /* RIP default metric configuration */
+               if (rip->default_metric != RIP_DEFAULT_METRIC_DEFAULT)
+                       vty_out(vty, " default-metric %d\n",
+                               rip->default_metric);
+
+               /* Distribute configuration. */
+               write += config_write_distribute(vty);
+
+               /* Interface routemap configuration */
+               write += config_write_if_rmap(vty);
+
+               /* Distance configuration. */
+               if (rip->distance)
+                       vty_out(vty, " distance %d\n", rip->distance);
+
+               /* RIP source IP prefix distance configuration. */
+               for (rn = route_top(rip_distance_table); rn;
+                    rn = route_next(rn))
+                       if ((rdistance = rn->info) != NULL)
+                               vty_out(vty, " distance %d %s/%d %s\n",
+                                       rdistance->distance,
+                                       inet_ntoa(rn->p.u.prefix4),
+                                       rn->p.prefixlen,
+                                       rdistance->access_list
+                                               ? rdistance->access_list
+                                               : "");
+
+               /* ECMP configuration. */
+               if (rip->ecmp)
+                       vty_out(vty, " allow-ecmp\n");
+
+               /* RIP static route configuration. */
+               for (rn = route_top(rip->route); rn; rn = route_next(rn))
+                       if (rn->info)
+                               vty_out(vty, " route %s/%d\n",
+                                       inet_ntoa(rn->p.u.prefix4),
+                                       rn->p.prefixlen);
+       }
+       return write;
+}
 
-      /* RIP source IP prefix distance configuration. */
-      for (rn = route_top (rip_distance_table); rn; rn = route_next (rn))
-       if ((rdistance = rn->info) != NULL)
-         vty_outln (vty, " distance %d %s/%d %s", rdistance->distance,
-                  inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen,
-                  rdistance->access_list ? rdistance->access_list : "");
+/* RIP node structure. */
+static struct cmd_node rip_node = {RIP_NODE, "%s(config-router)# ", 1};
 
-      /* ECMP configuration. */
-      if (rip->ecmp)
-        vty_outln (vty, " allow-ecmp");
+/* Distribute-list update functions. */
+static void rip_distribute_update(struct distribute *dist)
+{
+       struct interface *ifp;
+       struct rip_interface *ri;
+       struct access_list *alist;
+       struct prefix_list *plist;
 
-      /* RIP static route configuration. */
-      for (rn = route_top (rip->route); rn; rn = route_next (rn))
-       if (rn->info)
-         vty_outln (vty, " route %s/%d", 
-                  inet_ntoa (rn->p.u.prefix4),
-                  rn->p.prefixlen);
+       if (!dist->ifname)
+               return;
 
-    }
-  return write;
-}
+       ifp = if_lookup_by_name(dist->ifname, VRF_DEFAULT);
+       if (ifp == NULL)
+               return;
 
-/* RIP node structure. */
-static struct cmd_node rip_node =
-{
-  RIP_NODE,
-  "%s(config-router)# ",
-  1
-};
+       ri = ifp->info;
 
-/* Distribute-list update functions. */
-static void
-rip_distribute_update (struct distribute *dist)
-{
-  struct interface *ifp;
-  struct rip_interface *ri;
-  struct access_list *alist;
-  struct prefix_list *plist;
-
-  if (! dist->ifname)
-    return;
-
-  ifp = if_lookup_by_name (dist->ifname, VRF_DEFAULT);
-  if (ifp == NULL)
-    return;
-
-  ri = ifp->info;
-
-  if (dist->list[DISTRIBUTE_V4_IN])
-    {
-      alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_IN]);
-      if (alist)
-       ri->list[RIP_FILTER_IN] = alist;
-      else
-       ri->list[RIP_FILTER_IN] = NULL;
-    }
-  else
-    ri->list[RIP_FILTER_IN] = NULL;
-
-  if (dist->list[DISTRIBUTE_V4_OUT])
-    {
-      alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_V4_OUT]);
-      if (alist)
-       ri->list[RIP_FILTER_OUT] = alist;
-      else
-       ri->list[RIP_FILTER_OUT] = NULL;
-    }
-  else
-    ri->list[RIP_FILTER_OUT] = NULL;
-
-  if (dist->prefix[DISTRIBUTE_V4_IN])
-    {
-      plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_IN]);
-      if (plist)
-       ri->prefix[RIP_FILTER_IN] = plist;
-      else
-       ri->prefix[RIP_FILTER_IN] = NULL;
-    }
-  else
-    ri->prefix[RIP_FILTER_IN] = NULL;
-
-  if (dist->prefix[DISTRIBUTE_V4_OUT])
-    {
-      plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_V4_OUT]);
-      if (plist)
-       ri->prefix[RIP_FILTER_OUT] = plist;
-      else
-       ri->prefix[RIP_FILTER_OUT] = NULL;
-    }
-  else
-    ri->prefix[RIP_FILTER_OUT] = NULL;
-}
-
-void
-rip_distribute_update_interface (struct interface *ifp)
-{
-  struct distribute *dist;
-
-  dist = distribute_lookup (ifp->name);
-  if (dist)
-    rip_distribute_update (dist);
+       if (dist->list[DISTRIBUTE_V4_IN]) {
+               alist = access_list_lookup(AFI_IP,
+                                          dist->list[DISTRIBUTE_V4_IN]);
+               if (alist)
+                       ri->list[RIP_FILTER_IN] = alist;
+               else
+                       ri->list[RIP_FILTER_IN] = NULL;
+       } else
+               ri->list[RIP_FILTER_IN] = NULL;
+
+       if (dist->list[DISTRIBUTE_V4_OUT]) {
+               alist = access_list_lookup(AFI_IP,
+                                          dist->list[DISTRIBUTE_V4_OUT]);
+               if (alist)
+                       ri->list[RIP_FILTER_OUT] = alist;
+               else
+                       ri->list[RIP_FILTER_OUT] = NULL;
+       } else
+               ri->list[RIP_FILTER_OUT] = NULL;
+
+       if (dist->prefix[DISTRIBUTE_V4_IN]) {
+               plist = prefix_list_lookup(AFI_IP,
+                                          dist->prefix[DISTRIBUTE_V4_IN]);
+               if (plist)
+                       ri->prefix[RIP_FILTER_IN] = plist;
+               else
+                       ri->prefix[RIP_FILTER_IN] = NULL;
+       } else
+               ri->prefix[RIP_FILTER_IN] = NULL;
+
+       if (dist->prefix[DISTRIBUTE_V4_OUT]) {
+               plist = prefix_list_lookup(AFI_IP,
+                                          dist->prefix[DISTRIBUTE_V4_OUT]);
+               if (plist)
+                       ri->prefix[RIP_FILTER_OUT] = plist;
+               else
+                       ri->prefix[RIP_FILTER_OUT] = NULL;
+       } else
+               ri->prefix[RIP_FILTER_OUT] = NULL;
+}
+
+void rip_distribute_update_interface(struct interface *ifp)
+{
+       struct distribute *dist;
+
+       dist = distribute_lookup(ifp->name);
+       if (dist)
+               rip_distribute_update(dist);
 }
 
 /* Update all interface's distribute list. */
 /* ARGSUSED */
-static void
-rip_distribute_update_all (struct prefix_list *notused)
+static void rip_distribute_update_all(struct prefix_list *notused)
 {
-  struct interface *ifp;
-  struct listnode *node, *nnode;
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct interface *ifp;
 
-  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
-    rip_distribute_update_interface (ifp);
+       FOR_ALL_INTERFACES (vrf, ifp)
+               rip_distribute_update_interface(ifp);
 }
 /* ARGSUSED */
-static void
-rip_distribute_update_all_wrapper(struct access_list *notused)
+static void rip_distribute_update_all_wrapper(struct access_list *notused)
 {
-        rip_distribute_update_all(NULL);
+       rip_distribute_update_all(NULL);
 }
 
 /* Delete all added rip route. */
-void
-rip_clean (void)
+void rip_clean(void)
 {
-  int i;
-  struct route_node *rp;
-  struct rip_info *rinfo = NULL;
-  struct list *list = NULL;
-  struct listnode *listnode = NULL;
+       int i;
+       struct route_node *rp;
+       struct rip_info *rinfo = NULL;
+       struct list *list = NULL;
+       struct listnode *listnode = NULL;
+
+       if (rip) {
+               QOBJ_UNREG(rip);
+
+               /* Clear RIP routes */
+               for (rp = route_top(rip->table); rp; rp = route_next(rp))
+                       if ((list = rp->info) != NULL) {
+                               rinfo = listgetdata(listhead(list));
+                               if (rip_route_rte(rinfo))
+                                       rip_zebra_ipv4_delete(rp);
+
+                               for (ALL_LIST_ELEMENTS_RO(list, listnode,
+                                                         rinfo)) {
+                                       RIP_TIMER_OFF(rinfo->t_timeout);
+                                       RIP_TIMER_OFF(rinfo->t_garbage_collect);
+                                       rip_info_free(rinfo);
+                               }
+                               list_delete_and_null(&list);
+                               rp->info = NULL;
+                               route_unlock_node(rp);
+                       }
+
+               /* Cancel RIP related timers. */
+               RIP_TIMER_OFF(rip->t_update);
+               RIP_TIMER_OFF(rip->t_triggered_update);
+               RIP_TIMER_OFF(rip->t_triggered_interval);
+
+               /* Cancel read thread. */
+               THREAD_READ_OFF(rip->t_read);
+
+               /* Close RIP socket. */
+               if (rip->sock >= 0) {
+                       close(rip->sock);
+                       rip->sock = -1;
+               }
 
-  if (rip)
-    {
-      QOBJ_UNREG (rip);
-
-      /* Clear RIP routes */
-      for (rp = route_top (rip->table); rp; rp = route_next (rp))
-        if ((list = rp->info) != NULL)
-          {
-            rinfo = listgetdata (listhead (list));
-            if (rip_route_rte (rinfo))
-              rip_zebra_ipv4_delete (rp);
-
-            for (ALL_LIST_ELEMENTS_RO (list, listnode, rinfo))
-              {
-                RIP_TIMER_OFF (rinfo->t_timeout);
-                RIP_TIMER_OFF (rinfo->t_garbage_collect);
-                rip_info_free (rinfo);
-              }
-            list_delete (list);
-            rp->info = NULL;
-            route_unlock_node (rp);
-          }
-
-      /* Cancel RIP related timers. */
-      RIP_TIMER_OFF (rip->t_update);
-      RIP_TIMER_OFF (rip->t_triggered_update);
-      RIP_TIMER_OFF (rip->t_triggered_interval);
-
-      /* Cancel read thread. */
-      THREAD_READ_OFF (rip->t_read);
-
-      /* Close RIP socket. */
-      if (rip->sock >= 0)
-       {
-         close (rip->sock);
-         rip->sock = -1;
-       }
-
-      /* Static RIP route configuration. */
-      for (rp = route_top (rip->route); rp; rp = route_next (rp))
-       if (rp->info)
-         {
-           rp->info = NULL;
-           route_unlock_node (rp);
-         }
-
-      /* RIP neighbor configuration. */
-      for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))
-       if (rp->info)
-         {
-           rp->info = NULL;
-           route_unlock_node (rp);
-         }
-
-      /* Redistribute related clear. */
-      if (rip->default_information_route_map)
-       free (rip->default_information_route_map);
-
-      for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
-       if (rip->route_map[i].name)
-         free (rip->route_map[i].name);
-
-      XFREE (MTYPE_ROUTE_TABLE, rip->table);
-      XFREE (MTYPE_ROUTE_TABLE, rip->route);
-      XFREE (MTYPE_ROUTE_TABLE, rip->neighbor);
-      
-      XFREE (MTYPE_RIP, rip);
-      rip = NULL;
-    }
-
-  rip_clean_network ();
-  rip_passive_nondefault_clean ();
-  rip_offset_clean ();
-  rip_interfaces_clean ();
-  rip_distance_reset ();
-  rip_redistribute_clean ();
+               stream_free(rip->obuf);
+               /* Static RIP route configuration. */
+               for (rp = route_top(rip->route); rp; rp = route_next(rp))
+                       if (rp->info) {
+                               rp->info = NULL;
+                               route_unlock_node(rp);
+                       }
+
+               /* RIP neighbor configuration. */
+               for (rp = route_top(rip->neighbor); rp; rp = route_next(rp))
+                       if (rp->info) {
+                               rp->info = NULL;
+                               route_unlock_node(rp);
+                       }
+
+               /* Redistribute related clear. */
+               if (rip->default_information_route_map)
+                       free(rip->default_information_route_map);
+
+               for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+                       if (rip->route_map[i].name)
+                               free(rip->route_map[i].name);
+
+               XFREE(MTYPE_ROUTE_TABLE, rip->table);
+               XFREE(MTYPE_ROUTE_TABLE, rip->route);
+               XFREE(MTYPE_ROUTE_TABLE, rip->neighbor);
+
+               XFREE(MTYPE_RIP, rip);
+               rip = NULL;
+       }
+
+       rip_clean_network();
+       rip_passive_nondefault_clean();
+       rip_offset_clean();
+       rip_interfaces_clean();
+       rip_distance_reset();
+       rip_redistribute_clean();
 }
 
 /* Reset all values to the default settings. */
-void
-rip_reset (void)
+void rip_reset(void)
 {
-  /* Reset global counters. */
-  rip_global_route_changes = 0;
-  rip_global_queries = 0;
+       /* Reset global counters. */
+       rip_global_route_changes = 0;
+       rip_global_queries = 0;
 
-  /* Call ripd related reset functions. */
-  rip_debug_reset ();
-  rip_route_map_reset ();
+       /* Call ripd related reset functions. */
+       rip_debug_reset();
+       rip_route_map_reset();
 
-  /* Call library reset functions. */
-  vty_reset ();
-  access_list_reset ();
-  prefix_list_reset ();
+       /* Call library reset functions. */
+       vty_reset();
+       access_list_reset();
+       prefix_list_reset();
 
-  distribute_list_reset ();
+       distribute_list_reset();
 
-  rip_interfaces_reset ();
-  rip_distance_reset ();
+       rip_interfaces_reset();
+       rip_distance_reset();
 
-  rip_zclient_reset ();
+       rip_zclient_reset();
 }
 
-static void
-rip_if_rmap_update (struct if_rmap *if_rmap)
+static void rip_if_rmap_update(struct if_rmap *if_rmap)
 {
-  struct interface *ifp;
-  struct rip_interface *ri;
-  struct route_map *rmap;
+       struct interface *ifp;
+       struct rip_interface *ri;
+       struct route_map *rmap;
 
-  ifp = if_lookup_by_name (if_rmap->ifname, VRF_DEFAULT);
-  if (ifp == NULL)
-    return;
+       ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+       if (ifp == NULL)
+               return;
 
-  ri = ifp->info;
+       ri = ifp->info;
 
-  if (if_rmap->routemap[IF_RMAP_IN])
-    {
-      rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_IN]);
-      if (rmap)
-       ri->routemap[IF_RMAP_IN] = rmap;
-      else
-       ri->routemap[IF_RMAP_IN] = NULL;
-    }
-  else
-    ri->routemap[RIP_FILTER_IN] = NULL;
+       if (if_rmap->routemap[IF_RMAP_IN]) {
+               rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
+               if (rmap)
+                       ri->routemap[IF_RMAP_IN] = rmap;
+               else
+                       ri->routemap[IF_RMAP_IN] = NULL;
+       } else
+               ri->routemap[RIP_FILTER_IN] = NULL;
 
-  if (if_rmap->routemap[IF_RMAP_OUT])
-    {
-      rmap = route_map_lookup_by_name (if_rmap->routemap[IF_RMAP_OUT]);
-      if (rmap)
-       ri->routemap[IF_RMAP_OUT] = rmap;
-      else
-       ri->routemap[IF_RMAP_OUT] = NULL;
-    }
-  else
-    ri->routemap[RIP_FILTER_OUT] = NULL;
+       if (if_rmap->routemap[IF_RMAP_OUT]) {
+               rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]);
+               if (rmap)
+                       ri->routemap[IF_RMAP_OUT] = rmap;
+               else
+                       ri->routemap[IF_RMAP_OUT] = NULL;
+       } else
+               ri->routemap[RIP_FILTER_OUT] = NULL;
 }
 
-void
-rip_if_rmap_update_interface (struct interface *ifp)
+void rip_if_rmap_update_interface(struct interface *ifp)
 {
-  struct if_rmap *if_rmap;
+       struct if_rmap *if_rmap;
 
-  if_rmap = if_rmap_lookup (ifp->name);
-  if (if_rmap)
-    rip_if_rmap_update (if_rmap);
+       if_rmap = if_rmap_lookup(ifp->name);
+       if (if_rmap)
+               rip_if_rmap_update(if_rmap);
 }
 
-static void
-rip_routemap_update_redistribute (void)
+static void rip_routemap_update_redistribute(void)
 {
-  int i;
+       int i;
 
-  if (rip)
-    {
-      for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
-       {
-         if (rip->route_map[i].name)
-           rip->route_map[i].map = 
-             route_map_lookup_by_name (rip->route_map[i].name);
+       if (rip) {
+               for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+                       if (rip->route_map[i].name)
+                               rip->route_map[i].map =
+                                       route_map_lookup_by_name(
+                                               rip->route_map[i].name);
+               }
        }
-    }
 }
 
 /* ARGSUSED */
-static void
-rip_routemap_update (const char *notused)
+static void rip_routemap_update(const char *notused)
 {
-  struct interface *ifp;
-  struct listnode *node, *nnode;
+       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct interface *ifp;
 
-  for (ALL_LIST_ELEMENTS (vrf_iflist (VRF_DEFAULT), node, nnode, ifp))
-    rip_if_rmap_update_interface (ifp);
+       FOR_ALL_INTERFACES (vrf, ifp)
+               rip_if_rmap_update_interface(ifp);
 
-  rip_routemap_update_redistribute ();
+       rip_routemap_update_redistribute();
 }
 
 /* Allocate new rip structure and set default value. */
-void
-rip_init (void)
-{
-  /* Install top nodes. */
-  install_node (&rip_node, config_write_rip);
-
-  /* Install rip commands. */
-  install_element (VIEW_NODE, &show_ip_rip_cmd);
-  install_element (VIEW_NODE, &show_ip_rip_status_cmd);
-  install_element (CONFIG_NODE, &router_rip_cmd);
-  install_element (CONFIG_NODE, &no_router_rip_cmd);
-
-  install_default (RIP_NODE);
-  install_element (RIP_NODE, &rip_version_cmd);
-  install_element (RIP_NODE, &no_rip_version_cmd);
-  install_element (RIP_NODE, &rip_default_metric_cmd);
-  install_element (RIP_NODE, &no_rip_default_metric_cmd);
-  install_element (RIP_NODE, &rip_timers_cmd);
-  install_element (RIP_NODE, &no_rip_timers_cmd);
-  install_element (RIP_NODE, &rip_route_cmd);
-  install_element (RIP_NODE, &no_rip_route_cmd);
-  install_element (RIP_NODE, &rip_distance_cmd);
-  install_element (RIP_NODE, &no_rip_distance_cmd);
-  install_element (RIP_NODE, &rip_distance_source_cmd);
-  install_element (RIP_NODE, &no_rip_distance_source_cmd);
-  install_element (RIP_NODE, &rip_distance_source_access_list_cmd);
-  install_element (RIP_NODE, &no_rip_distance_source_access_list_cmd);
-  install_element (RIP_NODE, &rip_allow_ecmp_cmd);
-  install_element (RIP_NODE, &no_rip_allow_ecmp_cmd);
-
-  /* Debug related init. */
-  rip_debug_init ();
-
-  /* Access list install. */
-  access_list_init ();
-  access_list_add_hook (rip_distribute_update_all_wrapper);
-  access_list_delete_hook (rip_distribute_update_all_wrapper);
-
-  /* Prefix list initialize.*/
-  prefix_list_init ();
-  prefix_list_add_hook (rip_distribute_update_all);
-  prefix_list_delete_hook (rip_distribute_update_all);
-
-  /* Distribute list install. */
-  distribute_list_init (RIP_NODE);
-  distribute_list_add_hook (rip_distribute_update);
-  distribute_list_delete_hook (rip_distribute_update);
-
-  /* Route-map */
-  rip_route_map_init ();
-  rip_offset_init ();
-
-  route_map_add_hook (rip_routemap_update);
-  route_map_delete_hook (rip_routemap_update);
-
-  if_rmap_init (RIP_NODE);
-  if_rmap_hook_add (rip_if_rmap_update);
-  if_rmap_hook_delete (rip_if_rmap_update);
-
-  /* Distance control. */
-  rip_distance_table = route_table_init ();
+void rip_init(void)
+{
+       /* Install top nodes. */
+       install_node(&rip_node, config_write_rip);
+
+       /* Install rip commands. */
+       install_element(VIEW_NODE, &show_ip_rip_cmd);
+       install_element(VIEW_NODE, &show_ip_rip_status_cmd);
+       install_element(CONFIG_NODE, &router_rip_cmd);
+       install_element(CONFIG_NODE, &no_router_rip_cmd);
+
+       install_default(RIP_NODE);
+       install_element(RIP_NODE, &rip_version_cmd);
+       install_element(RIP_NODE, &no_rip_version_cmd);
+       install_element(RIP_NODE, &rip_default_metric_cmd);
+       install_element(RIP_NODE, &no_rip_default_metric_cmd);
+       install_element(RIP_NODE, &rip_timers_cmd);
+       install_element(RIP_NODE, &no_rip_timers_cmd);
+       install_element(RIP_NODE, &rip_route_cmd);
+       install_element(RIP_NODE, &no_rip_route_cmd);
+       install_element(RIP_NODE, &rip_distance_cmd);
+       install_element(RIP_NODE, &no_rip_distance_cmd);
+       install_element(RIP_NODE, &rip_distance_source_cmd);
+       install_element(RIP_NODE, &no_rip_distance_source_cmd);
+       install_element(RIP_NODE, &rip_distance_source_access_list_cmd);
+       install_element(RIP_NODE, &no_rip_distance_source_access_list_cmd);
+       install_element(RIP_NODE, &rip_allow_ecmp_cmd);
+       install_element(RIP_NODE, &no_rip_allow_ecmp_cmd);
+
+       /* Debug related init. */
+       rip_debug_init();
+
+       /* Access list install. */
+       access_list_init();
+       access_list_add_hook(rip_distribute_update_all_wrapper);
+       access_list_delete_hook(rip_distribute_update_all_wrapper);
+
+       /* Prefix list initialize.*/
+       prefix_list_init();
+       prefix_list_add_hook(rip_distribute_update_all);
+       prefix_list_delete_hook(rip_distribute_update_all);
+
+       /* Distribute list install. */
+       distribute_list_init(RIP_NODE);
+       distribute_list_add_hook(rip_distribute_update);
+       distribute_list_delete_hook(rip_distribute_update);
+
+       /* Route-map */
+       rip_route_map_init();
+       rip_offset_init();
+
+       route_map_add_hook(rip_routemap_update);
+       route_map_delete_hook(rip_routemap_update);
+
+       if_rmap_init(RIP_NODE);
+       if_rmap_hook_add(rip_if_rmap_update);
+       if_rmap_hook_delete(rip_if_rmap_update);
+
+       /* Distance control. */
+       rip_distance_table = route_table_init();
 }