]> git.proxmox.com Git - mirror_frr.git/blobdiff - eigrpd/eigrp_zebra.c
Merge pull request #1445 from donaldsharp/rpki_vtysh
[mirror_frr.git] / eigrpd / eigrp_zebra.c
index ba6ecf24520c225ab5eb64773880106d45275fd4..00438f2f47c0c2f7d69e19b4ac84a2b9ce75d853 100644 (file)
 #include "eigrpd/eigrp_topology.h"
 #include "eigrpd/eigrp_fsm.h"
 
-static int eigrp_interface_add (int , struct zclient *, zebra_size_t, vrf_id_t);
-static int eigrp_interface_delete (int , struct zclient *,
-                                   zebra_size_t, vrf_id_t);
-static int eigrp_interface_address_add (int, struct zclient *,
-                                        zebra_size_t, vrf_id_t vrf_id);
-static int eigrp_interface_address_delete (int, struct zclient *,
-                                           zebra_size_t, vrf_id_t vrf_id);
-static int eigrp_interface_state_up (int, struct zclient *,
-                                     zebra_size_t, vrf_id_t vrf_id);
-static int eigrp_interface_state_down (int, struct zclient *,
-                                       zebra_size_t, vrf_id_t vrf_id);
-static struct interface * zebra_interface_if_lookup (struct stream *);
-
-static int eigrp_zebra_read_ipv4 (int , struct zclient *,
-                                  zebra_size_t, vrf_id_t vrf_id);
+static int eigrp_interface_add(int, struct zclient *, zebra_size_t, vrf_id_t);
+static int eigrp_interface_delete(int, struct zclient *, zebra_size_t,
+                                 vrf_id_t);
+static int eigrp_interface_address_add(int, struct zclient *, zebra_size_t,
+                                      vrf_id_t vrf_id);
+static int eigrp_interface_address_delete(int, struct zclient *, zebra_size_t,
+                                         vrf_id_t vrf_id);
+static int eigrp_interface_state_up(int, struct zclient *, zebra_size_t,
+                                   vrf_id_t vrf_id);
+static int eigrp_interface_state_down(int, struct zclient *, zebra_size_t,
+                                     vrf_id_t vrf_id);
+static struct interface *zebra_interface_if_lookup(struct stream *);
+
+static int eigrp_zebra_read_route(int, struct zclient *, zebra_size_t,
+                                 vrf_id_t vrf_id);
 
 /* Zebra structure to hold current status. */
 struct zclient *zclient = NULL;
@@ -77,484 +77,398 @@ extern struct thread_master *master;
 struct in_addr router_id_zebra;
 
 /* Router-id update message from zebra. */
-static int
-eigrp_router_id_update_zebra (int command, struct zclient *zclient,
-                              zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_router_id_update_zebra(int command, struct zclient *zclient,
+                                       zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct eigrp *eigrp;
-  struct prefix router_id;
-  zebra_router_id_update_read (zclient->ibuf,&router_id);
+       struct eigrp *eigrp;
+       struct prefix router_id;
+       zebra_router_id_update_read(zclient->ibuf, &router_id);
 
-  router_id_zebra = router_id.u.prefix4;
+       router_id_zebra = router_id.u.prefix4;
 
-  eigrp = eigrp_lookup ();
+       eigrp = eigrp_lookup();
 
-  if (eigrp != NULL)
-    eigrp_router_id_update (eigrp);
+       if (eigrp != NULL)
+               eigrp_router_id_update(eigrp);
 
-  return 0;
+       return 0;
 }
 
-static void
-eigrp_zebra_connected (struct zclient *zclient)
+static int eigrp_zebra_notify_owner(int command, struct zclient *zclient,
+                                   zebra_size_t length, vrf_id_t vrf_id)
 {
-  zclient_send_reg_requests (zclient, VRF_DEFAULT);
+       struct prefix p;
+       enum zapi_route_notify_owner note;
+
+       if (!zapi_route_notify_decode(zclient->ibuf, &p, &note))
+               return -1;
+
+       return 0;
+}
+
+static void eigrp_zebra_connected(struct zclient *zclient)
+{
+       zclient_send_reg_requests(zclient, VRF_DEFAULT);
 }
 
-void
-eigrp_zebra_init (void)
+void eigrp_zebra_init(void)
 {
-  zclient = zclient_new (master);
-
-  zclient_init (zclient, ZEBRA_ROUTE_EIGRP, 0);
-  zclient->zebra_connected = eigrp_zebra_connected;
-  zclient->router_id_update = eigrp_router_id_update_zebra;
-  zclient->interface_add = eigrp_interface_add;
-  zclient->interface_delete = eigrp_interface_delete;
-  zclient->interface_up = eigrp_interface_state_up;
-  zclient->interface_down = eigrp_interface_state_down;
-  zclient->interface_address_add = eigrp_interface_address_add;
-  zclient->interface_address_delete = eigrp_interface_address_delete;
-  zclient->redistribute_route_ipv4_add = eigrp_zebra_read_ipv4;
-  zclient->redistribute_route_ipv4_del = eigrp_zebra_read_ipv4;
+       struct zclient_options opt = { .receive_notify = false };
+
+       zclient = zclient_new_notify(master, &opt);
+
+       zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
+       zclient->zebra_connected = eigrp_zebra_connected;
+       zclient->router_id_update = eigrp_router_id_update_zebra;
+       zclient->interface_add = eigrp_interface_add;
+       zclient->interface_delete = eigrp_interface_delete;
+       zclient->interface_up = eigrp_interface_state_up;
+       zclient->interface_down = eigrp_interface_state_down;
+       zclient->interface_address_add = eigrp_interface_address_add;
+       zclient->interface_address_delete = eigrp_interface_address_delete;
+       zclient->redistribute_route_add = eigrp_zebra_read_route;
+       zclient->redistribute_route_del = eigrp_zebra_read_route;
+       zclient->notify_owner = eigrp_zebra_notify_owner;
 }
 
 
 /* Zebra route add and delete treatment. */
-static int
-eigrp_zebra_read_ipv4 (int command, struct zclient *zclient,
-                       zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_zebra_read_route(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct stream *s;
-  struct zapi_ipv4 api;
-  struct prefix_ipv4 p;
-  struct eigrp *eigrp;
-
-  s = zclient->ibuf;
-
-  /* Type, flags, message. */
-  api.type = stream_getc (s);
-  api.instance = stream_getw (s);
-  api.flags = stream_getc (s);
-  api.message = stream_getc (s);
-
-  /* IPv4 prefix. */
-  memset (&p, 0, sizeof (struct prefix_ipv4));
-  p.family = AF_INET;
-  p.prefixlen = stream_getc (s);
-  stream_get (&p.prefix, s, PSIZE (p.prefixlen));
-
-  if (IPV4_NET127(ntohl(p.prefix.s_addr)))
-    return 0;
-
-  /* Nexthop, ifindex, distance, metric. */
-  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
-    {
-      api.nexthop_num = stream_getc (s);
-      stream_get_ipv4 (s);
-    }
-  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
-    {
-      api.ifindex_num = stream_getc (s);
-      /* XXX assert(api.ifindex_num == 1); */
-      stream_getl (s);  /* ifindex, unused */
-    }
-  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
-    api.distance = stream_getc (s);
-  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
-    api.metric = stream_getl (s);
-
-  eigrp = eigrp_lookup ();
-  if (eigrp == NULL)
-    return 0;
-
-  if (command == ZEBRA_IPV4_ROUTE_ADD)
-    {
-
-    }
-  else                          /* if (command == ZEBRA_IPV4_ROUTE_DELETE) */
-    {
-
-    }
-
-  return 0;
+       struct zapi_route api;
+       struct eigrp *eigrp;
+
+       if (zapi_route_decode(zclient->ibuf, &api) < 0)
+               return -1;
+
+       if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
+               return 0;
+
+       eigrp = eigrp_lookup();
+       if (eigrp == NULL)
+               return 0;
+
+       if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
+
+       } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
+       {
+       }
+
+       return 0;
 }
 
 /* Inteface addition message from zebra. */
-static int
-eigrp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
-                     vrf_id_t vrf_id)
+static int eigrp_interface_add(int command, struct zclient *zclient,
+                              zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
+       struct interface *ifp;
+       struct eigrp_interface *ei;
 
-  ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
+       ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
 
-  assert (ifp->info);
+       if (!ifp->info)
+               return 0;
 
-  if (!EIGRP_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), type))
-    {
-      SET_IF_PARAM (IF_DEF_PARAMS (ifp), type);
-      IF_DEF_PARAMS (ifp)->type = eigrp_default_iftype (ifp);
-    }
+       ei = ifp->info;
 
-  eigrp_if_update (ifp);
+       ei->params.type = eigrp_default_iftype(ifp);
 
-  return 0;
+       eigrp_if_update(ifp);
+
+       return 0;
 }
 
-static int
-eigrp_interface_delete (int command, struct zclient *zclient,
-                        zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_interface_delete(int command, struct zclient *zclient,
+                                 zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-  struct stream *s;
-  struct route_node *rn;
+       struct interface *ifp;
+       struct stream *s;
 
-  s = zclient->ibuf;
-  /* zebra_interface_state_read () updates interface structure in iflist */
-  ifp = zebra_interface_state_read (s, vrf_id);
+       s = zclient->ibuf;
+       /* zebra_interface_state_read () updates interface structure in iflist
+        */
+       ifp = zebra_interface_state_read(s, vrf_id);
 
-  if (ifp == NULL)
-    return 0;
+       if (ifp == NULL)
+               return 0;
 
-  if (if_is_up (ifp))
-    zlog_warn ("Zebra: got delete of %s, but interface is still up",
-               ifp->name);
+       if (if_is_up(ifp))
+               zlog_warn("Zebra: got delete of %s, but interface is still up",
+                         ifp->name);
 
-  if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-    zlog_debug("Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
-               ifp->name, ifp->ifindex, (unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+               zlog_debug(
+                       "Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
+                       ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
+                       ifp->metric, ifp->mtu);
 
-  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
-    if (rn->info)
-      eigrp_if_free ((struct eigrp_interface *) rn->info, INTERFACE_DOWN_BY_ZEBRA);
+       if (ifp->info)
+               eigrp_if_free(ifp->info,
+                             INTERFACE_DOWN_BY_ZEBRA);
 
-  ifp->ifindex = IFINDEX_INTERNAL;
-  return 0;
+       if_set_index(ifp, IFINDEX_INTERNAL);
+       return 0;
 }
 
-static int
-eigrp_interface_address_add (int command, struct zclient *zclient,
-                             zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_interface_address_add(int command, struct zclient *zclient,
+                                      zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct connected *c;
+       struct connected *c;
 
-  c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
+       c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
 
-  if (c == NULL)
-    return 0;
+       if (c == NULL)
+               return 0;
 
-  if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-    {
-      char buf[128];
-      prefix2str (c->address, buf, sizeof (buf));
-      zlog_debug ("Zebra: interface %s address add %s", c->ifp->name, buf);
-    }
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) {
+               char buf[128];
+               prefix2str(c->address, buf, sizeof(buf));
+               zlog_debug("Zebra: interface %s address add %s", c->ifp->name,
+                          buf);
+       }
 
-  eigrp_if_update (c->ifp);
+       eigrp_if_update(c->ifp);
 
-  return 0;
+       return 0;
 }
 
-static int
-eigrp_interface_address_delete (int command, struct zclient *zclient,
-                                zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_interface_address_delete(int command, struct zclient *zclient,
+                                         zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct connected *c;
-  struct interface *ifp;
-  struct eigrp_interface *ei;
-  struct route_node *rn;
-  struct prefix p;
-
-  c = zebra_interface_address_read (command, zclient->ibuf, vrf_id);
-
-  if (c == NULL)
-    return 0;
+       struct connected *c;
+       struct interface *ifp;
+       struct eigrp_interface *ei;
 
-  if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-    {
-      char buf[128];
-      prefix2str (c->address, buf, sizeof (buf));
-      zlog_debug ("Zebra: interface %s address delete %s", c->ifp->name, buf);
-    }
+       c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
 
-  ifp = c->ifp;
-  p = *c->address;
-  p.prefixlen = IPV4_MAX_PREFIXLEN;
+       if (c == NULL)
+               return 0;
 
-  rn = route_node_lookup (IF_OIFS (ifp), &p);
-  if (!rn)
-    {
-      connected_free (c);
-      return 0;
-    }
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) {
+               char buf[128];
+               prefix2str(c->address, buf, sizeof(buf));
+               zlog_debug("Zebra: interface %s address delete %s",
+                          c->ifp->name, buf);
+       }
 
-  assert (rn->info);
-  ei = rn->info;
+       ifp = c->ifp;
+       ei = ifp->info;
+       if (!ei)
+               return 0;
 
-  /* Call interface hook functions to clean up */
-  eigrp_if_free (ei, INTERFACE_DOWN_BY_ZEBRA);
+       /* Call interface hook functions to clean up */
+       eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA);
 
-  connected_free (c);
+       connected_free(c);
 
-  return 0;
+       return 0;
 }
 
-static int
-eigrp_interface_state_up (int command, struct zclient *zclient,
-                          zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_interface_state_up(int command, struct zclient *zclient,
+                                   zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-  struct eigrp_interface *ei;
-  struct route_node *rn;
+       struct interface *ifp;
 
-  ifp = zebra_interface_if_lookup (zclient->ibuf);
+       ifp = zebra_interface_if_lookup(zclient->ibuf);
 
-  if (ifp == NULL)
-    return 0;
+       if (ifp == NULL)
+               return 0;
 
-  /* Interface is already up. */
-  if (if_is_operative (ifp))
-    {
-      /* Temporarily keep ifp values. */
-      struct interface if_tmp;
-      memcpy (&if_tmp, ifp, sizeof (struct interface));
+       /* Interface is already up. */
+       if (if_is_operative(ifp)) {
+               /* Temporarily keep ifp values. */
+               struct interface if_tmp;
+               memcpy(&if_tmp, ifp, sizeof(struct interface));
 
-      zebra_interface_if_set_value (zclient->ibuf, ifp);
+               zebra_interface_if_set_value(zclient->ibuf, ifp);
 
-      if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-        zlog_debug ("Zebra: Interface[%s] state update.", ifp->name);
+               if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+                       zlog_debug("Zebra: Interface[%s] state update.",
+                                  ifp->name);
 
-      if (if_tmp.bandwidth != ifp->bandwidth)
-        {
-          if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-            zlog_debug ("Zebra: Interface[%s] bandwidth change %d -> %d.",
-                        ifp->name, if_tmp.bandwidth, ifp->bandwidth);
+               if (if_tmp.bandwidth != ifp->bandwidth) {
+                       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+                               zlog_debug(
+                                       "Zebra: Interface[%s] bandwidth change %d -> %d.",
+                                       ifp->name, if_tmp.bandwidth,
+                                       ifp->bandwidth);
 
-          //          eigrp_if_recalculate_output_cost (ifp);
-        }
+                       //          eigrp_if_recalculate_output_cost (ifp);
+               }
 
-      if (if_tmp.mtu != ifp->mtu)
-        {
-          if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-            zlog_debug ("Zebra: Interface[%s] MTU change %u -> %u.",
-                        ifp->name, if_tmp.mtu, ifp->mtu);
+               if (if_tmp.mtu != ifp->mtu) {
+                       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+                               zlog_debug(
+                                       "Zebra: Interface[%s] MTU change %u -> %u.",
+                                       ifp->name, if_tmp.mtu, ifp->mtu);
 
-          /* Must reset the interface (simulate down/up) when MTU changes. */
-          eigrp_if_reset (ifp);
-        }
-      return 0;
-    }
+                       /* Must reset the interface (simulate down/up) when MTU
+                        * changes. */
+                       eigrp_if_reset(ifp);
+               }
+               return 0;
+       }
 
-  zebra_interface_if_set_value (zclient->ibuf, ifp);
+       zebra_interface_if_set_value(zclient->ibuf, ifp);
 
-  if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-    zlog_debug ("Zebra: Interface[%s] state change to up.", ifp->name);
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+               zlog_debug("Zebra: Interface[%s] state change to up.",
+                          ifp->name);
 
-  for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
-    {
-      if ((ei = rn->info) == NULL)
-        continue;
+       if (ifp->info)
+               eigrp_if_up(ifp->info);
 
-      eigrp_if_up (ei);
-    }
-
-  return 0;
+       return 0;
 }
 
-static int
-eigrp_interface_state_down (int command, struct zclient *zclient,
-                            zebra_size_t length, vrf_id_t vrf_id)
+static int eigrp_interface_state_down(int command, struct zclient *zclient,
+                                     zebra_size_t length, vrf_id_t vrf_id)
 {
-  struct interface *ifp;
-  struct eigrp_interface *ei;
-  struct route_node *node;
+       struct interface *ifp;
 
-  ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
+       ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
 
-  if (ifp == NULL)
-    return 0;
+       if (ifp == NULL)
+               return 0;
 
-  if (IS_DEBUG_EIGRP (zebra, ZEBRA_INTERFACE))
-    zlog_debug ("Zebra: Interface[%s] state change to down.", ifp->name);
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
+               zlog_debug("Zebra: Interface[%s] state change to down.",
+                          ifp->name);
 
-  for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node))
-    {
-      if ((ei = node->info) == NULL)
-        continue;
-      eigrp_if_down (ei);
-    }
+       if (ifp->info)
+               eigrp_if_down(ifp->info);
 
-  return 0;
+       return 0;
 }
 
-static struct interface *
-zebra_interface_if_lookup (struct stream *s)
+static struct interface *zebra_interface_if_lookup(struct stream *s)
 {
-  char ifname_tmp[INTERFACE_NAMSIZ];
+       char ifname_tmp[INTERFACE_NAMSIZ];
 
-  /* Read interface name. */
-  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
+       /* Read interface name. */
+       stream_get(ifname_tmp, s, INTERFACE_NAMSIZ);
 
-  /* And look it up. */
-  return if_lookup_by_name_len (ifname_tmp,
-                                strnlen (ifname_tmp, INTERFACE_NAMSIZ),
-                                VRF_DEFAULT);
+       /* And look it up. */
+       return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
 }
 
-void
-eigrp_zebra_route_add (struct prefix_ipv4 *p, struct list *successors)
+void eigrp_zebra_route_add(struct prefix *p, struct list *successors)
 {
-  struct eigrp_neighbor_entry *te;
-  struct listnode *node;
-  u_char message;
-  u_char flags;
-  int psize;
-  struct stream *s;
-
-  if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
-    {
-      message = 0;
-      flags = 0;
-
-      /* EIGRP pass nexthop and metric */
-      SET_FLAG (message, ZAPI_MESSAGE_NEXTHOP);
-
-      /* Make packet. */
-      s = zclient->obuf;
-      stream_reset (s);
-
-      /* Put command, type, flags, message. */
-      zclient_create_header (s, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
-      stream_putc (s, ZEBRA_ROUTE_EIGRP);
-      stream_putw (s, 0);
-      stream_putl (s, flags);
-      stream_putc (s, message);
-      stream_putw (s, SAFI_UNICAST);
-
-      /* Put prefix information. */
-      psize = PSIZE (p->prefixlen);
-      stream_putc (s, p->prefixlen);
-      stream_write (s, (u_char *) & p->prefix, psize);
-
-      /* Nexthop count. */
-      stream_putc (s, successors->count);
-
-      /* Nexthop, ifindex, distance and metric information. */
-      for (ALL_LIST_ELEMENTS_RO (successors, node, te))
-        {
-          if (te->adv_router->src.s_addr)
-            {
-              stream_putc (s, NEXTHOP_TYPE_IPV4_IFINDEX);
-              stream_put_in_addr (s, &te->adv_router->src);
-            }
-          else
-            stream_putc (s, NEXTHOP_TYPE_IFINDEX);
-          stream_putl (s, te->ei->ifp->ifindex);
-        }
-
-      if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
-        {
-          char buf[2][INET_ADDRSTRLEN];
-          zlog_debug ("Zebra: Route add %s/%d nexthop %s",
-                      inet_ntop(AF_INET, &p->prefix, buf[0], sizeof (buf[0])),
-                      p->prefixlen,
-                      inet_ntop(AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1])));
-        }
-
-      stream_putw_at (s, 0, stream_get_endp (s));
-
-      zclient_send_message (zclient);
-    }
+       struct zapi_route api;
+       struct zapi_nexthop *api_nh;
+       struct eigrp_nexthop_entry *te;
+       struct listnode *node;
+       int count = 0;
+
+       if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
+               return;
+
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_EIGRP;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
+
+       SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
+
+       /* Nexthop, ifindex, distance and metric information. */
+       for (ALL_LIST_ELEMENTS_RO(successors, node, te)) {
+               if (count >= MULTIPATH_NUM)
+                       break;
+               api_nh = &api.nexthops[count];
+               if (te->adv_router->src.s_addr) {
+                       api_nh->gate.ipv4 = te->adv_router->src;
+                       api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+               } else
+                       api_nh->type = NEXTHOP_TYPE_IFINDEX;
+               api_nh->ifindex = te->ei->ifp->ifindex;
+
+               count++;
+       }
+       api.nexthop_num = count;
+
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
+               char buf[2][PREFIX_STRLEN];
+               zlog_debug("Zebra: Route add %s nexthop %s",
+                          prefix2str(p, buf[0], PREFIX_STRLEN),
+                          inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN));
+       }
+
+       zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
 }
 
-void
-eigrp_zebra_route_delete (struct prefix_ipv4 *p)
+void eigrp_zebra_route_delete(struct prefix *p)
 {
-  struct zapi_ipv4 api;
-
-  if (zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
-    {
-      api.vrf_id = VRF_DEFAULT;
-      api.type = ZEBRA_ROUTE_EIGRP;
-      api.instance = 0;
-      api.flags = 0;
-      api.message = 0;
-      api.safi = SAFI_UNICAST;
-      zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, p, &api);
-
-      if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
-        {
-          char buf[2][INET_ADDRSTRLEN];
-          zlog_debug ("Zebra: Route del %s/%d nexthop %s",
-                      inet_ntop (AF_INET, &p->prefix,  buf[0], sizeof (buf[0])),
-                      p->prefixlen,
-                      inet_ntop (AF_INET, 0 /*&p->nexthop*/, buf[1], sizeof (buf[1])));
-        }
-    }
-
-  return;
+       struct zapi_route api;
+
+       if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP])
+               return;
+
+       memset(&api, 0, sizeof(api));
+       api.vrf_id = VRF_DEFAULT;
+       api.type = ZEBRA_ROUTE_EIGRP;
+       api.safi = SAFI_UNICAST;
+       memcpy(&api.prefix, p, sizeof(*p));
+       zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+
+       if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
+               char buf[PREFIX_STRLEN];
+               zlog_debug("Zebra: Route del %s",
+                          prefix2str(p, buf, PREFIX_STRLEN));
+       }
+
+       return;
 }
 
-vrf_bitmap_t
-eigrp_is_type_redistributed (int type)
+int eigrp_is_type_redistributed(int type)
 {
-  return (DEFAULT_ROUTE_TYPE (type)) ?
-    zclient->default_information : zclient->redist[AFI_IP][type];
+       return ((DEFAULT_ROUTE_TYPE(type))
+                       ? vrf_bitmap_check(zclient->default_information,
+                                          VRF_DEFAULT)
+                       : vrf_bitmap_check(zclient->redist[AFI_IP][type],
+                                          VRF_DEFAULT));
 }
 
-int
-eigrp_redistribute_set (struct eigrp *eigrp, int type, struct eigrp_metrics metric)
+int eigrp_redistribute_set(struct eigrp *eigrp, int type,
+                          struct eigrp_metrics metric)
 {
 
-  if (eigrp_is_type_redistributed (type))
-    {
-      if (eigrp_metrics_is_same(&metric, &eigrp->dmetric[type]))
-        {
-          eigrp->dmetric[type] = metric;
-        }
-
-      eigrp_external_routes_refresh (eigrp, type);
+       if (eigrp_is_type_redistributed(type)) {
+               if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) {
+                       eigrp->dmetric[type] = metric;
+               }
 
-      //      if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE))
-      //        zlog_debug ("Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
-      //                   eigrp_redist_string(type),
-      //                   metric_type (eigrp, type), metric_value (eigrp, type));
-      return CMD_SUCCESS;
-    }
+               eigrp_external_routes_refresh(eigrp, type);
 
-  eigrp->dmetric[type] = metric;
+               //      if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE))
+               //        zlog_debug ("Redistribute[%s]: Refresh  Type[%d],
+               //        Metric[%d]",
+               //                   eigrp_redist_string(type),
+               //                   metric_type (eigrp, type), metric_value
+               //                   (eigrp, type));
+               return CMD_SUCCESS;
+       }
 
-  zclient_redistribute (ZEBRA_REDISTRIBUTE_ADD, zclient,
-                        AFI_IP, type, 0, VRF_DEFAULT);
+       eigrp->dmetric[type] = metric;
 
-  //  if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
-  //    zlog_debug ("Redistribute[%s]: Start  Type[%d], Metric[%d]",
-  //               ospf_redist_string(type),
-  //               metric_type (ospf, type), metric_value (ospf, type));
+       zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0,
+                            VRF_DEFAULT);
 
-  ++eigrp->redistribute;
+       ++eigrp->redistribute;
 
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
 
-int
-eigrp_redistribute_unset (struct eigrp *eigrp, int type)
+int eigrp_redistribute_unset(struct eigrp *eigrp, int type)
 {
 
-  if (eigrp_is_type_redistributed (type))
-    {
-      memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics));
-      zclient_redistribute (ZEBRA_REDISTRIBUTE_DELETE, zclient,
-                            AFI_IP, type, 0, VRF_DEFAULT);
-      --eigrp->redistribute;
-    }
+       if (eigrp_is_type_redistributed(type)) {
+               memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics));
+               zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP,
+                                    type, 0, VRF_DEFAULT);
+               --eigrp->redistribute;
+       }
 
-  //  if (IS_DEBUG_EIGRP (zebra, ZEBRA_REDISTRIBUTE))
-  //    zlog_debug ("Redistribute[%s]: Start  Type[%d], Metric[%d]",
-  //               ospf_redist_string(type),
-  //               metric_type (ospf, type), metric_value (ospf, type));
-
-  return CMD_SUCCESS;
+       return CMD_SUCCESS;
 }
-