Hi Kaloyan,
On Mon, 15 Jun 2015, Kaloyan Kovachev wrote:
Hello devs,
I am using the realms patch from Adrian Ban [1] for several years, but
it is still missing from Quagga, while it is very useful (not only for
me I hope). I have ported the patch for the latest version on GitHup and
while working on it found another small bug, which I have fixed [3] Is
there something else that needs to be done so they can be included in
the official source?
It's an interesting patch. I went through it and wrote a longer commit
message for it.
I think it needs work before we could commit it.
1. On the bgpd side, it's basically an ID that can be set per-peer and
that can be set in a route-map action, but isn't significant for
route-selection.
Setting it for a peer - can't you just use the peer ID? Is that
required?
Further, it looks like the peer->realm only gets used for RSclients?
Never gets used to set a route realm otherwise? Is that the intention?
The bgp_{export,input}_modifier hunks don't seem right. It's applying
the realm from the peer->realm regardless of the existing value, and
it's modifying the global attr. Shouldn't it be modifying the
rsclient specific attr?
I'm guessing you don't use the "neighbour ... realm ..." form, and only
use it with route-maps?
2. On the zebra side it seems to only be honoured for IPv4 routes. So it'd
need to be extended to v6 too, no?
The above need answering/fixing before we can go further I think. Upon
which, we'd need to think about:
3. How do we integrate this generally? Is there a general use-case for a
route-map setable ID in bgpd?
Thanks!
--
Paul Jakma [email protected] @pjakma Key ID: 64A2FF6A
Fortune:
The major difference between bonds and bond traders is that the bonds will
eventually mature.
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 5c832ed..5b2b764 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -379,6 +379,9 @@ attrhash_key_make (void *p)
MIX(extra->weight);
MIX(extra->mp_nexthop_global_in.s_addr);
MIX(extra->originator_id.s_addr);
+#ifdef SUPPORT_REALMS
+ MIX(extra->realm);
+#endif
}
if (attr->aspath)
@@ -426,6 +429,9 @@ attrhash_cmp (const void *p1, const void *p2)
&& ae1->aggregator_as == ae2->aggregator_as
&& ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
&& ae1->weight == ae2->weight
+#ifdef SUPPORT_REALMS
+ && ae1->realm == ae2->realm
+#endif
#ifdef HAVE_IPV6
&& ae1->mp_nexthop_len == ae2->mp_nexthop_len
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index b59fa8e..80fbdc2 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -85,6 +85,11 @@ struct attr_extra
/* MP Nexthop length */
u_char mp_nexthop_len;
+
+#ifdef SUPPORT_REALMS
+ /* Realm used */
+ u_int16_t realm;
+#endif
};
/* BGP core attribute structure. */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 34ba1ab..75ed805 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -56,6 +56,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_mpath.h"
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -691,6 +692,15 @@ bgp_input_modifier (struct peer *peer, struct prefix *p,
struct attr *attr,
struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
+#ifdef SUPPORT_REALMS
+ u_int16_t realm_value = 0;
+
+
+ /* Apply default realm value. */
+ realm_value = (u_int16_t)(peer->realm & 0xFFFF);
+ (bgp_attr_extra_get (attr))->realm = realm_value;
+
+#endif
filter = &peer->filter[afi][safi];
@@ -726,6 +736,15 @@ bgp_export_modifier (struct peer *rsclient, struct peer
*peer,
struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
+#ifdef SUPPORT_REALMS
+ u_int16_t realm_value = 0;
+
+
+ /* Apply default realm value. */
+ realm_value = (u_int16_t)(peer->realm & 0xFFFF);
+ (bgp_attr_extra_get (attr))->realm = realm_value;
+
+#endif
filter = &peer->filter[afi][safi];
@@ -5713,6 +5732,10 @@ route_vty_out (struct vty *vty, struct prefix *p,
vty_out (vty, " ");
vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
+
+#ifdef SUPPORT_REALMS
+ vty_out (vty, "%7u ", (attr->extra ? attr->extra->realm : 0));
+#endif
/* Print aspath */
if (attr->aspath)
@@ -5778,6 +5801,9 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p,
vty_out (vty, " ");
vty_out (vty, "%7u ", (attr->extra ? attr->extra->weight : 0));
+#ifdef SUPPORT_REALMS
+ vty_out (vty, "%7u ", (attr->extra ? attr->extra->realm : 0));
+#endif
/* Print aspath */
if (attr->aspath)
@@ -6056,7 +6082,14 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp,
struct prefix *p,
if (attr->extra && attr->extra->weight != 0)
vty_out (vty, ", weight %u", attr->extra->weight);
-
+
+#ifdef SUPPORT_REALMS
+ if (attr->extra && attr->extra->realm != 0) {
+ char realmbuf[64];
+ vty_out (vty, ", realm %s", rtnl_rtrealm_n2a (attr->extra->realm,
realmbuf, sizeof (realmbuf)));
+ }
+#endif
+
if (! CHECK_FLAG (binfo->flags, BGP_INFO_HISTORY))
vty_out (vty, ", valid");
@@ -6136,7 +6169,12 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp,
struct prefix *p,
"h history, * valid, > best, = multipath,%s"\
" i internal, r RIB-failure, S Stale, R Removed%s"
#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? -
incomplete%s%s"
+#ifdef SUPPORT_REALMS
+#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf
Weight Realm Path%s"
+#else
#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf
Weight Path%s"
+#endif
+
#define BGP_SHOW_DAMP_HEADER " Network From Reuse
Path%s"
#define BGP_SHOW_FLAP_HEADER " Network From Flaps
Duration Reuse Path%s"
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 5467cfd..01db7a0 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -53,6 +53,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA
#include "bgpd/bgp_ecommunity.h"
#include "bgpd/bgp_vty.h"
+
/* Memo of route-map commands.
o Cisco route-map
@@ -1159,6 +1160,61 @@ struct route_map_rule_cmd route_set_metric_cmd =
route_value_free,
};
+#ifdef SUPPORT_REALMS
+/* `set realm REALM' */
+static route_map_result_t
+route_set_realm (void *rule, struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ u_int32_t *realm;
+ u_int16_t realm_value = 0;
+ struct bgp_info *bgp_info;
+
+ if(type != RMAP_BGP)
+ return RMAP_OKAY;
+
+ bgp_info = object;
+ realm = (u_int32_t*) rule;
+
+ realm_value = (u_int16_t)(*realm & 0xFFFF);
+ (bgp_attr_extra_get (bgp_info->attr))->realm = realm_value;
+
+ return RMAP_OKAY;
+}
+
+static void *
+route_set_realm_compile (const char *arg)
+{
+ u_int32_t *realm;
+ u_int32_t realmid;
+
+ if (rtnl_rtrealm_a2n (&realmid, arg) < 0)
+ {
+ return NULL;
+ }
+
+ realm = XMALLOC (MTYPE_ROUTE_MAP_COMPILED, sizeof (u_int32_t));
+ *realm = (u_int32_t)realmid;
+
+ return realm;
+}
+
+static void
+route_set_realm_free (void *rule)
+{
+ XFREE (MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Set realms rule structure. */
+struct route_map_rule_cmd route_set_realm_cmd =
+{
+ "realm",
+ route_set_realm,
+ route_set_realm_compile,
+ route_set_realm_free,
+};
+#endif
+
/* `set as-path prepend ASPATH' */
/* For AS path prepend mechanism. */
@@ -3005,6 +3061,41 @@ ALIAS (set_metric,
"Add round trip time\n"
"Subtract round trip time\n")
+#ifdef SUPPORT_REALMS
+DEFUN (set_realm,
+ set_realm_cmd,
+ "set realm (<1-255>|WORD)",
+ SET_STR
+ "Set realm id or name for Linux FIB routes\n"
+ "Realm id for Linux FIB routes\n"
+ "Realm name for Linux FIB routes\n")
+{
+ return bgp_route_set_add (vty, vty->index, "realm", argv[0]);
+}
+
+DEFUN (no_set_realm,
+ no_set_realm_cmd,
+ "no set realm",
+ NO_STR
+ SET_STR
+ "Realm value(s) for Linux FIB routes\n")
+{
+ if (argc == 0)
+ return bgp_route_set_delete (vty, vty->index, "realm", NULL);
+
+ return bgp_route_set_delete (vty, vty->index, "realm", argv[0]);
+}
+
+ALIAS (no_set_realm,
+ no_set_realm_val_cmd,
+ "no set realm (<0-255>|WORD)",
+ NO_STR
+ SET_STR
+ "Realm value(s) for Linux FIB routes\n"
+ "Realm value\n"
+ "Realm name\n")
+#endif
+
DEFUN (no_set_metric,
no_set_metric_cmd,
"no set metric",
@@ -3899,6 +3990,9 @@ bgp_route_map_init (void)
route_map_install_set (&route_set_local_pref_cmd);
route_map_install_set (&route_set_weight_cmd);
route_map_install_set (&route_set_metric_cmd);
+#ifdef SUPPORT_REALMS
+ route_map_install_set (&route_set_realm_cmd);
+#endif
route_map_install_set (&route_set_aspath_prepend_cmd);
route_map_install_set (&route_set_aspath_exclude_cmd);
route_map_install_set (&route_set_origin_cmd);
@@ -3969,6 +4063,11 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &set_metric_cmd);
install_element (RMAP_NODE, &set_metric_addsub_cmd);
install_element (RMAP_NODE, &set_metric_rtt_cmd);
+#ifdef SUPPORT_REALMS
+ install_element (RMAP_NODE, &set_realm_cmd);
+ install_element (RMAP_NODE, &no_set_realm_cmd);
+ install_element (RMAP_NODE, &no_set_realm_val_cmd);
+#endif
install_element (RMAP_NODE, &no_set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_val_cmd);
install_element (RMAP_NODE, &set_aspath_prepend_cmd);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 6233163..81d385f 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -3303,6 +3303,78 @@ DEFUN (no_neighbor_strict_capability,
return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_STRICT_CAP_MATCH);
}
+#ifdef SUPPORT_REALMS
+/* neighbor realm.*/
+static int
+peer_realm_set_vty (struct vty *vty, const char *ip_str,
+ const char *realm_str)
+{
+ struct peer *peer;
+ u_int32_t realmid;
+
+ if (rtnl_rtrealm_a2n (&realmid, realm_str) < 0)
+ {
+ vty_out (vty, "%% Invalid realm value%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ peer = peer_and_group_lookup_vty (vty, ip_str);
+ if (! peer)
+ return CMD_WARNING;
+
+ peer_realm_set (peer, realmid);
+
+ return CMD_SUCCESS;
+}
+
+static int
+peer_realm_unset_vty (struct vty *vty, const char *ip_str)
+{
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty (vty, ip_str);
+ if (! peer)
+ return CMD_WARNING;
+
+ peer_realm_unset (peer);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (neighbor_realm,
+ neighbor_realm_cmd,
+ NEIGHBOR_CMD2 "realm (<0-255>|WORD)",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set default realm for routes from this neighbor\n"
+ "default realm id\n"
+ "default realm name\n")
+{
+ return peer_realm_set_vty (vty, argv[0], argv[1]);
+}
+
+DEFUN (no_neighbor_realm,
+ no_neighbor_realm_cmd,
+ NO_NEIGHBOR_CMD2 "realm",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set default realm for routes from this neighbor\n")
+{
+ return peer_realm_unset_vty (vty, argv[0]);
+}
+
+ALIAS (no_neighbor_realm,
+ no_neighbor_realm_val_cmd,
+ NO_NEIGHBOR_CMD2 "realm (<0-255>|WORD)",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set default realm for routes from this neighbor\n"
+ "default realm id\n"
+ "default realm name\n")
+#endif
+
static int
peer_timers_set_vty (struct vty *vty, const char *ip_str,
const char *keep_str, const char *hold_str)
@@ -7822,6 +7894,19 @@ bgp_show_peer (struct vty *vty, struct peer *p)
vty_out (vty, "%s", VTY_NEWLINE);
+#ifdef SUPPORT_REALMS
+ /* Default realm */
+ if (CHECK_FLAG (p->config, PEER_CONFIG_REALM))
+ {
+ char realmbuf[64];
+
+ vty_out (vty, " Default realm is %s%s",
+ rtnl_rtrealm_n2a (p->realm, realmbuf, sizeof (realmbuf)), VTY_NEWLINE);
+ }
+
+ vty_out (vty, "%s", VTY_NEWLINE);
+#endif
+
/* Address Family Information */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
@@ -9628,6 +9713,13 @@ bgp_vty_init (void)
install_element (BGP_NODE, &no_neighbor_weight_cmd);
install_element (BGP_NODE, &no_neighbor_weight_val_cmd);
+#ifdef SUPPORT_REALMS
+ /* "neighbor realm" commands. */
+ install_element (BGP_NODE, &neighbor_realm_cmd);
+ install_element (BGP_NODE, &no_neighbor_realm_cmd);
+ install_element (BGP_NODE, &no_neighbor_realm_val_cmd);
+#endif
+
/* "neighbor override-capability" commands. */
install_element (BGP_NODE, &neighbor_override_capability_cmd);
install_element (BGP_NODE, &no_neighbor_override_capability_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2616351..2f2e916 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -743,6 +743,14 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info
*info, struct bgp *bgp, sa
api.distance = distance;
}
+#ifdef SUPPORT_REALMS
+ if (info->attr->extra->realm && info->attr->extra->realm)
+ {
+ SET_FLAG (api.message, ZAPI_MESSAGE_REALM);
+ api.realm = info->attr->extra->realm;
+ }
+#endif
+
if (BGP_DEBUG(zebra, ZEBRA))
{
int i;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 4de854e..0f9a86e 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -644,6 +644,9 @@ peer_global_config_reset (struct peer *peer)
peer->keepalive = 0;
peer->connect = 0;
peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+#ifdef SUPPORT_REALMS
+ peer->realm = 0;
+#endif
}
/* Check peer's AS number and determines if this peer is IBGP or EBGP */
@@ -810,6 +813,9 @@ peer_new (struct bgp *bgp)
peer->status = Idle;
peer->ostatus = Idle;
peer->weight = 0;
+#ifdef SUPPORT_REALMS
+ peer->realm = 0;
+#endif
peer->password = NULL;
peer->bgp = bgp;
peer = peer_lock (peer); /* initial reference */
@@ -1437,6 +1443,11 @@ peer_group2peer_config_copy (struct peer_group *group,
struct peer *peer,
/* Weight */
peer->weight = conf->weight;
+#ifdef CONFIG_REALMS
+ /* Realm */
+ peer->realm = conf->realm;
+#endif
+
/* peer flags apply */
peer->flags = conf->flags;
/* peer af_flags apply */
@@ -3223,6 +3234,57 @@ peer_weight_unset (struct peer *peer)
return 0;
}
+#ifdef SUPPORT_REALMS
+
+/* neighbor realm. */
+int
+peer_realm_set (struct peer *peer, u_int32_t realm)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+
+ SET_FLAG (peer->config, PEER_CONFIG_REALM);
+ peer->realm = realm;
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ return 0;
+
+ /* peer-group member updates. */
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ {
+ peer->realm = group->conf->realm;
+ }
+ return 0;
+}
+
+int
+peer_realm_unset (struct peer *peer)
+{
+ struct peer_group *group;
+ struct listnode *node, *nnode;
+
+ /* Set default realm. */
+ if (peer_group_active (peer))
+ peer->realm = peer->group->conf->realm;
+ else
+ peer->realm = 0;
+
+ UNSET_FLAG (peer->config, PEER_CONFIG_REALM);
+
+ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+ return 0;
+
+ /* peer-group member updates. */
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+ {
+ peer->realm = 0;
+ }
+ return 0;
+}
+#endif
+
int
peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
{
@@ -4925,6 +4987,18 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
VTY_NEWLINE);
+#ifdef SUPPORT_REALMS
+ /* Default realm. */
+ if (CHECK_FLAG (peer->config, PEER_CONFIG_REALM))
+ if (! peer_group_active (peer) ||
+ g_peer->realm != peer->realm)
+ {
+ char realmbuf[64];
+ vty_out (vty, " neighbor %s realm %s%s", addr,
+ rtnl_rtrealm_n2a (peer->realm, realmbuf, sizeof (realmbuf)),
VTY_NEWLINE);
+ }
+#endif
+
/* Dynamic capability. */
if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
if (! peer_group_active (peer) ||
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 58d1eca..92413f5 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -460,6 +460,10 @@ struct peer
u_int32_t keepalive;
u_int32_t connect;
u_int32_t routeadv;
+#ifdef SUPPORT_REALMS
+#define PEER_CONFIG_REALM (1 << 4) /* Default realm. */
+ u_int32_t realm;
+#endif
/* Timer values. */
u_int32_t v_start;
@@ -895,6 +899,11 @@ extern int bgp_confederation_peers_remove (struct bgp *,
as_t);
extern int bgp_timers_set (struct bgp *, u_int32_t, u_int32_t);
extern int bgp_timers_unset (struct bgp *);
+#ifdef SUPPORT_REALMS
+extern int peer_realm_set (struct peer *, u_int32_t);
+extern int peer_realm_unset (struct peer *);
+#endif
+
extern int bgp_default_local_preference_set (struct bgp *, u_int32_t);
extern int bgp_default_local_preference_unset (struct bgp *);
diff --git a/configure.ac b/configure.ac
index 6da65f3..6395665 100755
--- a/configure.ac
+++ b/configure.ac
@@ -274,6 +274,8 @@ AC_ARG_ENABLE(configfile_mask,
AS_HELP_STRING([--enable-configfile-mask=ARG], [set mask for config files]))
AC_ARG_ENABLE(logfile_mask,
AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files]))
+AC_ARG_ENABLE(realms,
+ AS_HELP_STRING([--enable-realms], [enable REALMS support under Linux]))
AC_ARG_ENABLE(rtadv,
AS_HELP_STRING([--disable-rtadv], [disable IPV6 router advertisement
feature]))
@@ -631,6 +633,18 @@ esac
AC_SYS_LARGEFILE
+dnl ------------------------
+dnl Integrated REALMS option
+dnl ------------------------
+if test "${enable_realms}" = "yes"; then
+ if test "${opsys}" != "gnu-linux"; then
+ echo "Sorry, only Linux has REALMS support"
+ exit 1
+ fi
+ AC_DEFINE(SUPPORT_REALMS,, Realms support)
+fi
+AM_CONDITIONAL([SUPPORT_REALMS], [test "${enable_realms}" = "yes"])
+
dnl ---------------------
dnl Integrated VTY option
dnl ---------------------
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ac51fc6..677e19b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -46,6 +46,11 @@ memtypes.h: $(srcdir)/memtypes.c $(srcdir)/memtypes.awk
route_types.h: $(srcdir)/route_types.txt $(srcdir)/route_types.pl
@PERL@ $(srcdir)/route_types.pl < $(srcdir)/route_types.txt > $@
+if SUPPORT_REALMS
+libzebra_la_SOURCES += rt_names.c
+# pkginclude_HEADERS += rt_names.h
+endif
+
if GIT_VERSION
# bit of a trick here to always have up-to-date git stamps without triggering
diff --git a/lib/command.c b/lib/command.c
index 3a59f24..aceeb9c 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -614,8 +614,8 @@ install_element (enum node_type ntype, struct cmd_element
*cmd)
if (cnode == NULL)
{
- fprintf (stderr, "Command node %d doesn't exist, please check it\n",
- ntype);
+ fprintf (stderr, "Command node %d (%s) doesn't exist, please check it\n",
+ ntype, cmd->string);
exit (1);
}
diff --git a/lib/rt_names.c b/lib/rt_names.c
new file mode 100644
index 0000000..17d037f
--- /dev/null
+++ b/lib/rt_names.c
@@ -0,0 +1,143 @@
+/*
+ * rt_names.c rtnetlink names DB.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Alexey Kuznetsov, <[email protected]>
+ *
+ * Fix: 23 Apr 2005 Calin Velea <[email protected]>
+ *
+ * bgpd-specific fixes
+ *
+ * - Modified rtnl_tab_initialize() function to free
allocated entries
+ * before re-reading table; rtnl_rtrealm_initialize() to
zero
+ * unused entries at first call
+ * - Modified rtnl_rtrealm_a2n() to read realm table each
time; otherwise
+ * bgpd restart was necessary to be in sync with
/etc/iproute2/rt_realms
+ *
+ * Change: June 2015 Kaloyan Kovachev
+ *
+ * - Leave only calls we need for realms and fix "discards
'const' qualifier" warnings
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "zebra.h"
+
+static void rtnl_tab_initialize(const char *file, char **tab, int size)
+{
+ int i;
+ char buf[512];
+ FILE *fp;
+
+ for(i = 1; i < 255; i++)
+ if(tab[i]) {
+ free(tab[i]);
+ tab[i] = NULL;
+ }
+
+
+ fp = fopen(file, "r");
+ if (!fp)
+ return;
+ while (fgets(buf, sizeof(buf), fp)) {
+ char *p = buf;
+ int id;
+ char namebuf[512];
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+ if (*p == '#' || *p == '\n' || *p == 0)
+ continue;
+ if (sscanf(p, "0x%x %s\n", &id, namebuf) != 2 &&
+ sscanf(p, "0x%x %s #", &id, namebuf) != 2 &&
+ sscanf(p, "%d %s\n", &id, namebuf) != 2 &&
+ sscanf(p, "%d %s #", &id, namebuf) != 2) {
+ fprintf(stderr, "Database %s is corrupted at %s\n",
+ file, p);
+ return;
+ }
+
+ if (id<0 || id>size)
+ continue;
+
+ tab[id] = strdup(namebuf);
+ }
+ fclose(fp);
+}
+
+static char * rtnl_rtrealm_tab[256];
+
+static int rtnl_rtrealm_init = 0;
+
+static void rtnl_rtrealm_initialize(void)
+{
+ int i;
+
+ if(!rtnl_rtrealm_init)
+ for(i = 0; i < 255; i++)
+ rtnl_rtrealm_tab[i] = NULL;
+
+ rtnl_rtrealm_init = 1;
+ rtnl_tab_initialize("/etc/iproute2/rt_realms", rtnl_rtrealm_tab, 256);
+ if ( !rtnl_rtrealm_tab[0] )
+ rtnl_rtrealm_tab[0] = strdup("unknown");
+}
+
+const char * rtnl_rtrealm_n2a(int id, char *buf, int len)
+{
+ if (id<0 || id>=256) {
+ snprintf(buf, len, "%d", id);
+ return buf;
+ }
+ if (!rtnl_rtrealm_tab[id]) {
+ if (!rtnl_rtrealm_init)
+ rtnl_rtrealm_initialize();
+ }
+ if (rtnl_rtrealm_tab[id])
+ return rtnl_rtrealm_tab[id];
+ snprintf(buf, len, "%d", id);
+ return buf;
+}
+
+
+int rtnl_rtrealm_a2n(u_int32_t *id, const char *arg)
+{
+ static char *cache = NULL;
+ static unsigned long cache_res;
+ unsigned long res;
+ char *end;
+ int i;
+
+ if (cache && strcmp(cache, arg) == 0) {
+ *id = cache_res;
+ return 0;
+ }
+ rtnl_rtrealm_initialize();
+
+ for (i=0; i<256; i++) {
+ if (rtnl_rtrealm_tab[i] &&
+ strcmp(rtnl_rtrealm_tab[i], arg) == 0) {
+ cache = rtnl_rtrealm_tab[i];
+ cache_res = i;
+ *id = cache_res;
+ return 0;
+ }
+ }
+
+ res = strtoul(arg, &end, 0);
+ if (!end || end == arg || *end || res > 255)
+ return -1;
+ *id = res;
+ return 0;
+}
diff --git a/lib/rt_names.h b/lib/rt_names.h
new file mode 100644
index 0000000..be379de
--- /dev/null
+++ b/lib/rt_names.h
@@ -0,0 +1,7 @@
+#ifndef RT_NAMES_H_
+#define RT_NAMES_H_ 1
+
+extern const char* rtnl_rtrealm_n2a(int id, char *buf, int len);
+extern int rtnl_rtrealm_a2n(u_int32_t *id, const char *arg);
+
+#endif
diff --git a/lib/zclient.c b/lib/zclient.c
index 8e443e2..af0798c 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -538,6 +538,11 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient,
struct prefix_ipv4 *p,
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
stream_putl (s, api->metric);
+#ifdef SUPPORT_REALMS
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_REALM))
+ stream_putw (s, api->realm);
+#endif
+
/* Put length at the first point of the stream. */
stream_putw_at (s, 0, stream_get_endp (s));
diff --git a/lib/zclient.h b/lib/zclient.h
index 19b4f0e..9c1f559 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -93,6 +93,9 @@ struct zclient
#define ZAPI_MESSAGE_IFINDEX 0x02
#define ZAPI_MESSAGE_DISTANCE 0x04
#define ZAPI_MESSAGE_METRIC 0x08
+#ifdef SUPPORT_REALMS
+#define ZAPI_MESSAGE_REALM 0x10
+#endif
/* Zserv protocol message header */
struct zserv_header
@@ -129,6 +132,9 @@ struct zapi_ipv4
u_int32_t metric;
vrf_id_t vrf_id;
+#ifdef SUPPORT_REALMS
+ u_int16_t realm;
+#endif
};
/* Prototypes of zebra client service functions. */
diff --git a/lib/zebra.h b/lib/zebra.h
index 8586437..ae96acb 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -240,6 +240,10 @@ typedef int socklen_t;
#define UINT32_MAX (4294967295U)
#endif
+#ifdef SUPPORT_REALMS
+#include "rt_names.h"
+#endif
+
#ifdef HAVE_GLIBC_BACKTRACE
#include <execinfo.h>
#endif /* HAVE_GLIBC_BACKTRACE */
diff --git a/zebra/connected.c b/zebra/connected.c
index 244f291..97c9eea 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -192,10 +192,18 @@ connected_up_ipv4 (struct interface *ifp, struct
connected *ifc)
return;
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
- ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
+ ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST
+#ifdef SUPPORT_REALMS
+ , 0
+#endif
+ );
rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
- ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);
+ ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST
+#ifdef SUPPORT_REALMS
+ , 0
+#endif
+ );
rib_update (ifp->vrf_id);
}
diff --git a/zebra/rib.h b/zebra/rib.h
index 8328f23..8f656ca 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -83,6 +83,10 @@ struct rib
u_char nexthop_num;
u_char nexthop_active_num;
u_char nexthop_fib_num;
+#ifdef SUPPORT_REALMS
+ /* Realm information */
+ u_int16_t realm;
+#endif
};
/* meta-queue structure:
@@ -199,6 +203,10 @@ struct static_ipv4
see ZEBRA_FLAG_REJECT
ZEBRA_FLAG_BLACKHOLE
*/
+#ifdef SUPPORT_REALMS
+ /* Realm information */
+ u_int16_t realm;
+#endif
};
#ifdef HAVE_IPV6
@@ -497,7 +505,11 @@ extern struct route_table *zebra_vrf_static_table (afi_t,
safi_t, vrf_id_t);
extern int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
unsigned int ifindex, vrf_id_t vrf_id, int table_id,
- u_int32_t, u_char, safi_t);
+ u_int32_t, u_char, safi_t
+#ifdef SUPPORT_REALMS
+ , u_int16_t
+#endif
+ );
extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);
@@ -525,7 +537,11 @@ extern unsigned long rib_score_proto (u_char proto);
extern int
static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
const char *ifname, u_char flags, u_char distance,
- vrf_id_t vrf_id);
+ vrf_id_t vrf_id
+#ifdef SUPPORT_REALMS
+ , u_int16_t realm
+#endif
+ );
extern int
static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
const char *ifname, u_char distance, vrf_id_t vrf_id);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 0f0f3fe..3f5c204 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -672,6 +672,10 @@ netlink_routing_table (struct sockaddr_nl *snl, struct
nlmsghdr *h,
void *dest;
void *gate;
void *src;
+#ifdef SUPPORT_REALMS
+ u_int32_t rta_flow;
+ u_int16_t realm = 0;
+#endif
rtm = NLMSG_DATA (h);
@@ -730,6 +734,14 @@ netlink_routing_table (struct sockaddr_nl *snl, struct
nlmsghdr *h,
if (tb[RTA_PRIORITY])
metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
+#ifdef SUPPORT_REALMS
+ if (tb[RTA_FLOW])
+ {
+ rta_flow = *(u_int32_t *) RTA_DATA (tb[RTA_FLOW]);
+ realm = rta_flow & 0xFFFF;
+ }
+#endif
+
if (rtm->rtm_family == AF_INET)
{
struct prefix_ipv4 p;
@@ -739,7 +751,11 @@ netlink_routing_table (struct sockaddr_nl *snl, struct
nlmsghdr *h,
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index,
- vrf_id, table, metric, 0, SAFI_UNICAST);
+ vrf_id, table, metric, 0, SAFI_UNICAST
+#ifdef SUPPORT_REALMS
+ , realm
+#endif
+ );
else
{
/* This is a multipath route */
@@ -759,6 +775,9 @@ netlink_routing_table (struct sockaddr_nl *snl, struct
nlmsghdr *h,
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+#ifdef SUPPORT_REALMS
+ rib->realm = realm;
+#endif
for (;;)
{
@@ -846,6 +865,10 @@ netlink_route_change (struct sockaddr_nl *snl, struct
nlmsghdr *h,
void *dest;
void *gate;
void *src;
+#ifdef SUPPORT_REALMS
+ u_int32_t rta_flow;
+ u_int16_t realm = 0;
+#endif
rtm = NLMSG_DATA (h);
@@ -920,6 +943,14 @@ netlink_route_change (struct sockaddr_nl *snl, struct
nlmsghdr *h,
if (tb[RTA_PREFSRC])
src = RTA_DATA (tb[RTA_PREFSRC]);
+#ifdef SUPPORT_REALMS
+ if (tb[RTA_FLOW])
+ {
+ rta_flow = *(u_int32_t *) RTA_DATA (tb[RTA_FLOW]);
+ realm = rta_flow & 0xFFFF;
+ }
+#endif
+
if (h->nlmsg_type == RTM_NEWROUTE && tb[RTA_PRIORITY])
metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]);
@@ -942,7 +973,11 @@ netlink_route_change (struct sockaddr_nl *snl, struct
nlmsghdr *h,
{
if (!tb[RTA_MULTIPATH])
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, vrf_id,
- table, metric, 0, SAFI_UNICAST);
+ table, metric, 0, SAFI_UNICAST
+#ifdef SUPPORT_REALMS
+ , realm
+#endif
+ );
else
{
/* This is a multipath route */
@@ -962,6 +997,9 @@ netlink_route_change (struct sockaddr_nl *snl, struct
nlmsghdr *h,
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+#ifdef SUPPORT_REALMS
+ rib->realm = realm;
+#endif
for (;;)
{
@@ -1635,6 +1673,12 @@ netlink_route_multipath (int cmd, struct prefix *p,
struct rib *rib,
/* Metric. */
addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric);
+#ifdef SUPPORT_REALMS
+ if (rib->realm) {
+ addattr32 (&req.n, sizeof req, RTA_FLOW, rib->realm);
+ }
+#endif
+
if (discard)
{
if (cmd == RTM_NEWROUTE)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 084af38..bfc2988 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1806,7 +1806,11 @@ int
rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
struct in_addr *gate, struct in_addr *src,
unsigned int ifindex, vrf_id_t vrf_id, int table_id,
- u_int32_t metric, u_char distance, safi_t safi)
+ u_int32_t metric, u_char distance, safi_t safi
+#ifdef SUPPORT_REALMS
+ , u_int16_t realm
+#endif
+ )
{
struct rib *rib;
struct rib *same = NULL;
@@ -1873,6 +1877,9 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
rib->table = table_id;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+#ifdef SUPPORT_REALMS
+ rib->realm = realm;
+#endif
/* Nexthop settings. */
if (gate)
@@ -2335,6 +2342,9 @@ static_install_ipv4 (safi_t safi, struct prefix *p,
struct static_ipv4 *si)
rib->vrf_id = si->vrf_id;
rib->table = zebrad.rtm_table_default;
rib->nexthop_num = 0;
+#ifdef SUPPORT_REALMS
+ rib->realm = si->realm;
+#endif
switch (si->type)
{
@@ -2438,7 +2448,11 @@ static_uninstall_ipv4 (safi_t safi, struct prefix *p,
struct static_ipv4 *si)
int
static_add_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
const char *ifname, u_char flags, u_char distance,
- vrf_id_t vrf_id)
+ vrf_id_t vrf_id
+#ifdef SUPPORT_REALMS
+ , u_int16_t realm
+#endif
+ )
{
u_char type = 0;
struct route_node *rn;
@@ -2491,6 +2505,9 @@ static_add_ipv4_safi (safi_t safi, struct prefix *p,
struct in_addr *gate,
si->distance = distance;
si->flags = flags;
si->vrf_id = vrf_id;
+#ifdef SUPPORT_REALMS
+ si->realm = realm;
+#endif
if (gate)
si->gate.ipv4 = *gate;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index dd7df5c..f8002dd 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -42,7 +42,11 @@ static int
zebra_static_ipv4_safi (struct vty *vty, safi_t safi, int add_cmd,
const char *dest_str, const char *mask_str,
const char *gate_str, const char *flag_str,
- const char *distance_str, const char *vrf_id_str)
+ const char *distance_str, const char *vrf_id_str
+#ifdef SUPPORT_REALMS
+ , const char *realm_str
+#endif
+ )
{
int ret;
u_char distance;
@@ -52,6 +56,22 @@ zebra_static_ipv4_safi (struct vty *vty, safi_t safi, int
add_cmd,
const char *ifname;
u_char flag = 0;
vrf_id_t vrf_id = VRF_DEFAULT;
+#ifdef SUPPORT_REALMS
+ u_int16_t realm = 0;
+
+ if (realm_str != NULL) {
+ u_int32_t realmid;
+ int res;
+
+ res = rtnl_rtrealm_a2n (&realmid, realm_str);
+ if (res < 0) {
+ vty_out (vty, "%%Realm '%s' not found in rt_realms has invalid
value%s",
+ realm_str, VTY_NEWLINE);
+ return CMD_ERR_INCOMPLETE;
+ }
+ realm = (u_int16_t)realmid;
+ }
+#endif
ret = str2prefix (dest_str, &p);
if (ret <= 0)
@@ -94,7 +114,11 @@ zebra_static_ipv4_safi (struct vty *vty, safi_t safi, int
add_cmd,
return CMD_WARNING;
}
if (add_cmd)
- static_add_ipv4_safi (safi, &p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE,
distance, vrf_id);
+ static_add_ipv4_safi (safi, &p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE,
distance, vrf_id
+#ifdef SUPPORT_REALMS
+ , realm
+#endif
+ );
else
static_delete_ipv4_safi (safi, &p, NULL, NULL, distance, vrf_id);
return CMD_SUCCESS;
@@ -120,7 +144,11 @@ zebra_static_ipv4_safi (struct vty *vty, safi_t safi, int
add_cmd,
if (gate_str == NULL)
{
if (add_cmd)
- static_add_ipv4_safi (safi, &p, NULL, NULL, flag, distance, vrf_id);
+ static_add_ipv4_safi (safi, &p, NULL, NULL, flag, distance, vrf_id
+#ifdef SUPPORT_REALMS
+ , realm
+#endif
+ );
else
static_delete_ipv4_safi (safi, &p, NULL, NULL, distance, vrf_id);
@@ -136,7 +164,11 @@ zebra_static_ipv4_safi (struct vty *vty, safi_t safi, int
add_cmd,
ifname = gate_str;
if (add_cmd)
- static_add_ipv4_safi (safi, &p, ifname ? NULL : &gate, ifname, flag,
distance, vrf_id);
+ static_add_ipv4_safi (safi, &p, ifname ? NULL : &gate, ifname, flag,
distance, vrf_id
+#ifdef SUPPORT_REALMS
+ , realm
+#endif
+ );
else
static_delete_ipv4_safi (safi, &p, ifname ? NULL : &gate, ifname,
distance, vrf_id);
@@ -150,7 +182,11 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const
char *dest_str,
const char *vrf_id_str)
{
return zebra_static_ipv4_safi (vty, SAFI_UNICAST, add_cmd, dest_str,
mask_str,
- gate_str, flag_str, distance_str, vrf_id_str);
+ gate_str, flag_str, distance_str, vrf_id_str
+#ifdef SUPPORT_REALMS
+ , NULL
+#endif
+ );
}
/* Static unicast routes for multicast RPF lookup. */
@@ -166,7 +202,11 @@ DEFUN (ip_mroute_dist,
{
VTY_WARN_EXPERIMENTAL();
return zebra_static_ipv4_safi(vty, SAFI_MULTICAST, 1, argv[0], NULL, argv[1],
- NULL, argc > 2 ? argv[2] : NULL, NULL);
+ NULL, argc > 2 ? argv[2] : NULL, NULL
+#ifdef SUPPORT_REALMS
+ , NULL
+#endif
+ );
}
ALIAS (ip_mroute_dist,
@@ -192,7 +232,11 @@ DEFUN (ip_mroute_dist_vrf,
VTY_WARN_EXPERIMENTAL();
return zebra_static_ipv4_safi(vty, SAFI_MULTICAST, 1, argv[0], NULL, argv[1],
NULL, argc > 3 ? argv[2] : NULL,
- argc > 3 ? argv[3] : argv[2]);
+ argc > 3 ? argv[3] : argv[2]
+#ifdef SUPPORT_REALMS
+ , NULL
+#endif
+ );
}
ALIAS (ip_mroute_dist_vrf,
@@ -217,7 +261,11 @@ DEFUN (no_ip_mroute_dist,
{
VTY_WARN_EXPERIMENTAL();
return zebra_static_ipv4_safi(vty, SAFI_MULTICAST, 0, argv[0], NULL, argv[1],
- NULL, argc > 2 ? argv[2] : NULL, NULL);
+ NULL, argc > 2 ? argv[2] : NULL, NULL
+#ifdef SUPPORT_REALMS
+ , NULL
+#endif
+ );
}
ALIAS (no_ip_mroute_dist,
@@ -244,8 +292,70 @@ DEFUN (no_ip_mroute_dist_vrf,
VTY_WARN_EXPERIMENTAL();
return zebra_static_ipv4_safi(vty, SAFI_MULTICAST, 0, argv[0], NULL, argv[1],
NULL, argc > 3 ? argv[2] : NULL,
- argc > 3 ? argv[3] : argv[2]);
+ argc > 3 ? argv[3] : argv[2]
+#ifdef SUPPORT_REALMS
+ , NULL
+#endif
+ );
+}
+
+#ifdef SUPPORT_REALMS
+DEFUN (ip_route_realm,
+ ip_route_realm_cmd,
+ "ip route A.B.C.D/M (A.B.C.D|INTERFACE) realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Destination realm value or name\n")
+{
+ return zebra_static_ipv4_safi (vty, SAFI_UNICAST, 1, argv[0], NULL, argv[1],
+ NULL, NULL, NULL, argv[2]);
+}
+
+DEFUN (ip_route_mask_realm,
+ ip_route_mask_realm_cmd,
+ "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Destination realm value or name\n")
+{
+ return zebra_static_ipv4_safi (vty, SAFI_UNICAST, 1, argv[0], argv[1],
argv[2], NULL, NULL, NULL, argv[3]);
+}
+
+DEFUN (ip_route_pref_realm,
+ ip_route_pref_realm_cmd,
+ "ip route A.B.C.D/M (A.B.C.D|INTERFACE) <1-255> realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Distance value for this route\n"
+ "Destination realm value or name\n")
+{
+ return zebra_static_ipv4_safi (vty, SAFI_UNICAST, 1, argv[0], NULL, argv[1],
NULL, argv[2], NULL, argv[3]);
}
+
+DEFUN (ip_route_mask_pref_realm,
+ ip_route_mask_pref_realm_cmd,
+ "ip route A.B.C.D A.B.C.D (A.B.C.D|INTERFACE) <1-255> realm
(<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name\n"
+ "Distance value for this route\n")
+{
+ return zebra_static_ipv4_safi (vty, SAFI_UNICAST, 1, argv[0], argv[1],
argv[2], NULL, argv[3], NULL, argv[4]);
+}
+#endif /* SUPPORT_REALMS */
ALIAS (no_ip_mroute_dist_vrf,
no_ip_mroute_vrf_cmd,
@@ -1295,6 +1405,10 @@ vty_show_ip_route_detail (struct vty *vty, struct
route_node *rn, int mcast)
vty_out (vty, ", best");
if (rib->refcnt)
vty_out (vty, ", refcnt %ld", rib->refcnt);
+#ifdef SUPPORT_REALMS
+ if (rib->realm)
+ vty_out (vty, ", realm %5u", rib->realm);
+#endif
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
vty_out (vty, ", blackhole");
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
@@ -1380,6 +1494,12 @@ vty_show_ip_route_detail (struct vty *vty, struct
route_node *rn, int mcast)
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out (vty, " (recursive)");
+#ifdef SUPPORT_REALMS
+ if (rib->realm) {
+ char realmbuf[50];
+ vty_out (vty, " realm %5s", rtnl_rtrealm_n2a (rib->realm, realmbuf,
sizeof (realmbuf)));
+ }
+#endif
switch (nexthop->type)
{
@@ -1490,6 +1610,12 @@ vty_show_ip_route (struct vty *vty, struct route_node
*rn, struct rib *rib)
if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out (vty, " (recursive)");
+#ifdef SUPPORT_REALMS
+ if (rib->realm) {
+ char realmbuf[50];
+ vty_out (vty, " realm %5s", rtnl_rtrealm_n2a (rib->realm, realmbuf,
sizeof (realmbuf)));
+ }
+#endif
switch (nexthop->type)
{
@@ -2443,6 +2569,13 @@ static_config_ipv4 (struct vty *vty, safi_t safi, const
char *cmd)
if (si->vrf_id != VRF_DEFAULT)
vty_out (vty, " vrf %u", si->vrf_id);
+#ifdef SUPPORT_REALMS
+ if (si->realm) {
+ char realmbuf[11];
+ vty_out (vty, " realm %s", rtnl_rtrealm_n2a (si->realm,
realmbuf, sizeof realmbuf));
+ }
+#endif
+
vty_out (vty, "%s", VTY_NEWLINE);
write = 1;
@@ -3943,6 +4076,12 @@ zebra_vty_init (void)
install_element (CONFIG_NODE, &no_ip_route_mask_cmd);
install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd);
install_element (CONFIG_NODE, &no_ip_route_mask_flags2_cmd);
+#ifdef SUPPORT_REALMS
+ install_element (CONFIG_NODE, &ip_route_realm_cmd);
+ install_element (CONFIG_NODE, &ip_route_mask_realm_cmd);
+ install_element (CONFIG_NODE, &ip_route_pref_realm_cmd);
+ install_element (CONFIG_NODE, &ip_route_mask_pref_realm_cmd);
+#endif
install_element (CONFIG_NODE, &ip_route_distance_cmd);
install_element (CONFIG_NODE, &ip_route_flags_distance_cmd);
install_element (CONFIG_NODE, &ip_route_flags_distance2_cmd);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 8ca5615..5f13f24 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -905,6 +905,14 @@ zread_ipv4_add (struct zserv *client, u_short length,
vrf_id_t vrf_id)
/* Table */
rib->table=zebrad.rtm_table_default;
+
+#ifdef SUPPORT_REALMS
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_REALM))
+ rib->realm = stream_getw (s);
+ else
+ rib->realm = 0;
+#endif
+
rib_add_ipv4_multipath (&p, rib, safi);
return 0;
}
_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev