back to topotato report
topotato coverage report
Current view: top level - ripd - rip_interface.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 398 535 74.4 %
Date: 2023-02-24 14:41:08 Functions: 45 55 81.8 %

          Line data    Source code
       1             : /* Interface related function for RIP.
       2             :  * Copyright (C) 1997, 98 Kunihiro Ishiguro <kunihiro@zebra.org>
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "command.h"
      24             : #include "if.h"
      25             : #include "sockunion.h"
      26             : #include "prefix.h"
      27             : #include "memory.h"
      28             : #include "network.h"
      29             : #include "table.h"
      30             : #include "log.h"
      31             : #include "stream.h"
      32             : #include "thread.h"
      33             : #include "zclient.h"
      34             : #include "filter.h"
      35             : #include "sockopt.h"
      36             : #include "privs.h"
      37             : #include "lib_errors.h"
      38             : #include "northbound_cli.h"
      39             : 
      40             : #include "zebra/connected.h"
      41             : 
      42             : #include "ripd/ripd.h"
      43             : #include "ripd/rip_debug.h"
      44             : #include "ripd/rip_interface.h"
      45             : 
      46          15 : DEFINE_MTYPE_STATIC(RIPD, RIP_INTERFACE, "RIP interface");
      47          15 : DEFINE_MTYPE(RIPD, RIP_INTERFACE_STRING, "RIP Interface String");
      48          46 : DEFINE_HOOK(rip_ifaddr_add, (struct connected * ifc), (ifc));
      49          10 : DEFINE_HOOK(rip_ifaddr_del, (struct connected * ifc), (ifc));
      50             : 
      51             : /* static prototypes */
      52             : static void rip_enable_apply(struct interface *);
      53             : static void rip_passive_interface_apply(struct interface *);
      54             : static int rip_if_down(struct interface *ifp);
      55             : static int rip_enable_if_lookup(struct rip *rip, const char *ifname);
      56             : static int rip_enable_network_lookup2(struct connected *connected);
      57             : static void rip_enable_apply_all(struct rip *rip);
      58             : 
      59             : const struct message ri_version_msg[] = {{RI_RIP_VERSION_1, "1"},
      60             :                                          {RI_RIP_VERSION_2, "2"},
      61             :                                          {RI_RIP_VERSION_1_AND_2, "1 2"},
      62             :                                          {RI_RIP_VERSION_NONE, "none"},
      63             :                                          {0}};
      64             : 
      65             : /* Join to the RIP version 2 multicast group. */
      66           7 : static int ipv4_multicast_join(int sock, struct in_addr group,
      67             :                                struct in_addr ifa, ifindex_t ifindex)
      68             : {
      69           7 :         int ret;
      70             : 
      71           7 :         ret = setsockopt_ipv4_multicast(sock, IP_ADD_MEMBERSHIP, ifa,
      72             :                                         group.s_addr, ifindex);
      73             : 
      74           7 :         if (ret < 0)
      75           0 :                 zlog_info("can't setsockopt IP_ADD_MEMBERSHIP %s",
      76             :                           safe_strerror(errno));
      77             : 
      78           7 :         return ret;
      79             : }
      80             : 
      81             : /* Leave from the RIP version 2 multicast group. */
      82           0 : static int ipv4_multicast_leave(int sock, struct in_addr group,
      83             :                                 struct in_addr ifa, ifindex_t ifindex)
      84             : {
      85           0 :         int ret;
      86             : 
      87           0 :         ret = setsockopt_ipv4_multicast(sock, IP_DROP_MEMBERSHIP, ifa,
      88             :                                         group.s_addr, ifindex);
      89             : 
      90           0 :         if (ret < 0)
      91           0 :                 zlog_info("can't setsockopt IP_DROP_MEMBERSHIP");
      92             : 
      93           0 :         return ret;
      94             : }
      95             : 
      96             : static void rip_interface_reset(struct rip_interface *);
      97             : 
      98             : /* Allocate new RIP's interface configuration. */
      99          22 : static struct rip_interface *rip_interface_new(void)
     100             : {
     101          22 :         struct rip_interface *ri;
     102             : 
     103          22 :         ri = XCALLOC(MTYPE_RIP_INTERFACE, sizeof(struct rip_interface));
     104             : 
     105          22 :         rip_interface_reset(ri);
     106             : 
     107          22 :         return ri;
     108             : }
     109             : 
     110          16 : void rip_interface_multicast_set(int sock, struct connected *connected)
     111             : {
     112          16 :         struct in_addr addr;
     113             : 
     114          16 :         assert(connected != NULL);
     115             : 
     116          16 :         addr = CONNECTED_ID(connected)->u.prefix4;
     117             : 
     118          16 :         if (setsockopt_ipv4_multicast_if(sock, addr, connected->ifp->ifindex)
     119             :             < 0) {
     120           0 :                 zlog_warn(
     121             :                         "Can't setsockopt IP_MULTICAST_IF on fd %d to ifindex %d for interface %s",
     122             :                         sock, connected->ifp->ifindex, connected->ifp->name);
     123             :         }
     124             : 
     125          16 :         return;
     126             : }
     127             : 
     128             : /* Send RIP request packet to specified interface. */
     129           7 : static void rip_request_interface_send(struct interface *ifp, uint8_t version)
     130             : {
     131           7 :         struct sockaddr_in to;
     132             : 
     133             :         /* RIPv2 support multicast. */
     134           7 :         if (version == RIPv2 && if_is_multicast(ifp)) {
     135             : 
     136           7 :                 if (IS_RIP_DEBUG_EVENT)
     137           1 :                         zlog_debug("multicast request on %s", ifp->name);
     138             : 
     139           7 :                 rip_request_send(NULL, ifp, version, NULL);
     140           7 :                 return;
     141             :         }
     142             : 
     143             :         /* RIPv1 and non multicast interface. */
     144           0 :         if (if_is_pointopoint(ifp) || if_is_broadcast(ifp)) {
     145           0 :                 struct listnode *cnode, *cnnode;
     146           0 :                 struct connected *connected;
     147             : 
     148           0 :                 if (IS_RIP_DEBUG_EVENT)
     149           0 :                         zlog_debug("broadcast request to %s", ifp->name);
     150             : 
     151           0 :                 for (ALL_LIST_ELEMENTS(ifp->connected, cnode, cnnode,
     152             :                                        connected)) {
     153           0 :                         if (connected->address->family != AF_INET)
     154           0 :                                 continue;
     155             : 
     156           0 :                         memset(&to, 0, sizeof(struct sockaddr_in));
     157           0 :                         to.sin_port = htons(RIP_PORT_DEFAULT);
     158           0 :                         if (connected->destination)
     159             :                                 /* use specified broadcast or peer
     160             :                                  * destination addr */
     161           0 :                                 to.sin_addr = connected->destination->u.prefix4;
     162           0 :                         else if (connected->address->prefixlen
     163             :                                  < IPV4_MAX_BITLEN)
     164             :                                 /* calculate the appropriate broadcast
     165             :                                  * address */
     166           0 :                                 to.sin_addr.s_addr = ipv4_broadcast_addr(
     167             :                                         connected->address->u.prefix4.s_addr,
     168             :                                         connected->address->prefixlen);
     169             :                         else
     170             :                                 /* do not know where to send the packet
     171             :                                  */
     172           0 :                                 continue;
     173             : 
     174           0 :                         if (IS_RIP_DEBUG_EVENT)
     175           0 :                                 zlog_debug("SEND request to %pI4",
     176             :                                            &to.sin_addr);
     177             : 
     178           0 :                         rip_request_send(&to, ifp, version, connected);
     179             :                 }
     180             :         }
     181             : }
     182             : 
     183             : /* This will be executed when interface goes up. */
     184           7 : static void rip_request_interface(struct interface *ifp)
     185             : {
     186           7 :         struct rip_interface *ri;
     187           7 :         int vsend;
     188             : 
     189             :         /* In default ripd doesn't send RIP_REQUEST to the loopback interface.
     190             :          */
     191           7 :         if (if_is_loopback(ifp))
     192             :                 return;
     193             : 
     194             :         /* If interface is down, don't send RIP packet. */
     195           7 :         if (!if_is_operative(ifp))
     196             :                 return;
     197             : 
     198             :         /* Fetch RIP interface information. */
     199           7 :         ri = ifp->info;
     200             : 
     201             :         /* If there is no version configuration in the interface,
     202             :            use rip's version setting. */
     203          21 :         vsend = ((ri->ri_send == RI_RIP_UNSPEC) ? ri->rip->version_send
     204           7 :                                                 : ri->ri_send);
     205           7 :         if (vsend & RIPv1)
     206           0 :                 rip_request_interface_send(ifp, RIPv1);
     207           7 :         if (vsend & RIPv2)
     208           7 :                 rip_request_interface_send(ifp, RIPv2);
     209             : }
     210             : 
     211             : /* Multicast packet receive socket. */
     212           7 : static int rip_multicast_join(struct interface *ifp, int sock)
     213             : {
     214           7 :         struct listnode *cnode;
     215           7 :         struct connected *ifc;
     216             : 
     217           7 :         if (if_is_operative(ifp) && if_is_multicast(ifp)) {
     218           7 :                 if (IS_RIP_DEBUG_EVENT)
     219           1 :                         zlog_debug("multicast join at %s", ifp->name);
     220             : 
     221          14 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) {
     222           7 :                         struct prefix_ipv4 *p;
     223           7 :                         struct in_addr group;
     224             : 
     225           7 :                         p = (struct prefix_ipv4 *)ifc->address;
     226             : 
     227           7 :                         if (p->family != AF_INET)
     228           0 :                                 continue;
     229             : 
     230           7 :                         group.s_addr = htonl(INADDR_RIP_GROUP);
     231           7 :                         if (ipv4_multicast_join(sock, group, p->prefix,
     232             :                                                 ifp->ifindex)
     233             :                             < 0)
     234           7 :                                 return -1;
     235             :                         else
     236           7 :                                 return 0;
     237             :                 }
     238             :         }
     239             :         return 0;
     240             : }
     241             : 
     242             : /* Leave from multicast group. */
     243           0 : static void rip_multicast_leave(struct interface *ifp, int sock)
     244             : {
     245           0 :         struct listnode *cnode;
     246           0 :         struct connected *connected;
     247             : 
     248           0 :         if (if_is_up(ifp) && if_is_multicast(ifp)) {
     249           0 :                 if (IS_RIP_DEBUG_EVENT)
     250           0 :                         zlog_debug("multicast leave from %s", ifp->name);
     251             : 
     252           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
     253           0 :                         struct prefix_ipv4 *p;
     254           0 :                         struct in_addr group;
     255             : 
     256           0 :                         p = (struct prefix_ipv4 *)connected->address;
     257             : 
     258           0 :                         if (p->family != AF_INET)
     259           0 :                                 continue;
     260             : 
     261           0 :                         group.s_addr = htonl(INADDR_RIP_GROUP);
     262           0 :                         if (ipv4_multicast_leave(sock, group, p->prefix,
     263             :                                                  ifp->ifindex)
     264             :                             == 0)
     265           0 :                                 return;
     266             :                 }
     267             :         }
     268             : }
     269             : 
     270             : /* Is there and address on interface that I could use ? */
     271         114 : static int rip_if_ipv4_address_check(struct interface *ifp)
     272             : {
     273         114 :         struct listnode *nn;
     274         114 :         struct connected *connected;
     275         114 :         int count = 0;
     276             : 
     277         312 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, nn, connected)) {
     278          84 :                 struct prefix *p;
     279             : 
     280          84 :                 p = connected->address;
     281             : 
     282          84 :                 if (p->family == AF_INET)
     283          78 :                         count++;
     284             :         }
     285             : 
     286         114 :         return count;
     287             : }
     288             : 
     289             : 
     290             : /* Does this address belongs to me ? */
     291          11 : int if_check_address(struct rip *rip, struct in_addr addr)
     292             : {
     293          11 :         struct interface *ifp;
     294             : 
     295          61 :         FOR_ALL_INTERFACES (rip->vrf, ifp) {
     296          39 :                 struct listnode *cnode;
     297          39 :                 struct connected *connected;
     298             : 
     299         134 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, connected)) {
     300          56 :                         struct prefix_ipv4 *p;
     301             : 
     302          56 :                         p = (struct prefix_ipv4 *)connected->address;
     303             : 
     304          56 :                         if (p->family != AF_INET)
     305          28 :                                 continue;
     306             : 
     307          28 :                         if (IPV4_ADDR_CMP(&p->prefix, &addr) == 0)
     308             :                                 return 1;
     309             :                 }
     310             :         }
     311             :         return 0;
     312             : }
     313             : 
     314             : /* Interface link down message processing. */
     315          10 : static int rip_ifp_down(struct interface *ifp)
     316             : {
     317          20 :         rip_interface_sync(ifp);
     318          10 :         rip_if_down(ifp);
     319             : 
     320          10 :         if (IS_RIP_DEBUG_ZEBRA)
     321           0 :                 zlog_debug(
     322             :                         "interface %s vrf %s(%u) index %d flags %llx metric %d mtu %d is down",
     323             :                         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     324             :                         ifp->ifindex, (unsigned long long)ifp->flags,
     325             :                         ifp->metric, ifp->mtu);
     326             : 
     327          10 :         return 0;
     328             : }
     329             : 
     330             : /* Interface link up message processing */
     331          24 : static int rip_ifp_up(struct interface *ifp)
     332             : {
     333          24 :         if (IS_RIP_DEBUG_ZEBRA)
     334          14 :                 zlog_debug(
     335             :                         "interface %s vrf %s(%u) index %d flags %#llx metric %d mtu %d is up",
     336             :                         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     337             :                         ifp->ifindex, (unsigned long long)ifp->flags,
     338             :                         ifp->metric, ifp->mtu);
     339             : 
     340          48 :         rip_interface_sync(ifp);
     341             : 
     342             :         /* Check if this interface is RIP enabled or not.*/
     343          24 :         rip_enable_apply(ifp);
     344             : 
     345             :         /* Check for a passive interface */
     346          24 :         rip_passive_interface_apply(ifp);
     347             : 
     348             :         /* Apply distribute list to the all interface. */
     349          24 :         rip_distribute_update_interface(ifp);
     350             : 
     351          24 :         return 0;
     352             : }
     353             : 
     354             : /* Interface addition message from zebra. */
     355          44 : static int rip_ifp_create(struct interface *ifp)
     356             : {
     357          88 :         rip_interface_sync(ifp);
     358             : 
     359          44 :         if (IS_RIP_DEBUG_ZEBRA)
     360          16 :                 zlog_debug(
     361             :                         "interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
     362             :                         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     363             :                         ifp->ifindex, (unsigned long long)ifp->flags,
     364             :                         ifp->metric, ifp->mtu);
     365             : 
     366             :         /* Check if this interface is RIP enabled or not.*/
     367          44 :         rip_enable_apply(ifp);
     368             : 
     369             :         /* Check for a passive interface */
     370          44 :         rip_passive_interface_apply(ifp);
     371             : 
     372             :         /* Apply distribute list to the all interface. */
     373          44 :         rip_distribute_update_interface(ifp);
     374             : 
     375             :         /* rip_request_neighbor_all (); */
     376             : 
     377             :         /* Check interface routemap. */
     378          44 :         rip_if_rmap_update_interface(ifp);
     379             : 
     380          44 :         return 0;
     381             : }
     382             : 
     383           0 : static int rip_ifp_destroy(struct interface *ifp)
     384             : {
     385           0 :         rip_interface_sync(ifp);
     386           0 :         if (if_is_up(ifp)) {
     387           0 :                 rip_if_down(ifp);
     388             :         }
     389             : 
     390           0 :         if (IS_RIP_DEBUG_ZEBRA)
     391           0 :                 zlog_debug(
     392             :                         "interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
     393             :                         ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
     394             :                         ifp->ifindex, (unsigned long long)ifp->flags,
     395             :                         ifp->metric, ifp->mtu);
     396             : 
     397           0 :         return 0;
     398             : }
     399             : 
     400             : /* VRF update for an interface. */
     401           0 : int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
     402             : {
     403           0 :         struct interface *ifp;
     404           0 :         vrf_id_t new_vrf_id;
     405             : 
     406           0 :         ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
     407             :                                               &new_vrf_id);
     408           0 :         if (!ifp)
     409             :                 return 0;
     410             : 
     411           0 :         if (IS_RIP_DEBUG_ZEBRA) {
     412           0 :                 struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
     413             : 
     414           0 :                 zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
     415             :                            ifp->name, ifp->vrf->name, vrf_id, VRF_LOGNAME(nvrf),
     416             :                            new_vrf_id);
     417             :         }
     418             : 
     419           0 :         if_update_to_new_vrf(ifp, new_vrf_id);
     420           0 :         rip_interface_sync(ifp);
     421             : 
     422             :         return 0;
     423             : }
     424             : 
     425          44 : static void rip_interface_clean(struct rip_interface *ri)
     426             : {
     427          44 :         ri->enable_network = 0;
     428          44 :         ri->enable_interface = 0;
     429          44 :         ri->running = 0;
     430             : 
     431          44 :         THREAD_OFF(ri->t_wakeup);
     432          44 : }
     433             : 
     434           5 : void rip_interfaces_clean(struct rip *rip)
     435             : {
     436           5 :         struct interface *ifp;
     437             : 
     438           5 :         FOR_ALL_INTERFACES (rip->vrf, ifp)
     439           0 :                 rip_interface_clean(ifp->info);
     440           5 : }
     441             : 
     442          44 : static void rip_interface_reset(struct rip_interface *ri)
     443             : {
     444          44 :         ri->auth_type = yang_get_default_enum("%s/authentication-scheme/mode",
     445             :                                               RIP_IFACE);
     446          44 :         ri->md5_auth_len = yang_get_default_enum(
     447             :                 "%s/authentication-scheme/md5-auth-length", RIP_IFACE);
     448             : 
     449             :         /* Set default split-horizon behavior.  If the interface is Frame
     450             :            Relay or SMDS is enabled, the default value for split-horizon is
     451             :            off.  But currently Zebra does detect Frame Relay or SMDS
     452             :            interface.  So all interface is set to split horizon.  */
     453          88 :         ri->split_horizon =
     454          44 :                 yang_get_default_enum("%s/split-horizon", RIP_IFACE);
     455             : 
     456          44 :         ri->ri_send = yang_get_default_enum("%s/version-send", RIP_IFACE);
     457          44 :         ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
     458          44 :         ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
     459             : 
     460          44 :         XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
     461             : 
     462          44 :         XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
     463             : 
     464          44 :         ri->list[RIP_FILTER_IN] = NULL;
     465          44 :         ri->list[RIP_FILTER_OUT] = NULL;
     466             : 
     467          44 :         ri->prefix[RIP_FILTER_IN] = NULL;
     468          44 :         ri->prefix[RIP_FILTER_OUT] = NULL;
     469             : 
     470          44 :         ri->recv_badpackets = 0;
     471          44 :         ri->recv_badroutes = 0;
     472          44 :         ri->sent_updates = 0;
     473             : 
     474          44 :         ri->passive = 0;
     475             : 
     476          44 :         rip_interface_clean(ri);
     477          44 : }
     478             : 
     479          10 : int rip_if_down(struct interface *ifp)
     480             : {
     481          10 :         struct rip *rip;
     482          10 :         struct route_node *rp;
     483          10 :         struct rip_info *rinfo;
     484          10 :         struct rip_interface *ri = NULL;
     485          10 :         struct list *list = NULL;
     486          10 :         struct listnode *listnode = NULL, *nextnode = NULL;
     487             : 
     488          10 :         ri = ifp->info;
     489             : 
     490          10 :         THREAD_OFF(ri->t_wakeup);
     491             : 
     492          10 :         rip = ri->rip;
     493          10 :         if (rip) {
     494          46 :                 for (rp = route_top(rip->table); rp; rp = route_next(rp))
     495          36 :                         if ((list = rp->info) != NULL)
     496          44 :                                 for (ALL_LIST_ELEMENTS(list, listnode, nextnode,
     497             :                                                        rinfo))
     498          22 :                                         if (rinfo->nh.ifindex == ifp->ifindex)
     499           8 :                                                 rip_ecmp_delete(rip, rinfo);
     500             : 
     501          10 :                 if (ri->running) {
     502           0 :                         if (IS_RIP_DEBUG_EVENT)
     503           0 :                                 zlog_debug("turn off %s", ifp->name);
     504             : 
     505             :                         /* Leave from multicast group. */
     506           0 :                         rip_multicast_leave(ifp, rip->sock);
     507             : 
     508           0 :                         ri->running = 0;
     509             :                 }
     510             :         }
     511             : 
     512          10 :         return 0;
     513             : }
     514             : 
     515          46 : static void rip_apply_address_add(struct connected *ifc)
     516             : {
     517          46 :         struct rip_interface *ri = ifc->ifp->info;
     518          46 :         struct rip *rip = ri->rip;
     519          46 :         struct prefix_ipv4 address;
     520          46 :         struct nexthop nh;
     521          46 :         struct prefix *p;
     522             : 
     523          46 :         if (!rip)
     524           0 :                 return;
     525             : 
     526          46 :         if (!if_is_up(ifc->ifp))
     527             :                 return;
     528             : 
     529          46 :         p = ifc->address;
     530             : 
     531          46 :         memset(&address, 0, sizeof(address));
     532          46 :         memset(&nh, 0, sizeof(nh));
     533             : 
     534          46 :         address.family = p->family;
     535          46 :         address.prefix = p->u.prefix4;
     536          46 :         address.prefixlen = p->prefixlen;
     537          46 :         apply_mask_ipv4(&address);
     538             : 
     539          46 :         nh.ifindex = ifc->ifp->ifindex;
     540          46 :         nh.type = NEXTHOP_TYPE_IFINDEX;
     541             : 
     542             :         /* Check if this interface is RIP enabled or not
     543             :            or  Check if this address's prefix is RIP enabled */
     544          46 :         if ((rip_enable_if_lookup(rip, ifc->ifp->name) >= 0)
     545          40 :             || (rip_enable_network_lookup2(ifc) >= 0))
     546          20 :                 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
     547             :                                      RIP_ROUTE_INTERFACE, &address, &nh, 0, 0,
     548             :                                      0);
     549             : }
     550             : 
     551          67 : int rip_interface_address_add(ZAPI_CALLBACK_ARGS)
     552             : {
     553          67 :         struct connected *ifc;
     554          67 :         struct prefix *p;
     555             : 
     556          67 :         ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
     557             :                                            zclient->ibuf, vrf_id);
     558             : 
     559          67 :         if (ifc == NULL)
     560             :                 return 0;
     561             : 
     562          67 :         p = ifc->address;
     563             : 
     564          67 :         if (p->family == AF_INET) {
     565          46 :                 if (IS_RIP_DEBUG_ZEBRA)
     566          16 :                         zlog_debug("connected address %pFX is added", p);
     567             : 
     568          46 :                 rip_enable_apply(ifc->ifp);
     569             :                 /* Check if this prefix needs to be redistributed */
     570          46 :                 rip_apply_address_add(ifc);
     571             : 
     572          46 :                 hook_call(rip_ifaddr_add, ifc);
     573             :         }
     574             : 
     575             :         return 0;
     576             : }
     577             : 
     578          10 : static void rip_apply_address_del(struct connected *ifc)
     579             : {
     580          10 :         struct rip_interface *ri = ifc->ifp->info;
     581          10 :         struct rip *rip = ri->rip;
     582          10 :         struct prefix_ipv4 address;
     583          10 :         struct prefix *p;
     584             : 
     585          10 :         if (!rip)
     586           0 :                 return;
     587             : 
     588          10 :         if (!if_is_up(ifc->ifp))
     589             :                 return;
     590             : 
     591          10 :         p = ifc->address;
     592             : 
     593          10 :         memset(&address, 0, sizeof(address));
     594          10 :         address.family = p->family;
     595          10 :         address.prefix = p->u.prefix4;
     596          10 :         address.prefixlen = p->prefixlen;
     597          10 :         apply_mask_ipv4(&address);
     598             : 
     599          10 :         rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT, RIP_ROUTE_INTERFACE,
     600          10 :                                 &address, ifc->ifp->ifindex);
     601             : }
     602             : 
     603          10 : int rip_interface_address_delete(ZAPI_CALLBACK_ARGS)
     604             : {
     605          10 :         struct connected *ifc;
     606          10 :         struct prefix *p;
     607             : 
     608          10 :         ifc = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
     609             :                                            zclient->ibuf, vrf_id);
     610             : 
     611          10 :         if (ifc) {
     612          10 :                 p = ifc->address;
     613          10 :                 if (p->family == AF_INET) {
     614          10 :                         if (IS_RIP_DEBUG_ZEBRA)
     615           0 :                                 zlog_debug("connected address %pFX is deleted",
     616             :                                            p);
     617             : 
     618          10 :                         hook_call(rip_ifaddr_del, ifc);
     619             : 
     620             :                         /* Chech whether this prefix needs to be removed */
     621          10 :                         rip_apply_address_del(ifc);
     622             :                 }
     623             : 
     624          10 :                 connected_free(&ifc);
     625             :         }
     626             : 
     627          10 :         return 0;
     628             : }
     629             : 
     630             : /* Check interface is enabled by network statement. */
     631             : /* Check whether the interface has at least a connected prefix that
     632             :  * is within the ripng_enable_network table. */
     633         114 : static int rip_enable_network_lookup_if(struct interface *ifp)
     634             : {
     635         114 :         struct rip_interface *ri = ifp->info;
     636         114 :         struct rip *rip = ri->rip;
     637         114 :         struct listnode *node, *nnode;
     638         114 :         struct connected *connected;
     639         114 :         struct prefix_ipv4 address;
     640             : 
     641         114 :         if (!rip)
     642             :                 return -1;
     643             : 
     644         291 :         for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
     645          84 :                 struct prefix *p;
     646          84 :                 struct route_node *n;
     647             : 
     648          84 :                 p = connected->address;
     649             : 
     650          84 :                 if (p->family == AF_INET) {
     651          78 :                         address.family = AF_INET;
     652          78 :                         address.prefix = p->u.prefix4;
     653          78 :                         address.prefixlen = IPV4_MAX_BITLEN;
     654             : 
     655          78 :                         n = route_node_match(rip->enable_network,
     656             :                                              (struct prefix *)&address);
     657          78 :                         if (n) {
     658          21 :                                 route_unlock_node(n);
     659          21 :                                 return 1;
     660             :                         }
     661             :                 }
     662             :         }
     663             :         return -1;
     664             : }
     665             : 
     666             : /* Check whether connected is within the ripng_enable_network table. */
     667          61 : static int rip_enable_network_lookup2(struct connected *connected)
     668             : {
     669          61 :         struct rip_interface *ri = connected->ifp->info;
     670          61 :         struct rip *rip = ri->rip;
     671          61 :         struct prefix_ipv4 address;
     672          61 :         struct prefix *p;
     673             : 
     674          61 :         p = connected->address;
     675             : 
     676          61 :         if (p->family == AF_INET) {
     677          61 :                 struct route_node *node;
     678             : 
     679          61 :                 address.family = p->family;
     680          61 :                 address.prefix = p->u.prefix4;
     681          61 :                 address.prefixlen = IPV4_MAX_BITLEN;
     682             : 
     683             :                 /* LPM on p->family, p->u.prefix4/IPV4_MAX_BITLEN within
     684             :                  * rip->enable_network */
     685          61 :                 node = route_node_match(rip->enable_network,
     686             :                                         (struct prefix *)&address);
     687             : 
     688          61 :                 if (node) {
     689          35 :                         route_unlock_node(node);
     690          35 :                         return 1;
     691             :                 }
     692             :         }
     693             : 
     694             :         return -1;
     695             : }
     696             : /* Add RIP enable network. */
     697           5 : int rip_enable_network_add(struct rip *rip, struct prefix *p)
     698             : {
     699           5 :         struct route_node *node;
     700             : 
     701           5 :         node = route_node_get(rip->enable_network, p);
     702             : 
     703           5 :         if (node->info) {
     704           0 :                 route_unlock_node(node);
     705           0 :                 return NB_ERR_INCONSISTENCY;
     706             :         } else
     707           5 :                 node->info = (void *)1;
     708             : 
     709             :         /* XXX: One should find a better solution than a generic one */
     710           5 :         rip_enable_apply_all(rip);
     711             : 
     712           5 :         return NB_OK;
     713             : }
     714             : 
     715             : /* Delete RIP enable network. */
     716           0 : int rip_enable_network_delete(struct rip *rip, struct prefix *p)
     717             : {
     718           0 :         struct route_node *node;
     719             : 
     720           0 :         node = route_node_lookup(rip->enable_network, p);
     721           0 :         if (node) {
     722           0 :                 node->info = NULL;
     723             : 
     724             :                 /* Unlock info lock. */
     725           0 :                 route_unlock_node(node);
     726             : 
     727             :                 /* Unlock lookup lock. */
     728           0 :                 route_unlock_node(node);
     729             : 
     730             :                 /* XXX: One should find a better solution than a generic one */
     731           0 :                 rip_enable_apply_all(rip);
     732             : 
     733           0 :                 return NB_OK;
     734             :         }
     735             : 
     736             :         return NB_ERR_INCONSISTENCY;
     737             : }
     738             : 
     739             : /* Check interface is enabled by ifname statement. */
     740         191 : static int rip_enable_if_lookup(struct rip *rip, const char *ifname)
     741             : {
     742         191 :         unsigned int i;
     743         191 :         char *str;
     744             : 
     745         191 :         if (!rip)
     746             :                 return -1;
     747             : 
     748         253 :         for (i = 0; i < vector_active(rip->enable_interface); i++)
     749          88 :                 if ((str = vector_slot(rip->enable_interface, i)) != NULL)
     750          88 :                         if (strcmp(str, ifname) == 0)
     751          26 :                                 return i;
     752             :         return -1;
     753             : }
     754             : 
     755             : /* Add interface to rip_enable_if. */
     756           2 : int rip_enable_if_add(struct rip *rip, const char *ifname)
     757             : {
     758           2 :         int ret;
     759             : 
     760           2 :         ret = rip_enable_if_lookup(rip, ifname);
     761           2 :         if (ret >= 0)
     762             :                 return NB_ERR_INCONSISTENCY;
     763             : 
     764           2 :         vector_set(rip->enable_interface,
     765             :                    XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
     766             : 
     767           2 :         rip_enable_apply_all(rip); /* TODOVJ */
     768             : 
     769           2 :         return NB_OK;
     770             : }
     771             : 
     772             : /* Delete interface from rip_enable_if. */
     773           0 : int rip_enable_if_delete(struct rip *rip, const char *ifname)
     774             : {
     775           0 :         int index;
     776           0 :         char *str;
     777             : 
     778           0 :         index = rip_enable_if_lookup(rip, ifname);
     779           0 :         if (index < 0)
     780             :                 return NB_ERR_INCONSISTENCY;
     781             : 
     782           0 :         str = vector_slot(rip->enable_interface, index);
     783           0 :         XFREE(MTYPE_RIP_INTERFACE_STRING, str);
     784           0 :         vector_unset(rip->enable_interface, index);
     785             : 
     786           0 :         rip_enable_apply_all(rip); /* TODOVJ */
     787             : 
     788           0 :         return NB_OK;
     789             : }
     790             : 
     791             : /* Join to multicast group and send request to the interface. */
     792           7 : static void rip_interface_wakeup(struct thread *t)
     793             : {
     794           7 :         struct interface *ifp;
     795           7 :         struct rip_interface *ri;
     796             : 
     797             :         /* Get interface. */
     798           7 :         ifp = THREAD_ARG(t);
     799             : 
     800           7 :         ri = ifp->info;
     801             : 
     802             :         /* Join to multicast group. */
     803           7 :         if (rip_multicast_join(ifp, ri->rip->sock) < 0) {
     804           0 :                 flog_err_sys(EC_LIB_SOCKET,
     805             :                              "multicast join failed, interface %s not running",
     806             :                              ifp->name);
     807           0 :                 return;
     808             :         }
     809             : 
     810             :         /* Set running flag. */
     811           7 :         ri->running = 1;
     812             : 
     813             :         /* Send RIP request to the interface. */
     814           7 :         rip_request_interface(ifp);
     815             : }
     816             : 
     817          29 : static void rip_connect_set(struct interface *ifp, int set)
     818             : {
     819          29 :         struct rip_interface *ri = ifp->info;
     820          29 :         struct rip *rip = ri->rip;
     821          29 :         struct listnode *node, *nnode;
     822          29 :         struct connected *connected;
     823          29 :         struct prefix_ipv4 address;
     824          29 :         struct nexthop nh;
     825             : 
     826          29 :         memset(&nh, 0, sizeof(nh));
     827             : 
     828          87 :         for (ALL_LIST_ELEMENTS(ifp->connected, node, nnode, connected)) {
     829          29 :                 struct prefix *p;
     830          29 :                 p = connected->address;
     831             : 
     832          29 :                 if (p->family != AF_INET)
     833           0 :                         continue;
     834             : 
     835          29 :                 address.family = AF_INET;
     836          29 :                 address.prefix = p->u.prefix4;
     837          29 :                 address.prefixlen = p->prefixlen;
     838          29 :                 apply_mask_ipv4(&address);
     839             : 
     840          29 :                 nh.ifindex = connected->ifp->ifindex;
     841          29 :                 nh.type = NEXTHOP_TYPE_IFINDEX;
     842          29 :                 if (set) {
     843             :                         /* Check once more whether this prefix is within a
     844             :                          * "network IF_OR_PREF" one */
     845          29 :                         if ((rip_enable_if_lookup(rip, connected->ifp->name)
     846             :                              >= 0)
     847          21 :                             || (rip_enable_network_lookup2(connected) >= 0))
     848          29 :                                 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
     849             :                                                      RIP_ROUTE_INTERFACE,
     850             :                                                      &address, &nh, 0, 0, 0);
     851             :                 } else {
     852           0 :                         rip_redistribute_delete(rip, ZEBRA_ROUTE_CONNECT,
     853             :                                                 RIP_ROUTE_INTERFACE, &address,
     854             :                                                 connected->ifp->ifindex);
     855           0 :                         if (rip_redistribute_check(rip, ZEBRA_ROUTE_CONNECT))
     856           0 :                                 rip_redistribute_add(rip, ZEBRA_ROUTE_CONNECT,
     857             :                                                      RIP_ROUTE_REDISTRIBUTE,
     858             :                                                      &address, &nh, 0, 0, 0);
     859             :                 }
     860             :         }
     861          29 : }
     862             : 
     863             : /* Update interface status. */
     864         114 : void rip_enable_apply(struct interface *ifp)
     865             : {
     866         114 :         int ret;
     867         114 :         struct rip_interface *ri = NULL;
     868             : 
     869             :         /* Check interface. */
     870         114 :         if (!if_is_operative(ifp))
     871             :                 return;
     872             : 
     873         114 :         ri = ifp->info;
     874             : 
     875             :         /* Check network configuration. */
     876         114 :         ret = rip_enable_network_lookup_if(ifp);
     877             : 
     878             :         /* If the interface is matched. */
     879         114 :         if (ret > 0)
     880          21 :                 ri->enable_network = 1;
     881             :         else
     882          93 :                 ri->enable_network = 0;
     883             : 
     884             :         /* Check interface name configuration. */
     885         114 :         ret = rip_enable_if_lookup(ri->rip, ifp->name);
     886         114 :         if (ret >= 0)
     887          12 :                 ri->enable_interface = 1;
     888             :         else
     889         102 :                 ri->enable_interface = 0;
     890             : 
     891             :         /* any interface MUST have an IPv4 address */
     892         114 :         if (!rip_if_ipv4_address_check(ifp)) {
     893          36 :                 ri->enable_network = 0;
     894          36 :                 ri->enable_interface = 0;
     895             :         }
     896             : 
     897             :         /* Update running status of the interface. */
     898         114 :         if (ri->enable_network || ri->enable_interface) {
     899          29 :                 if (IS_RIP_DEBUG_EVENT)
     900           5 :                         zlog_debug("turn on %s", ifp->name);
     901             : 
     902             :                 /* Add interface wake up thread. */
     903          29 :                 thread_add_timer(master, rip_interface_wakeup, ifp, 1,
     904             :                                  &ri->t_wakeup);
     905          29 :                 rip_connect_set(ifp, 1);
     906          85 :         } else if (ri->running) {
     907             :                 /* Might as well clean up the route table as well
     908             :                  * rip_if_down sets to 0 ri->running, and displays "turn
     909             :                  *off %s"
     910             :                  **/
     911           0 :                 rip_if_down(ifp);
     912             : 
     913           0 :                 rip_connect_set(ifp, 0);
     914             :         }
     915             : }
     916             : 
     917             : /* Apply network configuration to all interface. */
     918           7 : static void rip_enable_apply_all(struct rip *rip)
     919             : {
     920           7 :         struct interface *ifp;
     921             : 
     922             :         /* Check each interface. */
     923          14 :         FOR_ALL_INTERFACES (rip->vrf, ifp)
     924           0 :                 rip_enable_apply(ifp);
     925           7 : }
     926             : 
     927           0 : int rip_neighbor_lookup(struct rip *rip, struct sockaddr_in *from)
     928             : {
     929           0 :         struct prefix_ipv4 p;
     930           0 :         struct route_node *node;
     931             : 
     932           0 :         memset(&p, 0, sizeof(p));
     933           0 :         p.family = AF_INET;
     934           0 :         p.prefix = from->sin_addr;
     935           0 :         p.prefixlen = IPV4_MAX_BITLEN;
     936             : 
     937           0 :         node = route_node_lookup(rip->neighbor, (struct prefix *)&p);
     938           0 :         if (node) {
     939           0 :                 route_unlock_node(node);
     940           0 :                 return 1;
     941             :         }
     942             :         return 0;
     943             : }
     944             : 
     945             : /* Add new RIP neighbor to the neighbor tree. */
     946           0 : int rip_neighbor_add(struct rip *rip, struct prefix_ipv4 *p)
     947             : {
     948           0 :         struct route_node *node;
     949             : 
     950           0 :         node = route_node_get(rip->neighbor, (struct prefix *)p);
     951             : 
     952           0 :         if (node->info)
     953             :                 return NB_ERR_INCONSISTENCY;
     954             : 
     955           0 :         node->info = rip->neighbor;
     956             : 
     957           0 :         return NB_OK;
     958             : }
     959             : 
     960             : /* Delete RIP neighbor from the neighbor tree. */
     961           0 : int rip_neighbor_delete(struct rip *rip, struct prefix_ipv4 *p)
     962             : {
     963           0 :         struct route_node *node;
     964             : 
     965             :         /* Lock for look up. */
     966           0 :         node = route_node_lookup(rip->neighbor, (struct prefix *)p);
     967           0 :         if (!node)
     968             :                 return NB_ERR_INCONSISTENCY;
     969             : 
     970           0 :         node->info = NULL;
     971             : 
     972             :         /* Unlock lookup lock. */
     973           0 :         route_unlock_node(node);
     974             : 
     975             :         /* Unlock real neighbor information lock. */
     976           0 :         route_unlock_node(node);
     977             : 
     978           0 :         return NB_OK;
     979             : }
     980             : 
     981             : /* Clear all network and neighbor configuration. */
     982           5 : void rip_clean_network(struct rip *rip)
     983             : {
     984           5 :         unsigned int i;
     985           5 :         char *str;
     986           5 :         struct route_node *rn;
     987             : 
     988             :         /* rip->enable_network. */
     989          11 :         for (rn = route_top(rip->enable_network); rn; rn = route_next(rn))
     990           6 :                 if (rn->info) {
     991           5 :                         rn->info = NULL;
     992           5 :                         route_unlock_node(rn);
     993             :                 }
     994             : 
     995             :         /* rip->enable_interface. */
     996           7 :         for (i = 0; i < vector_active(rip->enable_interface); i++)
     997           2 :                 if ((str = vector_slot(rip->enable_interface, i)) != NULL) {
     998           2 :                         XFREE(MTYPE_RIP_INTERFACE_STRING, str);
     999           2 :                         vector_slot(rip->enable_interface, i) = NULL;
    1000             :                 }
    1001           5 : }
    1002             : 
    1003             : /* Utility function for looking up passive interface settings. */
    1004          69 : static int rip_passive_nondefault_lookup(struct rip *rip, const char *ifname)
    1005             : {
    1006          69 :         unsigned int i;
    1007          69 :         char *str;
    1008             : 
    1009          80 :         for (i = 0; i < vector_active(rip->passive_nondefault); i++)
    1010          14 :                 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL)
    1011          14 :                         if (strcmp(str, ifname) == 0)
    1012           3 :                                 return i;
    1013             :         return -1;
    1014             : }
    1015             : 
    1016          68 : static void rip_passive_interface_apply(struct interface *ifp)
    1017             : {
    1018          68 :         struct rip *rip;
    1019          68 :         struct rip_interface *ri;
    1020             : 
    1021          68 :         ri = ifp->info;
    1022          68 :         rip = ri->rip;
    1023          68 :         if (rip == NULL)
    1024             :                 return;
    1025             : 
    1026          68 :         ri->passive = ((rip_passive_nondefault_lookup(rip, ifp->name) < 0)
    1027          65 :                                ? rip->passive_default
    1028          68 :                                : !rip->passive_default);
    1029             : 
    1030          68 :         if (IS_RIP_DEBUG_ZEBRA)
    1031          30 :                 zlog_debug("interface %s: passive = %d", ifp->name,
    1032             :                            ri->passive);
    1033             : }
    1034             : 
    1035           6 : static void rip_passive_interface_apply_all(struct rip *rip)
    1036             : {
    1037           6 :         struct interface *ifp;
    1038             : 
    1039           7 :         FOR_ALL_INTERFACES (rip->vrf, ifp)
    1040           0 :                 rip_passive_interface_apply(ifp);
    1041           6 : }
    1042             : 
    1043             : /* Passive interface. */
    1044           1 : int rip_passive_nondefault_set(struct rip *rip, const char *ifname)
    1045             : {
    1046           1 :         if (rip_passive_nondefault_lookup(rip, ifname) >= 0)
    1047             :                 /*
    1048             :                  * Don't return an error, this can happen after changing
    1049             :                  * 'passive-default'.
    1050             :                  */
    1051             :                 return NB_OK;
    1052             : 
    1053           1 :         vector_set(rip->passive_nondefault,
    1054             :                    XSTRDUP(MTYPE_RIP_INTERFACE_STRING, ifname));
    1055             : 
    1056           1 :         rip_passive_interface_apply_all(rip);
    1057             : 
    1058           1 :         return NB_OK;
    1059             : }
    1060             : 
    1061           0 : int rip_passive_nondefault_unset(struct rip *rip, const char *ifname)
    1062             : {
    1063           0 :         int i;
    1064           0 :         char *str;
    1065             : 
    1066           0 :         i = rip_passive_nondefault_lookup(rip, ifname);
    1067           0 :         if (i < 0)
    1068             :                 /*
    1069             :                  * Don't return an error, this can happen after changing
    1070             :                  * 'passive-default'.
    1071             :                  */
    1072             :                 return NB_OK;
    1073             : 
    1074           0 :         str = vector_slot(rip->passive_nondefault, i);
    1075           0 :         XFREE(MTYPE_RIP_INTERFACE_STRING, str);
    1076           0 :         vector_unset(rip->passive_nondefault, i);
    1077             : 
    1078           0 :         rip_passive_interface_apply_all(rip);
    1079             : 
    1080           0 :         return NB_OK;
    1081             : }
    1082             : 
    1083             : /* Free all configured RIP passive-interface settings. */
    1084           5 : void rip_passive_nondefault_clean(struct rip *rip)
    1085             : {
    1086           5 :         unsigned int i;
    1087           5 :         char *str;
    1088             : 
    1089           6 :         for (i = 0; i < vector_active(rip->passive_nondefault); i++)
    1090           1 :                 if ((str = vector_slot(rip->passive_nondefault, i)) != NULL) {
    1091           1 :                         XFREE(MTYPE_RIP_INTERFACE_STRING, str);
    1092           1 :                         vector_slot(rip->passive_nondefault, i) = NULL;
    1093             :                 }
    1094           5 :         rip_passive_interface_apply_all(rip);
    1095           5 : }
    1096             : 
    1097           7 : int rip_show_network_config(struct vty *vty, struct rip *rip)
    1098             : {
    1099           7 :         unsigned int i;
    1100           7 :         char *ifname;
    1101           7 :         struct route_node *node;
    1102             : 
    1103             :         /* Network type RIP enable interface statement. */
    1104          16 :         for (node = route_top(rip->enable_network); node;
    1105           9 :              node = route_next(node))
    1106           9 :                 if (node->info)
    1107           8 :                         vty_out(vty, "    %pFX\n", &node->p);
    1108             : 
    1109             :         /* Interface name RIP enable statement. */
    1110          15 :         for (i = 0; i < vector_active(rip->enable_interface); i++)
    1111           8 :                 if ((ifname = vector_slot(rip->enable_interface, i)) != NULL)
    1112           8 :                         vty_out(vty, "    %s\n", ifname);
    1113             : 
    1114             :         /* RIP neighbors listing. */
    1115           7 :         for (node = route_top(rip->neighbor); node; node = route_next(node))
    1116           0 :                 if (node->info)
    1117           0 :                         vty_out(vty, "    %pI4\n", &node->p.u.prefix4);
    1118             : 
    1119           7 :         return 0;
    1120             : }
    1121             : 
    1122         122 : void rip_interface_sync(struct interface *ifp)
    1123             : {
    1124         122 :         struct rip_interface *ri;
    1125             : 
    1126         122 :         ri = ifp->info;
    1127         100 :         if (ri)
    1128         122 :                 ri->rip = ifp->vrf->info;
    1129          22 : }
    1130             : 
    1131             : /* Called when interface structure allocated. */
    1132          22 : static int rip_interface_new_hook(struct interface *ifp)
    1133             : {
    1134          22 :         ifp->info = rip_interface_new();
    1135          22 :         rip_interface_sync(ifp);
    1136             : 
    1137          22 :         return 0;
    1138             : }
    1139             : 
    1140             : /* Called when interface structure deleted. */
    1141          22 : static int rip_interface_delete_hook(struct interface *ifp)
    1142             : {
    1143          22 :         rip_interface_reset(ifp->info);
    1144          22 :         XFREE(MTYPE_RIP_INTERFACE, ifp->info);
    1145          22 :         return 0;
    1146             : }
    1147             : 
    1148             : /* Allocate and initialize interface vector. */
    1149           5 : void rip_if_init(void)
    1150             : {
    1151             :         /* Default initial size of interface vector. */
    1152           5 :         hook_register_prio(if_add, 0, rip_interface_new_hook);
    1153           5 :         hook_register_prio(if_del, 0, rip_interface_delete_hook);
    1154             : 
    1155             :         /* Install interface node. */
    1156           5 :         if_cmd_init_default();
    1157           5 :         if_zapi_callbacks(rip_ifp_create, rip_ifp_up,
    1158             :                           rip_ifp_down, rip_ifp_destroy);
    1159           5 : }

Generated by: LCOV version v1.16-topotato