And here it is:
https://github.com/KaloNK/quagga/commit/fefc5bb127ea5575d2267e9f0feb403dbaf454f3
Also attached here as single file with all the commits as from
https://github.com/KaloNK/quagga/compare/master...realms_patchset.diff
On 2015-09-25 18:01, Kaloyan Kovachev wrote:
When i remove conditional compilation from the rest of the code
(except rt_name.c), will prepare a new diff with all the changes as
single file.
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 5c832ed..a198bd2 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -379,6 +379,7 @@ attrhash_key_make (void *p)
MIX(extra->weight);
MIX(extra->mp_nexthop_global_in.s_addr);
MIX(extra->originator_id.s_addr);
+ MIX(extra->realm);
}
if (attr->aspath)
@@ -426,6 +427,7 @@ 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
+ && ae1->realm == ae2->realm
#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..7c60155 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -85,6 +85,9 @@ struct attr_extra
/* MP Nexthop length */
u_char mp_nexthop_len;
+
+ /* Realm number */
+ u_int16_t realm;
};
/* BGP core attribute structure. */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 34ba1ab..ae58171 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -691,6 +691,12 @@ 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;
+ 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;
filter = &peer->filter[afi][safi];
@@ -726,6 +732,12 @@ bgp_export_modifier (struct peer *rsclient, struct peer *peer,
struct bgp_filter *filter;
struct bgp_info info;
route_map_result_t ret;
+ 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;
filter = &peer->filter[afi][safi];
@@ -5714,6 +5726,10 @@ route_vty_out (struct vty *vty, struct prefix *p,
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)
aspath_print_vty (vty, "%s", attr->aspath, " ");
@@ -5779,6 +5795,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p,
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)
aspath_print_vty (vty, "%s", attr->aspath, " ");
@@ -6057,6 +6077,13 @@ 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 +6163,11 @@ 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..dca17cf 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1159,6 +1159,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 /* SUPPORT_REALMS */
+
/* `set as-path prepend ASPATH' */
/* For AS path prepend mechanism. */
@@ -3036,6 +3091,41 @@ DEFUN (set_local_pref,
return bgp_route_set_add (vty, vty->index, "local-preference", argv[0]);
}
+#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 /* SUPPORT_REALMS */
+
DEFUN (no_set_local_pref,
no_set_local_pref_cmd,
"no set local-preference",
@@ -3899,6 +3989,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);
@@ -3971,6 +4064,11 @@ bgp_route_map_init (void)
install_element (RMAP_NODE, &set_metric_rtt_cmd);
install_element (RMAP_NODE, &no_set_metric_cmd);
install_element (RMAP_NODE, &no_set_metric_val_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, &set_aspath_prepend_cmd);
install_element (RMAP_NODE, &set_aspath_prepend_lastas_cmd);
install_element (RMAP_NODE, &set_aspath_exclude_cmd);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 6233163..8f734de 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 /* SUPPORT_REALMS */
+
static int
peer_timers_set_vty (struct vty *vty, const char *ip_str,
const char *keep_str, const char *hold_str)
@@ -7822,6 +7894,17 @@ bgp_show_peer (struct vty *vty, struct peer *p)
vty_out (vty, "%s", VTY_NEWLINE);
+ /* 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);
+
/* Address Family Information */
for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
@@ -9628,6 +9711,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..80d8ee0 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -743,6 +743,12 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, sa
api.distance = distance;
}
+ if (info->attr->extra->realm)
+ {
+ SET_FLAG (api.message, ZAPI_MESSAGE_REALM);
+ api.realm = info->attr->extra->realm;
+ }
+
if (BGP_DEBUG(zebra, ZEBRA))
{
int i;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 4de854e..f57dbd2 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -644,6 +644,7 @@ peer_global_config_reset (struct peer *peer)
peer->keepalive = 0;
peer->connect = 0;
peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
+ peer->realm = 0;
}
/* Check peer's AS number and determines if this peer is IBGP or EBGP */
@@ -810,6 +811,7 @@ peer_new (struct bgp *bgp)
peer->status = Idle;
peer->ostatus = Idle;
peer->weight = 0;
+ peer->realm = 0;
peer->password = NULL;
peer->bgp = bgp;
peer = peer_lock (peer); /* initial reference */
@@ -1437,6 +1439,9 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
/* Weight */
peer->weight = conf->weight;
+ /* Realm */
+ peer->realm = conf->realm;
+
/* peer flags apply */
peer->flags = conf->flags;
/* peer af_flags apply */
@@ -3223,6 +3228,54 @@ peer_weight_unset (struct peer *peer)
return 0;
}
+/* 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;
+}
+
int
peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
{
@@ -4925,6 +4978,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..35d8c0e 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -455,11 +455,13 @@ struct peer
#define PEER_CONFIG_TIMER (1 << 1) /* keepalive & holdtime */
#define PEER_CONFIG_CONNECT (1 << 2) /* connect */
#define PEER_CONFIG_ROUTEADV (1 << 3) /* route advertise */
+#define PEER_CONFIG_REALM (1 << 4) /* Default realm. */
u_int32_t weight;
u_int32_t holdtime;
u_int32_t keepalive;
u_int32_t connect;
u_int32_t routeadv;
+ u_int32_t realm;
/* Timer values. */
u_int32_t v_start;
@@ -892,6 +894,9 @@ extern int bgp_confederation_peers_check (struct bgp *, as_t);
extern int bgp_confederation_peers_add (struct bgp *, as_t);
extern int bgp_confederation_peers_remove (struct bgp *, as_t);
+extern int peer_realm_set (struct peer *, u_int32_t);
+extern int peer_realm_unset (struct peer *);
+
extern int bgp_timers_set (struct bgp *, u_int32_t, u_int32_t);
extern int bgp_timers_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..65f101d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -46,6 +46,10 @@ 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
+endif
+
if GIT_VERSION
# bit of a trick here to always have up-to-date git stamps without triggering
diff --git a/lib/rt_names.c b/lib/rt_names.c
new file mode 100644
index 0000000..3ed3b16
--- /dev/null
+++ b/lib/rt_names.c
@@ -0,0 +1,208 @@
+/*
+ * 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-July 2015 Kaloyan Kovachev
+ *
+ * - Leave only calls we need for realms and fix "discards 'const' qualifier" warnings
+ * - Cache rtnl_tab until file has changed.
+ * - Log events via Quagga.
+ *
+ */
+
+#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"
+#include <log.h>
+#include <sys/inotify.h>
+
+#ifdef SUPPORT_REALMS
+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) {
+ zlog_err("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;
+
+#define INOTIFY_EVENT_SIZE ( sizeof (struct inotify_event) )
+#define INOTIFY_EVENT_BUF_LEN ( 1024 * ( INOTIFY_EVENT_SIZE + 16 ) )
+static int realms_fd = -1;
+static int realms_wd = -1;
+
+static void rtnl_rtrealm_initialize(void)
+{
+ int i;
+
+ if(!rtnl_rtrealm_init) {
+ for(i = 0; i < 255; i++) {
+ rtnl_rtrealm_tab[i] = NULL;
+ }
+
+ if ( realms_fd < 0 ) {
+ realms_fd = inotify_init1(IN_NONBLOCK);
+ realms_wd = inotify_add_watch(realms_fd, "/etc/iproute2/rt_realms",
+ IN_CLOSE_WRITE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO );
+ if ( realms_wd < 0 ) {
+ zlog_err("Unable to register inotofy watch for realms change");
+ if ( realms_fd >= 0 ) {
+ close(realms_fd);
+ realms_fd = -1;
+ }
+ }
+ }
+ }
+
+ if ( realms_wd >= 0 ) {
+ char buffer[INOTIFY_EVENT_BUF_LEN];
+ int change_status = read(realms_fd, buffer, INOTIFY_EVENT_BUF_LEN);
+
+ if ( rtnl_rtrealm_init && change_status == EAGAIN)
+ return;
+
+ i = 0;
+ while ( i < change_status ) {
+ struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
+
+ if ( event->len && (event->mask & IN_DELETE_SELF || event->mask & IN_MOVE_SELF
+ || event->mask & IN_MOVED_FROM || event->mask & IN_MOVED_TO) ) {
+ change_status = -1;
+ }
+ }
+
+ if ( change_status < 0 ) {
+ inotify_rm_watch(realms_fd, realms_wd);
+ close(realms_fd);
+ realms_fd = -1;
+ realms_wd = -1;
+ } else {
+ rtnl_rtrealm_init = 1;
+ }
+ }
+
+ zlog_info ("Initializing realms");
+ 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;
+}
+#else
+
+const char * rtnl_rtrealm_n2a(int id, char *buf, int len)
+{
+ snprintf(buf, len, "%d", id);
+ return buf;
+}
+
+int rtnl_rtrealm_a2n(u_int32_t *id, const char *arg)
+{
+ return 0;
+}
+
+#endif
\ No newline at end of file
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..1fbe358 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -537,6 +537,8 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
stream_putc (s, api->distance);
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
stream_putl (s, api->metric);
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_REALM))
+ stream_putw (s, api->realm);
/* Put length at the first point of the stream. */
stream_putw_at (s, 0, stream_get_endp (s));
@@ -591,6 +593,8 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
stream_putc (s, api->distance);
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
stream_putl (s, api->metric);
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_REALM))
+ stream_putw (s, api->realm);
/* 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..a2b07f6 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -93,6 +93,7 @@ struct zclient
#define ZAPI_MESSAGE_IFINDEX 0x02
#define ZAPI_MESSAGE_DISTANCE 0x04
#define ZAPI_MESSAGE_METRIC 0x08
+#define ZAPI_MESSAGE_REALM 0x10
/* Zserv protocol message header */
struct zserv_header
@@ -129,6 +130,8 @@ struct zapi_ipv4
u_int32_t metric;
vrf_id_t vrf_id;
+
+ u_int16_t realm;
};
/* Prototypes of zebra client service functions. */
@@ -199,6 +202,8 @@ struct zapi_ipv6
u_int32_t metric;
vrf_id_t vrf_id;
+
+ u_int16_t realm;
};
extern int zapi_ipv6_route (u_char cmd, struct zclient *zclient,
diff --git a/lib/zebra.h b/lib/zebra.h
index 8586437..1ce62f3 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -252,6 +252,7 @@ typedef int socklen_t;
#include "zassert.h"
#include "str.h"
+#include "rt_names.h"
#ifdef HAVE_BROKEN_CMSG_FIRSTHDR
/* This bug is present in Solaris 8 and pre-patch Solaris 9 <sys/socket.h>;
diff --git a/zebra/connected.c b/zebra/connected.c
index 244f291..3e07a24 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -192,10 +192,10 @@ 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, 0);
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, 0);
rib_update (ifp->vrf_id);
}
@@ -356,7 +356,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
#endif
rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
- RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);
+ RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST, 0);
rib_update (ifp->vrf_id);
}
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index fd0d8fd..e535718 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -963,7 +963,7 @@ rtm_read (struct rt_msghdr *rtm)
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr,
- NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST);
+ NULL, 0, VRF_DEFAULT, 0, 0, 0, SAFI_UNICAST, 0);
else
rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
&gate.sin.sin_addr, 0, VRF_DEFAULT, SAFI_UNICAST);
@@ -1005,7 +1005,7 @@ rtm_read (struct rt_msghdr *rtm)
|| rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr,
- ifindex, VRF_DEFAULT, RT_TABLE_MAIN, 0, 0, SAFI_UNICAST);
+ ifindex, VRF_DEFAULT, RT_TABLE_MAIN, 0, 0, SAFI_UNICAST, 0);
else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p,
&gate.sin6.sin6_addr, ifindex,
diff --git a/zebra/rib.h b/zebra/rib.h
index 8328f23..1db6ca0 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -83,6 +83,9 @@ struct rib
u_char nexthop_num;
u_char nexthop_active_num;
u_char nexthop_fib_num;
+
+ /* Realm information */
+ u_int16_t realm;
};
/* meta-queue structure:
@@ -199,6 +202,9 @@ struct static_ipv4
see ZEBRA_FLAG_REJECT
ZEBRA_FLAG_BLACKHOLE
*/
+
+ /* Realm information */
+ u_int16_t realm;
};
#ifdef HAVE_IPV6
@@ -231,6 +237,9 @@ struct static_ipv6
see ZEBRA_FLAG_REJECT
ZEBRA_FLAG_BLACKHOLE
*/
+
+ /* Realm information */
+ u_int16_t realm;
};
#endif /* HAVE_IPV6 */
@@ -497,7 +506,7 @@ 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, u_int16_t realm);
extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *, safi_t);
@@ -525,7 +534,7 @@ 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, u_int16_t realm);
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);
@@ -534,7 +543,7 @@ static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
extern int
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex, vrf_id_t vrf_id,
- int table_id, u_int32_t metric, u_char distance, safi_t safi);
+ int table_id, u_int32_t metric, u_char distance, safi_t safi, u_int16_t realm);
extern int
rib_delete_ipv6 (int type, int flags, struct prefix_ipv6 *p,
@@ -549,7 +558,7 @@ extern struct route_table *rib_table_ipv6;
extern int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_char flags, u_char distance,
- vrf_id_t vrf_id);
+ vrf_id_t vrf_id, u_int16_t realm);
extern int
static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 33fbc08..f2d0482 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -672,6 +672,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
void *dest;
void *gate;
void *src;
+ u_int16_t realm = 0;
rtm = NLMSG_DATA (h);
@@ -730,6 +731,16 @@ 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])
+ {
+ u_int32_t 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 +750,7 @@ 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, realm);
else
{
/* This is a multipath route */
@@ -759,6 +770,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+ rib->realm = realm;
for (;;)
{
@@ -806,7 +818,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h,
p.prefixlen = rtm->rtm_dst_len;
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, vrf_id,
- table, metric, 0, SAFI_UNICAST);
+ table, metric, 0, SAFI_UNICAST, realm);
}
#endif /* HAVE_IPV6 */
@@ -846,6 +858,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
void *dest;
void *gate;
void *src;
+ u_int16_t realm = 0;
rtm = NLMSG_DATA (h);
@@ -920,6 +933,16 @@ 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])
+ {
+ u_int32_t 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 +965,7 @@ 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, realm);
else
{
/* This is a multipath route */
@@ -962,6 +985,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
rib->table = table;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+ rib->realm = realm;
for (;;)
{
@@ -1024,7 +1048,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h,
if (h->nlmsg_type == RTM_NEWROUTE)
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id, table,
- metric, 0, SAFI_UNICAST);
+ metric, 0, SAFI_UNICAST, realm);
else
rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, vrf_id,
SAFI_UNICAST);
@@ -1636,6 +1660,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..cd1903c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1806,7 +1806,7 @@ 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, u_int16_t realm)
{
struct rib *rib;
struct rib *same = NULL;
@@ -1873,6 +1873,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p,
rib->table = table_id;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+ rib->realm = realm;
/* Nexthop settings. */
if (gate)
@@ -2335,6 +2336,7 @@ 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;
+ rib->realm = si->realm;
switch (si->type)
{
@@ -2438,7 +2440,7 @@ 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, u_int16_t realm)
{
u_char type = 0;
struct route_node *rn;
@@ -2491,6 +2493,7 @@ 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;
+ si->realm = realm;
if (gate)
si->gate.ipv4 = *gate;
@@ -2597,8 +2600,8 @@ static_delete_ipv4_safi (safi_t safi, struct prefix *p, struct in_addr *gate,
int
rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
struct in6_addr *gate, unsigned int ifindex,
- vrf_id_t vrf_id, int table_id,
- u_int32_t metric, u_char distance, safi_t safi)
+ vrf_id_t vrf_id, int table_id, u_int32_t metric,
+ u_char distance, safi_t safi, u_int16_t realm)
{
struct rib *rib;
struct rib *same = NULL;
@@ -2658,6 +2661,7 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p,
rib->table = table_id;
rib->nexthop_num = 0;
rib->uptime = time (NULL);
+ rib->realm = realm;
/* Nexthop settings. */
if (gate)
@@ -2883,6 +2887,7 @@ static_install_ipv6 (struct prefix *p, struct static_ipv6 *si)
rib->vrf_id = si->vrf_id;
rib->table = zebrad.rtm_table_default;
rib->nexthop_num = 0;
+ rib->realm = si->realm;
switch (si->type)
{
@@ -2990,7 +2995,7 @@ static_uninstall_ipv6 (struct prefix *p, struct static_ipv6 *si)
int
static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
const char *ifname, u_char flags, u_char distance,
- vrf_id_t vrf_id)
+ vrf_id_t vrf_id, u_int16_t realm)
{
struct route_node *rn;
struct static_ipv6 *si;
@@ -3033,6 +3038,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate,
si->distance = distance;
si->flags = flags;
si->vrf_id = vrf_id;
+ si->realm = realm;
switch (type)
{
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index dd7df5c..3d7e32c 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -42,7 +42,8 @@ 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,
+ const char *realm_str)
{
int ret;
u_char distance;
@@ -52,6 +53,20 @@ 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;
+ 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;
+ }
ret = str2prefix (dest_str, &p);
if (ret <= 0)
@@ -94,7 +109,7 @@ 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, realm);
else
static_delete_ipv4_safi (safi, &p, NULL, NULL, distance, vrf_id);
return CMD_SUCCESS;
@@ -120,7 +135,7 @@ 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, realm);
else
static_delete_ipv4_safi (safi, &p, NULL, NULL, distance, vrf_id);
@@ -136,7 +151,7 @@ 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, realm);
else
static_delete_ipv4_safi (safi, &p, ifname ? NULL : &gate, ifname, distance, vrf_id);
@@ -150,7 +165,7 @@ 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, NULL);
}
/* Static unicast routes for multicast RPF lookup. */
@@ -166,7 +181,7 @@ 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, NULL);
}
ALIAS (ip_mroute_dist,
@@ -192,7 +207,7 @@ 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], NULL);
}
ALIAS (ip_mroute_dist_vrf,
@@ -217,7 +232,7 @@ 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, NULL);
}
ALIAS (no_ip_mroute_dist,
@@ -244,8 +259,66 @@ 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], NULL);
+}
+
+#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 +1368,8 @@ 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);
+ if (rib->realm)
+ vty_out (vty, ", realm %5u", rib->realm);
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
vty_out (vty, ", blackhole");
if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
@@ -1381,6 +1456,11 @@ 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)");
+ if (rib->realm) {
+ char realmbuf[50];
+ vty_out (vty, " realm %5s", rtnl_rtrealm_n2a (rib->realm, realmbuf, sizeof (realmbuf)));
+ }
+
switch (nexthop->type)
{
case NEXTHOP_TYPE_IPV4:
@@ -1491,6 +1571,11 @@ 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)");
+ if (rib->realm) {
+ char realmbuf[50];
+ vty_out (vty, " realm %5s", rtnl_rtrealm_n2a (rib->realm, realmbuf, sizeof (realmbuf)));
+ }
+
switch (nexthop->type)
{
case NEXTHOP_TYPE_IPV4:
@@ -2443,6 +2528,11 @@ 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);
+ if (si->realm) {
+ char realmbuf[11];
+ vty_out (vty, " realm %s", rtnl_rtrealm_n2a (si->realm, realmbuf, sizeof realmbuf));
+ }
+
vty_out (vty, "%s", VTY_NEWLINE);
write = 1;
@@ -2569,7 +2659,7 @@ static int
static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
const char *gate_str, const char *ifname,
const char *flag_str, const char *distance_str,
- const char *vrf_id_str)
+ const char *vrf_id_str, const char *realm_str)
{
int ret;
u_char distance;
@@ -2579,6 +2669,20 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
u_char type = 0;
vrf_id_t vrf_id = VRF_DEFAULT;
u_char flag = 0;
+ 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;
+ }
ret = str2prefix (dest_str, &p);
if (ret <= 0)
@@ -2648,7 +2752,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str,
VTY_GET_INTEGER ("VRF ID", vrf_id, vrf_id_str);
if (add_cmd)
- static_add_ipv6 (&p, type, gate, ifname, flag, distance, vrf_id);
+ static_add_ipv6 (&p, type, gate, ifname, flag, distance, vrf_id, realm);
else
static_delete_ipv6 (&p, type, gate, ifname, distance, vrf_id);
@@ -2665,7 +2769,7 @@ DEFUN (ipv6_route,
"IPv6 gateway interface name\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL,
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_flags,
@@ -2680,7 +2784,7 @@ DEFUN (ipv6_route_flags,
"Silently discard pkts when matched\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL,
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_ifname,
@@ -2693,7 +2797,7 @@ DEFUN (ipv6_route_ifname,
"IPv6 gateway interface name\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL,
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_ifname_flags,
@@ -2708,7 +2812,7 @@ DEFUN (ipv6_route_ifname_flags,
"Silently discard pkts when matched\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL,
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_pref,
@@ -2722,7 +2826,7 @@ DEFUN (ipv6_route_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2],
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_flags_pref,
@@ -2738,7 +2842,7 @@ DEFUN (ipv6_route_flags_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3],
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_ifname_pref,
@@ -2752,7 +2856,7 @@ DEFUN (ipv6_route_ifname_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3],
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_ifname_flags_pref,
@@ -2768,9 +2872,66 @@ DEFUN (ipv6_route_ifname_flags_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4],
- NULL);
+ NULL, NULL);
+}
+
+#ifdef SUPPORT_REALMS
+DEFUN (ipv6_route_realm,
+ ipv6_route_realm_cmd,
+ "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Destination realm value or name\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL,
+ NULL, argv[2]);
+}
+
+DEFUN (ipv6_route_ifname_realm,
+ ipv6_route_ifname_realm_cmd,
+ "ipv6 route X:X::X:X/M X:X::X:X INTERFACE realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL,
+ NULL, argv[3]);
+}
+
+DEFUN (ipv6_route_pref_realm,
+ ipv6_route_pref_realm_cmd,
+ "ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE) <1-255> realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Distance value for this prefix\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2],
+ NULL, argv[3]);
}
+DEFUN (ipv6_route_ifname_pref_realm,
+ ipv6_route_ifname_pref_realm_cmd,
+ "ipv6 route X:X::X:X/M X:X::X:X INTERFACE <1-255> realm (<1-255>|WORD)",
+ IP_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Distance value for this prefix\n")
+{
+ return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3],
+ NULL, argv[4]);
+}
+#endif /* SUPPORT_REALMS */
+
DEFUN (no_ipv6_route,
no_ipv6_route_cmd,
"no ipv6 route X:X::X:X/M (X:X::X:X|INTERFACE)",
@@ -2782,7 +2943,7 @@ DEFUN (no_ipv6_route,
"IPv6 gateway interface name\n")
{
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL,
- NULL);
+ NULL, NULL);
}
ALIAS (no_ipv6_route,
@@ -2808,7 +2969,7 @@ DEFUN (no_ipv6_route_ifname,
"IPv6 gateway interface name\n")
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL,
- NULL);
+ NULL, NULL);
}
ALIAS (no_ipv6_route_ifname,
@@ -2835,7 +2996,7 @@ DEFUN (no_ipv6_route_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2],
- NULL);
+ NULL, NULL);
}
DEFUN (no_ipv6_route_flags_pref,
@@ -2853,7 +3014,7 @@ DEFUN (no_ipv6_route_flags_pref,
{
/* We do not care about argv[2] */
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3],
- NULL);
+ NULL, NULL);
}
DEFUN (no_ipv6_route_ifname_pref,
@@ -2868,7 +3029,7 @@ DEFUN (no_ipv6_route_ifname_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3],
- NULL);
+ NULL, NULL);
}
DEFUN (no_ipv6_route_ifname_flags_pref,
@@ -2885,7 +3046,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref,
"Distance value for this prefix\n")
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4],
- NULL);
+ NULL, NULL);
}
DEFUN (ipv6_route_vrf,
@@ -2899,7 +3060,7 @@ DEFUN (ipv6_route_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, NULL,
- argv[2]);
+ argv[2], NULL);
}
DEFUN (ipv6_route_flags_vrf,
@@ -2915,7 +3076,7 @@ DEFUN (ipv6_route_flags_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], NULL,
- argv[3]);
+ argv[3], NULL);
}
DEFUN (ipv6_route_ifname_vrf,
@@ -2929,7 +3090,7 @@ DEFUN (ipv6_route_ifname_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, NULL,
- argv[3]);
+ argv[3], NULL);
}
DEFUN (ipv6_route_ifname_flags_vrf,
@@ -2945,7 +3106,7 @@ DEFUN (ipv6_route_ifname_flags_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL,
- argv[4]);
+ argv[4], NULL);
}
DEFUN (ipv6_route_pref_vrf,
@@ -2960,7 +3121,7 @@ DEFUN (ipv6_route_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, NULL, argv[2],
- argv[3]);
+ argv[3], NULL);
}
DEFUN (ipv6_route_flags_pref_vrf,
@@ -2977,7 +3138,7 @@ DEFUN (ipv6_route_flags_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3],
- argv[4]);
+ argv[4], NULL);
}
DEFUN (ipv6_route_ifname_pref_vrf,
@@ -2992,7 +3153,7 @@ DEFUN (ipv6_route_ifname_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3],
- argv[4]);
+ argv[4], NULL);
}
DEFUN (ipv6_route_ifname_flags_pref_vrf,
@@ -3009,7 +3170,7 @@ DEFUN (ipv6_route_ifname_flags_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5]);
+ argv[5], NULL);
}
DEFUN (no_ipv6_route_vrf,
@@ -3024,7 +3185,7 @@ DEFUN (no_ipv6_route_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, NULL,
- (argc > 3) ? argv[3] : argv[2]);
+ (argc > 3) ? argv[3] : argv[2], NULL);
}
ALIAS (no_ipv6_route_vrf,
@@ -3052,7 +3213,7 @@ DEFUN (no_ipv6_route_ifname_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, NULL,
- (argc > 4) ? argv[4] : argv[3]);
+ (argc > 4) ? argv[4] : argv[3], NULL);
}
ALIAS (no_ipv6_route_ifname_vrf,
@@ -3081,7 +3242,7 @@ DEFUN (no_ipv6_route_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, NULL, argv[2],
- argv[3]);
+ argv[3], NULL);
}
DEFUN (no_ipv6_route_flags_pref_vrf,
@@ -3100,7 +3261,7 @@ DEFUN (no_ipv6_route_flags_pref_vrf,
{
/* We do not care about argv[2] */
return static_ipv6_func (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3],
- argv[4]);
+ argv[4], NULL);
}
DEFUN (no_ipv6_route_ifname_pref_vrf,
@@ -3116,7 +3277,7 @@ DEFUN (no_ipv6_route_ifname_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3],
- argv[4]);
+ argv[4], NULL);
}
DEFUN (no_ipv6_route_ifname_flags_pref_vrf,
@@ -3134,7 +3295,7 @@ DEFUN (no_ipv6_route_ifname_flags_pref_vrf,
VRF_CMD_HELP_STR)
{
return static_ipv6_func (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4],
- argv[5]);
+ argv[5], NULL);
}
DEFUN (show_ipv6_route,
@@ -3856,6 +4017,11 @@ static_config_ipv6 (struct vty *vty)
if (si->vrf_id != VRF_DEFAULT)
vty_out (vty, " vrf %u", si->vrf_id);
+ if (si->realm) {
+ char realmbuf[11];
+
+ vty_out (vty, " realm %s", rtnl_rtrealm_n2a (si->realm, realmbuf, sizeof realmbuf));
+ }
vty_out (vty, "%s", VTY_NEWLINE);
write = 1;
@@ -3955,6 +4121,19 @@ zebra_vty_init (void)
install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance_cmd);
install_element (CONFIG_NODE, &no_ip_route_mask_flags_distance2_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);
+#ifdef HAVE_IPV6
+ install_element (CONFIG_NODE, &ipv6_route_realm_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_ifname_realm_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_pref_realm_cmd);
+ install_element (CONFIG_NODE, &ipv6_route_ifname_pref_realm_cmd);
+#endif /* HAVE_IPV6 */
+#endif /* SUPPORT_REALMS */
+
install_element (VIEW_NODE, &show_ip_route_cmd);
install_element (VIEW_NODE, &show_ip_route_addr_cmd);
install_element (VIEW_NODE, &show_ip_route_prefix_cmd);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 8ca5615..31d840e 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -905,6 +905,12 @@ zread_ipv4_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
/* Table */
rib->table=zebrad.rtm_table_default;
+
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_REALM))
+ rib->realm = stream_getw (s);
+ else
+ rib->realm = 0;
+
rib_add_ipv4_multipath (&p, rib, safi);
return 0;
}
@@ -1093,14 +1099,19 @@ zread_ipv6_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
else
api.metric = 0;
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_REALM))
+ api.realm = stream_getw (s);
+ else
+ api.realm = 0;
+
if (IN6_IS_ADDR_UNSPECIFIED (&nexthop))
rib_add_ipv6 (api.type, api.flags, &p, NULL, ifindex,
vrf_id, zebrad.rtm_table_default, api.metric,
- api.distance, api.safi);
+ api.distance, api.safi, api.realm);
else
rib_add_ipv6 (api.type, api.flags, &p, &nexthop, ifindex,
vrf_id, zebrad.rtm_table_default, api.metric,
- api.distance, api.safi);
+ api.distance, api.safi, api.realm);
return 0;
}
_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev