diff options
Diffstat (limited to 'ospfd/ospf_vty.c')
-rw-r--r-- | ospfd/ospf_vty.c | 13798 |
1 files changed, 13798 insertions, 0 deletions
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c new file mode 100644 index 0000000..355742a --- /dev/null +++ b/ospfd/ospf_vty.c @@ -0,0 +1,13798 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* OSPF VTY interface. + * Copyright (C) 2005 6WIND <alain.ritoux@6wind.com> + * Copyright (C) 2000 Toshiaki Takada + */ + +#include <zebra.h> +#include <string.h> + +#include "printfrr.h" +#include "monotime.h" +#include "memory.h" +#include "frrevent.h" +#include "prefix.h" +#include "table.h" +#include "vty.h" +#include "command.h" +#include "plist.h" +#include "log.h" +#include "zclient.h" +#include <lib/json.h> +#include "defaults.h" +#include "lib/printfrr.h" +#include "keychain.h" + +#include "ospfd/ospfd.h" +#include "ospfd/ospf_asbr.h" +#include "ospfd/ospf_lsa.h" +#include "ospfd/ospf_lsdb.h" +#include "ospfd/ospf_ism.h" +#include "ospfd/ospf_interface.h" +#include "ospfd/ospf_nsm.h" +#include "ospfd/ospf_neighbor.h" +#include "ospfd/ospf_flood.h" +#include "ospfd/ospf_abr.h" +#include "ospfd/ospf_spf.h" +#include "ospfd/ospf_route.h" +#include "ospfd/ospf_zebra.h" +#include "ospfd/ospf_vty.h" +#include "ospfd/ospf_dump.h" +#include "ospfd/ospf_bfd.h" +#include "ospfd/ospf_ldp_sync.h" +#include "ospfd/ospf_network.h" +#include "ospfd/ospf_memory.h" + +FRR_CFG_DEFAULT_BOOL(OSPF_LOG_ADJACENCY_CHANGES, + { .val_bool = true, .match_profile = "datacenter", }, + { .val_bool = false }, +); + +static const char *const ospf_network_type_str[] = { + "Null", "POINTOPOINT", "BROADCAST", "NBMA", "POINTOMULTIPOINT", + "VIRTUALLINK", "LOOPBACK"}; + +/* Utility functions. */ +int str2area_id(const char *str, struct in_addr *area_id, int *area_id_fmt) +{ + char *ep; + + area_id->s_addr = htonl(strtoul(str, &ep, 10)); + if (*ep && !inet_aton(str, area_id)) + return -1; + + *area_id_fmt = + *ep ? OSPF_AREA_ID_FMT_DOTTEDQUAD : OSPF_AREA_ID_FMT_DECIMAL; + + return 0; +} + +static void area_id2str(char *buf, int length, struct in_addr *area_id, + int area_id_fmt) +{ + if (area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + inet_ntop(AF_INET, area_id, buf, length); + else + snprintf(buf, length, "%lu", + (unsigned long)ntohl(area_id->s_addr)); +} + +static int str2metric(const char *str, int *metric) +{ + /* Sanity check. */ + if (str == NULL) + return 0; + + *metric = strtol(str, NULL, 10); + if (*metric < 0 || *metric > 16777214) { + /* vty_out (vty, "OSPF metric value is invalid\n"); */ + return 0; + } + + return 1; +} + +static int str2metric_type(const char *str, int *metric_type) +{ + /* Sanity check. */ + if (str == NULL) + return 0; + + if (strncmp(str, "1", 1) == 0) + *metric_type = EXTERNAL_METRIC_TYPE_1; + else if (strncmp(str, "2", 1) == 0) + *metric_type = EXTERNAL_METRIC_TYPE_2; + else + return 0; + + return 1; +} + +int ospf_oi_count(struct interface *ifp) +{ + struct route_node *rn; + int i = 0; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if (rn->info) + i++; + + return i; +} + +#define OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf) \ + if (argv_find(argv, argc, "vrf", &idx_vrf)) { \ + vrf_name = argv[idx_vrf + 1]->arg; \ + all_vrf = strmatch(vrf_name, "all"); \ + } + +static int ospf_router_cmd_parse(struct vty *vty, struct cmd_token *argv[], + const int argc, unsigned short *instance, + const char **vrf_name) +{ + int idx_vrf = 0, idx_inst = 0; + + *instance = 0; + if (argv_find(argv, argc, "(1-65535)", &idx_inst)) { + if (ospf_instance == 0) { + vty_out(vty, + "%% OSPF is not running in instance mode\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + *instance = strtoul(argv[idx_inst]->arg, NULL, 10); + } + + *vrf_name = VRF_DEFAULT_NAME; + if (argv_find(argv, argc, "vrf", &idx_vrf)) { + if (ospf_instance != 0) { + vty_out(vty, + "%% VRF is not supported in instance mode\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + *vrf_name = argv[idx_vrf + 1]->arg; + } + + return CMD_SUCCESS; +} + +static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty, + json_object *json, uint8_t use_vrf) +{ + if (use_vrf) { + if (json) { + json_object_string_add(json, "vrfName", + ospf_get_name(ospf)); + json_object_int_add(json, "vrfId", ospf->vrf_id); + } else + vty_out(vty, "VRF Name: %s\n", ospf_get_name(ospf)); + } +} + +#include "ospfd/ospf_vty_clippy.c" + +DEFUN_NOSH (router_ospf, + router_ospf_cmd, + "router ospf [{(1-65535)|vrf NAME}]", + "Enable a routing process\n" + "Start OSPF configuration\n" + "Instance ID\n" + VRF_CMD_HELP_STR) +{ + unsigned short instance; + const char *vrf_name; + bool created = false; + struct ospf *ospf; + int ret; + + ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name); + if (ret != CMD_SUCCESS) + return ret; + + if (instance != ospf_instance) { + VTY_PUSH_CONTEXT_NULL(OSPF_NODE); + return CMD_NOT_MY_INSTANCE; + } + + ospf = ospf_get(instance, vrf_name, &created); + + if (created) + if (DFLT_OSPF_LOG_ADJACENCY_CHANGES) + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "Config command 'router ospf %d' received, vrf %s id %u oi_running %u", + ospf->instance, ospf_get_name(ospf), ospf->vrf_id, + ospf->oi_running); + + VTY_PUSH_CONTEXT(OSPF_NODE, ospf); + + return ret; +} + +DEFUN (no_router_ospf, + no_router_ospf_cmd, + "no router ospf [{(1-65535)|vrf NAME}]", + NO_STR + "Enable a routing process\n" + "Start OSPF configuration\n" + "Instance ID\n" + VRF_CMD_HELP_STR) +{ + unsigned short instance; + const char *vrf_name; + struct ospf *ospf; + int ret; + + ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name); + if (ret != CMD_SUCCESS) + return ret; + + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup(instance, vrf_name); + if (ospf) { + if (ospf->gr_info.restart_support) + ospf_gr_nvm_delete(ospf); + + ospf_finish(ospf); + } else + ret = CMD_WARNING_CONFIG_FAILED; + + return ret; +} + + +DEFPY (ospf_router_id, + ospf_router_id_cmd, + "ospf router-id A.B.C.D", + "OSPF specific commands\n" + "router-id for the OSPF process\n" + "OSPF router-id in IP address format\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + struct listnode *node; + struct ospf_area *area; + + ospf->router_id_static = router_id; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect, use \"clear ip ospf process\" command\n"); + return CMD_SUCCESS; + } + + ospf_router_id_update(ospf); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_router_id_old, + ospf_router_id_old_cmd, + "router-id A.B.C.D", + "router-id for the OSPF process\n" + "OSPF router-id in IP address format\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + struct listnode *node; + struct ospf_area *area; + struct in_addr router_id; + int ret; + + ret = inet_aton(argv[idx_ipv4]->arg, &router_id); + if (!ret) { + vty_out(vty, "Please specify Router ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf->router_id_static = router_id; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect, use \"clear ip ospf process\" command\n"); + return CMD_SUCCESS; + } + + ospf_router_id_update(ospf); + + return CMD_SUCCESS; +} + +DEFPY (no_ospf_router_id, + no_ospf_router_id_cmd, + "no ospf router-id [A.B.C.D]", + NO_STR + "OSPF specific commands\n" + "router-id for the OSPF process\n" + "OSPF router-id in IP address format\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *node; + struct ospf_area *area; + + if (router_id_str) { + if (!IPV4_ADDR_SAME(&ospf->router_id_static, &router_id)) { + vty_out(vty, "%% OSPF router-id doesn't match\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + ospf->router_id_static.s_addr = 0; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) + if (area->full_nbrs) { + vty_out(vty, + "For this router-id change to take effect, use \"clear ip ospf process\" command\n"); + return CMD_SUCCESS; + } + + ospf_router_id_update(ospf); + + return CMD_SUCCESS; +} + + +static void ospf_passive_interface_default_update(struct ospf *ospf, + uint8_t newval) +{ + struct listnode *ln; + struct ospf_interface *oi; + + ospf->passive_interface_default = newval; + + /* update multicast memberships */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, ln, oi)) + ospf_if_set_multicast(oi); +} + +static void ospf_passive_interface_update(struct interface *ifp, + struct ospf_if_params *params, + struct in_addr addr, uint8_t newval) +{ + struct route_node *rn; + + if (OSPF_IF_PARAM_CONFIGURED(params, passive_interface)) { + if (params->passive_interface == newval) + return; + + params->passive_interface = newval; + UNSET_IF_PARAM(params, passive_interface); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + params->passive_interface = newval; + SET_IF_PARAM(params, passive_interface); + } + + /* + * XXX We should call ospf_if_set_multicast on exactly those + * interfaces for which the passive property changed. It is too much + * work to determine this set, so we do this for every interface. + * This is safe and reasonable because ospf_if_set_multicast uses a + * record of joined groups to avoid systems calls if the desired + * memberships match the current memership. + */ + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi) + ospf_if_set_multicast(oi); + } + + /* + * XXX It is not clear what state transitions the interface needs to + * undergo when going from active to passive and vice versa. Fixing + * this will require precise identification of interfaces having such a + * transition. + */ +} + +DEFUN (ospf_passive_interface_default, + ospf_passive_interface_default_cmd, + "passive-interface default", + "Suppress routing updates on an interface\n" + "Suppress routing updates on interfaces by default\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_passive_interface_default_update(ospf, OSPF_IF_PASSIVE); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_passive_interface_addr, + ospf_passive_interface_addr_cmd, + "passive-interface IFNAME [A.B.C.D]", + "Suppress routing updates on an interface\n" + "Interface's name\n" + "IPv4 address\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct interface *ifp = NULL; + struct in_addr addr = {.s_addr = INADDR_ANY}; + struct ospf_if_params *params; + int ret; + + vty_out(vty, + "This command is deprecated, because it is not VRF-aware.\n"); + vty_out(vty, + "Please, use \"ip ospf passive\" on an interface instead.\n"); + + if (ospf->vrf_id != VRF_UNKNOWN) + ifp = if_get_by_name(argv[1]->arg, ospf->vrf_id, ospf->name); + + if (ifp == NULL) { + vty_out(vty, "interface %s not found.\n", (char *)argv[1]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc == 3) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } else { + params = IF_DEF_PARAMS(ifp); + } + + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_PASSIVE); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_passive_interface_default, + no_ospf_passive_interface_default_cmd, + "no passive-interface default", + NO_STR + "Allow routing updates on an interface\n" + "Allow routing updates on interfaces by default\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_passive_interface_default_update(ospf, OSPF_IF_ACTIVE); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_passive_interface, + no_ospf_passive_interface_addr_cmd, + "no passive-interface IFNAME [A.B.C.D]", + NO_STR + "Allow routing updates on an interface\n" + "Interface's name\n" + "IPv4 address\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 3; + struct interface *ifp = NULL; + struct in_addr addr = {.s_addr = INADDR_ANY}; + struct ospf_if_params *params; + int ret; + + vty_out(vty, + "This command is deprecated, because it is not VRF-aware.\n"); + vty_out(vty, + "Please, use \"no ip ospf passive\" on an interface instead.\n"); + + if (ospf->vrf_id != VRF_UNKNOWN) + ifp = if_get_by_name(argv[2]->arg, ospf->vrf_id, ospf->name); + + if (ifp == NULL) { + vty_out(vty, "interface %s not found.\n", (char *)argv[2]->arg); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } else { + params = IF_DEF_PARAMS(ifp); + } + + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_ACTIVE); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_network_area, + ospf_network_area_cmd, + "network A.B.C.D/M area <A.B.C.D|(0-4294967295)>", + "Enable routing on an IP network\n" + "OSPF network prefix\n" + "Set the OSPF area ID\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_prefixlen = 1; + int idx_ipv4_number = 3; + struct prefix_ipv4 p; + struct in_addr area_id; + int ret, format; + uint32_t count; + + if (ospf->instance) { + vty_out(vty, + "The network command is not supported in multi-instance ospf\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + count = ospf_count_area_params(ospf); + if (count > 0) { + vty_out(vty, + "Please remove all ip ospf area x.x.x.x commands first.\n"); + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "%s ospf vrf %s num of %u ip ospf area x config", + __func__, ospf_get_name(ospf), count); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get network prefix and Area ID. */ + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + ret = ospf_network_set(ospf, &p, area_id, format); + if (ret == 0) { + vty_out(vty, "There is already same network statement.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_network_area, + no_ospf_network_area_cmd, + "no network A.B.C.D/M area <A.B.C.D|(0-4294967295)>", + NO_STR + "Enable routing on an IP network\n" + "OSPF network prefix\n" + "Set the OSPF area ID\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_prefixlen = 2; + int idx_ipv4_number = 4; + struct prefix_ipv4 p; + struct in_addr area_id; + int ret, format; + + if (ospf->instance) { + vty_out(vty, + "The network command is not supported in multi-instance ospf\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get network prefix and Area ID. */ + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + ret = ospf_network_unset(ospf, &p, area_id); + if (ret == 0) { + vty_out(vty, + "Can't find specified network area configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_range, + ospf_area_range_cmd, + "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M [advertise [cost (0-16777215)]]", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Summarize routes matching address/mask (border routers only)\n" + "Area range prefix\n" + "Advertise this range (default)\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + int idx_cost = 6; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; + uint32_t cost; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_set(ospf, area, area->ranges, &p, + OSPF_AREA_RANGE_ADVERTISE, false); + if (argc > 5) { + cost = strtoul(argv[idx_cost]->arg, NULL, 10); + ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost); + } + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_range_cost, + ospf_area_range_cost_cmd, + "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M {cost (0-16777215)|substitute A.B.C.D/M}", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Summarize routes matching address/mask (border routers only)\n" + "Area range prefix\n" + "User specified metric for this range\n" + "Advertised metric for this range\n" + "Announce area range as another prefix\n" + "Network prefix to be announced instead of range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + int idx = 4; + struct prefix_ipv4 p, s; + struct in_addr area_id; + int format; + uint32_t cost; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_set(ospf, area, area->ranges, &p, + OSPF_AREA_RANGE_ADVERTISE, false); + if (argv_find(argv, argc, "cost", &idx)) { + cost = strtoul(argv[idx + 1]->arg, NULL, 10); + ospf_area_range_cost_set(ospf, area, area->ranges, &p, cost); + } + + idx = 4; + if (argv_find(argv, argc, "substitute", &idx)) { + str2prefix_ipv4(argv[idx + 1]->arg, &s); + ospf_area_range_substitute_set(ospf, area, &p, &s); + } + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_range_not_advertise, + ospf_area_range_not_advertise_cmd, + "area <A.B.C.D|(0-4294967295)> range A.B.C.D/M not-advertise", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Summarize routes matching address/mask (border routers only)\n" + "Area range prefix\n" + "DoNotAdvertise this range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + int idx_ipv4_number = 1; + int idx_ipv4_prefixlen = 3; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_set(ospf, area, area->ranges, &p, 0, false); + ospf_area_range_substitute_unset(ospf, area, &p); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_range, + no_ospf_area_range_cmd, + "no area <A.B.C.D|(0-4294967295)> range A.B.C.D/M [<cost (0-16777215)|advertise [cost (0-16777215)]|not-advertise>]", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Summarize routes matching address/mask (border routers only)\n" + "Area range prefix\n" + "User specified metric for this range\n" + "Advertised metric for this range\n" + "Advertise this range (default)\n" + "User specified metric for this range\n" + "Advertised metric for this range\n" + "DoNotAdvertise this range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + int idx_ipv4_number = 2; + int idx_ipv4_prefixlen = 4; + struct prefix_ipv4 p; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_unset(ospf, area, area->ranges, &p); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_range_substitute, + no_ospf_area_range_substitute_cmd, + "no area <A.B.C.D|(0-4294967295)> range A.B.C.D/M substitute A.B.C.D/M", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Summarize routes matching address/mask (border routers only)\n" + "Area range prefix\n" + "Announce area range as another prefix\n" + "Network prefix to be announced instead of range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + int idx_ipv4_number = 2; + int idx_ipv4_prefixlen = 4; + int idx_ipv4_prefixlen_2 = 6; + struct prefix_ipv4 p, s; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p); + str2prefix_ipv4(argv[idx_ipv4_prefixlen_2]->arg, &s); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + ospf_area_range_substitute_unset(ospf, area, &p); + + return CMD_SUCCESS; +} + + +/* Command Handler Logic in VLink stuff is delicate!! + + ALTER AT YOUR OWN RISK!!!! + + Various dummy values are used to represent 'NoChange' state for + VLink configuration NOT being changed by a VLink command, and + special syntax is used within the command strings so that the + typed in command verbs can be seen in the configuration command + bacckend handler. This is to drastically reduce the verbeage + required to coe up with a reasonably compatible Cisco VLink command + + - Matthew Grant <grantma@anathoth.gen.nz> + Wed, 21 Feb 2001 15:13:52 +1300 + */ + +/* Configuration data for virtual links + */ +struct ospf_vl_config_data { + struct vty *vty; /* vty stuff */ + struct in_addr area_id; /* area ID from command line */ + int area_id_fmt; /* command line area ID format */ + struct in_addr vl_peer; /* command line vl_peer */ + int auth_type; /* Authehntication type, if given */ + char *auth_key; /* simple password if present */ + int crypto_key_id; /* Cryptographic key ID */ + char *md5_key; /* MD5 authentication key */ + char *keychain; /* Cryptographic keychain */ + int del_keychain; + int hello_interval; /* Obvious what these are... */ + int retransmit_interval; + int transmit_delay; + int dead_interval; +}; + +static void ospf_vl_config_data_init(struct ospf_vl_config_data *vl_config, + struct vty *vty) +{ + memset(vl_config, 0, sizeof(struct ospf_vl_config_data)); + vl_config->auth_type = OSPF_AUTH_CMD_NOTSEEN; + vl_config->vty = vty; +} + +static struct ospf_vl_data * +ospf_find_vl_data(struct ospf *ospf, struct ospf_vl_config_data *vl_config) +{ + struct ospf_area *area; + struct ospf_vl_data *vl_data; + struct vty *vty; + struct in_addr area_id; + + vty = vl_config->vty; + area_id = vl_config->area_id; + + if (area_id.s_addr == OSPF_AREA_BACKBONE) { + vty_out(vty, + "Configuring VLs over the backbone is not allowed\n"); + return NULL; + } + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, vl_config->area_id_fmt); + + if (area->external_routing != OSPF_AREA_DEFAULT) { + if (vl_config->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + vty_out(vty, "Area %pI4 is %s\n", &area_id, + area->external_routing == OSPF_AREA_NSSA + ? "nssa" + : "stub"); + else + vty_out(vty, "Area %ld is %s\n", + (unsigned long)ntohl(area_id.s_addr), + area->external_routing == OSPF_AREA_NSSA + ? "nssa" + : "stub"); + return NULL; + } + + if ((vl_data = ospf_vl_lookup(ospf, area, vl_config->vl_peer)) + == NULL) { + vl_data = ospf_vl_data_new(area, vl_config->vl_peer); + if (vl_data->vl_oi == NULL) { + vl_data->vl_oi = ospf_vl_new(ospf, vl_data); + ospf_vl_add(ospf, vl_data); + ospf_spf_calculate_schedule(ospf, + SPF_FLAG_CONFIG_CHANGE); + } + } + return vl_data; +} + + +static int ospf_vl_set_security(struct ospf_vl_data *vl_data, + struct ospf_vl_config_data *vl_config) +{ + struct crypt_key *ck; + struct vty *vty; + struct interface *ifp = vl_data->vl_oi->ifp; + + vty = vl_config->vty; + + if (vl_config->auth_type != OSPF_AUTH_CMD_NOTSEEN) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type); + IF_DEF_PARAMS(ifp)->auth_type = vl_config->auth_type; + } + + if (vl_config->auth_key) { + memset(IF_DEF_PARAMS(ifp)->auth_simple, 0, + OSPF_AUTH_SIMPLE_SIZE + 1); + strlcpy((char *)IF_DEF_PARAMS(ifp)->auth_simple, + vl_config->auth_key, + sizeof(IF_DEF_PARAMS(ifp)->auth_simple)); + } else if (vl_config->keychain) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), keychain_name); + XFREE(MTYPE_OSPF_IF_PARAMS, IF_DEF_PARAMS(ifp)->keychain_name); + IF_DEF_PARAMS(ifp)->keychain_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS, vl_config->keychain); + } else if (vl_config->md5_key) { + if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id) + != NULL) { + vty_out(vty, "OSPF: Key %d already exists\n", + vl_config->crypto_key_id); + return CMD_WARNING; + } + ck = ospf_crypt_key_new(); + ck->key_id = vl_config->crypto_key_id; + memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1); + strlcpy((char *)ck->auth_key, vl_config->md5_key, + sizeof(ck->auth_key)); + + ospf_crypt_key_add(IF_DEF_PARAMS(ifp)->auth_crypt, ck); + } else if (vl_config->crypto_key_id != 0) { + /* Delete a key */ + + if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id) + == NULL) { + vty_out(vty, "OSPF: Key %d does not exist\n", + vl_config->crypto_key_id); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf_crypt_key_delete(IF_DEF_PARAMS(ifp)->auth_crypt, + vl_config->crypto_key_id); + } else if (vl_config->del_keychain) { + UNSET_IF_PARAM(IF_DEF_PARAMS(ifp), keychain_name); + XFREE(MTYPE_OSPF_IF_PARAMS, IF_DEF_PARAMS(ifp)->keychain_name); + } + + return CMD_SUCCESS; +} + +static int ospf_vl_set_timers(struct ospf_vl_data *vl_data, + struct ospf_vl_config_data *vl_config) +{ + struct interface *ifp = vl_data->vl_oi->ifp; + /* Virtual Link data initialised to defaults, so only set + if a value given */ + if (vl_config->hello_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello); + IF_DEF_PARAMS(ifp)->v_hello = vl_config->hello_interval; + } + + if (vl_config->dead_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait); + IF_DEF_PARAMS(ifp)->v_wait = vl_config->dead_interval; + } + + if (vl_config->retransmit_interval) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_interval); + IF_DEF_PARAMS(ifp)->retransmit_interval = + vl_config->retransmit_interval; + } + + if (vl_config->transmit_delay) { + SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay); + IF_DEF_PARAMS(ifp)->transmit_delay = vl_config->transmit_delay; + } + + return CMD_SUCCESS; +} + + +/* The business end of all of the above */ +static int ospf_vl_set(struct ospf *ospf, struct ospf_vl_config_data *vl_config) +{ + struct ospf_vl_data *vl_data; + int ret; + + vl_data = ospf_find_vl_data(ospf, vl_config); + if (!vl_data) + return CMD_WARNING_CONFIG_FAILED; + + /* Process this one first as it can have a fatal result, which can + only logically occur if the virtual link exists already + Thus a command error does not result in a change to the + running configuration such as unexpectedly altered timer + values etc.*/ + ret = ospf_vl_set_security(vl_data, vl_config); + if (ret != CMD_SUCCESS) + return ret; + + /* Set any time based parameters, these area already range checked */ + + ret = ospf_vl_set_timers(vl_data, vl_config); + if (ret != CMD_SUCCESS) + return ret; + + return CMD_SUCCESS; +} + +/* This stuff exists to make specifying all the alias commands A LOT simpler + */ +#define VLINK_HELPSTR_IPADDR \ + "OSPF area parameters\n" \ + "OSPF area ID in IP address format\n" \ + "OSPF area ID as a decimal value\n" \ + "Configure a virtual link\n" \ + "Router ID of the remote ABR\n" + +#define VLINK_HELPSTR_AUTHTYPE_SIMPLE \ + "Enable authentication on this virtual link\n" \ + "dummy string \n" + +#define VLINK_HELPSTR_AUTHTYPE_ALL \ + VLINK_HELPSTR_AUTHTYPE_SIMPLE \ + "Use null authentication\n" \ + "Use message-digest authentication\n" + +#define VLINK_HELPSTR_TIME_PARAM \ + "Time between HELLO packets\n" \ + "Seconds\n" \ + "Time between retransmitting lost link state advertisements\n" \ + "Seconds\n" \ + "Link state transmit delay\n" \ + "Seconds\n" \ + "Interval time after which a neighbor is declared down\n" \ + "Seconds\n" + +#define VLINK_HELPSTR_AUTH_SIMPLE \ + "Authentication password (key)\n" \ + "The OSPF password (key)\n" + +#define VLINK_HELPSTR_AUTH_MD5 \ + "Message digest authentication password (key)\n" \ + "Key ID\n" \ + "Use MD5 algorithm\n" \ + "The OSPF password (key)\n" + +DEFUN (ospf_area_vlink, + ospf_area_vlink_cmd, + "area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D [authentication [<key-chain KEYCHAIN_NAME|message-digest|null>]] [<message-digest-key (1-255) md5 KEY|authentication-key AUTH_KEY>]", + VLINK_HELPSTR_IPADDR + "Enable authentication on this virtual link\n" + "Use a key-chain for cryptographic authentication keys\n" + "Key-chain name\n" + "Use message-digest authentication\n" + "Use null authentication\n" + VLINK_HELPSTR_AUTH_MD5 + VLINK_HELPSTR_AUTH_SIMPLE) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_ipv4 = 3; + struct ospf_vl_config_data vl_config; + char auth_key[OSPF_AUTH_SIMPLE_SIZE + 1]; + char md5_key[OSPF_AUTH_MD5_SIZE + 1]; + int ret; + int idx = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + /* Read off first 2 parameters and check them */ + ret = str2area_id(argv[idx_ipv4_number]->arg, &vl_config.area_id, + &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(argv[idx_ipv4]->arg, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc <= 4) { + /* Thats all folks! - BUGS B. strikes again!!!*/ + + return ospf_vl_set(ospf, &vl_config); + } + + if (argv_find(argv, argc, "authentication", &idx)) { + /* authentication - this option can only occur + at start of command line */ + vl_config.auth_type = OSPF_AUTH_SIMPLE; + } + + if (argv_find(argv, argc, "key-chain", &idx)) { + vl_config.auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + vl_config.keychain = argv[idx+1]->arg; + } else if (argv_find(argv, argc, "message-digest", &idx)) { + /* authentication message-digest */ + vl_config.auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + } else if (argv_find(argv, argc, "null", &idx)) { + /* "authentication null" */ + vl_config.auth_type = OSPF_AUTH_NULL; + } + + if (argv_find(argv, argc, "message-digest-key", &idx)) { + vl_config.md5_key = NULL; + vl_config.crypto_key_id = strtol(argv[idx + 1]->arg, NULL, 10); + if (vl_config.crypto_key_id < 0) + return CMD_WARNING_CONFIG_FAILED; + + strlcpy(md5_key, argv[idx + 3]->arg, sizeof(md5_key)); + vl_config.md5_key = md5_key; + } + + if (argv_find(argv, argc, "authentication-key", &idx)) { + strlcpy(auth_key, argv[idx + 1]->arg, sizeof(auth_key)); + vl_config.auth_key = auth_key; + } + + /* Action configuration */ + + return ospf_vl_set(ospf, &vl_config); +} + +DEFUN (no_ospf_area_vlink, + no_ospf_area_vlink_cmd, + "no area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D [authentication [<key-chain KEYCHAIN_NAME|message-digest|null>]] [<message-digest-key (1-255) md5 KEY|authentication-key AUTH_KEY>]", + NO_STR + VLINK_HELPSTR_IPADDR + "Enable authentication on this virtual link\n" + "Use a key-chain for cryptographic authentication keys\n" + "Key-chain name\n" + "Use message-digest authentication\n" + "Use null authentication\n" + VLINK_HELPSTR_AUTH_MD5 + VLINK_HELPSTR_AUTH_SIMPLE) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_ipv4 = 4; + struct ospf_area *area; + struct ospf_vl_config_data vl_config; + struct ospf_vl_data *vl_data = NULL; + char auth_key[OSPF_AUTH_SIMPLE_SIZE + 1]; + int idx = 0; + int ret, format; + + ospf_vl_config_data_init(&vl_config, vty); + + ret = str2area_id(argv[idx_ipv4_number]->arg, &vl_config.area_id, + &format); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + area = ospf_area_lookup_by_area_id(ospf, vl_config.area_id); + if (!area) { + vty_out(vty, "Area does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(argv[idx_ipv4]->arg, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer); + if (!vl_data) { + vty_out(vty, "Virtual link does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc <= 5) { + /* Basic VLink no command */ + /* Thats all folks! - BUGS B. strikes again!!!*/ + ospf_vl_delete(ospf, vl_data); + ospf_area_check_free(ospf, vl_config.area_id); + return CMD_SUCCESS; + } + + /* If we are down here, we are reseting parameters */ + /* Deal with other parameters */ + + if (argv_find(argv, argc, "authentication", &idx)) { + /* authentication - this option can only occur + at start of command line */ + vl_config.auth_type = OSPF_AUTH_NOTSET; + } + + if (argv_find(argv, argc, "key-chain", &idx)) { + vl_config.del_keychain = 1; + vl_config.keychain = NULL; + } + + if (argv_find(argv, argc, "message-digest-key", &idx)) { + vl_config.md5_key = NULL; + vl_config.crypto_key_id = strtol(argv[idx + 1]->arg, NULL, 10); + if (vl_config.crypto_key_id < 0) + return CMD_WARNING_CONFIG_FAILED; + } + + if (argv_find(argv, argc, "authentication-key", &idx)) { + /* Reset authentication-key to 0 */ + memset(auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1); + vl_config.auth_key = auth_key; + } + + /* Action configuration */ + + return ospf_vl_set(ospf, &vl_config); +} + +DEFUN (ospf_area_vlink_intervals, + ospf_area_vlink_intervals_cmd, + "area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", + VLINK_HELPSTR_IPADDR + VLINK_HELPSTR_TIME_PARAM) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_vl_config_data vl_config; + int ret = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + char *area_id = argv[1]->arg; + char *router_id = argv[3]->arg; + + ret = str2area_id(area_id, &vl_config.area_id, &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(router_id, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + for (int idx = 4; idx < argc; idx++) { + if (strmatch(argv[idx]->text, "hello-interval")) + vl_config.hello_interval = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = + strtol(argv[++idx]->arg, NULL, 10); + else if (strmatch(argv[idx]->text, "dead-interval")) + vl_config.dead_interval = + strtol(argv[++idx]->arg, NULL, 10); + } + + /* Action configuration */ + return ospf_vl_set(ospf, &vl_config); +} + +DEFUN (no_ospf_area_vlink_intervals, + no_ospf_area_vlink_intervals_cmd, + "no area <A.B.C.D|(0-4294967295)> virtual-link A.B.C.D {hello-interval (1-65535)|retransmit-interval (1-65535)|transmit-delay (1-65535)|dead-interval (1-65535)}", + NO_STR + VLINK_HELPSTR_IPADDR + VLINK_HELPSTR_TIME_PARAM) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_vl_config_data vl_config; + int ret = 0; + + ospf_vl_config_data_init(&vl_config, vty); + + char *area_id = argv[2]->arg; + char *router_id = argv[4]->arg; + + ret = str2area_id(area_id, &vl_config.area_id, &vl_config.area_id_fmt); + if (ret < 0) { + vty_out(vty, "OSPF area ID is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = inet_aton(router_id, &vl_config.vl_peer); + if (!ret) { + vty_out(vty, "Please specify valid Router ID as a.b.c.d\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + for (int idx = 5; idx < argc; idx++) { + if (strmatch(argv[idx]->text, "hello-interval")) + vl_config.hello_interval = OSPF_HELLO_INTERVAL_DEFAULT; + else if (strmatch(argv[idx]->text, "retransmit-interval")) + vl_config.retransmit_interval = + OSPF_RETRANSMIT_INTERVAL_DEFAULT; + else if (strmatch(argv[idx]->text, "transmit-delay")) + vl_config.transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; + else if (strmatch(argv[idx]->text, "dead-interval")) + vl_config.dead_interval = + OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + } + + /* Action configuration */ + return ospf_vl_set(ospf, &vl_config); +} + +DEFUN (ospf_area_shortcut, + ospf_area_shortcut_cmd, + "area <A.B.C.D|(0-4294967295)> shortcut <default|enable|disable>", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure the area's shortcutting mode\n" + "Set default shortcutting behavior\n" + "Enable shortcutting through the area\n" + "Disable shortcutting through the area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_enable_disable = 3; + struct ospf_area *area; + struct in_addr area_id; + int mode; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("shortcut", area_id, format, + argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (strncmp(argv[idx_enable_disable]->arg, "de", 2) == 0) + mode = OSPF_SHORTCUT_DEFAULT; + else if (strncmp(argv[idx_enable_disable]->arg, "di", 2) == 0) + mode = OSPF_SHORTCUT_DISABLE; + else if (strncmp(argv[idx_enable_disable]->arg, "e", 1) == 0) + mode = OSPF_SHORTCUT_ENABLE; + else + return CMD_WARNING_CONFIG_FAILED; + + ospf_area_shortcut_set(ospf, area, mode); + + if (ospf->abr_type != OSPF_ABR_SHORTCUT) + vty_out(vty, + "Shortcut area setting will take effect only when the router is configured as Shortcut ABR\n"); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_shortcut, + no_ospf_area_shortcut_cmd, + "no area <A.B.C.D|(0-4294967295)> shortcut <enable|disable>", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Deconfigure the area's shortcutting mode\n" + "Deconfigure enabled shortcutting through the area\n" + "Deconfigure disabled shortcutting through the area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("shortcut", area_id, format, + argv[idx_ipv4_number]->arg); + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (!area) + return CMD_SUCCESS; + + ospf_area_shortcut_unset(ospf, area); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_area_stub, + ospf_area_stub_cmd, + "area <A.B.C.D|(0-4294967295)> stub", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as stub\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + + ret = ospf_area_stub_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "First deconfigure all virtual link through this area\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Flush the external LSAs from the specified area */ + ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA); + ospf_area_no_summary_unset(ospf, area_id); + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_stub_no_summary, + ospf_area_stub_no_summary_cmd, + "area <A.B.C.D|(0-4294967295)> stub no-summary", + "OSPF stub parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as stub\n" + "Do not inject inter-area routes into stub\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + + ret = ospf_area_stub_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "%% Area cannot be stub as it contains a virtual link\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf_area_no_summary_set(ospf, area_id); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_stub, + no_ospf_area_stub_cmd, + "no area <A.B.C.D|(0-4294967295)> stub", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as stub\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + + ospf_area_stub_unset(ospf, area_id); + ospf_area_no_summary_unset(ospf, area_id); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_stub_no_summary, + no_ospf_area_stub_no_summary_cmd, + "no area <A.B.C.D|(0-4294967295)> stub no-summary", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as stub\n" + "Do not inject inter-area routes into area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("stub", area_id, format, + argv[idx_ipv4_number]->arg); + ospf_area_no_summary_unset(ospf, area_id); + + return CMD_SUCCESS; +} + +DEFPY (ospf_area_nssa, + ospf_area_nssa_cmd, + "area <A.B.C.D|(0-4294967295)>$area_str nssa\ + [{\ + <translate-candidate|translate-never|translate-always>$translator_role\ + |default-information-originate$dflt_originate [{metric (0-16777214)$mval|metric-type (1-2)$mtype}]\ + |no-summary$no_summary\ + |suppress-fa$suppress_fa\ + }]", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as nssa\n" + "Configure NSSA-ABR for translate election (default)\n" + "Configure NSSA-ABR to never translate\n" + "Configure NSSA-ABR to always translate\n" + "Originate Type 7 default into NSSA area\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Do not inject inter-area routes into nssa\n" + "Suppress forwarding address\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct in_addr area_id; + int ret, format; + + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str); + + ret = ospf_area_nssa_set(ospf, area_id); + ospf_area_display_format_set(ospf, ospf_area_get(ospf, area_id), + format); + if (ret == 0) { + vty_out(vty, + "%% Area cannot be nssa as it contains a virtual link\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (translator_role) { + if (strncmp(translator_role, "translate-c", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_CANDIDATE); + else if (strncmp(translator_role, "translate-n", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_NEVER); + else if (strncmp(translator_role, "translate-a", 11) == 0) + ospf_area_nssa_translator_role_set( + ospf, area_id, OSPF_NSSA_ROLE_ALWAYS); + } else { + ospf_area_nssa_translator_role_set(ospf, area_id, + OSPF_NSSA_ROLE_CANDIDATE); + } + + if (dflt_originate) { + int metric_type = DEFAULT_METRIC_TYPE; + + if (mval_str == NULL) + mval = -1; + if (mtype_str) + (void)str2metric_type(mtype_str, &metric_type); + ospf_area_nssa_default_originate_set(ospf, area_id, mval, + metric_type); + } else + ospf_area_nssa_default_originate_unset(ospf, area_id); + + if (no_summary) + ospf_area_nssa_no_summary_set(ospf, area_id); + else + ospf_area_no_summary_unset(ospf, area_id); + + if (suppress_fa) + ospf_area_nssa_suppress_fa_set(ospf, area_id); + else + ospf_area_nssa_suppress_fa_unset(ospf, area_id); + + /* Flush the external LSA for the specified area */ + ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA); + ospf_schedule_abr_task(ospf); + ospf_schedule_asbr_redist_update(ospf); + + return CMD_SUCCESS; +} + +DEFPY (no_ospf_area_nssa, + no_ospf_area_nssa_cmd, + "no area <A.B.C.D|(0-4294967295)>$area_str nssa\ + [{\ + <translate-candidate|translate-never|translate-always>\ + |default-information-originate [{metric (0-16777214)|metric-type (1-2)}]\ + |no-summary\ + |suppress-fa\ + }]", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as nssa\n" + "Configure NSSA-ABR for translate election (default)\n" + "Configure NSSA-ABR to never translate\n" + "Configure NSSA-ABR to always translate\n" + "Originate Type 7 default into NSSA area\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Do not inject inter-area routes into nssa\n" + "Suppress forwarding address\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID_NO_BB("NSSA", area_id, format, area_str); + + /* Flush the NSSA LSA for the specified area */ + ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_NSSA_LSA); + ospf_area_no_summary_unset(ospf, area_id); + ospf_area_nssa_default_originate_unset(ospf, area_id); + ospf_area_nssa_suppress_fa_unset(ospf, area_id); + ospf_area_nssa_unset(ospf, area_id); + + ospf_schedule_abr_task(ospf); + + return CMD_SUCCESS; +} + +DEFPY (ospf_area_nssa_range, + ospf_area_nssa_range_cmd, + "area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise$not_adv|cost (0-16777215)$cost>]", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as nssa\n" + "Configured address range\n" + "Specify IPv4 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + struct in_addr area_id; + int format; + int advertise = 0; + + VTY_GET_OSPF_AREA_ID(area_id, format, area_str); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (area->external_routing != OSPF_AREA_NSSA) { + vty_out(vty, "%% First configure %s as an NSSA area\n", + area_str); + return CMD_WARNING; + } + + if (!not_adv) + advertise = OSPF_AREA_RANGE_ADVERTISE; + + ospf_area_range_set(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix, advertise, true); + if (cost_str) + ospf_area_range_cost_set(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix, cost); + + return CMD_SUCCESS; +} + +DEFPY (no_ospf_area_nssa_range, + no_ospf_area_nssa_range_cmd, + "no area <A.B.C.D|(0-4294967295)>$area_str nssa range A.B.C.D/M$prefix [<not-advertise|cost (0-16777215)>]", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Configure OSPF area as nssa\n" + "Configured address range\n" + "Specify IPv4 prefix\n" + "Do not advertise\n" + "User specified metric for this range\n" + "Advertised metric for this range\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, area_str); + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (area->external_routing != OSPF_AREA_NSSA) { + vty_out(vty, "%% First configure %s as an NSSA area\n", + area_str); + return CMD_WARNING; + } + + ospf_area_range_unset(ospf, area, area->nssa_ranges, + (struct prefix_ipv4 *)prefix); + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_default_cost, + ospf_area_default_cost_cmd, + "area <A.B.C.D|(0-4294967295)> default-cost (0-16777215)", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Set the summary-default cost of a NSSA or stub area\n" + "Stub's advertised default summary cost\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_number = 3; + struct ospf_area *area; + struct in_addr area_id; + uint32_t cost; + int format; + struct prefix_ipv4 p; + + VTY_GET_OSPF_AREA_ID_NO_BB("default-cost", area_id, format, + argv[idx_ipv4_number]->arg); + cost = strtoul(argv[idx_number]->arg, NULL, 10); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + + if (area->external_routing == OSPF_AREA_DEFAULT) { + vty_out(vty, "The area is neither stub, nor NSSA\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + area->default_cost = cost; + + p.family = AF_INET; + p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; + p.prefixlen = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %pI4", + &area->area_id); + ospf_abr_announce_network_to_area(&p, area->default_cost, area); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_default_cost, + no_ospf_area_default_cost_cmd, + "no area <A.B.C.D|(0-4294967295)> default-cost (0-16777215)", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Set the summary-default cost of a NSSA or stub area\n" + "Stub's advertised default summary cost\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + struct prefix_ipv4 p; + + VTY_GET_OSPF_AREA_ID_NO_BB("default-cost", area_id, format, + argv[idx_ipv4_number]->arg); + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; + + if (area->external_routing == OSPF_AREA_DEFAULT) { + vty_out(vty, "The area is neither stub, nor NSSA\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + area->default_cost = 1; + + p.family = AF_INET; + p.prefix.s_addr = OSPF_DEFAULT_DESTINATION; + p.prefixlen = 0; + if (IS_DEBUG_OSPF_EVENT) + zlog_debug( + "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %pI4", + &area->area_id); + ospf_abr_announce_network_to_area(&p, area->default_cost, area); + + + ospf_area_check_free(ospf, area_id); + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_export_list, + ospf_area_export_list_cmd, + "area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST4_NAME", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Set the filter for networks announced to other areas\n" + "Name of the access-list\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + ospf_area_export_list_set(ospf, area, argv[3]->arg); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_export_list, + no_ospf_area_export_list_cmd, + "no area <A.B.C.D|(0-4294967295)> export-list ACCESSLIST4_NAME", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Unset the filter for networks announced to other areas\n" + "Name of the access-list\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; + + ospf_area_export_list_unset(ospf, area); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_area_import_list, + ospf_area_import_list_cmd, + "area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST4_NAME", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Set the filter for networks from other areas announced to the specified one\n" + "Name of the access-list\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + ospf_area_import_list_set(ospf, area, argv[3]->arg); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_import_list, + no_ospf_area_import_list_cmd, + "no area <A.B.C.D|(0-4294967295)> import-list ACCESSLIST4_NAME", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Unset the filter for networks announced to other areas\n" + "Name of the access-list\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; + + ospf_area_import_list_unset(ospf, area); + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_filter_list, + ospf_area_filter_list_cmd, + "area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Filter networks between OSPF areas\n" + "Filter prefixes between OSPF areas\n" + "Name of an IP prefix-list\n" + "Filter networks sent to this area\n" + "Filter networks sent from this area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + int idx_word = 4; + int idx_in_out = 5; + struct ospf_area *area; + struct in_addr area_id; + struct prefix_list *plist; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + plist = prefix_list_lookup(AFI_IP, argv[idx_word]->arg); + if (strncmp(argv[idx_in_out]->arg, "in", 2) == 0) { + PREFIX_LIST_IN(area) = plist; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); + + PREFIX_NAME_IN(area) = strdup(argv[idx_word]->arg); + ospf_schedule_abr_task(ospf); + } else { + PREFIX_LIST_OUT(area) = plist; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); + + PREFIX_NAME_OUT(area) = strdup(argv[idx_word]->arg); + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_filter_list, + no_ospf_area_filter_list_cmd, + "no area <A.B.C.D|(0-4294967295)> filter-list prefix PREFIXLIST_NAME <in|out>", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Filter networks between OSPF areas\n" + "Filter prefixes between OSPF areas\n" + "Name of an IP prefix-list\n" + "Filter networks sent to this area\n" + "Filter networks sent from this area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + int idx_word = 5; + int idx_in_out = 6; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + if ((area = ospf_area_lookup_by_area_id(ospf, area_id)) == NULL) + return CMD_SUCCESS; + + if (strncmp(argv[idx_in_out]->arg, "in", 2) == 0) { + if (PREFIX_NAME_IN(area)) + if (strcmp(PREFIX_NAME_IN(area), argv[idx_word]->arg) + != 0) + return CMD_SUCCESS; + + PREFIX_LIST_IN(area) = NULL; + if (PREFIX_NAME_IN(area)) + free(PREFIX_NAME_IN(area)); + + PREFIX_NAME_IN(area) = NULL; + + ospf_schedule_abr_task(ospf); + } else { + if (PREFIX_NAME_OUT(area)) + if (strcmp(PREFIX_NAME_OUT(area), argv[idx_word]->arg) + != 0) + return CMD_SUCCESS; + + PREFIX_LIST_OUT(area) = NULL; + if (PREFIX_NAME_OUT(area)) + free(PREFIX_NAME_OUT(area)); + + PREFIX_NAME_OUT(area) = NULL; + + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; +} + + +DEFUN (ospf_area_authentication_message_digest, + ospf_area_authentication_message_digest_cmd, + "[no] area <A.B.C.D|(0-4294967295)> authentication message-digest", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Enable authentication\n" + "Use message-digest authentication\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx = 0; + struct ospf_area *area; + struct in_addr area_id; + int format; + + argv_find(argv, argc, "area", &idx); + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx + 1]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + area->auth_type = strmatch(argv[0]->text, "no") + ? OSPF_AUTH_NULL + : OSPF_AUTH_CRYPTOGRAPHIC; + + return CMD_SUCCESS; +} + +DEFUN (ospf_area_authentication, + ospf_area_authentication_cmd, + "area <A.B.C.D|(0-4294967295)> authentication", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Enable authentication\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 1; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_get(ospf, area_id); + ospf_area_display_format_set(ospf, area, format); + area->auth_type = OSPF_AUTH_SIMPLE; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_area_authentication, + no_ospf_area_authentication_cmd, + "no area <A.B.C.D|(0-4294967295)> authentication", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Enable authentication\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4_number = 2; + struct ospf_area *area; + struct in_addr area_id; + int format; + + VTY_GET_OSPF_AREA_ID(area_id, format, argv[idx_ipv4_number]->arg); + + area = ospf_area_lookup_by_area_id(ospf, area_id); + if (area == NULL) + return CMD_SUCCESS; + + area->auth_type = OSPF_AUTH_NULL; + + ospf_area_check_free(ospf, area_id); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_abr_type, + ospf_abr_type_cmd, + "ospf abr-type <cisco|ibm|shortcut|standard>", + "OSPF specific commands\n" + "Set OSPF ABR type\n" + "Alternative ABR, cisco implementation\n" + "Alternative ABR, IBM implementation\n" + "Shortcut ABR\n" + "Standard behavior (RFC2328)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_vendor = 2; + uint8_t abr_type = OSPF_ABR_UNKNOWN; + + if (strncmp(argv[idx_vendor]->arg, "c", 1) == 0) + abr_type = OSPF_ABR_CISCO; + else if (strncmp(argv[idx_vendor]->arg, "i", 1) == 0) + abr_type = OSPF_ABR_IBM; + else if (strncmp(argv[idx_vendor]->arg, "sh", 2) == 0) + abr_type = OSPF_ABR_SHORTCUT; + else if (strncmp(argv[idx_vendor]->arg, "st", 2) == 0) + abr_type = OSPF_ABR_STAND; + else + return CMD_WARNING_CONFIG_FAILED; + + /* If ABR type value is changed, schedule ABR task. */ + if (ospf->abr_type != abr_type) { + ospf->abr_type = abr_type; + ospf_schedule_abr_task(ospf); + + /* The ABR task might not initiate SPF recalculation if the + * OSPF flags remain the same. And inter-area routes would not + * be added/deleted according to the new ABR type. So this + * needs to be done here too. + */ + ospf_spf_calculate_schedule(ospf, SPF_FLAG_ABR_STATUS_CHANGE); + } + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_abr_type, + no_ospf_abr_type_cmd, + "no ospf abr-type <cisco|ibm|shortcut|standard>", + NO_STR + "OSPF specific commands\n" + "Set OSPF ABR type\n" + "Alternative ABR, cisco implementation\n" + "Alternative ABR, IBM implementation\n" + "Shortcut ABR\n" + "Standard ABR\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_vendor = 3; + uint8_t abr_type = OSPF_ABR_UNKNOWN; + + if (strncmp(argv[idx_vendor]->arg, "c", 1) == 0) + abr_type = OSPF_ABR_CISCO; + else if (strncmp(argv[idx_vendor]->arg, "i", 1) == 0) + abr_type = OSPF_ABR_IBM; + else if (strncmp(argv[idx_vendor]->arg, "sh", 2) == 0) + abr_type = OSPF_ABR_SHORTCUT; + else if (strncmp(argv[idx_vendor]->arg, "st", 2) == 0) + abr_type = OSPF_ABR_STAND; + else + return CMD_WARNING_CONFIG_FAILED; + + /* If ABR type value is changed, schedule ABR task. */ + if (ospf->abr_type == abr_type) { + ospf->abr_type = OSPF_ABR_DEFAULT; + ospf_schedule_abr_task(ospf); + } + + return CMD_SUCCESS; +} + +DEFUN (ospf_log_adjacency_changes, + ospf_log_adjacency_changes_cmd, + "log-adjacency-changes", + "Log changes in adjacency state\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; +} + +DEFUN (ospf_log_adjacency_changes_detail, + ospf_log_adjacency_changes_detail_cmd, + "log-adjacency-changes detail", + "Log changes in adjacency state\n" + "Log all state changes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; +} + +DEFUN (no_ospf_log_adjacency_changes, + no_ospf_log_adjacency_changes_cmd, + "no log-adjacency-changes", + NO_STR + "Log changes in adjacency state\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES); + return CMD_SUCCESS; +} + +DEFUN (no_ospf_log_adjacency_changes_detail, + no_ospf_log_adjacency_changes_detail_cmd, + "no log-adjacency-changes detail", + NO_STR + "Log changes in adjacency state\n" + "Log all state changes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + UNSET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL); + return CMD_SUCCESS; +} + +DEFUN (ospf_compatible_rfc1583, + ospf_compatible_rfc1583_cmd, + "compatible rfc1583", + "OSPF compatibility list\n" + "compatible with RFC 1583\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (!CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + SET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE); + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + } + return CMD_SUCCESS; +} + +DEFUN (no_ospf_compatible_rfc1583, + no_ospf_compatible_rfc1583_cmd, + "no compatible rfc1583", + NO_STR + "OSPF compatibility list\n" + "compatible with RFC 1583\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + UNSET_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE); + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + } + return CMD_SUCCESS; +} + +ALIAS(ospf_compatible_rfc1583, ospf_rfc1583_flag_cmd, + "ospf rfc1583compatibility", + "OSPF specific commands\n" + "Enable the RFC1583Compatibility flag\n") + +ALIAS(no_ospf_compatible_rfc1583, no_ospf_rfc1583_flag_cmd, + "no ospf rfc1583compatibility", NO_STR + "OSPF specific commands\n" + "Disable the RFC1583Compatibility flag\n") + +static void ospf_table_reinstall_routes(struct ospf *ospf, + struct route_table *rt) +{ + struct route_node *rn; + + if (!rt) + return; + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + struct ospf_route *or; + + or = rn->info; + if (!or) + continue; + + if (or->type == OSPF_DESTINATION_NETWORK) + ospf_zebra_add(ospf, (struct prefix_ipv4 *)&rn->p, or); + else if (or->type == OSPF_DESTINATION_DISCARD) + ospf_zebra_add_discard(ospf, + (struct prefix_ipv4 *)&rn->p); + } +} + +static void ospf_reinstall_routes(struct ospf *ospf) +{ + ospf_table_reinstall_routes(ospf, ospf->new_table); + ospf_table_reinstall_routes(ospf, ospf->new_external_route); +} + +DEFPY (ospf_send_extra_data, + ospf_send_extra_data_cmd, + "[no] ospf send-extra-data zebra", + NO_STR + OSPF_STR + "Extra data to Zebra for display/use\n" + "To zebra\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (no && CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) { + UNSET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA); + ospf_reinstall_routes(ospf); + } else if (!CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) { + SET_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA); + ospf_reinstall_routes(ospf); + } + + return CMD_SUCCESS; +} + +static int ospf_timers_spf_set(struct vty *vty, unsigned int delay, + unsigned int hold, unsigned int max) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->spf_delay = delay; + ospf->spf_holdtime = hold; + ospf->spf_max_holdtime = max; + + return CMD_SUCCESS; +} + +DEFUN (ospf_timers_min_ls_interval, + ospf_timers_min_ls_interval_cmd, + "timers throttle lsa all (0-5000)", + "Adjust routing timers\n" + "Throttling adaptive timer\n" + "LSA delay between transmissions\n" + "All LSA types\n" + "Delay (msec) between sending LSAs\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 4; + unsigned int interval; + + if (argc < 5) { + vty_out(vty, "Insufficient arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + interval = strtoul(argv[idx_number]->arg, NULL, 10); + + ospf->min_ls_interval = interval; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_timers_min_ls_interval, + no_ospf_timers_min_ls_interval_cmd, + "no timers throttle lsa all [(0-5000)]", + NO_STR + "Adjust routing timers\n" + "Throttling adaptive timer\n" + "LSA delay between transmissions\n" + "All LSA types\n" + "Delay (msec) between sending LSAs\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + ospf->min_ls_interval = OSPF_MIN_LS_INTERVAL; + + return CMD_SUCCESS; +} + +DEFUN (ospf_timers_throttle_spf, + ospf_timers_throttle_spf_cmd, + "timers throttle spf (0-600000) (0-600000) (0-600000)", + "Adjust routing timers\n" + "Throttling adaptive timer\n" + "OSPF SPF timers\n" + "Delay (msec) from first change received till SPF calculation\n" + "Initial hold time (msec) between consecutive SPF calculations\n" + "Maximum hold time (msec)\n") +{ + int idx_number = 3; + int idx_number_2 = 4; + int idx_number_3 = 5; + unsigned int delay, hold, max; + + if (argc < 6) { + vty_out(vty, "Insufficient arguments\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + delay = strtoul(argv[idx_number]->arg, NULL, 10); + hold = strtoul(argv[idx_number_2]->arg, NULL, 10); + max = strtoul(argv[idx_number_3]->arg, NULL, 10); + + return ospf_timers_spf_set(vty, delay, hold, max); +} + +DEFUN (no_ospf_timers_throttle_spf, + no_ospf_timers_throttle_spf_cmd, + "no timers throttle spf [(0-600000)(0-600000)(0-600000)]", + NO_STR + "Adjust routing timers\n" + "Throttling adaptive timer\n" + "OSPF SPF timers\n" + "Delay (msec) from first change received till SPF calculation\n" + "Initial hold time (msec) between consecutive SPF calculations\n" + "Maximum hold time (msec)\n") +{ + return ospf_timers_spf_set(vty, OSPF_SPF_DELAY_DEFAULT, + OSPF_SPF_HOLDTIME_DEFAULT, + OSPF_SPF_MAX_HOLDTIME_DEFAULT); +} + + +DEFUN (ospf_timers_lsa_min_arrival, + ospf_timers_lsa_min_arrival_cmd, + "timers lsa min-arrival (0-600000)", + "Adjust routing timers\n" + "OSPF LSA timers\n" + "Minimum delay in receiving new version of a LSA\n" + "Delay in milliseconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + ospf->min_ls_arrival = strtoul(argv[argc - 1]->arg, NULL, 10); + return CMD_SUCCESS; +} + +DEFUN (no_ospf_timers_lsa_min_arrival, + no_ospf_timers_lsa_min_arrival_cmd, + "no timers lsa min-arrival [(0-600000)]", + NO_STR + "Adjust routing timers\n" + "OSPF LSA timers\n" + "Minimum delay in receiving new version of a LSA\n" + "Delay in milliseconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + unsigned int minarrival; + + if (argc > 4) { + minarrival = strtoul(argv[argc - 1]->arg, NULL, 10); + + if (ospf->min_ls_arrival != minarrival + || minarrival == OSPF_MIN_LS_ARRIVAL) + return CMD_SUCCESS; + } + + ospf->min_ls_arrival = OSPF_MIN_LS_ARRIVAL; + + return CMD_SUCCESS; +} + +DEFUN (ospf_neighbor, + ospf_neighbor_cmd, + "neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]", + NEIGHBOR_STR + "Neighbor IP address\n" + "Neighbor Priority\n" + "Priority\n" + "Dead Neighbor Polling interval\n" + "Seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + int idx_pri = 3; + int idx_poll = 5; + struct in_addr nbr_addr; + unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT; + unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT; + + if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) { + vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > 2) + priority = strtoul(argv[idx_pri]->arg, NULL, 10); + + if (argc > 4) + interval = strtoul(argv[idx_poll]->arg, NULL, 10); + + ospf_nbr_nbma_set(ospf, nbr_addr); + + if (argc > 2) + ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority); + + if (argc > 4) + ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval); + + return CMD_SUCCESS; +} + +DEFUN (ospf_neighbor_poll_interval, + ospf_neighbor_poll_interval_cmd, + "neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]", + NEIGHBOR_STR + "Neighbor IP address\n" + "Dead Neighbor Polling interval\n" + "Seconds\n" + "OSPF priority of non-broadcast neighbor\n" + "Priority\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 1; + int idx_poll = 3; + int idx_pri = 5; + struct in_addr nbr_addr; + unsigned int priority; + unsigned int interval; + + if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) { + vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + interval = strtoul(argv[idx_poll]->arg, NULL, 10); + + priority = argc > 4 ? strtoul(argv[idx_pri]->arg, NULL, 10) + : OSPF_NEIGHBOR_PRIORITY_DEFAULT; + + ospf_nbr_nbma_set(ospf, nbr_addr); + ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval); + + if (argc > 4) + ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_neighbor, + no_ospf_neighbor_cmd, + "no neighbor A.B.C.D [priority (0-255) [poll-interval (1-65525)]]", + NO_STR + NEIGHBOR_STR + "Neighbor IP address\n" + "Neighbor Priority\n" + "Priority\n" + "Dead Neighbor Polling interval\n" + "Seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct in_addr nbr_addr; + + if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) { + vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + (void)ospf_nbr_nbma_unset(ospf, nbr_addr); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_neighbor_poll, + no_ospf_neighbor_poll_cmd, + "no neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]", + NO_STR + NEIGHBOR_STR + "Neighbor IP address\n" + "Dead Neighbor Polling interval\n" + "Seconds\n" + "Neighbor Priority\n" + "Priority\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ipv4 = 2; + struct in_addr nbr_addr; + + if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) { + vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + (void)ospf_nbr_nbma_unset(ospf, nbr_addr); + + return CMD_SUCCESS; +} + +DEFUN (ospf_refresh_timer, + ospf_refresh_timer_cmd, + "refresh timer (10-1800)", + "Adjust refresh parameters\n" + "Set refresh timer\n" + "Timer value in seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 2; + unsigned int interval; + + interval = strtoul(argv[idx_number]->arg, NULL, 10); + interval = (interval / OSPF_LSA_REFRESHER_GRANULARITY) + * OSPF_LSA_REFRESHER_GRANULARITY; + + ospf_timers_refresh_set(ospf, interval); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_refresh_timer, + no_ospf_refresh_timer_val_cmd, + "no refresh timer [(10-1800)]", + NO_STR + "Adjust refresh parameters\n" + "Unset refresh timer\n" + "Timer value in seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int interval; + + if (argc == 1) { + interval = strtoul(argv[idx_number]->arg, NULL, 10); + + if (ospf->lsa_refresh_interval != interval + || interval == OSPF_LSA_REFRESH_INTERVAL_DEFAULT) + return CMD_SUCCESS; + } + + ospf_timers_refresh_unset(ospf); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_auto_cost_reference_bandwidth, + ospf_auto_cost_reference_bandwidth_cmd, + "auto-cost reference-bandwidth (1-4294967)", + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id); + int idx_number = 2; + uint32_t refbw; + struct interface *ifp; + + refbw = strtol(argv[idx_number]->arg, NULL, 10); + if (refbw < 1 || refbw > 4294967) { + vty_out(vty, "reference-bandwidth value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* If reference bandwidth is changed. */ + if ((refbw) == ospf->ref_bandwidth) + return CMD_SUCCESS; + + ospf->ref_bandwidth = refbw; + FOR_ALL_INTERFACES (vrf, ifp) + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_auto_cost_reference_bandwidth, + no_ospf_auto_cost_reference_bandwidth_cmd, + "no auto-cost reference-bandwidth [(1-4294967)]", + NO_STR + "Calculate OSPF interface cost according to bandwidth\n" + "Use reference bandwidth method to assign OSPF cost\n" + "The reference bandwidth in terms of Mbits per second\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id); + struct interface *ifp; + + if (ospf->ref_bandwidth == OSPF_DEFAULT_REF_BANDWIDTH) + return CMD_SUCCESS; + + ospf->ref_bandwidth = OSPF_DEFAULT_REF_BANDWIDTH; + vty_out(vty, "%% OSPF: Reference bandwidth is changed.\n"); + vty_out(vty, + " Please ensure reference bandwidth is consistent across all routers\n"); + + FOR_ALL_INTERFACES (vrf, ifp) + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; +} + +DEFUN (ospf_write_multiplier, + ospf_write_multiplier_cmd, + "ospf write-multiplier (1-100)", + "OSPF specific commands\n" + "Write multiplier\n" + "Maximum number of interface serviced per write\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number; + uint32_t write_oi_count; + + if (argc == 3) + idx_number = 2; + else + idx_number = 1; + + write_oi_count = strtol(argv[idx_number]->arg, NULL, 10); + if (write_oi_count < 1 || write_oi_count > 100) { + vty_out(vty, "write-multiplier value is invalid\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf->write_oi_count = write_oi_count; + return CMD_SUCCESS; +} + +ALIAS(ospf_write_multiplier, write_multiplier_cmd, "write-multiplier (1-100)", + "Write multiplier\n" + "Maximum number of interface serviced per write\n") + +DEFUN (no_ospf_write_multiplier, + no_ospf_write_multiplier_cmd, + "no ospf write-multiplier (1-100)", + NO_STR + "OSPF specific commands\n" + "Write multiplier\n" + "Maximum number of interface serviced per write\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT; + return CMD_SUCCESS; +} + +ALIAS(no_ospf_write_multiplier, no_write_multiplier_cmd, + "no write-multiplier (1-100)", NO_STR + "Write multiplier\n" + "Maximum number of interface serviced per write\n") + +DEFUN(ospf_ti_lfa, ospf_ti_lfa_cmd, "fast-reroute ti-lfa [node-protection]", + "Fast Reroute for MPLS and IP resilience\n" + "Topology Independent LFA (Loop-Free Alternate)\n" + "TI-LFA node protection (default is link protection)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->ti_lfa_enabled = true; + + if (argc == 3) + ospf->ti_lfa_protection_type = OSPF_TI_LFA_NODE_PROTECTION; + else + ospf->ti_lfa_protection_type = OSPF_TI_LFA_LINK_PROTECTION; + + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + + return CMD_SUCCESS; +} + +DEFUN(no_ospf_ti_lfa, no_ospf_ti_lfa_cmd, + "no fast-reroute ti-lfa [node-protection]", + NO_STR + "Fast Reroute for MPLS and IP resilience\n" + "Topology Independent LFA (Loop-Free Alternate)\n" + "TI-LFA node protection (default is link protection)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->ti_lfa_enabled = false; + + ospf->ti_lfa_protection_type = OSPF_TI_LFA_UNDEFINED_PROTECTION; + + ospf_spf_calculate_schedule(ospf, SPF_FLAG_CONFIG_CHANGE); + + return CMD_SUCCESS; +} + +static void ospf_maxpath_set(struct vty *vty, struct ospf *ospf, uint16_t paths) +{ + if (ospf->max_multipath == paths) + return; + + ospf->max_multipath = paths; + + /* Send deletion notification to zebra to delete all + * ospf specific routes and reinitiat SPF to reflect + * the new max multipath. + */ + ospf_restart_spf(ospf); +} + +/* Ospf Maximum multiple paths config support */ +DEFUN (ospf_max_multipath, + ospf_max_multipath_cmd, + "maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM), + "Max no of multiple paths for ECMP support\n" + "Number of paths\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 1; + uint16_t maxpaths; + + maxpaths = strtol(argv[idx_number]->arg, NULL, 10); + + ospf_maxpath_set(vty, ospf, maxpaths); + return CMD_SUCCESS; +} + +DEFUN (no_ospf_max_multipath, + no_ospf_max_multipath_cmd, + "no maximum-paths", + NO_STR + "Max no of multiple paths for ECMP support\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + uint16_t maxpaths = MULTIPATH_NUM; + + ospf_maxpath_set(vty, ospf, maxpaths); + return CMD_SUCCESS; +} + +static const char *const ospf_abr_type_descr_str[] = { + "Unknown", "Standard (RFC2328)", "Alternative IBM", + "Alternative Cisco", "Alternative Shortcut" +}; + +static const char *const ospf_shortcut_mode_descr_str[] = { + "Default", "Enabled", "Disabled" +}; + +static void show_ip_ospf_area(struct vty *vty, struct ospf_area *area, + json_object *json_areas, bool use_json) +{ + json_object *json_area = NULL; + char buf[PREFIX_STRLEN]; + + if (use_json) + json_area = json_object_new_object(); + + /* Show Area ID. */ + if (!use_json) + vty_out(vty, " Area ID: %pI4", &area->area_id); + + /* Show Area type/mode. */ + if (OSPF_IS_AREA_BACKBONE(area)) { + if (use_json) + json_object_boolean_true_add(json_area, "backbone"); + else + vty_out(vty, " (Backbone)\n"); + } else { + if (use_json) { + if (area->external_routing == OSPF_AREA_STUB) { + if (area->no_summary) + json_object_boolean_true_add( + json_area, "stubNoSummary"); + if (area->shortcut_configured) + json_object_boolean_true_add( + json_area, "stubShortcut"); + } else if (area->external_routing == OSPF_AREA_NSSA) { + if (area->no_summary) + json_object_boolean_true_add( + json_area, "nssaNoSummary"); + if (area->shortcut_configured) + json_object_boolean_true_add( + json_area, "nssaShortcut"); + } + + json_object_string_add( + json_area, "shortcuttingMode", + ospf_shortcut_mode_descr_str + [area->shortcut_configured]); + if (area->shortcut_capability) + json_object_boolean_true_add(json_area, + "sBitConcensus"); + } else { + if (area->external_routing == OSPF_AREA_STUB) + vty_out(vty, " (Stub%s%s)", + area->no_summary ? ", no summary" : "", + area->shortcut_configured ? "; " : ""); + else if (area->external_routing == OSPF_AREA_NSSA) + vty_out(vty, " (NSSA%s%s)", + area->no_summary ? ", no summary" : "", + area->shortcut_configured ? "; " : ""); + + vty_out(vty, "\n"); + vty_out(vty, " Shortcutting mode: %s", + ospf_shortcut_mode_descr_str + [area->shortcut_configured]); + vty_out(vty, ", S-bit consensus: %s\n", + area->shortcut_capability ? "ok" : "no"); + } + } + + /* Show number of interfaces */ + if (use_json) { + json_object_int_add(json_area, "areaIfTotalCounter", + listcount(area->oiflist)); + json_object_int_add(json_area, "areaIfActiveCounter", + area->act_ints); + } else + vty_out(vty, + " Number of interfaces in this area: Total: %d, Active: %d\n", + listcount(area->oiflist), area->act_ints); + + if (area->external_routing == OSPF_AREA_NSSA) { + if (use_json) { + json_object_boolean_true_add(json_area, "nssa"); + if (!IS_OSPF_ABR(area->ospf)) + json_object_boolean_false_add(json_area, "abr"); + else if (area->NSSATranslatorState) { + json_object_boolean_true_add(json_area, "abr"); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + json_object_boolean_true_add( + json_area, + "nssaTranslatorElected"); + else if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_ALWAYS) + json_object_boolean_true_add( + json_area, + "nssaTranslatorAlways"); + else + json_object_boolean_true_add( + json_area, + "nssaTranslatorNever"); + } else { + json_object_boolean_true_add(json_area, "abr"); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + json_object_boolean_false_add( + json_area, + "nssaTranslatorElected"); + else + json_object_boolean_true_add( + json_area, + "nssaTranslatorNever"); + } + } else { + vty_out(vty, + " It is an NSSA configuration.\n Elected NSSA/ABR performs type-7/type-5 LSA translation.\n"); + if (!IS_OSPF_ABR(area->ospf)) + vty_out(vty, + " It is not ABR, therefore not Translator.\n"); + else if (area->NSSATranslatorState) { + vty_out(vty, " We are an ABR and "); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + vty_out(vty, + "the NSSA Elected Translator.\n"); + else if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_ALWAYS) + vty_out(vty, + "always an NSSA Translator.\n"); + else + vty_out(vty, + "never an NSSA Translator.\n"); + } else { + vty_out(vty, " We are an ABR, but "); + if (area->NSSATranslatorRole + == OSPF_NSSA_ROLE_CANDIDATE) + vty_out(vty, + "not the NSSA Elected Translator.\n"); + else + vty_out(vty, + "never an NSSA Translator.\n"); + } + } + } + + /* Stub-router state for this area */ + if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)) { + char timebuf[OSPF_TIME_DUMP_SIZE]; + + if (use_json) { + json_object_boolean_true_add( + json_area, "originStubMaxDistRouterLsa"); + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) + json_object_boolean_true_add( + json_area, "indefiniteActiveAdmin"); + if (area->t_stub_router) { + long time_store; + time_store = + monotime_until( + &area->t_stub_router->u.sands, + NULL) + / 1000LL; + json_object_int_add( + json_area, + "activeStartupRemainderMsecs", + time_store); + } + } else { + vty_out(vty, + " Originating stub / maximum-distance Router-LSA\n"); + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) + vty_out(vty, + " Administratively activated (indefinitely)\n"); + if (area->t_stub_router) + vty_out(vty, + " Active from startup, %s remaining\n", + ospf_timer_dump(area->t_stub_router, + timebuf, + sizeof(timebuf))); + } + } + + if (use_json) { + /* Show number of fully adjacent neighbors. */ + json_object_int_add(json_area, "nbrFullAdjacentCounter", + area->full_nbrs); + + /* Show authentication type. */ + if (area->auth_type == OSPF_AUTH_NULL) + json_object_string_add(json_area, "authentication", + "authenticationNone"); + else if (area->auth_type == OSPF_AUTH_SIMPLE) + json_object_string_add(json_area, "authentication", + "authenticationSimplePassword"); + else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + json_object_string_add(json_area, "authentication", + "authenticationMessageDigest"); + + if (!OSPF_IS_AREA_BACKBONE(area)) + json_object_int_add(json_area, + "virtualAdjacenciesPassingCounter", + area->full_vls); + + /* Show SPF calculation times. */ + json_object_int_add(json_area, "spfExecutedCounter", + area->spf_calculation); + json_object_int_add(json_area, "lsaNumber", area->lsdb->total); + json_object_int_add( + json_area, "lsaRouterNumber", + ospf_lsdb_count(area->lsdb, OSPF_ROUTER_LSA)); + json_object_int_add( + json_area, "lsaRouterChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_ROUTER_LSA)); + json_object_int_add( + json_area, "lsaNetworkNumber", + ospf_lsdb_count(area->lsdb, OSPF_NETWORK_LSA)); + json_object_int_add( + json_area, "lsaNetworkChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_NETWORK_LSA)); + json_object_int_add( + json_area, "lsaSummaryNumber", + ospf_lsdb_count(area->lsdb, OSPF_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaSummaryChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaAsbrNumber", + ospf_lsdb_count(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaAsbrChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + json_object_int_add( + json_area, "lsaNssaNumber", + ospf_lsdb_count(area->lsdb, OSPF_AS_NSSA_LSA)); + json_object_int_add( + json_area, "lsaNssaChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_AS_NSSA_LSA)); + } else { + /* Show number of fully adjacent neighbors. */ + vty_out(vty, + " Number of fully adjacent neighbors in this area: %d\n", + area->full_nbrs); + + /* Show authentication type. */ + vty_out(vty, " Area has "); + if (area->auth_type == OSPF_AUTH_NULL) + vty_out(vty, "no authentication\n"); + else if (area->auth_type == OSPF_AUTH_SIMPLE) + vty_out(vty, "simple password authentication\n"); + else if (area->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + vty_out(vty, "message digest authentication\n"); + + if (!OSPF_IS_AREA_BACKBONE(area)) + vty_out(vty, + " Number of full virtual adjacencies going through this area: %d\n", + area->full_vls); + + /* Show SPF calculation times. */ + vty_out(vty, " SPF algorithm executed %d times\n", + area->spf_calculation); + + /* Show number of LSA. */ + vty_out(vty, " Number of LSA %ld\n", area->lsdb->total); + vty_out(vty, + " Number of router LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_ROUTER_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_ROUTER_LSA)); + vty_out(vty, + " Number of network LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_NETWORK_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_NETWORK_LSA)); + vty_out(vty, + " Number of summary LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_SUMMARY_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_SUMMARY_LSA)); + vty_out(vty, + " Number of ASBR summary LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_ASBR_SUMMARY_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_ASBR_SUMMARY_LSA)); + vty_out(vty, " Number of NSSA LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_AS_NSSA_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_AS_NSSA_LSA)); + } + + if (use_json) { + json_object_int_add( + json_area, "lsaOpaqueLinkNumber", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + json_object_int_add( + json_area, "lsaOpaqueLinkChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + json_object_int_add( + json_area, "lsaOpaqueAreaNumber", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + json_object_int_add( + json_area, "lsaOpaqueAreaChecksum", + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + } else { + vty_out(vty, + " Number of opaque link LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_LINK_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_LINK_LSA)); + vty_out(vty, + " Number of opaque area LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(area->lsdb, OSPF_OPAQUE_AREA_LSA), + ospf_lsdb_checksum(area->lsdb, OSPF_OPAQUE_AREA_LSA)); + } + + if (area->fr_info.configured) { + if (use_json) + json_object_string_add(json_area, "areaFloodReduction", + "configured"); + else + vty_out(vty, " Flood Reduction is configured.\n"); + } + + if (area->fr_info.enabled) { + if (use_json) { + json_object_boolean_true_add( + json_area, "areaFloodReductionEnabled"); + if (area->fr_info.router_lsas_recv_dc_bit) + json_object_boolean_true_add( + json_area, "lsasRecvDCbitSet"); + if (area->fr_info.area_ind_lsa_recvd) + json_object_string_add(json_area, + "areaIndicationLsaRecv", + "received"); + if (area->fr_info.indication_lsa_self) + json_object_string_addf( + json_area, "areaIndicationLsa", "%pI4", + &area->fr_info.indication_lsa_self->data + ->id); + } else { + vty_out(vty, " Flood Reduction is enabled.\n"); + vty_out(vty, " No of LSAs rcv'd with DC bit set %d\n", + area->fr_info.router_lsas_recv_dc_bit); + if (area->fr_info.area_ind_lsa_recvd) + vty_out(vty, " Ind LSA by other abr.\n"); + if (area->fr_info.indication_lsa_self) + vty_out(vty, " Ind LSA generated %pI4\n", + &area->fr_info.indication_lsa_self->data + ->id); + } + } + + if (use_json) + json_object_object_add(json_areas, + inet_ntop(AF_INET, &area->area_id, + buf, sizeof(buf)), + json_area); + else + vty_out(vty, "\n"); +} + +static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf, + json_object *json, uint8_t use_vrf) +{ + struct listnode *node, *nnode; + struct ospf_area *area; + struct timeval result; + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_vrf = NULL; + json_object *json_areas = NULL; + + if (json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + json_areas = json_object_new_object(); + } + + if (ospf->instance) { + if (json) { + json_object_int_add(json, "ospfInstance", + ospf->instance); + } else { + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + /* Show Router ID. */ + if (json) { + json_object_string_addf(json_vrf, "routerId", "%pI4", + &ospf->router_id); + } else { + vty_out(vty, " OSPF Routing Process, Router ID: %pI4\n", + &ospf->router_id); + } + + /* Graceful shutdown */ + if (ospf->t_deferred_shutdown) { + if (json) { + long time_store; + time_store = + monotime_until( + &ospf->t_deferred_shutdown->u.sands, + NULL) + / 1000LL; + json_object_int_add(json_vrf, "deferredShutdownMsecs", + time_store); + } else { + vty_out(vty, + " Deferred shutdown in progress, %s remaining\n", + ospf_timer_dump(ospf->t_deferred_shutdown, + timebuf, sizeof(timebuf))); + } + } + + /* Show capability. */ + if (json) { + json_object_boolean_true_add(json_vrf, "tosRoutesOnly"); + json_object_boolean_true_add(json_vrf, "rfc2328Conform"); + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) { + json_object_boolean_true_add(json_vrf, + "rfc1583Compatibility"); + } + } else { + vty_out(vty, " Supports only single TOS (TOS0) routes\n"); + vty_out(vty, " This implementation conforms to RFC2328\n"); + vty_out(vty, " RFC1583Compatibility flag is %s\n", + CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE) + ? "enabled" + : "disabled"); + } + + if (json) { + if (CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE)) { + json_object_boolean_true_add(json_vrf, "opaqueCapable"); + } + } else { + vty_out(vty, " OpaqueCapability flag is %s\n", + CHECK_FLAG(ospf->config, OSPF_OPAQUE_CAPABLE) + ? "enabled" + : "disabled"); + } + + /* Show stub-router configuration */ + if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED + || ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) { + if (json) { + json_object_boolean_true_add(json_vrf, + "stubAdvertisement"); + if (ospf->stub_router_startup_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + json_object_int_add( + json_vrf, "postStartEnabledSecs", + ospf->stub_router_startup_time); + if (ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + json_object_int_add( + json_vrf, "preShutdownEnabledSecs", + ospf->stub_router_shutdown_time); + } else { + vty_out(vty, + " Stub router advertisement is configured\n"); + if (ospf->stub_router_startup_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, + " Enabled for %us after start-up\n", + ospf->stub_router_startup_time); + if (ospf->stub_router_shutdown_time + != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, + " Enabled for %us prior to full shutdown\n", + ospf->stub_router_shutdown_time); + } + } + + /* Show SPF timers. */ + if (json) { + json_object_int_add(json_vrf, "spfScheduleDelayMsecs", + ospf->spf_delay); + json_object_int_add(json_vrf, "holdtimeMinMsecs", + ospf->spf_holdtime); + json_object_int_add(json_vrf, "holdtimeMaxMsecs", + ospf->spf_max_holdtime); + json_object_int_add(json_vrf, "holdtimeMultplier", + ospf->spf_hold_multiplier); + } else { + vty_out(vty, + " Initial SPF scheduling delay %d millisec(s)\n" + " Minimum hold time between consecutive SPFs %d millisec(s)\n" + " Maximum hold time between consecutive SPFs %d millisec(s)\n" + " Hold time multiplier is currently %d\n", + ospf->spf_delay, ospf->spf_holdtime, + ospf->spf_max_holdtime, ospf->spf_hold_multiplier); + } + + if (json) { + if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { + long time_store = 0; + + time_store = + monotime_since(&ospf->ts_spf, NULL) / 1000LL; + json_object_int_add(json_vrf, "spfLastExecutedMsecs", + time_store); + + time_store = (1000 * ospf->ts_spf_duration.tv_sec) + + (ospf->ts_spf_duration.tv_usec / 1000); + json_object_int_add(json_vrf, "spfLastDurationMsecs", + time_store); + } else + json_object_boolean_true_add(json_vrf, "spfHasNotRun"); + } else { + vty_out(vty, " SPF algorithm "); + if (ospf->ts_spf.tv_sec || ospf->ts_spf.tv_usec) { + monotime_since(&ospf->ts_spf, &result); + vty_out(vty, "last executed %s ago\n", + ospf_timeval_dump(&result, timebuf, + sizeof(timebuf))); + vty_out(vty, " Last SPF duration %s\n", + ospf_timeval_dump(&ospf->ts_spf_duration, + timebuf, sizeof(timebuf))); + } else + vty_out(vty, "has not been run\n"); + } + + if (json) { + if (ospf->t_spf_calc) { + long time_store; + time_store = + monotime_until(&ospf->t_spf_calc->u.sands, NULL) + / 1000LL; + json_object_int_add(json_vrf, "spfTimerDueInMsecs", + time_store); + } + + json_object_int_add(json_vrf, "lsaMinIntervalMsecs", + ospf->min_ls_interval); + json_object_int_add(json_vrf, "lsaMinArrivalMsecs", + ospf->min_ls_arrival); + /* Show write multiplier values */ + json_object_int_add(json_vrf, "writeMultiplier", + ospf->write_oi_count); + /* Show refresh parameters. */ + json_object_int_add(json_vrf, "refreshTimerMsecs", + ospf->lsa_refresh_interval * 1000); + + /* show max multipath */ + json_object_int_add(json_vrf, "maximumPaths", + ospf->max_multipath); + + /* show administrative distance */ + json_object_int_add(json_vrf, "preference", + ospf->distance_all + ? ospf->distance_all + : ZEBRA_OSPF_DISTANCE_DEFAULT); + } else { + vty_out(vty, " SPF timer %s%s\n", + (ospf->t_spf_calc ? "due in " : "is "), + ospf_timer_dump(ospf->t_spf_calc, timebuf, + sizeof(timebuf))); + + vty_out(vty, " LSA minimum interval %d msecs\n", + ospf->min_ls_interval); + vty_out(vty, " LSA minimum arrival %d msecs\n", + ospf->min_ls_arrival); + + /* Show write multiplier values */ + vty_out(vty, " Write Multiplier set to %d \n", + ospf->write_oi_count); + + /* Show refresh parameters. */ + vty_out(vty, " Refresh timer %d secs\n", + ospf->lsa_refresh_interval); + + /* show max multipath */ + vty_out(vty, " Maximum multiple paths(ECMP) supported %d\n", + ospf->max_multipath); + + /* show administrative distance */ + vty_out(vty, " Administrative distance %u\n", + ospf->distance_all ? ospf->distance_all + : ZEBRA_OSPF_DISTANCE_DEFAULT); + } + + if (ospf->fr_configured) { + if (json) + json_object_string_add(json_vrf, "floodReduction", + "configured"); + else + vty_out(vty, " Flood Reduction is configured.\n"); + } + + /* Show ABR/ASBR flags. */ + if (CHECK_FLAG(ospf->flags, OSPF_FLAG_ABR)) { + if (json) + json_object_string_add( + json_vrf, "abrType", + ospf_abr_type_descr_str[ospf->abr_type]); + else + vty_out(vty, + " This router is an ABR, ABR type is: %s\n", + ospf_abr_type_descr_str[ospf->abr_type]); + } + if (CHECK_FLAG(ospf->flags, OSPF_FLAG_ASBR)) { + if (json) + json_object_string_add( + json_vrf, "asbrRouter", + "injectingExternalRoutingInformation"); + else + vty_out(vty, + " This router is an ASBR (injecting external routing information)\n"); + } + + /* Show Number of AS-external-LSAs. */ + if (json) { + json_object_int_add( + json_vrf, "lsaExternalCounter", + ospf_lsdb_count(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + json_object_int_add( + json_vrf, "lsaExternalChecksum", + ospf_lsdb_checksum(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + } else { + vty_out(vty, + " Number of external LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(ospf->lsdb, OSPF_AS_EXTERNAL_LSA), + ospf_lsdb_checksum(ospf->lsdb, OSPF_AS_EXTERNAL_LSA)); + } + + if (json) { + json_object_int_add( + json_vrf, "lsaAsopaqueCounter", + ospf_lsdb_count(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + json_object_int_add( + json_vrf, "lsaAsOpaqueChecksum", + ospf_lsdb_checksum(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + } else { + vty_out(vty, + " Number of opaque AS LSA %ld. Checksum Sum 0x%08x\n", + ospf_lsdb_count(ospf->lsdb, OSPF_OPAQUE_AS_LSA), + ospf_lsdb_checksum(ospf->lsdb, OSPF_OPAQUE_AS_LSA)); + } + + /* Show number of areas attached. */ + if (json) + json_object_int_add(json_vrf, "attachedAreaCounter", + listcount(ospf->areas)); + else + vty_out(vty, " Number of areas attached to this router: %d\n", + listcount(ospf->areas)); + + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) { + if (json) + json_object_boolean_true_add( + json_vrf, "adjacencyChangesLoggedAll"); + else + vty_out(vty, + " All adjacency changes are logged\n"); + } else { + if (json) + json_object_boolean_true_add( + json_vrf, "adjacencyChangesLogged"); + else + vty_out(vty, " Adjacency changes are logged\n"); + } + } + + /* show LDP-Sync status */ + ospf_ldp_sync_show_info(vty, ospf, json_vrf, json ? 1 : 0); + + /* Socket buffer sizes */ + if (json) { + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + json_object_int_add(json_vrf, "recvSockBufsize", + ospf->recv_sock_bufsize); + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + json_object_int_add(json_vrf, "sendSockBufsize", + ospf->send_sock_bufsize); + } else { + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + vty_out(vty, " Receive socket bufsize: %u\n", + ospf->recv_sock_bufsize); + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) + vty_out(vty, " Send socket bufsize: %u\n", + ospf->send_sock_bufsize); + } + + /* Show each area status. */ + for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) + show_ip_ospf_area(vty, area, json_areas, json ? 1 : 0); + + if (json) { + if (use_vrf) { + json_object_object_add(json_vrf, "areas", json_areas); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else { + json_object_object_add(json, "areas", json_areas); + } + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf, + show_ip_ospf_cmd, + "show ip ospf [vrf <NAME|all>] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + JSON_STR) +{ + struct ospf *ospf; + bool uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + json_object *json = NULL; + uint8_t use_vrf = 0; + + if (listcount(om->ospf) == 0) + return CMD_SUCCESS; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + bool ospf_output = false; + + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ospf_output = true; + ret = show_ip_ospf_common(vty, ospf, json, + use_vrf); + } + if (uj) + vty_json(vty, json); + else if (!ospf_output) + vty_out(vty, "%% OSPF is not enabled\n"); + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if ((ospf == NULL) || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + } else { + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + /* Display default ospf (instance 0) info */ + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + } + + if (ospf) { + show_ip_ospf_common(vty, ospf, json, use_vrf); + if (uj) + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } + + if (uj) + json_object_free(json); + + return ret; +} + +DEFUN (show_ip_ospf_instance, + show_ip_ospf_instance_cmd, + "show ip ospf (1-65535) [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + JSON_STR) +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + int ret = CMD_SUCCESS; + json_object *json = NULL; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + json = json_object_new_object(); + + ret = show_ip_ospf_common(vty, ospf, json, 0); + + if (uj) + vty_json(vty, json); + + return ret; +} + +static void ospf_interface_auth_show(struct vty *vty, struct ospf_interface *oi, + json_object *json, bool use_json) +{ + int auth_type; + + auth_type = OSPF_IF_PARAM(oi, auth_type); + + switch (auth_type) { + case OSPF_AUTH_NULL: + if (use_json) + json_object_string_add(json, "authentication", + "authenticationNone"); + else + vty_out(vty, " Authentication NULL is enabled\n"); + break; + case OSPF_AUTH_SIMPLE: { + if (use_json) + json_object_string_add(json, "authentication", + "authenticationSimplePassword"); + else + vty_out(vty, + " Simple password authentication enabled\n"); + break; + } + case OSPF_AUTH_CRYPTOGRAPHIC: { + struct crypt_key *ckey; + + if (OSPF_IF_PARAM(oi, keychain_name)) { + if (use_json) { + json_object_string_add(json, "authentication", + "authenticationKeyChain"); + json_object_string_add(json, "keychain", + OSPF_IF_PARAM(oi, keychain_name)); + } else { + vty_out(vty, + " Cryptographic authentication enabled\n"); + struct keychain *keychain = keychain_lookup(OSPF_IF_PARAM(oi, keychain_name)); + + if (keychain) { + struct key *key = key_lookup_for_send(keychain); + + if (key) { + vty_out(vty, " Sending SA: Key %u, Algorithm %s - key chain %s\n", + key->index, keychain_get_algo_name_by_id(key->hash_algo), + OSPF_IF_PARAM(oi, keychain_name)); + } + } + } + } else { + if (list_isempty(OSPF_IF_PARAM(oi, auth_crypt))) + return; + + ckey = listgetdata(listtail(OSPF_IF_PARAM(oi, auth_crypt))); + if (ckey) { + if (use_json) { + json_object_string_add(json, "authentication", + "authenticationMessageDigest"); + } else { + vty_out(vty, + " Cryptographic authentication enabled\n"); + vty_out(vty, " Algorithm:MD5\n"); + } + } + } + break; + } + default: + break; + } +} + +static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf, + struct interface *ifp, + json_object *json_interface_sub, + bool use_json) +{ + int is_up; + struct ospf_neighbor *nbr; + struct route_node *rn; + uint32_t bandwidth = ifp->bandwidth ? ifp->bandwidth : ifp->speed; + struct ospf_if_params *params; + json_object *json_ois = NULL; + json_object *json_oi = NULL; + + /* Is interface up? */ + if (use_json) { + is_up = if_is_operative(ifp); + if (is_up) + json_object_boolean_true_add(json_interface_sub, + "ifUp"); + else + json_object_boolean_false_add(json_interface_sub, + "ifDown"); + + json_object_int_add(json_interface_sub, "ifIndex", + ifp->ifindex); + json_object_int_add(json_interface_sub, "mtuBytes", ifp->mtu); + json_object_int_add(json_interface_sub, "bandwidthMbit", + bandwidth); + json_object_string_add(json_interface_sub, "ifFlags", + if_flag_dump(ifp->flags)); + } else { + vty_out(vty, "%s is %s\n", ifp->name, + ((is_up = if_is_operative(ifp)) ? "up" : "down")); + vty_out(vty, " ifindex %u, MTU %u bytes, BW %u Mbit %s\n", + ifp->ifindex, ifp->mtu, bandwidth, + if_flag_dump(ifp->flags)); + } + + /* Is interface OSPF enabled? */ + if (use_json) { + if (ospf_oi_count(ifp) == 0) { + json_object_boolean_false_add(json_interface_sub, + "ospfEnabled"); + return; + } else if (!is_up) { + json_object_boolean_false_add(json_interface_sub, + "ospfRunning"); + return; + } else + json_object_boolean_true_add(json_interface_sub, + "ospfEnabled"); + } else { + if (ospf_oi_count(ifp) == 0) { + vty_out(vty, " OSPF not enabled on this interface\n"); + return; + } else if (!is_up) { + vty_out(vty, + " OSPF is enabled, but not running on this interface\n"); + return; + } + } + + if (use_json) { + json_ois = json_object_new_object(); + json_object_object_add(json_interface_sub, "interfaceIp", + json_ois); + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi == NULL) + continue; + +#if CONFDATE > 20240601 + CPP_NOTICE( + "Use all fields following ospfEnabled from interfaceIp hierarchy") +#endif + + if (use_json) + json_oi = json_object_new_object(); + + if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) { + if (use_json) { + json_object_boolean_true_add(json_interface_sub, + "ifUnnumbered"); + json_object_boolean_true_add(json_oi, + "ifUnnumbered"); + } else + vty_out(vty, " This interface is UNNUMBERED,"); + } else { + struct in_addr dest; + const char *dstr; + + /* Show OSPF interface information. */ + if (use_json) { + json_object_string_addf( + json_interface_sub, "ipAddress", "%pI4", + &oi->address->u.prefix4); + json_object_int_add(json_interface_sub, + "ipAddressPrefixlen", + oi->address->prefixlen); + + json_object_string_addf( + json_oi, "ipAddress", "%pI4", + &oi->address->u.prefix4); + json_object_int_add(json_oi, + "ipAddressPrefixlen", + oi->address->prefixlen); + } else + vty_out(vty, " Internet Address %pFX,", + oi->address); + + /* For Vlinks, showing the peer address is + * probably more informative than the local + * interface that is being used */ + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { + dstr = "Peer"; + dest = oi->vl_data->peer_addr; + } else if (CONNECTED_PEER(oi->connected) + && oi->connected->destination) { + dstr = "Peer"; + dest = oi->connected->destination->u.prefix4; + } else { + dstr = "Broadcast"; + dest.s_addr = ipv4_broadcast_addr( + oi->connected->address->u.prefix4.s_addr, + oi->connected->address->prefixlen); + } + + if (use_json) { + json_object_string_add(json_interface_sub, + "ospfIfType", dstr); + + json_object_string_add(json_oi, "ospfIfType", + dstr); + + if (oi->type == OSPF_IFTYPE_VIRTUALLINK) { + json_object_string_addf( + json_interface_sub, "vlinkPeer", + "%pI4", &dest); + + json_object_string_addf(json_oi, + "vlinkPeer", + "%pI4", &dest); + } else { + json_object_string_addf( + json_interface_sub, + "localIfUsed", "%pI4", &dest); + + json_object_string_addf(json_oi, + "localIfUsed", + "%pI4", &dest); + } + } else + vty_out(vty, " %s %pI4,", dstr, + &dest); + } + if (use_json) { + json_object_string_add(json_interface_sub, "area", + ospf_area_desc_string(oi->area)); + + json_object_string_add(json_oi, "area", + ospf_area_desc_string(oi->area)); + + if (OSPF_IF_PARAM(oi, mtu_ignore)) { + json_object_boolean_true_add( + json_oi, "mtuMismatchDetect"); + json_object_boolean_true_add( + json_interface_sub, + "mtuMismatchDetect"); + } + + json_object_string_addf(json_interface_sub, "routerId", + "%pI4", &ospf->router_id); + json_object_string_add(json_interface_sub, + "networkType", + ospf_network_type_str[oi->type]); + json_object_int_add(json_interface_sub, "cost", + oi->output_cost); + json_object_int_add(json_interface_sub, + "transmitDelaySecs", + OSPF_IF_PARAM(oi, transmit_delay)); + json_object_string_add(json_interface_sub, "state", + lookup_msg(ospf_ism_state_msg, + oi->state, NULL)); + json_object_int_add(json_interface_sub, "priority", + PRIORITY(oi)); + + json_object_string_addf(json_oi, "routerId", "%pI4", + &ospf->router_id); + json_object_string_add(json_oi, "networkType", + ospf_network_type_str[oi->type]); + json_object_int_add(json_oi, "cost", oi->output_cost); + json_object_int_add(json_oi, "transmitDelaySecs", + OSPF_IF_PARAM(oi, transmit_delay)); + json_object_string_add(json_oi, "state", + lookup_msg(ospf_ism_state_msg, + oi->state, NULL)); + json_object_int_add(json_oi, "priority", PRIORITY(oi)); + json_object_boolean_add( + json_interface_sub, "opaqueCapable", + OSPF_IF_PARAM(oi, opaque_capable)); + } else { + vty_out(vty, " Area %s\n", + ospf_area_desc_string(oi->area)); + + vty_out(vty, " MTU mismatch detection: %s\n", + OSPF_IF_PARAM(oi, mtu_ignore) ? "disabled" + : "enabled"); + + vty_out(vty, + " Router ID %pI4, Network Type %s, Cost: %d\n", + &ospf->router_id, + ospf_network_type_str[oi->type], + oi->output_cost); + + vty_out(vty, + " Transmit Delay is %d sec, State %s, Priority %d\n", + OSPF_IF_PARAM(oi, transmit_delay), + lookup_msg(ospf_ism_state_msg, oi->state, NULL), + PRIORITY(oi)); + if (!OSPF_IF_PARAM(oi, opaque_capable)) + vty_out(vty, + " Opaque LSA capability disabled on interface\n"); + } + + /* Show DR information. */ + if (DR(oi).s_addr == INADDR_ANY) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); + if (nbr) { + if (use_json) { + json_object_string_addf( + json_interface_sub, "drId", + "%pI4", &nbr->router_id); + json_object_string_addf( + json_interface_sub, "drAddress", + "%pI4", + &nbr->address.u.prefix4); + + json_object_string_addf( + json_oi, "drId", "%pI4", + &nbr->router_id); + json_object_string_addf( + json_oi, "drAddress", "%pI4", + &nbr->address.u.prefix4); + } else { + vty_out(vty, + " Designated Router (ID) %pI4", + &nbr->router_id); + vty_out(vty, + " Interface Address %pFX\n", + &nbr->address); + } + } + nbr = NULL; + + nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi)); + if (nbr == NULL) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + if (use_json) { + json_object_string_addf( + json_interface_sub, "bdrId", + "%pI4", &nbr->router_id); + json_object_string_addf( + json_interface_sub, + "bdrAddress", "%pI4", + &nbr->address.u.prefix4); + + json_object_string_addf( + json_oi, "bdrId", "%pI4", + &nbr->router_id); + json_object_string_addf( + json_oi, "bdrAddress", "%pI4", + &nbr->address.u.prefix4); + } else { + vty_out(vty, + " Backup Designated Router (ID) %pI4,", + &nbr->router_id); + vty_out(vty, " Interface Address %pI4\n", + &nbr->address.u.prefix4); + } + } + } + + /* Next network-LSA sequence number we'll use, if we're elected + * DR */ + if (oi->params + && ntohl(oi->params->network_lsa_seqnum) + != OSPF_INITIAL_SEQUENCE_NUMBER) { + if (use_json) { + json_object_int_add( + json_interface_sub, + "networkLsaSequence", + ntohl(oi->params->network_lsa_seqnum)); + + json_object_int_add( + json_oi, "networkLsaSequence", + ntohl(oi->params->network_lsa_seqnum)); + } else { + vty_out(vty, + " Saved Network-LSA sequence number 0x%x\n", + ntohl(oi->params->network_lsa_seqnum)); + } + } + + if (use_json) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) + || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) { + json_object_boolean_true_add( + json_interface_sub, + "mcastMemberOspfAllRouters"); + + json_object_boolean_true_add( + json_oi, + "mcastMemberOspfAllRouters"); + } + if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + json_object_boolean_true_add( + json_interface_sub, + "mcastMemberOspfDesignatedRouters"); + + json_object_boolean_true_add( + json_oi, + "mcastMemberOspfDesignatedRouters"); + } + } + } else { + vty_out(vty, " Multicast group memberships:"); + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) + || OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) { + if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) + vty_out(vty, " OSPFAllRouters"); + if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) + vty_out(vty, " OSPFDesignatedRouters"); + } else + vty_out(vty, " <None>"); + vty_out(vty, "\n"); + } + + if (use_json) { + if (OSPF_IF_PARAM(oi, fast_hello) == 0) { + json_object_int_add( + json_interface_sub, "timerMsecs", + OSPF_IF_PARAM(oi, v_hello) * 1000); + + json_object_int_add(json_oi, "timerMsecs", + OSPF_IF_PARAM(oi, v_hello) * + 1000); + } else { + json_object_int_add( + json_interface_sub, "timerMsecs", + 1000 / OSPF_IF_PARAM(oi, fast_hello)); + + json_object_int_add( + json_oi, "timerMsecs", + 1000 / OSPF_IF_PARAM(oi, fast_hello)); + } + json_object_int_add(json_interface_sub, "timerDeadSecs", + OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add(json_interface_sub, "timerWaitSecs", + OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add( + json_interface_sub, "timerRetransmitSecs", + OSPF_IF_PARAM(oi, retransmit_interval)); + + json_object_int_add(json_oi, "timerDeadSecs", + OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add(json_oi, "timerWaitSecs", + OSPF_IF_PARAM(oi, v_wait)); + json_object_int_add( + json_oi, "timerRetransmitSecs", + OSPF_IF_PARAM(oi, retransmit_interval)); + } else { + vty_out(vty, " Timer intervals configured,"); + vty_out(vty, " Hello "); + if (OSPF_IF_PARAM(oi, fast_hello) == 0) + vty_out(vty, "%ds,", + OSPF_IF_PARAM(oi, v_hello)); + else + vty_out(vty, "%dms,", + 1000 / OSPF_IF_PARAM(oi, fast_hello)); + vty_out(vty, " Dead %ds, Wait %ds, Retransmit %d\n", + OSPF_IF_PARAM(oi, v_wait), + OSPF_IF_PARAM(oi, v_wait), + OSPF_IF_PARAM(oi, retransmit_interval)); + } + + if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE) { + char timebuf[OSPF_TIME_DUMP_SIZE]; + if (use_json) { + long time_store = 0; + if (oi->t_hello) + time_store = + monotime_until( + &oi->t_hello->u.sands, + NULL) + / 1000LL; + json_object_int_add(json_interface_sub, + "timerHelloInMsecs", + time_store); + json_object_int_add(json_oi, + "timerHelloInMsecs", + time_store); + } else + vty_out(vty, " Hello due in %s\n", + ospf_timer_dump(oi->t_hello, timebuf, + sizeof(timebuf))); + } else /* passive-interface is set */ + { + if (use_json) { + json_object_boolean_true_add( + json_interface_sub, + "timerPassiveIface"); + + json_object_boolean_true_add( + json_oi, "timerPassiveIface"); + } else + vty_out(vty, + " No Hellos (Passive interface)\n"); + } + + if (use_json) { + json_object_int_add(json_interface_sub, "nbrCount", + ospf_nbr_count(oi, 0)); + json_object_int_add(json_interface_sub, + "nbrAdjacentCount", + ospf_nbr_count(oi, NSM_Full)); + + json_object_int_add(json_oi, "nbrCount", + ospf_nbr_count(oi, 0)); + json_object_int_add(json_oi, "nbrAdjacentCount", + ospf_nbr_count(oi, NSM_Full)); + } else + vty_out(vty, + " Neighbor Count is %d, Adjacent neighbor count is %d\n", + ospf_nbr_count(oi, 0), + ospf_nbr_count(oi, NSM_Full)); + + params = IF_DEF_PARAMS(ifp); + if (params && + OSPF_IF_PARAM_CONFIGURED(params, v_gr_hello_delay)) { + if (use_json) { + json_object_int_add(json_interface_sub, + "grHelloDelaySecs", + params->v_gr_hello_delay); + + json_object_int_add(json_oi, "grHelloDelaySecs", + params->v_gr_hello_delay); + } else + vty_out(vty, + " Graceful Restart hello delay: %us\n", + params->v_gr_hello_delay); + } + + ospf_interface_bfd_show(vty, ifp, json_interface_sub); + + if (use_json) { + json_object_boolean_add(json_interface_sub, + "prefixSuppression", + OSPF_IF_PARAM(oi, + prefix_suppression)); + json_object_boolean_add(json_oi, "prefixSuppression", + OSPF_IF_PARAM(oi, + prefix_suppression)); + } else { + if (OSPF_IF_PARAM(oi, prefix_suppression)) + vty_out(vty, + " Suppress advertisement of interface IP prefix\n"); + } + + /* OSPF Authentication information */ + ospf_interface_auth_show(vty, oi, json_interface_sub, use_json); + + ospf_interface_auth_show(vty, oi, json_oi, use_json); + if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) { + if (use_json) { + json_object_boolean_add(json_interface_sub, + "p2mpDelayReflood", + oi->p2mp_delay_reflood); + + json_object_boolean_add(json_oi, + "p2mpDelayReflood", + oi->p2mp_delay_reflood); + } else { + vty_out(vty, + " %sDelay reflooding LSAs received on P2MP interface\n", + oi->p2mp_delay_reflood ? "" : "Don't "); + } + } + + /* Add ospf_interface object to main json blob using SIP as key + */ + if (use_json) + json_object_object_addf(json_ois, json_oi, "%pI4", + &oi->address->u.prefix4); + } +} + +static int show_ip_ospf_interface_common(struct vty *vty, struct ospf *ospf, + char *intf_name, uint8_t use_vrf, + json_object *json, bool use_json) +{ + struct interface *ifp; + struct vrf *vrf = vrf_lookup_by_id(ospf->vrf_id); + json_object *json_vrf = NULL; + json_object *json_interface_sub = NULL, *json_interface = NULL; + + if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + json_interface = json_object_new_object(); + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (intf_name == NULL) { + /* Show All Interfaces.*/ + FOR_ALL_INTERFACES (vrf, ifp) { + if (ospf_oi_count(ifp)) { + if (use_json) { + json_interface_sub = + json_object_new_object(); + } + show_ip_ospf_interface_sub(vty, ospf, ifp, + json_interface_sub, + use_json); + + if (use_json) { + json_object_object_add( + json_interface, ifp->name, + json_interface_sub); + } + } + } + if (use_json) + json_object_object_add(json_vrf, "interfaces", + json_interface); + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name(intf_name, ospf->vrf_id); + if (ifp == NULL) { + if (use_json) { + json_object_boolean_true_add(json_vrf, + "noSuchIface"); + json_object_free(json_interface); + } else + vty_out(vty, "No such interface name\n"); + } else { + if (use_json) + json_interface_sub = json_object_new_object(); + + show_ip_ospf_interface_sub( + vty, ospf, ifp, json_interface_sub, use_json); + + if (use_json) { + json_object_object_add(json_interface, + ifp->name, + json_interface_sub); + json_object_object_add(json_vrf, "interfaces", + json_interface); + } + } + } + + if (use_json) { + if (use_vrf) { + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +static void show_ip_ospf_interface_traffic_sub(struct vty *vty, + struct ospf_interface *oi, + json_object *json_interface_sub, + bool use_json) +{ + if (use_json) { + json_object_int_add(json_interface_sub, "ifIndex", + oi->ifp->ifindex); + json_object_int_add(json_interface_sub, "helloIn", + oi->hello_in); + json_object_int_add(json_interface_sub, "helloOut", + oi->hello_out); + json_object_int_add(json_interface_sub, "dbDescIn", + oi->db_desc_in); + json_object_int_add(json_interface_sub, "dbDescOut", + oi->db_desc_out); + json_object_int_add(json_interface_sub, "lsReqIn", + oi->ls_req_in); + json_object_int_add(json_interface_sub, "lsReqOut", + oi->ls_req_out); + json_object_int_add(json_interface_sub, "lsUpdIn", + oi->ls_upd_in); + json_object_int_add(json_interface_sub, "lsUpdOut", + oi->ls_upd_out); + json_object_int_add(json_interface_sub, "lsAckIn", + oi->ls_ack_in); + json_object_int_add(json_interface_sub, "lsAckOut", + oi->ls_ack_out); + json_object_int_add(json_interface_sub, "packetsQueued", + listcount(oi->obuf)); + } else { + vty_out(vty, + "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %12lu\n", + oi->ifp->name, oi->hello_in, oi->hello_out, + oi->db_desc_in, oi->db_desc_out, oi->ls_req_in, + oi->ls_req_out, oi->ls_upd_in, oi->ls_upd_out, + oi->ls_ack_in, oi->ls_ack_out, listcount(oi->obuf)); + } +} + +/* OSPFv2 Packet Counters */ +static int show_ip_ospf_interface_traffic_common( + struct vty *vty, struct ospf *ospf, char *intf_name, json_object *json, + int display_once, uint8_t use_vrf, bool use_json) +{ + struct vrf *vrf = NULL; + struct interface *ifp = NULL; + json_object *json_vrf = NULL; + json_object *json_interface_sub = NULL; + + if (!use_json && !display_once) { + vty_out(vty, "\n"); + vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n", + "Interface", " HELLO", " DB-Desc", " LS-Req", + " LS-Update", " LS-Ack", " Packets"); + vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s%-17s\n", "", + " Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx", + " Rx/Tx", " Queued"); + vty_out(vty, + "-------------------------------------------------------------------------------------------------------------\n"); + } else if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (intf_name == NULL) { + vrf = vrf_lookup_by_id(ospf->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) { + struct route_node *rn; + struct ospf_interface *oi; + + if (ospf_oi_count(ifp) == 0) + continue; + + for (rn = route_top(IF_OIFS(ifp)); rn; + rn = route_next(rn)) { + oi = rn->info; + + if (oi == NULL) + continue; + + if (use_json) { + json_interface_sub = + json_object_new_object(); + } + + show_ip_ospf_interface_traffic_sub( + vty, oi, json_interface_sub, use_json); + if (use_json) { + json_object_object_add( + json_vrf, ifp->name, + json_interface_sub); + } + } + } + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name(intf_name, ospf->vrf_id); + if (ifp != NULL) { + struct route_node *rn; + struct ospf_interface *oi; + + if (ospf_oi_count(ifp) == 0) { + vty_out(vty, + " OSPF not enabled on this interface %s\n", + ifp->name); + return CMD_SUCCESS; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; + rn = route_next(rn)) { + oi = rn->info; + + if (oi == NULL) + continue; + + if (use_json) { + json_interface_sub = + json_object_new_object(); + } + + show_ip_ospf_interface_traffic_sub( + vty, oi, json_interface_sub, use_json); + if (use_json) { + json_object_object_add( + json_vrf, ifp->name, + json_interface_sub); + } + } + } + } + + if (use_json) { + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_interface, + show_ip_ospf_interface_cmd, + "show ip ospf [vrf <NAME|all>] interface [INTERFACE] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Interface information\n" + "Interface name\n" + JSON_STR) +{ + struct ospf *ospf; + bool uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL, *intf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0, idx_intf = 0; + uint8_t use_vrf = 0; + json_object *json = NULL; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "INTERFACE", &idx_intf)) + intf_name = argv[idx_intf]->arg; + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_interface_common( + vty, ospf, intf_name, use_vrf, json, + uj); + } + + if (uj) + vty_json(vty, json); + else if (!ospf) + vty_out(vty, "%% OSPF is not enabled\n"); + + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + ret = show_ip_ospf_interface_common(vty, ospf, intf_name, + use_vrf, json, uj); + + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + ret = show_ip_ospf_interface_common(vty, ospf, intf_name, + use_vrf, json, uj); + } + + if (uj) + vty_json(vty, json); + + return ret; +} + +DEFUN (show_ip_ospf_instance_interface, + show_ip_ospf_instance_interface_cmd, + "show ip ospf (1-65535) interface [INTERFACE] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Interface information\n" + "Interface name\n" + JSON_STR) +{ + int idx_number = 3; + int idx_intf = 0; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + char *intf_name = NULL; + int ret = CMD_SUCCESS; + json_object *json = NULL; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + json = json_object_new_object(); + + if (argv_find(argv, argc, "INTERFACE", &idx_intf)) + intf_name = argv[idx_intf]->arg; + + ret = show_ip_ospf_interface_common(vty, ospf, intf_name, 0, json, uj); + + if (uj) + vty_json(vty, json); + + return ret; +} + +DEFUN (show_ip_ospf_interface_traffic, + show_ip_ospf_interface_traffic_cmd, + "show ip ospf [vrf <NAME|all>] interface traffic [INTERFACE] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Interface information\n" + "Protocol Packet counters\n" + "Interface name\n" + JSON_STR) +{ + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL, *intf_name = NULL; + bool all_vrf = false; + int inst = 0; + int idx_vrf = 0, idx_intf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + int ret = CMD_SUCCESS; + int display_once = 0; + uint8_t use_vrf = 0; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "INTERFACE", &idx_intf)) + intf_name = argv[idx_intf]->arg; + + if (uj) + json = json_object_new_object(); + + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ret = show_ip_ospf_interface_traffic_common( + vty, ospf, intf_name, json, + display_once, use_vrf, uj); + display_once = 1; + } + + if (uj) + vty_json(vty, json); + + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + + ret = show_ip_ospf_interface_traffic_common( + vty, ospf, intf_name, json, display_once, use_vrf, uj); + } else { + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + + ret = show_ip_ospf_interface_traffic_common( + vty, ospf, intf_name, json, display_once, use_vrf, uj); + } + + if (uj) + vty_json(vty, json); + + return ret; +} + + +static void show_ip_ospf_neighbour_header(struct vty *vty) +{ + vty_out(vty, "\n%-15s %-3s %-15s %-15s %-9s %-15s %-32s %5s %5s %5s\n", + "Neighbor ID", "Pri", "State", "Up Time", "Dead Time", + "Address", "Interface", "RXmtL", "RqstL", "DBsmL"); +} + +static void show_ip_ospf_neighbour_brief(struct vty *vty, + struct ospf_neighbor *nbr, + struct ospf_neighbor *prev_nbr, + json_object *json, bool use_json) +{ + char msgbuf[16]; + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_neighbor = NULL, *json_neigh_array = NULL; + struct timeval res = {.tv_sec = 0, .tv_usec = 0}; + long time_val = 0; + char uptime[OSPF_TIME_DUMP_SIZE]; + + if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) + time_val = + monotime_since(&nbr->ts_last_progress, &res) / 1000LL; + + if (use_json) { + char neigh_str[INET_ADDRSTRLEN]; + + if (prev_nbr && !IPV4_ADDR_SAME(&prev_nbr->src, &nbr->src)) { + /* Start new neigh list */ + json_neigh_array = NULL; + } + + if (nbr->state == NSM_Attempt && + nbr->router_id.s_addr == INADDR_ANY) + strlcpy(neigh_str, "neighbor", sizeof(neigh_str)); + else + inet_ntop(AF_INET, &nbr->router_id, neigh_str, + sizeof(neigh_str)); + + json_object_object_get_ex(json, neigh_str, &json_neigh_array); + + if (!json_neigh_array) { + json_neigh_array = json_object_new_array(); + json_object_object_add(json, neigh_str, + json_neigh_array); + } + + json_neighbor = json_object_new_object(); + + ospf_nbr_ism_state_message(nbr, msgbuf, sizeof(msgbuf)); + json_object_string_add(json_neighbor, "nbrState", msgbuf); + + json_object_int_add(json_neighbor, "nbrPriority", + nbr->priority); + + json_object_string_add( + json_neighbor, "converged", + lookup_msg(ospf_nsm_state_msg, nbr->state, NULL)); + json_object_string_add(json_neighbor, "role", + lookup_msg(ospf_ism_state_msg, + ospf_nbr_ism_state(nbr), + NULL)); + if (nbr->t_inactivity) { + long time_store; + + time_store = monotime_until(&nbr->t_inactivity->u.sands, + NULL) / + 1000LL; + json_object_int_add(json_neighbor, "upTimeInMsec", + time_val); + json_object_int_add(json_neighbor, + "routerDeadIntervalTimerDueMsec", + time_store); + json_object_string_add( + json_neighbor, "upTime", + ospf_timeval_dump(&res, uptime, + sizeof(uptime))); + json_object_string_add( + json_neighbor, "deadTime", + ospf_timer_dump(nbr->t_inactivity, timebuf, + sizeof(timebuf))); + } else { + json_object_string_add(json_neighbor, "deadTimeMsecs", + "inactive"); + json_object_string_add(json_neighbor, + "routerDeadIntervalTimerDueMsec", + "inactive"); + } + json_object_string_addf(json_neighbor, "ifaceAddress", "%pI4", + &nbr->src); + json_object_string_add(json_neighbor, "ifaceName", + IF_NAME(nbr->oi)); + json_object_int_add(json_neighbor, + "linkStateRetransmissionListCounter", + ospf_ls_retransmit_count(nbr)); + json_object_int_add(json_neighbor, + "linkStateRequestListCounter", + ospf_ls_request_count(nbr)); + json_object_int_add(json_neighbor, "databaseSummaryListCounter", + ospf_db_summary_count(nbr)); + + json_object_array_add(json_neigh_array, json_neighbor); + } else { + ospf_nbr_ism_state_message(nbr, msgbuf, sizeof(msgbuf)); + + if (nbr->state == NSM_Attempt && + nbr->router_id.s_addr == INADDR_ANY) + vty_out(vty, "%-15s %3d %-15s ", "-", nbr->priority, + msgbuf); + else + vty_out(vty, "%-15pI4 %3d %-15s ", &nbr->router_id, + nbr->priority, msgbuf); + + vty_out(vty, "%-15s ", + ospf_timeval_dump(&res, uptime, sizeof(uptime))); + + vty_out(vty, "%9s ", + ospf_timer_dump(nbr->t_inactivity, timebuf, + sizeof(timebuf))); + vty_out(vty, "%-15pI4 ", &nbr->src); + vty_out(vty, "%-32s %5ld %5ld %5d\n", IF_NAME(nbr->oi), + ospf_ls_retransmit_count(nbr), + ospf_ls_request_count(nbr), ospf_db_summary_count(nbr)); + } +} + +static void show_ip_ospf_neighbor_sub(struct vty *vty, + struct ospf_interface *oi, + json_object *json, bool use_json) +{ + struct route_node *rn; + struct ospf_neighbor *nbr, *prev_nbr = NULL; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + nbr = rn->info; + + if (!nbr) + continue; + + /* Do not show myself. */ + if (nbr == oi->nbr_self) + continue; + /* Down state is not shown. */ + if (nbr->state == NSM_Down) + continue; + + prev_nbr = nbr; + + show_ip_ospf_neighbour_brief(vty, nbr, prev_nbr, json, + use_json); + } +} + +static int show_ip_ospf_neighbor_common(struct vty *vty, struct ospf *ospf, + json_object *json, bool use_json, + uint8_t use_vrf) +{ + struct ospf_interface *oi; + struct listnode *node; + json_object *json_vrf = NULL; + json_object *json_nbr_sub = NULL; + + if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + json_nbr_sub = json_object_new_object(); + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + if (!use_json) + show_ip_ospf_neighbour_header(vty); + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + if (ospf_interface_neighbor_count(oi) == 0) + continue; + show_ip_ospf_neighbor_sub(vty, oi, json_nbr_sub, use_json); + } + + if (use_json) { + json_object_object_add(json_vrf, "neighbors", json_nbr_sub); + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_neighbor, + show_ip_ospf_neighbor_cmd, + "show ip ospf [vrf <NAME|all>] neighbor [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Neighbor list\n" + JSON_STR) +{ + struct ospf *ospf; + bool uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + json_object *json = NULL; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_common( + vty, ospf, json, uj, use_vrf); + } + + if (uj) + vty_json(vty, json); + else if (!ospf) + vty_out(vty, "OSPF is not enabled\n"); + + return ret; + } + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_neighbor_common(vty, ospf, json, uj, + use_vrf); + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } + } + + if (uj) + json_object_free(json); + + return ret; +} + + +DEFUN (show_ip_ospf_instance_neighbor, + show_ip_ospf_instance_neighbor_cmd, + "show ip ospf (1-65535) neighbor [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + JSON_STR) +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + int ret = CMD_SUCCESS; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + json = json_object_new_object(); + + ret = show_ip_ospf_neighbor_common(vty, ospf, json, uj, 0); + + if (uj) + vty_json(vty, json); + + return ret; +} + +static int show_ip_ospf_neighbor_all_common(struct vty *vty, struct ospf *ospf, + json_object *json, bool use_json, + uint8_t use_vrf) +{ + struct listnode *node; + struct ospf_interface *oi; + char buf[PREFIX_STRLEN]; + json_object *json_vrf = NULL; + json_object *json_neighbor_sub = NULL; + + if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + if (!use_json) + show_ip_ospf_neighbour_header(vty); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json_vrf, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct listnode *nbr_node; + struct ospf_nbr_nbma *nbr_nbma; + + show_ip_ospf_neighbor_sub(vty, oi, json_vrf, use_json); + + /* print Down neighbor status */ + for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nbr_node, nbr_nbma)) { + if (nbr_nbma->nbr == NULL + || nbr_nbma->nbr->state == NSM_Down) { + if (use_json) { + json_neighbor_sub = + json_object_new_object(); + json_object_int_add(json_neighbor_sub, + "nbrNbmaPriority", + nbr_nbma->priority); + json_object_boolean_true_add( + json_neighbor_sub, + "nbrNbmaDown"); + json_object_string_add( + json_neighbor_sub, + "nbrNbmaIfaceName", + IF_NAME(oi)); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaRetransmitCounter", 0); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaRequestCounter", 0); + json_object_int_add( + json_neighbor_sub, + "nbrNbmaDbSummaryCounter", 0); + json_object_object_add( + json_vrf, + inet_ntop(AF_INET, + &nbr_nbma->addr, buf, + sizeof(buf)), + json_neighbor_sub); + } else { + vty_out(vty, "%-15s %3d %-15s %9s ", + "-", nbr_nbma->priority, "Down", + "-"); + vty_out(vty, + "%-32pI4 %-20s %5d %5d %5d\n", + &nbr_nbma->addr, + IF_NAME(oi), 0, 0, 0); + } + } + } + } + + if (use_json) { + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_neighbor_all, + show_ip_ospf_neighbor_all_cmd, + "show ip ospf [vrf <NAME|all>] neighbor all [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Neighbor list\n" + "include down status neighbor\n" + JSON_STR) +{ + struct ospf *ospf; + bool uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + json_object *json = NULL; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_all_common( + vty, ospf, json, uj, use_vrf); + } + + if (uj) + vty_json(vty, json); + + return ret; + } + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_neighbor_all_common(vty, ospf, json, uj, + use_vrf); + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } + } + + if (uj) + json_object_free(json); + + return ret; +} + +DEFUN (show_ip_ospf_instance_neighbor_all, + show_ip_ospf_instance_neighbor_all_cmd, + "show ip ospf (1-65535) neighbor all [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "include down status neighbor\n" + JSON_STR) +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + int ret = CMD_SUCCESS; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + if (uj) + json = json_object_new_object(); + + ret = show_ip_ospf_neighbor_all_common(vty, ospf, json, uj, 0); + + if (uj) + vty_json(vty, json); + + return ret; +} + +static int show_ip_ospf_neighbor_int_common(struct vty *vty, struct ospf *ospf, + const char *ifname, bool use_json, + uint8_t use_vrf) +{ + struct interface *ifp; + struct route_node *rn; + json_object *json = NULL; + + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json, use_vrf); + + ifp = if_lookup_by_name(ifname, ospf->vrf_id); + if (!ifp) { + if (use_json) + json_object_boolean_true_add(json, "noSuchIface"); + else + vty_out(vty, "No such interface.\n"); + return CMD_WARNING; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi == NULL) + continue; + + show_ip_ospf_neighbor_sub(vty, oi, json, use_json); + } + + if (use_json) + vty_json(vty, json); + else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFPY(show_ip_ospf_instance_neighbor_int, + show_ip_ospf_instance_neighbor_int_cmd, + "show ip ospf (1-65535)$instance neighbor IFNAME$ifname [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "Interface name\n" + JSON_STR) +{ + struct ospf *ospf; + + if (!json) + show_ip_ospf_neighbour_header(vty); + + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (!json) + show_ip_ospf_neighbour_header(vty); + + return show_ip_ospf_neighbor_int_common(vty, ospf, ifname, !!json, 0); +} + +static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, + struct ospf_interface *oi, + struct ospf_nbr_nbma *nbr_nbma, + bool use_json, json_object *json) +{ + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_sub = NULL; + + if (use_json) + json_sub = json_object_new_object(); + else /* Show neighbor ID. */ + vty_out(vty, " Neighbor %s,", "-"); + + /* Show interface address. */ + if (use_json) + json_object_string_addf(json_sub, "ifaceAddress", "%pI4", + &nbr_nbma->addr); + else + vty_out(vty, " interface address %pI4\n", + &nbr_nbma->addr); + + /* Show Area ID. */ + if (use_json) { + json_object_string_add(json_sub, "areaId", + ospf_area_desc_string(oi->area)); + json_object_string_add(json_sub, "iface", IF_NAME(oi)); + } else + vty_out(vty, " In the area %s via interface %s\n", + ospf_area_desc_string(oi->area), IF_NAME(oi)); + + /* Show neighbor priority and state. */ + if (use_json) { + json_object_int_add(json_sub, "nbrPriority", + nbr_nbma->priority); + json_object_string_add(json_sub, "nbrState", "down"); + } else + vty_out(vty, " Neighbor priority is %d, State is %s,", + nbr_nbma->priority, "Down"); + + /* Show state changes. */ + if (use_json) + json_object_int_add(json_sub, "stateChangeCounter", + nbr_nbma->state_change); + else + vty_out(vty, " %d state changes\n", nbr_nbma->state_change); + + /* Show PollInterval */ + if (use_json) + json_object_int_add(json_sub, "pollInterval", nbr_nbma->v_poll); + else + vty_out(vty, " Poll interval %d\n", nbr_nbma->v_poll); + + /* Show poll-interval timer. */ + if (nbr_nbma->t_poll) { + if (use_json) { + long time_store; + time_store = monotime_until(&nbr_nbma->t_poll->u.sands, + NULL) / 1000LL; + json_object_int_add(json_sub, + "pollIntervalTimerDueMsec", + time_store); + } else + vty_out(vty, " Poll timer due in %s\n", + ospf_timer_dump(nbr_nbma->t_poll, timebuf, + sizeof(timebuf))); + } + + /* Show poll-interval timer thread. */ + if (use_json) { + if (nbr_nbma->t_poll != NULL) + json_object_string_add(json_sub, + "pollIntervalTimerThread", "on"); + } else + vty_out(vty, " Thread Poll Timer %s\n", + nbr_nbma->t_poll != NULL ? "on" : "off"); + + if (use_json) + json_object_object_add(json, "noNbrId", json_sub); +} + +static void show_ip_ospf_neighbor_detail_sub(struct vty *vty, + struct ospf_interface *oi, + struct ospf_neighbor *nbr, + struct ospf_neighbor *prev_nbr, + json_object *json, bool use_json) +{ + char timebuf[OSPF_TIME_DUMP_SIZE]; + json_object *json_neigh = NULL, *json_neigh_array = NULL; + char neigh_str[INET_ADDRSTRLEN] = {0}; + char neigh_state[16] = {0}; + struct ospf_neighbor *nbr_dr, *nbr_bdr; + + if (use_json) { + if (prev_nbr && + !IPV4_ADDR_SAME(&prev_nbr->src, &nbr->src)) { + json_neigh_array = NULL; + } + + if (nbr->state == NSM_Attempt + && nbr->router_id.s_addr == INADDR_ANY) + strlcpy(neigh_str, "noNbrId", sizeof(neigh_str)); + else + inet_ntop(AF_INET, &nbr->router_id, + neigh_str, sizeof(neigh_str)); + + json_object_object_get_ex(json, neigh_str, &json_neigh_array); + + if (!json_neigh_array) { + json_neigh_array = json_object_new_array(); + json_object_object_add(json, neigh_str, + json_neigh_array); + } + + json_neigh = json_object_new_object(); + + } else { + /* Show neighbor ID. */ + if (nbr->state == NSM_Attempt + && nbr->router_id.s_addr == INADDR_ANY) + vty_out(vty, " Neighbor %s,", "-"); + else + vty_out(vty, " Neighbor %pI4,", + &nbr->router_id); + } + + /* Show interface address. */ + if (use_json) + json_object_string_addf(json_neigh, "ifaceAddress", "%pI4", + &nbr->address.u.prefix4); + else + vty_out(vty, " interface address %pI4\n", + &nbr->address.u.prefix4); + + /* Show Area ID. */ + if (use_json) { + json_object_string_add(json_neigh, "areaId", + ospf_area_desc_string(oi->area)); + json_object_string_add(json_neigh, "ifaceName", oi->ifp->name); + if (oi->address) + json_object_string_addf(json_neigh, "localIfaceAddress", + "%pI4", + &oi->address->u.prefix4); + } else { + vty_out(vty, " In the area %s via interface %s", + ospf_area_desc_string(oi->area), oi->ifp->name); + if (oi->address) + vty_out(vty, " local interface IP %pI4\n", + &oi->address->u.prefix4); + else + vty_out(vty, "\n"); + } + + /* Show neighbor priority and state. */ + ospf_nbr_ism_state_message(nbr, neigh_state, sizeof(neigh_state)); + if (use_json) { + json_object_int_add(json_neigh, "nbrPriority", nbr->priority); + json_object_string_add(json_neigh, "nbrState", neigh_state); + json_object_string_add(json_neigh, "role", + lookup_msg(ospf_ism_state_msg, + ospf_nbr_ism_state(nbr), + NULL)); + } else { + vty_out(vty, + " Neighbor priority is %d, State is %s, Role is %s,", + nbr->priority, neigh_state, + lookup_msg(ospf_ism_state_msg, ospf_nbr_ism_state(nbr), + NULL)); + } + /* Show state changes. */ + if (use_json) + json_object_int_add(json_neigh, "stateChangeCounter", + nbr->state_change); + else + vty_out(vty, " %d state changes\n", nbr->state_change); + + if (nbr->ts_last_progress.tv_sec || nbr->ts_last_progress.tv_usec) { + struct timeval res; + long time_store; + + time_store = + monotime_since(&nbr->ts_last_progress, &res) / 1000LL; + if (use_json) { + json_object_int_add(json_neigh, "lastPrgrsvChangeMsec", + time_store); + } else { + vty_out(vty, + " Most recent state change statistics:\n"); + vty_out(vty, " Progressive change %s ago\n", + ospf_timeval_dump(&res, timebuf, + sizeof(timebuf))); + } + } + + if (nbr->ts_last_regress.tv_sec || nbr->ts_last_regress.tv_usec) { + struct timeval res; + long time_store; + + time_store = + monotime_since(&nbr->ts_last_regress, &res) / 1000LL; + if (use_json) { + json_object_int_add(json_neigh, + "lastRegressiveChangeMsec", + time_store); + if (nbr->last_regress_str) + json_object_string_add( + json_neigh, + "lastRegressiveChangeReason", + nbr->last_regress_str); + } else { + vty_out(vty, + " Regressive change %s ago, due to %s\n", + ospf_timeval_dump(&res, timebuf, + sizeof(timebuf)), + (nbr->last_regress_str ? nbr->last_regress_str + : "??")); + } + } + + /* Show Designated Router ID. */ + if (DR(oi).s_addr == INADDR_ANY) { + if (!use_json) + vty_out(vty, + " No designated router on this network\n"); + } else { + nbr_dr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi)); + if (nbr_dr) { + if (use_json) + json_object_string_addf( + json_neigh, "routerDesignatedId", + "%pI4", &nbr_dr->router_id); + else + vty_out(vty, " DR is %pI4,", + &nbr_dr->router_id); + } + } + + /* Show Backup Designated Router ID. */ + nbr_bdr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi)); + if (nbr_bdr == NULL) { + if (!use_json) + vty_out(vty, + " No backup designated router on this network\n"); + } else { + if (use_json) + json_object_string_addf(json_neigh, + "routerDesignatedBackupId", + "%pI4", &nbr_bdr->router_id); + else + vty_out(vty, " BDR is %pI4\n", &nbr_bdr->router_id); + } + + /* Show options. */ + if (use_json) { + json_object_int_add(json_neigh, "optionsCounter", nbr->options); + json_object_string_add(json_neigh, "optionsList", + ospf_options_dump(nbr->options)); + } else + vty_out(vty, " Options %d %s\n", nbr->options, + ospf_options_dump(nbr->options)); + + /* Show Router Dead interval timer. */ + if (use_json) { + if (nbr->t_inactivity) { + long time_store; + time_store = monotime_until(&nbr->t_inactivity->u.sands, + NULL) + / 1000LL; + json_object_int_add(json_neigh, + "routerDeadIntervalTimerDueMsec", + time_store); + } else + json_object_int_add( + json_neigh, + "routerDeadIntervalTimerDueMsec", -1); + } else + vty_out(vty, " Dead timer due in %s\n", + ospf_timer_dump(nbr->t_inactivity, timebuf, + sizeof(timebuf))); + + /* Show Database Summary list. */ + if (use_json) + json_object_int_add(json_neigh, "databaseSummaryListCounter", + ospf_db_summary_count(nbr)); + else + vty_out(vty, " Database Summary List %d\n", + ospf_db_summary_count(nbr)); + + /* Show Link State Request list. */ + if (use_json) + json_object_int_add(json_neigh, "linkStateRequestListCounter", + ospf_ls_request_count(nbr)); + else + vty_out(vty, " Link State Request List %ld\n", + ospf_ls_request_count(nbr)); + + /* Show Link State Retransmission list. */ + if (use_json) + json_object_int_add(json_neigh, + "linkStateRetransmissionListCounter", + ospf_ls_retransmit_count(nbr)); + else + vty_out(vty, " Link State Retransmission List %ld\n", + ospf_ls_retransmit_count(nbr)); + + /* Show inactivity timer thread. */ + if (use_json) { + if (nbr->t_inactivity != NULL) + json_object_string_add(json_neigh, + "threadInactivityTimer", "on"); + } else + vty_out(vty, " Thread Inactivity Timer %s\n", + nbr->t_inactivity != NULL ? "on" : "off"); + + /* Show Database Description retransmission thread. */ + if (use_json) { + if (nbr->t_db_desc != NULL) + json_object_string_add( + json_neigh, + "threadDatabaseDescriptionRetransmission", + "on"); + } else + vty_out(vty, + " Thread Database Description Retransmision %s\n", + nbr->t_db_desc != NULL ? "on" : "off"); + + /* Show Link State Request Retransmission thread. */ + if (use_json) { + if (nbr->t_ls_req != NULL) + json_object_string_add( + json_neigh, + "threadLinkStateRequestRetransmission", "on"); + } else + vty_out(vty, + " Thread Link State Request Retransmission %s\n", + nbr->t_ls_req != NULL ? "on" : "off"); + + /* Show Link State Update Retransmission thread. */ + if (use_json) { + if (nbr->t_ls_upd != NULL) + json_object_string_add( + json_neigh, + "threadLinkStateUpdateRetransmission", + "on"); + } else + vty_out(vty, + " Thread Link State Update Retransmission %s\n\n", + nbr->t_ls_upd != NULL ? "on" : "off"); + + if (!use_json) { + vty_out(vty, " Graceful restart Helper info:\n"); + + if (OSPF_GR_IS_ACTIVE_HELPER(nbr)) { + vty_out(vty, + " Graceful Restart HELPER Status : Inprogress.\n"); + + vty_out(vty, + " Graceful Restart grace period time: %d (seconds).\n", + nbr->gr_helper_info.recvd_grace_period); + vty_out(vty, " Graceful Restart reason: %s.\n", + ospf_restart_reason2str( + nbr->gr_helper_info.gr_restart_reason)); + } else { + vty_out(vty, + " Graceful Restart HELPER Status : None\n"); + } + + if (nbr->gr_helper_info.rejected_reason + != OSPF_HELPER_REJECTED_NONE) + vty_out(vty, " Helper rejected reason: %s.\n", + ospf_rejected_reason2str( + nbr->gr_helper_info.rejected_reason)); + + if (nbr->gr_helper_info.helper_exit_reason + != OSPF_GR_HELPER_EXIT_NONE) + vty_out(vty, " Last helper exit reason: %s.\n\n", + ospf_exit_reason2str( + nbr->gr_helper_info.helper_exit_reason)); + else + vty_out(vty, "\n"); + } else { + json_object_string_add(json_neigh, "grHelperStatus", + OSPF_GR_IS_ACTIVE_HELPER(nbr) ? + "Inprogress" + : "None"); + if (OSPF_GR_IS_ACTIVE_HELPER(nbr)) { + json_object_int_add( + json_neigh, "graceInterval", + nbr->gr_helper_info.recvd_grace_period); + json_object_string_add( + json_neigh, "grRestartReason", + ospf_restart_reason2str( + nbr->gr_helper_info.gr_restart_reason)); + } + + if (nbr->gr_helper_info.rejected_reason + != OSPF_HELPER_REJECTED_NONE) + json_object_string_add( + json_neigh, "helperRejectReason", + ospf_rejected_reason2str( + nbr->gr_helper_info.rejected_reason)); + + if (nbr->gr_helper_info.helper_exit_reason + != OSPF_GR_HELPER_EXIT_NONE) + json_object_string_add( + json_neigh, "helperExitReason", + ospf_exit_reason2str( + nbr->gr_helper_info + .helper_exit_reason)); + } + + bfd_sess_show(vty, json_neigh, nbr->bfd_session); + + if (use_json) + json_object_array_add(json_neigh_array, json_neigh); + +} + +static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf, + struct in_addr *router_id, + bool use_json, uint8_t use_vrf, + bool is_detail, + json_object *json_vrf) +{ + struct listnode *node; + struct ospf_neighbor *nbr; + struct ospf_interface *oi; + json_object *json = NULL; + + if (use_json) + json = json_object_new_object(); + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json, use_vrf); + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id); + + if (!nbr) + continue; + + if (is_detail) + show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL, + json, use_json); + else + show_ip_ospf_neighbour_brief(vty, nbr, NULL, json, + use_json); + } + + if (json_vrf && use_json) { + json_object_object_add( + json_vrf, + (ospf->vrf_id == VRF_DEFAULT) ? "default" : ospf->name, + json); + return CMD_SUCCESS; + } + + if (use_json) + vty_json(vty, json); + else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFPY(show_ip_ospf_neighbor_id, + show_ip_ospf_neighbor_id_cmd, + "show ip ospf [vrf NAME$vrf_name] neighbor A.B.C.D$router_id [detail$detail] [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "Neighbor list\n" + "Neighbor ID\n" + "Detailed output\n" + JSON_STR) +{ + struct ospf *ospf; + struct listnode *node; + int ret = CMD_SUCCESS; + int inst = 0; + + if (vrf_name && !strmatch(vrf_name, "all")) { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (!json) + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + else + vty_json_empty(vty); + return CMD_SUCCESS; + } + ret = show_ip_ospf_neighbor_id_common( + vty, ospf, &router_id, !!json, 0, !!detail, NULL); + } else { + json_object *json_vrf = NULL; + + if (json) + json_vrf = json_object_new_object(); + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_id_common( + vty, ospf, &router_id, !!json, 0, !!detail, + json_vrf); + } + if (json) + vty_json(vty, json_vrf); + } + + return ret; +} + +DEFPY(show_ip_ospf_instance_neighbor_id, show_ip_ospf_instance_neighbor_id_cmd, + "show ip ospf (1-65535)$instance neighbor A.B.C.D$router_id [detail$detail] [json$json]", + SHOW_STR IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "Neighbor ID\n" + "Detailed output\n" JSON_STR) +{ + struct ospf *ospf; + + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + return show_ip_ospf_neighbor_id_common(vty, ospf, &router_id, !!json, 0, + !!detail, NULL); +} + +static int show_ip_ospf_neighbor_detail_common(struct vty *vty, + struct ospf *ospf, + json_object *json, bool use_json, + uint8_t use_vrf) +{ + struct ospf_interface *oi; + struct listnode *node; + json_object *json_vrf = NULL; + json_object *json_nbr_sub = NULL; + + if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + + json_nbr_sub = json_object_new_object(); + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr, *prev_nbr = NULL; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + nbr = rn->info; + + if (!nbr) + continue; + + if (nbr != oi->nbr_self) { + if (nbr->state != NSM_Down) { + show_ip_ospf_neighbor_detail_sub( + vty, oi, nbr, prev_nbr, + json_nbr_sub, use_json); + } + } + prev_nbr = nbr; + } + } + + if (use_json) { + json_object_object_add(json_vrf, "neighbors", + json_nbr_sub); + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFPY(show_ip_ospf_neighbor_detail, + show_ip_ospf_neighbor_detail_cmd, + "show ip ospf [vrf <NAME|all>$vrf_name] neighbor detail [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Neighbor list\n" + "detail of all neighbors\n" + JSON_STR) +{ + struct ospf *ospf; + struct listnode *node = NULL; + int ret = CMD_SUCCESS; + int inst = 0; + uint8_t use_vrf = 0; + json_object *json_vrf = NULL; + + if (json) + json_vrf = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + use_vrf = 1; + if (strmatch(vrf_name, "all")) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_detail_common( + vty, ospf, json_vrf, !!json, use_vrf); + } + if (json) + vty_json(vty, json_vrf); + + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (json) + vty_json(vty, json_vrf); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + return CMD_SUCCESS; + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (json) + vty_json(vty, json_vrf); + else + vty_out(vty, "%% OSPF is not enabled\n"); + return CMD_SUCCESS; + } + } + + if (ospf) + ret = show_ip_ospf_neighbor_detail_common(vty, ospf, json_vrf, + !!json, use_vrf); + + if (json) + vty_json(vty, json_vrf); + + return ret; +} + +DEFUN (show_ip_ospf_instance_neighbor_detail, + show_ip_ospf_instance_neighbor_detail_cmd, + "show ip ospf (1-65535) neighbor detail [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "detail of all neighbors\n" + JSON_STR) +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + int ret = CMD_SUCCESS; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + json = json_object_new_object(); + + ret = show_ip_ospf_neighbor_detail_common(vty, ospf, json, uj, 0); + + if (uj) + vty_json(vty, json); + + return ret; +} + +static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty, + struct ospf *ospf, + json_object *json, + bool use_json, + uint8_t use_vrf) +{ + struct listnode *node; + struct ospf_interface *oi; + json_object *json_vrf = NULL; + + if (use_json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr, *prev_nbr = NULL; + struct ospf_nbr_nbma *nbr_nbma; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + nbr = rn->info; + + if (!nbr) + continue; + + if (nbr != oi->nbr_self) + if (nbr->state != NSM_Down) + show_ip_ospf_neighbor_detail_sub( + vty, oi, rn->info, prev_nbr, + json_vrf, use_json); + prev_nbr = nbr; + } + + if (oi->type != OSPF_IFTYPE_NBMA) + continue; + + struct listnode *nd; + + for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) { + if (nbr_nbma->nbr == NULL || + nbr_nbma->nbr->state == NSM_Down) + show_ip_ospf_nbr_nbma_detail_sub( + vty, oi, nbr_nbma, use_json, json_vrf); + } + } + + if (use_json) { + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_neighbor_detail_all, + show_ip_ospf_neighbor_detail_all_cmd, + "show ip ospf [vrf <NAME|all>] neighbor detail all [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Neighbor list\n" + "detail of all neighbors\n" + "include down status neighbor\n" + JSON_STR) +{ + struct ospf *ospf; + bool uj = use_json(argc, argv); + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + json_object *json = NULL; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = show_ip_ospf_neighbor_detail_all_common( + vty, ospf, json, uj, use_vrf); + } + + if (uj) + vty_json(vty, json); + + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + json_object_free(json); + return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_neighbor_detail_all_common(vty, ospf, json, + uj, use_vrf); + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + } + } + + if (uj) + json_object_free(json); + + return ret; +} + +DEFUN (show_ip_ospf_instance_neighbor_detail_all, + show_ip_ospf_instance_neighbor_detail_all_cmd, + "show ip ospf (1-65535) neighbor detail all [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "detail of all neighbors\n" + "include down status neighbor\n" + JSON_STR) +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + int ret = CMD_SUCCESS; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + if (uj) + json = json_object_new_object(); + + ret = show_ip_ospf_neighbor_detail_all_common(vty, ospf, json, uj, 0); + + if (uj) + vty_json(vty, json); + + return ret; +} + +static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty, + struct ospf *ospf, + const char *ifname, + bool use_json, + json_object *json_vrf) +{ + struct ospf_interface *oi; + struct interface *ifp; + struct route_node *rn, *nrn; + struct ospf_neighbor *nbr; + json_object *json = NULL; + + if (use_json) { + json = json_object_new_object(); + if (json_vrf) + json_object_object_add(json_vrf, + (ospf->vrf_id == VRF_DEFAULT) + ? "default" + : ospf->name, + json); + } + + if (ospf->instance) { + if (use_json) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ifp = if_lookup_by_name(ifname, ospf->vrf_id); + if (!ifp) { + if (!use_json) { + vty_out(vty, "No such interface.\n"); + } else { + if (!json_vrf) + vty_json(vty, json); + } + return CMD_WARNING; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + oi = rn->info; + + if (!oi) + continue; + + for (nrn = route_top(oi->nbrs); nrn; nrn = route_next(nrn)) { + nbr = nrn->info; + + if (!nbr) + continue; + + if (nbr == oi->nbr_self) + continue; + + if (nbr->state == NSM_Down) + continue; + + show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL, + json, use_json); + } + } + + if (use_json) { + if (!json_vrf) + vty_json(vty, json); + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + +DEFPY(show_ip_ospf_neighbor_int, + show_ip_ospf_neighbor_int_cmd, + "show ip ospf [vrf NAME$vrf_name] neighbor IFNAME$ifname [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "Neighbor list\n" + "Interface name\n" + JSON_STR) +{ + struct ospf *ospf; + int ret = CMD_SUCCESS; + struct interface *ifp = NULL; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf = NULL; + + if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + vrf_id = vrf->vrf_id; + } + ospf = ospf_lookup_by_vrf_id(vrf_id); + + if (!ospf || !ospf->oi_running) { + if (json) + vty_json_empty(vty); + return ret; + } + + if (!json) + show_ip_ospf_neighbour_header(vty); + + ifp = if_lookup_by_name(ifname, vrf_id); + if (!ifp) { + if (json) + vty_json_empty(vty); + else + vty_out(vty, "No such interface.\n"); + return ret; + } + + ret = show_ip_ospf_neighbor_int_common(vty, ospf, ifname, !!json, 0); + return ret; +} + +DEFPY(show_ip_ospf_neighbor_int_detail, + show_ip_ospf_neighbor_int_detail_cmd, + "show ip ospf [vrf NAME$vrf_name] neighbor IFNAME$ifname detail [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "Neighbor list\n" + "Interface name\n" + "detail of all neighbors\n" + JSON_STR) +{ + struct ospf *ospf; + struct listnode *node = NULL; + int ret = CMD_SUCCESS; + bool ospf_output = false; + + if (vrf_name && !strmatch(vrf_name, "all")) { + int inst = 0; + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (!json) + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + else + vty_json_empty(vty); + return CMD_SUCCESS; + } + return show_ip_ospf_neighbor_int_detail_common( + vty, ospf, ifname, !!json, NULL); + } + + json_object *json_vrf = NULL; + + if (json) + json_vrf = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ospf_output = true; + ret = show_ip_ospf_neighbor_int_detail_common(vty, ospf, ifname, + !!json, json_vrf); + } + + if (json) { + vty_json(vty, json_vrf); + return ret; + } + + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); + + return ret; +} + +DEFPY(show_ip_ospf_instance_neighbor_int_detail, + show_ip_ospf_instance_neighbor_int_detail_cmd, + "show ip ospf (1-65535)$instance neighbor IFNAME$ifname detail [json$json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Neighbor list\n" + "Interface name\n" + "detail of all neighbors\n" + JSON_STR) +{ + struct ospf *ospf; + + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + return show_ip_ospf_neighbor_int_detail_common(vty, ospf, ifname, + !!json, NULL); +} + +/* Show functions */ +static int show_lsa_summary(struct vty *vty, struct ospf_lsa *lsa, int self, + json_object *json_lsa) +{ + struct router_lsa *rl; + struct summary_lsa *sl; + struct as_external_lsa *asel; + struct prefix_ipv4 p; + + if (lsa == NULL) + return 0; + + /* If self option is set, check LSA self flag. */ + if (self == 0 || IS_LSA_SELF(lsa)) { + + if (!json_lsa) { + /* LSA common part show. */ + vty_out(vty, "%-15pI4", &lsa->data->id); + vty_out(vty, "%-15pI4 %4d 0x%08lx 0x%04x", + &lsa->data->adv_router, LS_AGE(lsa), + (unsigned long)ntohl(lsa->data->ls_seqnum), + ntohs(lsa->data->checksum)); + } else { + char seqnum[10]; + char checksum[10]; + + snprintf(seqnum, sizeof(seqnum), "%x", + ntohl(lsa->data->ls_seqnum)); + snprintf(checksum, sizeof(checksum), "%x", + ntohs(lsa->data->checksum)); + json_object_string_addf(json_lsa, "lsId", "%pI4", + &lsa->data->id); + json_object_string_addf(json_lsa, "advertisedRouter", + "%pI4", &lsa->data->adv_router); + json_object_int_add(json_lsa, "lsaAge", LS_AGE(lsa)); + json_object_string_add(json_lsa, "sequenceNumber", + seqnum); + json_object_string_add(json_lsa, "checksum", checksum); + } + + /* LSA specific part show. */ + switch (lsa->data->type) { + case OSPF_ROUTER_LSA: + rl = (struct router_lsa *)lsa->data; + + if (!json_lsa) + vty_out(vty, " %-d", ntohs(rl->links)); + else + json_object_int_add(json_lsa, + "numOfRouterLinks", + ntohs(rl->links)); + break; + case OSPF_SUMMARY_LSA: + sl = (struct summary_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = sl->header.id; + p.prefixlen = ip_masklen(sl->mask); + apply_mask_ipv4(&p); + + if (!json_lsa) + vty_out(vty, " %pFX", &p); + else { + json_object_string_addf( + json_lsa, "summaryAddress", "%pFX", &p); + } + break; + case OSPF_AS_EXTERNAL_LSA: + case OSPF_AS_NSSA_LSA: + asel = (struct as_external_lsa *)lsa->data; + + p.family = AF_INET; + p.prefix = asel->header.id; + p.prefixlen = ip_masklen(asel->mask); + apply_mask_ipv4(&p); + + if (!json_lsa) + vty_out(vty, " %s %pFX [0x%lx]", + IS_EXTERNAL_METRIC(asel->e[0].tos) + ? "E2" + : "E1", + &p, + (unsigned long)ntohl( + asel->e[0].route_tag)); + else { + json_object_string_add( + json_lsa, "metricType", + IS_EXTERNAL_METRIC(asel->e[0].tos) + ? "E2" + : "E1"); + json_object_string_addf(json_lsa, "route", + "%pFX", &p); + json_object_int_add( + json_lsa, "tag", + (unsigned long)ntohl( + asel->e[0].route_tag)); + } + break; + case OSPF_NETWORK_LSA: + case OSPF_ASBR_SUMMARY_LSA: + case OSPF_OPAQUE_LINK_LSA: + case OSPF_OPAQUE_AREA_LSA: + case OSPF_OPAQUE_AS_LSA: + default: + break; + } + + if (!json_lsa) + vty_out(vty, "\n"); + } + + return 1; +} + +static const char *const show_database_desc[] = { + "unknown", + "Router Link States", + "Net Link States", + "Summary Link States", + "ASBR-Summary Link States", + "AS External Link States", + "Group Membership LSA", + "NSSA-external Link States", + "Type-8 LSA", + "Link-Local Opaque-LSA", + "Area-Local Opaque-LSA", + "AS-external Opaque-LSA", +}; + +static const char * const show_database_desc_json[] = { + "unknown", + "routerLinkStates", + "networkLinkStates", + "summaryLinkStates", + "asbrSummaryLinkStates", + "asExternalLinkStates", + "groupMembershipLsa", + "nssaExternalLinkStates", + "type8Lsa", + "linkLocalOpaqueLsa", + "areaLocalOpaqueLsa", + "asExternalOpaqueLsa", +}; + +static const char *const show_database_desc_count_json[] = { + "unknownCount", + "routerLinkStatesCount", + "networkLinkStatesCount", + "summaryLinkStatesCount", + "asbrSummaryLinkStatesCount", + "asExternalLinkStatesCount", + "groupMembershipLsaCount", + "nssaExternalLinkStatesCount", + "type8LsaCount", + "linkLocalOpaqueLsaCount", + "areaLocalOpaqueLsaCount", + "asExternalOpaqueLsaCount", +}; + +static const char *const show_database_header[] = { + "", + "Link ID ADV Router Age Seq# CkSum Link count", + "Link ID ADV Router Age Seq# CkSum", + "Link ID ADV Router Age Seq# CkSum Route", + "Link ID ADV Router Age Seq# CkSum", + "Link ID ADV Router Age Seq# CkSum Route", + " --- header for Group Member ----", + "Link ID ADV Router Age Seq# CkSum Route", + " --- type-8 ---", + "Opaque-Type/Id ADV Router Age Seq# CkSum", + "Opaque-Type/Id ADV Router Age Seq# CkSum", + "Opaque-Type/Id ADV Router Age Seq# CkSum", +}; + +static void show_ip_ospf_database_header(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + struct router_lsa *rlsa = (struct router_lsa *)lsa->data; + + if (!json) { + if (IS_LSA_SELF(lsa)) + vty_out(vty, " LS age: %d%s\n", LS_AGE(lsa), + CHECK_FLAG(lsa->data->ls_age, DO_NOT_AGE) + ? "(S-DNA)" + : ""); + else + vty_out(vty, " LS age: %d%s\n", LS_AGE(lsa), + CHECK_FLAG(lsa->data->ls_age, DO_NOT_AGE) + ? "(DNA)" + : ""); + vty_out(vty, " Options: 0x%-2x : %s\n", lsa->data->options, + ospf_options_dump(lsa->data->options)); + vty_out(vty, " LS Flags: 0x%-2x %s\n", lsa->flags, + ((lsa->flags & OSPF_LSA_LOCAL_XLT) + ? "(Translated from Type-7)" + : "")); + + if (lsa->data->type == OSPF_ROUTER_LSA) { + vty_out(vty, " Flags: 0x%x", rlsa->flags); + + if (rlsa->flags) + vty_out(vty, " :%s%s%s%s", + IS_ROUTER_LSA_BORDER(rlsa) ? " ABR" + : "", + IS_ROUTER_LSA_EXTERNAL(rlsa) ? " ASBR" + : "", + IS_ROUTER_LSA_VIRTUAL(rlsa) + ? " VL-endpoint" + : "", + IS_ROUTER_LSA_SHORTCUT(rlsa) + ? " Shortcut" + : ""); + + vty_out(vty, "\n"); + } + vty_out(vty, " LS Type: %s\n", + lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); + vty_out(vty, " Link State ID: %pI4 %s\n", + &lsa->data->id, + lookup_msg(ospf_link_state_id_type_msg, lsa->data->type, + NULL)); + vty_out(vty, " Advertising Router: %pI4\n", + &lsa->data->adv_router); + vty_out(vty, " LS Seq Number: %08lx\n", + (unsigned long)ntohl(lsa->data->ls_seqnum)); + vty_out(vty, " Checksum: 0x%04x\n", + ntohs(lsa->data->checksum)); + vty_out(vty, " Length: %d\n\n", ntohs(lsa->data->length)); + } else { + char seqnum[10]; + char checksum[10]; + + snprintf(seqnum, 10, "%x", ntohl(lsa->data->ls_seqnum)); + snprintf(checksum, 10, "%x", ntohs(lsa->data->checksum)); + + json_object_int_add(json, "lsaAge", LS_AGE(lsa)); + json_object_string_add(json, "options", + ospf_options_dump(lsa->data->options)); + json_object_int_add(json, "lsaFlags", lsa->flags); + + if (lsa->flags & OSPF_LSA_LOCAL_XLT) + json_object_boolean_true_add(json, + "translatedFromType7"); + + if (lsa->data->type == OSPF_ROUTER_LSA) { + json_object_int_add(json, "flags", rlsa->flags); + + if (rlsa->flags) { + if (IS_ROUTER_LSA_BORDER(rlsa)) + json_object_boolean_true_add(json, + "abr"); + if (IS_ROUTER_LSA_EXTERNAL(rlsa)) + json_object_boolean_true_add(json, + "asbr"); + if (IS_ROUTER_LSA_VIRTUAL(rlsa)) + json_object_boolean_true_add( + json, "vlEndpoint"); + if (IS_ROUTER_LSA_SHORTCUT(rlsa)) + json_object_boolean_true_add( + json, "shortcut"); + } + } + + json_object_string_add( + json, "lsaType", + lookup_msg(ospf_lsa_type_msg, lsa->data->type, NULL)); + json_object_string_addf(json, "linkStateId", "%pI4", + &lsa->data->id); + json_object_string_addf(json, "advertisingRouter", "%pI4", + &lsa->data->adv_router); + json_object_string_add(json, "lsaSeqNumber", seqnum); + json_object_string_add(json, "checksum", checksum); + json_object_int_add(json, "length", ntohs(lsa->data->length)); + } +} + +static const char *const link_type_desc[] = { + "(null)", + "another Router (point-to-point)", + "a Transit Network", + "Stub Network", + "a Virtual Link", +}; + +static const char *const link_id_desc[] = { + "(null)", "Neighboring Router ID", "Designated Router address", + "Net", "Neighboring Router ID", +}; + +static const char *const link_data_desc[] = { + "(null)", "Router Interface address", "Router Interface address", + "Network Mask", "Router Interface address", +}; + +static const char *const link_id_desc_json[] = { + "null", "neighborRouterId", "designatedRouterAddress", + "networkAddress", "neighborRouterId", +}; + +static const char *const link_data_desc_json[] = { + "null", "routerInterfaceAddress", "routerInterfaceAddress", + "networkMask", "routerInterfaceAddress", +}; + +/* Show router-LSA each Link information. */ +static void show_ip_ospf_database_router_links(struct vty *vty, + struct router_lsa *rl, + json_object *json) +{ + int len, type; + unsigned short i; + json_object *json_links = NULL; + json_object *json_link = NULL; + int metric = 0; + char buf[PREFIX_STRLEN]; + + if (json) + json_links = json_object_new_object(); + + len = ntohs(rl->header.length) - 4; + for (i = 0; i < ntohs(rl->links) && len > 0; len -= 12, i++) { + type = rl->link[i].type; + + if (json) { + char link[16]; + + snprintf(link, sizeof(link), "link%u", i); + json_link = json_object_new_object(); + json_object_string_add(json_link, "linkType", + link_type_desc[type]); + json_object_string_add(json_link, + link_id_desc_json[type], + inet_ntop(AF_INET, + &rl->link[i].link_id, + buf, sizeof(buf))); + json_object_string_add( + json_link, link_data_desc_json[type], + inet_ntop(AF_INET, &rl->link[i].link_data, + buf, sizeof(buf))); + json_object_int_add(json_link, "numOfTosMetrics", + metric); + json_object_int_add(json_link, "tos0Metric", + ntohs(rl->link[i].metric)); + json_object_object_add(json_links, link, json_link); + } else { + vty_out(vty, " Link connected to: %s\n", + link_type_desc[type]); + vty_out(vty, " (Link ID) %s: %pI4\n", + link_id_desc[type], + &rl->link[i].link_id); + vty_out(vty, " (Link Data) %s: %pI4\n", + link_data_desc[type], + &rl->link[i].link_data); + vty_out(vty, " Number of TOS metrics: 0\n"); + vty_out(vty, " TOS 0 Metric: %d\n", + ntohs(rl->link[i].metric)); + vty_out(vty, "\n"); + } + } + if (json) + json_object_object_add(json, "routerLinks", json_links); +} + +/* Show router-LSA detail information. */ +static int show_router_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + if (lsa != NULL) { + struct router_lsa *rl = (struct router_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) + vty_out(vty, " Number of Links: %d\n\n", + ntohs(rl->links)); + else + json_object_int_add(json, "numOfLinks", + ntohs(rl->links)); + + show_ip_ospf_database_router_links(vty, rl, json); + + if (!json) + vty_out(vty, "\n"); + } + + return 0; +} + +/* Show network-LSA detail information. */ +static int show_network_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + int length, i; + char buf[PREFIX_STRLEN]; + json_object *json_attached_rt = NULL; + json_object *json_router = NULL; + + if (json) + json_attached_rt = json_object_new_object(); + + if (lsa != NULL) { + struct network_lsa *nl = (struct network_lsa *)lsa->data; + struct in_addr *addr; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(nl->mask)); + else + json_object_int_add(json, "networkMask", + ip_masklen(nl->mask)); + + length = lsa->size - OSPF_LSA_HEADER_SIZE - 4; + addr = &nl->routers[0]; + for (i = 0; length > 0 && addr; + length -= 4, addr = &nl->routers[++i]) + if (!json) { + vty_out(vty, " Attached Router: %pI4\n", + addr); + vty_out(vty, "\n"); + } else { + json_router = json_object_new_object(); + json_object_string_add( + json_router, "attachedRouterId", + inet_ntop(AF_INET, addr, buf, + sizeof(buf))); + json_object_object_add(json_attached_rt, + inet_ntop(AF_INET, addr, + buf, + sizeof(buf)), + json_router); + } + } + + if (json) + json_object_object_add(json, "attchedRouters", + json_attached_rt); + + return 0; +} + +/* Show summary-LSA detail information. */ +static int show_summary_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + if (lsa != NULL) { + struct summary_lsa *sl = (struct summary_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(sl->mask)); + json_object_int_add(json, "tos0Metric", + GET_METRIC(sl->metric)); + } + } + + return 0; +} + +/* Show summary-ASBR-LSA detail information. */ +static int show_summary_asbr_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + if (lsa != NULL) { + struct summary_lsa *sl = (struct summary_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(sl->mask)); + vty_out(vty, " TOS: 0 Metric: %d\n", + GET_METRIC(sl->metric)); + vty_out(vty, "\n"); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(sl->mask)); + json_object_int_add(json, "tos0Metric", + GET_METRIC(sl->metric)); + } + } + + return 0; +} + +/* Show AS-external-LSA detail information. */ +static int show_as_external_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + int tos = 0; + + if (lsa != NULL) { + struct as_external_lsa *al = + (struct as_external_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " Forward Address: %pI4\n", + &al->e[0].fwd_addr); + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(al->mask)); + json_object_string_add( + json, "metricType", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "E2 (Larger than any link state path)" + : "E1"); + json_object_int_add(json, "tos", tos); + json_object_int_add(json, "metric", + GET_METRIC(al->e[0].metric)); + json_object_string_addf(json, "forwardAddress", "%pI4", + &(al->e[0].fwd_addr)); + json_object_int_add( + json, "externalRouteTag", + (route_tag_t)ntohl(al->e[0].route_tag)); + } + } + + return 0; +} + +/* Show AS-NSSA-LSA detail information. */ +static int show_as_nssa_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + int tos = 0; + + if (lsa != NULL) { + struct as_external_lsa *al = + (struct as_external_lsa *)lsa->data; + + show_ip_ospf_database_header(vty, lsa, json); + + if (!json) { + vty_out(vty, " Network Mask: /%d\n", + ip_masklen(al->mask)); + vty_out(vty, " Metric Type: %s\n", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "2 (Larger than any link state path)" + : "1"); + vty_out(vty, " TOS: 0\n"); + vty_out(vty, " Metric: %d\n", + GET_METRIC(al->e[0].metric)); + vty_out(vty, " NSSA: Forward Address: %pI4\n", + &al->e[0].fwd_addr); + vty_out(vty, + " External Route Tag: %" ROUTE_TAG_PRI + "\n\n", + (route_tag_t)ntohl(al->e[0].route_tag)); + } else { + json_object_int_add(json, "networkMask", + ip_masklen(al->mask)); + json_object_string_add( + json, "metricType", + IS_EXTERNAL_METRIC(al->e[0].tos) + ? "E2 (Larger than any link state path)" + : "E1"); + json_object_int_add(json, "tos", tos); + json_object_int_add(json, "metric", + GET_METRIC(al->e[0].metric)); + json_object_string_addf(json, "nssaForwardAddress", + "%pI4", &al->e[0].fwd_addr); + json_object_int_add( + json, "externalRouteTag", + (route_tag_t)ntohl(al->e[0].route_tag)); + } + } + + return 0; +} + +static int show_func_dummy(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + return 0; +} + +static int show_opaque_lsa_detail(struct vty *vty, struct ospf_lsa *lsa, + json_object *json) +{ + if (lsa != NULL) { + show_ip_ospf_database_header(vty, lsa, json); + show_opaque_info_detail(vty, lsa, json); + if (!json) + vty_out(vty, "\n"); + } + return 0; +} + +int (*show_function[])(struct vty *, struct ospf_lsa *, json_object *) = { + NULL, + show_router_lsa_detail, + show_network_lsa_detail, + show_summary_lsa_detail, + show_summary_asbr_lsa_detail, + show_as_external_lsa_detail, + show_func_dummy, + show_as_nssa_lsa_detail, /* almost same as external */ + NULL, /* type-8 */ + show_opaque_lsa_detail, + show_opaque_lsa_detail, + show_opaque_lsa_detail, +}; + +static void show_lsa_prefix_set(struct vty *vty, struct prefix_ls *lp, + struct in_addr *id, struct in_addr *adv_router) +{ + memset(lp, 0, sizeof(struct prefix_ls)); + lp->family = AF_UNSPEC; + if (id == NULL) + lp->prefixlen = 0; + else if (adv_router == NULL) { + lp->prefixlen = IPV4_MAX_BITLEN; + lp->id = *id; + } else { + lp->prefixlen = 64; + lp->id = *id; + lp->adv_router = *adv_router; + } +} + +static void show_lsa_detail_proc(struct vty *vty, struct route_table *rt, + struct in_addr *id, struct in_addr *adv_router, + json_object *json) +{ + struct prefix_ls lp; + struct route_node *rn, *start; + struct ospf_lsa *lsa; + json_object *json_lsa = NULL; + + show_lsa_prefix_set(vty, &lp, id, adv_router); + start = route_node_get(rt, (struct prefix *)&lp); + if (start) { + route_lock_node(start); + for (rn = start; rn; rn = route_next_until(rn, start)) + if ((lsa = rn->info)) { + if (show_function[lsa->data->type] != NULL) { + if (json) { + json_lsa = + json_object_new_object(); + json_object_array_add(json, + json_lsa); + } + + show_function[lsa->data->type]( + vty, lsa, json_lsa); + } + } + route_unlock_node(start); + } +} + +/* Show detail LSA information + -- if id is NULL then show all LSAs. */ +static void show_lsa_detail(struct vty *vty, struct ospf *ospf, int type, + struct in_addr *id, struct in_addr *adv_router, + json_object *json) +{ + struct listnode *node; + struct ospf_area *area; + char buf[PREFIX_STRLEN]; + json_object *json_lsa_type = NULL; + json_object *json_areas = NULL; + json_object *json_lsa_array = NULL; + + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + if (!json) + vty_out(vty, " %s \n\n", + show_database_desc[type]); + else + json_lsa_array = json_object_new_array(); + + show_lsa_detail_proc(vty, AS_LSDB(ospf, type), id, adv_router, + json_lsa_array); + if (json) + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_array); + + break; + default: + if (json) + json_areas = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (!json) { + vty_out(vty, + "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add(json_areas, + inet_ntop(AF_INET, + &area->area_id, + buf, + sizeof(buf)), + json_lsa_array); + } + + show_lsa_detail_proc(vty, AREA_LSDB(area, type), id, + adv_router, json_lsa_array); + } + + if (json) { + json_lsa_type = json_object_new_object(); + json_object_object_add(json_lsa_type, "areas", + json_areas); + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_type); + } + break; + } +} + +static void show_lsa_detail_adv_router_proc(struct vty *vty, + struct route_table *rt, + struct in_addr *adv_router, + json_object *json) +{ + struct route_node *rn; + struct ospf_lsa *lsa; + json_object *json_lsa = NULL; + + for (rn = route_top(rt); rn; rn = route_next(rn)) + if ((lsa = rn->info)) { + if (IPV4_ADDR_SAME(adv_router, + &lsa->data->adv_router)) { + if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) + continue; + if (json) { + json_lsa = json_object_new_object(); + json_object_array_add(json, json_lsa); + } + + if (show_function[lsa->data->type] != NULL) + show_function[lsa->data->type]( + vty, lsa, json_lsa); + } + } +} + +/* Show detail LSA information. */ +static void show_lsa_detail_adv_router(struct vty *vty, struct ospf *ospf, + int type, struct in_addr *adv_router, + json_object *json) +{ + struct listnode *node; + struct ospf_area *area; + char buf[PREFIX_STRLEN]; + json_object *json_lsa_type = NULL; + json_object *json_areas = NULL; + json_object *json_lsa_array = NULL; + + if (json) + json_lsa_type = json_object_new_object(); + + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + if (!json) + vty_out(vty, " %s \n\n", + show_database_desc[type]); + else + json_lsa_array = json_object_new_array(); + + show_lsa_detail_adv_router_proc(vty, AS_LSDB(ospf, type), + adv_router, json_lsa_array); + if (json) + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_array); + break; + default: + if (json) + json_areas = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (!json) { + vty_out(vty, + "\n %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add( + json_areas, + inet_ntop(AF_INET, &area->area_id, buf, + sizeof(buf)), + json_lsa_array); + } + + show_lsa_detail_adv_router_proc( + vty, AREA_LSDB(area, type), adv_router, + json_lsa_array); + } + + if (json) { + json_object_object_add(json_lsa_type, "areas", + json_areas); + json_object_object_add(json, + show_database_desc_json[type], + json_lsa_type); + } + break; + } +} + +void show_ip_ospf_database_summary(struct vty *vty, struct ospf *ospf, int self, + json_object *json) +{ + struct ospf_lsa *lsa; + struct route_node *rn; + struct ospf_area *area; + struct listnode *node; + char buf[PREFIX_STRLEN]; + json_object *json_areas = NULL; + json_object *json_area = NULL; + json_object *json_lsa = NULL; + int type; + json_object *json_lsa_array = NULL; + uint32_t count; + + if (json) + json_areas = json_object_new_object(); + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (json) + json_area = json_object_new_object(); + + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + count = 0; + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + continue; + default: + break; + } + if (ospf_lsdb_count_self(area->lsdb, type) > 0 + || (!self + && ospf_lsdb_count(area->lsdb, type) > 0)) { + + if (!json) { + vty_out(vty, + " %s (Area %s)\n\n", + show_database_desc[type], + ospf_area_desc_string(area)); + vty_out(vty, "%s\n", + show_database_header[type]); + } else { + json_lsa_array = + json_object_new_array(); + json_object_object_add( + json_area, + show_database_desc_json[type], + json_lsa_array); + } + + LSDB_LOOP (AREA_LSDB(area, type), rn, lsa) { + if (json) { + json_lsa = + json_object_new_object(); + json_object_array_add( + json_lsa_array, + json_lsa); + } + + count += show_lsa_summary( + vty, lsa, self, json_lsa); + } + + if (!json) + vty_out(vty, "\n"); + else + json_object_int_add( + json_area, + + show_database_desc_count_json + [type], + count); + } + } + if (json) + json_object_object_add(json_areas, + inet_ntop(AF_INET, + &area->area_id, + buf, sizeof(buf)), + json_area); + } + + if (json) + json_object_object_add(json, "areas", json_areas); + + for (type = OSPF_MIN_LSA; type < OSPF_MAX_LSA; type++) { + count = 0; + switch (type) { + case OSPF_AS_EXTERNAL_LSA: + case OSPF_OPAQUE_AS_LSA: + break; + default: + continue; + } + if (ospf_lsdb_count_self(ospf->lsdb, type) + || (!self && ospf_lsdb_count(ospf->lsdb, type))) { + if (!json) { + vty_out(vty, " %s\n\n", + show_database_desc[type]); + vty_out(vty, "%s\n", + show_database_header[type]); + } else { + json_lsa_array = json_object_new_array(); + json_object_object_add( + json, show_database_desc_json[type], + json_lsa_array); + } + + LSDB_LOOP (AS_LSDB(ospf, type), rn, lsa) { + if (json) { + json_lsa = json_object_new_object(); + json_object_array_add(json_lsa_array, + json_lsa); + } + + count += show_lsa_summary(vty, lsa, self, + json_lsa); + } + + if (!json) + vty_out(vty, "\n"); + else + json_object_int_add( + json, + show_database_desc_count_json[type], + count); + } + } + + if (!json) + vty_out(vty, "\n"); +} + +static void show_ip_ospf_database_maxage(struct vty *vty, struct ospf *ospf, + json_object *json) +{ + struct route_node *rn; + char buf[PREFIX_STRLEN]; + json_object *json_maxage = NULL; + + if (!json) + vty_out(vty, "\n MaxAge Link States:\n\n"); + else + json_maxage = json_object_new_object(); + + for (rn = route_top(ospf->maxage_lsa); rn; rn = route_next(rn)) { + struct ospf_lsa *lsa; + json_object *json_lsa = NULL; + + if ((lsa = rn->info) != NULL) { + if (!json) { + vty_out(vty, "Link type: %d\n", + lsa->data->type); + vty_out(vty, "Link State ID: %pI4\n", + &lsa->data->id); + vty_out(vty, "Advertising Router: %pI4\n", + &lsa->data->adv_router); + vty_out(vty, "LSA lock count: %d\n", lsa->lock); + vty_out(vty, "\n"); + } else { + json_lsa = json_object_new_object(); + json_object_int_add(json_lsa, "linkType", + lsa->data->type); + json_object_string_addf(json_lsa, "linkStateId", + "%pI4", &lsa->data->id); + json_object_string_addf( + json_lsa, "advertisingRouter", "%pI4", + &lsa->data->adv_router); + json_object_int_add(json_lsa, "lsaLockCount", + lsa->lock); + json_object_object_add( + json_maxage, + inet_ntop(AF_INET, + &lsa->data->id, + buf, sizeof(buf)), + json_lsa); + } + } + } + if (json) + json_object_object_add(json, "maxAgeLinkStates", json_maxage); +} + +#define OSPF_LSA_TYPE_NSSA_DESC "NSSA external link state\n" +#define OSPF_LSA_TYPE_NSSA_CMD_STR "|nssa-external" + +#define OSPF_LSA_TYPE_OPAQUE_LINK_DESC "Link local Opaque-LSA\n" +#define OSPF_LSA_TYPE_OPAQUE_AREA_DESC "Link area Opaque-LSA\n" +#define OSPF_LSA_TYPE_OPAQUE_AS_DESC "Link AS Opaque-LSA\n" +#define OSPF_LSA_TYPE_OPAQUE_CMD_STR "|opaque-link|opaque-area|opaque-as" + +#define OSPF_LSA_TYPES_DESC \ + "ASBR summary link states\n" \ + "External link states\n" \ + "Network link states\n" \ + "Router link states\n" \ + "Network summary link states\n" OSPF_LSA_TYPE_NSSA_DESC \ + OSPF_LSA_TYPE_OPAQUE_LINK_DESC OSPF_LSA_TYPE_OPAQUE_AREA_DESC \ + OSPF_LSA_TYPE_OPAQUE_AS_DESC + +static int +show_ip_ospf_database_common(struct vty *vty, struct ospf *ospf, bool maxage, + bool self, bool detail, const char *type_name, + struct in_addr *lsid, struct in_addr *adv_router, + bool use_vrf, json_object *json, bool uj) +{ + int type; + json_object *json_vrf = NULL; + + if (uj) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + if (ospf->instance) { + if (uj) + json_object_int_add(json_vrf, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + /* Show Router ID. */ + if (uj) { + json_object_string_addf(json_vrf, "routerId", "%pI4", + &ospf->router_id); + } else { + vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", + &ospf->router_id); + } + + /* Show MaxAge LSAs */ + if (maxage) { + show_ip_ospf_database_maxage(vty, ospf, json_vrf); + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } + return CMD_SUCCESS; + } + + /* Show all LSAs. */ + if (!type_name) { + if (detail) { + for (int i = OSPF_ROUTER_LSA; i <= OSPF_OPAQUE_AS_LSA; + i++) { + switch (i) { + case OSPF_GROUP_MEMBER_LSA: + case OSPF_EXTERNAL_ATTRIBUTES_LSA: + /* ignore deprecated LSA types */ + continue; + default: + break; + } + + if (adv_router && !lsid) + show_lsa_detail_adv_router(vty, ospf, i, + adv_router, + json_vrf); + else + show_lsa_detail(vty, ospf, i, lsid, + adv_router, json_vrf); + } + } else + show_ip_ospf_database_summary(vty, ospf, self, + json_vrf); + + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } + return CMD_SUCCESS; + } + + /* Set database type to show. */ + if (strncmp(type_name, "r", 1) == 0) + type = OSPF_ROUTER_LSA; + else if (strncmp(type_name, "ne", 2) == 0) + type = OSPF_NETWORK_LSA; + else if (strncmp(type_name, "ns", 2) == 0) + type = OSPF_AS_NSSA_LSA; + else if (strncmp(type_name, "su", 2) == 0) + type = OSPF_SUMMARY_LSA; + else if (strncmp(type_name, "a", 1) == 0) + type = OSPF_ASBR_SUMMARY_LSA; + else if (strncmp(type_name, "e", 1) == 0) + type = OSPF_AS_EXTERNAL_LSA; + else if (strncmp(type_name, "opaque-l", 8) == 0) + type = OSPF_OPAQUE_LINK_LSA; + else if (strncmp(type_name, "opaque-ar", 9) == 0) + type = OSPF_OPAQUE_AREA_LSA; + else if (strncmp(type_name, "opaque-as", 9) == 0) + type = OSPF_OPAQUE_AS_LSA; + else { + if (uj) { + if (use_vrf) + json_object_free(json_vrf); + } + return CMD_WARNING; + } + + if (adv_router && !lsid) + show_lsa_detail_adv_router(vty, ospf, type, adv_router, + json_vrf); + else + show_lsa_detail(vty, ospf, type, lsid, adv_router, json_vrf); + + if (json) { + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } + + return CMD_SUCCESS; +} + +DEFPY (show_ip_ospf_database, + show_ip_ospf_database_cmd, + "show ip ospf [(1-65535)$instance_id] [vrf <NAME|all>$vrf_name] database\ + [<\ + max-age$maxage\ + |self-originate$selforig\ + |<\ + detail$detail\ + |<asbr-summary|external|network|router|summary|nssa-external|opaque-link|opaque-area|opaque-as>$type_name\ + >\ + [{\ + A.B.C.D$lsid\ + |<adv-router A.B.C.D$adv_router|self-originate$adv_router_self>\ + }]\ + >]\ + [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Database summary\n" + "LSAs in MaxAge list\n" + "Self-originated link states\n" + "Show detailed information\n" + OSPF_LSA_TYPES_DESC + "Link State ID (as an IP address)\n" + "Advertising Router link states\n" + "Advertising Router (as an IP address)\n" + "Self-originated link states\n" + JSON_STR) +{ + struct ospf *ospf; + int ret = CMD_SUCCESS; + bool use_vrf = !!vrf_name; + bool uj = use_json(argc, argv); + struct in_addr *lsid_p = NULL; + struct in_addr *adv_router_p = NULL; + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); + if (lsid_str) + lsid_p = &lsid; + if (adv_router_str) + adv_router_p = &adv_router; + + if (vrf_name && strmatch(vrf_name, "all")) { + struct listnode *node; + bool ospf_output = false; + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + if (ospf->instance != instance_id) + continue; + + if (adv_router_self) + adv_router_p = &ospf->router_id; + + ospf_output = true; + ret = show_ip_ospf_database_common( + vty, ospf, !!maxage, !!selforig, !!detail, + type_name, lsid_p, adv_router_p, use_vrf, json, + uj); + } + + if (!ospf_output && !uj) + vty_out(vty, "%% OSPF is not enabled\n"); + } else { + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + ospf = ospf_lookup_by_inst_name(instance_id, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; + } + if (adv_router_self) + adv_router_p = &ospf->router_id; + + ret = (show_ip_ospf_database_common( + vty, ospf, !!maxage, !!selforig, !!detail, type_name, + lsid_p, adv_router_p, use_vrf, json, uj)); + } + + if (uj) + vty_json(vty, json); + + return ret; +} + +DEFUN (ip_ospf_authentication_args, + ip_ospf_authentication_args_addr_cmd, + "ip ospf authentication <null|message-digest|key-chain KEYCHAIN_NAME> [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Enable authentication on this interface\n" + "Use null authentication\n" + "Use message-digest authentication\n" + "Use a key-chain for cryptographic authentication keys\n" + "Key-chain name\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_encryption = 3; + int idx_ipv4 = argc-1; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv[idx_ipv4]->type == IPV4_TKN) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + /* Handle null authentication */ + if (argv[idx_encryption]->arg[0] == 'n') { + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_NULL; + return CMD_SUCCESS; + } + + /* Handle message-digest authentication */ + if (argv[idx_encryption]->arg[0] == 'm') { + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + UNSET_IF_PARAM(params, keychain_name); + XFREE(MTYPE_OSPF_IF_PARAMS, params->keychain_name); + return CMD_SUCCESS; + } + + if (argv[idx_encryption]->arg[0] == 'k') { + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + SET_IF_PARAM(params, keychain_name); + params->keychain_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS, argv[idx_encryption+1]->arg); + UNSET_IF_PARAM(params, auth_crypt); + return CMD_SUCCESS; + } + + vty_out(vty, "You shouldn't get here!\n"); + return CMD_WARNING_CONFIG_FAILED; +} + +DEFUN (ip_ospf_authentication, + ip_ospf_authentication_addr_cmd, + "ip ospf authentication [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Enable authentication on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + SET_IF_PARAM(params, auth_type); + params->auth_type = OSPF_AUTH_SIMPLE; + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_authentication_args, + no_ip_ospf_authentication_args_addr_cmd, + "no ip ospf authentication <null|message-digest|key-chain [KEYCHAIN_NAME]> [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Enable authentication on this interface\n" + "Use null authentication\n" + "Use message-digest authentication\n" + "Use a key-chain for cryptographic authentication keys\n" + "Key-chain name\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_encryption = 4; + int idx_ipv4 = argc-1; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct route_node *rn; + int auth_type; + + params = IF_DEF_PARAMS(ifp); + + if (argv[idx_ipv4]->type == IPV4_TKN) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) { + vty_out(vty, "Ip Address specified is unknown\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + + XFREE(MTYPE_OSPF_IF_PARAMS, params->keychain_name); + UNSET_IF_PARAM(params, keychain_name); + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + if (argv[idx_encryption]->arg[0] == 'n') { + auth_type = OSPF_AUTH_NULL; + } else if (argv[idx_encryption]->arg[0] == 'm' || + argv[idx_encryption]->arg[0] == 'k') { + auth_type = OSPF_AUTH_CRYPTOGRAPHIC; + } else { + vty_out(vty, "Unexpected input encountered\n"); + return CMD_WARNING_CONFIG_FAILED; + } + /* + * Here we have a case where the user has entered + * 'no ip ospf authentication (null | message_digest )' + * we need to find if we have any ip addresses underneath it + * that + * correspond to the associated type. + */ + if (params->auth_type == auth_type) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + XFREE(MTYPE_OSPF_IF_PARAMS, params->keychain_name); + UNSET_IF_PARAM(params, keychain_name); + } + + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; + rn = route_next(rn)) { + if ((params = rn->info)) { + if (params->auth_type == auth_type) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + XFREE(MTYPE_OSPF_IF_PARAMS, params->keychain_name); + UNSET_IF_PARAM(params, keychain_name); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params( + ifp, rn->p.u.prefix4); + ospf_if_update_params( + ifp, rn->p.u.prefix4); + } + } + } + } + } + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_authentication, + no_ip_ospf_authentication_addr_cmd, + "no ip ospf authentication [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Enable authentication on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) { + vty_out(vty, "Ip Address specified is unknown\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } else { + /* + * When a user enters 'no ip ospf authentication' + * We should remove all authentication types from + * the interface. + */ + if ((params->auth_type == OSPF_AUTH_NULL) + || (params->auth_type == OSPF_AUTH_CRYPTOGRAPHIC) + || (params->auth_type == OSPF_AUTH_SIMPLE)) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + } + + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; + rn = route_next(rn)) { + if ((params = rn->info)) { + + if ((params->auth_type == OSPF_AUTH_NULL) + || (params->auth_type + == OSPF_AUTH_CRYPTOGRAPHIC) + || (params->auth_type + == OSPF_AUTH_SIMPLE)) { + params->auth_type = OSPF_AUTH_NOTSET; + UNSET_IF_PARAM(params, auth_type); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params( + ifp, rn->p.u.prefix4); + ospf_if_update_params( + ifp, rn->p.u.prefix4); + } + } + } + } + } + + return CMD_SUCCESS; +} + + +DEFUN (ip_ospf_authentication_key, + ip_ospf_authentication_key_addr_cmd, + "ip ospf authentication-key AUTH_KEY [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Authentication password (key)\n" + "The OSPF password (key)\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + strlcpy((char *)params->auth_simple, argv[3]->arg, + sizeof(params->auth_simple)); + SET_IF_PARAM(params, auth_simple); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_authentication_key, + ospf_authentication_key_cmd, + "ospf authentication-key AUTH_KEY [A.B.C.D]", + "OSPF interface commands\n" + VLINK_HELPSTR_AUTH_SIMPLE + "Address of interface\n") +{ + return ip_ospf_authentication_key(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_authentication_key, + no_ip_ospf_authentication_key_authkey_addr_cmd, + "no ip ospf authentication-key [AUTH_KEY [A.B.C.D]]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + VLINK_HELPSTR_AUTH_SIMPLE + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + memset(params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE); + UNSET_IF_PARAM(params, auth_simple); + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_authentication_key, + no_ospf_authentication_key_authkey_addr_cmd, + "no ospf authentication-key [AUTH_KEY [A.B.C.D]]", + NO_STR + "OSPF interface commands\n" + VLINK_HELPSTR_AUTH_SIMPLE + "Address of interface\n") +{ + return no_ip_ospf_authentication_key(self, vty, argc, argv); +} + +DEFUN (ip_ospf_message_digest_key, + ip_ospf_message_digest_key_cmd, + "ip ospf message-digest-key (1-255) md5 KEY [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Message digest authentication password (key)\n" + "Key ID\n" + "Use MD5 algorithm\n" + "The OSPF password (key)\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct crypt_key *ck; + uint8_t key_id; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + int idx = 0; + + argv_find(argv, argc, "(1-255)", &idx); + char *keyid = argv[idx]->arg; + argv_find(argv, argc, "KEY", &idx); + char *cryptkey = argv[idx]->arg; + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + key_id = strtol(keyid, NULL, 10); + + /* Remove existing key, if any */ + ospf_crypt_key_delete(params->auth_crypt, key_id); + + ck = ospf_crypt_key_new(); + ck->key_id = (uint8_t)key_id; + strlcpy((char *)ck->auth_key, cryptkey, sizeof(ck->auth_key)); + + ospf_crypt_key_add(params->auth_crypt, ck); + SET_IF_PARAM(params, auth_crypt); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_message_digest_key, + ospf_message_digest_key_cmd, + "ospf message-digest-key (1-255) md5 KEY [A.B.C.D]", + "OSPF interface commands\n" + "Message digest authentication password (key)\n" + "Key ID\n" + "Use MD5 algorithm\n" + "The OSPF password (key)\n" + "Address of interface\n") +{ + return ip_ospf_message_digest_key(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_message_digest_key, + no_ip_ospf_message_digest_key_cmd, + "no ip ospf message-digest-key (1-255) [md5 KEY] [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Message digest authentication password (key)\n" + "Key ID\n" + "Use MD5 algorithm\n" + "The OSPF password (key)\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct crypt_key *ck; + int key_id; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(1-255)", &idx); + char *keyid = argv[idx]->arg; + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + key_id = strtol(keyid, NULL, 10); + ck = ospf_crypt_key_lookup(params->auth_crypt, key_id); + if (ck == NULL) { + vty_out(vty, "OSPF: Key %d does not exist\n", key_id); + return CMD_WARNING_CONFIG_FAILED; + } + + ospf_crypt_key_delete(params->auth_crypt, key_id); + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_message_digest_key, + no_ospf_message_digest_key_cmd, + "no ospf message-digest-key (1-255) [md5 KEY] [A.B.C.D]", + NO_STR + "OSPF interface commands\n" + "Message digest authentication password (key)\n" + "Key ID\n" + "Use MD5 algorithm\n" + "The OSPF password (key)\n" + "Address of interface\n") +{ + return no_ip_ospf_message_digest_key(self, vty, argc, argv); +} + +DEFUN (ip_ospf_cost, + ip_ospf_cost_cmd, + "ip ospf cost (1-65535) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Interface cost\n" + "Cost\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + uint32_t cost = OSPF_OUTPUT_COST_DEFAULT; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + // get arguments + char *coststr = NULL, *ifaddr = NULL; + + argv_find(argv, argc, "(1-65535)", &idx); + coststr = argv[idx]->arg; + cost = strtol(coststr, NULL, 10); + + ifaddr = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + if (ifaddr) { + if (!inet_aton(ifaddr, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + SET_IF_PARAM(params, output_cost_cmd); + params->output_cost_cmd = cost; + + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_cost, + ospf_cost_cmd, + "ospf cost (1-65535) [A.B.C.D]", + "OSPF interface commands\n" + "Interface cost\n" + "Cost\n" + "Address of interface\n") +{ + return ip_ospf_cost(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_cost, + no_ip_ospf_cost_cmd, + "no ip ospf cost [(1-65535)] [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Interface cost\n" + "Cost\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + // get arguments + char *ifaddr = NULL; + ifaddr = argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + + /* According to the semantics we are mimicking "no ip ospf cost N" is + * always treated as "no ip ospf cost" regardless of the actual value + * of N already configured for the interface. Thus ignore cost. */ + + if (ifaddr) { + if (!inet_aton(ifaddr, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, output_cost_cmd); + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + ospf_if_recalculate_output_cost(ifp); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_cost, + no_ospf_cost_cmd, + "no ospf cost [(1-65535)] [A.B.C.D]", + NO_STR + "OSPF interface commands\n" + "Interface cost\n" + "Cost\n" + "Address of interface\n") +{ + return no_ip_ospf_cost(self, vty, argc, argv); +} + +static void ospf_nbr_timer_update(struct ospf_interface *oi) +{ + struct route_node *rn; + struct ospf_neighbor *nbr; + + for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) { + nbr = rn->info; + + if (!nbr) + continue; + + nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait); + nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval); + nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval); + } +} + +static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str, + const char *nbr_str, + const char *fast_hello_str) +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + uint32_t seconds; + uint8_t hellomult; + struct in_addr addr; + int ret; + struct ospf_if_params *params; + struct ospf_interface *oi; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (nbr_str) { + ret = inet_aton(nbr_str, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + if (interval_str) { + seconds = strtoul(interval_str, NULL, 10); + + /* reset fast_hello too, just to be sure */ + UNSET_IF_PARAM(params, fast_hello); + params->fast_hello = OSPF_FAST_HELLO_DEFAULT; + } else if (fast_hello_str) { + hellomult = strtoul(fast_hello_str, NULL, 10); + /* 1s dead-interval with sub-second hellos desired */ + seconds = OSPF_ROUTER_DEAD_INTERVAL_MINIMAL; + SET_IF_PARAM(params, fast_hello); + params->fast_hello = hellomult; + } else { + vty_out(vty, + "Please specify dead-interval or hello-multiplier\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + SET_IF_PARAM(params, v_wait); + params->v_wait = seconds; + params->is_v_wait_set = true; + + /* Update timer values in neighbor structure. */ + if (nbr_str) { + struct ospf *ospf = NULL; + + ospf = ifp->vrf->info; + if (ospf) { + oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); + if (oi) + ospf_nbr_timer_update(oi); + } + } else { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if ((oi = rn->info)) + ospf_nbr_timer_update(oi); + } + + return CMD_SUCCESS; +} + +DEFUN (ip_ospf_dead_interval, + ip_ospf_dead_interval_cmd, + "ip ospf dead-interval (1-65535) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Interval time after which a neighbor is declared down\n" + "Seconds\n" + "Address of interface\n") +{ + int idx = 0; + char *interval = argv_find(argv, argc, "(1-65535)", &idx) + ? argv[idx]->arg + : NULL; + char *ifaddr = + argv_find(argv, argc, "A.B.C.D", &idx) ? argv[idx]->arg : NULL; + return ospf_vty_dead_interval_set(vty, interval, ifaddr, NULL); +} + + +DEFUN_HIDDEN (ospf_dead_interval, + ospf_dead_interval_cmd, + "ospf dead-interval (1-65535) [A.B.C.D]", + "OSPF interface commands\n" + "Interval time after which a neighbor is declared down\n" + "Seconds\n" + "Address of interface\n") +{ + return ip_ospf_dead_interval(self, vty, argc, argv); +} + +DEFUN (ip_ospf_dead_interval_minimal, + ip_ospf_dead_interval_minimal_addr_cmd, + "ip ospf dead-interval minimal hello-multiplier (1-10) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Interval time after which a neighbor is declared down\n" + "Minimal 1s dead-interval with fast sub-second hellos\n" + "Hello multiplier factor\n" + "Number of Hellos to send each second\n" + "Address of interface\n") +{ + int idx_number = 5; + int idx_ipv4 = 6; + if (argc == 7) + return ospf_vty_dead_interval_set( + vty, NULL, argv[idx_ipv4]->arg, argv[idx_number]->arg); + else + return ospf_vty_dead_interval_set(vty, NULL, NULL, + argv[idx_number]->arg); +} + +DEFUN (no_ip_ospf_dead_interval, + no_ip_ospf_dead_interval_cmd, + "no ip ospf dead-interval [<(1-65535)|minimal hello-multiplier (1-10)> [A.B.C.D]]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Interval time after which a neighbor is declared down\n" + "Seconds\n" + "Minimal 1s dead-interval with fast sub-second hellos\n" + "Hello multiplier factor\n" + "Number of Hellos to send each second\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = argc - 1; + struct in_addr addr = {.s_addr = 0L}; + int ret; + struct ospf_if_params *params; + struct ospf_interface *oi; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (argv[idx_ipv4]->type == IPV4_TKN) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, v_wait); + params->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + params->is_v_wait_set = false; + + UNSET_IF_PARAM(params, fast_hello); + params->fast_hello = OSPF_FAST_HELLO_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + /* Update timer values in neighbor structure. */ + if (argc == 1) { + struct ospf *ospf = NULL; + + ospf = ifp->vrf->info; + if (ospf) { + oi = ospf_if_lookup_by_local_addr(ospf, ifp, addr); + if (oi) + ospf_nbr_timer_update(oi); + } + } else { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) + if ((oi = rn->info)) + ospf_nbr_timer_update(oi); + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_dead_interval, + no_ospf_dead_interval_cmd, + "no ospf dead-interval [<(1-65535)|minimal hello-multiplier (1-10)> [A.B.C.D]]", + NO_STR + "OSPF interface commands\n" + "Interval time after which a neighbor is declared down\n" + "Seconds\n" + "Minimal 1s dead-interval with fast sub-second hellos\n" + "Hello multiplier factor\n" + "Number of Hellos to send each second\n" + "Address of interface\n") +{ + return no_ip_ospf_dead_interval(self, vty, argc, argv); +} + +DEFUN (ip_ospf_hello_interval, + ip_ospf_hello_interval_cmd, + "ip ospf hello-interval (1-65535) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Time between HELLO packets\n" + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr = {.s_addr = 0L}; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + uint32_t seconds = 0; + bool is_addr = false; + uint32_t old_interval = 0; + + argv_find(argv, argc, "(1-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + is_addr = true; + } + + old_interval = params->v_hello; + + /* Return, if same interval is configured. */ + if (old_interval == seconds) + return CMD_SUCCESS; + + SET_IF_PARAM(params, v_hello); + params->v_hello = seconds; + + if (!params->is_v_wait_set) { + SET_IF_PARAM(params, v_wait); + /* As per RFC 4062 + * The router dead interval should + * be some multiple of the HelloInterval (perhaps 4 times the + * hello interval) and must be the same for all routers + * attached to a common network. + */ + params->v_wait = 4 * seconds; + } + + ospf_reset_hello_timer(ifp, addr, is_addr); + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_hello_interval, + ospf_hello_interval_cmd, + "ospf hello-interval (1-65535) [A.B.C.D]", + "OSPF interface commands\n" + "Time between HELLO packets\n" + "Seconds\n" + "Address of interface\n") +{ + return ip_ospf_hello_interval(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_hello_interval, + no_ip_ospf_hello_interval_cmd, + "no ip ospf hello-interval [(1-65535) [A.B.C.D]]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Time between HELLO packets\n" // ignored + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr = {.s_addr = 0L}; + struct ospf_if_params *params; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, v_hello); + params->v_hello = OSPF_HELLO_INTERVAL_DEFAULT; + + if (!params->is_v_wait_set) { + UNSET_IF_PARAM(params, v_wait); + params->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT; + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + oi->type = IF_DEF_PARAMS(ifp)->type; + oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn; + + if (oi->state > ISM_Down) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } + } + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_hello_interval, + no_ospf_hello_interval_cmd, + "no ospf hello-interval [(1-65535) [A.B.C.D]]", + NO_STR + "OSPF interface commands\n" + "Time between HELLO packets\n" // ignored + "Seconds\n" + "Address of interface\n") +{ + return no_ip_ospf_hello_interval(self, vty, argc, argv); +} + +DEFUN(ip_ospf_network, ip_ospf_network_cmd, + "ip ospf network <broadcast|" + "non-broadcast|" + "point-to-multipoint [delay-reflood]|" + "point-to-point [dmvpn]>", + "IP Information\n" + "OSPF interface commands\n" + "Network type\n" + "Specify OSPF broadcast multi-access network\n" + "Specify OSPF NBMA network\n" + "Specify OSPF point-to-multipoint network\n" + "Specify OSPF delayed reflooding of LSAs received on P2MP interface\n" + "Specify OSPF point-to-point network\n" + "Specify OSPF point-to-point DMVPN network\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + int old_type = IF_DEF_PARAMS(ifp)->type; + uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn; + uint8_t old_p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood; + struct route_node *rn; + + if (old_type == OSPF_IFTYPE_LOOPBACK) { + vty_out(vty, + "This is a loopback interface. Can't set network type.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0; + IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = + OSPF_P2MP_DELAY_REFLOOD_DEFAULT; + + if (argv_find(argv, argc, "broadcast", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST; + else if (argv_find(argv, argc, "non-broadcast", &idx)) + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA; + else if (argv_find(argv, argc, "point-to-multipoint", &idx)) { + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT; + if (argv_find(argv, argc, "delay-reflood", &idx)) + IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true; + } else if (argv_find(argv, argc, "point-to-point", &idx)) { + IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT; + if (argv_find(argv, argc, "dmvpn", &idx)) + IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1; + } + + if (IF_DEF_PARAMS(ifp)->type == old_type && + IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn && + IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood) + return CMD_SUCCESS; + + SET_IF_PARAM(IF_DEF_PARAMS(ifp), type); + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + oi->type = IF_DEF_PARAMS(ifp)->type; + oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn; + oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood; + + /* + * The OSPF interface only needs to be flapped if the network + * type or DMVPN parameter changes. + */ + if (IF_DEF_PARAMS(ifp)->type != old_type || + IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn) { + if (oi->state > ISM_Down) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } + } + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_network, + ospf_network_cmd, + "ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point>", + "OSPF interface commands\n" + "Network type\n" + "Specify OSPF broadcast multi-access network\n" + "Specify OSPF NBMA network\n" + "Specify OSPF point-to-multipoint network\n" + "Specify OSPF point-to-point network\n") +{ + return ip_ospf_network(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_network, + no_ip_ospf_network_cmd, + "no ip ospf network [<broadcast|non-broadcast|point-to-multipoint|point-to-point>]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Network type\n" + "Specify OSPF broadcast multi-access network\n" + "Specify OSPF NBMA network\n" + "Specify OSPF point-to-multipoint network\n" + "Specify OSPF point-to-point network\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int old_type = IF_DEF_PARAMS(ifp)->type; + struct route_node *rn; + + IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp); + IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0; + IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = + OSPF_P2MP_DELAY_REFLOOD_DEFAULT; + + if (IF_DEF_PARAMS(ifp)->type == old_type) + return CMD_SUCCESS; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + oi->type = IF_DEF_PARAMS(ifp)->type; + oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn; + oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood; + + if (oi->state > ISM_Down) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_network, + no_ospf_network_cmd, + "no ospf network [<broadcast|non-broadcast|point-to-multipoint|point-to-point>]", + NO_STR + "OSPF interface commands\n" + "Network type\n" + "Specify OSPF broadcast multi-access network\n" + "Specify OSPF NBMA network\n" + "Specify OSPF point-to-multipoint network\n" + "Specify OSPF point-to-point network\n") +{ + return no_ip_ospf_network(self, vty, argc, argv); +} + +DEFUN (ip_ospf_priority, + ip_ospf_priority_cmd, + "ip ospf priority (0-255) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Router priority\n" + "Priority\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + long priority; + struct route_node *rn; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(0-255)", &idx); + priority = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + SET_IF_PARAM(params, priority); + params->priority = priority; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + if (PRIORITY(oi) != OSPF_IF_PARAM(oi, priority)) { + PRIORITY(oi) = OSPF_IF_PARAM(oi, priority); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_priority, + ospf_priority_cmd, + "ospf priority (0-255) [A.B.C.D]", + "OSPF interface commands\n" + "Router priority\n" + "Priority\n" + "Address of interface\n") +{ + return ip_ospf_priority(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_priority, + no_ip_ospf_priority_cmd, + "no ip ospf priority [(0-255) [A.B.C.D]]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Router priority\n" // ignored + "Priority\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct route_node *rn; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, priority); + params->priority = OSPF_ROUTER_PRIORITY_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (!oi) + continue; + + if (PRIORITY(oi) != OSPF_IF_PARAM(oi, priority)) { + PRIORITY(oi) = OSPF_IF_PARAM(oi, priority); + OSPF_ISM_EVENT_SCHEDULE(oi, ISM_NeighborChange); + } + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_priority, + no_ospf_priority_cmd, + "no ospf priority [(0-255) [A.B.C.D]]", + NO_STR + "OSPF interface commands\n" + "Router priority\n" + "Priority\n" + "Address of interface\n") +{ + return no_ip_ospf_priority(self, vty, argc, argv); +} + +DEFUN (ip_ospf_retransmit_interval, + ip_ospf_retransmit_interval_addr_cmd, + "ip ospf retransmit-interval (1-65535) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Time between retransmitting lost link state advertisements\n" + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + uint32_t seconds; + struct in_addr addr; + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + argv_find(argv, argc, "(1-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + SET_IF_PARAM(params, retransmit_interval); + params->retransmit_interval = seconds; + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_retransmit_interval, + ospf_retransmit_interval_cmd, + "ospf retransmit-interval (1-65535) [A.B.C.D]", + "OSPF interface commands\n" + "Time between retransmitting lost link state advertisements\n" + "Seconds\n" + "Address of interface\n") +{ + return ip_ospf_retransmit_interval(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_retransmit_interval, + no_ip_ospf_retransmit_interval_addr_cmd, + "no ip ospf retransmit-interval [(1-65535)] [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Time between retransmitting lost link state advertisements\n" + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, retransmit_interval); + params->retransmit_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (no_ospf_retransmit_interval, + no_ospf_retransmit_interval_cmd, + "no ospf retransmit-interval [(1-65535)] [A.B.C.D]", + NO_STR + "OSPF interface commands\n" + "Time between retransmitting lost link state advertisements\n" + "Seconds\n" + "Address of interface\n") +{ + return no_ip_ospf_retransmit_interval(self, vty, argc, argv); +} + +DEFPY (ip_ospf_gr_hdelay, + ip_ospf_gr_hdelay_cmd, + "ip ospf graceful-restart hello-delay (1-1800)", + IP_STR + "OSPF interface commands\n" + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + /* Note: new or updated value won't affect ongoing graceful restart. */ + SET_IF_PARAM(params, v_gr_hello_delay); + params->v_gr_hello_delay = hello_delay; + + return CMD_SUCCESS; +} + +DEFPY (no_ip_ospf_gr_hdelay, + no_ip_ospf_gr_hdelay_cmd, + "no ip ospf graceful-restart hello-delay [(1-1800)]", + NO_STR + IP_STR + "OSPF interface commands\n" + "Graceful Restart parameters\n" + "Delay the sending of the first hello packets.\n" + "Delay in seconds\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct ospf_if_params *params; + struct route_node *rn; + + params = IF_DEF_PARAMS(ifp); + UNSET_IF_PARAM(params, v_gr_hello_delay); + params->v_gr_hello_delay = OSPF_HELLO_DELAY_DEFAULT; + + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi; + + oi = rn->info; + if (!oi) + continue; + + oi->gr.hello_delay.elapsed_seconds = 0; + EVENT_OFF(oi->gr.hello_delay.t_grace_send); + } + + return CMD_SUCCESS; +} + +DEFUN (ip_ospf_transmit_delay, + ip_ospf_transmit_delay_addr_cmd, + "ip ospf transmit-delay (1-65535) [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Link state transmit delay\n" + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + uint32_t seconds; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + argv_find(argv, argc, "(1-65535)", &idx); + seconds = strtol(argv[idx]->arg, NULL, 10); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + SET_IF_PARAM(params, transmit_delay); + params->transmit_delay = seconds; + + return CMD_SUCCESS; +} + +DEFUN_HIDDEN (ospf_transmit_delay, + ospf_transmit_delay_cmd, + "ospf transmit-delay (1-65535) [A.B.C.D]", + "OSPF interface commands\n" + "Link state transmit delay\n" + "Seconds\n" + "Address of interface\n") +{ + return ip_ospf_transmit_delay(self, vty, argc, argv); +} + +DEFUN (no_ip_ospf_transmit_delay, + no_ip_ospf_transmit_delay_addr_cmd, + "no ip ospf transmit-delay [(1-65535)] [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Link state transmit delay\n" + "Seconds\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct in_addr addr; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (argv_find(argv, argc, "A.B.C.D", &idx)) { + if (!inet_aton(argv[idx]->arg, &addr)) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } + + UNSET_IF_PARAM(params, transmit_delay); + params->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT; + + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + + return CMD_SUCCESS; +} + + +DEFUN_HIDDEN (no_ospf_transmit_delay, + no_ospf_transmit_delay_cmd, + "no ospf transmit-delay [(1-65535) [A.B.C.D]]", + NO_STR + "OSPF interface commands\n" + "Link state transmit delay\n" + "Seconds\n" + "Address of interface\n") +{ + return no_ip_ospf_transmit_delay(self, vty, argc, argv); +} + +DEFUN (ip_ospf_area, + ip_ospf_area_cmd, + "ip ospf [(1-65535)] area <A.B.C.D|(0-4294967295)> [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Instance ID\n" + "Enable OSPF on this interface\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + int format, ret; + struct in_addr area_id; + struct in_addr addr; + struct ospf_if_params *params = NULL; + struct route_node *rn; + struct ospf *ospf = NULL; + unsigned short instance = 0; + char *areaid; + uint32_t count = 0; + + if (argv_find(argv, argc, "(1-65535)", &idx)) + instance = strtol(argv[idx]->arg, NULL, 10); + + argv_find(argv, argc, "area", &idx); + areaid = argv[idx + 1]->arg; + + if (!instance) + ospf = ifp->vrf->info; + else + ospf = ospf_lookup_instance(instance); + + if (instance && instance != ospf_instance) { + /* + * At this point we know we have received + * an instance and there is no ospf instance + * associated with it. This means we are + * in a situation where we have an + * ospf command that is setup for a different + * process(instance). We need to safely + * remove the command from ourselves and + * allow the other instance(process) handle + * the configuration command. + */ + count = 0; + + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + UNSET_IF_PARAM(params, if_area); + count++; + } + + for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn)) + if ((params = rn->info) && OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + UNSET_IF_PARAM(params, if_area); + count++; + } + + if (count > 0) { + ospf = ifp->vrf->info; + if (ospf) + ospf_interface_area_unset(ospf, ifp); + } + + return CMD_NOT_MY_INSTANCE; + } + + ret = str2area_id(areaid, &area_id, &format); + if (ret < 0) { + vty_out(vty, "Please specify area by A.B.C.D|<0-4294967295>\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (memcmp(ifp->name, "VLINK", 5) == 0) { + vty_out(vty, "Cannot enable OSPF on a virtual link.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (ospf) { + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) { + if (rn->info != NULL) { + vty_out(vty, + "Please remove all network commands first.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + } + + params = IF_DEF_PARAMS(ifp); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area) + && !IPV4_ADDR_SAME(¶ms->if_area, &area_id)) { + vty_out(vty, + "Must remove previous area config before changing ospf area \n"); + return CMD_WARNING_CONFIG_FAILED; + } + + // Check if we have an address arg and proccess it + if (argc == idx + 3) { + if (!inet_aton(argv[idx + 2]->arg, &addr)) { + vty_out(vty, + "Please specify Intf Address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + // update/create address-level params + params = ospf_get_if_params((ifp), (addr)); + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + if (!IPV4_ADDR_SAME(¶ms->if_area, &area_id)) { + vty_out(vty, + "Must remove previous area/address config before changing ospf area\n"); + return CMD_WARNING_CONFIG_FAILED; + } else + return CMD_SUCCESS; + } + ospf_if_update_params((ifp), (addr)); + } + + /* enable ospf on this interface with area_id */ + if (params) { + SET_IF_PARAM(params, if_area); + params->if_area = area_id; + params->if_area_id_fmt = format; + } + + if (ospf) + ospf_interface_area_set(ospf, ifp); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_area, + no_ip_ospf_area_cmd, + "no ip ospf [(1-65535)] area [<A.B.C.D|(0-4294967295)> [A.B.C.D]]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Instance ID\n" + "Disable OSPF on this interface\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx = 0; + struct ospf *ospf; + struct ospf_if_params *params; + unsigned short instance = 0; + struct in_addr addr; + struct in_addr area_id; + + if (argv_find(argv, argc, "(1-65535)", &idx)) + instance = strtol(argv[idx]->arg, NULL, 10); + + if (!instance) + ospf = ifp->vrf->info; + else + ospf = ospf_lookup_instance(instance); + + if (instance && instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + argv_find(argv, argc, "area", &idx); + + // Check if we have an address arg and proccess it + if (argc == idx + 3) { + if (!inet_aton(argv[idx + 2]->arg, &addr)) { + vty_out(vty, + "Please specify Intf Address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_lookup_if_params(ifp, addr); + if ((params) == NULL) + return CMD_SUCCESS; + } else + params = IF_DEF_PARAMS(ifp); + + area_id = params->if_area; + if (!OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + vty_out(vty, + "Can't find specified interface area configuration.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + UNSET_IF_PARAM(params, if_area); + if (params != IF_DEF_PARAMS((ifp))) { + ospf_free_if_params((ifp), (addr)); + ospf_if_update_params((ifp), (addr)); + } + + if (ospf) { + ospf_interface_area_unset(ospf, ifp); + ospf_area_check_free(ospf, area_id); + } + + return CMD_SUCCESS; +} + +DEFUN (ip_ospf_passive, + ip_ospf_passive_cmd, + "ip ospf passive [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Suppress routing updates on an interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + struct in_addr addr = {.s_addr = INADDR_ANY}; + struct ospf_if_params *params; + int ret; + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } else { + params = IF_DEF_PARAMS(ifp); + } + + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_PASSIVE); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_passive, + no_ip_ospf_passive_cmd, + "no ip ospf passive [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Enable routing updates on an interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + struct in_addr addr = {.s_addr = INADDR_ANY}; + struct ospf_if_params *params; + int ret; + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_lookup_if_params(ifp, addr); + if (params == NULL) + return CMD_SUCCESS; + } else { + params = IF_DEF_PARAMS(ifp); + } + + ospf_passive_interface_update(ifp, params, addr, OSPF_IF_ACTIVE); + + return CMD_SUCCESS; +} + +DEFUN (ospf_redistribute_source, + ospf_redistribute_source_cmd, + "redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + REDIST_STR + FRR_REDIST_HELP_STR_OSPFD + "Metric for redistributed routes\n" + "OSPF default metric\n" + "OSPF exterior metric type for redistributed routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_protocol = 1; + int source; + int type = -1; + int metric = -1; + struct ospf_redist *red; + int idx = 0; + bool update = false; + + /* Get distribute source. */ + source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; + + /* Get metric value. */ + if (argv_find(argv, argc, "(0-16777214)", &idx)) { + if (!str2metric(argv[idx]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + } + idx = 1; + /* Get metric type. */ + if (argv_find(argv, argc, "(1-2)", &idx)) { + if (!str2metric_type(argv[idx]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; + } + idx = 1; + + red = ospf_redist_lookup(ospf, source, 0); + if (!red) + red = ospf_redist_add(ospf, source, 0); + else + update = true; + + /* Get route-map */ + if (argv_find(argv, argc, "route-map", &idx)) { + ospf_routemap_set(red, argv[idx + 1]->arg); + } else + ospf_routemap_unset(red); + + if (update) + return ospf_redistribute_update(ospf, red, source, 0, type, + metric); + else + return ospf_redistribute_set(ospf, red, source, 0, type, + metric); +} + +DEFUN (no_ospf_redistribute_source, + no_ospf_redistribute_source_cmd, + "no redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + NO_STR + REDIST_STR + FRR_REDIST_HELP_STR_OSPFD + "Metric for redistributed routes\n" + "OSPF default metric\n" + "OSPF exterior metric type for redistributed routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_protocol = 2; + int source; + struct ospf_redist *red; + + source = proto_redistnum(AFI_IP, argv[idx_protocol]->text); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; + + red = ospf_redist_lookup(ospf, source, 0); + if (!red) + return CMD_SUCCESS; + + ospf_routemap_unset(red); + ospf_redist_del(ospf, source, 0); + + return ospf_redistribute_unset(ospf, source, 0); +} + +DEFUN (ospf_redistribute_instance_source, + ospf_redistribute_instance_source_cmd, + "redistribute <ospf|table> (1-65535) [{metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + REDIST_STR + "Open Shortest Path First\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table ID\n" + "Metric for redistributed routes\n" + "OSPF default metric\n" + "OSPF exterior metric type for redistributed routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ospf_table = 1; + int idx_number = 2; + int idx = 3; + int source; + int type = -1; + int metric = -1; + unsigned short instance; + struct ospf_redist *red; + bool update = false; + + source = proto_redistnum(AFI_IP, argv[idx_ospf_table]->text); + + if (source < 0) { + vty_out(vty, "Unknown instance redistribution\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + + if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) { + vty_out(vty, + "Instance redistribution in non-instanced OSPF not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) { + vty_out(vty, "Same instance OSPF redistribution not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Get metric value. */ + if (argv_find(argv, argc, "metric", &idx)) + if (!str2metric(argv[idx + 1]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + + idx = 3; + /* Get metric type. */ + if (argv_find(argv, argc, "metric-type", &idx)) + if (!str2metric_type(argv[idx + 1]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; + + red = ospf_redist_lookup(ospf, source, instance); + if (!red) + red = ospf_redist_add(ospf, source, instance); + else + update = true; + + idx = 3; + if (argv_find(argv, argc, "route-map", &idx)) + ospf_routemap_set(red, argv[idx + 1]->arg); + else + ospf_routemap_unset(red); + + if (update) + return ospf_redistribute_update(ospf, red, source, instance, + type, metric); + else + return ospf_redistribute_set(ospf, red, source, instance, type, + metric); +} + +DEFUN (no_ospf_redistribute_instance_source, + no_ospf_redistribute_instance_source_cmd, + "no redistribute <ospf|table> (1-65535) [{metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + NO_STR + REDIST_STR + "Open Shortest Path First\n" + "Non-main Kernel Routing Table\n" + "Instance ID/Table Id\n" + "Metric for redistributed routes\n" + "OSPF default metric\n" + "OSPF exterior metric type for redistributed routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_ospf_table = 2; + int idx_number = 3; + unsigned int instance; + struct ospf_redist *red; + int source; + + if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) + source = ZEBRA_ROUTE_OSPF; + else + source = ZEBRA_ROUTE_TABLE; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + + if ((source == ZEBRA_ROUTE_OSPF) && !ospf->instance) { + vty_out(vty, + "Instance redistribution in non-instanced OSPF not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if ((source == ZEBRA_ROUTE_OSPF) && (ospf->instance == instance)) { + vty_out(vty, "Same instance OSPF redistribution not allowed\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + red = ospf_redist_lookup(ospf, source, instance); + if (!red) + return CMD_SUCCESS; + + ospf_routemap_unset(red); + ospf_redist_del(ospf, source, instance); + + return ospf_redistribute_unset(ospf, source, instance); +} + +DEFUN (ospf_distribute_list_out, + ospf_distribute_list_out_cmd, + "distribute-list ACCESSLIST4_NAME out " FRR_REDIST_STR_OSPFD, + "Filter networks in routing updates\n" + "Access-list name\n" + OUT_STR + FRR_REDIST_HELP_STR_OSPFD) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_word = 1; + int source; + + char *proto = argv[argc - 1]->text; + + /* Get distribute source. */ + source = proto_redistnum(AFI_IP, proto); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; + + return ospf_distribute_list_out_set(ospf, source, argv[idx_word]->arg); +} + +DEFUN (no_ospf_distribute_list_out, + no_ospf_distribute_list_out_cmd, + "no distribute-list ACCESSLIST4_NAME out " FRR_REDIST_STR_OSPFD, + NO_STR + "Filter networks in routing updates\n" + "Access-list name\n" + OUT_STR + FRR_REDIST_HELP_STR_OSPFD) +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_word = 2; + int source; + + char *proto = argv[argc - 1]->text; + source = proto_redistnum(AFI_IP, proto); + if (source < 0) + return CMD_WARNING_CONFIG_FAILED; + + return ospf_distribute_list_out_unset(ospf, source, + argv[idx_word]->arg); +} + +/* Default information originate. */ +DEFUN (ospf_default_information_originate, + ospf_default_information_originate_cmd, + "default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + "Control distribution of default information\n" + "Distribute a default route\n" + "Always advertise default route\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int default_originate = DEFAULT_ORIGINATE_ZEBRA; + int type = -1; + int metric = -1; + struct ospf_redist *red; + int idx = 0; + int cur_originate = ospf->default_originate; + bool sameRtmap = false; + char *rtmap = NULL; + + red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); + + /* Check whether "always" was specified */ + if (argv_find(argv, argc, "always", &idx)) + default_originate = DEFAULT_ORIGINATE_ALWAYS; + idx = 1; + /* Get metric value */ + if (argv_find(argv, argc, "(0-16777214)", &idx)) { + if (!str2metric(argv[idx]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + } + idx = 1; + /* Get metric type. */ + if (argv_find(argv, argc, "(1-2)", &idx)) { + if (!str2metric_type(argv[idx]->arg, &type)) + return CMD_WARNING_CONFIG_FAILED; + } + idx = 1; + /* Get route-map */ + if (argv_find(argv, argc, "route-map", &idx)) + rtmap = argv[idx + 1]->arg; + + /* To check if user is providing same route map */ + if ((!rtmap && !ROUTEMAP_NAME(red)) || + (rtmap && ROUTEMAP_NAME(red) && + (strcmp(rtmap, ROUTEMAP_NAME(red)) == 0))) + sameRtmap = true; + + /* Don't allow if the same lsa is already originated. */ + if ((sameRtmap) + && (red->dmetric.type == type) + && (red->dmetric.value == metric) + && (cur_originate == default_originate)) + return CMD_SUCCESS; + + /* Updating Metric details */ + red->dmetric.type = type; + red->dmetric.value = metric; + + /* updating route map details */ + if (rtmap) + ospf_routemap_set(red, rtmap); + else + ospf_routemap_unset(red); + + return ospf_redistribute_default_set(ospf, default_originate, type, + metric); +} + +DEFUN (no_ospf_default_information_originate, + no_ospf_default_information_originate_cmd, + "no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map RMAP_NAME}]", + NO_STR + "Control distribution of default information\n" + "Distribute a default route\n" + "Always advertise default route\n" + "OSPF default metric\n" + "OSPF metric\n" + "OSPF metric type for default routes\n" + "Set OSPF External Type 1/2 metrics\n" + "Route map reference\n" + "Pointer to route-map entries\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct ospf_redist *red; + + red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); + if (!red) + return CMD_SUCCESS; + + ospf_routemap_unset(red); + ospf_redist_del(ospf, DEFAULT_ROUTE, 0); + + return ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, + 0, 0); +} + +DEFUN (ospf_default_metric, + ospf_default_metric_cmd, + "default-metric (0-16777214)", + "Set metric of redistributed routes\n" + "Default metric\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 1; + int metric = -1; + + if (!str2metric(argv[idx_number]->arg, &metric)) + return CMD_WARNING_CONFIG_FAILED; + + ospf->default_metric = metric; + + ospf_schedule_asbr_redist_update(ospf); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_default_metric, + no_ospf_default_metric_cmd, + "no default-metric [(0-16777214)]", + NO_STR + "Set metric of redistributed routes\n" + "Default metric\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->default_metric = -1; + + ospf_schedule_asbr_redist_update(ospf); + + return CMD_SUCCESS; +} + + +DEFUN (ospf_distance, + ospf_distance_cmd, + "distance (1-255)", + "Administrative distance\n" + "OSPF Administrative distance\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 1; + uint8_t distance; + + distance = atoi(argv[idx_number]->arg); + if (ospf->distance_all != distance) { + ospf->distance_all = distance; + ospf_restart_spf(ospf); + } + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_distance, + no_ospf_distance_cmd, + "no distance (1-255)", + NO_STR + "Administrative distance\n" + "OSPF Administrative distance\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (ospf->distance_all) { + ospf->distance_all = 0; + ospf_restart_spf(ospf); + } + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_distance_ospf, + no_ospf_distance_ospf_cmd, + "no distance ospf [{intra-area [(1-255)]|inter-area [(1-255)]|external [(1-255)]}]", + NO_STR + "Administrative distance\n" + "OSPF administrative distance\n" + "Intra-area routes\n" + "Distance for intra-area routes\n" + "Inter-area routes\n" + "Distance for inter-area routes\n" + "External routes\n" + "Distance for external routes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx = 0; + + if (argv_find(argv, argc, "intra-area", &idx) || argc == 3) + idx = ospf->distance_intra = 0; + if (argv_find(argv, argc, "inter-area", &idx) || argc == 3) + idx = ospf->distance_inter = 0; + if (argv_find(argv, argc, "external", &idx) || argc == 3) + ospf->distance_external = 0; + + return CMD_SUCCESS; +} + +DEFUN (ospf_distance_ospf, + ospf_distance_ospf_cmd, + "distance ospf {intra-area (1-255)|inter-area (1-255)|external (1-255)}", + "Administrative distance\n" + "OSPF administrative distance\n" + "Intra-area routes\n" + "Distance for intra-area routes\n" + "Inter-area routes\n" + "Distance for inter-area routes\n" + "External routes\n" + "Distance for external routes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx = 0; + + ospf->distance_intra = 0; + ospf->distance_inter = 0; + ospf->distance_external = 0; + + if (argv_find(argv, argc, "intra-area", &idx)) + ospf->distance_intra = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "inter-area", &idx)) + ospf->distance_inter = atoi(argv[idx + 1]->arg); + idx = 0; + if (argv_find(argv, argc, "external", &idx)) + ospf->distance_external = atoi(argv[idx + 1]->arg); + + return CMD_SUCCESS; +} + +DEFUN (ip_ospf_mtu_ignore, + ip_ospf_mtu_ignore_addr_cmd, + "ip ospf mtu-ignore [A.B.C.D]", + "IP Information\n" + "OSPF interface commands\n" + "Disable MTU mismatch detection on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 3; + struct in_addr addr; + int ret; + + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argc == 4) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + params->mtu_ignore = 1; + if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) + SET_IF_PARAM(params, mtu_ignore); + else { + UNSET_IF_PARAM(params, mtu_ignore); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_mtu_ignore, + no_ip_ospf_mtu_ignore_addr_cmd, + "no ip ospf mtu-ignore [A.B.C.D]", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disable MTU mismatch detection on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + int idx_ipv4 = 4; + struct in_addr addr; + int ret; + + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (argc == 5) { + ret = inet_aton(argv[idx_ipv4]->arg, &addr); + if (!ret) { + vty_out(vty, + "Please specify interface address by A.B.C.D\n"); + return CMD_WARNING_CONFIG_FAILED; + } + params = ospf_get_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + params->mtu_ignore = 0; + if (params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) + SET_IF_PARAM(params, mtu_ignore); + else { + UNSET_IF_PARAM(params, mtu_ignore); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, addr); + ospf_if_update_params(ifp, addr); + } + } + return CMD_SUCCESS; +} + +DEFPY(ip_ospf_capability_opaque, ip_ospf_capability_opaque_addr_cmd, + "[no] ip ospf capability opaque [A.B.C.D]$ip_addr", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disable OSPF capability on this interface\n" + "Disable OSPF opaque LSA capability on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct route_node *rn; + bool old_opaque_capable; + bool opaque_capable_change; + + struct ospf_if_params *params; + params = IF_DEF_PARAMS(ifp); + + if (ip_addr.s_addr != INADDR_ANY) { + params = ospf_get_if_params(ifp, ip_addr); + ospf_if_update_params(ifp, ip_addr); + } + + old_opaque_capable = params->opaque_capable; + params->opaque_capable = (no) ? false : true; + opaque_capable_change = (old_opaque_capable != params->opaque_capable); + if (params->opaque_capable != OSPF_OPAQUE_CAPABLE_DEFAULT) + SET_IF_PARAM(params, opaque_capable); + else { + UNSET_IF_PARAM(params, opaque_capable); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, ip_addr); + ospf_if_update_params(ifp, ip_addr); + } + } + + /* + * If there is a change to the opaque capability, flap the interface + * to reset all the neighbor adjacencies. + */ + if (opaque_capable_change) { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi && (oi->state > ISM_Down) && + (ip_addr.s_addr == INADDR_ANY || + IPV4_ADDR_SAME(&oi->address->u.prefix4, + &ip_addr))) { + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown); + OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp); + } + } + } + return CMD_SUCCESS; +} + + +DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd, + "[no] ip ospf prefix-suppression [A.B.C.D]$ip_addr", NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Supress OSPF prefix advertisement on this interface\n" + "Address of interface\n") +{ + VTY_DECLVAR_CONTEXT(interface, ifp); + struct route_node *rn; + bool prefix_suppression_change; + struct ospf_if_params *params; + + params = IF_DEF_PARAMS(ifp); + + if (ip_addr.s_addr != INADDR_ANY) { + params = ospf_get_if_params(ifp, ip_addr); + ospf_if_update_params(ifp, ip_addr); + } + + prefix_suppression_change = (params->prefix_suppression == (bool)no); + params->prefix_suppression = (no) ? false : true; + if (params->prefix_suppression != OSPF_PREFIX_SUPPRESSION_DEFAULT) + SET_IF_PARAM(params, prefix_suppression); + else { + UNSET_IF_PARAM(params, prefix_suppression); + if (params != IF_DEF_PARAMS(ifp)) { + ospf_free_if_params(ifp, ip_addr); + ospf_if_update_params(ifp, ip_addr); + } + } + + /* + * If there is a change to the prefix suppression, update the Router-LSA. + */ + if (prefix_suppression_change) { + for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) { + struct ospf_interface *oi = rn->info; + + if (oi && (oi->state > ISM_Down) && + (ip_addr.s_addr == INADDR_ANY || + IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr))) { + (void)ospf_router_lsa_update_area(oi->area); + if (oi->state == ISM_DR) + ospf_network_lsa_update(oi); + } + } + } + return CMD_SUCCESS; +} + +DEFUN (ospf_max_metric_router_lsa_admin, + ospf_max_metric_router_lsa_admin_cmd, + "max-metric router-lsa administrative", + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Administratively applied, for an indefinite period\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + SET_FLAG(area->stub_router_state, OSPF_AREA_ADMIN_STUB_ROUTED); + + if (!CHECK_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED)) + ospf_router_lsa_update_area(area); + } + + /* Allows for areas configured later to get the property */ + ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_SET; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_max_metric_router_lsa_admin, + no_ospf_max_metric_router_lsa_admin_cmd, + "no max-metric router-lsa administrative", + NO_STR + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Administratively applied, for an indefinite period\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED); + + /* Don't trample on the start-up stub timer */ + if (CHECK_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED) + && !area->t_stub_router) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED); + ospf_router_lsa_update_area(area); + } + } + ospf->stub_router_admin_set = OSPF_STUB_ROUTER_ADMINISTRATIVE_UNSET; + return CMD_SUCCESS; +} + +DEFUN (ospf_max_metric_router_lsa_startup, + ospf_max_metric_router_lsa_startup_cmd, + "max-metric router-lsa on-startup (5-86400)", + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Automatically advertise stub Router-LSA on startup of OSPF\n" + "Time (seconds) to advertise self as stub-router\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int seconds; + + if (argc < 4) { + vty_out(vty, "%% Must supply stub-router period\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + seconds = strtoul(argv[idx_number]->arg, NULL, 10); + + ospf->stub_router_startup_time = seconds; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_max_metric_router_lsa_startup, + no_ospf_max_metric_router_lsa_startup_cmd, + "no max-metric router-lsa on-startup [(5-86400)]", + NO_STR + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Automatically advertise stub Router-LSA on startup of OSPF\n" + "Time (seconds) to advertise self as stub-router\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *ln; + struct ospf_area *area; + + ospf->stub_router_startup_time = OSPF_STUB_ROUTER_UNCONFIGURED; + + for (ALL_LIST_ELEMENTS_RO(ospf->areas, ln, area)) { + SET_FLAG(area->stub_router_state, + OSPF_AREA_WAS_START_STUB_ROUTED); + EVENT_OFF(area->t_stub_router); + + /* Don't trample on admin stub routed */ + if (!CHECK_FLAG(area->stub_router_state, + OSPF_AREA_ADMIN_STUB_ROUTED)) { + UNSET_FLAG(area->stub_router_state, + OSPF_AREA_IS_STUB_ROUTED); + ospf_router_lsa_update_area(area); + } + } + return CMD_SUCCESS; +} + + +DEFUN (ospf_max_metric_router_lsa_shutdown, + ospf_max_metric_router_lsa_shutdown_cmd, + "max-metric router-lsa on-shutdown (5-100)", + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Advertise stub-router prior to full shutdown of OSPF\n" + "Time (seconds) to wait till full shutdown\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + int idx_number = 3; + unsigned int seconds; + + if (argc < 4) { + vty_out(vty, "%% Must supply stub-router shutdown period\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + seconds = strtoul(argv[idx_number]->arg, NULL, 10); + + ospf->stub_router_shutdown_time = seconds; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_max_metric_router_lsa_shutdown, + no_ospf_max_metric_router_lsa_shutdown_cmd, + "no max-metric router-lsa on-shutdown [(5-100)]", + NO_STR + "OSPF maximum / infinite-distance metric\n" + "Advertise own Router-LSA with infinite distance (stub router)\n" + "Advertise stub-router prior to full shutdown of OSPF\n" + "Time (seconds) to wait till full shutdown\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->stub_router_shutdown_time = OSPF_STUB_ROUTER_UNCONFIGURED; + + return CMD_SUCCESS; +} + +DEFUN (ospf_proactive_arp, + ospf_proactive_arp_cmd, + "proactive-arp", + "Allow sending ARP requests proactively\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->proactive_arp = true; + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_proactive_arp, + no_ospf_proactive_arp_cmd, + "no proactive-arp", + NO_STR + "Disallow sending ARP requests proactively\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf->proactive_arp = false; + + return CMD_SUCCESS; +} + +/* Graceful Restart HELPER Commands */ +DEFPY(ospf_gr_helper_enable, ospf_gr_helper_enable_cmd, + "graceful-restart helper enable [A.B.C.D$address]", + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Enable Helper support\n" + "Advertising Router-ID\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (address_str) { + ospf_gr_helper_support_set_per_routerid(ospf, &address, + OSPF_GR_TRUE); + return CMD_SUCCESS; + } + + ospf_gr_helper_support_set(ospf, OSPF_GR_TRUE); + + return CMD_SUCCESS; +} + +DEFPY(no_ospf_gr_helper_enable, + no_ospf_gr_helper_enable_cmd, + "no graceful-restart helper enable [A.B.C.D$address]", + NO_STR + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Enable Helper support\n" + "Advertising Router-ID\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + if (address_str) { + ospf_gr_helper_support_set_per_routerid(ospf, &address, + OSPF_GR_FALSE); + return CMD_SUCCESS; + } + + ospf_gr_helper_support_set(ospf, OSPF_GR_FALSE); + return CMD_SUCCESS; +} + +DEFPY(ospf_gr_helper_enable_lsacheck, + ospf_gr_helper_enable_lsacheck_cmd, + "graceful-restart helper strict-lsa-checking", + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Enable strict LSA check\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_lsa_check_set(ospf, OSPF_GR_TRUE); + return CMD_SUCCESS; +} + +DEFPY(no_ospf_gr_helper_enable_lsacheck, + no_ospf_gr_helper_enable_lsacheck_cmd, + "no graceful-restart helper strict-lsa-checking", + NO_STR + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Disable strict LSA check\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_lsa_check_set(ospf, OSPF_GR_FALSE); + return CMD_SUCCESS; +} + +DEFPY(ospf_gr_helper_supported_grace_time, + ospf_gr_helper_supported_grace_time_cmd, + "graceful-restart helper supported-grace-time (10-1800)$interval", + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Supported grace timer\n" + "Grace interval(in seconds)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_supported_gracetime_set(ospf, interval); + return CMD_SUCCESS; +} + +DEFPY(no_ospf_gr_helper_supported_grace_time, + no_ospf_gr_helper_supported_grace_time_cmd, + "no graceful-restart helper supported-grace-time (10-1800)$interval", + NO_STR + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Supported grace timer\n" + "Grace interval(in seconds)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_supported_gracetime_set(ospf, OSPF_MAX_GRACE_INTERVAL); + return CMD_SUCCESS; +} + +DEFPY(ospf_gr_helper_planned_only, + ospf_gr_helper_planned_only_cmd, + "graceful-restart helper planned-only", + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Supported only planned restart\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_set_supported_planned_only_restart(ospf, OSPF_GR_TRUE); + + return CMD_SUCCESS; +} + +/* External Route Aggregation */ +DEFUN (ospf_external_route_aggregation, + ospf_external_route_aggregation_cmd, + "summary-address A.B.C.D/M [tag (1-4294967295)]", + "External summary address\n" + "Summary address prefix\n" + "Router tag \n" + "Router tag value\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct prefix_ipv4 p; + int idx = 1; + route_tag_t tag = 0; + int ret = OSPF_SUCCESS; + + str2prefix_ipv4(argv[idx]->arg, &p); + + if (is_default_prefix4(&p)) { + vty_out(vty, + "Default address shouldn't be configured as summary address.\n"); + return CMD_SUCCESS; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + if (!is_valid_summary_addr(&p)) { + vty_out(vty, "Not a valid summary address.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > 2) + tag = strtoul(argv[idx + 2]->arg, NULL, 10); + + ret = ospf_asbr_external_aggregator_set(ospf, &p, tag); + if (ret == OSPF_INVALID) + vty_out(vty, "Invalid configuration!!\n"); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_external_route_aggregation, + no_ospf_external_route_aggregation_cmd, + "no summary-address A.B.C.D/M [tag (1-4294967295)]", + NO_STR + "External summary address\n" + "Summary address prefix\n" + "Router tag\n" + "Router tag value\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct prefix_ipv4 p; + int idx = 2; + route_tag_t tag = 0; + int ret = OSPF_SUCCESS; + + str2prefix_ipv4(argv[idx]->arg, &p); + + if (is_default_prefix4(&p)) { + vty_out(vty, + "Default address shouldn't be configured as summary address.\n"); + return CMD_SUCCESS; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + if (!is_valid_summary_addr(&p)) { + vty_out(vty, "Not a valid summary address.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + if (argc > 3) + tag = strtoul(argv[idx + 2]->arg, NULL, 10); + + ret = ospf_asbr_external_aggregator_unset(ospf, &p, tag); + if (ret == OSPF_INVALID) + vty_out(vty, "Invalid configuration!!\n"); + + return CMD_SUCCESS; +} + +DEFPY(no_ospf_gr_helper_planned_only, + no_ospf_gr_helper_planned_only_cmd, + "no graceful-restart helper planned-only", + NO_STR + "OSPF Graceful Restart\n" + "OSPF GR Helper\n" + "Supported only for planned restart\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_gr_helper_set_supported_planned_only_restart(ospf, OSPF_GR_FALSE); + + return CMD_SUCCESS; +} + +static int ospf_print_vty_helper_dis_rtr_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct advRtr *rtr = bucket->data; + struct vty *vty = (struct vty *)arg; + static unsigned int count; + + vty_out(vty, "%-6pI4,", &rtr->advRtrAddr); + count++; + + if (count % 5 == 0) + vty_out(vty, "\n"); + + return HASHWALK_CONTINUE; +} + +static int ospf_print_json_helper_enabled_rtr_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct advRtr *rtr = bucket->data; + struct json_object *json_rid_array = arg; + struct json_object *json_rid; + + json_rid = json_object_new_object(); + + json_object_string_addf(json_rid, "routerId", "%pI4", &rtr->advRtrAddr); + json_object_array_add(json_rid_array, json_rid); + + return HASHWALK_CONTINUE; +} + +static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, + uint8_t use_vrf, json_object *json, + bool uj, bool detail) +{ + struct listnode *node; + struct ospf_interface *oi; + char buf[PREFIX_STRLEN]; + json_object *json_vrf = NULL; + + if (uj) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + if (ospf->instance) { + if (uj) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (uj) { + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + /* Show Router ID. */ + if (uj) { + json_object_string_add(json_vrf, "routerId", + inet_ntop(AF_INET, &ospf->router_id, + buf, sizeof(buf))); + } else { + vty_out(vty, "\n OSPF Router with ID (%pI4)\n\n", + &ospf->router_id); + } + + if (!uj) { + + if (ospf->is_helper_supported) + vty_out(vty, + " Graceful restart helper support enabled.\n"); + else + vty_out(vty, + " Graceful restart helper support disabled.\n"); + + if (ospf->strict_lsa_check) + vty_out(vty, " Strict LSA check is enabled.\n"); + else + vty_out(vty, " Strict LSA check is disabled.\n"); + + if (ospf->only_planned_restart) + vty_out(vty, + " Helper supported for planned restarts only.\n"); + else + vty_out(vty, + " Helper supported for Planned and Unplanned Restarts.\n"); + + vty_out(vty, + " Supported Graceful restart interval: %d(in seconds).\n", + ospf->supported_grace_time); + + if (OSPF_HELPER_ENABLE_RTR_COUNT(ospf)) { + vty_out(vty, " Enable Router list:\n"); + vty_out(vty, " "); + hash_walk(ospf->enable_rtr_list, + ospf_print_vty_helper_dis_rtr_walkcb, vty); + vty_out(vty, "\n\n"); + } + + if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE) { + vty_out(vty, " Last Helper exit Reason :%s\n", + ospf_exit_reason2str(ospf->last_exit_reason)); + } + + if (ospf->active_restarter_cnt) + vty_out(vty, + " Number of Active neighbours in graceful restart: %d\n", + ospf->active_restarter_cnt); + else + vty_out(vty, "\n"); + + } else { + json_object_string_add( + json_vrf, "helperSupport", + (ospf->is_helper_supported) ? "Enabled" : "Disabled"); + json_object_string_add(json_vrf, "strictLsaCheck", + (ospf->strict_lsa_check) ? "Enabled" + : "Disabled"); +#if CONFDATE > 20240401 + CPP_NOTICE("Remove deprecated json key: restartSupoort") +#endif + json_object_string_add( + json_vrf, "restartSupoort", + (ospf->only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + + json_object_string_add( + json_vrf, "restartSupport", + (ospf->only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + + json_object_int_add(json_vrf, "supportedGracePeriod", + ospf->supported_grace_time); + + if (ospf->last_exit_reason != OSPF_GR_HELPER_EXIT_NONE) + json_object_string_add( + json_vrf, "lastExitReason", + ospf_exit_reason2str(ospf->last_exit_reason)); + + if (ospf->active_restarter_cnt) + json_object_int_add(json_vrf, "activeRestarterCnt", + ospf->active_restarter_cnt); + + if (OSPF_HELPER_ENABLE_RTR_COUNT(ospf)) { + struct json_object *json_rid_array = + json_object_new_array(); + + json_object_object_add(json_vrf, "enabledRouterIds", + json_rid_array); + + hash_walk(ospf->enable_rtr_list, + ospf_print_json_helper_enabled_rtr_walkcb, + json_rid_array); + } + } + + + if (detail) { + int cnt = 1; + json_object *json_neighbors = NULL; + + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) { + struct route_node *rn; + struct ospf_neighbor *nbr; + json_object *json_neigh; + + if (ospf_interface_neighbor_count(oi) == 0) + continue; + + if (uj) { + json_object_object_get_ex(json_vrf, "neighbors", + &json_neighbors); + if (!json_neighbors) { + json_neighbors = + json_object_new_object(); + json_object_object_add(json_vrf, + "neighbors", + json_neighbors); + } + } + + for (rn = route_top(oi->nbrs); rn; + rn = route_next(rn)) { + + if (!rn->info) + continue; + + nbr = rn->info; + + if (!OSPF_GR_IS_ACTIVE_HELPER(nbr)) + continue; + + if (!uj) { + vty_out(vty, " Neighbour %d :\n", cnt); + vty_out(vty, " Address : %pI4\n", + &nbr->address.u.prefix4); + vty_out(vty, " Routerid : %pI4\n", + &nbr->router_id); + vty_out(vty, + " Received Grace period : %d(in seconds).\n", + nbr->gr_helper_info + .recvd_grace_period); + vty_out(vty, + " Actual Grace period : %d(in seconds)\n", + nbr->gr_helper_info + .actual_grace_period); + vty_out(vty, + " Remaining GraceTime:%ld(in seconds).\n", + event_timer_remain_second( + nbr->gr_helper_info + .t_grace_timer)); + vty_out(vty, + " Graceful Restart reason: %s.\n\n", + ospf_restart_reason2str( + nbr->gr_helper_info + .gr_restart_reason)); + cnt++; + } else { + json_neigh = json_object_new_object(); + json_object_string_add( + json_neigh, "srcAddr", + inet_ntop(AF_INET, &nbr->src, + buf, sizeof(buf))); + + json_object_string_add( + json_neigh, "routerid", + inet_ntop(AF_INET, + &nbr->router_id, + buf, sizeof(buf))); + json_object_int_add( + json_neigh, + "recvdGraceInterval", + nbr->gr_helper_info + .recvd_grace_period); + json_object_int_add( + json_neigh, + "actualGraceInterval", + nbr->gr_helper_info + .actual_grace_period); + json_object_int_add( + json_neigh, "remainGracetime", + event_timer_remain_second( + nbr->gr_helper_info + .t_grace_timer)); + json_object_string_add( + json_neigh, "restartReason", + ospf_restart_reason2str( + nbr->gr_helper_info + .gr_restart_reason)); + json_object_object_add( + json_neighbors, + inet_ntop(AF_INET, &nbr->src, + buf, sizeof(buf)), + json_neigh); + } + } + } + } + return CMD_SUCCESS; +} + +DEFUN (ospf_external_route_aggregation_no_adrvertise, + ospf_external_route_aggregation_no_adrvertise_cmd, + "summary-address A.B.C.D/M no-advertise", + "External summary address\n" + "Summary address prefix\n" + "Don't advertise summary route \n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct prefix_ipv4 p; + int idx = 1; + int ret = OSPF_SUCCESS; + + str2prefix_ipv4(argv[idx]->arg, &p); + + if (is_default_prefix4(&p)) { + vty_out(vty, + "Default address shouldn't be configured as summary address.\n"); + return CMD_SUCCESS; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + if (!is_valid_summary_addr(&p)) { + vty_out(vty, "Not a valid summary address.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = ospf_asbr_external_rt_no_advertise(ospf, &p); + if (ret == OSPF_INVALID) + vty_out(vty, "Invalid configuration!!\n"); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf_external_route_aggregation_no_adrvertise, + no_ospf_external_route_aggregation_no_adrvertise_cmd, + "no summary-address A.B.C.D/M no-advertise", + NO_STR + "External summary address\n" + "Summary address prefix\n" + "Advertise summary route to the AS \n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct prefix_ipv4 p; + int idx = 2; + int ret = OSPF_SUCCESS; + + str2prefix_ipv4(argv[idx]->arg, &p); + + if (is_default_prefix4(&p)) { + vty_out(vty, + "Default address shouldn't be configured as summary address.\n"); + return CMD_SUCCESS; + } + + /* Apply mask for given prefix. */ + apply_mask(&p); + + if (!is_valid_summary_addr(&p)) { + vty_out(vty, "Not a valid summary address.\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + ret = ospf_asbr_external_rt_advertise(ospf, &p); + if (ret == OSPF_INVALID) + vty_out(vty, "Invalid configuration!!\n"); + + return CMD_SUCCESS; +} + +DEFUN (ospf_route_aggregation_timer, + ospf_route_aggregation_timer_cmd, + "aggregation timer (5-1800)", + "External route aggregation\n" + "Delay timer (in seconds)\n" + "Timer interval(in seconds)\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + uint16_t interval = 0; + + interval = strtoul(argv[2]->arg, NULL, 10); + + ospf_external_aggregator_timer_set(ospf, interval); + + return CMD_SUCCESS; +} + +DEFPY (show_ip_ospf_gr_helper, + show_ip_ospf_gr_helper_cmd, + "show ip ospf [vrf <NAME|all>] graceful-restart helper [detail] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "OSPF Graceful Restart\n" + "Helper details in the router\n" + "Detailed information\n" + JSON_STR) +{ + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int idx_vrf = 0; + int idx = 0; + uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + struct ospf *ospf = NULL; + json_object *json = NULL; + struct listnode *node = NULL; + int inst = 0; + bool detail = false; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided */ + if (vrf_name) { + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ret = ospf_show_gr_helper_details( + vty, ospf, use_vrf, json, uj, detail); + } + + if (uj) + vty_json(vty, json); + + return ret; + } + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + } else { + /* Default Vrf */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + } + + if (ospf == NULL || !ospf->oi_running) { + + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", vrf_name ? vrf_name : "default"); + + return CMD_SUCCESS; + } + + ospf_show_gr_helper_details(vty, ospf, use_vrf, json, uj, detail); + if (uj) + vty_json(vty, json); + + return CMD_SUCCESS; +} +/* Graceful Restart HELPER commands end */ +DEFUN (no_ospf_route_aggregation_timer, + no_ospf_route_aggregation_timer_cmd, + "no aggregation timer", + NO_STR + "External route aggregation\n" + "Delay timer\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + + ospf_external_aggregator_timer_set(ospf, OSPF_EXTL_AGGR_DEFAULT_DELAY); + + return CMD_SUCCESS; +} + +/* External Route Aggregation End */ + +static void config_write_stub_router(struct vty *vty, struct ospf *ospf) +{ + if (ospf->stub_router_startup_time != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, " max-metric router-lsa on-startup %u\n", + ospf->stub_router_startup_time); + if (ospf->stub_router_shutdown_time != OSPF_STUB_ROUTER_UNCONFIGURED) + vty_out(vty, " max-metric router-lsa on-shutdown %u\n", + ospf->stub_router_shutdown_time); + if (ospf->stub_router_admin_set == OSPF_STUB_ROUTER_ADMINISTRATIVE_SET) + vty_out(vty, " max-metric router-lsa administrative\n"); + + return; +} + +static void show_ip_ospf_route_network(struct vty *vty, struct ospf *ospf, + struct route_table *rt, + json_object *json, bool detail) +{ + struct route_node *rn; + struct ospf_route * or ; + struct listnode *pnode, *pnnode; + struct ospf_path *path; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; + + if (!json) + vty_out(vty, + "============ OSPF network routing table ============\n"); + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + char buf1[PREFIX2STR_BUFFER]; + + if ((or = rn->info) == NULL) + continue; + + prefix2str(&rn->p, buf1, sizeof(buf1)); + + if (json) { + json_route = json_object_new_object(); + json_object_object_add(json, buf1, json_route); + } + + switch (or->path_type) { + case OSPF_PATH_INTER_AREA: + if (or->type == OSPF_DESTINATION_NETWORK) { + if (json) { + json_object_string_add(json_route, + "routeType", + "N IA"); + json_object_int_add(json_route, "cost", + or->cost); + json_object_string_addf( + json_route, "area", "%pI4", + &or->u.std.area_id); + } else { + vty_out(vty, + "N IA %-18s [%d] area: %pI4\n", + buf1, or->cost, + &or->u.std.area_id); + } + } else if (or->type == OSPF_DESTINATION_DISCARD) { + if (json) { + json_object_string_add(json_route, + "routeType", + "D IA"); + } else { + vty_out(vty, + "D IA %-18s Discard entry\n", + buf1); + } + } + break; + case OSPF_PATH_INTRA_AREA: + if (json) { + json_object_string_add(json_route, "routeType", + "N"); + json_object_boolean_add(json_route, "transit", + or->u.std.transit); + json_object_int_add(json_route, "cost", + or->cost); + json_object_string_addf(json_route, "area", + "%pI4", + &or->u.std.area_id); + } else { + vty_out(vty, "N %s %-18s [%d] area: %pI4\n", + or->u.std.transit && detail ? "T" : " ", + buf1, or->cost, &or->u.std.area_id); + } + break; + default: + break; + } + + if (or->type == OSPF_DESTINATION_NETWORK) { + if (json) { + json_nexthop_array = json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS(or->paths, pnode, pnnode, + path)) { + if (json) { + json_nexthop = json_object_new_object(); + json_object_array_add( + json_nexthop_array, + json_nexthop); + } + if (if_lookup_by_index(path->ifindex, + ospf->vrf_id)) { + + if (path->nexthop.s_addr + == INADDR_ANY) { + if (json) { + json_object_string_add( + json_nexthop, + "ip", " "); + json_object_string_add( + json_nexthop, + "directlyAttachedTo", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_addf( + json_nexthop, + "ip", "%pI4", + &path->nexthop); + json_object_string_add( + json_nexthop, + "via", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + json_object_string_addf( + json_nexthop, + "advertisedRouter", + "%pI4", + &path->adv_router); + } else { + vty_out(vty, + "%24s via %pI4, %s\n", + "", + &path->nexthop, + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + if (detail && !json) + vty_out(vty, + "%24s adv %pI4\n", + "", + &path->adv_router); + } + } + } + } + } + if (!json) + vty_out(vty, "\n"); +} + +static void show_ip_ospf_route_router(struct vty *vty, struct ospf *ospf, + struct route_table *rtrs, + json_object *json) +{ + struct route_node *rn; + struct ospf_route * or ; + struct listnode *pnode; + struct listnode *node; + struct ospf_path *path; + char buf[PREFIX_STRLEN]; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; + + if (!json) + vty_out(vty, "============ OSPF %s table =============\n", + ospf->all_rtrs == rtrs ? "reachable routers" + : "router routing"); + + for (rn = route_top(rtrs); rn; rn = route_next(rn)) { + if (rn->info == NULL) + continue; + int flag = 0; + + if (json) { + json_route = json_object_new_object(); + json_object_object_add( + json, inet_ntop(AF_INET, &rn->p.u.prefix4, + buf, sizeof(buf)), + json_route); + json_object_string_add(json_route, "routeType", "R "); + } else { + vty_out(vty, "R %-15pI4 ", + &rn->p.u.prefix4); + } + + for (ALL_LIST_ELEMENTS_RO((struct list *)rn->info, node, or)) { + if (flag++) { + if (!json) + vty_out(vty, "%24s", ""); + } + + /* Show path. */ + if (json) { + json_object_int_add(json_route, "cost", + or->cost); + json_object_string_addf(json_route, "area", + "%pI4", + &or->u.std.area_id); + if (or->path_type == OSPF_PATH_INTER_AREA) { + json_object_boolean_true_add(json_route, + "IA"); + json_object_boolean_true_add(json_route, + "ia"); + } + if (or->u.std.flags & ROUTER_LSA_BORDER) + json_object_string_add(json_route, + "routerType", + "abr"); + else if (or->u.std.flags & ROUTER_LSA_EXTERNAL) + json_object_string_add(json_route, + "routerType", + "asbr"); + } else { + vty_out(vty, "%s [%d] area: %pI4", + (or->path_type == OSPF_PATH_INTER_AREA + ? "IA" + : " "), + or->cost, &or->u.std.area_id); + /* Show flags. */ + vty_out(vty, "%s%s\n", + (or->u.std.flags & ROUTER_LSA_BORDER + ? ", ABR" + : ""), + (or->u.std.flags & ROUTER_LSA_EXTERNAL + ? ", ASBR" + : "")); + } + + if (json) { + json_nexthop_array = json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS_RO(or->paths, pnode, path)) { + if (json) { + json_nexthop = json_object_new_object(); + json_object_array_add( + json_nexthop_array, + json_nexthop); + } + if (if_lookup_by_index(path->ifindex, + ospf->vrf_id)) { + if (path->nexthop.s_addr + == INADDR_ANY) { + if (json) { + json_object_string_add( + json_nexthop, + "ip", " "); + json_object_string_add( + json_nexthop, + "directlyAttachedTo", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_addf( + json_nexthop, + "ip", "%pI4", + &path->nexthop); + json_object_string_add( + json_nexthop, + "via", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s via %pI4, %s\n", + "", + &path->nexthop, + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } + } + } + } + } + if (!json) + vty_out(vty, "\n"); +} + +static void show_ip_ospf_route_external(struct vty *vty, struct ospf *ospf, + struct route_table *rt, + json_object *json, bool detail) +{ + struct route_node *rn; + struct ospf_route *er; + struct listnode *pnode, *pnnode; + struct ospf_path *path; + json_object *json_route = NULL, *json_nexthop_array = NULL, + *json_nexthop = NULL; + + if (!json) + vty_out(vty, + "============ OSPF external routing table ===========\n"); + + for (rn = route_top(rt); rn; rn = route_next(rn)) { + if ((er = rn->info) == NULL) + continue; + + char buf1[19]; + + snprintfrr(buf1, sizeof(buf1), "%pFX", &rn->p); + if (json) { + json_route = json_object_new_object(); + json_object_object_add(json, buf1, json_route); + } + + switch (er->path_type) { + case OSPF_PATH_TYPE1_EXTERNAL: + if (json) { + json_object_string_add(json_route, "routeType", + "N E1"); + json_object_int_add(json_route, "cost", + er->cost); + json_object_int_add(json_route, "tag", + er->u.ext.tag); + } else { + vty_out(vty, + "N E1 %-18s [%d] tag: %" ROUTE_TAG_PRI + "\n", + buf1, er->cost, er->u.ext.tag); + } + break; + case OSPF_PATH_TYPE2_EXTERNAL: + if (json) { + json_object_string_add(json_route, "routeType", + "N E2"); + json_object_int_add(json_route, "cost", + er->cost); + json_object_int_add(json_route, "type2cost", + er->u.ext.type2_cost); + json_object_int_add(json_route, "tag", + er->u.ext.tag); + } else { + vty_out(vty, + "N E2 %-18s [%d/%d] tag: %" ROUTE_TAG_PRI + "\n", + buf1, er->cost, er->u.ext.type2_cost, + er->u.ext.tag); + } + break; + } + + if (json) { + json_nexthop_array = json_object_new_array(); + json_object_object_add(json_route, "nexthops", + json_nexthop_array); + } + + for (ALL_LIST_ELEMENTS(er->paths, pnode, pnnode, path)) { + if (json) { + json_nexthop = json_object_new_object(); + json_object_array_add(json_nexthop_array, + json_nexthop); + } + + if (if_lookup_by_index(path->ifindex, ospf->vrf_id)) { + if (path->nexthop.s_addr == INADDR_ANY) { + if (json) { + json_object_string_add( + json_nexthop, "ip", + " "); + json_object_string_add( + json_nexthop, + "directlyAttachedTo", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } else { + vty_out(vty, + "%24s directly attached to %s\n", + "", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + } else { + if (json) { + json_object_string_addf( + json_nexthop, "ip", + "%pI4", &path->nexthop); + json_object_string_add( + json_nexthop, "via", + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + json_object_string_addf( + json_nexthop, + "advertisedRouter", + "%pI4", + &path->adv_router); + } else { + vty_out(vty, + "%24s via %pI4, %s\n", + "", + &path->nexthop, + ifindex2ifname( + path->ifindex, + ospf->vrf_id)); + } + if (detail && !json) + vty_out(vty, + "%24s adv %pI4\n", "", + &path->adv_router); + } + } + } + } + if (!json) + vty_out(vty, "\n"); +} + +static int show_ip_ospf_reachable_routers_common(struct vty *vty, + struct ospf *ospf, + uint8_t use_vrf) +{ + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + + ospf_show_vrf_name(ospf, vty, NULL, use_vrf); + + if (ospf->all_rtrs == NULL) { + vty_out(vty, "No OSPF reachable router information exist\n"); + return CMD_SUCCESS; + } + + /* Show Router routes. */ + show_ip_ospf_route_router(vty, ospf, ospf->all_rtrs, NULL); + + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_reachable_routers, + show_ip_ospf_reachable_routers_cmd, + "show ip ospf [vrf <NAME|all>] reachable-routers", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Show all the reachable OSPF routers\n") +{ + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (vrf_name) { + bool ospf_output = false; + + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ospf_output = true; + ret = show_ip_ospf_reachable_routers_common( + vty, ospf, use_vrf); + } + + if (!ospf_output) + vty_out(vty, "%% OSPF instance not found\n"); + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; + } + + ret = show_ip_ospf_reachable_routers_common(vty, ospf, + use_vrf); + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + vty_out(vty, "%% OSPF instance not found\n"); + return CMD_SUCCESS; + } + + ret = show_ip_ospf_reachable_routers_common(vty, ospf, use_vrf); + } + + return ret; +} + +DEFUN (show_ip_ospf_instance_reachable_routers, + show_ip_ospf_instance_reachable_routers_cmd, + "show ip ospf (1-65535) reachable-routers", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Show all the reachable OSPF routers\n") +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + return show_ip_ospf_reachable_routers_common(vty, ospf, 0); +} + +static int show_ip_ospf_border_routers_common(struct vty *vty, + struct ospf *ospf, + uint8_t use_vrf, + json_object *json) +{ + json_object *json_vrf = NULL; + json_object *json_router = NULL; + + if (json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + json_router = json_object_new_object(); + } + + if (ospf->instance) { + if (!json) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + else + json_object_int_add(json_vrf, "ospfInstance", + ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (ospf->new_table == NULL) { + if (!json) + vty_out(vty, "No OSPF routing information exist\n"); + else { + json_object_free(json_router); + if (use_vrf) + json_object_free(json_vrf); + } + return CMD_SUCCESS; + } + + /* Show Network routes. + show_ip_ospf_route_network (vty, ospf->new_table); */ + + /* Show Router routes. */ + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, json_router); + + if (json) { + json_object_object_add(json_vrf, "routers", json_router); + if (use_vrf) { + if (ospf->vrf_id == VRF_DEFAULT) + json_object_object_add(json, "default", + json_vrf); + else + json_object_object_add(json, ospf->name, + json_vrf); + } + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + +DEFPY (show_ip_ospf_border_routers, + show_ip_ospf_border_routers_cmd, + "show ip ospf [vrf <NAME|all>] border-routers [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Show all the ABR's and ASBR's\n" + JSON_STR) +{ + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (vrf_name) { + bool ospf_output = false; + + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ospf_output = true; + ret = show_ip_ospf_border_routers_common( + vty, ospf, use_vrf, json); + } + + if (uj) + vty_json(vty, json); + else if (!ospf_output) + vty_out(vty, "%% OSPF is not enabled\n"); + + return ret; + } else { + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_border_routers_common(vty, ospf, use_vrf, + json); + if (uj) + vty_json(vty, json); + } + + return ret; +} + +DEFUN (show_ip_ospf_instance_border_routers, + show_ip_ospf_instance_border_routers_cmd, + "show ip ospf (1-65535) border-routers", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Show all the ABR's and ASBR's\n") +{ + int idx_number = 3; + struct ospf *ospf; + unsigned short instance = 0; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + return show_ip_ospf_border_routers_common(vty, ospf, 0, NULL); +} + +static int show_ip_ospf_route_common(struct vty *vty, struct ospf *ospf, + json_object *json, uint8_t use_vrf, + bool detail) +{ + json_object *json_vrf = NULL; + + if (ospf->instance) + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + + + if (json) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (ospf->new_table == NULL) { + if (json) { + if (use_vrf) + json_object_free(json_vrf); + } else { + vty_out(vty, "No OSPF routing information exist\n"); + } + return CMD_SUCCESS; + } + + if (detail && json == NULL) { + vty_out(vty, "Codes: N - network T - transitive\n"); + vty_out(vty, " IA - inter-area E - external route\n"); + vty_out(vty, " D - destination R - router\n\n"); + } + + /* Show Network routes. */ + show_ip_ospf_route_network(vty, ospf, ospf->new_table, json_vrf, + detail); + + /* Show Router routes. */ + show_ip_ospf_route_router(vty, ospf, ospf->new_rtrs, json_vrf); + + /* Show Router routes. */ + if (ospf->all_rtrs) + show_ip_ospf_route_router(vty, ospf, ospf->all_rtrs, json_vrf); + + /* Show AS External routes. */ + show_ip_ospf_route_external(vty, ospf, ospf->old_external_route, + json_vrf, detail); + + if (json) { + if (use_vrf) { + // json_object_object_add(json_vrf, "areas", + // json_areas); + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } + } else { + vty_out(vty, "\n"); + } + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_route, + show_ip_ospf_route_cmd, + "show ip ospf [vrf <NAME|all>] route [detail] [json]", + SHOW_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "OSPF routing table\n" + "Detailed information\n" + JSON_STR) +{ + struct ospf *ospf = NULL; + struct listnode *node = NULL; + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int inst = 0; + int idx = 0; + int idx_vrf = 0; + uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + bool detail = false; + json_object *json = NULL; + + if (uj) + json = json_object_new_object(); + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + /* vrf input is provided could be all or specific vrf*/ + if (vrf_name) { + bool ospf_output = false; + + use_vrf = 1; + + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ospf_output = true; + ret = show_ip_ospf_route_common( + vty, ospf, json, use_vrf, detail); + } + + if (uj) { + /* Keep Non-pretty format */ + vty_json(vty, json); + } else if (!ospf_output) + vty_out(vty, "%% OSPF is not enabled\n"); + + return ret; + } + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + } else { + /* Display default ospf (instance 0) info */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + } + + if (ospf) { + ret = show_ip_ospf_route_common(vty, ospf, json, use_vrf, + detail); + /* Keep Non-pretty format */ + if (uj) + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_NOSLASHESCAPE)); + } + + if (uj) + json_object_free(json); + + return ret; +} + +DEFUN (show_ip_ospf_instance_route, + show_ip_ospf_instance_route_cmd, + "show ip ospf (1-65535) route [detail]", + SHOW_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "OSPF routing table\n" + "Detailed information\n") +{ + int idx_number = 3; + int idx = 0; + struct ospf *ospf; + unsigned short instance = 0; + bool detail = false; + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + instance = strtoul(argv[idx_number]->arg, NULL, 10); + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + + ospf = ospf_lookup_instance(instance); + if (!ospf || !ospf->oi_running) + return CMD_SUCCESS; + + return show_ip_ospf_route_common(vty, ospf, NULL, 0, detail); +} + + +DEFUN (show_ip_ospf_vrfs, + show_ip_ospf_vrfs_cmd, + "show ip ospf vrfs [json]", + SHOW_STR + IP_STR + "OSPF information\n" + "Show OSPF VRFs \n" + JSON_STR) +{ + bool uj = use_json(argc, argv); + json_object *json = NULL; + json_object *json_vrfs = NULL; + struct ospf *ospf = NULL; + struct listnode *node = NULL; + int count = 0; + static const char header[] = "Name Id RouterId "; + + if (uj) { + json = json_object_new_object(); + json_vrfs = json_object_new_object(); + } + + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + json_object *json_vrf = NULL; + const char *name = NULL; + int64_t vrf_id_ui = 0; + + count++; + + if (!uj && count == 1) + vty_out(vty, "%s\n", header); + if (uj) + json_vrf = json_object_new_object(); + + name = ospf_get_name(ospf); + + vrf_id_ui = (ospf->vrf_id == VRF_UNKNOWN) + ? -1 + : (int64_t)ospf->vrf_id; + + if (uj) { + json_object_int_add(json_vrf, "vrfId", vrf_id_ui); + json_object_string_addf(json_vrf, "routerId", "%pI4", + &ospf->router_id); + + json_object_object_add(json_vrfs, name, json_vrf); + + } else { + vty_out(vty, "%-25s %-5d %-16pI4 \n", name, + ospf->vrf_id, &ospf->router_id); + } + } + + if (uj) { + json_object_object_add(json, "vrfs", json_vrfs); + json_object_int_add(json, "totalVrfs", count); + + vty_json(vty, json); + } else { + if (count) + vty_out(vty, "\nTotal number of OSPF VRFs: %d\n", + count); + } + + return CMD_SUCCESS; +} +DEFPY (clear_ip_ospf_neighbor, + clear_ip_ospf_neighbor_cmd, + "clear ip ospf [(1-65535)]$instance neighbor [A.B.C.D$nbr_id]", + CLEAR_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Reset OSPF Neighbor\n" + "Neighbor ID\n") +{ + struct listnode *node; + struct ospf *ospf = NULL; + + /* If user does not specify the arguments, + * instance = 0 and nbr_id = 0.0.0.0 + */ + if (instance != 0) { + /* This means clear only the particular ospf process */ + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + } + + /* Clear all the ospf processes */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + if (nbr_id_str && IPV4_ADDR_SAME(&ospf->router_id, &nbr_id)) { + vty_out(vty, "Self router-id is not allowed.\r\n "); + return CMD_SUCCESS; + } + + ospf_neighbor_reset(ospf, nbr_id, nbr_id_str); + } + + return CMD_SUCCESS; +} + +DEFPY (clear_ip_ospf_process, + clear_ip_ospf_process_cmd, + "clear ip ospf [(1-65535)]$instance process", + CLEAR_STR + IP_STR + "OSPF information\n" + "Instance ID\n" + "Reset OSPF Process\n") +{ + struct listnode *node; + struct ospf *ospf = NULL; + + /* Check if instance is not passed as an argument */ + if (instance != 0) { + /* This means clear only the particular ospf process */ + if (instance != ospf_instance) + return CMD_NOT_MY_INSTANCE; + } + + /* Clear all the ospf processes */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + + ospf_process_reset(ospf); + } + + return CMD_SUCCESS; +} + +static const char *const ospf_abr_type_str[] = { + "unknown", "standard", "ibm", "cisco", "shortcut" +}; + +static const char *const ospf_shortcut_mode_str[] = { + "default", "enable", "disable" +}; +static int ospf_vty_external_rt_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct external_info *ei = bucket->data; + struct vty *vty = (struct vty *)arg; + static unsigned int count; + + vty_out(vty, "%-4pI4/%d, ", &ei->p.prefix, ei->p.prefixlen); + count++; + + if (count % 5 == 0) + vty_out(vty, "\n"); + + if (OSPF_EXTERNAL_RT_COUNT(ei->aggr_route) == count) + count = 0; + + return HASHWALK_CONTINUE; +} + +static int ospf_json_external_rt_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct external_info *ei = bucket->data; + struct json_object *json = (struct json_object *)arg; + char buf[PREFIX2STR_BUFFER]; + char exnalbuf[20]; + static unsigned int count; + + prefix2str(&ei->p, buf, sizeof(buf)); + + snprintf(exnalbuf, 20, "Exnl Addr-%d", count); + + json_object_string_add(json, exnalbuf, buf); + + count++; + + if (OSPF_EXTERNAL_RT_COUNT(ei->aggr_route) == count) + count = 0; + + return HASHWALK_CONTINUE; +} + +static int ospf_show_summary_address(struct vty *vty, struct ospf *ospf, + uint8_t use_vrf, json_object *json, + bool uj, bool detail) +{ + struct route_node *rn; + json_object *json_vrf = NULL; + int mtype = 0; + int mval = 0; + static char header[] = + "Summary-address Metric-type Metric Tag External_Rt_count\n"; + + mtype = metric_type(ospf, 0, ospf->instance); + mval = metric_value(ospf, 0, ospf->instance); + + if (!uj) + vty_out(vty, "%s\n", header); + + if (uj) { + if (use_vrf) + json_vrf = json_object_new_object(); + else + json_vrf = json; + } + + if (ospf->instance) { + if (uj) + json_object_int_add(json, "ospfInstance", + ospf->instance); + else + vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance); + } + + ospf_show_vrf_name(ospf, vty, json_vrf, use_vrf); + + if (!uj) { + vty_out(vty, "aggregation delay interval: %u(in seconds)\n\n", + ospf->aggr_delay_interval); + } else { + json_object_int_add(json_vrf, "aggregationDelayInterval", + ospf->aggr_delay_interval); + } + + for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) + if (rn->info) { + struct ospf_external_aggr_rt *aggr = rn->info; + json_object *json_aggr = NULL; + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&aggr->p, buf, sizeof(buf)); + + if (uj) { + + json_aggr = json_object_new_object(); + + json_object_object_add(json_vrf, buf, + json_aggr); + json_object_string_add(json_aggr, + "summaryAddress", buf); + json_object_string_add( + json_aggr, "metricType", + (mtype == EXTERNAL_METRIC_TYPE_1) + ? "E1" + : "E2"); + + json_object_int_add(json_aggr, "metric", mval); + json_object_int_add(json_aggr, "tag", + aggr->tag); + json_object_int_add( + json_aggr, "externalRouteCount", + OSPF_EXTERNAL_RT_COUNT(aggr)); + + if (OSPF_EXTERNAL_RT_COUNT(aggr) && detail) { + hash_walk( + aggr->match_extnl_hash, + ospf_json_external_rt_walkcb, + json_aggr); + } + + } else { + vty_out(vty, "%-20s", buf); + + (mtype == EXTERNAL_METRIC_TYPE_1) + ? vty_out(vty, "%-16s", "E1") + : vty_out(vty, "%-16s", "E2"); + vty_out(vty, "%-11d", mval); + + vty_out(vty, "%-12u", aggr->tag); + + vty_out(vty, "%-5ld\n", + OSPF_EXTERNAL_RT_COUNT(aggr)); + + if (OSPF_EXTERNAL_RT_COUNT(aggr) && detail) { + vty_out(vty, + "Matched External routes:\n"); + hash_walk( + aggr->match_extnl_hash, + ospf_vty_external_rt_walkcb, + vty); + vty_out(vty, "\n"); + } + + vty_out(vty, "\n"); + } + } + + if (uj) { + if (use_vrf) + json_object_object_add(json, ospf_get_name(ospf), + json_vrf); + } else + vty_out(vty, "\n"); + + return CMD_SUCCESS; +} + +DEFUN (show_ip_ospf_external_aggregator, + show_ip_ospf_external_aggregator_cmd, + "show ip ospf [vrf <NAME|all>] summary-address [detail] [json]", + SHOW_STR IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "All VRFs\n" + "Show external summary addresses\n" + "Detailed information\n" + JSON_STR) +{ + char *vrf_name = NULL; + bool all_vrf = false; + int ret = CMD_SUCCESS; + int idx_vrf = 0; + int idx = 0; + uint8_t use_vrf = 0; + bool uj = use_json(argc, argv); + struct ospf *ospf = NULL; + json_object *json = NULL; + struct listnode *node = NULL; + int inst = 0; + bool detail = false; + + OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf); + + if (argv_find(argv, argc, "detail", &idx)) + detail = true; + + if (uj) + json = json_object_new_object(); + + /* vrf input is provided */ + if (vrf_name) { + use_vrf = 1; + if (all_vrf) { + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (!ospf->oi_running) + continue; + ret = ospf_show_summary_address( + vty, ospf, use_vrf, json, uj, detail); + } + + if (uj) + vty_json(vty, json); + + return ret; + } + + ospf = ospf_lookup_by_inst_name(inst, vrf_name); + + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf %s\n", + vrf_name); + + return CMD_SUCCESS; + } + ospf_show_summary_address(vty, ospf, use_vrf, json, uj, detail); + + } else { + /* Default Vrf */ + ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT); + if (ospf == NULL || !ospf->oi_running) { + if (uj) + vty_json(vty, json); + else + vty_out(vty, + "%% OSPF is not enabled in vrf default\n"); + + return CMD_SUCCESS; + } + + ospf_show_summary_address(vty, ospf, use_vrf, json, uj, detail); + } + + if (uj) + vty_json(vty, json); + return CMD_SUCCESS; +} + +static const char *const ospf_int_type_str[] = { + "unknown", /* should never be used. */ + "point-to-point", + "broadcast", + "non-broadcast", + "point-to-multipoint", + "virtual-link", /* should never be used. */ + "loopback" +}; + +static int interface_config_auth_str(struct ospf_if_params *params, char *buf) +{ + if (!OSPF_IF_PARAM_CONFIGURED(params, auth_type) + || params->auth_type == OSPF_AUTH_NOTSET) + return 0; + + /* Translation tables are not that much help + * here due to syntax + * of the simple option */ + switch (params->auth_type) { + + case OSPF_AUTH_NULL: + snprintf(buf, BUFSIZ, " null"); + break; + + case OSPF_AUTH_SIMPLE: + snprintf(buf, BUFSIZ, " "); + break; + + case OSPF_AUTH_CRYPTOGRAPHIC: + if (OSPF_IF_PARAM_CONFIGURED(params, keychain_name)) + snprintf(buf, BUFSIZ, " key-chain %s", params->keychain_name); + else + snprintf(buf, BUFSIZ, " message-digest"); + break; + } + + return 1; +} + +static int config_write_interface_one(struct vty *vty, struct vrf *vrf) +{ + struct listnode *node; + struct interface *ifp; + struct crypt_key *ck; + struct route_node *rn = NULL; + struct ospf_if_params *params; + char buf[BUFSIZ]; + int ret = 0; + int write = 0; + + FOR_ALL_INTERFACES (vrf, ifp) { + + if (memcmp(ifp->name, "VLINK", 5) == 0) + continue; + + if_vty_config_start(vty, ifp); + + if (ifp->desc) + vty_out(vty, " description %s\n", ifp->desc); + + write++; + + params = IF_DEF_PARAMS(ifp); + + do { + /* Interface Network print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, type) + && params->type != OSPF_IFTYPE_LOOPBACK) { + if (params->type != ospf_default_iftype(ifp)) { + vty_out(vty, " ip ospf network %s", + ospf_int_type_str + [params->type]); + if (params->type + == OSPF_IFTYPE_POINTOPOINT + && params->ptp_dmvpn) + vty_out(vty, " dmvpn"); + if (params->type == + OSPF_IFTYPE_POINTOMULTIPOINT && + params->p2mp_delay_reflood) + vty_out(vty, " delay-reflood"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + } + + /* OSPF interface authentication print */ + ret = interface_config_auth_str(params, buf); + if (ret) { + vty_out(vty, " ip ospf authentication%s", + buf); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Simple Authentication Password print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, auth_simple) + && params->auth_simple[0] != '\0') { + vty_out(vty, " ip ospf authentication-key %s", + params->auth_simple); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Cryptographic Authentication Key print. */ + if (params && params->auth_crypt) { + for (ALL_LIST_ELEMENTS_RO(params->auth_crypt, + node, ck)) { + vty_out(vty, + " ip ospf message-digest-key %d md5 %s", + ck->key_id, ck->auth_key); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + } + + /* Interface Output Cost print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, output_cost_cmd)) { + vty_out(vty, " ip ospf cost %u", + params->output_cost_cmd); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Hello Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, v_hello) + && params->v_hello != OSPF_HELLO_INTERVAL_DEFAULT) { + vty_out(vty, " ip ospf hello-interval %u", + params->v_hello); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + + /* Router Dead Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, v_wait) + && params->is_v_wait_set) { + vty_out(vty, " ip ospf dead-interval "); + + /* fast hello ? */ + if (OSPF_IF_PARAM_CONFIGURED(params, + fast_hello)) + vty_out(vty, + "minimal hello-multiplier %d", + params->fast_hello); + else + vty_out(vty, "%u", params->v_wait); + + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Hello Graceful-Restart Delay print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, + v_gr_hello_delay) && + params->v_gr_hello_delay != + OSPF_HELLO_DELAY_DEFAULT) + vty_out(vty, + " ip ospf graceful-restart hello-delay %u\n", + params->v_gr_hello_delay); + + /* Router Priority print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, priority) + && params->priority + != OSPF_ROUTER_PRIORITY_DEFAULT) { + vty_out(vty, " ip ospf priority %u", + params->priority); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Retransmit Interval print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, + retransmit_interval) + && params->retransmit_interval + != OSPF_RETRANSMIT_INTERVAL_DEFAULT) { + vty_out(vty, " ip ospf retransmit-interval %u", + params->retransmit_interval); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Transmit Delay print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, transmit_delay) + && params->transmit_delay + != OSPF_TRANSMIT_DELAY_DEFAULT) { + vty_out(vty, " ip ospf transmit-delay %u", + params->transmit_delay); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* Area print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) { + if (ospf_instance) + vty_out(vty, " ip ospf %d", + ospf_instance); + else + vty_out(vty, " ip ospf"); + + char buf[INET_ADDRSTRLEN]; + + area_id2str(buf, sizeof(buf), ¶ms->if_area, + params->if_area_id_fmt); + vty_out(vty, " area %s", buf); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* bfd print. */ + if (params && params->bfd_config) + ospf_bfd_write_config(vty, params); + + /* MTU ignore print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, mtu_ignore) + && params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT) { + if (params->mtu_ignore == 0) + vty_out(vty, " no ip ospf mtu-ignore"); + else + vty_out(vty, " ip ospf mtu-ignore"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", + &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + if (OSPF_IF_PARAM_CONFIGURED(params, + passive_interface)) { + vty_out(vty, " %sip ospf passive", + params->passive_interface + == OSPF_IF_ACTIVE + ? "no " + : ""); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* LDP-Sync print */ + if (params && params->ldp_sync_info) + ospf_ldp_sync_if_write_config(vty, params); + + /* Capability opaque print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, opaque_capable) && + params->opaque_capable != + OSPF_OPAQUE_CAPABLE_DEFAULT) { + if (params->opaque_capable == false) + vty_out(vty, + " no ip ospf capability opaque"); + else + vty_out(vty, + " ip ospf capability opaque"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + /* prefix-suppression print. */ + if (OSPF_IF_PARAM_CONFIGURED(params, + prefix_suppression) && + params->prefix_suppression != + OSPF_PREFIX_SUPPRESSION_DEFAULT) { + if (params->prefix_suppression == false) + vty_out(vty, + " no ip ospf prefix-suppression"); + else + vty_out(vty, + " ip ospf prefix-suppression"); + if (params != IF_DEF_PARAMS(ifp) && rn) + vty_out(vty, " %pI4", &rn->p.u.prefix4); + vty_out(vty, "\n"); + } + + while (1) { + if (rn == NULL) + rn = route_top(IF_OIFS_PARAMS(ifp)); + else + rn = route_next(rn); + + if (rn == NULL) + break; + params = rn->info; + if (params != NULL) + break; + } + } while (rn); + + ospf_opaque_config_write_if(vty, ifp); + + if_vty_config_end(vty); + } + + return write; +} + +/* Configuration write function for ospfd. */ +static int config_write_interface(struct vty *vty) +{ + int write = 0; + struct vrf *vrf = NULL; + + /* Display all VRF aware OSPF interface configuration */ + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + write += config_write_interface_one(vty, vrf); + } + + return write; +} + +static int config_write_network_area(struct vty *vty, struct ospf *ospf) +{ + struct route_node *rn; + char buf[INET_ADDRSTRLEN]; + + /* `network area' print. */ + for (rn = route_top(ospf->networks); rn; rn = route_next(rn)) + if (rn->info) { + struct ospf_network *n = rn->info; + + /* Create Area ID string by specified Area ID format. */ + if (n->area_id_fmt == OSPF_AREA_ID_FMT_DOTTEDQUAD) + inet_ntop(AF_INET, &n->area_id, buf, + sizeof(buf)); + else + snprintf(buf, sizeof(buf), "%lu", + (unsigned long int)ntohl( + n->area_id.s_addr)); + + /* Network print. */ + vty_out(vty, " network %pFX area %s\n", &rn->p, buf); + } + + return 0; +} + +static int config_write_ospf_area(struct vty *vty, struct ospf *ospf) +{ + struct listnode *node; + struct ospf_area *area; + char buf[INET_ADDRSTRLEN]; + + /* Area configuration print. */ + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + struct route_node *rn1; + + area_id2str(buf, sizeof(buf), &area->area_id, + area->area_id_fmt); + + if (area->auth_type != OSPF_AUTH_NULL) { + if (area->auth_type == OSPF_AUTH_SIMPLE) + vty_out(vty, " area %s authentication\n", buf); + else + vty_out(vty, + " area %s authentication message-digest\n", + buf); + } + + if (area->shortcut_configured != OSPF_SHORTCUT_DEFAULT) + vty_out(vty, " area %s shortcut %s\n", buf, + ospf_shortcut_mode_str + [area->shortcut_configured]); + + if ((area->external_routing == OSPF_AREA_STUB) + || (area->external_routing == OSPF_AREA_NSSA)) { + if (area->external_routing == OSPF_AREA_STUB) { + vty_out(vty, " area %s stub", buf); + if (area->no_summary) + vty_out(vty, " no-summary\n"); + vty_out(vty, "\n"); + } else if (area->external_routing == OSPF_AREA_NSSA) { + vty_out(vty, " area %s nssa", buf); + + switch (area->NSSATranslatorRole) { + case OSPF_NSSA_ROLE_NEVER: + vty_out(vty, " translate-never"); + break; + case OSPF_NSSA_ROLE_ALWAYS: + vty_out(vty, " translate-always"); + break; + case OSPF_NSSA_ROLE_CANDIDATE: + break; + } + + if (area->nssa_default_originate.enabled) { + vty_out(vty, + " default-information-originate"); + if (area->nssa_default_originate + .metric_value != -1) + vty_out(vty, " metric %d", + area->nssa_default_originate + .metric_value); + if (area->nssa_default_originate + .metric_type != + DEFAULT_METRIC_TYPE) + vty_out(vty, " metric-type 1"); + } + + if (area->no_summary) + vty_out(vty, " no-summary"); + if (area->suppress_fa) + vty_out(vty, " suppress-fa"); + vty_out(vty, "\n"); + + for (rn1 = route_top(area->nssa_ranges); rn1; + rn1 = route_next(rn1)) { + struct ospf_area_range *range; + + range = rn1->info; + if (!range) + continue; + + vty_out(vty, " area %s nssa range %pFX", + buf, &rn1->p); + + if (range->cost_config != + OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %u", + range->cost_config); + + if (!CHECK_FLAG( + range->flags, + OSPF_AREA_RANGE_ADVERTISE)) + vty_out(vty, " not-advertise"); + + vty_out(vty, "\n"); + } + } + + if (area->default_cost != 1) + vty_out(vty, " area %s default-cost %d\n", buf, + area->default_cost); + } + + for (rn1 = route_top(area->ranges); rn1; rn1 = route_next(rn1)) + if (rn1->info) { + struct ospf_area_range *range = rn1->info; + + vty_out(vty, " area %s range %pFX", buf, + &rn1->p); + + if (range->cost_config + != OSPF_AREA_RANGE_COST_UNSPEC) + vty_out(vty, " cost %d", + range->cost_config); + + if (!CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_ADVERTISE)) + vty_out(vty, " not-advertise"); + + if (CHECK_FLAG(range->flags, + OSPF_AREA_RANGE_SUBSTITUTE)) + vty_out(vty, " substitute %pI4/%d", + &range->subst_addr, + range->subst_masklen); + + vty_out(vty, "\n"); + } + + if (EXPORT_NAME(area)) + vty_out(vty, " area %s export-list %s\n", buf, + EXPORT_NAME(area)); + + if (IMPORT_NAME(area)) + vty_out(vty, " area %s import-list %s\n", buf, + IMPORT_NAME(area)); + + if (PREFIX_NAME_IN(area)) + vty_out(vty, " area %s filter-list prefix %s in\n", buf, + PREFIX_NAME_IN(area)); + + if (PREFIX_NAME_OUT(area)) + vty_out(vty, " area %s filter-list prefix %s out\n", + buf, PREFIX_NAME_OUT(area)); + + if (area->fr_info.configured) + vty_out(vty, " area %s flood-reduction\n", buf); + } + + return 0; +} + +static int config_write_ospf_nbr_nbma(struct vty *vty, struct ospf *ospf) +{ + struct ospf_nbr_nbma *nbr_nbma; + struct route_node *rn; + + /* Static Neighbor configuration print. */ + for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn)) + if ((nbr_nbma = rn->info)) { + vty_out(vty, " neighbor %pI4", &nbr_nbma->addr); + + if (nbr_nbma->priority + != OSPF_NEIGHBOR_PRIORITY_DEFAULT) + vty_out(vty, " priority %d", + nbr_nbma->priority); + + if (nbr_nbma->v_poll != OSPF_POLL_INTERVAL_DEFAULT) + vty_out(vty, " poll-interval %d", + nbr_nbma->v_poll); + + vty_out(vty, "\n"); + } + + return 0; +} + +static int config_write_virtual_link(struct vty *vty, struct ospf *ospf) +{ + struct listnode *node; + struct ospf_vl_data *vl_data; + char buf[INET_ADDRSTRLEN]; + char buf2[BUFSIZ]; + int ret = 0; + + /* Virtual-Link print */ + for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) { + struct listnode *n2; + struct crypt_key *ck; + struct ospf_interface *oi; + + if (vl_data != NULL) { + area_id2str(buf, sizeof(buf), &vl_data->vl_area_id, + vl_data->vl_area_id_fmt); + oi = vl_data->vl_oi; + + /* timers */ + if (OSPF_IF_PARAM(oi, v_hello) + != OSPF_HELLO_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, v_wait) + != OSPF_ROUTER_DEAD_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, retransmit_interval) + != OSPF_RETRANSMIT_INTERVAL_DEFAULT + || OSPF_IF_PARAM(oi, transmit_delay) + != OSPF_TRANSMIT_DELAY_DEFAULT) + vty_out(vty, + " area %s virtual-link %pI4 hello-interval %d retransmit-interval %d transmit-delay %d dead-interval %d\n", + buf, &vl_data->vl_peer, + OSPF_IF_PARAM(oi, v_hello), + OSPF_IF_PARAM(oi, retransmit_interval), + OSPF_IF_PARAM(oi, transmit_delay), + OSPF_IF_PARAM(oi, v_wait)); + else + vty_out(vty, " area %s virtual-link %pI4\n", buf, + &vl_data->vl_peer); + /* Auth type */ + ret = interface_config_auth_str( + IF_DEF_PARAMS(oi->ifp), buf2); + if (ret) + vty_out(vty, + " area %s virtual-link %pI4 authentication%s\n", + buf, &vl_data->vl_peer, buf2); + /* Auth key */ + if (IF_DEF_PARAMS(vl_data->vl_oi->ifp)->auth_simple[0] + != '\0') + vty_out(vty, + " area %s virtual-link %pI4 authentication-key %s\n", + buf, &vl_data->vl_peer, + IF_DEF_PARAMS(vl_data->vl_oi->ifp) + ->auth_simple); + /* md5 keys */ + for (ALL_LIST_ELEMENTS_RO( + IF_DEF_PARAMS(vl_data->vl_oi->ifp) + ->auth_crypt, + n2, ck)) + vty_out(vty, + " area %s virtual-link %pI4 message-digest-key %d md5 %s\n", + buf, &vl_data->vl_peer, + ck->key_id, ck->auth_key); + } + } + + return 0; +} + + +static int config_write_ospf_redistribute(struct vty *vty, struct ospf *ospf) +{ + int type; + + /* redistribute print. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + struct list *red_list; + struct listnode *node; + struct ospf_redist *red; + + red_list = ospf->redist[type]; + if (!red_list) + continue; + + for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { + vty_out(vty, " redistribute %s", + zebra_route_string(type)); + if (red->instance) + vty_out(vty, " %d", red->instance); + + if (red->dmetric.value >= 0) + vty_out(vty, " metric %d", red->dmetric.value); + + if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) + vty_out(vty, " metric-type 1"); + + if (ROUTEMAP_NAME(red)) + vty_out(vty, " route-map %s", + ROUTEMAP_NAME(red)); + + vty_out(vty, "\n"); + } + } + + return 0; +} + +static int ospf_cfg_write_helper_dis_rtr_walkcb(struct hash_bucket *bucket, + void *arg) +{ + struct advRtr *rtr = bucket->data; + struct vty *vty = (struct vty *)arg; + + vty_out(vty, " graceful-restart helper enable %pI4\n", + &rtr->advRtrAddr); + return HASHWALK_CONTINUE; +} + +static void config_write_ospf_gr(struct vty *vty, struct ospf *ospf) +{ + if (!ospf->gr_info.restart_support) + return; + + if (ospf->gr_info.grace_period == OSPF_DFLT_GRACE_INTERVAL) + vty_out(vty, " graceful-restart\n"); + else + vty_out(vty, " graceful-restart grace-period %u\n", + ospf->gr_info.grace_period); +} + +static int config_write_ospf_gr_helper(struct vty *vty, struct ospf *ospf) +{ + if (ospf->is_helper_supported) + vty_out(vty, " graceful-restart helper enable\n"); + + if (!ospf->strict_lsa_check) + vty_out(vty, + " no graceful-restart helper strict-lsa-checking\n"); + + if (ospf->only_planned_restart) + vty_out(vty, " graceful-restart helper planned-only\n"); + + if (ospf->supported_grace_time != OSPF_MAX_GRACE_INTERVAL) + vty_out(vty, + " graceful-restart helper supported-grace-time %d\n", + ospf->supported_grace_time); + + if (OSPF_HELPER_ENABLE_RTR_COUNT(ospf)) { + hash_walk(ospf->enable_rtr_list, + ospf_cfg_write_helper_dis_rtr_walkcb, vty); + } + return 0; +} + +static int config_write_ospf_external_aggregator(struct vty *vty, + struct ospf *ospf) +{ + struct route_node *rn; + + if (ospf->aggr_delay_interval != OSPF_EXTL_AGGR_DEFAULT_DELAY) + vty_out(vty, " aggregation timer %u\n", + ospf->aggr_delay_interval); + + /* print 'summary-address A.B.C.D/M' */ + for (rn = route_top(ospf->rt_aggr_tbl); rn; rn = route_next(rn)) + if (rn->info) { + struct ospf_external_aggr_rt *aggr = rn->info; + + vty_out(vty, " summary-address %pI4/%d", + &aggr->p.prefix, aggr->p.prefixlen); + if (aggr->tag) + vty_out(vty, " tag %u", aggr->tag); + + if (CHECK_FLAG(aggr->flags, + OSPF_EXTERNAL_AGGRT_NO_ADVERTISE)) + vty_out(vty, " no-advertise"); + + vty_out(vty, "\n"); + } + + return 0; +} + +static int config_write_ospf_default_metric(struct vty *vty, struct ospf *ospf) +{ + if (ospf->default_metric != -1) + vty_out(vty, " default-metric %d\n", ospf->default_metric); + return 0; +} + +static int config_write_ospf_distribute(struct vty *vty, struct ospf *ospf) +{ + int type; + struct ospf_redist *red; + + if (ospf) { + /* distribute-list print. */ + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) + if (DISTRIBUTE_NAME(ospf, type)) + vty_out(vty, " distribute-list %s out %s\n", + DISTRIBUTE_NAME(ospf, type), + zebra_route_string(type)); + + /* default-information print. */ + if (ospf->default_originate != DEFAULT_ORIGINATE_NONE) { + vty_out(vty, " default-information originate"); + if (ospf->default_originate == DEFAULT_ORIGINATE_ALWAYS) + vty_out(vty, " always"); + + red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0); + if (red) { + if (red->dmetric.value >= 0) + vty_out(vty, " metric %d", + red->dmetric.value); + + if (red->dmetric.type == EXTERNAL_METRIC_TYPE_1) + vty_out(vty, " metric-type 1"); + + if (ROUTEMAP_NAME(red)) + vty_out(vty, " route-map %s", + ROUTEMAP_NAME(red)); + } + + vty_out(vty, "\n"); + } + } + + return 0; +} + +static int config_write_ospf_distance(struct vty *vty, struct ospf *ospf) +{ + struct route_node *rn; + struct ospf_distance *odistance; + + if (ospf->distance_all) + vty_out(vty, " distance %d\n", ospf->distance_all); + + if (ospf->distance_intra || ospf->distance_inter + || ospf->distance_external) { + vty_out(vty, " distance ospf"); + + if (ospf->distance_intra) + vty_out(vty, " intra-area %d", ospf->distance_intra); + if (ospf->distance_inter) + vty_out(vty, " inter-area %d", ospf->distance_inter); + if (ospf->distance_external) + vty_out(vty, " external %d", ospf->distance_external); + + vty_out(vty, "\n"); + } + + for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) + if ((odistance = rn->info) != NULL) { + vty_out(vty, " distance %d %pFX %s\n", + odistance->distance, &rn->p, + odistance->access_list ? odistance->access_list + : ""); + } + return 0; +} + +static int ospf_config_write_one(struct vty *vty, struct ospf *ospf) +{ + int write = 0; + + /* `router ospf' print. */ + if (ospf->instance && strcmp(ospf->name, VRF_DEFAULT_NAME)) { + vty_out(vty, "router ospf %d vrf %s\n", ospf->instance, + ospf->name); + } else if (ospf->instance) { + vty_out(vty, "router ospf %d\n", ospf->instance); + } else if (strcmp(ospf->name, VRF_DEFAULT_NAME)) { + vty_out(vty, "router ospf vrf %s\n", ospf->name); + } else + vty_out(vty, "router ospf\n"); + + if (!ospf->networks) { + write++; + return write; + } + + /* Router ID print. */ + if (ospf->router_id_static.s_addr != INADDR_ANY) + vty_out(vty, " ospf router-id %pI4\n", + &ospf->router_id_static); + + /* zebra opaque attributes configuration. */ + if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA)) + vty_out(vty, " ospf send-extra-data zebra\n"); + + /* ABR type print. */ + if (ospf->abr_type != OSPF_ABR_DEFAULT) + vty_out(vty, " ospf abr-type %s\n", + ospf_abr_type_str[ospf->abr_type]); + + /* log-adjacency-changes flag print. */ + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES)) { + if (CHECK_FLAG(ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) + vty_out(vty, " log-adjacency-changes detail\n"); + else if (!SAVE_OSPF_LOG_ADJACENCY_CHANGES) + vty_out(vty, " log-adjacency-changes\n"); + } else if (SAVE_OSPF_LOG_ADJACENCY_CHANGES) { + vty_out(vty, " no log-adjacency-changes\n"); + } + + /* RFC1583 compatibility flag print -- Compatible with CISCO + * 12.1. */ + if (CHECK_FLAG(ospf->config, OSPF_RFC1583_COMPATIBLE)) + vty_out(vty, " compatible rfc1583\n"); + + /* auto-cost reference-bandwidth configuration. */ + if (ospf->ref_bandwidth != OSPF_DEFAULT_REF_BANDWIDTH) { + vty_out(vty, + "! Important: ensure reference bandwidth is consistent across all routers\n"); + vty_out(vty, " auto-cost reference-bandwidth %d\n", + ospf->ref_bandwidth); + } + + /* SPF timers print. */ + if (ospf->spf_delay != OSPF_SPF_DELAY_DEFAULT + || ospf->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT + || ospf->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT) + vty_out(vty, " timers throttle spf %d %d %d\n", ospf->spf_delay, + ospf->spf_holdtime, ospf->spf_max_holdtime); + + /* LSA timers print. */ + if (ospf->min_ls_interval != OSPF_MIN_LS_INTERVAL) + vty_out(vty, " timers throttle lsa all %d\n", + ospf->min_ls_interval); + if (ospf->min_ls_arrival != OSPF_MIN_LS_ARRIVAL) + vty_out(vty, " timers lsa min-arrival %d\n", + ospf->min_ls_arrival); + + /* Write multiplier print. */ + if (ospf->write_oi_count != OSPF_WRITE_INTERFACE_COUNT_DEFAULT) + vty_out(vty, " ospf write-multiplier %d\n", + ospf->write_oi_count); + + if (ospf->max_multipath != MULTIPATH_NUM) + vty_out(vty, " maximum-paths %d\n", ospf->max_multipath); + + /* Max-metric router-lsa print */ + config_write_stub_router(vty, ospf); + + /* SPF refresh parameters print. */ + if (ospf->lsa_refresh_interval != OSPF_LSA_REFRESH_INTERVAL_DEFAULT) + vty_out(vty, " refresh timer %d\n", ospf->lsa_refresh_interval); + + if (ospf->fr_configured) + vty_out(vty, " flood-reduction\n"); + + if (!ospf->intf_socket_enabled) + vty_out(vty, " no socket-per-interface\n"); + + /* Redistribute information print. */ + config_write_ospf_redistribute(vty, ospf); + + /* Graceful Restart print */ + config_write_ospf_gr(vty, ospf); + config_write_ospf_gr_helper(vty, ospf); + + /* Print external route aggregation. */ + config_write_ospf_external_aggregator(vty, ospf); + + /* passive-interface print. */ + if (ospf->passive_interface_default == OSPF_IF_PASSIVE) + vty_out(vty, " passive-interface default\n"); + + /* proactive-arp print. */ + if (ospf->proactive_arp != OSPF_PROACTIVE_ARP_DEFAULT) { + if (ospf->proactive_arp) + vty_out(vty, " proactive-arp\n"); + else + vty_out(vty, " no proactive-arp\n"); + } + + /* TI-LFA print. */ + if (ospf->ti_lfa_enabled) { + if (ospf->ti_lfa_protection_type == OSPF_TI_LFA_NODE_PROTECTION) + vty_out(vty, " fast-reroute ti-lfa node-protection\n"); + else + vty_out(vty, " fast-reroute ti-lfa\n"); + } + + /* Network area print. */ + config_write_network_area(vty, ospf); + + /* Area config print. */ + config_write_ospf_area(vty, ospf); + + /* static neighbor print. */ + config_write_ospf_nbr_nbma(vty, ospf); + + /* Virtual-Link print. */ + config_write_virtual_link(vty, ospf); + + /* Default metric configuration. */ + config_write_ospf_default_metric(vty, ospf); + + /* Distribute-list and default-information print. */ + config_write_ospf_distribute(vty, ospf); + + /* Distance configuration. */ + config_write_ospf_distance(vty, ospf); + + ospf_opaque_config_write_router(vty, ospf); + + /* LDP-Sync print */ + ospf_ldp_sync_write_config(vty, ospf); + + /* Socket buffer sizes */ + if (ospf->recv_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE) { + if (ospf->send_sock_bufsize == ospf->recv_sock_bufsize) + vty_out(vty, " socket buffer all %u\n", + ospf->recv_sock_bufsize); + else + vty_out(vty, " socket buffer recv %u\n", + ospf->recv_sock_bufsize); + } + + if (ospf->send_sock_bufsize != OSPF_DEFAULT_SOCK_BUFSIZE && + ospf->send_sock_bufsize != ospf->recv_sock_bufsize) + vty_out(vty, " socket buffer send %u\n", + ospf->send_sock_bufsize); + + + vty_out(vty, "exit\n"); + + write++; + return write; +} + +/* OSPF configuration write function. */ +static int ospf_config_write(struct vty *vty) +{ + struct ospf *ospf; + struct listnode *ospf_node = NULL; + int write = 0; + + if (listcount(om->ospf) == 0) + return write; + + for (ALL_LIST_ELEMENTS_RO(om->ospf, ospf_node, ospf)) { + /* VRF Default check if it is running. + * Upon daemon start, there could be default instance + * in absence of 'router ospf'/oi_running is disabled. */ + if (ospf->vrf_id == VRF_DEFAULT && ospf->oi_running) + write += ospf_config_write_one(vty, ospf); + /* For Non-Default VRF simply display the configuration, + * even if it is not oi_running. */ + else if (ospf->vrf_id != VRF_DEFAULT) + write += ospf_config_write_one(vty, ospf); + } + return write; +} + +void ospf_vty_show_init(void) +{ + /* "show ip ospf" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_cmd); + + /* "show ip ospf database" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_database_cmd); + + /* "show ip ospf interface" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_interface_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_interface_cmd); + /* "show ip ospf interface traffic */ + install_element(VIEW_NODE, &show_ip_ospf_interface_traffic_cmd); + + /* "show ip ospf neighbor" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_neighbor_int_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_int_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_id_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_detail_all_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_ospf_neighbor_all_cmd); + + install_element(VIEW_NODE, + &show_ip_ospf_instance_neighbor_int_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_int_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_id_cmd); + install_element(VIEW_NODE, + &show_ip_ospf_instance_neighbor_detail_all_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_detail_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_neighbor_all_cmd); + + /* "show ip ospf route" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_route_cmd); + install_element(VIEW_NODE, &show_ip_ospf_border_routers_cmd); + install_element(VIEW_NODE, &show_ip_ospf_reachable_routers_cmd); + + install_element(VIEW_NODE, &show_ip_ospf_instance_route_cmd); + install_element(VIEW_NODE, &show_ip_ospf_instance_border_routers_cmd); + install_element(VIEW_NODE, + &show_ip_ospf_instance_reachable_routers_cmd); + + /* "show ip ospf vrfs" commands. */ + install_element(VIEW_NODE, &show_ip_ospf_vrfs_cmd); + + /* "show ip ospf gr-helper details" command */ + install_element(VIEW_NODE, &show_ip_ospf_gr_helper_cmd); + + /* "show ip ospf summary-address" command */ + install_element(VIEW_NODE, &show_ip_ospf_external_aggregator_cmd); +} + +/* Initialization of OSPF interface. */ +static void ospf_vty_if_init(void) +{ + /* Install interface node. */ + if_cmd_init(config_write_interface); + + /* "ip ospf authentication" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_authentication_args_addr_cmd); + install_element(INTERFACE_NODE, &ip_ospf_authentication_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_authentication_args_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_authentication_addr_cmd); + install_element(INTERFACE_NODE, &ip_ospf_authentication_key_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_authentication_key_authkey_addr_cmd); + install_element(INTERFACE_NODE, + &no_ospf_authentication_key_authkey_addr_cmd); + + /* "ip ospf message-digest-key" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_message_digest_key_cmd); + + /* "ip ospf cost" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_cost_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_cost_cmd); + + /* "ip ospf mtu-ignore" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_mtu_ignore_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_mtu_ignore_addr_cmd); + + /* "ip ospf dead-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, + &ip_ospf_dead_interval_minimal_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_dead_interval_cmd); + + /* "ip ospf hello-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_hello_interval_cmd); + + /* "ip ospf network" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_network_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_network_cmd); + + /* "ip ospf priority" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_priority_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_priority_cmd); + + /* "ip ospf retransmit-interval" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_retransmit_interval_addr_cmd); + install_element(INTERFACE_NODE, + &no_ip_ospf_retransmit_interval_addr_cmd); + + /* "ip ospf transmit-delay" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_transmit_delay_addr_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_transmit_delay_addr_cmd); + + /* "ip ospf area" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_area_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_area_cmd); + + /* "ip ospf passive" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_passive_cmd); + install_element(INTERFACE_NODE, &no_ip_ospf_passive_cmd); + + /* "ip ospf capability opaque" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_capability_opaque_addr_cmd); + + /* "ip ospf prefix-suppression" commands. */ + install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_addr_cmd); + + /* These commands are compatibitliy for previous version. */ + install_element(INTERFACE_NODE, &ospf_authentication_key_cmd); + install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &no_ospf_message_digest_key_cmd); + install_element(INTERFACE_NODE, &ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_dead_interval_cmd); + install_element(INTERFACE_NODE, &ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_hello_interval_cmd); + install_element(INTERFACE_NODE, &ospf_cost_cmd); + install_element(INTERFACE_NODE, &no_ospf_cost_cmd); + install_element(INTERFACE_NODE, &ospf_network_cmd); + install_element(INTERFACE_NODE, &no_ospf_network_cmd); + install_element(INTERFACE_NODE, &ospf_priority_cmd); + install_element(INTERFACE_NODE, &no_ospf_priority_cmd); + install_element(INTERFACE_NODE, &ospf_retransmit_interval_cmd); + install_element(INTERFACE_NODE, &no_ospf_retransmit_interval_cmd); + install_element(INTERFACE_NODE, &ospf_transmit_delay_cmd); + install_element(INTERFACE_NODE, &no_ospf_transmit_delay_cmd); +} + +static void ospf_vty_zebra_init(void) +{ + install_element(OSPF_NODE, &ospf_redistribute_source_cmd); + install_element(OSPF_NODE, &no_ospf_redistribute_source_cmd); + install_element(OSPF_NODE, &ospf_redistribute_instance_source_cmd); + install_element(OSPF_NODE, &no_ospf_redistribute_instance_source_cmd); + + install_element(OSPF_NODE, &ospf_distribute_list_out_cmd); + install_element(OSPF_NODE, &no_ospf_distribute_list_out_cmd); + + install_element(OSPF_NODE, &ospf_default_information_originate_cmd); + install_element(OSPF_NODE, &no_ospf_default_information_originate_cmd); + + install_element(OSPF_NODE, &ospf_default_metric_cmd); + install_element(OSPF_NODE, &no_ospf_default_metric_cmd); + + install_element(OSPF_NODE, &ospf_distance_cmd); + install_element(OSPF_NODE, &no_ospf_distance_cmd); + install_element(OSPF_NODE, &no_ospf_distance_ospf_cmd); + install_element(OSPF_NODE, &ospf_distance_ospf_cmd); + + /*Ospf garcefull restart helper configurations */ + install_element(OSPF_NODE, &ospf_gr_helper_enable_cmd); + install_element(OSPF_NODE, &no_ospf_gr_helper_enable_cmd); + install_element(OSPF_NODE, &ospf_gr_helper_enable_lsacheck_cmd); + install_element(OSPF_NODE, &no_ospf_gr_helper_enable_lsacheck_cmd); + install_element(OSPF_NODE, &ospf_gr_helper_supported_grace_time_cmd); + install_element(OSPF_NODE, &no_ospf_gr_helper_supported_grace_time_cmd); + install_element(OSPF_NODE, &ospf_gr_helper_planned_only_cmd); + install_element(OSPF_NODE, &no_ospf_gr_helper_planned_only_cmd); + + /* External LSA summarisation config commands.*/ + install_element(OSPF_NODE, &ospf_external_route_aggregation_cmd); + install_element(OSPF_NODE, &no_ospf_external_route_aggregation_cmd); + install_element(OSPF_NODE, + &ospf_external_route_aggregation_no_adrvertise_cmd); + install_element(OSPF_NODE, + &no_ospf_external_route_aggregation_no_adrvertise_cmd); + install_element(OSPF_NODE, &ospf_route_aggregation_timer_cmd); + install_element(OSPF_NODE, &no_ospf_route_aggregation_timer_cmd); +} + +static int ospf_config_write(struct vty *vty); +static struct cmd_node ospf_node = { + .name = "ospf", + .node = OSPF_NODE, + .parent_node = CONFIG_NODE, + .prompt = "%s(config-router)# ", + .config_write = ospf_config_write, +}; + +static void ospf_interface_clear(struct interface *ifp) +{ + if (!if_is_operative(ifp)) + return; + + if (IS_DEBUG_OSPF(ism, ISM_EVENTS)) + zlog_debug("ISM[%s]: clear by reset", ifp->name); + + ospf_if_reset(ifp); +} + +DEFUN (clear_ip_ospf_interface, + clear_ip_ospf_interface_cmd, + "clear ip ospf [vrf NAME] interface [IFNAME]", + CLEAR_STR + IP_STR + "OSPF information\n" + VRF_CMD_HELP_STR + "Interface information\n" + "Interface name\n") +{ + int idx_ifname = 0; + int idx_vrf = 0; + struct interface *ifp; + struct listnode *node; + struct ospf *ospf = NULL; + char *vrf_name = NULL; + vrf_id_t vrf_id = VRF_DEFAULT; + struct vrf *vrf = NULL; + + if (argv_find(argv, argc, "vrf", &idx_vrf)) + vrf_name = argv[idx_vrf + 1]->arg; + if (vrf_name && strmatch(vrf_name, VRF_DEFAULT_NAME)) + vrf_name = NULL; + if (vrf_name) { + vrf = vrf_lookup_by_name(vrf_name); + if (vrf) + vrf_id = vrf->vrf_id; + } + if (!argv_find(argv, argc, "IFNAME", &idx_ifname)) { + /* Clear all the ospfv2 interfaces. */ + for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { + if (vrf_id != ospf->vrf_id) + continue; + if (!vrf) + vrf = vrf_lookup_by_id(ospf->vrf_id); + FOR_ALL_INTERFACES (vrf, ifp) + ospf_interface_clear(ifp); + } + } else { + /* Interface name is specified. */ + ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id); + if (ifp == NULL) + vty_out(vty, "No such interface name\n"); + else + ospf_interface_clear(ifp); + } + + return CMD_SUCCESS; +} + +DEFPY_HIDDEN(ospf_lsa_refresh_timer, ospf_lsa_refresh_timer_cmd, + "[no$no] ospf lsa-refresh [(120-1800)]$value", + NO_STR OSPF_STR + "OSPF lsa refresh timer\n" + "timer value in seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + + if (no) + ospf->lsa_refresh_timer = OSPF_LS_REFRESH_TIME; + else + ospf->lsa_refresh_timer = value; + + return CMD_SUCCESS; +} + +DEFPY_HIDDEN(ospf_maxage_delay_timer, ospf_maxage_delay_timer_cmd, + "[no$no] ospf maxage-delay [(0-60)]$value", + NO_STR OSPF_STR + "OSPF lsa maxage delay timer\n" + "timer value in seconds\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + + if (no) + ospf->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT; + else + ospf->maxage_delay = value; + + EVENT_OFF(ospf->t_maxage); + OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover, + ospf->maxage_delay); + + return CMD_SUCCESS; +} + +/* + * ------------------------------------------------------------------------* + * Following is (vty) configuration functions for flood-reduction handling. + * ------------------------------------------------------------------------ + */ + +DEFPY(flood_reduction, flood_reduction_cmd, "flood-reduction", + "flood reduction feature\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + struct ospf_area *area; + struct listnode *node; + + /* Turn on the Flood Reduction feature for the router. */ + if (!ospf->fr_configured) { + ospf->fr_configured = true; + OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, + "Flood Reduction: OFF -> ON"); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (area) { + ospf_area_update_fr_state(area); + ospf_refresh_area_self_lsas(area); + } + } + } + + return CMD_SUCCESS; +} + +DEFPY(flood_reduction_area, flood_reduction_area_cmd, + "area <A.B.C.D|(0-4294967295)> flood-reduction", + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Enable flood reduction for area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + struct ospf_area *oa; + int idx = 1; + int format; + int ret; + const char *areaid; + struct in_addr area_id; + + areaid = argv[idx]->arg; + + ret = str2area_id(areaid, &area_id, &format); + if (ret < 0) { + vty_out(vty, "Please specify area by A.B.C.D|<0-4294967295>\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + oa = ospf_area_lookup_by_area_id(ospf, area_id); + if (!oa) { + vty_out(vty, "OSPF area ID not present\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Turn on the Flood Reduction feature for the area. */ + if (!oa->fr_info.configured) { + oa->fr_info.configured = true; + OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, + "Flood Reduction area %pI4 : OFF -> ON", + &oa->area_id); + ospf_area_update_fr_state(oa); + ospf_refresh_area_self_lsas(oa); + } + + return CMD_SUCCESS; +} + +DEFPY(no_flood_reduction, no_flood_reduction_cmd, "no flood-reduction", + NO_STR "flood reduction feature\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + struct listnode *node; + struct ospf_area *area; + + /* Turn off the Flood Reduction feature for the router. */ + if (ospf->fr_configured) { + ospf->fr_configured = false; + OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, + "Flood Reduction: ON -> OFF"); + for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { + if (area) { + ospf_area_update_fr_state(area); + ospf_refresh_area_self_lsas(area); + } + } + } + + return CMD_SUCCESS; +} + +DEFPY(no_flood_reduction_area, no_flood_reduction_area_cmd, + "no area <A.B.C.D|(0-4294967295)> flood-reduction", + NO_STR + "OSPF area parameters\n" + "OSPF area ID in IP address format\n" + "OSPF area ID as a decimal value\n" + "Disable flood reduction for area\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf) + struct ospf_area *oa; + int idx = 2; + int format; + int ret; + const char *areaid; + struct in_addr area_id; + + areaid = argv[idx]->arg; + + ret = str2area_id(areaid, &area_id, &format); + if (ret < 0) { + vty_out(vty, "Please specify area by A.B.C.D|<0-4294967295>\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + oa = ospf_area_lookup_by_area_id(ospf, area_id); + if (!oa) { + vty_out(vty, "OSPF area ID not present\n"); + return CMD_WARNING_CONFIG_FAILED; + } + + /* Turn off the Flood Reduction feature for the area. */ + if (oa->fr_info.configured) { + oa->fr_info.configured = false; + OSPF_LOG_DEBUG(IS_DEBUG_OSPF_EVENT, + "Flood Reduction area %pI4 : ON -> OFF", + &oa->area_id); + ospf_area_update_fr_state(oa); + ospf_refresh_area_self_lsas(oa); + } + + return CMD_SUCCESS; +} + +DEFPY(ospf_socket_bufsizes, + ospf_socket_bufsizes_cmd, + "[no] socket buffer <send$send_val | recv$recv_val | all$all_val> \ + ![(1-4000000000)$bufsize]", + NO_STR + "Socket parameters\n" + "Buffer size configuration\n" + "Send buffer size\n" + "Receive buffer size\n" + "Both send and receive buffer sizes\n" + "Buffer size, in bytes\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + uint32_t recvsz, sendsz; + + if (no) + bufsize = OSPF_DEFAULT_SOCK_BUFSIZE; + + if (all_val) { + recvsz = bufsize; + sendsz = bufsize; + } else if (send_val) { + sendsz = bufsize; + recvsz = ospf->recv_sock_bufsize; + } else if (recv_val) { + recvsz = bufsize; + sendsz = ospf->send_sock_bufsize; + } else + return CMD_SUCCESS; + + /* React to a change by modifying existing sockets */ + ospf_update_bufsize(ospf, recvsz, sendsz); + + return CMD_SUCCESS; +} + +DEFPY (per_intf_socket, + per_intf_socket_cmd, + "[no] socket-per-interface", + NO_STR + "Use write socket per interface\n") +{ + VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf); + struct listnode *node; + struct ospf_interface *oi; + + if (no) { + if (ospf->intf_socket_enabled) { + ospf->intf_socket_enabled = false; + + /* Iterate and close any sockets */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + ospf_ifp_sock_close(oi->ifp); + } + } else if (!ospf->intf_socket_enabled) { + ospf->intf_socket_enabled = true; + + /* Iterate and open sockets */ + for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) + ospf_ifp_sock_init(oi->ifp); + } + + return CMD_SUCCESS; +} + +void ospf_vty_clear_init(void) +{ + install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd); + install_element(ENABLE_NODE, &clear_ip_ospf_process_cmd); + install_element(ENABLE_NODE, &clear_ip_ospf_neighbor_cmd); +} + + +/* Install OSPF related vty commands. */ +void ospf_vty_init(void) +{ + /* Install ospf top node. */ + install_node(&ospf_node); + + /* "router ospf" commands. */ + install_element(CONFIG_NODE, &router_ospf_cmd); + install_element(CONFIG_NODE, &no_router_ospf_cmd); + + + install_default(OSPF_NODE); + + /* "ospf router-id" commands. */ + install_element(OSPF_NODE, &ospf_router_id_cmd); + install_element(OSPF_NODE, &ospf_router_id_old_cmd); + install_element(OSPF_NODE, &no_ospf_router_id_cmd); + + /* "passive-interface" commands. */ + install_element(OSPF_NODE, &ospf_passive_interface_default_cmd); + install_element(OSPF_NODE, &ospf_passive_interface_addr_cmd); + install_element(OSPF_NODE, &no_ospf_passive_interface_default_cmd); + install_element(OSPF_NODE, &no_ospf_passive_interface_addr_cmd); + + /* "ospf abr-type" commands. */ + install_element(OSPF_NODE, &ospf_abr_type_cmd); + install_element(OSPF_NODE, &no_ospf_abr_type_cmd); + + /* "ospf log-adjacency-changes" commands. */ + install_element(OSPF_NODE, &ospf_log_adjacency_changes_cmd); + install_element(OSPF_NODE, &ospf_log_adjacency_changes_detail_cmd); + install_element(OSPF_NODE, &no_ospf_log_adjacency_changes_cmd); + install_element(OSPF_NODE, &no_ospf_log_adjacency_changes_detail_cmd); + + /* "ospf rfc1583-compatible" commands. */ + install_element(OSPF_NODE, &ospf_compatible_rfc1583_cmd); + install_element(OSPF_NODE, &no_ospf_compatible_rfc1583_cmd); + install_element(OSPF_NODE, &ospf_rfc1583_flag_cmd); + install_element(OSPF_NODE, &no_ospf_rfc1583_flag_cmd); + + /* "ospf send-extra-data zebra" commands. */ + install_element(OSPF_NODE, &ospf_send_extra_data_cmd); + + /* "network area" commands. */ + install_element(OSPF_NODE, &ospf_network_area_cmd); + install_element(OSPF_NODE, &no_ospf_network_area_cmd); + + /* "area authentication" commands. */ + install_element(OSPF_NODE, + &ospf_area_authentication_message_digest_cmd); + install_element(OSPF_NODE, &ospf_area_authentication_cmd); + install_element(OSPF_NODE, &no_ospf_area_authentication_cmd); + + /* "area range" commands. */ + install_element(OSPF_NODE, &ospf_area_range_cmd); + install_element(OSPF_NODE, &ospf_area_range_cost_cmd); + install_element(OSPF_NODE, &ospf_area_range_not_advertise_cmd); + install_element(OSPF_NODE, &no_ospf_area_range_cmd); + install_element(OSPF_NODE, &no_ospf_area_range_substitute_cmd); + + /* "area virtual-link" commands. */ + install_element(OSPF_NODE, &ospf_area_vlink_cmd); + install_element(OSPF_NODE, &ospf_area_vlink_intervals_cmd); + install_element(OSPF_NODE, &no_ospf_area_vlink_cmd); + install_element(OSPF_NODE, &no_ospf_area_vlink_intervals_cmd); + + + /* "area stub" commands. */ + install_element(OSPF_NODE, &ospf_area_stub_no_summary_cmd); + install_element(OSPF_NODE, &ospf_area_stub_cmd); + install_element(OSPF_NODE, &no_ospf_area_stub_no_summary_cmd); + install_element(OSPF_NODE, &no_ospf_area_stub_cmd); + + /* "area nssa" commands. */ + install_element(OSPF_NODE, &ospf_area_nssa_cmd); + install_element(OSPF_NODE, &no_ospf_area_nssa_cmd); + install_element(OSPF_NODE, &ospf_area_nssa_range_cmd); + install_element(OSPF_NODE, &no_ospf_area_nssa_range_cmd); + + install_element(OSPF_NODE, &ospf_area_default_cost_cmd); + install_element(OSPF_NODE, &no_ospf_area_default_cost_cmd); + + install_element(OSPF_NODE, &ospf_area_shortcut_cmd); + install_element(OSPF_NODE, &no_ospf_area_shortcut_cmd); + + install_element(OSPF_NODE, &ospf_area_export_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_export_list_cmd); + + install_element(OSPF_NODE, &ospf_area_filter_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_filter_list_cmd); + + install_element(OSPF_NODE, &ospf_area_import_list_cmd); + install_element(OSPF_NODE, &no_ospf_area_import_list_cmd); + + /* SPF timer commands */ + install_element(OSPF_NODE, &ospf_timers_throttle_spf_cmd); + install_element(OSPF_NODE, &no_ospf_timers_throttle_spf_cmd); + + /* LSA timers commands */ + install_element(OSPF_NODE, &ospf_timers_min_ls_interval_cmd); + install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd); + install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd); + install_element(OSPF_NODE, &no_ospf_timers_lsa_min_arrival_cmd); + + /* refresh timer commands */ + install_element(OSPF_NODE, &ospf_refresh_timer_cmd); + install_element(OSPF_NODE, &no_ospf_refresh_timer_val_cmd); + + /* max-metric commands */ + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_admin_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_admin_cmd); + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_startup_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_startup_cmd); + install_element(OSPF_NODE, &ospf_max_metric_router_lsa_shutdown_cmd); + install_element(OSPF_NODE, &no_ospf_max_metric_router_lsa_shutdown_cmd); + + /* reference bandwidth commands */ + install_element(OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd); + install_element(OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd); + + /* "neighbor" commands. */ + install_element(OSPF_NODE, &ospf_neighbor_cmd); + install_element(OSPF_NODE, &ospf_neighbor_poll_interval_cmd); + install_element(OSPF_NODE, &no_ospf_neighbor_cmd); + install_element(OSPF_NODE, &no_ospf_neighbor_poll_cmd); + + /* write multiplier commands */ + install_element(OSPF_NODE, &ospf_write_multiplier_cmd); + install_element(OSPF_NODE, &write_multiplier_cmd); + install_element(OSPF_NODE, &no_ospf_write_multiplier_cmd); + install_element(OSPF_NODE, &no_write_multiplier_cmd); + + /* "proactive-arp" commands. */ + install_element(OSPF_NODE, &ospf_proactive_arp_cmd); + install_element(OSPF_NODE, &no_ospf_proactive_arp_cmd); + + /* TI-LFA commands */ + install_element(OSPF_NODE, &ospf_ti_lfa_cmd); + install_element(OSPF_NODE, &no_ospf_ti_lfa_cmd); + + /* Max path configurations */ + install_element(OSPF_NODE, &ospf_max_multipath_cmd); + install_element(OSPF_NODE, &no_ospf_max_multipath_cmd); + + vrf_cmd_init(NULL); + + install_element(OSPF_NODE, &ospf_lsa_refresh_timer_cmd); + install_element(OSPF_NODE, &ospf_maxage_delay_timer_cmd); + + /* Flood Reduction commands */ + install_element(OSPF_NODE, &flood_reduction_cmd); + install_element(OSPF_NODE, &no_flood_reduction_cmd); + install_element(OSPF_NODE, &flood_reduction_area_cmd); + install_element(OSPF_NODE, &no_flood_reduction_area_cmd); + + install_element(OSPF_NODE, &ospf_socket_bufsizes_cmd); + install_element(OSPF_NODE, &per_intf_socket_cmd); + + /* Init interface related vty commands. */ + ospf_vty_if_init(); + + /* Init zebra related vty commands. */ + ospf_vty_zebra_init(); +} |