back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_zebra.c (source / functions) Hit Total Coverage
Test: test_ospf_topo1.py::OSPFTopo1Test Lines: 341 1006 33.9 %
Date: 2023-02-24 18:38:32 Functions: 33 63 52.4 %

          Line data    Source code
       1             : /*
       2             :  * Zebra connect library for OSPFd
       3             :  * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the
       9             :  * Free Software Foundation; either version 2, or (at your option) any
      10             :  * later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "thread.h"
      25             : #include "command.h"
      26             : #include "network.h"
      27             : #include "prefix.h"
      28             : #include "routemap.h"
      29             : #include "table.h"
      30             : #include "stream.h"
      31             : #include "memory.h"
      32             : #include "zclient.h"
      33             : #include "filter.h"
      34             : #include "plist.h"
      35             : #include "log.h"
      36             : #include "route_opaque.h"
      37             : #include "lib/bfd.h"
      38             : #include "nexthop.h"
      39             : 
      40             : #include "ospfd/ospfd.h"
      41             : #include "ospfd/ospf_interface.h"
      42             : #include "ospfd/ospf_ism.h"
      43             : #include "ospfd/ospf_asbr.h"
      44             : #include "ospfd/ospf_asbr.h"
      45             : #include "ospfd/ospf_abr.h"
      46             : #include "ospfd/ospf_lsa.h"
      47             : #include "ospfd/ospf_dump.h"
      48             : #include "ospfd/ospf_route.h"
      49             : #include "ospfd/ospf_lsdb.h"
      50             : #include "ospfd/ospf_neighbor.h"
      51             : #include "ospfd/ospf_nsm.h"
      52             : #include "ospfd/ospf_zebra.h"
      53             : #include "ospfd/ospf_te.h"
      54             : #include "ospfd/ospf_sr.h"
      55             : #include "ospfd/ospf_ldp_sync.h"
      56             : 
      57          12 : DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table");
      58          12 : DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute");
      59             : 
      60             : 
      61             : /* Zebra structure to hold current status. */
      62             : struct zclient *zclient = NULL;
      63             : /* and for the Synchronous connection to the Label Manager */
      64             : static struct zclient *zclient_sync;
      65             : 
      66             : /* For registering threads. */
      67             : extern struct thread_master *master;
      68             : 
      69             : /* Router-id update message from zebra. */
      70           8 : static int ospf_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
      71             : {
      72           8 :         struct ospf *ospf = NULL;
      73           8 :         struct prefix router_id;
      74           8 :         zebra_router_id_update_read(zclient->ibuf, &router_id);
      75             : 
      76           8 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
      77           0 :                 zlog_debug("Zebra rcvd: router id update %pFX vrf %s id %u",
      78             :                            &router_id, ospf_vrf_id_to_name(vrf_id), vrf_id);
      79             : 
      80           8 :         ospf = ospf_lookup_by_vrf_id(vrf_id);
      81             : 
      82           8 :         if (ospf != NULL) {
      83           8 :                 ospf->router_id_zebra = router_id.u.prefix4;
      84           8 :                 ospf_router_id_update(ospf);
      85             :         } else {
      86           0 :                 if (IS_DEBUG_OSPF_EVENT)
      87           0 :                         zlog_debug(
      88             :                                 "%s: ospf instance not found for vrf %s id %u router_id %pFX",
      89             :                                 __func__, ospf_vrf_id_to_name(vrf_id), vrf_id,
      90             :                                 &router_id);
      91             :         }
      92           8 :         return 0;
      93             : }
      94             : 
      95          97 : static int ospf_interface_address_add(ZAPI_CALLBACK_ARGS)
      96             : {
      97          97 :         struct connected *c;
      98          97 :         struct ospf *ospf = NULL;
      99             : 
     100             : 
     101          97 :         c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     102             : 
     103          97 :         if (c == NULL)
     104             :                 return 0;
     105             : 
     106          97 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
     107           0 :                 zlog_debug("Zebra: interface %s address add %pFX vrf %s id %u",
     108             :                            c->ifp->name, c->address,
     109             :                            ospf_vrf_id_to_name(vrf_id), vrf_id);
     110             : 
     111          97 :         ospf = ospf_lookup_by_vrf_id(vrf_id);
     112          97 :         if (!ospf)
     113             :                 return 0;
     114             : 
     115          97 :         ospf_if_update(ospf, c->ifp);
     116             : 
     117          97 :         ospf_if_interface(c->ifp);
     118             : 
     119          97 :         return 0;
     120             : }
     121             : 
     122          19 : static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS)
     123             : {
     124          19 :         struct connected *c;
     125          19 :         struct interface *ifp;
     126          19 :         struct ospf_interface *oi;
     127          19 :         struct route_node *rn;
     128          19 :         struct prefix p;
     129             : 
     130          19 :         c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);
     131             : 
     132          19 :         if (c == NULL)
     133             :                 return 0;
     134             : 
     135          19 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
     136           0 :                 zlog_debug("Zebra: interface %s address delete %pFX",
     137             :                            c->ifp->name, c->address);
     138             : 
     139          19 :         ifp = c->ifp;
     140          19 :         p = *c->address;
     141          19 :         p.prefixlen = IPV4_MAX_BITLEN;
     142             : 
     143          19 :         rn = route_node_lookup(IF_OIFS(ifp), &p);
     144          19 :         if (!rn) {
     145           9 :                 connected_free(&c);
     146           9 :                 return 0;
     147             :         }
     148             : 
     149          10 :         assert(rn->info);
     150          10 :         oi = rn->info;
     151          10 :         route_unlock_node(rn);
     152             : 
     153             :         /* Call interface hook functions to clean up */
     154          10 :         ospf_if_free(oi);
     155             : 
     156          10 :         ospf_if_interface(c->ifp);
     157             : 
     158          10 :         connected_free(&c);
     159             : 
     160          10 :         return 0;
     161             : }
     162             : 
     163          48 : static int ospf_interface_link_params(ZAPI_CALLBACK_ARGS)
     164             : {
     165          48 :         struct interface *ifp;
     166          48 :         bool changed = false;
     167             : 
     168          48 :         ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed);
     169             : 
     170          48 :         if (ifp == NULL || !changed)
     171             :                 return 0;
     172             : 
     173             :         /* Update TE TLV */
     174           0 :         ospf_mpls_te_update_if(ifp);
     175             : 
     176           0 :         return 0;
     177             : }
     178             : 
     179             : /* VRF update for an interface. */
     180           0 : static int ospf_interface_vrf_update(ZAPI_CALLBACK_ARGS)
     181             : {
     182           0 :         struct interface *ifp = NULL;
     183           0 :         vrf_id_t new_vrf_id;
     184             : 
     185           0 :         ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,
     186             :                                               &new_vrf_id);
     187           0 :         if (!ifp)
     188             :                 return 0;
     189             : 
     190           0 :         if (IS_DEBUG_OSPF_EVENT)
     191           0 :                 zlog_debug(
     192             :                         "%s: Rx Interface %s VRF change vrf_id %u New vrf %s id %u",
     193             :                         __func__, ifp->name, vrf_id,
     194             :                         ospf_vrf_id_to_name(new_vrf_id), new_vrf_id);
     195             : 
     196             :         /*if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id);*/
     197           0 :         if_update_to_new_vrf(ifp, new_vrf_id);
     198             : 
     199           0 :         return 0;
     200             : }
     201             : 
     202             : /* Nexthop, ifindex, distance and metric information. */
     203          50 : static void ospf_zebra_add_nexthop(struct ospf *ospf, struct ospf_path *path,
     204             :                                    struct zapi_route *api)
     205             : {
     206          50 :         struct zapi_nexthop *api_nh;
     207          50 :         struct zapi_nexthop *api_nh_backup;
     208             : 
     209             :         /* TI-LFA backup path label stack comes first, if present */
     210          50 :         if (path->srni.backup_label_stack) {
     211           0 :                 api_nh_backup = &api->backup_nexthops[api->backup_nexthop_num];
     212           0 :                 api_nh_backup->vrf_id = ospf->vrf_id;
     213             : 
     214           0 :                 api_nh_backup->type = NEXTHOP_TYPE_IPV4;
     215           0 :                 api_nh_backup->gate.ipv4 = path->srni.backup_nexthop;
     216             : 
     217           0 :                 api_nh_backup->label_num =
     218           0 :                         path->srni.backup_label_stack->num_labels;
     219           0 :                 memcpy(api_nh_backup->labels,
     220           0 :                        path->srni.backup_label_stack->label,
     221           0 :                        sizeof(mpls_label_t) * api_nh_backup->label_num);
     222             : 
     223           0 :                 api->backup_nexthop_num++;
     224             :         }
     225             : 
     226             :         /* And here comes the primary nexthop */
     227          50 :         api_nh = &api->nexthops[api->nexthop_num];
     228             : #ifdef HAVE_NETLINK
     229          50 :         if (path->unnumbered
     230          50 :             || (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) {
     231             : #else  /* HAVE_NETLINK */
     232             :         if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) {
     233             : #endif /* HAVE_NETLINK */
     234          29 :                 api_nh->gate.ipv4 = path->nexthop;
     235          29 :                 api_nh->ifindex = path->ifindex;
     236          29 :                 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
     237          21 :         } else if (path->nexthop.s_addr != INADDR_ANY) {
     238           0 :                 api_nh->gate.ipv4 = path->nexthop;
     239           0 :                 api_nh->type = NEXTHOP_TYPE_IPV4;
     240             :         } else {
     241          21 :                 api_nh->ifindex = path->ifindex;
     242          21 :                 api_nh->type = NEXTHOP_TYPE_IFINDEX;
     243             :         }
     244          50 :         api_nh->vrf_id = ospf->vrf_id;
     245             : 
     246             :         /* Set TI-LFA backup nexthop info if present */
     247          50 :         if (path->srni.backup_label_stack) {
     248           0 :                 SET_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);
     249           0 :                 SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
     250             : 
     251             :                 /* Just care about a single TI-LFA backup path for now */
     252           0 :                 api_nh->backup_num = 1;
     253           0 :                 api_nh->backup_idx[0] = api->backup_nexthop_num - 1;
     254             :         }
     255             : 
     256          50 :         api->nexthop_num++;
     257          50 : }
     258             : 
     259           0 : static void ospf_zebra_append_opaque_attr(struct ospf_route *or,
     260             :                                           struct zapi_route *api)
     261             : {
     262           0 :         struct ospf_zebra_opaque ospf_opaque = {};
     263             : 
     264             :         /* OSPF path type */
     265           0 :         snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s",
     266           0 :                  ospf_path_type_name(or->path_type));
     267             : 
     268           0 :         switch (or->path_type) {
     269           0 :         case OSPF_PATH_INTRA_AREA:
     270             :         case OSPF_PATH_INTER_AREA:
     271             :                 /* OSPF area ID */
     272           0 :                 (void)inet_ntop(AF_INET, &or->u.std.area_id,
     273             :                                 ospf_opaque.area_id,
     274             :                                 sizeof(ospf_opaque.area_id));
     275           0 :                 break;
     276           0 :         case OSPF_PATH_TYPE1_EXTERNAL:
     277             :         case OSPF_PATH_TYPE2_EXTERNAL:
     278             :                 /* OSPF route tag */
     279           0 :                 snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u",
     280             :                          or->u.ext.tag);
     281           0 :                 break;
     282             :         default:
     283             :                 break;
     284             :         }
     285             : 
     286           0 :         SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE);
     287           0 :         api->opaque.length = sizeof(struct ospf_zebra_opaque);
     288           0 :         memcpy(api->opaque.data, &ospf_opaque, api->opaque.length);
     289           0 : }
     290             : 
     291          50 : void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,
     292             :                     struct ospf_route * or)
     293             : {
     294          50 :         struct zapi_route api;
     295          50 :         uint8_t distance;
     296          50 :         struct ospf_path *path;
     297          50 :         struct listnode *node;
     298             : 
     299          50 :         if (ospf->gr_info.restart_in_progress) {
     300           0 :                 if (IS_DEBUG_OSPF_GR)
     301           0 :                         zlog_debug(
     302             :                                 "Zebra: Graceful Restart in progress -- not installing %pFX",
     303             :                                 p);
     304           0 :                 return;
     305             :         }
     306             : 
     307          50 :         memset(&api, 0, sizeof(api));
     308          50 :         api.vrf_id = ospf->vrf_id;
     309          50 :         api.type = ZEBRA_ROUTE_OSPF;
     310          50 :         api.instance = ospf->instance;
     311          50 :         api.safi = SAFI_UNICAST;
     312             : 
     313          50 :         memcpy(&api.prefix, p, sizeof(*p));
     314          50 :         SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
     315             : 
     316             :         /* Metric value. */
     317          50 :         SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
     318          50 :         if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
     319           0 :                 api.metric = or->cost + or->u.ext.type2_cost;
     320          50 :         else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
     321          12 :                 api.metric = or->u.ext.type2_cost;
     322             :         else
     323          38 :                 api.metric = or->cost;
     324             : 
     325             :         /* Check if path type is ASE */
     326          50 :         if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)
     327          50 :              || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
     328          12 :             && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) {
     329           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
     330           0 :                 api.tag = or->u.ext.tag;
     331             :         }
     332             : 
     333             :         /* Distance value. */
     334          50 :         distance = ospf_distance_apply(ospf, p, or);
     335          50 :         if (distance) {
     336           0 :                 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
     337           0 :                 api.distance = distance;
     338             :         }
     339             : 
     340         150 :         for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) {
     341          50 :                 if (api.nexthop_num >= ospf->max_multipath)
     342             :                         break;
     343             : 
     344          50 :                 ospf_zebra_add_nexthop(ospf, path, &api);
     345             : 
     346          50 :                 if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) {
     347           0 :                         struct interface *ifp;
     348             : 
     349           0 :                         ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id);
     350             : 
     351          50 :                         zlog_debug(
     352             :                                 "Zebra: Route add %pFX nexthop %pI4, ifindex=%d %s",
     353             :                                 p, &path->nexthop, path->ifindex,
     354             :                                 ifp ? ifp->name : " ");
     355             :                 }
     356             :         }
     357             : 
     358          50 :         if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA))
     359           0 :                 ospf_zebra_append_opaque_attr(or, &api);
     360             : 
     361          50 :         zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
     362             : }
     363             : 
     364          48 : void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,
     365             :                        struct ospf_route * or)
     366             : {
     367          48 :         struct zapi_route api;
     368             : 
     369          48 :         if (ospf->gr_info.restart_in_progress) {
     370           0 :                 if (IS_DEBUG_OSPF_GR)
     371           0 :                         zlog_debug(
     372             :                                 "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
     373             :                                 p);
     374           0 :                 return;
     375             :         }
     376             : 
     377          48 :         memset(&api, 0, sizeof(api));
     378          48 :         api.vrf_id = ospf->vrf_id;
     379          48 :         api.type = ZEBRA_ROUTE_OSPF;
     380          48 :         api.instance = ospf->instance;
     381          48 :         api.safi = SAFI_UNICAST;
     382          48 :         memcpy(&api.prefix, p, sizeof(*p));
     383             : 
     384          48 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     385           0 :                 zlog_debug("Zebra: Route delete %pFX", p);
     386             : 
     387          48 :         zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
     388             : }
     389             : 
     390           0 : void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)
     391             : {
     392           0 :         struct zapi_route api;
     393             : 
     394           0 :         if (ospf->gr_info.restart_in_progress) {
     395           0 :                 if (IS_DEBUG_OSPF_GR)
     396           0 :                         zlog_debug(
     397             :                                 "Zebra: Graceful Restart in progress -- not installing %pFX",
     398             :                                 p);
     399           0 :                 return;
     400             :         }
     401             : 
     402           0 :         memset(&api, 0, sizeof(api));
     403           0 :         api.vrf_id = ospf->vrf_id;
     404           0 :         api.type = ZEBRA_ROUTE_OSPF;
     405           0 :         api.instance = ospf->instance;
     406           0 :         api.safi = SAFI_UNICAST;
     407           0 :         memcpy(&api.prefix, p, sizeof(*p));
     408           0 :         zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
     409             : 
     410           0 :         zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
     411             : 
     412           0 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     413           0 :                 zlog_debug("Zebra: Route add discard %pFX", p);
     414             : }
     415             : 
     416           0 : void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)
     417             : {
     418           0 :         struct zapi_route api;
     419             : 
     420           0 :         if (ospf->gr_info.restart_in_progress) {
     421           0 :                 if (IS_DEBUG_OSPF_GR)
     422           0 :                         zlog_debug(
     423             :                                 "Zebra: Graceful Restart in progress -- not uninstalling %pFX",
     424             :                                 p);
     425           0 :                 return;
     426             :         }
     427             : 
     428           0 :         memset(&api, 0, sizeof(api));
     429           0 :         api.vrf_id = ospf->vrf_id;
     430           0 :         api.type = ZEBRA_ROUTE_OSPF;
     431           0 :         api.instance = ospf->instance;
     432           0 :         api.safi = SAFI_UNICAST;
     433           0 :         memcpy(&api.prefix, p, sizeof(*p));
     434           0 :         zapi_route_set_blackhole(&api, BLACKHOLE_NULL);
     435             : 
     436           0 :         zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
     437             : 
     438           0 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     439           0 :                 zlog_debug("Zebra: Route delete discard %pFX", p);
     440             : }
     441             : 
     442        1610 : struct ospf_external *ospf_external_lookup(struct ospf *ospf, uint8_t type,
     443             :                                            unsigned short instance)
     444             : {
     445        1610 :         struct list *ext_list;
     446        1610 :         struct listnode *node;
     447        1610 :         struct ospf_external *ext;
     448             : 
     449        1610 :         ext_list = ospf->external[type];
     450        1610 :         if (!ext_list)
     451             :                 return (NULL);
     452             : 
     453         224 :         for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))
     454         224 :                 if (ext->instance == instance)
     455         224 :                         return ext;
     456             : 
     457             :         return NULL;
     458             : }
     459             : 
     460           4 : struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,
     461             :                                         unsigned short instance)
     462             : {
     463           4 :         struct list *ext_list;
     464           4 :         struct ospf_external *ext;
     465             : 
     466           4 :         ext = ospf_external_lookup(ospf, type, instance);
     467           4 :         if (ext)
     468             :                 return ext;
     469             : 
     470           4 :         if (!ospf->external[type])
     471           4 :                 ospf->external[type] = list_new();
     472             : 
     473           4 :         ext_list = ospf->external[type];
     474           4 :         ext = XCALLOC(MTYPE_OSPF_EXTERNAL, sizeof(struct ospf_external));
     475           4 :         ext->instance = instance;
     476           4 :         EXTERNAL_INFO(ext) = route_table_init();
     477             : 
     478           4 :         listnode_add(ext_list, ext);
     479             : 
     480           4 :         return ext;
     481             : }
     482             : 
     483             : /*
     484             :  * Walk all the ei received from zebra for a route type and apply
     485             :  * default route-map.
     486             :  */
     487           0 : bool ospf_external_default_routemap_apply_walk(struct ospf *ospf,
     488             :                                                struct list *ext_list,
     489             :                                                struct external_info *default_ei)
     490             : {
     491           0 :         struct listnode *node;
     492           0 :         struct ospf_external *ext;
     493           0 :         struct route_node *rn;
     494           0 :         struct external_info *ei = NULL;
     495           0 :         int ret = 0;
     496             : 
     497           0 :         for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
     498           0 :                 if (!ext->external_info)
     499           0 :                         continue;
     500             : 
     501           0 :                 for (rn = route_top(ext->external_info); rn;
     502           0 :                      rn = route_next(rn)) {
     503           0 :                         ei = rn->info;
     504           0 :                         if (!ei)
     505           0 :                                 continue;
     506           0 :                         ret = ospf_external_info_apply_default_routemap(
     507             :                                 ospf, ei, default_ei);
     508           0 :                         if (ret)
     509             :                                 break;
     510             :                 }
     511             :         }
     512             : 
     513           0 :         if (ret && ei) {
     514           0 :                 if (IS_DEBUG_OSPF_DEFAULT_INFO)
     515           0 :                         zlog_debug("Default originate routemap permit ei: %pI4",
     516             :                                    &ei->p.prefix);
     517           0 :                 return true;
     518             :         }
     519             : 
     520             :         return false;
     521             : }
     522             : 
     523             : /*
     524             :  * Function to originate or flush default after applying
     525             :  * route-map on all ei.
     526             :  */
     527           0 : static void ospf_external_lsa_default_routemap_timer(struct thread *thread)
     528             : {
     529           0 :         struct list *ext_list;
     530           0 :         struct ospf *ospf = THREAD_ARG(thread);
     531           0 :         struct prefix_ipv4 p;
     532           0 :         int type;
     533           0 :         int ret = 0;
     534           0 :         struct ospf_lsa *lsa;
     535           0 :         struct external_info *default_ei;
     536             : 
     537           0 :         p.family = AF_INET;
     538           0 :         p.prefixlen = 0;
     539           0 :         p.prefix.s_addr = INADDR_ANY;
     540             : 
     541             :         /* Get the default extenal info. */
     542           0 :         default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
     543           0 :                                                ospf->instance, &p);
     544           0 :         if (!default_ei) {
     545             :                 /* Nothing to be done here. */
     546           0 :                 if (IS_DEBUG_OSPF_DEFAULT_INFO)
     547           0 :                         zlog_debug("Default originate info not present");
     548           0 :                 return;
     549             :         }
     550             : 
     551             :         /* For all the ei apply route-map */
     552           0 :         for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
     553           0 :                 ext_list = ospf->external[type];
     554           0 :                 if (!ext_list || type == ZEBRA_ROUTE_OSPF)
     555           0 :                         continue;
     556             : 
     557           0 :                 ret = ospf_external_default_routemap_apply_walk(ospf, ext_list,
     558             :                                                                 default_ei);
     559           0 :                 if (ret)
     560             :                         break;
     561             :         }
     562             : 
     563             :         /* Get the default LSA. */
     564           0 :         lsa = ospf_external_info_find_lsa(ospf, &p);
     565             : 
     566             :         /* If permit then originate default. */
     567           0 :         if (ret && !lsa)
     568           0 :                 ospf_external_lsa_originate(ospf, default_ei);
     569           0 :         else if (ret && lsa && IS_LSA_MAXAGE(lsa))
     570           0 :                 ospf_external_lsa_refresh(ospf, lsa, default_ei, true, false);
     571           0 :         else if (!ret && lsa)
     572           0 :                 ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0);
     573             : }
     574             : 
     575             : 
     576           4 : void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)
     577             : {
     578           4 :         struct ospf_external *ext;
     579             : 
     580           4 :         ext = ospf_external_lookup(ospf, type, instance);
     581             : 
     582           4 :         if (ext) {
     583           4 :                 if (EXTERNAL_INFO(ext))
     584           4 :                         route_table_finish(EXTERNAL_INFO(ext));
     585             : 
     586           4 :                 listnode_delete(ospf->external[type], ext);
     587             : 
     588           4 :                 if (!ospf->external[type]->count)
     589           4 :                         list_delete(&ospf->external[type]);
     590             : 
     591           4 :                 XFREE(MTYPE_OSPF_EXTERNAL, ext);
     592             :         }
     593             : 
     594             :         /*
     595             :          * Check if default needs to be flushed too.
     596             :          */
     597           4 :         thread_add_event(master, ospf_external_lsa_default_routemap_timer, ospf,
     598             :                          0, &ospf->t_default_routemap_timer);
     599           4 : }
     600             : 
     601             : /* Update NHLFE for Prefix SID */
     602           0 : void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp)
     603             : {
     604           0 :         struct zapi_labels zl;
     605           0 :         struct zapi_nexthop *znh;
     606           0 :         struct zapi_nexthop *znh_backup;
     607           0 :         struct listnode *node;
     608           0 :         struct ospf_path *path;
     609             : 
     610             :         /* Prepare message. */
     611           0 :         memset(&zl, 0, sizeof(zl));
     612           0 :         zl.type = ZEBRA_LSP_OSPF_SR;
     613           0 :         zl.local_label = srp->label_in;
     614             : 
     615           0 :         switch (srp->type) {
     616           0 :         case LOCAL_SID:
     617             :                 /* Set Label for local Prefix */
     618           0 :                 znh = &zl.nexthops[zl.nexthop_num++];
     619           0 :                 znh->type = NEXTHOP_TYPE_IFINDEX;
     620           0 :                 znh->ifindex = srp->nhlfe.ifindex;
     621           0 :                 znh->label_num = 1;
     622           0 :                 znh->labels[0] = srp->nhlfe.label_out;
     623             : 
     624           0 :                 osr_debug("SR (%s): Configure Prefix %pFX with labels %u/%u",
     625             :                           __func__, (struct prefix *)&srp->prefv4,
     626             :                           srp->label_in, srp->nhlfe.label_out);
     627             : 
     628             :                 break;
     629             : 
     630           0 :         case PREF_SID:
     631             :                 /* Update route in the RIB too. */
     632           0 :                 SET_FLAG(zl.message, ZAPI_LABELS_FTN);
     633           0 :                 zl.route.prefix.u.prefix4 = srp->prefv4.prefix;
     634           0 :                 zl.route.prefix.prefixlen = srp->prefv4.prefixlen;
     635           0 :                 zl.route.prefix.family = srp->prefv4.family;
     636           0 :                 zl.route.type = ZEBRA_ROUTE_OSPF;
     637           0 :                 zl.route.instance = 0;
     638             : 
     639             :                 /* Check that SRP contains at least one valid path */
     640           0 :                 if (srp->route == NULL) {
     641           0 :                         return;
     642             :                 }
     643             : 
     644           0 :                 osr_debug("SR (%s): Configure Prefix %pFX with",
     645             :                           __func__, (struct prefix *)&srp->prefv4);
     646             : 
     647           0 :                 for (ALL_LIST_ELEMENTS_RO(srp->route->paths, node, path)) {
     648           0 :                         if (path->srni.label_out == MPLS_INVALID_LABEL)
     649           0 :                                 continue;
     650             : 
     651           0 :                         if (zl.nexthop_num >= MULTIPATH_NUM)
     652             :                                 break;
     653             : 
     654             :                         /*
     655             :                          * TI-LFA backup path label stack comes first, if
     656             :                          * present.
     657             :                          */
     658           0 :                         if (path->srni.backup_label_stack) {
     659           0 :                                 znh_backup = &zl.backup_nexthops
     660           0 :                                                       [zl.backup_nexthop_num++];
     661           0 :                                 znh_backup->type = NEXTHOP_TYPE_IPV4;
     662           0 :                                 znh_backup->gate.ipv4 =
     663             :                                         path->srni.backup_nexthop;
     664             : 
     665           0 :                                 memcpy(znh_backup->labels,
     666           0 :                                        path->srni.backup_label_stack->label,
     667             :                                        sizeof(mpls_label_t)
     668             :                                                * path->srni.backup_label_stack
     669           0 :                                                          ->num_labels);
     670             : 
     671           0 :                                 znh_backup->label_num =
     672           0 :                                         path->srni.backup_label_stack
     673           0 :                                                 ->num_labels;
     674           0 :                                 if (path->srni.label_out
     675             :                                             != MPLS_LABEL_IPV4_EXPLICIT_NULL
     676           0 :                                     && path->srni.label_out
     677             :                                                != MPLS_LABEL_IMPLICIT_NULL)
     678           0 :                                         znh_backup->labels
     679           0 :                                                 [znh_backup->label_num++] =
     680             :                                                 path->srni.label_out;
     681             :                         }
     682             : 
     683           0 :                         znh = &zl.nexthops[zl.nexthop_num++];
     684           0 :                         znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
     685           0 :                         znh->gate.ipv4 = path->nexthop;
     686           0 :                         znh->ifindex = path->ifindex;
     687           0 :                         znh->label_num = 1;
     688           0 :                         znh->labels[0] = path->srni.label_out;
     689             : 
     690           0 :                         osr_debug("  |- labels %u/%u", srp->label_in,
     691             :                                   path->srni.label_out);
     692             : 
     693             :                         /* Set TI-LFA backup nexthop info if present */
     694           0 :                         if (path->srni.backup_label_stack) {
     695           0 :                                 SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);
     696           0 :                                 SET_FLAG(znh->flags,
     697             :                                          ZAPI_NEXTHOP_FLAG_HAS_BACKUP);
     698             : 
     699             :                                 /* Just care about a single TI-LFA backup path
     700             :                                  * for now */
     701           0 :                                 znh->backup_num = 1;
     702           0 :                                 znh->backup_idx[0] = zl.backup_nexthop_num - 1;
     703             :                         }
     704             :                 }
     705             :                 break;
     706             :         case ADJ_SID:
     707             :         case LAN_ADJ_SID:
     708             :                 return;
     709             :         }
     710             : 
     711             :         /* Finally, send message to zebra. */
     712           0 :         (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);
     713             : }
     714             : 
     715             : /* Remove NHLFE for Prefix-SID */
     716           0 : void ospf_zebra_delete_prefix_sid(const struct sr_prefix *srp)
     717             : {
     718           0 :         struct zapi_labels zl;
     719             : 
     720           0 :         osr_debug("SR (%s): Delete Labels %u for Prefix %pFX", __func__,
     721             :                   srp->label_in, (struct prefix *)&srp->prefv4);
     722             : 
     723             :         /* Prepare message. */
     724           0 :         memset(&zl, 0, sizeof(zl));
     725           0 :         zl.type = ZEBRA_LSP_OSPF_SR;
     726           0 :         zl.local_label = srp->label_in;
     727             : 
     728           0 :         if (srp->type == PREF_SID) {
     729             :                 /* Update route in the RIB too */
     730           0 :                 SET_FLAG(zl.message, ZAPI_LABELS_FTN);
     731           0 :                 zl.route.prefix.u.prefix4 = srp->prefv4.prefix;
     732           0 :                 zl.route.prefix.prefixlen = srp->prefv4.prefixlen;
     733           0 :                 zl.route.prefix.family = srp->prefv4.family;
     734           0 :                 zl.route.type = ZEBRA_ROUTE_OSPF;
     735           0 :                 zl.route.instance = 0;
     736             :         }
     737             : 
     738             :         /* Send message to zebra. */
     739           0 :         (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);
     740           0 : }
     741             : 
     742             : /* Send MPLS Label entry to Zebra for installation or deletion */
     743           0 : void ospf_zebra_send_adjacency_sid(int cmd, struct sr_nhlfe nhlfe)
     744             : {
     745           0 :         struct zapi_labels zl;
     746           0 :         struct zapi_nexthop *znh;
     747             : 
     748           0 :         osr_debug("SR (%s): %s Labels %u/%u for Adjacency via %u", __func__,
     749             :                   cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",
     750             :                   nhlfe.label_in, nhlfe.label_out, nhlfe.ifindex);
     751             : 
     752           0 :         memset(&zl, 0, sizeof(zl));
     753           0 :         zl.type = ZEBRA_LSP_OSPF_SR;
     754           0 :         zl.local_label = nhlfe.label_in;
     755           0 :         zl.nexthop_num = 1;
     756           0 :         znh = &zl.nexthops[0];
     757           0 :         znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
     758           0 :         znh->gate.ipv4 = nhlfe.nexthop;
     759           0 :         znh->ifindex = nhlfe.ifindex;
     760           0 :         znh->label_num = 1;
     761           0 :         znh->labels[0] = nhlfe.label_out;
     762             : 
     763           0 :         (void)zebra_send_mpls_labels(zclient, cmd, &zl);
     764           0 : }
     765             : 
     766          53 : struct ospf_redist *ospf_redist_lookup(struct ospf *ospf, uint8_t type,
     767             :                                        unsigned short instance)
     768             : {
     769          53 :         struct list *red_list;
     770          53 :         struct listnode *node;
     771          53 :         struct ospf_redist *red;
     772             : 
     773          53 :         red_list = ospf->redist[type];
     774          53 :         if (!red_list)
     775             :                 return (NULL);
     776             : 
     777          41 :         for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
     778          41 :                 if (red->instance == instance)
     779          41 :                         return red;
     780             : 
     781             :         return NULL;
     782             : }
     783             : 
     784           4 : struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type,
     785             :                                     unsigned short instance)
     786             : {
     787           4 :         struct list *red_list;
     788           4 :         struct ospf_redist *red;
     789             : 
     790           4 :         red = ospf_redist_lookup(ospf, type, instance);
     791           4 :         if (red)
     792             :                 return red;
     793             : 
     794           4 :         if (!ospf->redist[type])
     795           4 :                 ospf->redist[type] = list_new();
     796             : 
     797           4 :         red_list = ospf->redist[type];
     798           4 :         red = XCALLOC(MTYPE_OSPF_REDISTRIBUTE, sizeof(struct ospf_redist));
     799           4 :         red->instance = instance;
     800           4 :         red->dmetric.type = -1;
     801           4 :         red->dmetric.value = -1;
     802           4 :         ROUTEMAP_NAME(red) = NULL;
     803           4 :         ROUTEMAP(red) = NULL;
     804             : 
     805           4 :         listnode_add(red_list, red);
     806             : 
     807           4 :         return red;
     808             : }
     809             : 
     810           4 : void ospf_redist_del(struct ospf *ospf, uint8_t type, unsigned short instance)
     811             : {
     812           4 :         struct ospf_redist *red;
     813             : 
     814           4 :         red = ospf_redist_lookup(ospf, type, instance);
     815             : 
     816           4 :         if (red) {
     817           4 :                 listnode_delete(ospf->redist[type], red);
     818           4 :                 if (!ospf->redist[type]->count) {
     819           4 :                         list_delete(&ospf->redist[type]);
     820             :                 }
     821           4 :                 ospf_routemap_unset(red);
     822           4 :                 XFREE(MTYPE_OSPF_REDISTRIBUTE, red);
     823             :         }
     824           4 : }
     825             : 
     826             : 
     827         151 : int ospf_is_type_redistributed(struct ospf *ospf, int type,
     828             :                                unsigned short instance)
     829             : {
     830         151 :         return (DEFAULT_ROUTE_TYPE(type)
     831           0 :                         ? vrf_bitmap_check(zclient->default_information[AFI_IP],
     832             :                                            ospf->vrf_id)
     833         151 :                         : ((instance
     834           0 :                             && redist_check_instance(
     835           0 :                                     &zclient->mi_redist[AFI_IP][type],
     836             :                                     instance))
     837         151 :                            || (!instance
     838         151 :                                && vrf_bitmap_check(
     839         151 :                                        zclient->redist[AFI_IP][type],
     840             :                                        ospf->vrf_id))));
     841             : }
     842             : 
     843           0 : int ospf_redistribute_update(struct ospf *ospf, struct ospf_redist *red,
     844             :                              int type, unsigned short instance, int mtype,
     845             :                              int mvalue)
     846             : {
     847           0 :         int force = 0;
     848             : 
     849           0 :         if (mtype != red->dmetric.type) {
     850           0 :                 red->dmetric.type = mtype;
     851           0 :                 force = LSA_REFRESH_FORCE;
     852             :         }
     853           0 :         if (mvalue != red->dmetric.value) {
     854           0 :                 red->dmetric.value = mvalue;
     855           0 :                 force = LSA_REFRESH_FORCE;
     856             :         }
     857             : 
     858           0 :         ospf_external_lsa_refresh_type(ospf, type, instance, force);
     859             : 
     860           0 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     861           0 :                 zlog_debug(
     862             :                         "Redistribute[%s][%d]: Refresh  Type[%d], Metric[%d]",
     863             :                         ospf_redist_string(type), instance,
     864             :                         metric_type(ospf, type, instance),
     865             :                         metric_value(ospf, type, instance));
     866             : 
     867           0 :         return CMD_SUCCESS;
     868             : }
     869             : 
     870           4 : int ospf_redistribute_set(struct ospf *ospf, struct ospf_redist *red, int type,
     871             :                           unsigned short instance, int mtype, int mvalue)
     872             : {
     873           4 :         red->dmetric.type = mtype;
     874           4 :         red->dmetric.value = mvalue;
     875             : 
     876           4 :         ospf_external_add(ospf, type, instance);
     877             : 
     878           4 :         zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
     879             :                              instance, ospf->vrf_id);
     880             : 
     881           4 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     882           0 :                 zlog_debug(
     883             :                         "Redistribute[%s][%d] vrf id %u: Start  Type[%d], Metric[%d]",
     884             :                         ospf_redist_string(type), instance, ospf->vrf_id,
     885             :                         metric_type(ospf, type, instance),
     886             :                         metric_value(ospf, type, instance));
     887             : 
     888           4 :         ospf_asbr_status_update(ospf, ++ospf->redistribute);
     889             : 
     890           4 :         return CMD_SUCCESS;
     891             : }
     892             : 
     893           4 : int ospf_redistribute_unset(struct ospf *ospf, int type,
     894             :                             unsigned short instance)
     895             : {
     896           4 :         if (type == zclient->redist_default && instance == zclient->instance)
     897             :                 return CMD_SUCCESS;
     898             : 
     899           4 :         zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type,
     900             :                              instance, ospf->vrf_id);
     901             : 
     902           4 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     903           0 :                 zlog_debug("Redistribute[%s][%d] vrf id %u: Stop",
     904             :                            ospf_redist_string(type), instance, ospf->vrf_id);
     905             : 
     906             :         /* Remove the routes from OSPF table. */
     907           4 :         ospf_redistribute_withdraw(ospf, type, instance);
     908             : 
     909           4 :         ospf_external_del(ospf, type, instance);
     910             : 
     911           4 :         ospf_asbr_status_update(ospf, --ospf->redistribute);
     912             : 
     913           4 :         return CMD_SUCCESS;
     914             : }
     915             : 
     916           0 : int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,
     917             :                                   int mvalue)
     918             : {
     919           0 :         struct prefix_ipv4 p;
     920           0 :         struct in_addr nexthop;
     921           0 :         int cur_originate = ospf->default_originate;
     922           0 :         const char *type_str = NULL;
     923             : 
     924           0 :         nexthop.s_addr = INADDR_ANY;
     925           0 :         p.family = AF_INET;
     926           0 :         p.prefix.s_addr = INADDR_ANY;
     927           0 :         p.prefixlen = 0;
     928             : 
     929           0 :         ospf->default_originate = originate;
     930             : 
     931           0 :         if (cur_originate == originate) {
     932             :                 /* Refresh the lsa since metric might different */
     933           0 :                 if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     934           0 :                         zlog_debug(
     935             :                                 "Redistribute[%s]: Refresh  Type[%d], Metric[%d]",
     936             :                                 ospf_redist_string(DEFAULT_ROUTE),
     937             :                                 metric_type(ospf, DEFAULT_ROUTE, 0),
     938             :                                 metric_value(ospf, DEFAULT_ROUTE, 0));
     939             : 
     940           0 :                 ospf_external_lsa_refresh_default(ospf);
     941           0 :                 return CMD_SUCCESS;
     942             :         }
     943             : 
     944           0 :         switch (cur_originate) {
     945             :         case DEFAULT_ORIGINATE_NONE:
     946             :                 break;
     947           0 :         case DEFAULT_ORIGINATE_ZEBRA:
     948           0 :                 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
     949             :                                  zclient, AFI_IP, ospf->vrf_id);
     950           0 :                 ospf->redistribute--;
     951           0 :                 break;
     952           0 :         case DEFAULT_ORIGINATE_ALWAYS:
     953           0 :                 ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);
     954           0 :                 ospf_external_del(ospf, DEFAULT_ROUTE, 0);
     955           0 :                 ospf->redistribute--;
     956           0 :                 break;
     957             :         }
     958             : 
     959           0 :         switch (originate) {
     960           0 :         case DEFAULT_ORIGINATE_NONE:
     961           0 :                 type_str = "none";
     962           0 :                 break;
     963           0 :         case DEFAULT_ORIGINATE_ZEBRA:
     964           0 :                 type_str = "normal";
     965           0 :                 ospf->redistribute++;
     966           0 :                 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
     967             :                                              zclient, AFI_IP, ospf->vrf_id);
     968           0 :                 break;
     969           0 :         case DEFAULT_ORIGINATE_ALWAYS:
     970           0 :                 type_str = "always";
     971           0 :                 ospf->redistribute++;
     972           0 :                 ospf_external_add(ospf, DEFAULT_ROUTE, 0);
     973           0 :                 ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop,
     974             :                                        0);
     975           0 :                 break;
     976             :         }
     977             : 
     978           0 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
     979           0 :                 zlog_debug("Redistribute[DEFAULT]: %s Type[%d], Metric[%d]",
     980             :                 type_str,
     981             :                 metric_type(ospf, DEFAULT_ROUTE, 0),
     982             :                 metric_value(ospf, DEFAULT_ROUTE, 0));
     983             : 
     984           0 :         ospf_external_lsa_refresh_default(ospf);
     985           0 :         ospf_asbr_status_update(ospf, ospf->redistribute);
     986           0 :         return CMD_SUCCESS;
     987             : }
     988             : 
     989          47 : static int ospf_external_lsa_originate_check(struct ospf *ospf,
     990             :                                              struct external_info *ei)
     991             : {
     992             :         /* If prefix is multicast, then do not originate LSA. */
     993          47 :         if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) {
     994           0 :                 zlog_info(
     995             :                         "LSA[Type5:%pI4]: Not originate AS-external-LSA, Prefix belongs multicast",
     996             :                         &ei->p.prefix);
     997           0 :                 return 0;
     998             :         }
     999             : 
    1000             :         /* Take care of default-originate. */
    1001          47 :         if (is_default_prefix4(&ei->p))
    1002           0 :                 if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) {
    1003           0 :                         zlog_info(
    1004             :                                 "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA for default");
    1005           0 :                         return 0;
    1006             :                 }
    1007             : 
    1008             :         return 1;
    1009             : }
    1010             : 
    1011             : /* If connected prefix is OSPF enable interface, then do not announce. */
    1012          47 : int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei)
    1013             : {
    1014          47 :         struct listnode *node;
    1015          47 :         struct ospf_interface *oi;
    1016             : 
    1017             : 
    1018         158 :         for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
    1019          82 :                 if (prefix_match(oi->address, (struct prefix *)&ei->p))
    1020             :                         return 0;
    1021             :         return 1;
    1022             : }
    1023             : 
    1024             : 
    1025             : /* Apply default route-map on ei received. */
    1026           0 : int ospf_external_info_apply_default_routemap(struct ospf *ospf,
    1027             :                                               struct external_info *ei,
    1028             :                                               struct external_info *default_ei)
    1029             : {
    1030           0 :         struct ospf_redist *red;
    1031           0 :         int type = default_ei->type;
    1032           0 :         struct prefix_ipv4 *p = &ei->p;
    1033           0 :         struct route_map_set_values save_values;
    1034             : 
    1035             : 
    1036           0 :         if (!ospf_external_lsa_originate_check(ospf, default_ei))
    1037             :                 return 0;
    1038             : 
    1039           0 :         save_values = default_ei->route_map_set;
    1040           0 :         ospf_reset_route_map_set_values(&default_ei->route_map_set);
    1041             : 
    1042             :         /* apply route-map if needed */
    1043           0 :         red = ospf_redist_lookup(ospf, type, ospf->instance);
    1044           0 :         if (red && ROUTEMAP_NAME(red)) {
    1045           0 :                 route_map_result_t ret;
    1046             : 
    1047           0 :                 ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);
    1048             : 
    1049           0 :                 if (ret == RMAP_DENYMATCH) {
    1050           0 :                         ei->route_map_set = save_values;
    1051           0 :                         return 0;
    1052             :                 }
    1053             :         }
    1054             : 
    1055             :         return 1;
    1056             : }
    1057             : 
    1058             : 
    1059             : /*
    1060             :  * Default originated is based on route-map condition then
    1061             :  * apply route-map on received external info. Originate or
    1062             :  * flush based on route-map condition.
    1063             :  */
    1064          14 : static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf,
    1065             :                                                      struct external_info *ei,
    1066             :                                                      int cmd)
    1067             : {
    1068          14 :         struct external_info *default_ei;
    1069          14 :         struct prefix_ipv4 p;
    1070          14 :         struct ospf_lsa *lsa;
    1071          14 :         int ret;
    1072             : 
    1073          14 :         p.family = AF_INET;
    1074          14 :         p.prefixlen = 0;
    1075          14 :         p.prefix.s_addr = INADDR_ANY;
    1076             : 
    1077             : 
    1078             :         /* Get the default extenal info. */
    1079          28 :         default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,
    1080          14 :                                                ospf->instance, &p);
    1081          14 :         if (!default_ei) {
    1082             :                 /* Nothing to be done here. */
    1083             :                 return false;
    1084             :         }
    1085             : 
    1086           0 :         if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1087           0 :                 zlog_debug("Apply default originate routemap on ei: %pI4 cmd: %d",
    1088             :                            &ei->p.prefix, cmd);
    1089             : 
    1090           0 :         ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei);
    1091             : 
    1092             :         /* If deny then nothing to be done both in add and del case. */
    1093           0 :         if (!ret) {
    1094           0 :                 if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1095           0 :                         zlog_debug("Default originte routemap deny for ei: %pI4",
    1096             :                                    &ei->p.prefix);
    1097           0 :                 return false;
    1098             :         }
    1099             : 
    1100             :         /* Get the default LSA. */
    1101           0 :         lsa = ospf_external_info_find_lsa(ospf, &p);
    1102             : 
    1103             :         /* If this is add route and permit then ooriginate default. */
    1104           0 :         if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
    1105             :                 /* If permit and default already advertise then return. */
    1106           0 :                 if (lsa && !IS_LSA_MAXAGE(lsa)) {
    1107           0 :                         if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1108           0 :                                 zlog_debug("Default lsa already originated");
    1109           0 :                         return true;
    1110             :                 }
    1111             : 
    1112           0 :                 if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1113           0 :                         zlog_debug("Originating/Refreshing default lsa");
    1114             : 
    1115           0 :                 if (lsa && IS_LSA_MAXAGE(lsa))
    1116             :                         /* Refresh lsa.*/
    1117           0 :                         ospf_external_lsa_refresh(ospf, lsa, default_ei, true,
    1118             :                                                   false);
    1119             :                 else
    1120             :                         /* If permit and default not advertised then advertise.
    1121             :                          */
    1122           0 :                         ospf_external_lsa_originate(ospf, default_ei);
    1123             : 
    1124           0 :         } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) {
    1125             :                 /* If deny and lsa is not originated then nothing to be done.*/
    1126           0 :                 if (!lsa) {
    1127           0 :                         if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1128           0 :                                 zlog_debug(
    1129             :                                         "Default lsa not originated, not flushing");
    1130           0 :                         return true;
    1131             :                 }
    1132             : 
    1133           0 :                 if (IS_DEBUG_OSPF_DEFAULT_INFO)
    1134           0 :                         zlog_debug(
    1135             :                                 "Running default route-map again as ei: %pI4 deleted",
    1136             :                                 &ei->p.prefix);
    1137             :                 /*
    1138             :                  * if this route delete was permitted then we need to check
    1139             :                  * there are any other external info which can still trigger
    1140             :                  * default route origination else flush it.
    1141             :                  */
    1142           0 :                 thread_add_event(master,
    1143             :                                  ospf_external_lsa_default_routemap_timer, ospf,
    1144             :                                  0, &ospf->t_default_routemap_timer);
    1145             :         }
    1146             : 
    1147             :         return true;
    1148             : }
    1149             : 
    1150             : /* return 1 if external LSA must be originated, 0 otherwise */
    1151          47 : int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
    1152             :                             int *changed)
    1153             : {
    1154          47 :         struct route_map_set_values save_values;
    1155          47 :         struct prefix_ipv4 *p = &ei->p;
    1156          47 :         struct ospf_redist *red;
    1157          47 :         uint8_t type = is_default_prefix4(&ei->p) ? DEFAULT_ROUTE : ei->type;
    1158          47 :         unsigned short instance = is_default_prefix4(&ei->p) ? 0 : ei->instance;
    1159          47 :         route_tag_t saved_tag = 0;
    1160             : 
    1161             :         /* Default is handled differently. */
    1162          47 :         if (type == DEFAULT_ROUTE)
    1163             :                 return 1;
    1164             : 
    1165          47 :         if (changed)
    1166           0 :                 *changed = 0;
    1167             : 
    1168          47 :         if (!ospf_external_lsa_originate_check(ospf, ei))
    1169             :                 return 0;
    1170             : 
    1171             :         /* Take care connected route. */
    1172          47 :         if (type == ZEBRA_ROUTE_CONNECT
    1173          47 :             && !ospf_distribute_check_connected(ospf, ei))
    1174             :                 return 0;
    1175             : 
    1176          29 :         if (!DEFAULT_ROUTE_TYPE(type) && DISTRIBUTE_NAME(ospf, type))
    1177             :                 /* distirbute-list exists, but access-list may not? */
    1178           0 :                 if (DISTRIBUTE_LIST(ospf, type))
    1179           0 :                         if (access_list_apply(DISTRIBUTE_LIST(ospf, type), p)
    1180             :                             == FILTER_DENY) {
    1181           0 :                                 if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
    1182           0 :                                         zlog_debug(
    1183             :                                                 "Redistribute[%s]: %pFX filtered by distribute-list.",
    1184             :                                                 ospf_redist_string(type), p);
    1185           0 :                                 return 0;
    1186             :                         }
    1187             : 
    1188          29 :         save_values = ei->route_map_set;
    1189          29 :         ospf_reset_route_map_set_values(&ei->route_map_set);
    1190             : 
    1191          29 :         saved_tag = ei->tag;
    1192             :         /* Resetting with original route tag */
    1193          29 :         ei->tag = ei->orig_tag;
    1194             : 
    1195             :         /* apply route-map if needed */
    1196          29 :         red = ospf_redist_lookup(ospf, type, instance);
    1197          29 :         if (red && ROUTEMAP_NAME(red)) {
    1198           0 :                 route_map_result_t ret;
    1199             : 
    1200           0 :                 ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);
    1201             : 
    1202           0 :                 if (ret == RMAP_DENYMATCH) {
    1203           0 :                         ei->route_map_set = save_values;
    1204           0 :                         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
    1205           0 :                                 zlog_debug(
    1206             :                                         "Redistribute[%s]: %pFX filtered by route-map.",
    1207             :                                         ospf_redist_string(type), p);
    1208           0 :                         return 0;
    1209             :                 }
    1210             : 
    1211             :                 /* check if 'route-map set' changed something */
    1212           0 :                 if (changed) {
    1213           0 :                         *changed = !ospf_route_map_set_compare(
    1214             :                                 &ei->route_map_set, &save_values);
    1215             : 
    1216             :                         /* check if tag is modified */
    1217           0 :                         *changed |= (saved_tag != ei->tag);
    1218             :                 }
    1219             :         }
    1220             : 
    1221             :         return 1;
    1222             : }
    1223             : 
    1224             : /* OSPF route-map set for redistribution */
    1225           0 : void ospf_routemap_set(struct ospf_redist *red, const char *name)
    1226             : {
    1227           0 :         if (ROUTEMAP_NAME(red)) {
    1228           0 :                 route_map_counter_decrement(ROUTEMAP(red));
    1229           0 :                 free(ROUTEMAP_NAME(red));
    1230             :         }
    1231             : 
    1232           0 :         ROUTEMAP_NAME(red) = strdup(name);
    1233           0 :         ROUTEMAP(red) = route_map_lookup_by_name(name);
    1234           0 :         route_map_counter_increment(ROUTEMAP(red));
    1235           0 : }
    1236             : 
    1237           8 : void ospf_routemap_unset(struct ospf_redist *red)
    1238             : {
    1239           8 :         if (ROUTEMAP_NAME(red)) {
    1240           0 :                 route_map_counter_decrement(ROUTEMAP(red));
    1241           0 :                 free(ROUTEMAP_NAME(red));
    1242             :         }
    1243             : 
    1244           8 :         ROUTEMAP_NAME(red) = NULL;
    1245           8 :         ROUTEMAP(red) = NULL;
    1246           8 : }
    1247             : 
    1248           0 : static int ospf_zebra_gr_update(struct ospf *ospf, int command,
    1249             :                                 uint32_t stale_time)
    1250             : {
    1251           0 :         struct zapi_cap api;
    1252             : 
    1253           0 :         if (!zclient || zclient->sock < 0 || !ospf)
    1254             :                 return 1;
    1255             : 
    1256           0 :         memset(&api, 0, sizeof(api));
    1257           0 :         api.cap = command;
    1258           0 :         api.stale_removal_time = stale_time;
    1259           0 :         api.vrf_id = ospf->vrf_id;
    1260             : 
    1261           0 :         (void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient,
    1262             :                                         &api);
    1263             : 
    1264           0 :         return 0;
    1265             : }
    1266             : 
    1267           0 : int ospf_zebra_gr_enable(struct ospf *ospf, uint32_t stale_time)
    1268             : {
    1269           0 :         return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_CAPABILITIES,
    1270             :                                     stale_time);
    1271             : }
    1272             : 
    1273           0 : int ospf_zebra_gr_disable(struct ospf *ospf)
    1274             : {
    1275           0 :         return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_DISABLE, 0);
    1276             : }
    1277             : 
    1278             : /* Zebra route add and delete treatment. */
    1279          64 : static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
    1280             : {
    1281          64 :         struct zapi_route api;
    1282          64 :         struct prefix_ipv4 p;
    1283          64 :         struct prefix pgen;
    1284          64 :         unsigned long ifindex;
    1285          64 :         struct in_addr nexthop;
    1286          64 :         struct external_info *ei;
    1287          64 :         struct ospf *ospf;
    1288          64 :         int i;
    1289          64 :         uint8_t rt_type;
    1290             : 
    1291          64 :         ospf = ospf_lookup_by_vrf_id(vrf_id);
    1292          64 :         if (ospf == NULL)
    1293             :                 return 0;
    1294             : 
    1295          64 :         if (zapi_route_decode(zclient->ibuf, &api) < 0)
    1296             :                 return -1;
    1297             : 
    1298          64 :         ifindex = api.nexthops[0].ifindex;
    1299          64 :         nexthop = api.nexthops[0].gate.ipv4;
    1300          64 :         rt_type = api.type;
    1301             : 
    1302          64 :         memcpy(&p, &api.prefix, sizeof(p));
    1303          64 :         if (IPV4_NET127(ntohl(p.prefix.s_addr)))
    1304             :                 return 0;
    1305             : 
    1306          64 :         pgen.family = p.family;
    1307          64 :         pgen.prefixlen = p.prefixlen;
    1308          64 :         pgen.u.prefix4 = p.prefix;
    1309             : 
    1310             :         /* Re-destributed route is default route.
    1311             :          * Here, route type is used as 'ZEBRA_ROUTE_KERNEL' for
    1312             :          * updating ex-info. But in resetting (no default-info
    1313             :          * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.
    1314             :          * Resolved this inconsistency by maintaining same route type.
    1315             :          */
    1316          64 :         if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF))
    1317           0 :                 rt_type = DEFAULT_ROUTE;
    1318             : 
    1319          64 :         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
    1320           0 :                 zlog_debug("%s: cmd %s from client %s: vrf_id %d, p %pFX",
    1321             :                            __func__, zserv_command_string(cmd),
    1322             :                            zebra_route_string(api.type), vrf_id, &api.prefix);
    1323             : 
    1324          64 :         if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {
    1325             :                 /* XXX|HACK|TODO|FIXME:
    1326             :                  * Maybe we should ignore reject/blackhole routes? Testing
    1327             :                  * shows that there is no problems though and this is only way
    1328             :                  * to "summarize" routes in ASBR at the moment. Maybe we need
    1329             :                  * just a better generalised solution for these types?
    1330             :                  */
    1331             : 
    1332             :                 /* Protocol tag overwrites all other tag value sent by zebra */
    1333          44 :                 if (ospf->dtag[rt_type] > 0)
    1334           0 :                         api.tag = ospf->dtag[rt_type];
    1335             : 
    1336             :                 /*
    1337             :                  * Given zebra sends update for a prefix via ADD message, it
    1338             :                  * should
    1339             :                  * be considered as an implicit DEL for that prefix with other
    1340             :                  * source
    1341             :                  * types.
    1342             :                  */
    1343        1452 :                 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)
    1344        1408 :                         if (i != rt_type)
    1345        1364 :                                 ospf_external_info_delete(ospf, i, api.instance,
    1346             :                                                           p);
    1347             : 
    1348          44 :                 ei = ospf_external_info_add(ospf, rt_type, api.instance, p,
    1349             :                                             ifindex, nexthop, api.tag);
    1350          44 :                 if (ei == NULL) {
    1351             :                         /* Nothing has changed, so nothing to do; return */
    1352             :                         return 0;
    1353             :                 }
    1354          22 :                 if (ospf->router_id.s_addr != INADDR_ANY) {
    1355          22 :                         if (is_default_prefix4(&p))
    1356           0 :                                 ospf_external_lsa_refresh_default(ospf);
    1357             :                         else {
    1358          22 :                                 struct ospf_external_aggr_rt *aggr;
    1359          22 :                                 struct as_external_lsa *al;
    1360          22 :                                 struct ospf_lsa *lsa = NULL;
    1361          22 :                                 struct in_addr mask;
    1362             : 
    1363          22 :                                 aggr = ospf_external_aggr_match(ospf, &ei->p);
    1364             : 
    1365          22 :                                 if (aggr) {
    1366             :                                         /* Check the AS-external-LSA
    1367             :                                          * should be originated.
    1368             :                                          */
    1369           0 :                                         if (!ospf_redistribute_check(ospf, ei,
    1370             :                                                                      NULL))
    1371          18 :                                                 return 0;
    1372             : 
    1373           0 :                                         if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
    1374           0 :                                                 zlog_debug(
    1375             :                                                         "%s: Send Aggreate LSA (%pI4/%d)",
    1376             :                                                         __func__,
    1377             :                                                         &aggr->p.prefix,
    1378             :                                                         aggr->p.prefixlen);
    1379             : 
    1380           0 :                                         ospf_originate_summary_lsa(ospf, aggr,
    1381             :                                                                    ei);
    1382             : 
    1383             :                                         /* Handling the case where the
    1384             :                                          * external route prefix
    1385             :                                          * and aggegate prefix is same
    1386             :                                          * If same don't flush the
    1387             :                                          * originated
    1388             :                                          * external LSA.
    1389             :                                          */
    1390           0 :                                         if (prefix_same(
    1391           0 :                                                     (struct prefix *)&aggr->p,
    1392             :                                                     (struct prefix *)&ei->p))
    1393             :                                                 return 0;
    1394             : 
    1395           0 :                                         lsa = ospf_external_info_find_lsa(
    1396             :                                                 ospf, &ei->p);
    1397             : 
    1398           0 :                                         if (lsa) {
    1399           0 :                                                 al = (struct as_external_lsa *)
    1400             :                                                              lsa->data;
    1401           0 :                                                 masklen2ip(ei->p.prefixlen,
    1402             :                                                            &mask);
    1403             : 
    1404           0 :                                                 if (mask.s_addr
    1405           0 :                                                     != al->mask.s_addr)
    1406             :                                                         return 0;
    1407             : 
    1408           0 :                                                 ospf_external_lsa_flush(
    1409           0 :                                                         ospf, ei->type, &ei->p,
    1410             :                                                         0);
    1411             :                                         }
    1412             :                                 } else {
    1413          22 :                                         struct ospf_lsa *current;
    1414             : 
    1415          22 :                                         current = ospf_external_info_find_lsa(
    1416             :                                                 ospf, &ei->p);
    1417          22 :                                         if (!current) {
    1418             :                                                 /* Check the
    1419             :                                                  * AS-external-LSA
    1420             :                                                  * should be
    1421             :                                                  * originated.
    1422             :                                                  */
    1423          22 :                                                 if (!ospf_redistribute_check(
    1424             :                                                             ospf, ei, NULL))
    1425             :                                                         return 0;
    1426             : 
    1427           4 :                                                 ospf_external_lsa_originate(
    1428             :                                                         ospf, ei);
    1429             :                                         } else {
    1430           0 :                                                 if (IS_DEBUG_OSPF(
    1431             :                                                             zebra,
    1432             :                                                             ZEBRA_REDISTRIBUTE))
    1433           0 :                                                         zlog_debug(
    1434             :                                                                 "%s: %pI4 refreshing LSA",
    1435             :                                                                 __func__,
    1436             :                                                                 &p.prefix);
    1437           0 :                                                 ospf_external_lsa_refresh(
    1438             :                                                         ospf, current, ei,
    1439             :                                                         LSA_REFRESH_FORCE,
    1440             :                                                         false);
    1441             :                                         }
    1442             :                                 }
    1443             :                         }
    1444             :                 }
    1445             : 
    1446             :                 /*
    1447             :                  * Check if default-information originate is
    1448             :                  * with some routemap prefix/access list match.
    1449             :                  */
    1450           4 :                 ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
    1451             : 
    1452             :         } else { /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
    1453          20 :                 struct ospf_external_aggr_rt *aggr;
    1454             : 
    1455          20 :                 ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p);
    1456          20 :                 if (ei == NULL)
    1457             :                         return 0;
    1458             : 
    1459             :                 /*
    1460             :                  * Check if default-information originate i
    1461             :                  * with some routemap prefix/access list match.
    1462             :                  * Apply before ei is deleted.
    1463             :                  */
    1464          10 :                 ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
    1465             : 
    1466          10 :                 aggr = ospf_external_aggr_match(ospf, &ei->p);
    1467             : 
    1468          10 :                 if (aggr && (ei->aggr_route == aggr)) {
    1469           0 :                         ospf_unlink_ei_from_aggr(ospf, aggr, ei);
    1470             : 
    1471           0 :                         ospf_external_info_delete(ospf, rt_type, api.instance,
    1472             :                                                   p);
    1473             :                 } else {
    1474          10 :                         ospf_external_info_delete(ospf, rt_type, api.instance,
    1475             :                                                   p);
    1476             : 
    1477          10 :                         if (is_default_prefix4(&p))
    1478           0 :                                 ospf_external_lsa_refresh_default(ospf);
    1479             :                         else
    1480          10 :                                 ospf_external_lsa_flush(ospf, rt_type, &p,
    1481             :                                                         ifindex /*, nexthop */);
    1482             :                 }
    1483             :         }
    1484             : 
    1485             :         return 0;
    1486             : }
    1487             : 
    1488             : 
    1489           0 : int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name)
    1490             : {
    1491             :         /* Lookup access-list for distribute-list. */
    1492           0 :         DISTRIBUTE_LIST(ospf, type) = access_list_lookup(AFI_IP, name);
    1493             : 
    1494             :         /* Clear previous distribute-name. */
    1495           0 :         if (DISTRIBUTE_NAME(ospf, type))
    1496           0 :                 free(DISTRIBUTE_NAME(ospf, type));
    1497             : 
    1498             :         /* Set distribute-name. */
    1499           0 :         DISTRIBUTE_NAME(ospf, type) = strdup(name);
    1500             : 
    1501             :         /* If access-list have been set, schedule update timer. */
    1502           0 :         if (DISTRIBUTE_LIST(ospf, type))
    1503           0 :                 ospf_distribute_list_update(ospf, type, 0);
    1504             : 
    1505           0 :         return CMD_SUCCESS;
    1506             : }
    1507             : 
    1508           0 : int ospf_distribute_list_out_unset(struct ospf *ospf, int type,
    1509             :                                    const char *name)
    1510             : {
    1511             :         /* Schedule update timer. */
    1512           0 :         if (DISTRIBUTE_LIST(ospf, type))
    1513           0 :                 ospf_distribute_list_update(ospf, type, 0);
    1514             : 
    1515             :         /* Unset distribute-list. */
    1516           0 :         DISTRIBUTE_LIST(ospf, type) = NULL;
    1517             : 
    1518             :         /* Clear distribute-name. */
    1519           0 :         if (DISTRIBUTE_NAME(ospf, type))
    1520           0 :                 free(DISTRIBUTE_NAME(ospf, type));
    1521             : 
    1522           0 :         DISTRIBUTE_NAME(ospf, type) = NULL;
    1523             : 
    1524           0 :         return CMD_SUCCESS;
    1525             : }
    1526             : 
    1527             : /* distribute-list update timer. */
    1528           0 : static void ospf_distribute_list_update_timer(struct thread *thread)
    1529             : {
    1530           0 :         struct route_node *rn;
    1531           0 :         struct external_info *ei;
    1532           0 :         struct route_table *rt;
    1533           0 :         struct ospf_lsa *lsa;
    1534           0 :         int type, default_refresh = 0;
    1535           0 :         struct ospf *ospf = THREAD_ARG(thread);
    1536             : 
    1537           0 :         if (ospf == NULL)
    1538             :                 return;
    1539             : 
    1540           0 :         ospf->t_distribute_update = NULL;
    1541             : 
    1542           0 :         zlog_info("Zebra[Redistribute]: distribute-list update timer fired!");
    1543             : 
    1544           0 :         if (IS_DEBUG_OSPF_EVENT) {
    1545           0 :                 zlog_debug("%s: ospf distribute-list update vrf %s id %d",
    1546             :                            __func__, ospf_vrf_id_to_name(ospf->vrf_id),
    1547             :                            ospf->vrf_id);
    1548             :         }
    1549             : 
    1550             :         /* foreach all external info. */
    1551           0 :         for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
    1552           0 :                 struct list *ext_list;
    1553           0 :                 struct listnode *node;
    1554           0 :                 struct ospf_external *ext;
    1555             : 
    1556           0 :                 ext_list = ospf->external[type];
    1557           0 :                 if (!ext_list)
    1558           0 :                         continue;
    1559             : 
    1560           0 :                 for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) {
    1561           0 :                         rt = ext->external_info;
    1562           0 :                         if (!rt)
    1563           0 :                                 continue;
    1564           0 :                         for (rn = route_top(rt); rn; rn = route_next(rn)) {
    1565           0 :                                 ei = rn->info;
    1566           0 :                                 if (!ei)
    1567           0 :                                         continue;
    1568             : 
    1569           0 :                                 if (is_default_prefix4(&ei->p))
    1570             :                                         default_refresh = 1;
    1571             :                                 else {
    1572           0 :                                         struct ospf_external_aggr_rt *aggr;
    1573             : 
    1574           0 :                                         aggr = ospf_external_aggr_match(ospf,
    1575             :                                                                         &ei->p);
    1576           0 :                                         if (aggr) {
    1577             :                                                 /* Check the
    1578             :                                                  * AS-external-LSA
    1579             :                                                  * should be originated.
    1580             :                                                  */
    1581           0 :                                                 if (!ospf_redistribute_check(
    1582             :                                                             ospf, ei, NULL)) {
    1583             : 
    1584           0 :                                                         ospf_unlink_ei_from_aggr(
    1585             :                                                                 ospf, aggr, ei);
    1586           0 :                                                         continue;
    1587             :                                                 }
    1588             : 
    1589           0 :                                                 if (IS_DEBUG_OSPF(
    1590             :                                                             lsa,
    1591             :                                                             EXTNL_LSA_AGGR))
    1592           0 :                                                         zlog_debug(
    1593             :                                                                 "%s: Send Aggregate LSA (%pI4/%d)",
    1594             :                                                                 __func__,
    1595             :                                                                 &aggr->p.prefix,
    1596             :                                                                 aggr->p.prefixlen);
    1597             : 
    1598             :                                                 /* Originate Aggregate
    1599             :                                                  * LSA
    1600             :                                                  */
    1601           0 :                                                 ospf_originate_summary_lsa(
    1602             :                                                         ospf, aggr, ei);
    1603           0 :                                         } else if (
    1604           0 :                                                 (lsa = ospf_external_info_find_lsa(
    1605             :                                                          ospf, &ei->p))) {
    1606           0 :                                                 int force =
    1607             :                                                         LSA_REFRESH_IF_CHANGED;
    1608             :                                                 /* If this is a MaxAge
    1609             :                                                  * LSA, we need to
    1610             :                                                  * force refresh it
    1611             :                                                  * because distribute
    1612             :                                                  * settings might have
    1613             :                                                  * changed and now,
    1614             :                                                  * this LSA needs to be
    1615             :                                                  * originated, not be
    1616             :                                                  * removed.
    1617             :                                                  * If we don't force
    1618             :                                                  * refresh it, it will
    1619             :                                                  * remain a MaxAge LSA
    1620             :                                                  * because it will look
    1621             :                                                  * like it hasn't
    1622             :                                                  * changed. Neighbors
    1623             :                                                  * will not receive
    1624             :                                                  * updates for this LSA.
    1625             :                                                  */
    1626           0 :                                                 if (IS_LSA_MAXAGE(lsa))
    1627             :                                                         force = LSA_REFRESH_FORCE;
    1628             : 
    1629           0 :                                                 ospf_external_lsa_refresh(
    1630             :                                                         ospf, lsa, ei, force,
    1631             :                                                         false);
    1632             :                                         } else {
    1633           0 :                                                 if (!ospf_redistribute_check(
    1634             :                                                             ospf, ei, NULL))
    1635           0 :                                                         continue;
    1636           0 :                                                 ospf_external_lsa_originate(
    1637             :                                                         ospf, ei);
    1638             :                                         }
    1639             :                                 }
    1640             :                         }
    1641             :                 }
    1642             :         }
    1643           0 :         if (default_refresh)
    1644           0 :                 ospf_external_lsa_refresh_default(ospf);
    1645             : }
    1646             : 
    1647             : /* Update distribute-list and set timer to apply access-list. */
    1648           0 : void ospf_distribute_list_update(struct ospf *ospf, int type,
    1649             :                                  unsigned short instance)
    1650             : {
    1651           0 :         struct ospf_external *ext;
    1652             : 
    1653             :         /* External info does not exist. */
    1654           0 :         ext = ospf_external_lookup(ospf, type, instance);
    1655           0 :         if (!ext || !EXTERNAL_INFO(ext))
    1656             :                 return;
    1657             : 
    1658             :         /* Set timer. If timer is already started, this call does nothing. */
    1659           0 :         thread_add_timer_msec(master, ospf_distribute_list_update_timer, ospf,
    1660             :                               ospf->min_ls_interval,
    1661             :                               &ospf->t_distribute_update);
    1662             : }
    1663             : 
    1664             : /* If access-list is updated, apply some check. */
    1665           0 : static void ospf_filter_update(struct access_list *access)
    1666             : {
    1667           0 :         struct ospf *ospf;
    1668           0 :         int type;
    1669           0 :         int abr_inv = 0;
    1670           0 :         struct ospf_area *area;
    1671           0 :         struct listnode *node, *n1;
    1672             : 
    1673             :         /* If OSPF instance does not exist, return right now. */
    1674           0 :         if (listcount(om->ospf) == 0)
    1675             :                 return;
    1676             : 
    1677             :         /* Iterate all ospf [VRF] instances */
    1678           0 :         for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) {
    1679             :                 /* Update distribute-list, and apply filter. */
    1680           0 :                 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
    1681           0 :                         struct list *red_list;
    1682           0 :                         struct ospf_redist *red;
    1683             : 
    1684           0 :                         red_list = ospf->redist[type];
    1685           0 :                         if (red_list)
    1686           0 :                                 for (ALL_LIST_ELEMENTS_RO(red_list, node,
    1687             :                                                           red)) {
    1688           0 :                                         if (ROUTEMAP(red)) {
    1689             :                                                 /* if route-map is not NULL it
    1690             :                                                  * may be
    1691             :                                                  * using this access list */
    1692           0 :                                                 ospf_distribute_list_update(
    1693             :                                                         ospf, type,
    1694           0 :                                                         red->instance);
    1695             :                                         }
    1696             :                                 }
    1697             : 
    1698             :                         /* There is place for route-map for default-information
    1699             :                          * (ZEBRA_ROUTE_MAX),
    1700             :                          * but no distribute list. */
    1701           0 :                         if (type == ZEBRA_ROUTE_MAX)
    1702             :                                 break;
    1703             : 
    1704           0 :                         if (DISTRIBUTE_NAME(ospf, type)) {
    1705             :                                 /* Keep old access-list for distribute-list. */
    1706           0 :                                 struct access_list *old =
    1707             :                                         DISTRIBUTE_LIST(ospf, type);
    1708             : 
    1709             :                                 /* Update access-list for distribute-list. */
    1710           0 :                                 DISTRIBUTE_LIST(ospf, type) =
    1711           0 :                                         access_list_lookup(
    1712             :                                                 AFI_IP,
    1713             :                                                 DISTRIBUTE_NAME(ospf, type));
    1714             : 
    1715             :                                 /* No update for this distribute type. */
    1716           0 :                                 if (old == NULL
    1717           0 :                                     && DISTRIBUTE_LIST(ospf, type) == NULL)
    1718           0 :                                         continue;
    1719             : 
    1720             :                                 /* Schedule distribute-list update timer. */
    1721           0 :                                 if (DISTRIBUTE_LIST(ospf, type) == NULL
    1722           0 :                                     || strcmp(DISTRIBUTE_NAME(ospf, type),
    1723           0 :                                               access->name)
    1724             :                                                == 0)
    1725           0 :                                         ospf_distribute_list_update(ospf, type,
    1726             :                                                                     0);
    1727             :                         }
    1728             :                 }
    1729             : 
    1730             :                 /* Update Area access-list. */
    1731           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
    1732           0 :                         if (EXPORT_NAME(area)) {
    1733           0 :                                 EXPORT_LIST(area) = NULL;
    1734           0 :                                 abr_inv++;
    1735             :                         }
    1736             : 
    1737           0 :                         if (IMPORT_NAME(area)) {
    1738           0 :                                 IMPORT_LIST(area) = NULL;
    1739           0 :                                 abr_inv++;
    1740             :                         }
    1741             :                 }
    1742             : 
    1743             :                 /* Schedule ABR tasks -- this will be changed -- takada. */
    1744           0 :                 if (IS_OSPF_ABR(ospf) && abr_inv)
    1745           0 :                         ospf_schedule_abr_task(ospf);
    1746             :         }
    1747             : }
    1748             : 
    1749             : /* If prefix-list is updated, do some updates. */
    1750           0 : static void ospf_prefix_list_update(struct prefix_list *plist)
    1751             : {
    1752           0 :         struct ospf *ospf = NULL;
    1753           0 :         int type;
    1754           0 :         int abr_inv = 0;
    1755           0 :         struct ospf_area *area;
    1756           0 :         struct listnode *node, *n1;
    1757             : 
    1758             :         /* If OSPF instatnce does not exist, return right now. */
    1759           0 :         if (listcount(om->ospf) == 0)
    1760             :                 return;
    1761             : 
    1762             :         /* Iterate all ospf [VRF] instances */
    1763           0 :         for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) {
    1764             : 
    1765             :                 /* Update all route-maps which are used
    1766             :                  * as redistribution filters.
    1767             :                  * They might use prefix-list.
    1768             :                  */
    1769           0 :                 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
    1770           0 :                         struct list *red_list;
    1771           0 :                         struct ospf_redist *red;
    1772             : 
    1773           0 :                         red_list = ospf->redist[type];
    1774           0 :                         if (!red_list)
    1775           0 :                                 continue;
    1776             : 
    1777           0 :                         for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
    1778           0 :                                 if (ROUTEMAP(red)) {
    1779             :                                         /* if route-map is not NULL
    1780             :                                          * it may be using
    1781             :                                          * this prefix list */
    1782           0 :                                         ospf_distribute_list_update(
    1783           0 :                                                 ospf, type, red->instance);
    1784             :                                 }
    1785             :                         }
    1786             :                 }
    1787             : 
    1788             :                 /* Update area filter-lists. */
    1789           0 :                 for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
    1790             :                         /* Update filter-list in. */
    1791           0 :                         if (PREFIX_NAME_IN(area)
    1792           0 :                             && strcmp(PREFIX_NAME_IN(area),
    1793             :                                       prefix_list_name(plist))
    1794             :                                        == 0) {
    1795           0 :                                 PREFIX_LIST_IN(area) = prefix_list_lookup(
    1796             :                                         AFI_IP, PREFIX_NAME_IN(area));
    1797           0 :                                 abr_inv++;
    1798             :                         }
    1799             : 
    1800             :                         /* Update filter-list out. */
    1801           0 :                         if (PREFIX_NAME_OUT(area)
    1802           0 :                             && strcmp(PREFIX_NAME_OUT(area),
    1803             :                                       prefix_list_name(plist))
    1804             :                                        == 0) {
    1805           0 :                                 PREFIX_LIST_IN(area) = prefix_list_lookup(
    1806             :                                         AFI_IP, PREFIX_NAME_OUT(area));
    1807           0 :                                 abr_inv++;
    1808             :                         }
    1809             :                 }
    1810             : 
    1811             :                 /* Schedule ABR task. */
    1812           0 :                 if (IS_OSPF_ABR(ospf) && abr_inv)
    1813           0 :                         ospf_schedule_abr_task(ospf);
    1814             :         }
    1815             : }
    1816             : 
    1817           0 : static struct ospf_distance *ospf_distance_new(void)
    1818             : {
    1819           0 :         return XCALLOC(MTYPE_OSPF_DISTANCE, sizeof(struct ospf_distance));
    1820             : }
    1821             : 
    1822           0 : static void ospf_distance_free(struct ospf_distance *odistance)
    1823             : {
    1824           0 :         XFREE(MTYPE_OSPF_DISTANCE, odistance);
    1825             : }
    1826             : 
    1827           0 : int ospf_distance_set(struct vty *vty, struct ospf *ospf,
    1828             :                       const char *distance_str, const char *ip_str,
    1829             :                       const char *access_list_str)
    1830             : {
    1831           0 :         int ret;
    1832           0 :         struct prefix_ipv4 p;
    1833           0 :         uint8_t distance;
    1834           0 :         struct route_node *rn;
    1835           0 :         struct ospf_distance *odistance;
    1836             : 
    1837           0 :         ret = str2prefix_ipv4(ip_str, &p);
    1838           0 :         if (ret == 0) {
    1839           0 :                 vty_out(vty, "Malformed prefix\n");
    1840           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1841             :         }
    1842             : 
    1843           0 :         distance = atoi(distance_str);
    1844             : 
    1845             :         /* Get OSPF distance node. */
    1846           0 :         rn = route_node_get(ospf->distance_table, (struct prefix *)&p);
    1847           0 :         if (rn->info) {
    1848           0 :                 odistance = rn->info;
    1849           0 :                 route_unlock_node(rn);
    1850             :         } else {
    1851           0 :                 odistance = ospf_distance_new();
    1852           0 :                 rn->info = odistance;
    1853             :         }
    1854             : 
    1855             :         /* Set distance value. */
    1856           0 :         odistance->distance = distance;
    1857             : 
    1858             :         /* Reset access-list configuration. */
    1859           0 :         if (odistance->access_list) {
    1860           0 :                 free(odistance->access_list);
    1861           0 :                 odistance->access_list = NULL;
    1862             :         }
    1863           0 :         if (access_list_str)
    1864           0 :                 odistance->access_list = strdup(access_list_str);
    1865             : 
    1866             :         return CMD_SUCCESS;
    1867             : }
    1868             : 
    1869           0 : int ospf_distance_unset(struct vty *vty, struct ospf *ospf,
    1870             :                         const char *distance_str, const char *ip_str,
    1871             :                         char const *access_list_str)
    1872             : {
    1873           0 :         int ret;
    1874           0 :         struct prefix_ipv4 p;
    1875           0 :         struct route_node *rn;
    1876           0 :         struct ospf_distance *odistance;
    1877             : 
    1878           0 :         ret = str2prefix_ipv4(ip_str, &p);
    1879           0 :         if (ret == 0) {
    1880           0 :                 vty_out(vty, "Malformed prefix\n");
    1881           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1882             :         }
    1883             : 
    1884           0 :         rn = route_node_lookup(ospf->distance_table, (struct prefix *)&p);
    1885           0 :         if (!rn) {
    1886           0 :                 vty_out(vty, "Can't find specified prefix\n");
    1887           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1888             :         }
    1889             : 
    1890           0 :         odistance = rn->info;
    1891             : 
    1892           0 :         if (odistance->access_list)
    1893           0 :                 free(odistance->access_list);
    1894           0 :         ospf_distance_free(odistance);
    1895             : 
    1896           0 :         rn->info = NULL;
    1897           0 :         route_unlock_node(rn);
    1898           0 :         route_unlock_node(rn);
    1899             : 
    1900           0 :         return CMD_SUCCESS;
    1901             : }
    1902             : 
    1903           4 : void ospf_distance_reset(struct ospf *ospf)
    1904             : {
    1905           4 :         struct route_node *rn;
    1906           4 :         struct ospf_distance *odistance;
    1907             : 
    1908           4 :         for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) {
    1909           0 :                 odistance = rn->info;
    1910           0 :                 if (!odistance)
    1911           0 :                         continue;
    1912             : 
    1913           0 :                 if (odistance->access_list)
    1914           0 :                         free(odistance->access_list);
    1915           0 :                 ospf_distance_free(odistance);
    1916           0 :                 rn->info = NULL;
    1917           0 :                 route_unlock_node(rn);
    1918             :         }
    1919           4 : }
    1920             : 
    1921          50 : uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p,
    1922             :                             struct ospf_route * or)
    1923             : {
    1924             : 
    1925          50 :         if (ospf == NULL)
    1926             :                 return 0;
    1927             : 
    1928          50 :         if (ospf->distance_intra && or->path_type == OSPF_PATH_INTRA_AREA)
    1929             :                 return ospf->distance_intra;
    1930             : 
    1931          50 :         if (ospf->distance_inter && or->path_type == OSPF_PATH_INTER_AREA)
    1932             :                 return ospf->distance_inter;
    1933             : 
    1934          50 :         if (ospf->distance_external
    1935           0 :             && (or->path_type == OSPF_PATH_TYPE1_EXTERNAL ||
    1936             :                 or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
    1937             :                 return ospf->distance_external;
    1938             : 
    1939          50 :         if (ospf->distance_all)
    1940             :                 return ospf->distance_all;
    1941             : 
    1942             :         return 0;
    1943             : }
    1944             : 
    1945           4 : void ospf_zebra_vrf_register(struct ospf *ospf)
    1946             : {
    1947           4 :         if (!zclient || zclient->sock < 0 || !ospf)
    1948             :                 return;
    1949             : 
    1950           4 :         if (ospf->vrf_id != VRF_UNKNOWN) {
    1951           4 :                 if (IS_DEBUG_OSPF_EVENT)
    1952           4 :                         zlog_debug("%s: Register VRF %s id %u", __func__,
    1953             :                                    ospf_vrf_id_to_name(ospf->vrf_id),
    1954             :                                    ospf->vrf_id);
    1955           4 :                 zclient_send_reg_requests(zclient, ospf->vrf_id);
    1956             :         }
    1957             : }
    1958             : 
    1959           4 : void ospf_zebra_vrf_deregister(struct ospf *ospf)
    1960             : {
    1961           4 :         if (!zclient || zclient->sock < 0 || !ospf)
    1962             :                 return;
    1963             : 
    1964           4 :         if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) {
    1965           0 :                 if (IS_DEBUG_OSPF_EVENT)
    1966           0 :                         zlog_debug("%s: De-Register VRF %s id %u to Zebra.",
    1967             :                                    __func__, ospf_vrf_id_to_name(ospf->vrf_id),
    1968             :                                    ospf->vrf_id);
    1969             :                 /* Deregister for router-id, interfaces,
    1970             :                  * redistributed routes. */
    1971           0 :                 zclient_send_dereg_requests(zclient, ospf->vrf_id);
    1972             :         }
    1973             : }
    1974             : 
    1975             : /* Label Manager Functions */
    1976             : 
    1977             : /**
    1978             :  * Check if Label Manager is Ready or not.
    1979             :  *
    1980             :  * @return      True if Label Manager is ready, False otherwise
    1981             :  */
    1982           0 : bool ospf_zebra_label_manager_ready(void)
    1983             : {
    1984           0 :         return (zclient_sync->sock > 0);
    1985             : }
    1986             : 
    1987             : /**
    1988             :  * Request Label Range to the Label Manager.
    1989             :  *
    1990             :  * @param base          base label of the label range to request
    1991             :  * @param chunk_size    size of the label range to request
    1992             :  *
    1993             :  * @return      0 on success, -1 on failure
    1994             :  */
    1995           0 : int ospf_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
    1996             : {
    1997           0 :         int ret;
    1998           0 :         uint32_t start, end;
    1999             : 
    2000           0 :         if (zclient_sync->sock < 0)
    2001             :                 return -1;
    2002             : 
    2003           0 :         ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,
    2004             :                                  &end);
    2005           0 :         if (ret < 0) {
    2006           0 :                 zlog_warn("%s: error getting label range!", __func__);
    2007           0 :                 return -1;
    2008             :         }
    2009             : 
    2010             :         return 0;
    2011             : }
    2012             : 
    2013             : /**
    2014             :  * Release Label Range to the Label Manager.
    2015             :  *
    2016             :  * @param start         start of label range to release
    2017             :  * @param end           end of label range to release
    2018             :  *
    2019             :  * @return              0 on success, -1 otherwise
    2020             :  */
    2021           0 : int ospf_zebra_release_label_range(uint32_t start, uint32_t end)
    2022             : {
    2023           0 :         int ret;
    2024             : 
    2025           0 :         if (zclient_sync->sock < 0)
    2026             :                 return -1;
    2027             : 
    2028           0 :         ret = lm_release_label_chunk(zclient_sync, start, end);
    2029           0 :         if (ret < 0) {
    2030           0 :                 zlog_warn("%s: error releasing label range!", __func__);
    2031           0 :                 return -1;
    2032             :         }
    2033             : 
    2034             :         return 0;
    2035             : }
    2036             : 
    2037             : /**
    2038             :  * Connect to the Label Manager.
    2039             :  *
    2040             :  * @return      0 on success, -1 otherwise
    2041             :  */
    2042           0 : int ospf_zebra_label_manager_connect(void)
    2043             : {
    2044             :         /* Connect to label manager. */
    2045           0 :         if (zclient_socket_connect(zclient_sync) < 0) {
    2046           0 :                 zlog_warn("%s: failed connecting synchronous zclient!",
    2047             :                           __func__);
    2048           0 :                 return -1;
    2049             :         }
    2050             :         /* make socket non-blocking */
    2051           0 :         set_nonblocking(zclient_sync->sock);
    2052             : 
    2053             :         /* Send hello to notify zebra this is a synchronous client */
    2054           0 :         if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) {
    2055           0 :                 zlog_warn("%s: failed sending hello for synchronous zclient!",
    2056             :                           __func__);
    2057           0 :                 close(zclient_sync->sock);
    2058           0 :                 zclient_sync->sock = -1;
    2059           0 :                 return -1;
    2060             :         }
    2061             : 
    2062             :         /* Connect to label manager */
    2063           0 :         if (lm_label_manager_connect(zclient_sync, 0) != 0) {
    2064           0 :                 zlog_warn("%s: failed connecting to label manager!", __func__);
    2065           0 :                 if (zclient_sync->sock > 0) {
    2066           0 :                         close(zclient_sync->sock);
    2067           0 :                         zclient_sync->sock = -1;
    2068             :                 }
    2069           0 :                 return -1;
    2070             :         }
    2071             : 
    2072           0 :         osr_debug("SR (%s): Successfully connected to the Label Manager",
    2073             :                   __func__);
    2074             : 
    2075             :         return 0;
    2076             : }
    2077             : 
    2078           4 : static void ospf_zebra_connected(struct zclient *zclient)
    2079             : {
    2080             :         /* Send the client registration */
    2081           4 :         bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
    2082             : 
    2083           4 :         zclient_send_reg_requests(zclient, VRF_DEFAULT);
    2084           4 : }
    2085             : 
    2086             : /*
    2087             :  * opaque messages between processes
    2088             :  */
    2089           0 : static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS)
    2090             : {
    2091           0 :         struct stream *s;
    2092           0 :         struct zapi_opaque_msg info;
    2093           0 :         struct ldp_igp_sync_if_state state;
    2094           0 :         struct ldp_igp_sync_announce announce;
    2095           0 :         struct zapi_opaque_reg_info dst;
    2096           0 :         int ret = 0;
    2097             : 
    2098           0 :         s = zclient->ibuf;
    2099             : 
    2100           0 :         if (zclient_opaque_decode(s, &info) != 0)
    2101             :                 return -1;
    2102             : 
    2103           0 :         switch (info.type) {
    2104           0 :         case LINK_STATE_SYNC:
    2105           0 :                 STREAM_GETC(s, dst.proto);
    2106           0 :                 STREAM_GETW(s, dst.instance);
    2107           0 :                 STREAM_GETL(s, dst.session_id);
    2108           0 :                 dst.type = LINK_STATE_SYNC;
    2109           0 :                 ret = ospf_te_sync_ted(dst);
    2110           0 :                 break;
    2111           0 :         case LDP_IGP_SYNC_IF_STATE_UPDATE:
    2112           0 :                 STREAM_GET(&state, s, sizeof(state));
    2113           0 :                 ret = ospf_ldp_sync_state_update(state);
    2114           0 :                 break;
    2115           0 :         case LDP_IGP_SYNC_ANNOUNCE_UPDATE:
    2116           0 :                 STREAM_GET(&announce, s, sizeof(announce));
    2117           0 :                 ret = ospf_ldp_sync_announce_update(announce);
    2118           0 :                 break;
    2119             :         default:
    2120             :                 break;
    2121             :         }
    2122             : 
    2123             : stream_failure:
    2124             : 
    2125             :         return ret;
    2126             : }
    2127             : 
    2128           0 : static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)
    2129             : {
    2130           0 :         int ret = 0;
    2131             : 
    2132           0 :         struct zapi_client_close_info info;
    2133             : 
    2134           0 :         if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)
    2135             :                 return -1;
    2136             : 
    2137           0 :         ospf_ldp_sync_handle_client_close(&info);
    2138             : 
    2139           0 :         return ret;
    2140             : }
    2141             : 
    2142             : static zclient_handler *const ospf_handlers[] = {
    2143             :         [ZEBRA_ROUTER_ID_UPDATE] = ospf_router_id_update_zebra,
    2144             :         [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf_interface_address_add,
    2145             :         [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf_interface_address_delete,
    2146             :         [ZEBRA_INTERFACE_LINK_PARAMS] = ospf_interface_link_params,
    2147             :         [ZEBRA_INTERFACE_VRF_UPDATE] = ospf_interface_vrf_update,
    2148             : 
    2149             :         [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route,
    2150             :         [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route,
    2151             : 
    2152             :         [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler,
    2153             : 
    2154             :         [ZEBRA_CLIENT_CLOSE_NOTIFY] = ospf_zebra_client_close_notify,
    2155             : };
    2156             : 
    2157           4 : void ospf_zebra_init(struct thread_master *master, unsigned short instance)
    2158             : {
    2159             :         /* Allocate zebra structure. */
    2160           4 :         zclient = zclient_new(master, &zclient_options_default, ospf_handlers,
    2161             :                               array_size(ospf_handlers));
    2162           4 :         zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);
    2163           4 :         zclient->zebra_connected = ospf_zebra_connected;
    2164             : 
    2165             :         /* Initialize special zclient for synchronous message exchanges. */
    2166           4 :         struct zclient_options options = zclient_options_default;
    2167           4 :         options.synchronous = true;
    2168           4 :         zclient_sync = zclient_new(master, &options, NULL, 0);
    2169           4 :         zclient_sync->sock = -1;
    2170           4 :         zclient_sync->redist_default = ZEBRA_ROUTE_OSPF;
    2171           4 :         zclient_sync->instance = instance;
    2172             :         /*
    2173             :          * session_id must be different from default value (0) to distinguish
    2174             :          * the asynchronous socket from the synchronous one
    2175             :          */
    2176           4 :         zclient_sync->session_id = 1;
    2177           4 :         zclient_sync->privs = &ospfd_privs;
    2178             : 
    2179           4 :         access_list_add_hook(ospf_filter_update);
    2180           4 :         access_list_delete_hook(ospf_filter_update);
    2181           4 :         prefix_list_add_hook(ospf_prefix_list_update);
    2182           4 :         prefix_list_delete_hook(ospf_prefix_list_update);
    2183           4 : }
    2184             : 
    2185          31 : void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p)
    2186             : {
    2187          31 :         zclient_send_neigh_discovery_req(zclient, ifp, p);
    2188          31 : }

Generated by: LCOV version v1.16-topotato