summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ospf6d/ospf6_top.c185
-rw-r--r--ospf6d/ospf6_top.h8
-rw-r--r--ospf6d/ospf6_zebra.c150
-rw-r--r--ospf6d/ospf6_zebra.h19
4 files changed, 362 insertions, 0 deletions
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);