From 2d35a720b9f997d08dd3da5441fc7ce889135a05 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 19 Oct 2016 14:38:48 +0200 Subject: [PATCH 01/18] vtysh: fix oversight in vtysh buffer rewrite end can be NULL and shouldn't be adjusted in that case. Signed-off-by: David Lamparter --- vtysh/vtysh.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index aaf3f828c4..4b579ddbdb 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -185,7 +185,8 @@ vtysh_client_run (struct vtysh_client *vclient, const char *line, FILE *fp) memmove (buf, eol, bufvalid - eol); bufvalid -= eol - buf; - end -= eol - buf; + if (end) + end -= eol - buf; } if (bufvalid == buf + bufsz) From 274f29b2f43c82e223d7a8d6899fae74fdcc5105 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 16 Jun 2016 16:03:11 +0100 Subject: [PATCH 02/18] lib: keep hash of node's commands to detect duplicate installs * command.h: (struct cmd_node) Add a hash, so duplicate installs of a cmd_element to a command node can be detected. To help catch strays from the VIEW/ENABLE node consolidation particularly (installs to VIEW automatically install to ENABLE too now). * command.c: (cmd_hash_{key,cmp}) helpers for the hash - just directly on the pointer value is sufficient to catch the main problem. (install_node) setup the hash for the command node. (install_element) check for duplicate installs. The assert on the cmd_parse_format seems misplaced. (install_default_basic) separate the basic, VIEW, node default commands to here. (cmd_init) get rid of dupes, given consolidation. (cmd_terminate) clean up the node command hash. Not done: The (struct cmd_node)'s vector could be replaced with the cmd hash, however much of the command parser depends heavily on the vector and it's a lot of work to change. A vector_lookup_value could also work, particularly if vector could be backed by a hash. The duplicate check could be disabled in releases - but useful in development. It's a little extra overhead at startup. The command initialisation overhead is already something that bites in micro-benchmarks - makes it easy for other implementations to show how much faster they are with benchmarks where other load is low enough that startup time is a factor. --- lib/command.c | 34 ++++++++++++++++++++++++++++++++-- lib/command.h | 6 +++++- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/command.c b/lib/command.c index 4f5b727ac5..56c262a647 100644 --- a/lib/command.c +++ b/lib/command.c @@ -224,6 +224,18 @@ argv_concat (const char **argv, int argc, int shift) return str; } +static unsigned int +cmd_hash_key (void *p) +{ + return (uintptr_t) p; +} + +static int +cmd_hash_cmp (const void *a, const void *b) +{ + return a == b; +} + /* Install top node of command vector. */ void install_node (struct cmd_node *node, @@ -232,6 +244,7 @@ install_node (struct cmd_node *node, vector_set_index (cmdvec, node->node, node); node->func = func; node->cmd_vector = vector_init (VECTOR_MIN_SIZE); + node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp); } /* Breaking up string into each command piece. I assume given @@ -704,7 +717,11 @@ install_element (enum node_type ntype, struct cmd_element *cmd) /* cmd_init hasn't been called */ if (!cmdvec) - return; + { + fprintf (stderr, "%s called before cmd_init, breakage likely\n", + __func__); + return; + } cnode = vector_slot (cmdvec, ntype); @@ -714,7 +731,17 @@ install_element (enum node_type ntype, struct cmd_element *cmd) ntype); exit (1); } - + + if (hash_lookup (cnode->cmd_hash, cmd) != NULL) + { + fprintf (stderr, + "Multiple command installs to node %d of command:\n%s\n", + ntype, cmd->string); + return; + } + + assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern)); + vector_set (cnode->cmd_vector, cmd); if (cmd->tokens == NULL) cmd->tokens = cmd_parse_format(cmd->string, cmd->doc); @@ -4364,6 +4391,9 @@ cmd_terminate () cmd_terminate_element(cmd_element); vector_free (cmd_node_v); + hash_clean (cmd_node->cmd_hash, NULL); + hash_free (cmd_node->cmd_hash); + cmd_node->cmd_hash = NULL; } vector_free (cmdvec); diff --git a/lib/command.h b/lib/command.h index ad9ccf505e..e4aa10196f 100644 --- a/lib/command.h +++ b/lib/command.h @@ -27,6 +27,7 @@ #include "vty.h" #include "lib/route_types.h" #include "memory.h" +#include "hash.h" DECLARE_MTYPE(HOST) @@ -147,7 +148,10 @@ struct cmd_node int (*func) (struct vty *); /* Vector of this node's command list. */ - vector cmd_vector; + vector cmd_vector; + + /* Hashed index of command node list, for de-dupping primarily */ + struct hash *cmd_hash; }; enum From e95c4d17a7e9fcd22b2bb14ccdac93e458e08cb7 Mon Sep 17 00:00:00 2001 From: Paul Jakma Date: Thu, 16 Jun 2016 16:06:13 +0100 Subject: [PATCH 03/18] *: Fix duplicate commands from view/enable node consolidation --- ospf6d/ospf6d.c | 37 ------------------------------------- zebra/debug.c | 1 - zebra/zebra_mpls_vty.c | 3 --- zebra/zebra_routemap.c | 4 ---- 4 files changed, 45 deletions(-) diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 5ae7e60e8b..76874f6d1d 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -1848,43 +1848,6 @@ ospf6_init (void) INSTALL (VIEW, database_type_self_originated_linkstate_id_cmd); INSTALL (VIEW, database_type_self_originated_linkstate_id_detail_cmd); - INSTALL (ENABLE, database_cmd); - INSTALL (ENABLE, database_detail_cmd); - INSTALL (ENABLE, database_type_cmd); - INSTALL (ENABLE, database_type_detail_cmd); - INSTALL (ENABLE, database_id_cmd); - INSTALL (ENABLE, database_id_detail_cmd); - INSTALL (ENABLE, database_linkstate_id_cmd); - INSTALL (ENABLE, database_linkstate_id_detail_cmd); - INSTALL (ENABLE, database_router_cmd); - INSTALL (ENABLE, database_router_detail_cmd); - INSTALL (ENABLE, database_adv_router_cmd); - INSTALL (ENABLE, database_adv_router_detail_cmd); - INSTALL (ENABLE, database_type_id_cmd); - INSTALL (ENABLE, database_type_id_detail_cmd); - INSTALL (ENABLE, database_type_linkstate_id_cmd); - INSTALL (ENABLE, database_type_linkstate_id_detail_cmd); - INSTALL (ENABLE, database_type_router_cmd); - INSTALL (ENABLE, database_type_router_detail_cmd); - INSTALL (ENABLE, database_type_adv_router_cmd); - INSTALL (ENABLE, database_type_adv_router_detail_cmd); - INSTALL (ENABLE, database_adv_router_linkstate_id_cmd); - INSTALL (ENABLE, database_adv_router_linkstate_id_detail_cmd); - INSTALL (ENABLE, database_id_router_cmd); - INSTALL (ENABLE, database_id_router_detail_cmd); - INSTALL (ENABLE, database_type_id_router_cmd); - INSTALL (ENABLE, database_type_id_router_detail_cmd); - INSTALL (ENABLE, database_type_adv_router_linkstate_id_cmd); - INSTALL (ENABLE, database_type_adv_router_linkstate_id_detail_cmd); - INSTALL (ENABLE, database_self_originated_cmd); - INSTALL (ENABLE, database_self_originated_detail_cmd); - INSTALL (ENABLE, database_type_self_originated_cmd); - INSTALL (ENABLE, database_type_self_originated_detail_cmd); - INSTALL (ENABLE, database_type_id_self_originated_cmd); - INSTALL (ENABLE, database_type_id_self_originated_detail_cmd); - INSTALL (ENABLE, database_type_self_originated_linkstate_id_cmd); - INSTALL (ENABLE, database_type_self_originated_linkstate_id_detail_cmd); - /* Make ospf protocol socket. */ ospf6_serv_sock (); thread_add_read (master, ospf6_receive, NULL, ospf6_sock); diff --git a/zebra/debug.c b/zebra/debug.c index 92354070ef..93cd4dd9c6 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -449,7 +449,6 @@ zebra_debug_init (void) install_element (VIEW_NODE, &show_debugging_zebra_cmd); - install_element (ENABLE_NODE, &show_debugging_zebra_cmd); install_element (ENABLE_NODE, &debug_zebra_events_cmd); install_element (ENABLE_NODE, &debug_zebra_nht_cmd); install_element (ENABLE_NODE, &debug_zebra_mpls_cmd); diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 6136e92cdd..6e95236c20 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -828,7 +828,6 @@ void zebra_mpls_vty_init (void) { install_element (VIEW_NODE, &show_mpls_status_cmd); - install_element (ENABLE_NODE, &show_mpls_status_cmd); if (! mpls_enabled) return; @@ -875,7 +874,5 @@ zebra_mpls_vty_init (void) install_element (CONFIG_NODE, &no_mpls_transit_lsp_all_cmd); install_element (VIEW_NODE, &show_mpls_table_cmd); - install_element (ENABLE_NODE, &show_mpls_table_cmd); install_element (VIEW_NODE, &show_mpls_table_lsp_cmd); - install_element (ENABLE_NODE, &show_mpls_table_lsp_cmd); } diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 21fd6a4db9..25091a3eab 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1790,22 +1790,18 @@ zebra_route_map_init () install_element (CONFIG_NODE, &no_ip_protocol_cmd); install_element (CONFIG_NODE, &no_ip_protocol_val_cmd); install_element (VIEW_NODE, &show_ip_protocol_cmd); - install_element (ENABLE_NODE, &show_ip_protocol_cmd); install_element (CONFIG_NODE, &ipv6_protocol_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_val_cmd); install_element (VIEW_NODE, &show_ipv6_protocol_cmd); - install_element (ENABLE_NODE, &show_ipv6_protocol_cmd); install_element (CONFIG_NODE, &ip_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ip_protocol_nht_rmap_val_cmd); install_element (VIEW_NODE, &show_ip_protocol_nht_cmd); - install_element (ENABLE_NODE, &show_ip_protocol_nht_cmd); install_element (CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); install_element (CONFIG_NODE, &no_ipv6_protocol_nht_rmap_val_cmd); install_element (VIEW_NODE, &show_ipv6_protocol_nht_cmd); - install_element (ENABLE_NODE, &show_ipv6_protocol_nht_cmd); install_element (CONFIG_NODE, &zebra_route_map_timer_cmd); install_element (CONFIG_NODE, &no_zebra_route_map_timer_cmd); install_element (CONFIG_NODE, &no_zebra_route_map_timer_val_cmd); From baff583e8bb5f703ab07aab55fea9a7ddf42a468 Mon Sep 17 00:00:00 2001 From: Maitane Zotes Date: Wed, 5 Mar 2014 09:13:43 +0100 Subject: [PATCH 04/18] ospf6d: implement admin distance Until today the admin distance cannot be configured for any IPv6 routing protocol. This patch implements it for ospf6. Signed-off-by: Maitane Zotes Signed-off-by: Roman Hoog Antink --- ospf6d/ospf6_top.c | 185 +++++++++++++++++++++++++++++++++++++++++++ ospf6d/ospf6_top.h | 8 ++ ospf6d/ospf6_zebra.c | 150 +++++++++++++++++++++++++++++++++++ ospf6d/ospf6_zebra.h | 19 +++++ 4 files changed, 362 insertions(+) diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 5def2acf69..3d632b644e 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -155,6 +155,8 @@ ospf6_create (void) o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH; + o->distance_table = route_table_init (); + /* Enable "log-adjacency-changes" */ SET_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES); @@ -184,6 +186,9 @@ ospf6_delete (struct ospf6 *o) ospf6_route_table_delete (o->external_table); route_table_finish (o->external_id_table); + ospf6_distance_reset (o); + route_table_finish (o->distance_table); + XFREE (MTYPE_OSPF6_TOP, o); } @@ -460,6 +465,138 @@ ALIAS (no_ospf6_timers_lsa, "Minimum delay in receiving new version of a LSA\n" "Delay in milliseconds\n") +DEFUN (ospf6_distance, + ospf6_distance_cmd, + "distance <1-255>", + "Administrative distance\n" + "OSPF6 Administrative distance\n") +{ + struct ospf6 *o = vty->index; + + o->distance_all = atoi (argv[0]); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf6_distance, + no_ospf6_distance_cmd, + "no distance <1-255>", + NO_STR + "Administrative distance\n" + "OSPF6 Administrative distance\n") +{ + struct ospf6 *o = vty->index; + + o->distance_all = 0; + + return CMD_SUCCESS; +} + +DEFUN (ospf6_distance_ospf6, + ospf6_distance_ospf6_cmd, + "distance ospf6 {intra-area <1-255>|inter-area <1-255>|external <1-255>}", + "Administrative distance\n" + "OSPF6 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") +{ + struct ospf6 *o = vty->index; + + if (argc < 3) /* should not happen */ + return CMD_WARNING; + + if (!argv[0] && !argv[1] && !argv[2]) + { + vty_out(vty, "%% Command incomplete. (Arguments required)%s", + VTY_NEWLINE); + return CMD_WARNING; + } + + if (argv[0] != NULL) + o->distance_intra = atoi (argv[0]); + + if (argv[1] != NULL) + o->distance_inter = atoi (argv[1]); + + if (argv[2] != NULL) + o->distance_external = atoi (argv[2]); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf6_distance_ospf6, + no_ospf6_distance_ospf6_cmd, + "no distance ospf6 {intra-area <1-255>|inter-area <1-255>|external <1-255>}", + NO_STR + "Administrative distance\n" + "OSPF6 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") +{ + struct ospf6 *o = vty->index; + + if (argc < 3) /* should not happen */ + return CMD_WARNING; + + if (argv[0] != NULL) + o->distance_intra = 0; + + if (argv[1] != NULL) + o->distance_inter = 0; + + if (argv[2] != NULL) + o->distance_external = 0; + + if (argv[0] || argv[1] || argv[2]) + return CMD_SUCCESS; + + /* If no arguments are given, clear all distance information */ + o->distance_intra = 0; + o->distance_inter = 0; + o->distance_external = 0; + + return CMD_SUCCESS; +} + +DEFUN (ospf6_distance_source, + ospf6_distance_source_cmd, + "distance <1-255> X:X::X:X/M [WORD]", + "Administrative distance\n" + "Distance value\n" + "IP source prefix\n" + "Access list name\n") +{ + struct ospf6 *o = vty->index; + + ospf6_distance_set (vty, o, argv[0], argv[1], argc == 3 ? argv[2] : NULL); + + return CMD_SUCCESS; +} + +DEFUN (no_ospf6_distance_source, + no_ospf6_distance_source_cmd, + "no distance <1-255> X:X::X:X/M [WORD]", + NO_STR + "Administrative distance\n" + "Distance value\n" + "IP source prefix\n" + "Access list name\n") +{ + struct ospf6 *o = vty->index; + + ospf6_distance_unset (vty, o, argv[0], argv[1], argc == 3 ? argv[2] : NULL); + + return CMD_SUCCESS; +} + DEFUN (ospf6_interface_area, ospf6_interface_area_cmd, "interface IFNAME area A.B.C.D", @@ -934,6 +1071,44 @@ ospf6_stub_router_config_write (struct vty *vty) return; } +static int +ospf6_distance_config_write (struct vty *vty) +{ + struct route_node *rn; + struct ospf6_distance *odistance; + + if (ospf6->distance_all) + vty_out (vty, " distance %u%s", ospf6->distance_all, VTY_NEWLINE); + + if (ospf6->distance_intra + || ospf6->distance_inter + || ospf6->distance_external) + { + vty_out (vty, " distance ospf6"); + + if (ospf6->distance_intra) + vty_out (vty, " intra-area %u", ospf6->distance_intra); + if (ospf6->distance_inter) + vty_out (vty, " inter-area %u", ospf6->distance_inter); + if (ospf6->distance_external) + vty_out (vty, " external %u", ospf6->distance_external); + + vty_out (vty, "%s", VTY_NEWLINE); + } + + for (rn = route_top (ospf6->distance_table); rn; rn = route_next (rn)) + if ((odistance = rn->info) != NULL) + { + char buf[PREFIX_STRLEN]; + + vty_out (vty, " distance %u %s %s%s", odistance->distance, + prefix2str (&rn->p, buf, sizeof (buf)), + odistance->access_list ? odistance->access_list : "", + VTY_NEWLINE); + } + return 0; +} + /* OSPF configuration write function. */ static int config_write_ospf6 (struct vty *vty) @@ -976,6 +1151,7 @@ config_write_ospf6 (struct vty *vty) ospf6_redistribute_config_write (vty); ospf6_area_config_write (vty); ospf6_spf_config_write (vty); + ospf6_distance_config_write (vty); for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa)) { @@ -1037,6 +1213,15 @@ ospf6_top_init (void) install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd); install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd); */ + + install_element (OSPF6_NODE, &ospf6_distance_cmd); + install_element (OSPF6_NODE, &no_ospf6_distance_cmd); + install_element (OSPF6_NODE, &ospf6_distance_ospf6_cmd); + install_element (OSPF6_NODE, &no_ospf6_distance_ospf6_cmd); +#if 0 + install_element (OSPF6_NODE, &ospf6_distance_source_cmd); + install_element (OSPF6_NODE, &no_ospf6_distance_source_cmd); +#endif } diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 518db3860c..8985eeaa28 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -85,6 +85,14 @@ struct ospf6 struct thread *maxage_remover; u_int32_t ref_bandwidth; + + /* Distance parameters */ + u_char distance_all; + u_char distance_intra; + u_char distance_inter; + u_char distance_external; + + struct route_table *distance_table; }; #define OSPF6_DISABLED 0x01 diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 4d658ed1b8..3e4042d65d 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -40,6 +40,8 @@ #include "ospf6_zebra.h" #include "ospf6d.h" +DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_DISTANCE, "OSPF6 distance") + unsigned char conf_debug_ospf6_zebra = 0; /* information about zebra. */ @@ -480,6 +482,10 @@ ospf6_zebra_route_update (int type, struct ospf6_route *request) } dest = (struct prefix_ipv6 *) &request->prefix; + + SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = ospf6_distance_apply (dest, request); + if (type == REM) ret = zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, dest, &api); else @@ -664,6 +670,150 @@ DEFUN (no_redistribute_ospf6, return CMD_SUCCESS; } +static struct ospf6_distance * +ospf6_distance_new (void) +{ + return XCALLOC (MTYPE_OSPF6_DISTANCE, sizeof (struct ospf6_distance)); +} + +static void +ospf6_distance_free (struct ospf6_distance *odistance) +{ + XFREE (MTYPE_OSPF6_DISTANCE, odistance); +} + +int +ospf6_distance_set (struct vty *vty, struct ospf6 *o, + const char *distance_str, + const char *ip_str, + const char *access_list_str) +{ + int ret; + struct prefix_ipv6 p; + u_char distance; + struct route_node *rn; + struct ospf6_distance *odistance; + + ret = str2prefix_ipv6 (ip_str, &p); + if (ret == 0) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + distance = atoi (distance_str); + + /* Get OSPF6 distance node. */ + rn = route_node_get (o->distance_table, (struct prefix *) &p); + if (rn->info) + { + odistance = rn->info; + route_unlock_node (rn); + } + else + { + odistance = ospf6_distance_new (); + rn->info = odistance; + } + + /* Set distance value. */ + odistance->distance = distance; + + /* Reset access-list configuration. */ + if (odistance->access_list) + { + free (odistance->access_list); + odistance->access_list = NULL; + } + if (access_list_str) + odistance->access_list = strdup (access_list_str); + + return CMD_SUCCESS; +} + +int +ospf6_distance_unset (struct vty *vty, struct ospf6 *o, + const char *distance_str, + const char *ip_str, + const char *access_list_str) +{ + int ret; + struct prefix_ipv6 p; + struct route_node *rn; + struct ospf6_distance *odistance; + + ret = str2prefix_ipv6 (ip_str, &p); + if (ret == 0) + { + vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + rn = route_node_lookup (o->distance_table, (struct prefix *) &p); + if (!rn) + { + vty_out (vty, "Cant't find specified prefix%s", VTY_NEWLINE); + return CMD_WARNING; + } + + odistance = rn->info; + + if (odistance->access_list) + free (odistance->access_list); + ospf6_distance_free (odistance); + + rn->info = NULL; + route_unlock_node (rn); + route_unlock_node (rn); + + return CMD_SUCCESS; +} + +void +ospf6_distance_reset (struct ospf6 *o) +{ + struct route_node *rn; + struct ospf6_distance *odistance; + + for (rn = route_top (o->distance_table); rn; rn = route_next (rn)) + if ((odistance = rn->info) != NULL) + { + if (odistance->access_list) + free (odistance->access_list); + ospf6_distance_free (odistance); + rn->info = NULL; + route_unlock_node (rn); + } +} + +u_char +ospf6_distance_apply (struct prefix_ipv6 *p, struct ospf6_route *or) +{ + struct ospf6 *o; + + o = ospf6; + if (o == NULL) + return 0; + + if (o->distance_intra) + if (or->path.type == OSPF6_PATH_TYPE_INTRA) + return o->distance_intra; + + if (o->distance_inter) + if (or->path.type == OSPF6_PATH_TYPE_INTER) + return o->distance_inter; + + if (o->distance_external) + if(or->path.type == OSPF6_PATH_TYPE_EXTERNAL1 + || or->path.type == OSPF6_PATH_TYPE_EXTERNAL2) + return o->distance_external; + + if (o->distance_all) + return o->distance_all; + + return 0; +} + static void ospf6_zebra_connected (struct zclient *zclient) { diff --git a/ospf6d/ospf6_zebra.h b/ospf6d/ospf6_zebra.h index 5b28c07636..83032b64b1 100644 --- a/ospf6d/ospf6_zebra.h +++ b/ospf6d/ospf6_zebra.h @@ -35,6 +35,16 @@ extern unsigned char conf_debug_ospf6_zebra; #define IS_OSPF6_DEBUG_ZEBRA(e) \ (conf_debug_ospf6_zebra & OSPF6_DEBUG_ZEBRA_ ## e) +/* OSPF6 distance */ +struct ospf6_distance +{ + /* Distance value for the IP source prefix */ + u_char distance; + + /* Name of the access-list to be matched */ + char *access_list; +}; + extern struct zclient *zclient; extern void ospf6_zebra_route_update_add (struct ospf6_route *request); @@ -48,6 +58,15 @@ extern void ospf6_zebra_init (struct thread_master *); extern void ospf6_zebra_add_discard (struct ospf6_route *request); extern void ospf6_zebra_delete_discard (struct ospf6_route *request); +struct ospf6; +extern void ospf6_distance_reset (struct ospf6 *); +extern u_char ospf6_distance_apply (struct prefix_ipv6 *, struct ospf6_route *); + +extern int ospf6_distance_set (struct vty *, struct ospf6 *, const char *, + const char *, const char *); +extern int ospf6_distance_unset (struct vty *, struct ospf6 *, const char *, + const char *, const char *); + extern int config_write_ospf6_debug_zebra (struct vty *vty); extern void install_element_ospf6_debug_zebra (void); From 734b349e15d05fd7722a7b2dd5a5e52c9efe85cb Mon Sep 17 00:00:00 2001 From: Maitane Zotes Date: Mon, 17 Mar 2014 14:01:42 +0100 Subject: [PATCH 05/18] bgpd: implement admin distance Until today the admin distance cannot be configured for any IPv6 routing protocol. This patch implements it for bgp. Signed-off-by: Maitane Zotes Signed-off-by: Roman Hoog Antink --- bgpd/bgp_route.c | 211 +++++++++++++++++++++++++++++++++++------------ bgpd/bgp_route.h | 4 +- bgpd/bgp_zebra.c | 10 ++- bgpd/bgpd.c | 5 +- bgpd/bgpd.h | 6 +- 5 files changed, 173 insertions(+), 63 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index afb37aeef6..44377c3692 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -13995,7 +13995,7 @@ ALIAS (show_bgp_instance_neighbor_damp, #endif /* HAVE_IPV6 */ -struct bgp_table *bgp_distance_table; +struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX]; struct bgp_distance { @@ -14023,12 +14023,17 @@ bgp_distance_set (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; - struct prefix_ipv4 p; + afi_t afi; + safi_t safi; + struct prefix p; u_char distance; struct bgp_node *rn; struct bgp_distance *bdistance; - ret = str2prefix_ipv4 (ip_str, &p); + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); + + ret = str2prefix (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); @@ -14038,7 +14043,7 @@ bgp_distance_set (struct vty *vty, const char *distance_str, distance = atoi (distance_str); /* Get BGP distance node. */ - rn = bgp_node_get (bgp_distance_table, (struct prefix *) &p); + rn = bgp_node_get (bgp_distance_table[afi][safi], (struct prefix *) &p); if (rn->info) { bdistance = rn->info; @@ -14070,19 +14075,24 @@ bgp_distance_unset (struct vty *vty, const char *distance_str, const char *ip_str, const char *access_list_str) { int ret; + afi_t afi; + safi_t safi; + struct prefix p; int distance; - struct prefix_ipv4 p; struct bgp_node *rn; struct bgp_distance *bdistance; - ret = str2prefix_ipv4 (ip_str, &p); + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); + + ret = str2prefix (ip_str, &p); if (ret == 0) { vty_out (vty, "Malformed prefix%s", VTY_NEWLINE); return CMD_WARNING; } - rn = bgp_node_lookup (bgp_distance_table, (struct prefix *)&p); + rn = bgp_node_lookup (bgp_distance_table[afi][safi], (struct prefix *)&p); if (! rn) { vty_out (vty, "Can't find specified prefix%s", VTY_NEWLINE); @@ -14111,10 +14121,11 @@ bgp_distance_unset (struct vty *vty, const char *distance_str, /* Apply BGP information to distance method. */ u_char -bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) +bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, afi_t afi, + safi_t safi, struct bgp *bgp) { struct bgp_node *rn; - struct prefix_ipv4 q; + struct prefix q; struct peer *peer; struct bgp_distance *bdistance; struct access_list *alist; @@ -14123,21 +14134,11 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (! bgp) return 0; - if (p->family != AF_INET) - return 0; - peer = rinfo->peer; - if (peer->su.sa.sa_family != AF_INET) - return 0; - - memset (&q, 0, sizeof (struct prefix_ipv4)); - q.family = AF_INET; - q.prefix = peer->su.sin.sin_addr; - q.prefixlen = IPV4_MAX_BITLEN; - /* Check source address. */ - rn = bgp_node_match (bgp_distance_table, (struct prefix *) &q); + sockunion2hostprefix (&peer->su, &q); + rn = bgp_node_match (bgp_distance_table[afi][safi], &q); if (rn) { bdistance = rn->info; @@ -14145,7 +14146,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (bdistance->access_list) { - alist = access_list_lookup (AFI_IP, bdistance->access_list); + alist = access_list_lookup (afi, bdistance->access_list); if (alist && access_list_apply (alist, p) == FILTER_PERMIT) return bdistance->distance; } @@ -14154,7 +14155,7 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) } /* Backdoor check. */ - rn = bgp_node_lookup (bgp->route[AFI_IP][SAFI_UNICAST], p); + rn = bgp_node_lookup (bgp->route[afi][safi], p); if (rn) { bgp_static = rn->info; @@ -14162,8 +14163,8 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (bgp_static->backdoor) { - if (bgp->distance_local) - return bgp->distance_local; + if (bgp->distance_local[afi][safi]) + return bgp->distance_local[afi][safi]; else return ZEBRA_IBGP_DISTANCE_DEFAULT; } @@ -14171,14 +14172,14 @@ bgp_distance_apply (struct prefix *p, struct bgp_info *rinfo, struct bgp *bgp) if (peer->sort == BGP_PEER_EBGP) { - if (bgp->distance_ebgp) - return bgp->distance_ebgp; + if (bgp->distance_ebgp[afi][safi]) + return bgp->distance_ebgp[afi][safi]; return ZEBRA_EBGP_DISTANCE_DEFAULT; } else { - if (bgp->distance_ibgp) - return bgp->distance_ibgp; + if (bgp->distance_ibgp[afi][safi]) + return bgp->distance_ibgp[afi][safi]; return ZEBRA_IBGP_DISTANCE_DEFAULT; } } @@ -14193,12 +14194,16 @@ DEFUN (bgp_distance, "Distance for local routes\n") { struct bgp *bgp; + afi_t afi; + safi_t safi; bgp = vty->index; + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); - bgp->distance_ebgp = atoi (argv[0]); - bgp->distance_ibgp = atoi (argv[1]); - bgp->distance_local = atoi (argv[2]); + bgp->distance_ebgp[afi][safi] = atoi (argv[0]); + bgp->distance_ibgp[afi][safi] = atoi (argv[1]); + bgp->distance_local[afi][safi] = atoi (argv[2]); return CMD_SUCCESS; } @@ -14213,12 +14218,16 @@ DEFUN (no_bgp_distance, "Distance for local routes\n") { struct bgp *bgp; + afi_t afi; + safi_t safi; bgp = vty->index; + afi = bgp_node_afi (vty); + safi = bgp_node_safi (vty); - bgp->distance_ebgp= 0; - bgp->distance_ibgp = 0; - bgp->distance_local = 0; + bgp->distance_ebgp[afi][safi] = 0; + bgp->distance_ibgp[afi][safi] = 0; + bgp->distance_local[afi][safi] = 0; return CMD_SUCCESS; } @@ -14277,6 +14286,54 @@ DEFUN (no_bgp_distance_source_access_list, return CMD_SUCCESS; } +DEFUN (ipv6_bgp_distance_source, + ipv6_bgp_distance_source_cmd, + "distance <1-255> X:X::X:X/M", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_set (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_bgp_distance_source, + no_ipv6_bgp_distance_source_cmd, + "no distance <1-255> X:X::X:X/M", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], NULL); + return CMD_SUCCESS; +} + +DEFUN (ipv6_bgp_distance_source_access_list, + ipv6_bgp_distance_source_access_list_cmd, + "distance <1-255> X:X::X:X/M WORD", + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_set (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_bgp_distance_source_access_list, + no_ipv6_bgp_distance_source_access_list_cmd, + "no distance <1-255> X:X::X:X/M WORD", + NO_STR + "Define an administrative distance\n" + "Administrative distance\n" + "IP source prefix\n" + "Access list name\n") +{ + bgp_distance_unset (vty, argv[0], argv[1], argv[2]); + return CMD_SUCCESS; +} + DEFUN (bgp_damp_set, bgp_damp_set_cmd, "bgp dampening <1-45> <1-20000> <1-20000> <1-255>", @@ -14711,40 +14768,53 @@ bgp_config_write_network (struct vty *vty, struct bgp *bgp, } int -bgp_config_write_distance (struct vty *vty, struct bgp *bgp) +bgp_config_write_distance (struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi, int *write) { struct bgp_node *rn; struct bgp_distance *bdistance; /* Distance configuration. */ - if (bgp->distance_ebgp - && bgp->distance_ibgp - && bgp->distance_local - && (bgp->distance_ebgp != ZEBRA_EBGP_DISTANCE_DEFAULT - || bgp->distance_ibgp != ZEBRA_IBGP_DISTANCE_DEFAULT - || bgp->distance_local != ZEBRA_IBGP_DISTANCE_DEFAULT)) - vty_out (vty, " distance bgp %d %d %d%s", - bgp->distance_ebgp, bgp->distance_ibgp, bgp->distance_local, - VTY_NEWLINE); - - for (rn = bgp_table_top (bgp_distance_table); rn; rn = bgp_route_next (rn)) + if (bgp->distance_ebgp[afi][safi] + && bgp->distance_ibgp[afi][safi] + && bgp->distance_local[afi][safi] + && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT + || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT + || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT)) + { + bgp_config_write_family_header (vty, afi, safi, write); + vty_out (vty, " distance bgp %d %d %d%s", + bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi], + bgp->distance_local[afi][safi], VTY_NEWLINE); + } + + for (rn = bgp_table_top (bgp_distance_table[afi][safi]); rn; + rn = bgp_route_next (rn)) if ((bdistance = rn->info) != NULL) { - vty_out (vty, " distance %d %s/%d %s%s", bdistance->distance, - inet_ntoa (rn->p.u.prefix4), rn->p.prefixlen, + char buf[PREFIX_STRLEN]; + + bgp_config_write_family_header (vty, afi, safi, write); + vty_out (vty, " distance %d %s %s%s", bdistance->distance, + prefix2str (&rn->p, buf, sizeof (buf)), bdistance->access_list ? bdistance->access_list : "", VTY_NEWLINE); } - return 0; + return *write; } /* Allocate routing table structure and install commands. */ void bgp_route_init (void) { + afi_t afi; + safi_t safi; + /* Init BGP distance table. */ - bgp_distance_table = bgp_table_init (AFI_IP, SAFI_UNICAST); + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + bgp_distance_table[afi][safi] = bgp_table_init (afi, safi); /* IPv4 BGP commands. */ install_element (BGP_NODE, &bgp_table_map_cmd); @@ -15178,6 +15248,34 @@ bgp_route_init (void) install_element (BGP_NODE, &no_bgp_distance_source_cmd); install_element (BGP_NODE, &bgp_distance_source_access_list_cmd); install_element (BGP_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_source_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_source_cmd); + install_element (BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_source_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_cmd); + install_element (BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd); + install_element (BGP_IPV4M_NODE, &no_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6_NODE, &bgp_distance_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV6_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6_NODE, &ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6M_NODE, &bgp_distance_cmd); + install_element (BGP_IPV6M_NODE, &no_bgp_distance_cmd); + install_element (BGP_IPV6M_NODE, &no_bgp_distance2_cmd); + install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd); + install_element (BGP_IPV6M_NODE, &ipv6_bgp_distance_source_access_list_cmd); + install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_access_list_cmd); install_element (BGP_NODE, &bgp_damp_set_cmd); install_element (BGP_NODE, &bgp_damp_set2_cmd); @@ -15203,6 +15301,13 @@ bgp_route_init (void) void bgp_route_finish (void) { - bgp_table_unlock (bgp_distance_table); - bgp_distance_table = NULL; + afi_t afi; + safi_t safi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + bgp_table_unlock (bgp_distance_table[afi][safi]); + bgp_distance_table[afi][safi] = NULL; + } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0dce5da572..bb06204689 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -307,14 +307,14 @@ extern void bgp_add_eoiu_mark (struct bgp *); extern int bgp_config_write_table_map (struct vty *, struct bgp *, afi_t, safi_t, int *); extern int bgp_config_write_network (struct vty *, struct bgp *, afi_t, safi_t, int *); -extern int bgp_config_write_distance (struct vty *, struct bgp *); +extern int bgp_config_write_distance (struct vty *, struct bgp *, afi_t, safi_t, int *); extern void bgp_aggregate_increment (struct bgp *, struct prefix *, struct bgp_info *, afi_t, safi_t); extern void bgp_aggregate_decrement (struct bgp *, struct prefix *, struct bgp_info *, afi_t, safi_t); -extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, struct bgp *); +extern u_char bgp_distance_apply (struct prefix *, struct bgp_info *, afi_t, safi_t, struct bgp *); extern afi_t bgp_node_afi (struct vty *); extern safi_t bgp_node_safi (struct vty *); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 11e888d7e9..8ecd025397 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1367,8 +1367,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.tag = tag; } - distance = bgp_distance_apply (p, info, bgp); - + distance = bgp_distance_apply (p, info, afi, safi, bgp); if (distance) { SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); @@ -1554,6 +1553,13 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, api.tag = tag; } + distance = bgp_distance_apply (p, info, afi, safi, bgp); + if (distance) + { + SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); + api.distance = distance; + } + if (p->family == AF_INET) { if (bgp_debug_zebra(p)) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 71c2c84e61..403468a630 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7123,6 +7123,8 @@ bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi, struct peer_group *group; struct listnode *node, *nnode; + bgp_config_write_distance (vty, bgp, afi, safi, &write); + bgp_config_write_network (vty, bgp, afi, safi, &write); bgp_config_write_redistribute (vty, bgp, afi, safi, &write); @@ -7371,9 +7373,6 @@ bgp_config_write (struct vty *vty) bgp_config_write_peer_global (vty, bgp, peer); } - /* Distance configuration. */ - bgp_config_write_distance (vty, bgp); - /* listen range and limit for dynamic BGP neighbors */ bgp_config_write_listen (vty, bgp); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index ee105201e8..f6e8598494 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -320,9 +320,9 @@ struct bgp #define RMAP_DEFAULT_ORIGINATE_EVAL_TIMER 5 /* BGP distance configuration. */ - u_char distance_ebgp; - u_char distance_ibgp; - u_char distance_local; + u_char distance_ebgp[AFI_MAX][SAFI_MAX]; + u_char distance_ibgp[AFI_MAX][SAFI_MAX]; + u_char distance_local[AFI_MAX][SAFI_MAX]; /* BGP default local-preference. */ u_int32_t default_local_pref; From 7b8def580a061c7e454db83b85e8453d13d65c78 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 19 Oct 2016 13:44:38 -0400 Subject: [PATCH 06/18] bgpd: Fix shutdown order. When shutting down bgp we were freeing the ecommunity hash before we unintern'ed everything in it. This is fallout from: 289d250 bgpd, lib: memory cleanups for valgrind, plus debug changes Basically we started free'ing data we've never freed before which caused us to access a hash that had already been freed. Signed-off-by: Donald Sharp --- bgpd/bgp_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c index 3aa16b2632..50ca7eda4c 100644 --- a/bgpd/bgp_main.c +++ b/bgpd/bgp_main.c @@ -253,9 +253,6 @@ bgp_exit (int status) bgp_delete (bgp); list_free (bm->bgp); - /* reverse bgp_attr_init */ - bgp_attr_finish (); - /* reverse bgp_dump_init */ bgp_dump_finish (); @@ -265,6 +262,9 @@ bgp_exit (int status) /* cleanup route maps */ bgp_route_map_terminate(); + /* reverse bgp_attr_init */ + bgp_attr_finish (); + /* reverse access_list_init */ access_list_add_hook (NULL); access_list_delete_hook (NULL); From c6a7d59c20f238aab096f918acf84ca30265ed07 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Thu, 20 Oct 2016 17:21:34 +0000 Subject: [PATCH 07/18] bgpd: 'show ip bgp summary json' shows large negative value for "peerUptimeMsec" Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Reviewed-by: Don Slice Ticket: CM-13239 --- bgpd/bgpd.c | 30 ++++++++++-------------------- lib/json.c | 6 ++++++ lib/json.h | 2 ++ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 403468a630..df7be41ef9 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6193,7 +6193,6 @@ peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi, } /* Display peer uptime.*/ -/* XXX: why does this function return char * when it takes buffer? */ char * peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json) { @@ -6216,7 +6215,10 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object if (uptime2 == 0) { if (use_json) - json_object_string_add(json, "peerUptime", "never"); + { + json_object_string_add(json, "peerUptime", "never"); + json_object_int_add(json, "peerUptimeMsec", 0); + } else snprintf (buf, len, "never"); return buf; @@ -6232,24 +6234,6 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object #define ONE_WEEK_SECOND ONE_DAY_SECOND*7 #define ONE_YEAR_SECOND ONE_DAY_SECOND*365 - if (use_json) - { - unsigned long time_store; - unsigned long sec_msec = 1000; - unsigned long minute_msec = sec_msec * 60; - unsigned long hour_msec = minute_msec * 60; - unsigned long day_msec = hour_msec * 24; - unsigned long year_msec = day_msec *365; - - time_store = - year_msec * tm->tm_year + - day_msec * tm->tm_yday + - hour_msec * tm->tm_hour + - minute_msec * tm->tm_min + - sec_msec * tm->tm_sec; - json_object_int_add(json, "peerUptimeMsec", time_store); - } - if (uptime1 < ONE_DAY_SECOND) snprintf (buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); @@ -6264,6 +6248,12 @@ peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object tm->tm_year - 70, tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7)); + if (use_json) + { + json_object_string_add(json, "peerUptime", buf); + json_object_long_add(json, "peerUptimeMsec", uptime1 * 1000); + } + return buf; } diff --git a/lib/json.c b/lib/json.c index 58f0e995f2..ca30c60984 100644 --- a/lib/json.c +++ b/lib/json.c @@ -53,6 +53,12 @@ json_object_int_add(struct json_object* obj, const char *key, int32_t i) json_object_object_add(obj, key, json_object_new_int(i)); } +void +json_object_long_add(struct json_object* obj, const char *key, int64_t i) +{ + json_object_object_add(obj, key, json_object_new_int64(i)); +} + void json_object_boolean_false_add(struct json_object* obj, const char *key) { diff --git a/lib/json.h b/lib/json.h index c8d7fae1cd..b217df0a7b 100644 --- a/lib/json.h +++ b/lib/json.h @@ -39,6 +39,8 @@ extern void json_object_string_add(struct json_object* obj, const char *key, const char *s); extern void json_object_int_add(struct json_object* obj, const char *key, int32_t i); +extern void json_object_long_add(struct json_object* obj, const char *key, + int64_t i); extern void json_object_boolean_false_add(struct json_object* obj, const char *key); extern void json_object_boolean_true_add(struct json_object* obj, From 6e71194f115ece3985665b7c6e22818b79c3c533 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:06:56 +0200 Subject: [PATCH 08/18] bgpd: setting nexthop doesn't need inet_pton Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- bgpd/bgp_routemap.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 0702b4ffd1..ebf83a783e 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2267,7 +2267,6 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix, struct in6_addr peer_address; struct bgp_info *bgp_info; struct peer *peer; - char peer_addr_buf[INET6_ADDRSTRLEN]; if (type == RMAP_BGP) { @@ -2280,10 +2279,7 @@ route_set_ipv6_nexthop_peer (void *rule, struct prefix *prefix, && peer->su_remote && sockunion_family (peer->su_remote) == AF_INET6) { - inet_pton (AF_INET6, sockunion2str (peer->su_remote, - peer_addr_buf, - INET6_ADDRSTRLEN), - &peer_address); + peer_address = peer->su_remote->sin6.sin6_addr; /* Set next hop value and length in attribute. */ if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) { From b84ee83b10473391caa7a8dbc3d7a21f9558a95d Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:06:59 +0200 Subject: [PATCH 09/18] bgpd: don't leak memory in community_regexp_include Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- bgpd/bgp_clist.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 12c936b190..9032b1e2f4 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -403,17 +403,22 @@ community_str_get (struct community *com, int i) static int community_regexp_include (regex_t * reg, struct community *com, int i) { - const char *str; + char *str; + int rv; /* When there is no communities attribute it is treated as empty * string. */ if (com == NULL || com->size == 0) - str = ""; + str = XSTRDUP(MTYPE_COMMUNITY_STR, ""); else str = community_str_get (com, i); /* Regular expression match. */ - if (regexec (reg, str, 0, NULL, 0) == 0) + rv = regexec (reg, str, 0, NULL, 0); + + XFREE(MTYPE_COMMUNITY_STR, str); + + if (rv == 0) return 1; /* No match. */ From 099111efa997efa69596cff9b3a598464fc854cf Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:00 +0200 Subject: [PATCH 10/18] bgpd: fix off-by-one in attribute flags handling bgp_attr_flag_invalid can access beyond the last element of attr_flags_values. Fix this by initializing attr_flags_values_max to the correct value. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- bgpd/bgp_attr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index a366a09453..89b1c75f6b 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1143,8 +1143,7 @@ const u_int8_t attr_flags_values [] = { [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, }; -static const size_t attr_flags_values_max = - sizeof (attr_flags_values) / sizeof (attr_flags_values[0]); +static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; static int bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) From c8cdf5c774c1e2dcd25d06f995deda7fe72fb9dc Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:02 +0200 Subject: [PATCH 11/18] ospfd: fix double assignment in ospf_vl_set_timers Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- ospfd/ospf_vty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 9da36f6a6c..dbda2bc757 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -968,7 +968,7 @@ static int ospf_vl_set_timers (struct ospf_vl_data *vl_data, struct ospf_vl_config_data *vl_config) { - struct interface *ifp = ifp = vl_data->vl_oi->ifp; + 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) From e531bbe2f06e01e5f890e9a62ae25b093407e4c3 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:04 +0200 Subject: [PATCH 12/18] ospf6d: fix off-by-one on display of spf reasons The loop should only iterate to array_size - 1. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- ospf6d/ospf6_spf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c index 957988b53d..7e977499cf 100644 --- a/ospf6d/ospf6_spf.c +++ b/ospf6d/ospf6_spf.c @@ -444,7 +444,7 @@ void ospf6_spf_reason_string (unsigned int reason, char *buf, int size) if (!buf) return; - for (bit = 0; bit <= (sizeof(ospf6_spf_reason_str) / sizeof(char *)); bit++) + for (bit = 0; bit < array_size(ospf6_spf_reason_str); bit++) { if ((reason & (1 << bit)) && (len < size)) { From b6175e0ca2a741e2efcf44422e014b0678cf0865 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:01 +0200 Subject: [PATCH 13/18] bgpd: fix memory leaks in show commands sockunion_str2su allocates a struct sockunion that used to be leaked in the show commands. Use str2sockunion and keep the information on the stack instead. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp Signed-off-by: Philippe Guibert --- bgpd/bgp_encap.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c index ac99169e7f..c60b592133 100644 --- a/bgpd/bgp_encap.c +++ b/bgpd/bgp_encap.c @@ -620,24 +620,23 @@ DEFUN (show_bgp_ipv4_encap_neighbor_routes, "Neighbor to display information about\n" "Display routes learned from neighbor\n") { - union sockunion *su; + union sockunion su; struct peer *peer; - - su = sockunion_str2su (argv[0]); - if (su == NULL) + + if (str2sockunion(argv[0], &su)) { vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - peer = peer_lookup (NULL, su); + peer = peer_lookup (NULL, &su); if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_encap (vty, AFI_IP, NULL, bgp_show_type_neighbor, su, 0); + return bgp_show_encap (vty, AFI_IP, NULL, bgp_show_type_neighbor, &su, 0); } #ifdef HAVE_IPV6 DEFUN (show_bgp_ipv6_encap_neighbor_routes, @@ -651,24 +650,23 @@ DEFUN (show_bgp_ipv6_encap_neighbor_routes, "Neighbor to display information about\n" "Display routes learned from neighbor\n") { - union sockunion *su; + union sockunion su; struct peer *peer; - su = sockunion_str2su (argv[0]); - if (su == NULL) + if (str2sockunion(argv[0], &su)) { vty_out (vty, "Malformed address: %s%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - peer = peer_lookup (NULL, su); + peer = peer_lookup (NULL, &su); if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_encap (vty, AFI_IP6, NULL, bgp_show_type_neighbor, su, 0); + return bgp_show_encap (vty, AFI_IP6, NULL, bgp_show_type_neighbor, &su, 0); } #endif @@ -687,7 +685,7 @@ DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes, "Display routes learned from neighbor\n") { int ret; - union sockunion *su; + union sockunion su; struct peer *peer; struct prefix_rd prd; @@ -698,21 +696,20 @@ DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes, return CMD_WARNING; } - su = sockunion_str2su (argv[1]); - if (su == NULL) + if (str2sockunion(argv[1], &su)) { vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE); return CMD_WARNING; } - peer = peer_lookup (NULL, su); + peer = peer_lookup (NULL, &su); if (! peer || ! peer->afc[AFI_IP][SAFI_ENCAP]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_encap (vty, AFI_IP, &prd, bgp_show_type_neighbor, su, 0); + return bgp_show_encap (vty, AFI_IP, &prd, bgp_show_type_neighbor, &su, 0); } #ifdef HAVE_IPV6 DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes, @@ -730,7 +727,7 @@ DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes, "Display routes learned from neighbor\n") { int ret; - union sockunion *su; + union sockunion su; struct peer *peer; struct prefix_rd prd; @@ -741,21 +738,20 @@ DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes, return CMD_WARNING; } - su = sockunion_str2su (argv[1]); - if (su == NULL) + if (str2sockunion(argv[1], &su)) { vty_out (vty, "Malformed address: %s%s", argv[1], VTY_NEWLINE); return CMD_WARNING; } - peer = peer_lookup (NULL, su); + peer = peer_lookup (NULL, &su); if (! peer || ! peer->afc[AFI_IP6][SAFI_ENCAP]) { vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE); return CMD_WARNING; } - return bgp_show_encap (vty, AFI_IP6, &prd, bgp_show_type_neighbor, su, 0); + return bgp_show_encap (vty, AFI_IP6, &prd, bgp_show_type_neighbor, &su, 0); } #endif From 881d5b3b61a00c6c69598c1d5076ae279263bd2c Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:05 +0200 Subject: [PATCH 14/18] isisd: fix an error that was probably a result of copypasting The code should check for the existance of the correct list prior to accessing it. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- isisd/isis_circuit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index c66fa48263..c2b7ec7507 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -979,7 +979,7 @@ isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, vty_out(vty, " %s%s", buf, VTY_NEWLINE); } } - if (circuit->ipv6_link && listcount(circuit->ipv6_non_link) > 0) + if (circuit->ipv6_non_link && listcount(circuit->ipv6_non_link) > 0) { vty_out(vty, " IPv6 Prefixes:%s", VTY_NEWLINE); for (ALL_LIST_ELEMENTS_RO(circuit->ipv6_non_link, node, ip_addr)) From 6465ad886120f514001e826d35efa14ec0ba409c Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:06 +0200 Subject: [PATCH 15/18] isisd: Fix size of malloc Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- isisd/isis_routemap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index 1f947fb047..070965b2df 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -230,7 +230,7 @@ route_set_metric_compile(const char *arg) if (arg[0] == '\0' || *endp != '\0' || metric > MAX_WIDE_PATH_METRIC) return NULL; - ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(ret)); + ret = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*ret)); *ret = metric; return ret; From 2447614b9c283ee419543d480a8cb2918ce470e6 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:07 +0200 Subject: [PATCH 16/18] pimd: don't leak original_s_route on error original_s_route is allocated on the heap and was not freed during the error case. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- pimd/pim_static.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pimd/pim_static.c b/pimd/pim_static.c index c1154dc088..5882142b32 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -198,6 +198,10 @@ int pim_static_add(struct interface *iif, struct interface *oif, struct in_addr pim_static_route_free(s_route); } + if (original_s_route) { + pim_static_route_free(original_s_route); + } + return -1; } From 58093a791767e5c1e412a6d3fcbe6927f4ffda0b Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:08 +0200 Subject: [PATCH 17/18] ripd: print md5 auth digest correctly The dump of the md5 hash was missing one byte of the hash. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- ripd/ripd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ripd/ripd.c b/ripd/ripd.c index ab81996640..6124471161 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -748,9 +748,9 @@ rip_packet_dump (struct rip_packet *packet, int size, const char *sndrcv) zlog_debug (" family 0x%X type %d (MD5 data)", ntohs (rte->family), ntohs (rte->tag)); zlog_debug (" MD5: %02X%02X%02X%02X%02X%02X%02X%02X" - "%02X%02X%02X%02X%02X%02X%02X", + "%02X%02X%02X%02X%02X%02X%02X%02X", p[0], p[1], p[2], p[3], p[4], p[5], p[6], - p[7], p[9], p[10], p[11], p[12], p[13], + p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); } else From ce01a2ca3f4501b75e55fe325c150eb9c2ae329d Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Tue, 14 Jun 2016 20:07:09 +0200 Subject: [PATCH 18/18] vtysh: handle case if there is no match in "write terminal $daemon" While the DEFUN should match the list of clients registered in vtysh, it seems better to handle the case explicitly instead of relying on the client list and the DEFUN signature being in sync. Signed-off-by: Christian Franke Signed-off-by: Christian Franke Acked-by: Donald Sharp --- vtysh/vtysh.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 4b579ddbdb..a5e146c945 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2409,6 +2409,9 @@ DEFUN (vtysh_write_terminal_daemon, break; } + if (i == array_size(vtysh_client)) + return CMD_ERR_NO_MATCH; + ret = vtysh_client_execute(&vtysh_client[i], "show running-config\n", stdout); return ret;