summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c3
-rw-r--r--bgpd/bgp_clist.c11
-rw-r--r--bgpd/bgp_encap.c38
-rw-r--r--bgpd/bgp_main.c6
-rw-r--r--bgpd/bgp_route.c221
-rw-r--r--bgpd/bgp_route.h4
-rw-r--r--bgpd/bgp_routemap.c6
-rw-r--r--bgpd/bgp_zebra.c10
-rw-r--r--bgpd/bgpd.c35
-rw-r--r--bgpd/bgpd.h6
-rw-r--r--isisd/isis_circuit.c2
-rw-r--r--isisd/isis_routemap.c2
-rw-r--r--lib/command.c42
-rw-r--r--lib/command.h4
-rw-r--r--lib/json.c6
-rw-r--r--lib/json.h2
-rw-r--r--ospf6d/ospf6_spf.c2
-rw-r--r--ospf6d/ospf6_top.c262
-rw-r--r--ospf6d/ospf6_top.h8
-rw-r--r--ospf6d/ospf6_zebra.c150
-rw-r--r--ospf6d/ospf6_zebra.h19
-rw-r--r--ospfd/ospf_vty.c2
-rw-r--r--pimd/pim_static.c4
-rw-r--r--ripd/ripd.c4
-rw-r--r--vtysh/vtysh.c3
25 files changed, 705 insertions, 147 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 08398192f3..fa941e8e6a 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1144,8 +1144,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)
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. */
diff --git a/bgpd/bgp_encap.c b/bgpd/bgp_encap.c
index bb62e37134..499401bd4f 100644
--- a/bgpd/bgp_encap.c
+++ b/bgpd/bgp_encap.c
@@ -631,24 +631,23 @@ DEFUN (show_bgp_ipv4_encap_neighbor_routes,
"Display routes learned from neighbor\n")
{
int idx_peer = 5;
- union sockunion *su;
+ union sockunion su;
struct peer *peer;
-
- su = sockunion_str2su (argv[idx_peer]->arg);
- if (su == NULL)
+
+ if (sockunion_str2su (argv[idx_peer]->arg))
{
vty_out (vty, "Malformed address: %s%s", argv[idx_peer]->arg, 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,
@@ -663,24 +662,23 @@ DEFUN (show_bgp_ipv6_encap_neighbor_routes,
"Display routes learned from neighbor\n")
{
int idx_peer = 5;
- union sockunion *su;
+ union sockunion su;
struct peer *peer;
- su = sockunion_str2su (argv[idx_peer]->arg);
- if (su == NULL)
+ if (str2sockunion(argv[idx_peer]->arg, &su))
{
vty_out (vty, "Malformed address: %s%s", argv[idx_peer]->arg, 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
@@ -701,7 +699,7 @@ DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes,
int idx_rd = 5;
int idx_peer = 7;
int ret;
- union sockunion *su;
+ union sockunion su;
struct peer *peer;
struct prefix_rd prd;
@@ -712,21 +710,20 @@ DEFUN (show_bgp_ipv4_encap_rd_neighbor_routes,
return CMD_WARNING;
}
- su = sockunion_str2su (argv[idx_peer]->arg);
- if (su == NULL)
+ if (str2sockunion(argv[idx_peer]->arg, &su))
{
vty_out (vty, "Malformed address: %s%s", argv[idx_peer]->arg, 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,
@@ -746,7 +743,7 @@ DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes,
int idx_rd = 5;
int idx_peer = 7;
int ret;
- union sockunion *su;
+ union sockunion su;
struct peer *peer;
struct prefix_rd prd;
@@ -757,21 +754,20 @@ DEFUN (show_bgp_ipv6_encap_rd_neighbor_routes,
return CMD_WARNING;
}
- su = sockunion_str2su (argv[idx_peer]->arg);
- if (su == NULL)
+ if (str2sockunion(argv[idx_peer]->arg, &su))
{
vty_out (vty, "Malformed address: %s%s", argv[idx_peer]->arg, 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
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);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index b03b296ea8..cfe4f8b7b4 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -8110,15 +8110,6 @@ DEFUN (show_ip_bgp_ipv4,
if (strmatch(argv[idx]->text, "cidr-only"))
return bgp_show (vty, bgp, afi, safi, bgp_show_type_cidr_only, NULL, uj);
- else if (strmatch(argv[idx]->text, "dampening"))
- {
- if (strmatch(argv[idx + 1]->text, "dampened-paths"))
- return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj);
-
- else if (strmatch(argv[idx + 1]->text, "flap-statistics"))
- return bgp_show (vty, bgp, afi, safi, bgp_show_type_flap_statistics, NULL, uj);
- }
-
else if (strmatch(argv[idx]->text, "dampened-paths"))
return bgp_show (vty, bgp, afi, safi, bgp_show_type_dampend_paths, NULL, uj);
@@ -8295,10 +8286,14 @@ DEFUN (show_ip_bgp_instance_all,
return CMD_SUCCESS;
}
+
static int
bgp_show_regexp (struct vty *vty, int argc, struct cmd_token **argv, afi_t afi,
safi_t safi, enum bgp_show_type type)
{
+ return CMD_SUCCESS;
+/* XXX(vtysh-grammar): Needs updating for new CLI backend.
+
int i;
struct buffer *b;
char *regstr;
@@ -8338,6 +8333,7 @@ bgp_show_regexp (struct vty *vty, int argc, struct cmd_token **argv, afi_t afi,
rc = bgp_show (vty, NULL, afi, safi, type, regex, 0);
bgp_regex_free (regex);
return rc;
+*/
}
static int
@@ -9827,7 +9823,7 @@ DEFUN (show_ip_bgp_neighbor_routes,
return bgp_show_neighbor_route (vty, peer, afi, safi, sh_type, uj);
}
-struct bgp_table *bgp_distance_table;
+struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
struct bgp_distance
{
@@ -9855,12 +9851,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);
@@ -9870,7 +9871,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;
@@ -9902,19 +9903,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);
@@ -9943,10 +9949,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;
@@ -9955,21 +9962,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;
@@ -9977,7 +9974,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;
}
@@ -9986,7 +9983,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;
@@ -9994,8 +9991,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;
}
@@ -10003,14 +10000,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;
}
}
@@ -10028,12 +10025,16 @@ DEFUN (bgp_distance,
int idx_number_2 = 3;
int idx_number_3 = 4;
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[idx_number]->arg);
- bgp->distance_ibgp = atoi (argv[idx_number_2]->arg);
- bgp->distance_local = atoi (argv[idx_number_3]->arg);
+ bgp->distance_ebgp[afi][safi] = atoi (argv[idx_number]->arg);
+ bgp->distance_ibgp[afi][safi] = atoi (argv[idx_number_2]->arg);
+ bgp->distance_local[afi][safi] = atoi (argv[idx_number_3]->arg);
return CMD_SUCCESS;
}
@@ -10048,12 +10049,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;
}
@@ -10116,6 +10121,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[1]->arg, argv[2]->arg, 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[2]->arg, argv[3]->arg, 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[1]->arg, argv[2]->arg, argv[3]->arg);
+ 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[2]->arg, argv[3]->arg, argv[4]->arg);
+ return CMD_SUCCESS;
+}
+
DEFUN (bgp_damp_set,
bgp_damp_set_cmd,
"bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
@@ -10484,40 +10537,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);
@@ -10656,6 +10722,30 @@ 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, &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, &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, &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, &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_unset_cmd);
@@ -10670,6 +10760,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_routemap.c b/bgpd/bgp_routemap.c
index 6933611abd..1ddae3cd88 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2268,7 +2268,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)
{
@@ -2281,10 +2280,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))
{
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 64ebbea6a6..0cb8e6bb9f 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;
}
@@ -7123,6 +7113,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 +7363,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;
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))
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index 1d734fbc2f..61f3315f08 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;
diff --git a/lib/command.c b/lib/command.c
index 3416bcd1c7..f9c4107745 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -213,6 +213,18 @@ argv_find (struct cmd_token **argv, int argc, const char *text, int *index)
return found;
}
+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,
@@ -225,6 +237,7 @@ install_node (struct cmd_node *node,
// add start node
struct cmd_token *token = new_cmd_token (START_TKN, NULL, NULL);
graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token);
+ node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp);
}
/* Breaking up string into each command piece. I assume given
@@ -332,8 +345,12 @@ 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);
if (cnode == NULL)
@@ -342,19 +359,17 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
ntype);
exit (EXIT_FAILURE);
}
-
- // add node to command graph and command vector
- // idiotic O(n) deduplication logic, should just use a merkle tree
- for (unsigned int i = 0; i < vector_active (cnode->cmd_vector); i++)
- {
- struct cmd_element *existing = vector_slot (cnode->cmd_vector, i);
- if (strmatch (existing->string, cmd->string))
+
+ if (hash_lookup (cnode->cmd_hash, cmd) != NULL)
{
- zlog_warn ("Duplicate command: %s\n", cmd->string);
+ 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));
+
command_parse_format (cnode->cmdgraph, cmd);
vector_set (cnode->cmd_vector, cmd);
@@ -2433,6 +2448,9 @@ cmd_terminate ()
// deleting the graph delets the cmd_element as well
graph_delete_graph (cmd_node->cmdgraph);
vector_free (cmd_node->cmd_vector);
+ 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 0e2d27f19c..4d60c5b4fe 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -28,6 +28,7 @@
#include "lib/route_types.h"
#include "graph.h"
#include "memory.h"
+#include "hash.h"
DECLARE_MTYPE(HOST)
@@ -152,6 +153,9 @@ struct cmd_node
/* Vector of this node's command list. */
vector cmd_vector;
+
+ /* Hashed index of command node list, for de-dupping primarily */
+ struct hash *cmd_hash;
};
/**
diff --git a/lib/json.c b/lib/json.c
index 1d22180e10..966d24f005 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -55,6 +55,12 @@ json_object_int_add(struct json_object* obj, const char *key, int32_t 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)
{
json_object_object_add(obj, key, json_object_new_boolean(0));
diff --git a/lib/json.h b/lib/json.h
index e3d73d9d88..0ceffd4e8e 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,
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 67958be06c..df8925c453 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))
{
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 31cdbd3c5d..5471e58622 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);
}
@@ -448,6 +453,213 @@ DEFUN (no_ospf6_timers_lsa,
}
+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[1]->arg);
+
+ 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)> <intra-area (1-255)|inter-area (1-255)|external (1-255)> <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"
+ "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"
+ "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;
+
+ char *intra, *inter, *external;
+ intra = inter = external = NULL;
+
+ int idx = 0;
+ if (argv_find (argv, argc, "intra-area", &idx))
+ intra = argv[++idx]->arg;
+ if (argv_find (argv, argc, "intra-area", &idx))
+ {
+ vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ idx = 0;
+ if (argv_find (argv, argc, "inter-area", &idx))
+ inter = argv[++idx]->arg;
+ if (argv_find (argv, argc, "inter-area", &idx))
+ {
+ vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ idx = 0;
+ if (argv_find (argv, argc, "external", &idx))
+ external = argv[++idx]->arg;
+ if (argv_find (argv, argc, "external", &idx))
+ {
+ vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+
+ if (intra)
+ o->distance_intra = atoi (intra);
+
+ if (inter)
+ o->distance_inter = atoi (inter);
+
+ if (external)
+ o->distance_external = atoi (external);
+
+ 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)> <intra-area (1-255)|inter-area (1-255)|external (1-255)> <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"
+ "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"
+ "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;
+
+ char *intra, *inter, *external;
+ intra = inter = external = NULL;
+
+ if (argc == 3)
+ {
+ /* If no arguments are given, clear all distance information */
+ o->distance_intra = 0;
+ o->distance_inter = 0;
+ o->distance_external = 0;
+ return CMD_SUCCESS;
+ }
+
+ int idx = 0;
+ if (argv_find (argv, argc, "intra-area", &idx))
+ intra = argv[++idx]->arg;
+ if (argv_find (argv, argc, "intra-area", &idx))
+ {
+ vty_out (vty, "%% Cannot specify intra-area distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ idx = 0;
+ if (argv_find (argv, argc, "inter-area", &idx))
+ inter = argv[++idx]->arg;
+ if (argv_find (argv, argc, "inter-area", &idx))
+ {
+ vty_out (vty, "%% Cannot specify inter-area distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ idx = 0;
+ if (argv_find (argv, argc, "external", &idx))
+ external = argv[++idx]->arg;
+ if (argv_find (argv, argc, "external", &idx))
+ {
+ vty_out (vty, "%% Cannot specify external distance twice%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (argc < 3) /* should not happen */
+ return CMD_WARNING;
+
+ if (intra)
+ o->distance_intra = 0;
+
+ if (inter)
+ o->distance_inter = 0;
+
+ if (external)
+ 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;
+ char *alname = (argc == 4) ? argv[3]->arg : NULL;
+ ospf6_distance_set (vty, o, argv[1]->arg, argv[2]->arg, alname);
+
+ 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;
+ char *alname = (argc == 5) ? argv[4]->arg : NULL;
+ ospf6_distance_unset (vty, o, argv[2]->arg, argv[3]->arg, alname);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf6_interface_area,
ospf6_interface_area_cmd,
"interface IFNAME area A.B.C.D",
@@ -855,6 +1067,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)
@@ -897,6 +1147,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))
{
@@ -953,6 +1204,13 @@ 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 c3b8739532..a5303fb1b8 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. */
@@ -456,6 +458,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
@@ -640,6 +646,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);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 8261a96a20..a447fbb35c 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -946,7 +946,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)
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;
}
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 7b04368496..24ba74c73f 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
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 6eac461895..7a56d3802e 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)