back to topotato report
topotato coverage report
Current view: top level - ospf6d - ospf6_interface.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 587 1639 35.8 %
Date: 2023-02-24 19:38:44 Functions: 52 98 53.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 Yasuhiro Ohara
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "memory.h"
      24             : #include "if.h"
      25             : #include "log.h"
      26             : #include "command.h"
      27             : #include "thread.h"
      28             : #include "prefix.h"
      29             : #include "plist.h"
      30             : #include "zclient.h"
      31             : #include "printfrr.h"
      32             : 
      33             : #include "ospf6_lsa.h"
      34             : #include "ospf6_lsdb.h"
      35             : #include "ospf6_top.h"
      36             : #include "ospf6_network.h"
      37             : #include "ospf6_message.h"
      38             : #include "ospf6_route.h"
      39             : #include "ospf6_area.h"
      40             : #include "ospf6_abr.h"
      41             : #include "ospf6_nssa.h"
      42             : #include "ospf6_interface.h"
      43             : #include "ospf6_neighbor.h"
      44             : #include "ospf6_intra.h"
      45             : #include "ospf6_spf.h"
      46             : #include "ospf6d.h"
      47             : #include "ospf6_bfd.h"
      48             : #include "ospf6_zebra.h"
      49             : #include "ospf6_gr.h"
      50             : #include "lib/json.h"
      51             : #include "ospf6_proto.h"
      52             : #include "lib/keychain.h"
      53             : #include "ospf6_auth_trailer.h"
      54             : 
      55          48 : DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_IF, "OSPF6 interface");
      56          48 : DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_KEYCHAIN, "OSPF6 auth keychain");
      57          48 : DEFINE_MTYPE(OSPF6D, OSPF6_AUTH_MANUAL_KEY, "OSPF6 auth key");
      58          48 : DEFINE_MTYPE_STATIC(OSPF6D, CFG_PLIST_NAME, "configured prefix list names");
      59             : DEFINE_QOBJ_TYPE(ospf6_interface);
      60          91 : DEFINE_HOOK(ospf6_interface_change,
      61             :             (struct ospf6_interface * oi, int state, int old_state),
      62             :             (oi, state, old_state));
      63             : 
      64             : unsigned char conf_debug_ospf6_interface = 0;
      65             : 
      66             : const char *const ospf6_interface_state_str[] = {
      67             :         "None",               "Down",              "Loopback", "Waiting", "PointToPoint",
      68             :         "PtMultipoint", "VirtualLink", "DROther",  "BDR",     "DR",
      69             :         NULL
      70             : };
      71             : 
      72          16 : printfrr_ext_autoreg_p("OI", printfrr_oi);
      73          37 : static ssize_t printfrr_oi(struct fbuf *buf, struct printfrr_eargs *ea,
      74             :                            const void *ptr)
      75             : {
      76          37 :         const struct ospf6_interface *oi = ptr;
      77             : 
      78          37 :         if (!oi)
      79           0 :                 return bputs(buf, "(null)");
      80          74 :         return bputs(buf, ospf6_ifname(oi));
      81             : }
      82             : 
      83         170 : int ospf6_interface_neighbor_count(struct ospf6_interface *oi)
      84             : {
      85         170 :         int count = 0;
      86         170 :         struct ospf6_neighbor *nbr = NULL;
      87         170 :         struct listnode *node;
      88             : 
      89         372 :         for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, nbr)) {
      90             :                 /* Down state is not shown. */
      91          32 :                 if (nbr->state == OSPF6_NEIGHBOR_DOWN)
      92           0 :                         continue;
      93          32 :                 count++;
      94             :         }
      95             : 
      96         170 :         return count;
      97             : }
      98             : 
      99        1217 : struct ospf6_interface *ospf6_interface_lookup_by_ifindex(ifindex_t ifindex,
     100             :                                                           vrf_id_t vrf_id)
     101             : {
     102        1217 :         struct ospf6_interface *oi;
     103        1217 :         struct interface *ifp;
     104             : 
     105        1217 :         ifp = if_lookup_by_index(ifindex, vrf_id);
     106        1217 :         if (ifp == NULL)
     107             :                 return (struct ospf6_interface *)NULL;
     108             : 
     109        1167 :         oi = (struct ospf6_interface *)ifp->info;
     110        1167 :         return oi;
     111             : }
     112             : 
     113             : /* schedule routing table recalculation */
     114         164 : static void ospf6_interface_lsdb_hook(struct ospf6_lsa *lsa,
     115             :                                       unsigned int reason)
     116             : {
     117         164 :         struct ospf6_interface *oi;
     118             : 
     119         164 :         if (lsa == NULL)
     120             :                 return;
     121             : 
     122         164 :         oi = lsa->lsdb->data;
     123         164 :         switch (ntohs(lsa->header->type)) {
     124         164 :         case OSPF6_LSTYPE_LINK:
     125         164 :                 if (oi->state == OSPF6_INTERFACE_DR)
     126          20 :                         OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
     127         164 :                 if (oi->area)
     128         164 :                         ospf6_spf_schedule(oi->area->ospf6, reason);
     129             :                 break;
     130             : 
     131             :         default:
     132             :                 break;
     133             :         }
     134             : }
     135             : 
     136          70 : static void ospf6_interface_lsdb_hook_add(struct ospf6_lsa *lsa)
     137             : {
     138          70 :         ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
     139          70 : }
     140             : 
     141          94 : static void ospf6_interface_lsdb_hook_remove(struct ospf6_lsa *lsa)
     142             : {
     143          94 :         ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
     144          94 : }
     145             : 
     146          55 : static uint8_t ospf6_default_iftype(struct interface *ifp)
     147             : {
     148          55 :         if (if_is_pointopoint(ifp))
     149             :                 return OSPF_IFTYPE_POINTOPOINT;
     150          55 :         else if (if_is_loopback(ifp))
     151             :                 return OSPF_IFTYPE_LOOPBACK;
     152             :         else
     153          55 :                 return OSPF_IFTYPE_BROADCAST;
     154             : }
     155             : 
     156         145 : static uint32_t ospf6_interface_get_cost(struct ospf6_interface *oi)
     157             : {
     158             :         /* If all else fails, use default OSPF cost */
     159         145 :         uint32_t cost;
     160         145 :         uint32_t bw, refbw;
     161         145 :         struct ospf6 *ospf6;
     162             :         /* interface speed and bw can be 0 in some platforms,
     163             :          * use ospf default bw. If bw is configured then it would
     164             :          * be used.
     165             :          */
     166         145 :         if (!oi->interface->bandwidth && oi->interface->speed) {
     167             :                 bw = oi->interface->speed;
     168             :         } else {
     169          29 :                 bw = oi->interface->bandwidth ? oi->interface->bandwidth
     170          29 :                                               : OSPF6_INTERFACE_BANDWIDTH;
     171             :         }
     172             : 
     173         145 :         ospf6 = oi->interface->vrf->info;
     174         145 :         refbw = ospf6 ? ospf6->ref_bandwidth : OSPF6_REFERENCE_BANDWIDTH;
     175             : 
     176             :         /* A specified ip ospf cost overrides a calculated one. */
     177         145 :         if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
     178           0 :                 cost = oi->cost;
     179             :         else {
     180         145 :                 cost = (uint32_t)((double)refbw / (double)bw + (double)0.5);
     181         145 :                 if (cost < 1)
     182             :                         cost = 1;
     183             :         }
     184             : 
     185         145 :         return cost;
     186             : }
     187             : 
     188           0 : static void ospf6_interface_force_recalculate_cost(struct ospf6_interface *oi)
     189             : {
     190             :         /* update cost held in route_connected list in ospf6_interface */
     191           0 :         ospf6_interface_connected_route_update(oi->interface);
     192             : 
     193             :         /* execute LSA hooks */
     194           0 :         if (oi->area) {
     195           0 :                 OSPF6_LINK_LSA_SCHEDULE(oi);
     196           0 :                 OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
     197           0 :                 OSPF6_NETWORK_LSA_SCHEDULE(oi);
     198           0 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
     199           0 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
     200             :         }
     201           0 : }
     202             : 
     203         116 : static void ospf6_interface_recalculate_cost(struct ospf6_interface *oi)
     204             : {
     205         116 :         uint32_t newcost;
     206             : 
     207         116 :         newcost = ospf6_interface_get_cost(oi);
     208         116 :         if (newcost == oi->cost)
     209             :                 return;
     210           0 :         oi->cost = newcost;
     211             : 
     212           0 :         ospf6_interface_force_recalculate_cost(oi);
     213             : }
     214             : 
     215             : /* Create new ospf6 interface structure */
     216          29 : struct ospf6_interface *ospf6_interface_basic_create(struct interface *ifp)
     217             : {
     218          29 :         struct ospf6_interface *oi;
     219             : 
     220          29 :         oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
     221             : 
     222          29 :         oi->obuf = ospf6_fifo_new();
     223             : 
     224          29 :         oi->area = (struct ospf6_area *)NULL;
     225          29 :         oi->neighbor_list = list_new();
     226          29 :         oi->neighbor_list->cmp = ospf6_neighbor_cmp;
     227          29 :         oi->linklocal_addr = (struct in6_addr *)NULL;
     228          29 :         oi->instance_id = OSPF6_INTERFACE_INSTANCE_ID;
     229          29 :         oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
     230          29 :         oi->priority = OSPF6_INTERFACE_PRIORITY;
     231             : 
     232          29 :         oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
     233          29 :         oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
     234          29 :         oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
     235          29 :         oi->type = ospf6_default_iftype(ifp);
     236          29 :         oi->state = OSPF6_INTERFACE_DOWN;
     237          29 :         oi->flag = 0;
     238          29 :         oi->mtu_ignore = 0;
     239          29 :         oi->c_ifmtu = 0;
     240             : 
     241          58 :         oi->route_connected =
     242          29 :                 OSPF6_ROUTE_TABLE_CREATE(INTERFACE, CONNECTED_ROUTES);
     243          29 :         oi->route_connected->scope = oi;
     244             : 
     245             :         /* link both */
     246          29 :         oi->interface = ifp;
     247          29 :         ifp->info = oi;
     248             : 
     249          29 :         return oi;
     250             : }
     251             : 
     252          29 : struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
     253             : {
     254          29 :         struct ospf6_interface *oi = ospf6_interface_basic_create(ifp);
     255          29 :         unsigned int iobuflen;
     256             : 
     257             :         /* Try to adjust I/O buffer size with IfMtu */
     258          29 :         oi->ifmtu = ifp->mtu6;
     259          29 :         iobuflen = ospf6_iobuf_size(ifp->mtu6);
     260          29 :         if (oi->ifmtu > iobuflen) {
     261           0 :                 if (IS_OSPF6_DEBUG_INTERFACE)
     262           0 :                         zlog_debug(
     263             :                                 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
     264             :                                 ifp->name, iobuflen);
     265           0 :                 oi->ifmtu = iobuflen;
     266             :         }
     267             : 
     268          29 :         QOBJ_REG(oi, ospf6_interface);
     269             : 
     270          29 :         oi->lsupdate_list = ospf6_lsdb_create(oi);
     271          29 :         oi->lsack_list = ospf6_lsdb_create(oi);
     272          29 :         oi->lsdb = ospf6_lsdb_create(oi);
     273          29 :         oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
     274          29 :         oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
     275          29 :         oi->lsdb_self = ospf6_lsdb_create(oi);
     276             : 
     277             :         /* Compute cost. */
     278          29 :         oi->cost = ospf6_interface_get_cost(oi);
     279             : 
     280          29 :         oi->at_data.flags = 0;
     281             : 
     282          29 :         return oi;
     283             : }
     284             : 
     285          29 : void ospf6_interface_delete(struct ospf6_interface *oi)
     286             : {
     287          29 :         QOBJ_UNREG(oi);
     288             : 
     289          29 :         THREAD_OFF(oi->thread_send_hello);
     290          29 :         THREAD_OFF(oi->thread_send_lsupdate);
     291          29 :         THREAD_OFF(oi->thread_send_lsack);
     292          29 :         THREAD_OFF(oi->thread_sso);
     293          29 :         THREAD_OFF(oi->thread_wait_timer);
     294             : 
     295          29 :         ospf6_lsdb_remove_all(oi->lsdb);
     296          29 :         ospf6_lsdb_remove_all(oi->lsupdate_list);
     297          29 :         ospf6_lsdb_remove_all(oi->lsack_list);
     298             : 
     299          29 :         ospf6_lsdb_delete(oi->lsdb);
     300          29 :         ospf6_lsdb_delete(oi->lsdb_self);
     301             : 
     302          29 :         ospf6_lsdb_delete(oi->lsupdate_list);
     303          29 :         ospf6_lsdb_delete(oi->lsack_list);
     304             : 
     305          29 :         ospf6_interface_basic_delete(oi);
     306          29 : }
     307             : 
     308          29 : void ospf6_interface_basic_delete(struct ospf6_interface *oi)
     309             : {
     310          29 :         struct listnode *node, *nnode;
     311          29 :         struct ospf6_neighbor *on;
     312             : 
     313          29 :         ospf6_route_table_delete(oi->route_connected);
     314             : 
     315          58 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
     316           0 :                 ospf6_neighbor_delete(on);
     317             : 
     318          29 :         list_delete(&oi->neighbor_list);
     319             : 
     320          29 :         ospf6_fifo_free(oi->obuf);
     321             : 
     322             :         /* cut link */
     323          29 :         oi->interface->info = NULL;
     324             : 
     325             :         /* plist_name */
     326          29 :         if (oi->plist_name)
     327           0 :                 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
     328             : 
     329             :         /* disable from area list if possible */
     330          29 :         ospf6_area_interface_delete(oi);
     331             : 
     332          29 :         if (oi->at_data.auth_key)
     333           0 :                 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
     334             : 
     335             :         /* Free BFD allocated data. */
     336          29 :         XFREE(MTYPE_TMP, oi->bfd_config.profile);
     337             : 
     338          29 :         XFREE(MTYPE_OSPF6_IF, oi);
     339          29 : }
     340             : 
     341          29 : void ospf6_interface_enable(struct ospf6_interface *oi)
     342             : {
     343          29 :         UNSET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
     344             : 
     345          29 :         if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
     346             :                 return;
     347             : 
     348          29 :         ospf6_interface_state_update(oi->interface);
     349             : }
     350             : 
     351          29 : void ospf6_interface_disable(struct ospf6_interface *oi)
     352             : {
     353          29 :         SET_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE);
     354             : 
     355          29 :         if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
     356             :                 return;
     357             : 
     358          29 :         thread_execute(master, interface_down, oi, 0);
     359             : 
     360          29 :         ospf6_lsdb_remove_all(oi->lsdb);
     361          29 :         ospf6_lsdb_remove_all(oi->lsdb_self);
     362          29 :         ospf6_lsdb_remove_all(oi->lsupdate_list);
     363          29 :         ospf6_lsdb_remove_all(oi->lsack_list);
     364             : 
     365          29 :         THREAD_OFF(oi->thread_send_hello);
     366          29 :         THREAD_OFF(oi->thread_send_lsupdate);
     367          29 :         THREAD_OFF(oi->thread_send_lsack);
     368          29 :         THREAD_OFF(oi->thread_sso);
     369             : 
     370          29 :         THREAD_OFF(oi->thread_network_lsa);
     371          29 :         THREAD_OFF(oi->thread_link_lsa);
     372          29 :         THREAD_OFF(oi->thread_intra_prefix_lsa);
     373          29 :         THREAD_OFF(oi->thread_as_extern_lsa);
     374          29 :         THREAD_OFF(oi->thread_wait_timer);
     375             : }
     376             : 
     377             : static struct in6_addr *
     378         263 : ospf6_interface_get_linklocal_address(struct interface *ifp)
     379             : {
     380         263 :         struct listnode *n;
     381         263 :         struct connected *c;
     382         263 :         struct in6_addr *l = (struct in6_addr *)NULL;
     383             : 
     384             :         /* for each connected address */
     385        1046 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
     386             :                 /* if family not AF_INET6, ignore */
     387         520 :                 if (c->address->family != AF_INET6)
     388         245 :                         continue;
     389             : 
     390             :                 /* linklocal scope check */
     391         275 :                 if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
     392         119 :                         l = &c->address->u.prefix6;
     393             :         }
     394         263 :         return l;
     395             : }
     396             : 
     397         215 : void ospf6_interface_state_update(struct interface *ifp)
     398             : {
     399         215 :         struct ospf6_interface *oi;
     400         215 :         unsigned int iobuflen;
     401             : 
     402         215 :         oi = (struct ospf6_interface *)ifp->info;
     403         215 :         if (oi == NULL)
     404             :                 return;
     405         167 :         if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
     406             :                 return;
     407             : 
     408             :         /* Adjust the mtu values if the kernel told us something new */
     409         167 :         if (ifp->mtu6 != oi->ifmtu) {
     410             :                 /* If nothing configured, accept it and check for buffer size */
     411          29 :                 if (!oi->c_ifmtu) {
     412          29 :                         oi->ifmtu = ifp->mtu6;
     413          29 :                         iobuflen = ospf6_iobuf_size(ifp->mtu6);
     414          29 :                         if (oi->ifmtu > iobuflen) {
     415           0 :                                 if (IS_OSPF6_DEBUG_INTERFACE)
     416           0 :                                         zlog_debug(
     417             :                                                 "Interface %s: IfMtu is adjusted to I/O buffer size: %d.",
     418             :                                                 ifp->name, iobuflen);
     419           0 :                                 oi->ifmtu = iobuflen;
     420             :                         }
     421           0 :                 } else if (oi->c_ifmtu > ifp->mtu6) {
     422           0 :                         oi->ifmtu = ifp->mtu6;
     423           0 :                         zlog_warn(
     424             :                                 "Configured mtu %u on %s overridden by kernel %u",
     425             :                                 oi->c_ifmtu, ifp->name, ifp->mtu6);
     426             :                 } else
     427           0 :                         oi->ifmtu = oi->c_ifmtu;
     428             :         }
     429             : 
     430         167 :         if (if_is_operative(ifp)
     431         119 :             && (ospf6_interface_get_linklocal_address(oi->interface)
     432          90 :                 || if_is_loopback(oi->interface)))
     433          29 :                 thread_execute(master, interface_up, oi, 0);
     434             :         else
     435         138 :                 thread_execute(master, interface_down, oi, 0);
     436             : 
     437             :         return;
     438             : }
     439             : 
     440         241 : bool ospf6_interface_addr_valid(struct ospf6_interface *oi, struct connected *c,
     441             :                                 bool debug)
     442             : {
     443         241 :         if (c->address->family != AF_INET6)
     444             :                 return false;
     445             : 
     446         135 :         if (IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6)) {
     447          61 :                 if (debug)
     448           0 :                         zlog_debug("Filter out Linklocal: %pFX", c->address);
     449          61 :                 return false;
     450             :         }
     451          74 :         if (IN6_IS_ADDR_UNSPECIFIED(&c->address->u.prefix6)) {
     452           0 :                 if (debug)
     453           0 :                         zlog_debug("Filter out Unspecified: %pFX", c->address);
     454           0 :                 return false;
     455             :         }
     456          74 :         if (IN6_IS_ADDR_LOOPBACK(&c->address->u.prefix6)) {
     457           0 :                 if (debug)
     458           0 :                         zlog_debug("Filter out Loopback: %pFX", c->address);
     459           0 :                 return false;
     460             :         }
     461          74 :         if (IN6_IS_ADDR_V4COMPAT(&c->address->u.prefix6)) {
     462           0 :                 if (debug)
     463           0 :                         zlog_debug("Filter out V4Compat: %pFX", c->address);
     464           0 :                 return false;
     465             :         }
     466          74 :         if (IN6_IS_ADDR_V4MAPPED(&c->address->u.prefix6)) {
     467           0 :                 if (debug)
     468           0 :                         zlog_debug("Filter out V4Mapped: %pFX", c->address);
     469           0 :                 return false;
     470             :         }
     471             : 
     472             :         /* apply filter */
     473          74 :         if (oi->plist_name) {
     474           0 :                 struct prefix_list *plist;
     475           0 :                 enum prefix_list_type ret;
     476             : 
     477           0 :                 plist = prefix_list_lookup(AFI_IP6, oi->plist_name);
     478           0 :                 ret = prefix_list_apply(plist, (void *)c->address);
     479           0 :                 if (ret == PREFIX_DENY) {
     480           0 :                         if (debug)
     481           0 :                                 zlog_debug(
     482             :                                         "%pFX on %pOI filtered by prefix-list %s ",
     483             :                                         c->address, oi, oi->plist_name);
     484           0 :                         return false;
     485             :                 }
     486             :         }
     487             :         return true;
     488             : }
     489             : 
     490         163 : void ospf6_interface_connected_route_update(struct interface *ifp)
     491             : {
     492         163 :         struct ospf6_interface *oi;
     493         163 :         struct connected *c;
     494         163 :         struct listnode *node, *nnode;
     495         163 :         struct in6_addr nh_addr;
     496             : 
     497         163 :         oi = (struct ospf6_interface *)ifp->info;
     498         163 :         if (oi == NULL)
     499          48 :                 return;
     500             : 
     501         115 :         if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
     502             :                 return;
     503             : 
     504             :         /* reset linklocal pointer */
     505         115 :         oi->linklocal_addr = ospf6_interface_get_linklocal_address(ifp);
     506             : 
     507             :         /* if area is null, do not make connected-route list */
     508         115 :         if (oi->area == NULL)
     509             :                 return;
     510             : 
     511         115 :         if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
     512             :                 return;
     513             : 
     514             :         /* update "route to advertise" interface route table */
     515         115 :         ospf6_route_remove_all(oi->route_connected);
     516             : 
     517         471 :         for (ALL_LIST_ELEMENTS(oi->interface->connected, node, nnode, c)) {
     518         241 :                 if (!ospf6_interface_addr_valid(oi, c,
     519             :                                                 IS_OSPF6_DEBUG_INTERFACE))
     520         167 :                         continue;
     521             : 
     522          74 :                 if (oi->state == OSPF6_INTERFACE_LOOPBACK
     523          74 :                     || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT
     524          69 :                     || oi->state == OSPF6_INTERFACE_POINTTOPOINT
     525          69 :                     || c->address->prefixlen == 128) {
     526           5 :                         struct ospf6_route *la_route;
     527             : 
     528           5 :                         la_route = ospf6_route_create(oi->area->ospf6);
     529           5 :                         la_route->prefix = *c->address;
     530           5 :                         la_route->prefix.prefixlen = 128;
     531           5 :                         la_route->prefix_options |= OSPF6_PREFIX_OPTION_LA;
     532             : 
     533           5 :                         la_route->type = OSPF6_DEST_TYPE_NETWORK;
     534           5 :                         la_route->path.area_id = oi->area->area_id;
     535           5 :                         la_route->path.type = OSPF6_PATH_TYPE_INTRA;
     536           5 :                         la_route->path.cost = 0;
     537           5 :                         inet_pton(AF_INET6, "::1", &nh_addr);
     538           5 :                         ospf6_route_add_nexthop(
     539             :                                 la_route, oi->interface->ifindex, &nh_addr);
     540           5 :                         ospf6_route_add(la_route, oi->route_connected);
     541             :                 }
     542             : 
     543          74 :                 if (c->address->prefixlen == 128)
     544           0 :                         continue;
     545          74 :                 if (oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT
     546           5 :                     && !oi->p2xp_connected_pfx_include)
     547           3 :                         continue;
     548          71 :                 if (oi->state == OSPF6_INTERFACE_POINTTOPOINT
     549           0 :                     && oi->p2xp_connected_pfx_exclude)
     550           0 :                         continue;
     551             : 
     552          71 :                 struct ospf6_route *route;
     553             : 
     554          71 :                 route = ospf6_route_create(oi->area->ospf6);
     555          71 :                 memcpy(&route->prefix, c->address, sizeof(struct prefix));
     556          71 :                 apply_mask(&route->prefix);
     557          71 :                 route->type = OSPF6_DEST_TYPE_NETWORK;
     558          71 :                 route->path.area_id = oi->area->area_id;
     559          71 :                 route->path.type = OSPF6_PATH_TYPE_INTRA;
     560          71 :                 route->path.cost = oi->cost;
     561          71 :                 inet_pton(AF_INET6, "::1", &nh_addr);
     562          71 :                 ospf6_route_add_nexthop(route, oi->interface->ifindex,
     563             :                                         &nh_addr);
     564          71 :                 ospf6_route_add(route, oi->route_connected);
     565             :         }
     566             : 
     567             :         /* create new Link-LSA */
     568         115 :         OSPF6_LINK_LSA_SCHEDULE(oi);
     569         115 :         OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
     570         115 :         OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
     571             : }
     572             : 
     573         245 : static int ospf6_interface_state_change(uint8_t next_state,
     574             :                                         struct ospf6_interface *oi)
     575             : {
     576         245 :         uint8_t prev_state;
     577         245 :         struct ospf6 *ospf6;
     578             : 
     579         245 :         prev_state = oi->state;
     580         245 :         oi->state = next_state;
     581             : 
     582         245 :         if (prev_state == next_state)
     583             :                 return -1;
     584             : 
     585          91 :         if (!oi->area)
     586             :                 return -1;
     587             : 
     588             :         /* log */
     589          91 :         if (IS_OSPF6_DEBUG_INTERFACE) {
     590           0 :                 zlog_debug("Interface state change %pOI: %s -> %s", oi,
     591             :                            ospf6_interface_state_str[prev_state],
     592             :                            ospf6_interface_state_str[next_state]);
     593             :         }
     594          91 :         oi->state_change++;
     595             : 
     596          91 :         ospf6 = oi->area->ospf6;
     597             : 
     598          91 :         if ((prev_state == OSPF6_INTERFACE_DR
     599          91 :              || prev_state == OSPF6_INTERFACE_BDR)
     600          26 :             && (next_state != OSPF6_INTERFACE_DR
     601          26 :                 && next_state != OSPF6_INTERFACE_BDR))
     602          25 :                 ospf6_sso(oi->interface->ifindex, &alldrouters6,
     603             :                           IPV6_LEAVE_GROUP, ospf6->fd);
     604             : 
     605          65 :         if ((prev_state != OSPF6_INTERFACE_DR
     606             :              && prev_state != OSPF6_INTERFACE_BDR)
     607          65 :             && (next_state == OSPF6_INTERFACE_DR
     608          65 :                 || next_state == OSPF6_INTERFACE_BDR))
     609          25 :                 ospf6_sso(oi->interface->ifindex, &alldrouters6,
     610             :                           IPV6_JOIN_GROUP, ospf6->fd);
     611             : 
     612          91 :         OSPF6_ROUTER_LSA_SCHEDULE(oi->area);
     613          91 :         OSPF6_LINK_LSA_SCHEDULE(oi);
     614          91 :         if (next_state == OSPF6_INTERFACE_DOWN) {
     615          29 :                 OSPF6_NETWORK_LSA_EXECUTE(oi);
     616          29 :                 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
     617          29 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
     618          29 :                 OSPF6_INTRA_PREFIX_LSA_EXECUTE_TRANSIT(oi);
     619          62 :         } else if (prev_state == OSPF6_INTERFACE_DR
     620          62 :                    || next_state == OSPF6_INTERFACE_DR) {
     621          15 :                 OSPF6_NETWORK_LSA_SCHEDULE(oi);
     622          15 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
     623          15 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
     624             :         }
     625             : 
     626          91 :         if (next_state == OSPF6_INTERFACE_POINTTOPOINT
     627          91 :             || next_state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
     628           3 :                 ospf6_if_p2xp_up(oi);
     629             : 
     630          91 :         hook_call(ospf6_interface_change, oi, next_state, prev_state);
     631             : 
     632          91 :         return 0;
     633             : }
     634             : 
     635             : 
     636             : /* DR Election, RFC2328 section 9.4 */
     637             : 
     638             : #define IS_ELIGIBLE(n)                                                         \
     639             :         ((n)->state >= OSPF6_NEIGHBOR_TWOWAY && (n)->priority != 0)
     640             : 
     641         134 : static struct ospf6_neighbor *better_bdrouter(struct ospf6_neighbor *a,
     642             :                                               struct ospf6_neighbor *b)
     643             : {
     644         134 :         if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
     645          71 :             && (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id))
     646             :                 return NULL;
     647         121 :         else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter == a->router_id)
     648             :                 return b;
     649          63 :         else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter == b->router_id)
     650             :                 return a;
     651             : 
     652          35 :         if (a->bdrouter == a->router_id && b->bdrouter != b->router_id)
     653             :                 return a;
     654          32 :         if (a->bdrouter != a->router_id && b->bdrouter == b->router_id)
     655             :                 return b;
     656             : 
     657          27 :         if (a->priority > b->priority)
     658             :                 return a;
     659          27 :         if (a->priority < b->priority)
     660             :                 return b;
     661             : 
     662          27 :         if (ntohl(a->router_id) > ntohl(b->router_id))
     663             :                 return a;
     664          18 :         if (ntohl(a->router_id) < ntohl(b->router_id))
     665             :                 return b;
     666             : 
     667           0 :         zlog_warn("Router-ID duplicate ?");
     668           0 :         return a;
     669             : }
     670             : 
     671         134 : static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
     672             :                                              struct ospf6_neighbor *b)
     673             : {
     674         134 :         if ((a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
     675         108 :             && (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id))
     676             :                 return NULL;
     677          67 :         else if (a == NULL || !IS_ELIGIBLE(a) || a->drouter != a->router_id)
     678             :                 return b;
     679          26 :         else if (b == NULL || !IS_ELIGIBLE(b) || b->drouter != b->router_id)
     680             :                 return a;
     681             : 
     682           0 :         if (a->drouter == a->router_id && b->drouter != b->router_id)
     683             :                 return a;
     684           0 :         if (a->drouter != a->router_id && b->drouter == b->router_id)
     685             :                 return b;
     686             : 
     687           0 :         if (a->priority > b->priority)
     688             :                 return a;
     689           0 :         if (a->priority < b->priority)
     690             :                 return b;
     691             : 
     692           0 :         if (ntohl(a->router_id) > ntohl(b->router_id))
     693             :                 return a;
     694           0 :         if (ntohl(a->router_id) < ntohl(b->router_id))
     695             :                 return b;
     696             : 
     697           0 :         zlog_warn("Router-ID duplicate ?");
     698           0 :         return a;
     699             : }
     700             : 
     701          49 : uint8_t dr_election(struct ospf6_interface *oi)
     702             : {
     703          49 :         struct listnode *node, *nnode;
     704          49 :         struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
     705          49 :         struct ospf6_neighbor *best_drouter, *best_bdrouter;
     706          49 :         uint8_t next_state = 0;
     707             : 
     708          49 :         drouter = bdrouter = NULL;
     709          49 :         best_drouter = best_bdrouter = NULL;
     710             : 
     711             :         /* pseudo neighbor myself, including noting current DR/BDR (1) */
     712          49 :         memset(&myself, 0, sizeof(myself));
     713          49 :         inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name,
     714             :                   sizeof(myself.name));
     715          49 :         myself.state = OSPF6_NEIGHBOR_TWOWAY;
     716          49 :         myself.drouter = oi->drouter;
     717          49 :         myself.bdrouter = oi->bdrouter;
     718          49 :         myself.priority = oi->priority;
     719          49 :         myself.router_id = oi->area->ospf6->router_id;
     720             : 
     721             :         /* Electing BDR (2) */
     722         157 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
     723          59 :                 bdrouter = better_bdrouter(bdrouter, on);
     724             : 
     725          49 :         best_bdrouter = bdrouter;
     726          49 :         bdrouter = better_bdrouter(best_bdrouter, &myself);
     727             : 
     728             :         /* Electing DR (3) */
     729         157 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
     730          59 :                 drouter = better_drouter(drouter, on);
     731             : 
     732          49 :         best_drouter = drouter;
     733          49 :         drouter = better_drouter(best_drouter, &myself);
     734          49 :         if (drouter == NULL)
     735          23 :                 drouter = bdrouter;
     736             : 
     737             :         /* the router itself is newly/no longer DR/BDR (4) */
     738          49 :         if ((drouter == &myself && myself.drouter != myself.router_id)
     739          34 :             || (drouter != &myself && myself.drouter == myself.router_id)
     740          34 :             || (bdrouter == &myself && myself.bdrouter != myself.router_id)
     741          23 :             || (bdrouter != &myself && myself.bdrouter == myself.router_id)) {
     742          26 :                 myself.drouter = (drouter ? drouter->router_id : htonl(0));
     743          26 :                 myself.bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
     744             : 
     745             :                 /* compatible to Electing BDR (2) */
     746          26 :                 bdrouter = better_bdrouter(best_bdrouter, &myself);
     747             : 
     748             :                 /* compatible to Electing DR (3) */
     749          26 :                 drouter = better_drouter(best_drouter, &myself);
     750          26 :                 if (drouter == NULL)
     751             :                         drouter = bdrouter;
     752             :         }
     753             : 
     754             :         /* Set interface state accordingly (5) */
     755          49 :         if (drouter && drouter == &myself)
     756             :                 next_state = OSPF6_INTERFACE_DR;
     757          23 :         else if (bdrouter && bdrouter == &myself)
     758             :                 next_state = OSPF6_INTERFACE_BDR;
     759             :         else
     760          12 :                 next_state = OSPF6_INTERFACE_DROTHER;
     761             : 
     762             :         /* If NBMA, schedule Start for each neighbor having priority of 0 (6) */
     763             :         /* XXX */
     764             : 
     765             :         /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
     766             :         /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
     767             :            accordingly after AdjOK */
     768          49 :         if (oi->drouter != (drouter ? drouter->router_id : htonl(0))
     769          21 :             || oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) {
     770          36 :                 if (IS_OSPF6_DEBUG_INTERFACE)
     771           0 :                         zlog_debug("DR Election on %pOI: DR: %s BDR: %s", oi,
     772             :                                    (drouter ? drouter->name : "0.0.0.0"),
     773             :                                    (bdrouter ? bdrouter->name : "0.0.0.0"));
     774             : 
     775         114 :                 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
     776          42 :                         if (on->state < OSPF6_NEIGHBOR_TWOWAY)
     777           0 :                                 continue;
     778             :                         /* Schedule AdjOK. */
     779          42 :                         thread_add_event(master, adj_ok, on, 0,
     780             :                                          &on->thread_adj_ok);
     781             :                 }
     782             :         }
     783             : 
     784          49 :         oi->drouter = (drouter ? drouter->router_id : htonl(0));
     785          49 :         oi->bdrouter = (bdrouter ? bdrouter->router_id : htonl(0));
     786          49 :         return next_state;
     787             : }
     788             : 
     789             : #ifdef __FreeBSD__
     790             : 
     791             : #include <ifaddrs.h>
     792             : 
     793             : static bool ifmaddr_check(ifindex_t ifindex, struct in6_addr *addr)
     794             : {
     795             :         struct ifmaddrs *ifmap, *ifma;
     796             :         struct sockaddr_dl *sdl;
     797             :         struct sockaddr_in6 *sin6;
     798             :         bool found = false;
     799             : 
     800             :         if (getifmaddrs(&ifmap) != 0)
     801             :                 return false;
     802             : 
     803             :         for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
     804             :                 if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
     805             :                         continue;
     806             :                 if (ifma->ifma_name->sa_family != AF_LINK)
     807             :                         continue;
     808             :                 if (ifma->ifma_addr->sa_family != AF_INET6)
     809             :                         continue;
     810             :                 sdl = (struct sockaddr_dl *)ifma->ifma_name;
     811             :                 sin6 = (struct sockaddr_in6 *)ifma->ifma_addr;
     812             :                 if (sdl->sdl_index == ifindex
     813             :                     && memcmp(&sin6->sin6_addr, addr, IPV6_MAX_BYTELEN) == 0) {
     814             :                         found = true;
     815             :                         break;
     816             :                 }
     817             :         }
     818             : 
     819             :         if (ifmap)
     820             :                 freeifmaddrs(ifmap);
     821             : 
     822             :         return found;
     823             : }
     824             : 
     825             : #endif /* __FreeBSD__ */
     826             : 
     827             : /* Interface State Machine */
     828          32 : void interface_up(struct thread *thread)
     829             : {
     830          32 :         struct ospf6_interface *oi;
     831          32 :         struct ospf6 *ospf6;
     832             : 
     833          32 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     834          32 :         assert(oi && oi->interface);
     835             : 
     836          32 :         if (!oi->type_cfg)
     837          26 :                 oi->type = ospf6_default_iftype(oi->interface);
     838             : 
     839          32 :         thread_cancel(&oi->thread_sso);
     840             : 
     841          32 :         if (IS_OSPF6_DEBUG_INTERFACE)
     842           0 :                 zlog_debug("Interface Event %pOI: [InterfaceUp]", oi);
     843             : 
     844             :         /* check physical interface is up */
     845          32 :         if (!if_is_operative(oi->interface)) {
     846           3 :                 zlog_warn("Interface %pOI is down, can't execute [InterfaceUp]",
     847             :                           oi);
     848           3 :                 return;
     849             :         }
     850             : 
     851             :         /* check interface has a link-local address */
     852          29 :         if (!(ospf6_interface_get_linklocal_address(oi->interface)
     853           0 :               || if_is_loopback(oi->interface))) {
     854           0 :                 zlog_warn(
     855             :                         "Interface %pOI has no link local address, can't execute [InterfaceUp]",
     856             :                         oi);
     857           0 :                 return;
     858             :         }
     859             : 
     860             :         /* Recompute cost */
     861          29 :         ospf6_interface_recalculate_cost(oi);
     862             : 
     863             :         /* if already enabled, do nothing */
     864          29 :         if (oi->state > OSPF6_INTERFACE_DOWN) {
     865           0 :                 if (IS_OSPF6_DEBUG_INTERFACE)
     866           0 :                         zlog_debug("Interface %pOI already enabled", oi);
     867           0 :                 return;
     868             :         }
     869             : 
     870             :         /* If no area assigned, return */
     871          29 :         if (oi->area == NULL) {
     872           0 :                 zlog_warn(
     873             :                         "%s: Not scheduling Hello for %pOI as there is no area assigned yet",
     874             :                         __func__, oi);
     875           0 :                 return;
     876             :         }
     877             : 
     878             : #ifdef __FreeBSD__
     879             :         /*
     880             :          * There's a delay in FreeBSD between issuing a command to leave a
     881             :          * multicast group and an actual leave. If we execute "no router ospf6"
     882             :          * and "router ospf6" fast enough, we can end up in a situation when OS
     883             :          * performs the leave later than it performs the join and the interface
     884             :          * remains without a multicast group. We have to do the join only after
     885             :          * the interface actually left the group.
     886             :          */
     887             :         if (ifmaddr_check(oi->interface->ifindex, &allspfrouters6)) {
     888             :                 zlog_info(
     889             :                         "Interface %pOI is still in all routers group, rescheduling for SSO",
     890             :                         oi);
     891             :                 thread_add_timer(master, interface_up, oi,
     892             :                                  OSPF6_INTERFACE_SSO_RETRY_INT,
     893             :                                  &oi->thread_sso);
     894             :                 return;
     895             :         }
     896             : #endif /* __FreeBSD__ */
     897             : 
     898          29 :         ospf6 = oi->area->ospf6;
     899             : 
     900             :         /* Join AllSPFRouters */
     901          29 :         if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP,
     902             :                       ospf6->fd)
     903             :             < 0) {
     904           0 :                 if (oi->sso_try_cnt++ < OSPF6_INTERFACE_SSO_RETRY_MAX) {
     905           0 :                         zlog_info(
     906             :                                 "Scheduling %pOI for sso retry, trial count: %d",
     907             :                                 oi, oi->sso_try_cnt);
     908           0 :                         thread_add_timer(master, interface_up, oi,
     909             :                                          OSPF6_INTERFACE_SSO_RETRY_INT,
     910             :                                          &oi->thread_sso);
     911             :                 }
     912           0 :                 return;
     913             :         }
     914          29 :         oi->sso_try_cnt = 0; /* Reset on success */
     915             : 
     916             :         /* Update interface route */
     917          29 :         ospf6_interface_connected_route_update(oi->interface);
     918             : 
     919             :         /* Schedule Hello */
     920          29 :         if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)
     921          29 :             && !if_is_loopback(oi->interface)) {
     922          29 :                 thread_add_timer(master, ospf6_hello_send, oi, 0,
     923             :                                  &oi->thread_send_hello);
     924             :         }
     925             : 
     926             :         /* decide next interface state */
     927          29 :         if (oi->type == OSPF_IFTYPE_LOOPBACK) {
     928           0 :                 ospf6_interface_state_change(OSPF6_INTERFACE_LOOPBACK, oi);
     929          29 :         } else if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
     930           0 :                 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
     931          29 :         } else if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
     932           3 :                 ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOMULTIPOINT,
     933             :                                              oi);
     934          26 :         } else if (oi->priority == 0)
     935           0 :                 ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
     936             :         else {
     937          26 :                 ospf6_interface_state_change(OSPF6_INTERFACE_WAITING, oi);
     938          26 :                 thread_add_timer(master, wait_timer, oi, oi->dead_interval,
     939             :                                  &oi->thread_wait_timer);
     940             :         }
     941             : }
     942             : 
     943          26 : void wait_timer(struct thread *thread)
     944             : {
     945          26 :         struct ospf6_interface *oi;
     946             : 
     947          26 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     948          26 :         assert(oi && oi->interface);
     949             : 
     950          26 :         if (IS_OSPF6_DEBUG_INTERFACE)
     951           0 :                 zlog_debug("Interface Event %pOI: [WaitTimer]", oi);
     952             : 
     953          26 :         if (oi->state == OSPF6_INTERFACE_WAITING)
     954          26 :                 ospf6_interface_state_change(dr_election(oi), oi);
     955          26 : }
     956             : 
     957           0 : void backup_seen(struct thread *thread)
     958             : {
     959           0 :         struct ospf6_interface *oi;
     960             : 
     961           0 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     962           0 :         assert(oi && oi->interface);
     963             : 
     964           0 :         if (IS_OSPF6_DEBUG_INTERFACE)
     965           0 :                 zlog_debug("Interface Event %pOI: [BackupSeen]", oi);
     966             : 
     967           0 :         if (oi->state == OSPF6_INTERFACE_WAITING)
     968           0 :                 ospf6_interface_state_change(dr_election(oi), oi);
     969           0 : }
     970             : 
     971          62 : void neighbor_change(struct thread *thread)
     972             : {
     973          62 :         struct ospf6_interface *oi;
     974             : 
     975          62 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     976          62 :         assert(oi && oi->interface);
     977             : 
     978          62 :         if (IS_OSPF6_DEBUG_INTERFACE)
     979           0 :                 zlog_debug("Interface Event %pOI: [NeighborChange]", oi);
     980             : 
     981          62 :         if (oi->state == OSPF6_INTERFACE_DROTHER
     982             :             || oi->state == OSPF6_INTERFACE_BDR
     983          62 :             || oi->state == OSPF6_INTERFACE_DR)
     984          23 :                 ospf6_interface_state_change(dr_election(oi), oi);
     985          62 : }
     986             : 
     987         170 : void interface_down(struct thread *thread)
     988             : {
     989         170 :         struct ospf6_interface *oi;
     990         170 :         struct listnode *node, *nnode;
     991         170 :         struct ospf6_neighbor *on;
     992         170 :         struct ospf6 *ospf6;
     993             : 
     994         170 :         oi = (struct ospf6_interface *)THREAD_ARG(thread);
     995         170 :         assert(oi && oi->interface);
     996             : 
     997         170 :         if (IS_OSPF6_DEBUG_INTERFACE)
     998           0 :                 zlog_debug("Interface Event %pOI: [InterfaceDown]", oi);
     999             : 
    1000             :         /* Stop Hellos */
    1001         170 :         THREAD_OFF(oi->thread_send_hello);
    1002             : 
    1003             :         /* Stop trying to set socket options. */
    1004         170 :         THREAD_OFF(oi->thread_sso);
    1005             : 
    1006             :         /* Cease the HELPER role for all the neighbours
    1007             :          * of this interface.
    1008             :          */
    1009         170 :         if (ospf6_interface_neighbor_count(oi)) {
    1010          25 :                 struct listnode *ln;
    1011          25 :                 struct ospf6_neighbor *nbr = NULL;
    1012             : 
    1013          82 :                 for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, ln, nbr))
    1014          32 :                         ospf6_gr_helper_exit(nbr, OSPF6_GR_HELPER_TOPO_CHG);
    1015             :         }
    1016             : 
    1017         372 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
    1018          32 :                 ospf6_neighbor_delete(on);
    1019             : 
    1020         170 :         list_delete_all_node(oi->neighbor_list);
    1021             : 
    1022             :         /* When interface state is reset, also reset information about
    1023             :          * DR election, as it is no longer valid. */
    1024         170 :         oi->drouter = oi->prev_drouter = htonl(0);
    1025         170 :         oi->bdrouter = oi->prev_bdrouter = htonl(0);
    1026             : 
    1027         170 :         if (oi->area == NULL)
    1028             :                 return;
    1029             : 
    1030         167 :         ospf6 = oi->area->ospf6;
    1031             :         /* Leave AllSPFRouters */
    1032         167 :         if (oi->state > OSPF6_INTERFACE_DOWN)
    1033          29 :                 ospf6_sso(oi->interface->ifindex, &allspfrouters6,
    1034             :                           IPV6_LEAVE_GROUP, ospf6->fd);
    1035             : 
    1036             :         /* deal with write fifo */
    1037         167 :         ospf6_fifo_flush(oi->obuf);
    1038         167 :         if (oi->on_write_q) {
    1039           0 :                 listnode_delete(ospf6->oi_write_q, oi);
    1040           0 :                 if (list_isempty(ospf6->oi_write_q))
    1041           0 :                         thread_cancel(&ospf6->t_write);
    1042           0 :                 oi->on_write_q = 0;
    1043             :         }
    1044             : 
    1045         167 :         ospf6_interface_state_change(OSPF6_INTERFACE_DOWN, oi);
    1046             : }
    1047             : 
    1048             : 
    1049           0 : static const char *ospf6_iftype_str(uint8_t iftype)
    1050             : {
    1051           0 :         switch (iftype) {
    1052             :         case OSPF_IFTYPE_LOOPBACK:
    1053             :                 return "LOOPBACK";
    1054           0 :         case OSPF_IFTYPE_BROADCAST:
    1055           0 :                 return "BROADCAST";
    1056           0 :         case OSPF_IFTYPE_POINTOPOINT:
    1057           0 :                 return "POINTOPOINT";
    1058           0 :         case OSPF_IFTYPE_POINTOMULTIPOINT:
    1059           0 :                 return "POINTOMULTIPOINT";
    1060             :         }
    1061           0 :         return "UNKNOWN";
    1062             : }
    1063             : 
    1064             : /* show specified interface structure */
    1065           0 : static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
    1066             :                                 json_object *json_obj, bool use_json)
    1067             : {
    1068           0 :         struct ospf6_interface *oi;
    1069           0 :         struct connected *c;
    1070           0 :         struct prefix *p;
    1071           0 :         struct listnode *i;
    1072           0 :         char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
    1073           0 :         uint8_t default_iftype;
    1074           0 :         struct timeval res, now;
    1075           0 :         char duration[32];
    1076           0 :         struct ospf6_lsa *lsa, *lsanext;
    1077           0 :         json_object *json_arr;
    1078           0 :         json_object *json_addr;
    1079           0 :         struct json_object *json_auth = NULL;
    1080             : 
    1081           0 :         default_iftype = ospf6_default_iftype(ifp);
    1082             : 
    1083           0 :         if (use_json) {
    1084           0 :                 json_object_string_add(json_obj, "status",
    1085           0 :                                        (if_is_operative(ifp) ? "up" : "down"));
    1086           0 :                 json_object_string_add(json_obj, "type",
    1087             :                                        ospf6_iftype_str(default_iftype));
    1088           0 :                 json_object_int_add(json_obj, "interfaceId", ifp->ifindex);
    1089             : 
    1090           0 :                 if (ifp->info == NULL)
    1091             :                         return 0;
    1092             : 
    1093           0 :                 oi = (struct ospf6_interface *)ifp->info;
    1094             : 
    1095           0 :                 if (if_is_operative(ifp) && oi->type != default_iftype)
    1096           0 :                         json_object_string_add(json_obj, "operatingAsType",
    1097             :                                                ospf6_iftype_str(oi->type));
    1098             : 
    1099             :         } else {
    1100           0 :                 vty_out(vty, "%s is %s, type %s\n", ifp->name,
    1101           0 :                         (if_is_operative(ifp) ? "up" : "down"),
    1102             :                         ospf6_iftype_str(default_iftype));
    1103           0 :                 vty_out(vty, "  Interface ID: %d\n", ifp->ifindex);
    1104             : 
    1105           0 :                 if (ifp->info == NULL) {
    1106           0 :                         vty_out(vty, "   OSPF not enabled on this interface\n");
    1107           0 :                         return 0;
    1108             :                 }
    1109           0 :                 oi = (struct ospf6_interface *)ifp->info;
    1110             : 
    1111           0 :                 if (if_is_operative(ifp) && oi->type != default_iftype)
    1112           0 :                         vty_out(vty, "  Operating as type %s\n",
    1113             :                                 ospf6_iftype_str(oi->type));
    1114             :         }
    1115             : 
    1116           0 :         if (use_json) {
    1117           0 :                 json_arr = json_object_new_array();
    1118           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
    1119           0 :                         json_addr = json_object_new_object();
    1120           0 :                         p = c->address;
    1121           0 :                         prefix2str(p, strbuf, sizeof(strbuf));
    1122           0 :                         switch (p->family) {
    1123           0 :                         case AF_INET:
    1124           0 :                                 json_object_string_add(json_addr, "type",
    1125             :                                                        "inet");
    1126           0 :                                 json_object_string_add(json_addr, "address",
    1127             :                                                        strbuf);
    1128           0 :                                 json_object_array_add(json_arr, json_addr);
    1129           0 :                                 break;
    1130           0 :                         case AF_INET6:
    1131           0 :                                 json_object_string_add(json_addr, "type",
    1132             :                                                        "inet6");
    1133           0 :                                 json_object_string_add(json_addr, "address",
    1134             :                                                        strbuf);
    1135           0 :                                 json_object_array_add(json_arr, json_addr);
    1136           0 :                                 break;
    1137           0 :                         default:
    1138           0 :                                 json_object_string_add(json_addr, "type",
    1139             :                                                        "unknown");
    1140           0 :                                 json_object_string_add(json_addr, "address",
    1141             :                                                        strbuf);
    1142           0 :                                 json_object_array_add(json_arr, json_addr);
    1143           0 :                                 break;
    1144             :                         }
    1145             :                 }
    1146           0 :                 json_object_object_add(json_obj, "internetAddress", json_arr);
    1147             :         } else {
    1148           0 :                 vty_out(vty, "  Internet Address:\n");
    1149             : 
    1150           0 :                 for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
    1151           0 :                         p = c->address;
    1152           0 :                         prefix2str(p, strbuf, sizeof(strbuf));
    1153           0 :                         switch (p->family) {
    1154           0 :                         case AF_INET:
    1155           0 :                                 vty_out(vty, "    inet : %pFX\n", p);
    1156           0 :                                 break;
    1157           0 :                         case AF_INET6:
    1158           0 :                                 vty_out(vty, "    inet6: %pFX\n", p);
    1159           0 :                                 break;
    1160           0 :                         default:
    1161           0 :                                 vty_out(vty, "    ???  : %pFX\n", p);
    1162           0 :                                 break;
    1163             :                         }
    1164             :                 }
    1165             :         }
    1166             : 
    1167           0 :         if (use_json) {
    1168           0 :                 if (oi->area) {
    1169           0 :                         json_object_boolean_true_add(json_obj,
    1170             :                                                      "attachedToArea");
    1171           0 :                         json_object_int_add(json_obj, "instanceId",
    1172           0 :                                             oi->instance_id);
    1173           0 :                         json_object_int_add(json_obj, "interfaceMtu",
    1174           0 :                                             oi->ifmtu);
    1175           0 :                         json_object_int_add(json_obj, "autoDetect", ifp->mtu6);
    1176           0 :                         json_object_string_add(json_obj, "mtuMismatchDetection",
    1177           0 :                                                oi->mtu_ignore ? "disabled"
    1178             :                                                               : "enabled");
    1179           0 :                         inet_ntop(AF_INET, &oi->area->area_id, strbuf,
    1180             :                                   sizeof(strbuf));
    1181           0 :                         json_object_string_add(json_obj, "areaId", strbuf);
    1182           0 :                         json_object_int_add(json_obj, "cost", oi->cost);
    1183             :                 } else
    1184           0 :                         json_object_boolean_false_add(json_obj,
    1185             :                                                       "attachedToArea");
    1186             : 
    1187             :         } else {
    1188           0 :                 if (oi->area) {
    1189           0 :                         vty_out(vty,
    1190             :                                 "  Instance ID %d, Interface MTU %d (autodetect: %d)\n",
    1191           0 :                                 oi->instance_id, oi->ifmtu, ifp->mtu6);
    1192           0 :                         vty_out(vty, "  MTU mismatch detection: %s\n",
    1193           0 :                                 oi->mtu_ignore ? "disabled" : "enabled");
    1194           0 :                         inet_ntop(AF_INET, &oi->area->area_id, strbuf,
    1195             :                                   sizeof(strbuf));
    1196           0 :                         vty_out(vty, "  Area ID %s, Cost %u\n", strbuf,
    1197             :                                 oi->cost);
    1198             :                 } else
    1199           0 :                         vty_out(vty, "  Not Attached to Area\n");
    1200             :         }
    1201             : 
    1202           0 :         if (use_json) {
    1203           0 :                 json_object_string_add(json_obj, "ospf6InterfaceState",
    1204           0 :                                        ospf6_interface_state_str[oi->state]);
    1205           0 :                 json_object_int_add(json_obj, "transmitDelaySec",
    1206           0 :                                     oi->transdelay);
    1207           0 :                 json_object_int_add(json_obj, "priority", oi->priority);
    1208           0 :                 json_object_int_add(json_obj, "timerIntervalsConfigHello",
    1209           0 :                                     oi->hello_interval);
    1210           0 :                 json_object_int_add(json_obj, "timerIntervalsConfigDead",
    1211           0 :                                     oi->dead_interval);
    1212           0 :                 json_object_int_add(json_obj, "timerIntervalsConfigRetransmit",
    1213           0 :                                     oi->rxmt_interval);
    1214           0 :                 json_object_boolean_add(
    1215             :                         json_obj, "timerPassiveIface",
    1216           0 :                         !!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE));
    1217             :         } else {
    1218           0 :                 vty_out(vty, "  State %s, Transmit Delay %d sec, Priority %d\n",
    1219           0 :                         ospf6_interface_state_str[oi->state], oi->transdelay,
    1220           0 :                         oi->priority);
    1221           0 :                 vty_out(vty, "  Timer intervals configured:\n");
    1222           0 :                 if (!CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
    1223           0 :                         vty_out(vty,
    1224             :                                 "   Hello %d(%pTHd), Dead %d, Retransmit %d\n",
    1225           0 :                                 oi->hello_interval, oi->thread_send_hello,
    1226           0 :                                 oi->dead_interval, oi->rxmt_interval);
    1227             :                 else
    1228           0 :                         vty_out(vty, "   No Hellos (Passive interface)\n");
    1229             :         }
    1230             : 
    1231           0 :         inet_ntop(AF_INET, &oi->drouter, drouter, sizeof(drouter));
    1232           0 :         inet_ntop(AF_INET, &oi->bdrouter, bdrouter, sizeof(bdrouter));
    1233           0 :         if (use_json) {
    1234           0 :                 json_object_string_add(json_obj, "dr", drouter);
    1235           0 :                 json_object_string_add(json_obj, "bdr", bdrouter);
    1236           0 :                 if (oi->lsdb)
    1237           0 :                         json_object_int_add(json_obj,
    1238             :                                             "numberOfInterfaceScopedLsa",
    1239           0 :                                             oi->lsdb->count);
    1240             :         } else {
    1241           0 :                 vty_out(vty, "  DR: %s BDR: %s\n", drouter, bdrouter);
    1242           0 :                 if (oi->lsdb)
    1243           0 :                         vty_out(vty, "  Number of I/F scoped LSAs is %u\n",
    1244             :                                 oi->lsdb->count);
    1245             :         }
    1246             : 
    1247           0 :         monotime(&now);
    1248             : 
    1249           0 :         if (use_json) {
    1250           0 :                 timerclear(&res);
    1251           0 :                 if (thread_is_scheduled(oi->thread_send_lsupdate))
    1252           0 :                         timersub(&oi->thread_send_lsupdate->u.sands, &now,
    1253             :                                  &res);
    1254           0 :                 timerstring(&res, duration, sizeof(duration));
    1255           0 :                 json_object_int_add(json_obj, "pendingLsaLsUpdateCount",
    1256           0 :                                     oi->lsupdate_list->count);
    1257           0 :                 json_object_string_add(json_obj, "pendingLsaLsUpdateTime",
    1258             :                                        duration);
    1259           0 :                 json_object_string_add(
    1260             :                         json_obj, "lsUpdateSendThread",
    1261           0 :                         (thread_is_scheduled(oi->thread_send_lsupdate)
    1262             :                                  ? "on"
    1263             :                                  : "off"));
    1264             : 
    1265           0 :                 json_arr = json_object_new_array();
    1266           0 :                 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
    1267           0 :                         json_object_array_add(
    1268           0 :                                 json_arr, json_object_new_string(lsa->name));
    1269           0 :                 json_object_object_add(json_obj, "pendingLsaLsUpdate",
    1270             :                                        json_arr);
    1271             : 
    1272           0 :                 timerclear(&res);
    1273           0 :                 if (thread_is_scheduled(oi->thread_send_lsack))
    1274           0 :                         timersub(&oi->thread_send_lsack->u.sands, &now, &res);
    1275           0 :                 timerstring(&res, duration, sizeof(duration));
    1276             : 
    1277           0 :                 json_object_int_add(json_obj, "pendingLsaLsAckCount",
    1278           0 :                                     oi->lsack_list->count);
    1279           0 :                 json_object_string_add(json_obj, "pendingLsaLsAckTime",
    1280             :                                        duration);
    1281           0 :                 json_object_string_add(
    1282             :                         json_obj, "lsAckSendThread",
    1283           0 :                         (thread_is_scheduled(oi->thread_send_lsack) ? "on"
    1284             :                                                                     : "off"));
    1285             : 
    1286           0 :                 json_arr = json_object_new_array();
    1287           0 :                 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
    1288           0 :                         json_object_array_add(
    1289           0 :                                 json_arr, json_object_new_string(lsa->name));
    1290           0 :                 json_object_object_add(json_obj, "pendingLsaLsAck", json_arr);
    1291             : 
    1292             :         } else {
    1293           0 :                 timerclear(&res);
    1294           0 :                 if (thread_is_scheduled(oi->thread_send_lsupdate))
    1295           0 :                         timersub(&oi->thread_send_lsupdate->u.sands, &now,
    1296             :                                  &res);
    1297           0 :                 timerstring(&res, duration, sizeof(duration));
    1298           0 :                 vty_out(vty,
    1299             :                         "    %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
    1300           0 :                         oi->lsupdate_list->count, duration,
    1301           0 :                         (thread_is_scheduled(oi->thread_send_lsupdate)
    1302             :                                  ? "on"
    1303             :                                  : "off"));
    1304           0 :                 for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext))
    1305           0 :                         vty_out(vty, "      %s\n", lsa->name);
    1306             : 
    1307           0 :                 timerclear(&res);
    1308           0 :                 if (thread_is_scheduled(oi->thread_send_lsack))
    1309           0 :                         timersub(&oi->thread_send_lsack->u.sands, &now, &res);
    1310           0 :                 timerstring(&res, duration, sizeof(duration));
    1311           0 :                 vty_out(vty,
    1312             :                         "    %d Pending LSAs for LSAck in Time %s [thread %s]\n",
    1313           0 :                         oi->lsack_list->count, duration,
    1314           0 :                         (thread_is_scheduled(oi->thread_send_lsack) ? "on"
    1315             :                                                                     : "off"));
    1316           0 :                 for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
    1317           0 :                         vty_out(vty, "      %s\n", lsa->name);
    1318             :         }
    1319             : 
    1320             :         /* BFD specific. */
    1321           0 :         if (oi->bfd_config.enabled) {
    1322           0 :                 if (use_json) {
    1323           0 :                         struct json_object *json_bfd = json_object_new_object();
    1324             : 
    1325           0 :                         json_object_int_add(
    1326             :                                 json_bfd, "detectMultiplier",
    1327           0 :                                 oi->bfd_config.detection_multiplier);
    1328           0 :                         json_object_int_add(json_bfd, "rxMinInterval",
    1329           0 :                                             oi->bfd_config.min_rx);
    1330           0 :                         json_object_int_add(json_bfd, "txMinInterval",
    1331           0 :                                             oi->bfd_config.min_tx);
    1332           0 :                         json_object_object_add(json_obj, "peerBfdInfo",
    1333             :                                                json_bfd);
    1334             :                 } else {
    1335           0 :                         vty_out(vty,
    1336             :                                 "  BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
    1337           0 :                                 oi->bfd_config.detection_multiplier,
    1338             :                                 oi->bfd_config.min_rx, oi->bfd_config.min_tx);
    1339             :                 }
    1340             :         }
    1341             : 
    1342           0 :         if (use_json)
    1343           0 :                 json_auth = json_object_new_object();
    1344           0 :         if (oi->at_data.flags != 0) {
    1345           0 :                 if (use_json) {
    1346           0 :                         if (CHECK_FLAG(oi->at_data.flags,
    1347             :                                        OSPF6_AUTH_TRAILER_KEYCHAIN)) {
    1348           0 :                                 json_object_string_add(json_auth, "authType",
    1349             :                                                        "keychain");
    1350           0 :                                 json_object_string_add(json_auth,
    1351             :                                                        "keychainName",
    1352           0 :                                                        oi->at_data.keychain);
    1353           0 :                         } else if (CHECK_FLAG(oi->at_data.flags,
    1354             :                                               OSPF6_AUTH_TRAILER_MANUAL_KEY))
    1355           0 :                                 json_object_string_add(json_auth, "authType",
    1356             :                                                        "manualkey");
    1357           0 :                         json_object_int_add(json_auth, "txPktDrop",
    1358           0 :                                             oi->at_data.tx_drop);
    1359           0 :                         json_object_int_add(json_auth, "rxPktDrop",
    1360           0 :                                             oi->at_data.rx_drop);
    1361             :                 } else {
    1362           0 :                         if (CHECK_FLAG(oi->at_data.flags,
    1363             :                                        OSPF6_AUTH_TRAILER_KEYCHAIN))
    1364           0 :                                 vty_out(vty,
    1365             :                                         "  Authentication Trailer is enabled with key-chain %s\n",
    1366             :                                         oi->at_data.keychain);
    1367           0 :                         else if (CHECK_FLAG(oi->at_data.flags,
    1368             :                                             OSPF6_AUTH_TRAILER_MANUAL_KEY))
    1369           0 :                                 vty_out(vty,
    1370             :                                         "  Authentication trailer is enabled with manual key\n");
    1371           0 :                         vty_out(vty,
    1372             :                                 "    Packet drop Tx %u, Packet drop Rx %u\n",
    1373             :                                 oi->at_data.tx_drop, oi->at_data.rx_drop);
    1374             :                 }
    1375             :         } else {
    1376           0 :                 if (use_json)
    1377           0 :                         json_object_string_add(json_auth, "authType", "NULL");
    1378             :                 else
    1379           0 :                         vty_out(vty, "  Authentication Trailer is disabled\n");
    1380             :         }
    1381             : 
    1382           0 :         if (use_json)
    1383           0 :                 json_object_object_add(json_obj, "authInfo", json_auth);
    1384             : 
    1385             :         return 0;
    1386             : }
    1387             : 
    1388             : /* Find the global address to be used as a forwarding address in NSSA LSA.*/
    1389           0 : struct in6_addr *ospf6_interface_get_global_address(struct interface *ifp)
    1390             : {
    1391           0 :         struct listnode *n;
    1392           0 :         struct connected *c;
    1393             : 
    1394             :         /* for each connected address */
    1395           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, n, c)) {
    1396             :                 /* if family not AF_INET6, ignore */
    1397           0 :                 if (c->address->family != AF_INET6)
    1398           0 :                         continue;
    1399             : 
    1400           0 :                 if (!IN6_IS_ADDR_LINKLOCAL(&c->address->u.prefix6))
    1401           0 :                         return &c->address->u.prefix6;
    1402             :         }
    1403             : 
    1404             :         return NULL;
    1405             : }
    1406             : 
    1407             : 
    1408           0 : static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
    1409             :                                        int argc, struct cmd_token **argv,
    1410             :                                        int idx_ifname, int intf_idx,
    1411             :                                        int json_idx, bool uj)
    1412             : {
    1413             : 
    1414           0 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
    1415           0 :         struct interface *ifp;
    1416           0 :         json_object *json;
    1417           0 :         json_object *json_int;
    1418             : 
    1419           0 :         if (uj) {
    1420           0 :                 json = json_object_new_object();
    1421           0 :                 if (argc == json_idx) {
    1422           0 :                         ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
    1423           0 :                         json_int = json_object_new_object();
    1424           0 :                         if (ifp == NULL) {
    1425           0 :                                 json_object_string_add(json, "noSuchInterface",
    1426           0 :                                                        argv[idx_ifname]->arg);
    1427           0 :                                 vty_json(vty, json);
    1428           0 :                                 json_object_free(json_int);
    1429           0 :                                 return CMD_WARNING;
    1430             :                         }
    1431           0 :                         ospf6_interface_show(vty, ifp, json_int, uj);
    1432           0 :                         json_object_object_add(json, ifp->name, json_int);
    1433             :                 } else {
    1434           0 :                         FOR_ALL_INTERFACES (vrf, ifp) {
    1435           0 :                                 json_int = json_object_new_object();
    1436           0 :                                 ospf6_interface_show(vty, ifp, json_int, uj);
    1437           0 :                                 json_object_object_add(json, ifp->name,
    1438             :                                                        json_int);
    1439             :                         }
    1440             :                 }
    1441           0 :                 vty_json(vty, json);
    1442             :         } else {
    1443           0 :                 if (argc == intf_idx) {
    1444           0 :                         ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
    1445           0 :                         if (ifp == NULL) {
    1446           0 :                                 vty_out(vty, "No such Interface: %s\n",
    1447           0 :                                         argv[idx_ifname]->arg);
    1448           0 :                                 return CMD_WARNING;
    1449             :                         }
    1450           0 :                         ospf6_interface_show(vty, ifp, NULL, uj);
    1451             :                 } else {
    1452           0 :                         FOR_ALL_INTERFACES (vrf, ifp)
    1453           0 :                                 ospf6_interface_show(vty, ifp, NULL, uj);
    1454             :                 }
    1455             :         }
    1456             :         return CMD_SUCCESS;
    1457             : }
    1458             : 
    1459             : #ifndef VTYSH_EXTRACT_PL
    1460             : #include "ospf6d/ospf6_interface_clippy.c"
    1461             : #endif
    1462             : 
    1463             : /* show interface */
    1464           0 : DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
    1465             :       "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
    1466             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1467             :       "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
    1468             : {
    1469           0 :         int idx_ifname = 4;
    1470           0 :         int intf_idx = 5;
    1471           0 :         int json_idx = 6;
    1472           0 :         struct listnode *node;
    1473           0 :         struct ospf6 *ospf6;
    1474           0 :         const char *vrf_name = NULL;
    1475           0 :         bool all_vrf = false;
    1476           0 :         int idx_vrf = 0;
    1477           0 :         bool uj = use_json(argc, argv);
    1478             : 
    1479           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1480           0 :         if (idx_vrf > 0) {
    1481           0 :                 idx_ifname += 2;
    1482           0 :                 intf_idx += 2;
    1483           0 :                 json_idx += 2;
    1484             :         }
    1485             : 
    1486           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1487           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1488           0 :                         show_ospf6_interface_common(vty, ospf6->vrf_id, argc,
    1489             :                                                     argv, idx_ifname, intf_idx,
    1490             :                                                     json_idx, uj);
    1491             : 
    1492           0 :                         if (!all_vrf)
    1493             :                                 break;
    1494             :                 }
    1495             :         }
    1496             : 
    1497           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1498             : 
    1499             :         return CMD_SUCCESS;
    1500             : }
    1501             : 
    1502           0 : static int ospf6_interface_show_traffic(struct vty *vty,
    1503             :                                         struct interface *intf_ifp,
    1504             :                                         int display_once, json_object *json,
    1505             :                                         bool use_json, vrf_id_t vrf_id)
    1506             : {
    1507           0 :         struct interface *ifp;
    1508           0 :         struct vrf *vrf = NULL;
    1509           0 :         struct ospf6_interface *oi = NULL;
    1510           0 :         json_object *json_interface;
    1511             : 
    1512           0 :         if (!display_once && !use_json) {
    1513           0 :                 vty_out(vty, "\n");
    1514           0 :                 vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
    1515             :                         "    HELLO", "    DB-Desc", "   LS-Req", "   LS-Update",
    1516             :                         "   LS-Ack");
    1517           0 :                 vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
    1518             :                         "      Rx/Tx", "     Rx/Tx", "    Rx/Tx", "    Rx/Tx",
    1519             :                         "    Rx/Tx");
    1520           0 :                 vty_out(vty,
    1521             :                         "--------------------------------------------------------------------------------------------\n");
    1522             :         }
    1523             : 
    1524           0 :         if (intf_ifp == NULL) {
    1525           0 :                 vrf = vrf_lookup_by_id(vrf_id);
    1526           0 :                 FOR_ALL_INTERFACES (vrf, ifp) {
    1527           0 :                         if (ifp->info)
    1528           0 :                                 oi = (struct ospf6_interface *)ifp->info;
    1529             :                         else
    1530           0 :                                 continue;
    1531             : 
    1532           0 :                         if (use_json) {
    1533           0 :                                 json_interface = json_object_new_object();
    1534           0 :                                 json_object_int_add(json_interface, "helloRx",
    1535           0 :                                                     oi->hello_in);
    1536           0 :                                 json_object_int_add(json_interface, "helloTx",
    1537           0 :                                                     oi->hello_out);
    1538           0 :                                 json_object_int_add(json_interface, "dbDescRx",
    1539           0 :                                                     oi->db_desc_in);
    1540           0 :                                 json_object_int_add(json_interface, "dbDescTx",
    1541           0 :                                                     oi->db_desc_out);
    1542           0 :                                 json_object_int_add(json_interface, "lsReqRx",
    1543           0 :                                                     oi->ls_req_in);
    1544           0 :                                 json_object_int_add(json_interface, "lsReqTx",
    1545           0 :                                                     oi->ls_req_out);
    1546           0 :                                 json_object_int_add(json_interface,
    1547             :                                                     "lsUpdateRx",
    1548           0 :                                                     oi->ls_upd_in);
    1549           0 :                                 json_object_int_add(json_interface,
    1550             :                                                     "lsUpdateTx",
    1551           0 :                                                     oi->ls_upd_out);
    1552           0 :                                 json_object_int_add(json_interface, "lsAckRx",
    1553           0 :                                                     oi->ls_ack_in);
    1554           0 :                                 json_object_int_add(json_interface, "lsAckTx",
    1555           0 :                                                     oi->ls_ack_out);
    1556             : 
    1557           0 :                                 json_object_object_add(json,
    1558             :                                                        ospf6_ifname(oi),
    1559             :                                                        json_interface);
    1560             :                         } else
    1561           0 :                                 vty_out(vty,
    1562             :                                         "%-10pOI %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
    1563             :                                         oi, oi->hello_in, oi->hello_out,
    1564             :                                         oi->db_desc_in, oi->db_desc_out,
    1565             :                                         oi->ls_req_in, oi->ls_req_out,
    1566             :                                         oi->ls_upd_in, oi->ls_upd_out,
    1567             :                                         oi->ls_ack_in, oi->ls_ack_out);
    1568             :                 }
    1569             :         } else {
    1570           0 :                 oi = intf_ifp->info;
    1571           0 :                 if (oi == NULL)
    1572             :                         return CMD_WARNING;
    1573             : 
    1574           0 :                 if (use_json) {
    1575           0 :                         json_interface = json_object_new_object();
    1576           0 :                         json_object_int_add(json_interface, "helloRx",
    1577           0 :                                             oi->hello_in);
    1578           0 :                         json_object_int_add(json_interface, "helloTx",
    1579           0 :                                             oi->hello_out);
    1580           0 :                         json_object_int_add(json_interface, "dbDescRx",
    1581           0 :                                             oi->db_desc_in);
    1582           0 :                         json_object_int_add(json_interface, "dbDescTx",
    1583           0 :                                             oi->db_desc_out);
    1584           0 :                         json_object_int_add(json_interface, "lsReqRx",
    1585           0 :                                             oi->ls_req_in);
    1586           0 :                         json_object_int_add(json_interface, "lsReqTx",
    1587           0 :                                             oi->ls_req_out);
    1588           0 :                         json_object_int_add(json_interface, "lsUpdateRx",
    1589           0 :                                             oi->ls_upd_in);
    1590           0 :                         json_object_int_add(json_interface, "lsUpdateTx",
    1591           0 :                                             oi->ls_upd_out);
    1592           0 :                         json_object_int_add(json_interface, "lsAckRx",
    1593           0 :                                             oi->ls_ack_in);
    1594           0 :                         json_object_int_add(json_interface, "lsAckTx",
    1595           0 :                                             oi->ls_ack_out);
    1596             : 
    1597           0 :                         json_object_object_add(json, ospf6_ifname(oi),
    1598             :                                                json_interface);
    1599             :                 } else
    1600           0 :                         vty_out(vty,
    1601             :                                 "%-10pOI %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
    1602             :                                 oi, oi->hello_in, oi->hello_out,
    1603             :                                 oi->db_desc_in, oi->db_desc_out,
    1604             :                                 oi->ls_req_in, oi->ls_req_out,
    1605             :                                 oi->ls_upd_in, oi->ls_upd_out,
    1606             :                                 oi->ls_ack_in, oi->ls_ack_out);
    1607             :         }
    1608             : 
    1609             :         return CMD_SUCCESS;
    1610             : }
    1611             : 
    1612           0 : static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
    1613             :                                                struct cmd_token **argv,
    1614             :                                                vrf_id_t vrf_id, bool uj)
    1615             : {
    1616           0 :         int idx_ifname = 0;
    1617           0 :         int display_once = 0;
    1618           0 :         char *intf_name = NULL;
    1619           0 :         struct interface *ifp = NULL;
    1620           0 :         json_object *json = NULL;
    1621             : 
    1622           0 :         if (uj)
    1623           0 :                 json = json_object_new_object();
    1624             : 
    1625           0 :         if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
    1626           0 :                 intf_name = argv[idx_ifname]->arg;
    1627           0 :                 ifp = if_lookup_by_name(intf_name, vrf_id);
    1628           0 :                 if (uj) {
    1629           0 :                         if (ifp == NULL) {
    1630           0 :                                 json_object_string_add(json, "status",
    1631             :                                                        "No Such Interface");
    1632           0 :                                 json_object_string_add(json, "interface",
    1633             :                                                        intf_name);
    1634           0 :                                 vty_json(vty, json);
    1635           0 :                                 return CMD_WARNING;
    1636             :                         }
    1637           0 :                         if (ifp->info == NULL) {
    1638           0 :                                 json_object_string_add(
    1639             :                                         json, "status",
    1640             :                                         "OSPF not enabled on this interface");
    1641           0 :                                 json_object_string_add(json, "interface",
    1642             :                                                        intf_name);
    1643           0 :                                 vty_json(vty, json);
    1644           0 :                                 return 0;
    1645             :                         }
    1646             :                 } else {
    1647           0 :                         if (ifp == NULL) {
    1648           0 :                                 vty_out(vty, "No such Interface: %s\n",
    1649             :                                         intf_name);
    1650           0 :                                 return CMD_WARNING;
    1651             :                         }
    1652           0 :                         if (ifp->info == NULL) {
    1653           0 :                                 vty_out(vty,
    1654             :                                         "   OSPF not enabled on this interface %s\n",
    1655             :                                         intf_name);
    1656           0 :                                 return 0;
    1657             :                         }
    1658             :                 }
    1659             :         }
    1660             : 
    1661           0 :         ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
    1662             : 
    1663           0 :         if (uj)
    1664           0 :                 vty_json(vty, json);
    1665             : 
    1666             :         return CMD_SUCCESS;
    1667             : }
    1668             : 
    1669             : /* show interface */
    1670           0 : DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
    1671             :       "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
    1672             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1673             :       "All VRFs\n" INTERFACE_STR
    1674             :       "Protocol Packet counters\n" IFNAME_STR JSON_STR)
    1675             : {
    1676           0 :         struct ospf6 *ospf6;
    1677           0 :         struct listnode *node;
    1678           0 :         const char *vrf_name = NULL;
    1679           0 :         bool all_vrf = false;
    1680           0 :         int idx_vrf = 0;
    1681           0 :         bool uj = use_json(argc, argv);
    1682             : 
    1683           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1684             : 
    1685           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1686           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1687           0 :                         ospf6_interface_show_traffic_common(vty, argc, argv,
    1688             :                                                             ospf6->vrf_id, uj);
    1689             : 
    1690           0 :                         if (!all_vrf)
    1691             :                                 break;
    1692             :                 }
    1693             :         }
    1694             : 
    1695           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1696             : 
    1697             :         return CMD_SUCCESS;
    1698             : }
    1699             : 
    1700             : 
    1701           0 : DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
    1702             :       show_ipv6_ospf6_interface_ifname_prefix_cmd,
    1703             :       "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
    1704             :           [<\
    1705             :             detail\
    1706             :             |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
    1707             :           >] [json]",
    1708             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1709             :       "All VRFs\n" INTERFACE_STR IFNAME_STR
    1710             :       "Display connected prefixes to advertise\n"
    1711             :       "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
    1712             :               OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
    1713             :       "Display details of the prefixes\n" JSON_STR)
    1714             : {
    1715           0 :         int idx_ifname = 4;
    1716           0 :         int idx_prefix = 6;
    1717           0 :         struct ospf6_interface *oi;
    1718           0 :         bool uj = use_json(argc, argv);
    1719             : 
    1720           0 :         struct ospf6 *ospf6;
    1721           0 :         struct listnode *node;
    1722           0 :         struct interface *ifp;
    1723           0 :         const char *vrf_name = NULL;
    1724           0 :         bool all_vrf = false;
    1725           0 :         int idx_vrf = 0;
    1726             : 
    1727           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1728           0 :         if (idx_vrf > 0) {
    1729           0 :                 idx_ifname += 2;
    1730           0 :                 idx_prefix += 2;
    1731             :         }
    1732             : 
    1733           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1734           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1735           0 :                         ifp = if_lookup_by_name(argv[idx_ifname]->arg,
    1736             :                                                 ospf6->vrf_id);
    1737           0 :                         if (ifp == NULL) {
    1738           0 :                                 vty_out(vty, "No such Interface: %s\n",
    1739           0 :                                         argv[idx_ifname]->arg);
    1740           0 :                                 return CMD_WARNING;
    1741             :                         }
    1742             : 
    1743           0 :                         oi = ifp->info;
    1744           0 :                         if (oi == NULL
    1745           0 :                             || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
    1746           0 :                                 vty_out(vty,
    1747             :                                         "Interface %s not attached to area\n",
    1748           0 :                                         argv[idx_ifname]->arg);
    1749           0 :                                 return CMD_WARNING;
    1750             :                         }
    1751             : 
    1752           0 :                         ospf6_route_table_show(vty, idx_prefix, argc, argv,
    1753             :                                                oi->route_connected, uj);
    1754             : 
    1755           0 :                         if (!all_vrf)
    1756             :                                 break;
    1757             :                 }
    1758             :         }
    1759             : 
    1760           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1761             : 
    1762             :         return CMD_SUCCESS;
    1763             : }
    1764             : 
    1765           0 : DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
    1766             :       "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
    1767             :           [<\
    1768             :             detail\
    1769             :             |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
    1770             :           >] [json]",
    1771             :       SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
    1772             :       "All VRFs\n" INTERFACE_STR
    1773             :       "Display connected prefixes to advertise\n"
    1774             :       "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
    1775             :               OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
    1776             :       "Display details of the prefixes\n" JSON_STR)
    1777             : {
    1778           0 :         struct vrf *vrf = NULL;
    1779           0 :         int idx_prefix = 5;
    1780           0 :         struct ospf6_interface *oi;
    1781           0 :         struct interface *ifp;
    1782           0 :         bool uj = use_json(argc, argv);
    1783           0 :         struct listnode *node;
    1784           0 :         struct ospf6 *ospf6;
    1785           0 :         const char *vrf_name = NULL;
    1786           0 :         bool all_vrf = false;
    1787           0 :         int idx_vrf = 0;
    1788             : 
    1789           0 :         OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
    1790           0 :         if (idx_vrf > 0)
    1791           0 :                 idx_prefix += 2;
    1792             : 
    1793           0 :         for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
    1794           0 :                 if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
    1795           0 :                         vrf = vrf_lookup_by_id(ospf6->vrf_id);
    1796           0 :                         FOR_ALL_INTERFACES (vrf, ifp) {
    1797           0 :                                 oi = (struct ospf6_interface *)ifp->info;
    1798           0 :                                 if (oi == NULL
    1799           0 :                                     || CHECK_FLAG(oi->flag,
    1800             :                                                   OSPF6_INTERFACE_DISABLE))
    1801           0 :                                         continue;
    1802             : 
    1803           0 :                                 ospf6_route_table_show(vty, idx_prefix, argc,
    1804             :                                                        argv,
    1805             :                                                        oi->route_connected, uj);
    1806             :                         }
    1807           0 :                         if (!all_vrf)
    1808             :                                 break;
    1809             :                 }
    1810             :         }
    1811             : 
    1812           0 :         OSPF6_CMD_CHECK_VRF(uj, all_vrf, ospf6);
    1813             : 
    1814             :         return CMD_SUCCESS;
    1815             : }
    1816             : 
    1817         136 : void ospf6_interface_start(struct ospf6_interface *oi)
    1818             : {
    1819         136 :         struct ospf6 *ospf6;
    1820         136 :         struct ospf6_area *oa;
    1821             : 
    1822         136 :         if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
    1823             :                 return;
    1824             : 
    1825         127 :         if (oi->area) {
    1826             :                 /* Recompute cost */
    1827          87 :                 ospf6_interface_recalculate_cost(oi);
    1828          87 :                 return;
    1829             :         }
    1830             : 
    1831          40 :         ospf6 = oi->interface->vrf->info;
    1832          40 :         if (!ospf6)
    1833             :                 return;
    1834             : 
    1835          20 :         oa = ospf6_area_lookup(oi->area_id, ospf6);
    1836          20 :         if (oa == NULL)
    1837          14 :                 oa = ospf6_area_create(oi->area_id, ospf6, oi->area_id_format);
    1838             : 
    1839             :         /* attach interface to area */
    1840          20 :         listnode_add(oa->if_list, oi);
    1841          20 :         oi->area = oa;
    1842             : 
    1843          20 :         SET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
    1844             : 
    1845             :         /* start up */
    1846          20 :         ospf6_interface_enable(oi);
    1847             : 
    1848             :         /* If the router is ABR, originate summary routes */
    1849          20 :         if (ospf6_check_and_set_router_abr(ospf6)) {
    1850           2 :                 ospf6_abr_enable_area(oa);
    1851           2 :                 ospf6_schedule_abr_task(ospf6);
    1852             :         }
    1853             : }
    1854             : 
    1855           0 : void ospf6_interface_stop(struct ospf6_interface *oi)
    1856             : {
    1857           0 :         struct ospf6_area *oa;
    1858             : 
    1859           0 :         oa = oi->area;
    1860           0 :         if (!oa)
    1861             :                 return;
    1862             : 
    1863           0 :         ospf6_interface_disable(oi);
    1864             : 
    1865           0 :         listnode_delete(oa->if_list, oi);
    1866           0 :         oi->area = NULL;
    1867             : 
    1868           0 :         if (oa->if_list->count == 0) {
    1869           0 :                 UNSET_FLAG(oa->flag, OSPF6_AREA_ENABLE);
    1870           0 :                 ospf6_abr_disable_area(oa);
    1871             :         }
    1872             : }
    1873             : 
    1874             : /* interface variable set command */
    1875          20 : DEFUN (ipv6_ospf6_area,
    1876             :        ipv6_ospf6_area_cmd,
    1877             :        "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
    1878             :        IP6_STR
    1879             :        OSPF6_STR
    1880             :        "Specify the OSPF6 area ID\n"
    1881             :        "OSPF6 area ID in IPv4 address notation\n"
    1882             :        "OSPF6 area ID in decimal notation\n")
    1883             : {
    1884          20 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1885          20 :         struct ospf6_interface *oi;
    1886          20 :         int idx_ipv4 = 3;
    1887          20 :         uint32_t area_id;
    1888          20 :         int format;
    1889             : 
    1890          20 :         assert(ifp);
    1891             : 
    1892          20 :         oi = (struct ospf6_interface *)ifp->info;
    1893          20 :         if (oi == NULL)
    1894          20 :                 oi = ospf6_interface_create(ifp);
    1895          20 :         assert(oi);
    1896             : 
    1897          20 :         if (oi->area) {
    1898           0 :                 vty_out(vty, "%pOI already attached to Area %s\n", oi,
    1899           0 :                         oi->area->name);
    1900           0 :                 return CMD_SUCCESS;
    1901             :         }
    1902             : 
    1903          20 :         if (str2area_id(argv[idx_ipv4]->arg, &area_id, &format)) {
    1904           0 :                 vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
    1905           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1906             :         }
    1907             : 
    1908          20 :         oi->area_id = area_id;
    1909          20 :         oi->area_id_format = format;
    1910             : 
    1911          20 :         ospf6_interface_start(oi);
    1912             : 
    1913          20 :         return CMD_SUCCESS;
    1914             : }
    1915             : 
    1916           0 : DEFUN (no_ipv6_ospf6_area,
    1917             :        no_ipv6_ospf6_area_cmd,
    1918             :        "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
    1919             :        NO_STR
    1920             :        IP6_STR
    1921             :        OSPF6_STR
    1922             :        "Specify the OSPF6 area ID\n"
    1923             :        "OSPF6 area ID in IPv4 address notation\n"
    1924             :        "OSPF6 area ID in decimal notation\n")
    1925             : {
    1926           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1927           0 :         struct ospf6_interface *oi;
    1928             : 
    1929           0 :         assert(ifp);
    1930             : 
    1931           0 :         oi = (struct ospf6_interface *)ifp->info;
    1932           0 :         if (oi == NULL)
    1933           0 :                 oi = ospf6_interface_create(ifp);
    1934           0 :         assert(oi);
    1935             : 
    1936           0 :         ospf6_interface_stop(oi);
    1937             : 
    1938           0 :         oi->area_id = 0;
    1939           0 :         oi->area_id_format = OSPF6_AREA_FMT_UNSET;
    1940             : 
    1941           0 :         return CMD_SUCCESS;
    1942             : }
    1943             : 
    1944           0 : DEFUN (ipv6_ospf6_ifmtu,
    1945             :        ipv6_ospf6_ifmtu_cmd,
    1946             :        "ipv6 ospf6 ifmtu (1-65535)",
    1947             :        IP6_STR
    1948             :        OSPF6_STR
    1949             :        "Interface MTU\n"
    1950             :        "OSPFv3 Interface MTU\n"
    1951             :        )
    1952             : {
    1953           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    1954           0 :         int idx_number = 3;
    1955           0 :         struct ospf6_interface *oi;
    1956           0 :         unsigned int ifmtu, iobuflen;
    1957           0 :         struct listnode *node, *nnode;
    1958           0 :         struct ospf6_neighbor *on;
    1959             : 
    1960           0 :         assert(ifp);
    1961             : 
    1962           0 :         oi = (struct ospf6_interface *)ifp->info;
    1963           0 :         if (oi == NULL)
    1964           0 :                 oi = ospf6_interface_create(ifp);
    1965           0 :         assert(oi);
    1966             : 
    1967           0 :         ifmtu = strtol(argv[idx_number]->arg, NULL, 10);
    1968             : 
    1969           0 :         if (oi->c_ifmtu == ifmtu)
    1970             :                 return CMD_SUCCESS;
    1971             : 
    1972           0 :         if (ifp->mtu6 != 0 && ifp->mtu6 < ifmtu) {
    1973           0 :                 vty_out(vty,
    1974             :                         "%s's ospf6 ifmtu cannot go beyond physical mtu (%d)\n",
    1975           0 :                         ifp->name, ifp->mtu6);
    1976           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1977             :         }
    1978             : 
    1979           0 :         if (oi->ifmtu < ifmtu) {
    1980           0 :                 iobuflen = ospf6_iobuf_size(ifmtu);
    1981           0 :                 if (iobuflen < ifmtu) {
    1982           0 :                         vty_out(vty,
    1983             :                                 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
    1984           0 :                                 ifp->name, iobuflen);
    1985           0 :                         oi->ifmtu = oi->c_ifmtu = iobuflen;
    1986             :                 } else
    1987           0 :                         oi->ifmtu = oi->c_ifmtu = ifmtu;
    1988             :         } else
    1989           0 :                 oi->ifmtu = oi->c_ifmtu = ifmtu;
    1990             : 
    1991             :         /* re-establish adjacencies */
    1992           0 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
    1993           0 :                 THREAD_OFF(on->inactivity_timer);
    1994           0 :                 thread_add_event(master, inactivity_timer, on, 0, NULL);
    1995             :         }
    1996             : 
    1997             :         return CMD_SUCCESS;
    1998             : }
    1999             : 
    2000           0 : DEFUN (no_ipv6_ospf6_ifmtu,
    2001             :        no_ipv6_ospf6_ifmtu_cmd,
    2002             :        "no ipv6 ospf6 ifmtu [(1-65535)]",
    2003             :        NO_STR
    2004             :        IP6_STR
    2005             :        OSPF6_STR
    2006             :        "Interface MTU\n"
    2007             :        "OSPFv3 Interface MTU\n"
    2008             :        )
    2009             : {
    2010           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2011           0 :         struct ospf6_interface *oi;
    2012           0 :         unsigned int iobuflen;
    2013           0 :         struct listnode *node, *nnode;
    2014           0 :         struct ospf6_neighbor *on;
    2015             : 
    2016           0 :         assert(ifp);
    2017             : 
    2018           0 :         oi = (struct ospf6_interface *)ifp->info;
    2019           0 :         if (oi == NULL)
    2020           0 :                 oi = ospf6_interface_create(ifp);
    2021           0 :         assert(oi);
    2022             : 
    2023           0 :         if (oi->ifmtu < ifp->mtu) {
    2024           0 :                 iobuflen = ospf6_iobuf_size(ifp->mtu);
    2025           0 :                 if (iobuflen < ifp->mtu) {
    2026           0 :                         vty_out(vty,
    2027             :                                 "%s's ifmtu is adjusted to I/O buffer size (%d).\n",
    2028           0 :                                 ifp->name, iobuflen);
    2029           0 :                         oi->ifmtu = iobuflen;
    2030             :                 } else
    2031           0 :                         oi->ifmtu = ifp->mtu;
    2032             :         } else
    2033           0 :                 oi->ifmtu = ifp->mtu;
    2034             : 
    2035           0 :         oi->c_ifmtu = 0;
    2036             : 
    2037             :         /* re-establish adjacencies */
    2038           0 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
    2039           0 :                 THREAD_OFF(on->inactivity_timer);
    2040           0 :                 thread_add_event(master, inactivity_timer, on, 0, NULL);
    2041             :         }
    2042             : 
    2043             :         return CMD_SUCCESS;
    2044             : }
    2045             : 
    2046           0 : DEFUN (ipv6_ospf6_cost,
    2047             :        ipv6_ospf6_cost_cmd,
    2048             :        "ipv6 ospf6 cost (1-65535)",
    2049             :        IP6_STR
    2050             :        OSPF6_STR
    2051             :        "Interface cost\n"
    2052             :        "Outgoing metric of this interface\n")
    2053             : {
    2054           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2055           0 :         int idx_number = 3;
    2056           0 :         struct ospf6_interface *oi;
    2057           0 :         unsigned long int lcost;
    2058             : 
    2059           0 :         assert(ifp);
    2060             : 
    2061           0 :         oi = (struct ospf6_interface *)ifp->info;
    2062           0 :         if (oi == NULL)
    2063           0 :                 oi = ospf6_interface_create(ifp);
    2064           0 :         assert(oi);
    2065             : 
    2066           0 :         lcost = strtol(argv[idx_number]->arg, NULL, 10);
    2067             : 
    2068           0 :         if (lcost > UINT32_MAX) {
    2069           0 :                 vty_out(vty, "Cost %ld is out of range\n", lcost);
    2070           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2071             :         }
    2072             : 
    2073           0 :         SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
    2074           0 :         if (oi->cost == lcost)
    2075             :                 return CMD_SUCCESS;
    2076             : 
    2077           0 :         oi->cost = lcost;
    2078           0 :         ospf6_interface_force_recalculate_cost(oi);
    2079             : 
    2080           0 :         return CMD_SUCCESS;
    2081             : }
    2082             : 
    2083           0 : DEFUN (no_ipv6_ospf6_cost,
    2084             :        no_ipv6_ospf6_cost_cmd,
    2085             :        "no ipv6 ospf6 cost [(1-65535)]",
    2086             :        NO_STR
    2087             :        IP6_STR
    2088             :        OSPF6_STR
    2089             :        "Calculate interface cost from bandwidth\n"
    2090             :        "Outgoing metric of this interface\n")
    2091             : {
    2092           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2093           0 :         struct ospf6_interface *oi;
    2094           0 :         assert(ifp);
    2095             : 
    2096           0 :         oi = (struct ospf6_interface *)ifp->info;
    2097           0 :         if (oi == NULL)
    2098           0 :                 oi = ospf6_interface_create(ifp);
    2099           0 :         assert(oi);
    2100             : 
    2101           0 :         UNSET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
    2102             : 
    2103           0 :         ospf6_interface_recalculate_cost(oi);
    2104             : 
    2105           0 :         return CMD_SUCCESS;
    2106             : }
    2107             : 
    2108           0 : DEFUN (auto_cost_reference_bandwidth,
    2109             :        auto_cost_reference_bandwidth_cmd,
    2110             :        "auto-cost reference-bandwidth (1-4294967)",
    2111             :        "Calculate OSPF interface cost according to bandwidth\n"
    2112             :        "Use reference bandwidth method to assign OSPF cost\n"
    2113             :        "The reference bandwidth in terms of Mbits per second\n")
    2114             : {
    2115           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    2116           0 :         int idx_number = 2;
    2117           0 :         struct ospf6_area *oa;
    2118           0 :         struct ospf6_interface *oi;
    2119           0 :         struct listnode *i, *j;
    2120           0 :         uint32_t refbw;
    2121             : 
    2122           0 :         refbw = strtol(argv[idx_number]->arg, NULL, 10);
    2123           0 :         if (refbw < 1 || refbw > 4294967) {
    2124           0 :                 vty_out(vty, "reference-bandwidth value is invalid\n");
    2125           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2126             :         }
    2127             : 
    2128             :         /* If reference bandwidth is changed. */
    2129           0 :         if ((refbw) == o->ref_bandwidth)
    2130             :                 return CMD_SUCCESS;
    2131             : 
    2132           0 :         o->ref_bandwidth = refbw;
    2133           0 :         for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
    2134           0 :                 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
    2135           0 :                         ospf6_interface_recalculate_cost(oi);
    2136             : 
    2137             :         return CMD_SUCCESS;
    2138             : }
    2139             : 
    2140           0 : DEFUN (no_auto_cost_reference_bandwidth,
    2141             :        no_auto_cost_reference_bandwidth_cmd,
    2142             :        "no auto-cost reference-bandwidth [(1-4294967)]",
    2143             :        NO_STR
    2144             :        "Calculate OSPF interface cost according to bandwidth\n"
    2145             :        "Use reference bandwidth method to assign OSPF cost\n"
    2146             :        "The reference bandwidth in terms of Mbits per second\n")
    2147             : {
    2148           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    2149           0 :         struct ospf6_area *oa;
    2150           0 :         struct ospf6_interface *oi;
    2151           0 :         struct listnode *i, *j;
    2152             : 
    2153           0 :         if (o->ref_bandwidth == OSPF6_REFERENCE_BANDWIDTH)
    2154             :                 return CMD_SUCCESS;
    2155             : 
    2156           0 :         o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
    2157           0 :         for (ALL_LIST_ELEMENTS_RO(o->area_list, i, oa))
    2158           0 :                 for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
    2159           0 :                         ospf6_interface_recalculate_cost(oi);
    2160             : 
    2161             :         return CMD_SUCCESS;
    2162             : }
    2163             : 
    2164             : 
    2165           0 : DEFUN (ospf6_write_multiplier,
    2166             :        ospf6_write_multiplier_cmd,
    2167             :        "write-multiplier (1-100)",
    2168             :        "Write multiplier\n"
    2169             :        "Maximum number of interface serviced per write\n")
    2170             : {
    2171           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    2172           0 :         uint32_t write_oi_count;
    2173             : 
    2174           0 :         write_oi_count = strtol(argv[1]->arg, NULL, 10);
    2175           0 :         if (write_oi_count < 1 || write_oi_count > 100) {
    2176           0 :                 vty_out(vty, "write-multiplier value is invalid\n");
    2177           0 :                 return CMD_WARNING_CONFIG_FAILED;
    2178             :         }
    2179             : 
    2180           0 :         o->write_oi_count = write_oi_count;
    2181           0 :         return CMD_SUCCESS;
    2182             : }
    2183             : 
    2184           0 : DEFUN (no_ospf6_write_multiplier,
    2185             :        no_ospf6_write_multiplier_cmd,
    2186             :        "no write-multiplier (1-100)",
    2187             :        NO_STR
    2188             :        "Write multiplier\n"
    2189             :        "Maximum number of interface serviced per write\n")
    2190             : {
    2191           0 :         VTY_DECLVAR_CONTEXT(ospf6, o);
    2192             : 
    2193           0 :         o->write_oi_count = OSPF6_WRITE_INTERFACE_COUNT_DEFAULT;
    2194           0 :         return CMD_SUCCESS;
    2195             : }
    2196             : 
    2197          29 : DEFUN (ipv6_ospf6_hellointerval,
    2198             :        ipv6_ospf6_hellointerval_cmd,
    2199             :        "ipv6 ospf6 hello-interval (1-65535)",
    2200             :        IP6_STR
    2201             :        OSPF6_STR
    2202             :        "Time between HELLO packets\n"
    2203             :        SECONDS_STR)
    2204             : {
    2205          29 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2206          29 :         int idx_number = 3;
    2207          29 :         struct ospf6_interface *oi;
    2208          29 :         assert(ifp);
    2209             : 
    2210          29 :         oi = (struct ospf6_interface *)ifp->info;
    2211          29 :         if (oi == NULL)
    2212           9 :                 oi = ospf6_interface_create(ifp);
    2213          29 :         assert(oi);
    2214             : 
    2215          58 :         oi->hello_interval = strmatch(argv[0]->text, "no")
    2216             :                                      ? OSPF_HELLO_INTERVAL_DEFAULT
    2217          29 :                                      : strtoul(argv[idx_number]->arg, NULL, 10);
    2218             : 
    2219             :         /*
    2220             :          * If the thread is scheduled, send the new hello now.
    2221             :          */
    2222          29 :         if (thread_is_scheduled(oi->thread_send_hello)) {
    2223           0 :                 THREAD_OFF(oi->thread_send_hello);
    2224             : 
    2225           0 :                 thread_add_timer(master, ospf6_hello_send, oi, 0,
    2226             :                                  &oi->thread_send_hello);
    2227             :         }
    2228             :         return CMD_SUCCESS;
    2229             : }
    2230             : 
    2231             : ALIAS (ipv6_ospf6_hellointerval,
    2232             :        no_ipv6_ospf6_hellointerval_cmd,
    2233             :        "no ipv6 ospf6 hello-interval [(1-65535)]",
    2234             :        NO_STR
    2235             :        IP6_STR
    2236             :        OSPF6_STR
    2237             :        "Time between HELLO packets\n"
    2238             :        SECONDS_STR)
    2239             : 
    2240             : /* interface variable set command */
    2241          29 : DEFUN (ipv6_ospf6_deadinterval,
    2242             :        ipv6_ospf6_deadinterval_cmd,
    2243             :        "ipv6 ospf6 dead-interval (1-65535)",
    2244             :        IP6_STR
    2245             :        OSPF6_STR
    2246             :        "Interval time after which a neighbor is declared down\n"
    2247             :        SECONDS_STR)
    2248             : {
    2249          29 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2250          29 :         int idx_number = 3;
    2251          29 :         struct ospf6_interface *oi;
    2252          29 :         assert(ifp);
    2253             : 
    2254          29 :         oi = (struct ospf6_interface *)ifp->info;
    2255          29 :         if (oi == NULL)
    2256           0 :                 oi = ospf6_interface_create(ifp);
    2257          29 :         assert(oi);
    2258             : 
    2259          58 :         oi->dead_interval = strmatch(argv[0]->arg, "no")
    2260             :                                     ? OSPF_ROUTER_DEAD_INTERVAL_DEFAULT
    2261          29 :                                     : strtoul(argv[idx_number]->arg, NULL, 10);
    2262          29 :         return CMD_SUCCESS;
    2263             : }
    2264             : 
    2265             : ALIAS (ipv6_ospf6_deadinterval,
    2266             :        no_ipv6_ospf6_deadinterval_cmd,
    2267             :        "no ipv6 ospf6 dead-interval [(1-65535)]",
    2268             :        NO_STR
    2269             :        IP6_STR
    2270             :        OSPF6_STR
    2271             :        "Interval time after which a neighbor is declared down\n"
    2272             :        SECONDS_STR)
    2273             : 
    2274             : /* interface variable set command */
    2275           0 : DEFUN (ipv6_ospf6_transmitdelay,
    2276             :        ipv6_ospf6_transmitdelay_cmd,
    2277             :        "ipv6 ospf6 transmit-delay (1-3600)",
    2278             :        IP6_STR
    2279             :        OSPF6_STR
    2280             :        "Link state transmit delay\n"
    2281             :        SECONDS_STR)
    2282             : {
    2283           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2284           0 :         int idx_number = 3;
    2285           0 :         struct ospf6_interface *oi;
    2286           0 :         assert(ifp);
    2287             : 
    2288           0 :         oi = (struct ospf6_interface *)ifp->info;
    2289           0 :         if (oi == NULL)
    2290           0 :                 oi = ospf6_interface_create(ifp);
    2291           0 :         assert(oi);
    2292             : 
    2293           0 :         oi->transdelay = strmatch(argv[0]->text, "no")
    2294             :                                  ? OSPF6_INTERFACE_TRANSDELAY
    2295           0 :                                  : strtoul(argv[idx_number]->arg, NULL, 10);
    2296           0 :         return CMD_SUCCESS;
    2297             : }
    2298             : 
    2299             : ALIAS (ipv6_ospf6_transmitdelay,
    2300             :        no_ipv6_ospf6_transmitdelay_cmd,
    2301             :        "no ipv6 ospf6 transmit-delay [(1-3600)]",
    2302             :        NO_STR
    2303             :        IP6_STR
    2304             :        OSPF6_STR
    2305             :        "Link state transmit delay\n"
    2306             :        SECONDS_STR)
    2307             : 
    2308             : /* interface variable set command */
    2309          29 : DEFUN (ipv6_ospf6_retransmitinterval,
    2310             :        ipv6_ospf6_retransmitinterval_cmd,
    2311             :        "ipv6 ospf6 retransmit-interval (1-65535)",
    2312             :        IP6_STR
    2313             :        OSPF6_STR
    2314             :        "Time between retransmitting lost link state advertisements\n"
    2315             :        SECONDS_STR)
    2316             : {
    2317          29 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2318          29 :         int idx_number = 3;
    2319          29 :         struct ospf6_interface *oi;
    2320          29 :         assert(ifp);
    2321             : 
    2322          29 :         oi = (struct ospf6_interface *)ifp->info;
    2323          29 :         if (oi == NULL)
    2324           0 :                 oi = ospf6_interface_create(ifp);
    2325          29 :         assert(oi);
    2326             : 
    2327          58 :         oi->rxmt_interval = strmatch(argv[0]->text, "no")
    2328             :                                     ? OSPF_RETRANSMIT_INTERVAL_DEFAULT
    2329          29 :                                     : strtoul(argv[idx_number]->arg, NULL, 10);
    2330          29 :         return CMD_SUCCESS;
    2331             : }
    2332             : 
    2333             : ALIAS (ipv6_ospf6_retransmitinterval,
    2334             :        no_ipv6_ospf6_retransmitinterval_cmd,
    2335             :        "no ipv6 ospf6 retransmit-interval [(1-65535)]",
    2336             :        NO_STR
    2337             :        IP6_STR
    2338             :        OSPF6_STR
    2339             :        "Time between retransmitting lost link state advertisements\n"
    2340             :        SECONDS_STR)
    2341             : 
    2342             : /* interface variable set command */
    2343           0 : DEFUN (ipv6_ospf6_priority,
    2344             :        ipv6_ospf6_priority_cmd,
    2345             :        "ipv6 ospf6 priority (0-255)",
    2346             :        IP6_STR
    2347             :        OSPF6_STR
    2348             :        "Router priority\n"
    2349             :        "Priority value\n")
    2350             : {
    2351           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2352           0 :         int idx_number = 3;
    2353           0 :         struct ospf6_interface *oi;
    2354           0 :         assert(ifp);
    2355             : 
    2356           0 :         oi = (struct ospf6_interface *)ifp->info;
    2357           0 :         if (oi == NULL)
    2358           0 :                 oi = ospf6_interface_create(ifp);
    2359           0 :         assert(oi);
    2360             : 
    2361           0 :         oi->priority = strmatch(argv[0]->text, "no")
    2362             :                                ? OSPF6_INTERFACE_PRIORITY
    2363           0 :                                : strtoul(argv[idx_number]->arg, NULL, 10);
    2364             : 
    2365           0 :         if (oi->area
    2366           0 :             && (oi->state == OSPF6_INTERFACE_DROTHER
    2367             :                 || oi->state == OSPF6_INTERFACE_BDR
    2368           0 :                 || oi->state == OSPF6_INTERFACE_DR)) {
    2369           0 :                 if (ospf6_interface_state_change(dr_election(oi), oi) == -1)
    2370           0 :                         OSPF6_LINK_LSA_SCHEDULE(oi);
    2371             :         }
    2372             : 
    2373             :         return CMD_SUCCESS;
    2374             : }
    2375             : 
    2376             : ALIAS (ipv6_ospf6_priority,
    2377             :        no_ipv6_ospf6_priority_cmd,
    2378             :        "no ipv6 ospf6 priority [(0-255)]",
    2379             :        NO_STR
    2380             :        IP6_STR
    2381             :        OSPF6_STR
    2382             :        "Router priority\n"
    2383             :        "Priority value\n")
    2384             : 
    2385           0 : DEFUN (ipv6_ospf6_instance,
    2386             :        ipv6_ospf6_instance_cmd,
    2387             :        "ipv6 ospf6 instance-id (0-255)",
    2388             :        IP6_STR
    2389             :        OSPF6_STR
    2390             :        "Instance ID for this interface\n"
    2391             :        "Instance ID value\n")
    2392             : {
    2393           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2394           0 :         int idx_number = 3;
    2395           0 :         struct ospf6_interface *oi;
    2396           0 :         assert(ifp);
    2397             : 
    2398           0 :         oi = (struct ospf6_interface *)ifp->info;
    2399           0 :         if (oi == NULL)
    2400           0 :                 oi = ospf6_interface_create(ifp);
    2401           0 :         assert(oi);
    2402             : 
    2403           0 :         oi->instance_id = strmatch(argv[0]->text, "no")
    2404             :                                   ? OSPF6_INTERFACE_INSTANCE_ID
    2405           0 :                                   : strtoul(argv[idx_number]->arg, NULL, 10);
    2406           0 :         return CMD_SUCCESS;
    2407             : }
    2408             : 
    2409             : ALIAS (ipv6_ospf6_instance,
    2410             :        no_ipv6_ospf6_instance_cmd,
    2411             :        "no ipv6 ospf6 instance-id [(0-255)]",
    2412             :        NO_STR
    2413             :        IP6_STR
    2414             :        OSPF6_STR
    2415             :        "Instance ID for this interface\n"
    2416             :        "Instance ID value\n")
    2417             : 
    2418           0 : DEFUN (ipv6_ospf6_passive,
    2419             :        ipv6_ospf6_passive_cmd,
    2420             :        "ipv6 ospf6 passive",
    2421             :        IP6_STR
    2422             :        OSPF6_STR
    2423             :        "Passive interface; no adjacency will be formed on this interface\n"
    2424             :        )
    2425             : {
    2426           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2427           0 :         struct ospf6_interface *oi;
    2428           0 :         struct listnode *node, *nnode;
    2429           0 :         struct ospf6_neighbor *on;
    2430             : 
    2431           0 :         assert(ifp);
    2432             : 
    2433           0 :         oi = (struct ospf6_interface *)ifp->info;
    2434           0 :         if (oi == NULL)
    2435           0 :                 oi = ospf6_interface_create(ifp);
    2436           0 :         assert(oi);
    2437             : 
    2438           0 :         SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
    2439           0 :         THREAD_OFF(oi->thread_send_hello);
    2440           0 :         THREAD_OFF(oi->thread_sso);
    2441             : 
    2442           0 :         for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
    2443           0 :                 THREAD_OFF(on->inactivity_timer);
    2444           0 :                 thread_add_event(master, inactivity_timer, on, 0, NULL);
    2445             :         }
    2446             : 
    2447             :         return CMD_SUCCESS;
    2448             : }
    2449             : 
    2450           0 : DEFUN (no_ipv6_ospf6_passive,
    2451             :        no_ipv6_ospf6_passive_cmd,
    2452             :        "no ipv6 ospf6 passive",
    2453             :        NO_STR
    2454             :        IP6_STR
    2455             :        OSPF6_STR
    2456             :        "passive interface: No Adjacency will be formed on this I/F\n"
    2457             :        )
    2458             : {
    2459           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2460           0 :         struct ospf6_interface *oi;
    2461           0 :         assert(ifp);
    2462             : 
    2463           0 :         oi = (struct ospf6_interface *)ifp->info;
    2464           0 :         if (oi == NULL)
    2465           0 :                 oi = ospf6_interface_create(ifp);
    2466           0 :         assert(oi);
    2467             : 
    2468           0 :         UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
    2469           0 :         THREAD_OFF(oi->thread_send_hello);
    2470           0 :         THREAD_OFF(oi->thread_sso);
    2471             : 
    2472             :         /* don't send hellos over loopback interface */
    2473           0 :         if (!if_is_loopback(oi->interface))
    2474           0 :                 thread_add_timer(master, ospf6_hello_send, oi, 0,
    2475             :                                  &oi->thread_send_hello);
    2476             : 
    2477             :         return CMD_SUCCESS;
    2478             : }
    2479             : 
    2480           0 : DEFUN (ipv6_ospf6_mtu_ignore,
    2481             :        ipv6_ospf6_mtu_ignore_cmd,
    2482             :        "ipv6 ospf6 mtu-ignore",
    2483             :        IP6_STR
    2484             :        OSPF6_STR
    2485             :        "Disable MTU mismatch detection on this interface\n"
    2486             :        )
    2487             : {
    2488           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2489           0 :         struct ospf6_interface *oi;
    2490           0 :         assert(ifp);
    2491             : 
    2492           0 :         oi = (struct ospf6_interface *)ifp->info;
    2493           0 :         if (oi == NULL)
    2494           0 :                 oi = ospf6_interface_create(ifp);
    2495           0 :         assert(oi);
    2496             : 
    2497           0 :         oi->mtu_ignore = 1;
    2498             : 
    2499           0 :         return CMD_SUCCESS;
    2500             : }
    2501             : 
    2502           0 : DEFUN (no_ipv6_ospf6_mtu_ignore,
    2503             :        no_ipv6_ospf6_mtu_ignore_cmd,
    2504             :        "no ipv6 ospf6 mtu-ignore",
    2505             :        NO_STR
    2506             :        IP6_STR
    2507             :        OSPF6_STR
    2508             :        "Disable MTU mismatch detection on this interface\n"
    2509             :        )
    2510             : {
    2511           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2512           0 :         struct ospf6_interface *oi;
    2513           0 :         assert(ifp);
    2514             : 
    2515           0 :         oi = (struct ospf6_interface *)ifp->info;
    2516           0 :         if (oi == NULL)
    2517           0 :                 oi = ospf6_interface_create(ifp);
    2518           0 :         assert(oi);
    2519             : 
    2520           0 :         oi->mtu_ignore = 0;
    2521             : 
    2522           0 :         return CMD_SUCCESS;
    2523             : }
    2524             : 
    2525           0 : DEFUN (ipv6_ospf6_advertise_prefix_list,
    2526             :        ipv6_ospf6_advertise_prefix_list_cmd,
    2527             :        "ipv6 ospf6 advertise prefix-list WORD",
    2528             :        IP6_STR
    2529             :        OSPF6_STR
    2530             :        "Advertising options\n"
    2531             :        "Filter prefix using prefix-list\n"
    2532             :        "Prefix list name\n"
    2533             :        )
    2534             : {
    2535           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2536           0 :         int idx_word = 4;
    2537           0 :         struct ospf6_interface *oi;
    2538           0 :         assert(ifp);
    2539             : 
    2540           0 :         oi = (struct ospf6_interface *)ifp->info;
    2541           0 :         if (oi == NULL)
    2542           0 :                 oi = ospf6_interface_create(ifp);
    2543           0 :         assert(oi);
    2544             : 
    2545           0 :         if (oi->plist_name)
    2546           0 :                 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
    2547           0 :         oi->plist_name = XSTRDUP(MTYPE_CFG_PLIST_NAME, argv[idx_word]->arg);
    2548             : 
    2549           0 :         ospf6_interface_connected_route_update(oi->interface);
    2550             : 
    2551           0 :         if (oi->area) {
    2552           0 :                 OSPF6_LINK_LSA_SCHEDULE(oi);
    2553           0 :                 if (oi->state == OSPF6_INTERFACE_DR) {
    2554           0 :                         OSPF6_NETWORK_LSA_SCHEDULE(oi);
    2555           0 :                         OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
    2556             :                 }
    2557           0 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
    2558             :         }
    2559             : 
    2560             :         return CMD_SUCCESS;
    2561             : }
    2562             : 
    2563           0 : DEFUN (no_ipv6_ospf6_advertise_prefix_list,
    2564             :        no_ipv6_ospf6_advertise_prefix_list_cmd,
    2565             :        "no ipv6 ospf6 advertise prefix-list [WORD]",
    2566             :        NO_STR
    2567             :        IP6_STR
    2568             :        OSPF6_STR
    2569             :        "Advertising options\n"
    2570             :        "Filter prefix using prefix-list\n"
    2571             :        "Prefix list name\n")
    2572             : {
    2573           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2574           0 :         struct ospf6_interface *oi;
    2575           0 :         assert(ifp);
    2576             : 
    2577           0 :         oi = (struct ospf6_interface *)ifp->info;
    2578           0 :         if (oi == NULL)
    2579           0 :                 oi = ospf6_interface_create(ifp);
    2580           0 :         assert(oi);
    2581             : 
    2582           0 :         if (oi->plist_name)
    2583           0 :                 XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
    2584             : 
    2585           0 :         ospf6_interface_connected_route_update(oi->interface);
    2586             : 
    2587           0 :         if (oi->area) {
    2588           0 :                 OSPF6_LINK_LSA_SCHEDULE(oi);
    2589           0 :                 if (oi->state == OSPF6_INTERFACE_DR) {
    2590           0 :                         OSPF6_NETWORK_LSA_SCHEDULE(oi);
    2591           0 :                         OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi);
    2592             :                 }
    2593           0 :                 OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
    2594             :         }
    2595             : 
    2596             :         return CMD_SUCCESS;
    2597             : }
    2598             : 
    2599           3 : DEFUN (ipv6_ospf6_network,
    2600             :        ipv6_ospf6_network_cmd,
    2601             :        "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>",
    2602             :        IP6_STR
    2603             :        OSPF6_STR
    2604             :        "Network type\n"
    2605             :        "Specify OSPF6 broadcast network\n"
    2606             :        "Specify OSPF6 point-to-point network\n"
    2607             :        "Specify OSPF6 point-to-multipoint network\n"
    2608             :        )
    2609             : {
    2610           3 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2611           3 :         int idx_network = 3;
    2612           3 :         struct ospf6_interface *oi;
    2613           3 :         assert(ifp);
    2614             : 
    2615           3 :         oi = (struct ospf6_interface *)ifp->info;
    2616           3 :         if (oi == NULL) {
    2617           0 :                 oi = ospf6_interface_create(ifp);
    2618             :         }
    2619           3 :         assert(oi);
    2620             : 
    2621           3 :         oi->type_cfg = true;
    2622             : 
    2623           3 :         if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
    2624           0 :                 if (oi->type == OSPF_IFTYPE_BROADCAST)
    2625             :                         return CMD_SUCCESS;
    2626             : 
    2627           0 :                 oi->type = OSPF_IFTYPE_BROADCAST;
    2628           3 :         } else if (strncmp(argv[idx_network]->arg, "point-to-p", 10) == 0) {
    2629           0 :                 if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
    2630             :                         return CMD_SUCCESS;
    2631             :                 }
    2632           0 :                 oi->type = OSPF_IFTYPE_POINTOPOINT;
    2633           3 :         } else if (strncmp(argv[idx_network]->arg, "point-to-m", 10) == 0) {
    2634           3 :                 if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
    2635             :                         return CMD_SUCCESS;
    2636             :                 }
    2637           3 :                 oi->type = OSPF_IFTYPE_POINTOMULTIPOINT;
    2638             :         }
    2639             : 
    2640             :         /* Reset the interface */
    2641           3 :         thread_execute(master, interface_down, oi, 0);
    2642           3 :         thread_execute(master, interface_up, oi, 0);
    2643             : 
    2644           3 :         return CMD_SUCCESS;
    2645             : }
    2646             : 
    2647           0 : DEFUN (no_ipv6_ospf6_network,
    2648             :        no_ipv6_ospf6_network_cmd,
    2649             :        "no ipv6 ospf6 network [<broadcast|point-to-point>]",
    2650             :        NO_STR
    2651             :        IP6_STR
    2652             :        OSPF6_STR
    2653             :        "Set default network type\n"
    2654             :        "Specify OSPF6 broadcast network\n"
    2655             :        "Specify OSPF6 point-to-point network\n")
    2656             : {
    2657           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2658           0 :         struct ospf6_interface *oi;
    2659           0 :         int type;
    2660             : 
    2661           0 :         assert(ifp);
    2662             : 
    2663           0 :         oi = (struct ospf6_interface *)ifp->info;
    2664           0 :         if (oi == NULL) {
    2665             :                 return CMD_SUCCESS;
    2666             :         }
    2667             : 
    2668           0 :         oi->type_cfg = false;
    2669             : 
    2670           0 :         type = ospf6_default_iftype(ifp);
    2671           0 :         if (oi->type == type) {
    2672             :                 return CMD_SUCCESS;
    2673             :         }
    2674           0 :         oi->type = type;
    2675             : 
    2676             :         /* Reset the interface */
    2677           0 :         thread_execute(master, interface_down, oi, 0);
    2678           0 :         thread_execute(master, interface_up, oi, 0);
    2679             : 
    2680           0 :         return CMD_SUCCESS;
    2681             : }
    2682             : 
    2683           0 : DEFPY (ipv6_ospf6_p2xp_only_cfg_neigh,
    2684             :        ipv6_ospf6_p2xp_only_cfg_neigh_cmd,
    2685             :        "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only",
    2686             :        NO_STR
    2687             :        IP6_STR
    2688             :        OSPF6_STR
    2689             :        "Point-to-point and Point-to-Multipoint parameters\n"
    2690             :        "Only form adjacencies with explicitly configured neighbors\n")
    2691             : {
    2692           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2693           0 :         struct ospf6_interface *oi = ifp->info;
    2694             : 
    2695           0 :         if (no) {
    2696           0 :                 if (!oi)
    2697             :                         return CMD_SUCCESS;
    2698             : 
    2699           0 :                 oi->p2xp_only_cfg_neigh = false;
    2700           0 :                 return CMD_SUCCESS;
    2701             :         }
    2702             : 
    2703           0 :         if (!oi)
    2704           0 :                 oi = ospf6_interface_create(ifp);
    2705             : 
    2706           0 :         oi->p2xp_only_cfg_neigh = true;
    2707           0 :         return CMD_SUCCESS;
    2708             : }
    2709             : 
    2710           0 : DEFPY (ipv6_ospf6_p2xp_no_multicast_hello,
    2711             :        ipv6_ospf6_p2xp_no_multicast_hello_cmd,
    2712             :        "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello",
    2713             :        NO_STR
    2714             :        IP6_STR
    2715             :        OSPF6_STR
    2716             :        "Point-to-point and Point-to-Multipoint parameters\n"
    2717             :        "Do not send multicast hellos\n")
    2718             : {
    2719           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2720           0 :         struct ospf6_interface *oi = ifp->info;
    2721             : 
    2722           0 :         if (no) {
    2723           0 :                 if (!oi)
    2724             :                         return CMD_SUCCESS;
    2725             : 
    2726           0 :                 oi->p2xp_no_multicast_hello = false;
    2727           0 :                 return CMD_SUCCESS;
    2728             :         }
    2729             : 
    2730           0 :         if (!oi)
    2731           0 :                 oi = ospf6_interface_create(ifp);
    2732             : 
    2733           0 :         oi->p2xp_no_multicast_hello = true;
    2734           0 :         return CMD_SUCCESS;
    2735             : }
    2736             : 
    2737           2 : DEFPY (ipv6_ospf6_p2xp_connected_pfx,
    2738             :        ipv6_ospf6_p2xp_connected_pfx_cmd,
    2739             :        "[no] ipv6 ospf6 p2p-p2mp connected-prefixes <include$incl|exclude$excl>",
    2740             :        NO_STR
    2741             :        IP6_STR
    2742             :        OSPF6_STR
    2743             :        "Point-to-point and Point-to-Multipoint parameters\n"
    2744             :        "Adjust handling of directly connected prefixes\n"
    2745             :        "Advertise prefixes and own /128 (default for PtP)\n"
    2746             :        "Ignore, only advertise own /128 (default for PtMP)\n")
    2747             : {
    2748           2 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    2749           2 :         struct ospf6_interface *oi = ifp->info;
    2750           2 :         bool old_incl, old_excl;
    2751             : 
    2752           2 :         if (no && !oi)
    2753             :                 return CMD_SUCCESS;
    2754             : 
    2755           2 :         if (!oi)
    2756           0 :                 oi = ospf6_interface_create(ifp);
    2757             : 
    2758           2 :         old_incl = oi->p2xp_connected_pfx_include;
    2759           2 :         old_excl = oi->p2xp_connected_pfx_exclude;
    2760           2 :         oi->p2xp_connected_pfx_include = false;
    2761           2 :         oi->p2xp_connected_pfx_exclude = false;
    2762             : 
    2763           2 :         if (incl && !no)
    2764           2 :                 oi->p2xp_connected_pfx_include = true;
    2765           2 :         if (excl && !no)
    2766           0 :                 oi->p2xp_connected_pfx_exclude = true;
    2767             : 
    2768           2 :         if (oi->p2xp_connected_pfx_include != old_incl
    2769           0 :             || oi->p2xp_connected_pfx_exclude != old_excl)
    2770           2 :                 ospf6_interface_connected_route_update(ifp);
    2771             :         return CMD_SUCCESS;
    2772             : }
    2773             : 
    2774             : ALIAS (ipv6_ospf6_p2xp_connected_pfx,
    2775             :        no_ipv6_ospf6_p2xp_connected_pfx_cmd,
    2776             :        "no ipv6 ospf6 p2p-p2mp connected-prefixes",
    2777             :        NO_STR
    2778             :        IP6_STR
    2779             :        OSPF6_STR
    2780             :        "Point-to-point and Point-to-Multipoint parameters\n"
    2781             :        "Adjust handling of directly connected prefixes\n")
    2782             : 
    2783             : 
    2784           0 : static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
    2785             : {
    2786           0 :         struct ospf6_interface *oi;
    2787           0 :         struct interface *ifp;
    2788           0 :         char buf[INET_ADDRSTRLEN];
    2789             : 
    2790           0 :         FOR_ALL_INTERFACES (vrf, ifp) {
    2791           0 :                 oi = (struct ospf6_interface *)ifp->info;
    2792           0 :                 if (oi == NULL)
    2793           0 :                         continue;
    2794             : 
    2795           0 :                 if_vty_config_start(vty, ifp);
    2796             : 
    2797           0 :                 if (ifp->desc)
    2798           0 :                         vty_out(vty, " description %s\n", ifp->desc);
    2799           0 :                 if (oi->area_id_format != OSPF6_AREA_FMT_UNSET) {
    2800           0 :                         area_id2str(buf, sizeof(buf), oi->area_id,
    2801             :                                     oi->area_id_format);
    2802           0 :                         vty_out(vty, " ipv6 ospf6 area %s\n", buf);
    2803             :                 }
    2804           0 :                 if (oi->c_ifmtu)
    2805           0 :                         vty_out(vty, " ipv6 ospf6 ifmtu %d\n", oi->c_ifmtu);
    2806             : 
    2807           0 :                 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST))
    2808           0 :                         vty_out(vty, " ipv6 ospf6 cost %d\n", oi->cost);
    2809             : 
    2810           0 :                 if (oi->hello_interval != OSPF6_INTERFACE_HELLO_INTERVAL)
    2811           0 :                         vty_out(vty, " ipv6 ospf6 hello-interval %d\n",
    2812             :                                 oi->hello_interval);
    2813             : 
    2814           0 :                 if (oi->dead_interval != OSPF6_INTERFACE_DEAD_INTERVAL)
    2815           0 :                         vty_out(vty, " ipv6 ospf6 dead-interval %d\n",
    2816             :                                 oi->dead_interval);
    2817             : 
    2818           0 :                 if (oi->rxmt_interval != OSPF6_INTERFACE_RXMT_INTERVAL)
    2819           0 :                         vty_out(vty, " ipv6 ospf6 retransmit-interval %d\n",
    2820             :                                 oi->rxmt_interval);
    2821             : 
    2822           0 :                 if (oi->priority != OSPF6_INTERFACE_PRIORITY)
    2823           0 :                         vty_out(vty, " ipv6 ospf6 priority %d\n", oi->priority);
    2824             : 
    2825           0 :                 if (oi->transdelay != OSPF6_INTERFACE_TRANSDELAY)
    2826           0 :                         vty_out(vty, " ipv6 ospf6 transmit-delay %d\n",
    2827             :                                 oi->transdelay);
    2828             : 
    2829           0 :                 if (oi->instance_id != OSPF6_INTERFACE_INSTANCE_ID)
    2830           0 :                         vty_out(vty, " ipv6 ospf6 instance-id %d\n",
    2831             :                                 oi->instance_id);
    2832             : 
    2833           0 :                 if (oi->plist_name)
    2834           0 :                         vty_out(vty, " ipv6 ospf6 advertise prefix-list %s\n",
    2835             :                                 oi->plist_name);
    2836             : 
    2837           0 :                 if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE))
    2838           0 :                         vty_out(vty, " ipv6 ospf6 passive\n");
    2839             : 
    2840           0 :                 if (oi->mtu_ignore)
    2841           0 :                         vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
    2842             : 
    2843           0 :                 if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
    2844           0 :                         vty_out(vty,
    2845             :                                 " ipv6 ospf6 network point-to-multipoint\n");
    2846           0 :                 else if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
    2847           0 :                         vty_out(vty, " ipv6 ospf6 network point-to-point\n");
    2848           0 :                 else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
    2849           0 :                         vty_out(vty, " ipv6 ospf6 network broadcast\n");
    2850             : 
    2851           0 :                 if (oi->p2xp_only_cfg_neigh)
    2852           0 :                         vty_out(vty,
    2853             :                                 " ipv6 ospf6 p2p-p2mp config-neighbors-only\n");
    2854             : 
    2855           0 :                 if (oi->p2xp_no_multicast_hello)
    2856           0 :                         vty_out(vty,
    2857             :                                 " ipv6 ospf6 p2p-p2mp disable-multicast-hello\n");
    2858             : 
    2859           0 :                 if (oi->p2xp_connected_pfx_include)
    2860           0 :                         vty_out(vty,
    2861             :                                 " ipv6 ospf6 p2p-p2mp connected-prefixes include\n");
    2862           0 :                 else if (oi->p2xp_connected_pfx_exclude)
    2863           0 :                         vty_out(vty,
    2864             :                                 " ipv6 ospf6 p2p-p2mp connected-prefixes exclude\n");
    2865             : 
    2866           0 :                 config_write_ospf6_p2xp_neighbor(vty, oi);
    2867           0 :                 ospf6_bfd_write_config(vty, oi);
    2868             : 
    2869           0 :                 ospf6_auth_write_config(vty, &oi->at_data);
    2870           0 :                 if_vty_config_end(vty);
    2871             :         }
    2872           0 :         return 0;
    2873             : }
    2874             : 
    2875             : /* Configuration write function for ospfd. */
    2876           0 : static int config_write_interface(struct vty *vty)
    2877             : {
    2878           0 :         int write = 0;
    2879           0 :         struct vrf *vrf = NULL;
    2880             : 
    2881             :         /* Display all VRF aware OSPF interface configuration */
    2882           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    2883           0 :                 write += config_write_ospf6_interface(vty, vrf);
    2884             :         }
    2885             : 
    2886           0 :         return write;
    2887             : }
    2888             : 
    2889         135 : static int ospf6_ifp_create(struct interface *ifp)
    2890             : {
    2891         135 :         if (IS_OSPF6_DEBUG_ZEBRA(RECV))
    2892           0 :                 zlog_debug("Zebra Interface add: %s index %d mtu %d", ifp->name,
    2893             :                            ifp->ifindex, ifp->mtu6);
    2894             : 
    2895         135 :         if (ifp->info)
    2896          87 :                 ospf6_interface_start(ifp->info);
    2897             : 
    2898         135 :         return 0;
    2899             : }
    2900             : 
    2901          44 : static int ospf6_ifp_up(struct interface *ifp)
    2902             : {
    2903          44 :         if (IS_OSPF6_DEBUG_ZEBRA(RECV))
    2904           0 :                 zlog_debug(
    2905             :                         "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
    2906             :                         ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
    2907             :                         ifp->metric, ifp->mtu6, ifp->bandwidth);
    2908             : 
    2909          44 :         ospf6_interface_state_update(ifp);
    2910             : 
    2911          44 :         return 0;
    2912             : }
    2913             : 
    2914          10 : static int ospf6_ifp_down(struct interface *ifp)
    2915             : {
    2916          10 :         if (IS_OSPF6_DEBUG_ZEBRA(RECV))
    2917           0 :                 zlog_debug(
    2918             :                         "Zebra Interface state change: %s index %d flags %llx metric %d mtu %d bandwidth %d",
    2919             :                         ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
    2920             :                         ifp->metric, ifp->mtu6, ifp->bandwidth);
    2921             : 
    2922          10 :         ospf6_interface_state_update(ifp);
    2923             : 
    2924          10 :         return 0;
    2925             : }
    2926             : 
    2927           0 : static int ospf6_ifp_destroy(struct interface *ifp)
    2928             : {
    2929           0 :         if (if_is_up(ifp))
    2930           0 :                 zlog_warn("Zebra: got delete of %s, but interface is still up",
    2931             :                           ifp->name);
    2932             : 
    2933           0 :         if (IS_OSPF6_DEBUG_ZEBRA(RECV))
    2934           0 :                 zlog_debug("Zebra Interface delete: %s index %d mtu %d",
    2935             :                            ifp->name, ifp->ifindex, ifp->mtu6);
    2936             : 
    2937           0 :         if (ifp->info)
    2938           0 :                 ospf6_interface_stop(ifp->info);
    2939             : 
    2940           0 :         return 0;
    2941             : }
    2942             : 
    2943          16 : void ospf6_interface_init(void)
    2944             : {
    2945             :         /* Install interface node. */
    2946          16 :         if_cmd_init(config_write_interface);
    2947          16 :         if_zapi_callbacks(ospf6_ifp_create, ospf6_ifp_up,
    2948             :                           ospf6_ifp_down, ospf6_ifp_destroy);
    2949             : 
    2950          16 :         install_element(VIEW_NODE, &show_ipv6_ospf6_interface_prefix_cmd);
    2951          16 :         install_element(VIEW_NODE, &show_ipv6_ospf6_interface_ifname_cmd);
    2952          16 :         install_element(VIEW_NODE,
    2953             :                         &show_ipv6_ospf6_interface_ifname_prefix_cmd);
    2954          16 :         install_element(VIEW_NODE, &show_ipv6_ospf6_interface_traffic_cmd);
    2955             : 
    2956          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_area_cmd);
    2957          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_area_cmd);
    2958          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_cost_cmd);
    2959          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_cost_cmd);
    2960          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_ifmtu_cmd);
    2961          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_ifmtu_cmd);
    2962             : 
    2963          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_deadinterval_cmd);
    2964          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_hellointerval_cmd);
    2965          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_priority_cmd);
    2966          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_retransmitinterval_cmd);
    2967          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_transmitdelay_cmd);
    2968          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_instance_cmd);
    2969          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_deadinterval_cmd);
    2970          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_hellointerval_cmd);
    2971          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_priority_cmd);
    2972          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_retransmitinterval_cmd);
    2973          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_transmitdelay_cmd);
    2974          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_instance_cmd);
    2975             : 
    2976          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_passive_cmd);
    2977          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_passive_cmd);
    2978             : 
    2979          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_mtu_ignore_cmd);
    2980          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_mtu_ignore_cmd);
    2981             : 
    2982          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
    2983          16 :         install_element(INTERFACE_NODE,
    2984             :                         &no_ipv6_ospf6_advertise_prefix_list_cmd);
    2985             : 
    2986          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_network_cmd);
    2987          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
    2988             : 
    2989          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_only_cfg_neigh_cmd);
    2990          16 :         install_element(INTERFACE_NODE,
    2991             :                         &ipv6_ospf6_p2xp_no_multicast_hello_cmd);
    2992          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_p2xp_connected_pfx_cmd);
    2993          16 :         install_element(INTERFACE_NODE, &no_ipv6_ospf6_p2xp_connected_pfx_cmd);
    2994             : 
    2995             :         /* reference bandwidth commands */
    2996          16 :         install_element(OSPF6_NODE, &auto_cost_reference_bandwidth_cmd);
    2997          16 :         install_element(OSPF6_NODE, &no_auto_cost_reference_bandwidth_cmd);
    2998             :         /* write-multiplier commands */
    2999          16 :         install_element(OSPF6_NODE, &ospf6_write_multiplier_cmd);
    3000          16 :         install_element(OSPF6_NODE, &no_ospf6_write_multiplier_cmd);
    3001          16 : }
    3002             : 
    3003             : /* Clear the specified interface structure */
    3004          29 : void ospf6_interface_clear(struct interface *ifp)
    3005             : {
    3006          29 :         struct ospf6_interface *oi;
    3007             : 
    3008          29 :         if (!if_is_operative(ifp))
    3009             :                 return;
    3010             : 
    3011           0 :         if (ifp->info == NULL)
    3012             :                 return;
    3013             : 
    3014           0 :         oi = (struct ospf6_interface *)ifp->info;
    3015             : 
    3016           0 :         if (IS_OSPF6_DEBUG_INTERFACE)
    3017           0 :                 zlog_debug("Interface %s: clear by reset", ifp->name);
    3018             : 
    3019             :         /* Reset the interface */
    3020           0 :         thread_execute(master, interface_down, oi, 0);
    3021           0 :         thread_execute(master, interface_up, oi, 0);
    3022             : }
    3023             : 
    3024             : /* Clear interface */
    3025           0 : DEFUN (clear_ipv6_ospf6_interface,
    3026             :        clear_ipv6_ospf6_interface_cmd,
    3027             :        "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
    3028             :        CLEAR_STR
    3029             :        IP6_STR
    3030             :        OSPF6_STR
    3031             :        VRF_CMD_HELP_STR
    3032             :        INTERFACE_STR
    3033             :        IFNAME_STR
    3034             :        )
    3035             : {
    3036           0 :         struct vrf *vrf;
    3037           0 :         int idx_vrf = 3;
    3038           0 :         int idx_ifname = 4;
    3039           0 :         struct interface *ifp;
    3040           0 :         const char *vrf_name;
    3041             : 
    3042           0 :         if (argv_find(argv, argc, "vrf", &idx_vrf))
    3043           0 :                 vrf_name = argv[idx_vrf + 1]->arg;
    3044             :         else
    3045           0 :                 vrf_name = VRF_DEFAULT_NAME;
    3046           0 :         vrf = vrf_lookup_by_name(vrf_name);
    3047           0 :         if (!vrf) {
    3048           0 :                 vty_out(vty, "%% VRF %s not found\n", vrf_name);
    3049           0 :                 return CMD_WARNING;
    3050             :         }
    3051             : 
    3052           0 :         if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) {
    3053             :                 /* Clear all the ospfv3 interfaces. */
    3054           0 :                 FOR_ALL_INTERFACES (vrf, ifp)
    3055           0 :                         ospf6_interface_clear(ifp);
    3056             :         } else {
    3057             :                 /* Interface name is specified. */
    3058           0 :                 ifp = if_lookup_by_name_vrf(argv[idx_ifname]->arg, vrf);
    3059           0 :                 if (!ifp) {
    3060           0 :                         vty_out(vty, "No such Interface: %s\n",
    3061           0 :                                 argv[idx_ifname]->arg);
    3062           0 :                         return CMD_WARNING;
    3063             :                 }
    3064           0 :                 ospf6_interface_clear(ifp);
    3065             :         }
    3066             : 
    3067             :         return CMD_SUCCESS;
    3068             : }
    3069             : 
    3070          16 : void install_element_ospf6_clear_interface(void)
    3071             : {
    3072          16 :         install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
    3073          16 : }
    3074             : 
    3075           0 : DEFUN (debug_ospf6_interface,
    3076             :        debug_ospf6_interface_cmd,
    3077             :        "debug ospf6 interface",
    3078             :        DEBUG_STR
    3079             :        OSPF6_STR
    3080             :        "Debug OSPFv3 Interface\n"
    3081             :       )
    3082             : {
    3083           0 :         OSPF6_DEBUG_INTERFACE_ON();
    3084           0 :         return CMD_SUCCESS;
    3085             : }
    3086             : 
    3087           0 : DEFUN (no_debug_ospf6_interface,
    3088             :        no_debug_ospf6_interface_cmd,
    3089             :        "no debug ospf6 interface",
    3090             :        NO_STR
    3091             :        DEBUG_STR
    3092             :        OSPF6_STR
    3093             :        "Debug OSPFv3 Interface\n"
    3094             :       )
    3095             : {
    3096           0 :         OSPF6_DEBUG_INTERFACE_OFF();
    3097           0 :         return CMD_SUCCESS;
    3098             : }
    3099             : 
    3100           0 : int config_write_ospf6_debug_interface(struct vty *vty)
    3101             : {
    3102           0 :         if (IS_OSPF6_DEBUG_INTERFACE)
    3103           0 :                 vty_out(vty, "debug ospf6 interface\n");
    3104           0 :         return 0;
    3105             : }
    3106             : 
    3107          16 : void install_element_ospf6_debug_interface(void)
    3108             : {
    3109          16 :         install_element(ENABLE_NODE, &debug_ospf6_interface_cmd);
    3110          16 :         install_element(ENABLE_NODE, &no_debug_ospf6_interface_cmd);
    3111          16 :         install_element(CONFIG_NODE, &debug_ospf6_interface_cmd);
    3112          16 :         install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd);
    3113          16 : }
    3114             : 
    3115           0 : void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
    3116             : {
    3117           0 :         if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
    3118           0 :                 vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",
    3119             :                         at_data->keychain);
    3120           0 :         else if (CHECK_FLAG(at_data->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
    3121           0 :                 vty_out(vty,
    3122             :                         " ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",
    3123           0 :                         at_data->key_id,
    3124           0 :                         keychain_get_algo_name_by_id(at_data->hash_algo),
    3125             :                         at_data->auth_key);
    3126           0 : }
    3127             : 
    3128           0 : DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
    3129             :       ipv6_ospf6_intf_auth_trailer_keychain_cmd,
    3130             :       "ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
    3131             :       IP6_STR OSPF6_STR
    3132             :       "Enable authentication on this interface\n"
    3133             :       "Keychain\n"
    3134             :       "Keychain name\n")
    3135             : {
    3136           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    3137           0 :         int keychain_idx = 4;
    3138           0 :         struct ospf6_interface *oi;
    3139             : 
    3140           0 :         oi = (struct ospf6_interface *)ifp->info;
    3141           0 :         if (oi == NULL)
    3142           0 :                 oi = ospf6_interface_create(ifp);
    3143             : 
    3144           0 :         assert(oi);
    3145           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
    3146           0 :                 vty_out(vty,
    3147             :                         "Manual key configured, unconfigure it before configuring key chain\n");
    3148           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3149             :         }
    3150             : 
    3151           0 :         SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);
    3152           0 :         if (oi->at_data.keychain)
    3153           0 :                 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
    3154             : 
    3155           0 :         oi->at_data.keychain =
    3156           0 :                 XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);
    3157             : 
    3158           0 :         return CMD_SUCCESS;
    3159             : }
    3160             : 
    3161           0 : DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
    3162             :       no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
    3163             :       "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
    3164             :       NO_STR IP6_STR OSPF6_STR
    3165             :       "Enable authentication on this interface\n"
    3166             :       "Keychain\n"
    3167             :       "Keychain name\n")
    3168             : {
    3169           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    3170           0 :         struct ospf6_interface *oi;
    3171             : 
    3172           0 :         oi = (struct ospf6_interface *)ifp->info;
    3173           0 :         if (oi == NULL)
    3174           0 :                 oi = ospf6_interface_create(ifp);
    3175             : 
    3176           0 :         assert(oi);
    3177           0 :         if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))
    3178             :                 return CMD_SUCCESS;
    3179             : 
    3180           0 :         if (oi->at_data.keychain) {
    3181           0 :                 oi->at_data.flags = 0;
    3182           0 :                 XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_data.keychain);
    3183           0 :                 oi->at_data.keychain = NULL;
    3184             :         }
    3185             : 
    3186             :         return CMD_SUCCESS;
    3187             : }
    3188             : 
    3189           0 : DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
    3190             :       "ipv6 ospf6 authentication key-id (1-65535) hash-algo "
    3191             :       "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
    3192             :       "key WORD",
    3193             :       IP6_STR OSPF6_STR
    3194             :       "Authentication\n"
    3195             :       "Key ID\n"
    3196             :       "Key ID value\n"
    3197             :       "Cryptographic-algorithm\n"
    3198             :       "Use MD5 algorithm\n"
    3199             :       "Use HMAC-SHA-1 algorithm\n"
    3200             :       "Use HMAC-SHA-256 algorithm\n"
    3201             :       "Use HMAC-SHA-384 algorithm\n"
    3202             :       "Use HMAC-SHA-512 algorithm\n"
    3203             :       "Password\n"
    3204             :       "Password string (key)\n")
    3205             : {
    3206           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    3207           0 :         int key_id_idx = 4;
    3208           0 :         int hash_algo_idx = 6;
    3209           0 :         int password_idx = 8;
    3210           0 :         struct ospf6_interface *oi;
    3211           0 :         uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
    3212             : 
    3213           0 :         oi = (struct ospf6_interface *)ifp->info;
    3214           0 :         if (oi == NULL)
    3215           0 :                 oi = ospf6_interface_create(ifp);
    3216             : 
    3217           0 :         assert(oi);
    3218           0 :         if (CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {
    3219           0 :                 vty_out(vty,
    3220             :                         "key chain configured, unconfigure it before configuring manual key\n");
    3221           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3222             :         }
    3223             : 
    3224           0 :         hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
    3225             : #ifndef CRYPTO_OPENSSL
    3226           0 :         if (hash_algo == KEYCHAIN_ALGO_NULL) {
    3227           0 :                 vty_out(vty,
    3228             :                         "Hash algorithm not supported, compile with --with-crypto=openssl\n");
    3229           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3230             :         }
    3231             : #endif /* CRYPTO_OPENSSL */
    3232             : 
    3233           0 :         SET_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY);
    3234           0 :         oi->at_data.hash_algo = hash_algo;
    3235           0 :         oi->at_data.key_id = (uint16_t)strtol(argv[key_id_idx]->arg, NULL, 10);
    3236           0 :         if (oi->at_data.auth_key)
    3237           0 :                 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
    3238           0 :         oi->at_data.auth_key =
    3239           0 :                 XSTRDUP(MTYPE_OSPF6_AUTH_MANUAL_KEY, argv[password_idx]->arg);
    3240             : 
    3241           0 :         return CMD_SUCCESS;
    3242             : }
    3243             : 
    3244           0 : DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
    3245             :       no_ipv6_ospf6_intf_auth_trailer_key_cmd,
    3246             :       "no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
    3247             :       "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
    3248             :       "key WORD]",
    3249             :       NO_STR IP6_STR OSPF6_STR
    3250             :       "Authentication\n"
    3251             :       "Key ID\n"
    3252             :       "Key ID value\n"
    3253             :       "Cryptographic-algorithm\n"
    3254             :       "Use MD5 algorithm\n"
    3255             :       "Use HMAC-SHA-1 algorithm\n"
    3256             :       "Use HMAC-SHA-256 algorithm\n"
    3257             :       "Use HMAC-SHA-384 algorithm\n"
    3258             :       "Use HMAC-SHA-512 algorithm\n"
    3259             :       "Password\n"
    3260             :       "Password string (key)\n")
    3261             : {
    3262           0 :         VTY_DECLVAR_CONTEXT(interface, ifp);
    3263           0 :         struct ospf6_interface *oi;
    3264             : #ifndef CRYPTO_OPENSSL
    3265           0 :         int hash_algo_idx = 7;
    3266           0 :         uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
    3267             : #endif /* CRYPTO_OPENSSL */
    3268             : 
    3269           0 :         oi = (struct ospf6_interface *)ifp->info;
    3270           0 :         if (oi == NULL)
    3271           0 :                 oi = ospf6_interface_create(ifp);
    3272             : 
    3273           0 :         assert(oi);
    3274           0 :         if (!CHECK_FLAG(oi->at_data.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))
    3275             :                 return CMD_SUCCESS;
    3276             : 
    3277             : #ifndef CRYPTO_OPENSSL
    3278           0 :         hash_algo = keychain_get_algo_id_by_name(argv[hash_algo_idx]->arg);
    3279           0 :         if (hash_algo == KEYCHAIN_ALGO_NULL) {
    3280           0 :                 vty_out(vty,
    3281             :                         "Hash algorithm not supported, compile with --with-crypto=openssl\n");
    3282           0 :                 return CMD_WARNING_CONFIG_FAILED;
    3283             :         }
    3284             : #endif /* CRYPTO_OPENSSL */
    3285             : 
    3286           0 :         if (oi->at_data.auth_key) {
    3287           0 :                 oi->at_data.flags = 0;
    3288           0 :                 XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_data.auth_key);
    3289           0 :                 oi->at_data.auth_key = NULL;
    3290             :         }
    3291             : 
    3292             :         return CMD_SUCCESS;
    3293             : }
    3294             : 
    3295          16 : void ospf6_interface_auth_trailer_cmd_init(void)
    3296             : {
    3297             :         /*Install OSPF6 auth trailer commands at interface level */
    3298          16 :         install_element(INTERFACE_NODE,
    3299             :                         &ipv6_ospf6_intf_auth_trailer_keychain_cmd);
    3300          16 :         install_element(INTERFACE_NODE,
    3301             :                         &no_ipv6_ospf6_intf_auth_trailer_keychain_cmd);
    3302          16 :         install_element(INTERFACE_NODE, &ipv6_ospf6_intf_auth_trailer_key_cmd);
    3303          16 :         install_element(INTERFACE_NODE,
    3304             :                         &no_ipv6_ospf6_intf_auth_trailer_key_cmd);
    3305          16 : }

Generated by: LCOV version v1.16-topotato