diff -Nru quagga-0.98.6.orig/ChangeLog quagga-0.98.6/ChangeLog
--- quagga-0.98.6.orig/ChangeLog	2005-09-23 13:41:16.000000000 +0300
+++ quagga-0.98.6/ChangeLog	2006-05-10 10:02:55.000000000 +0300
@@ -6,6 +6,13 @@
 
 	* configure.ac: Actually test whether libc has IPv6 support.
 
+2005-07-30 Calin Velea <vcalinus at gemenii.ro>
+	* configure.ac: Modified to include realms --enable-realms which
+ 	  uses the realms patch to add suport for route realms under Linux. 
+ 	  This patch is an enhanced version of Arcady Stepanov's original
+ 	  realms patch for zebra-0.93b. It adds route-map and neighbor default
+ 	  realm setting in bgpd and static route realm setting in zebra
+
 2005-06-27 Hasso Tepper <hasso at quagga.net>
 	
 	* configure.ac: Bump version to 0.98.4.
@@ -41,6 +48,7 @@
 	* configure.ac: Add action for case of crosscompiling to the
 	  AC_TRY_RUN macro.
 
+
 2005-04-01 Hasso Tepper <hasso at quagga.net>
 
 	* configure.ac: Bump version to 0.98.3.
diff -Nru quagga-0.98.6.orig/bgpd/ChangeLog quagga-0.98.6/bgpd/ChangeLog
--- quagga-0.98.6.orig/bgpd/ChangeLog	2006-05-08 17:58:20.000000000 +0300
+++ quagga-0.98.6/bgpd/ChangeLog	2006-05-10 10:02:55.000000000 +0300
@@ -47,6 +47,18 @@
 	* bgpd.c: Fix obvious (routeserver patch) merge error. This makes "no
 	  neighbor x.x.x.x routemap [export|import] commands work again.
 
+2005-04-24 Calin Velea <vcalinus at gemenii.ro>
+ 	* bgp_attr.c: Modified attrhash_cmp and attrhash_key_make to use realms
+ 	* bgp_attr.h: Added realm attribute to attr struct
+ 	* bgp_route.c: Changed bgp_input_modifier and bgp_import_modifier
+ 	    to apply default realm to routes
+ 	* bgp_routemap.c: Added realm route map commands
+ 	* bgp_vty.c: Added neighbor realm commands
+ 	* bgp_zebra.c: Added API realm message
+ 	* bgpd.c: Added functions to set default peer realm
+ 	* bgpd.h: Added flag for peer default realm, peer default realm
+ 	    functions prototypes
+
 2005-03-21 Hasso Tepper <hasso at quagga.net>
 
 	* bgp_route.c: Don't crash while clearing route tables if there is
diff -Nru quagga-0.98.6.orig/bgpd/bgp_attr.c quagga-0.98.6/bgpd/bgp_attr.c
--- quagga-0.98.6.orig/bgpd/bgp_attr.c	2006-05-03 01:37:47.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_attr.c	2006-05-10 10:02:55.000000000 +0300
@@ -58,7 +58,7 @@
   { BGP_ATTR_MP_UNREACH_NLRI,  "MP_UNREACH_NLRI" },
   { 0, NULL }
 };
-
+
 struct hash *cluster_hash;
 
 void *
@@ -192,7 +192,7 @@
 {
   cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp);
 }
-
+
 /* Unknown transit attribute. */
 struct hash *transit_hash;
 
@@ -287,6 +287,11 @@
   key += attr->aggregator_addr.s_addr;
   key += attr->weight;
 
+#ifdef SUPPORT_REALMS
+  key += attr->realmto;
+#endif
+
+
   key += attr->mp_nexthop_global_in.s_addr;
   if (attr->aspath)
     key += aspath_key_make (attr->aspath);
@@ -325,6 +330,11 @@
       && attr1->aggregator_as == attr2->aggregator_as
       && attr1->aggregator_addr.s_addr == attr2->aggregator_addr.s_addr
       && attr1->weight == attr2->weight
+
+#ifdef SUPPORT_REALMS
+      && attr1->realmto == attr2->realmto
+#endif
+
 #ifdef HAVE_IPV6
       && attr1->mp_nexthop_len == attr2->mp_nexthop_len
       && IPV6_ADDR_SAME (&attr1->mp_nexthop_global, &attr2->mp_nexthop_global)
diff -Nru quagga-0.98.6.orig/bgpd/bgp_attr.h quagga-0.98.6/bgpd/bgp_attr.h
--- quagga-0.98.6.orig/bgpd/bgp_attr.h	2006-05-03 01:37:48.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_attr.h	2006-05-10 10:02:55.000000000 +0300
@@ -81,6 +81,13 @@
 
   /* Unknown transitive attribute. */
   struct transit *transit;
+
+  
+#ifdef SUPPORT_REALMS
+  /* Realm used */  
+  u_int16_t realmto;
+#endif
+
 };
 
 /* Router Reflector related structure. */
diff -Nru quagga-0.98.6.orig/bgpd/bgp_route.c quagga-0.98.6/bgpd/bgp_route.c
--- quagga-0.98.6.orig/bgpd/bgp_route.c	2006-05-08 18:03:25.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_route.c	2006-05-10 10:02:55.000000000 +0300
@@ -413,7 +413,28 @@
     }
   return 0;
 }
-
+
+#ifdef SUPPORT_REALMS
+
+#define REALM_PEER_AS	0xFFFFA
+#define REALM_ORIGIN_AS	0xFFFFB
+
+/* Attr. Flags and Attr. Type Code. */
+#define AS_HEADER_SIZE        2	 
+
+/* Two octet is used for AS value. */
+#define AS_VALUE_SIZE         sizeof (as_t)
+
+/* To fetch and store as segment value. */
+struct assegment
+{
+  u_char type;
+  u_char length;
+  as_t asval[1];
+};
+
+#endif
+
 int
 bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr,
 		    afi_t afi, safi_t safi)
@@ -422,6 +443,50 @@
   struct bgp_info info;
   route_map_result_t ret;
 
+#ifdef SUPPORT_REALMS
+
+  u_int16_t realm_value = 0;
+  struct aspath *aspath;
+
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+
+
+  /* Apply default realm value. */
+  aspath = attr->aspath;
+
+  if (peer->realm == REALM_PEER_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_PERMIT;
+
+      pnt = aspath->data;
+      assegment = (struct assegment *) pnt;      
+      realm_value = ntohs (assegment->asval[0]);
+
+  }
+  else if (peer->realm == REALM_ORIGIN_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_PERMIT;
+
+     pnt = aspath->data;
+     end = aspath->data + aspath->length;
+
+     while (pnt < end)
+      {
+        assegment = (struct assegment *) pnt;
+	realm_value = ntohs (assegment->asval[assegment->length - 1]);
+        pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+     }
+  }
+  else realm_value = (u_int16_t)(peer->realm & 0xFFFF);
+  
+  attr->realmto = realm_value;
+
+#endif
+
   filter = &peer->filter[afi][safi];
 
   /* Apply default weight value. */
@@ -450,7 +515,7 @@
     }
   return RMAP_PERMIT;
 }
-
+
 int
 bgp_export_modifier (struct peer *rsclient, struct peer *peer,
         struct prefix *p, struct attr *attr, afi_t afi, safi_t safi)
@@ -493,6 +558,51 @@
   struct bgp_info info;
   route_map_result_t ret;
 
+#ifdef SUPPORT_REALMS
+
+  u_int16_t realm_value = 0;
+  struct aspath *aspath;
+
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+
+
+  /* Apply default realm value. */
+  aspath = attr->aspath;
+
+  if (peer->realm == REALM_PEER_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_PERMIT;
+
+      pnt = aspath->data;
+      assegment = (struct assegment *) pnt;      
+      realm_value = ntohs (assegment->asval[0]);
+
+  }
+  else if (peer->realm == REALM_ORIGIN_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_PERMIT;
+
+     pnt = aspath->data;
+     end = aspath->data + aspath->length;
+
+     while (pnt < end)
+      {
+        assegment = (struct assegment *) pnt;
+	realm_value = ntohs (assegment->asval[assegment->length - 1]);
+        pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+     }
+  }
+  else realm_value = (u_int16_t)(peer->realm & 0xFFFF);
+  
+  attr->realmto = realm_value;
+
+#endif
+
+
   filter = &rsclient->filter[afi][safi];
 
   /* Apply default weight value. */
@@ -4776,6 +4886,11 @@
 
       vty_out (vty, "%7u ",attr->weight);
     
+#ifdef SUPPORT_REALMS
+      vty_out (vty, "%7u    ", attr->realmto);
+#endif
+
+    
     /* Print aspath */
     if (attr->aspath)
       aspath_print_vty (vty, attr->aspath);
@@ -5196,6 +5311,13 @@
       if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
 	vty_out (vty, ", best");
 
+#ifdef SUPPORT_REALMS
+      if (attr->realmto) {
+	char realmbuf[64];
+	vty_out (vty, ", realm %s", rtnl_rtrealm_n2a (attr->realmto, realmbuf, sizeof (realmbuf)));
+      }
+#endif
+
       vty_out (vty, "%s", VTY_NEWLINE);
 	  
       /* Line 4 display Community */
@@ -5233,8 +5355,14 @@
     }
   vty_out (vty, "%s", VTY_NEWLINE);
 }  
-
+
+
+#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 -Nru quagga-0.98.6.orig/bgpd/bgp_routemap.c quagga-0.98.6/bgpd/bgp_routemap.c
--- quagga-0.98.6.orig/bgpd/bgp_routemap.c	2006-03-30 20:49:45.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_routemap.c	2006-05-10 10:02:55.000000000 +0300
@@ -1054,6 +1054,123 @@
   route_set_metric_compile,
   route_set_metric_free,
 };
+
+#ifdef SUPPORT_REALMS
+/* `set realm REALM' */
+
+#define REALM_PEER_AS	0xFFFFA
+#define REALM_ORIGIN_AS	0xFFFFB
+
+/* Attr. Flags and Attr. Type Code. */
+#define AS_HEADER_SIZE        2	 
+
+/* Two octet is used for AS value. */
+#define AS_VALUE_SIZE         sizeof (as_t)
+
+/* To fetch and store as segment value. */
+struct assegment
+{
+  u_char type;
+  u_char length;
+  as_t asval[1];
+};
+
+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;
+  struct aspath *aspath;
+
+  caddr_t pnt;
+  caddr_t end;
+  struct assegment *assegment;
+
+  if(type != RMAP_BGP)
+    return RMAP_OKAY;
+
+  bgp_info = object;
+  aspath = bgp_info->attr->aspath;
+  realm = (u_int32_t*) rule;
+  
+  if (*realm == REALM_PEER_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_OKAY;
+
+      pnt = aspath->data;
+      assegment = (struct assegment *) pnt;      
+      realm_value = ntohs (assegment->asval[0]);
+
+  }
+  else if (*realm == REALM_ORIGIN_AS)
+  {
+      if (aspath == NULL || aspath->length == 0)
+	return RMAP_OKAY;
+
+     pnt = aspath->data;
+     end = aspath->data + aspath->length;
+
+     while (pnt < end)
+      {
+        assegment = (struct assegment *) pnt;
+	realm_value = ntohs (assegment->asval[assegment->length - 1]);
+        pnt += (assegment->length * AS_VALUE_SIZE) + AS_HEADER_SIZE;
+     }
+  }
+  else realm_value = (u_int16_t)(*realm & 0xFFFF);
+  
+  bgp_info->attr->realmto = realm_value;
+
+  return RMAP_OKAY;
+}
+
+/*
+ * set realm REALM - to set 'to' realm of route
+ */
+void *
+route_set_realm_compile (char *arg)
+{
+  u_int32_t *realm;
+  u_int32_t realmid;
+
+  if (strcmp(arg, "peer-as") == 0) 
+  {
+    realmid = REALM_PEER_AS;
+  } 
+  else if (strcmp(arg, "origin-as") == 0) 
+  {
+    realmid = REALM_ORIGIN_AS;
+  } 
+  else 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;
+}
+
+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' */
 
@@ -2694,6 +2811,59 @@
        "Metric value for destination routing protocol\n"
        "Metric value\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]);
+}
+
+ALIAS (set_realm,
+       set_realm_origin_peer_cmd,
+       "set realm (origin-as|peer-as)",
+       MATCH_STR
+       "Set realm for Linux FIB routes\n"
+       "Use route origin AS as realm id\n"
+       "Use route peer AS as realm id\n")
+
+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")
+
+ALIAS (no_set_realm,
+       no_set_realm_origin_peer_cmd,
+       "no set realm (origin-as|peer-as)",
+       NO_STR
+       SET_STR
+       "Realm value(s) for Linux FIB routes\n"
+       "Origin AS - realm\n"
+       "Peer AS - realm\n")
+
+#endif
+
 DEFUN (set_local_pref,
        set_local_pref_cmd,
        "set local-preference <0-4294967295>",
@@ -3419,6 +3589,10 @@
   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_origin_cmd);
   route_map_install_set (&route_set_atomic_aggregate_cmd);
@@ -3481,6 +3655,13 @@
   install_element (RMAP_NODE, &set_metric_addsub_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, &set_realm_origin_peer_cmd);
+  install_element (RMAP_NODE, &no_set_realm_cmd);
+  install_element (RMAP_NODE, &no_set_realm_val_cmd);
+  install_element (RMAP_NODE, &no_set_realm_origin_peer_cmd);
+#endif
   install_element (RMAP_NODE, &set_aspath_prepend_cmd);
   install_element (RMAP_NODE, &no_set_aspath_prepend_cmd);
   install_element (RMAP_NODE, &no_set_aspath_prepend_val_cmd);
diff -Nru quagga-0.98.6.orig/bgpd/bgp_vty.c quagga-0.98.6/bgpd/bgp_vty.c
--- quagga-0.98.6.orig/bgpd/bgp_vty.c	2006-03-30 19:12:25.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_vty.c	2006-05-10 10:02:55.000000000 +0300
@@ -2812,7 +2812,7 @@
        NEIGHBOR_ADDR_STR
        "Neighbor's BGP port\n"
        "TCP port number\n")
-
+
 /* neighbor weight. */
 int
 peer_weight_set_vty (struct vty *vty, const char *ip_str, 
@@ -2877,7 +2877,114 @@
        NEIGHBOR_ADDR_STR2
        "Set default weight for routes from this neighbor\n"
        "default weight\n")
-
+
+#ifdef SUPPORT_REALMS
+
+#define REALM_PEER_AS	0xFFFFA
+#define REALM_ORIGIN_AS	0xFFFFB
+
+/* neighbor realm.*/
+int
+peer_realm_set_vty (struct vty *vty, const char *ip_str, 
+                     const char *realm_str)
+{
+  struct peer *peer;
+  u_int32_t realmid;
+  
+  if (strcmp(realm_str, "peer-as") == 0)
+  {
+    realmid = REALM_PEER_AS;
+  } 
+  else if (strcmp(realm_str, "origin-as") == 0)
+  {
+    realmid = REALM_ORIGIN_AS;
+  } 
+  else 
+  {
+    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;
+}
+
+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]);
+}
+
+ALIAS (neighbor_realm,
+       neighbor_realm_origin_peer_cmd,
+       NEIGHBOR_CMD2 "realm (origin-as|peer-as)",
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set default realm for routes from this neighbor\n"
+       "Set default realm to received route origin AS\n"
+       "Set default realm to peer AS")
+
+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")
+
+ALIAS (no_neighbor_realm,
+       no_neighbor_realm_origin_peer_cmd,
+       NO_NEIGHBOR_CMD2 "realm (origin-as|peer-as)",
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Set default realm for routes from this neighbor\n"
+       "Set default realm to received route origin AS\n"
+       "Set default realm to peer AS")
+#endif
+
 /* Override capability negotiation. */
 DEFUN (neighbor_override_capability,
        neighbor_override_capability_cmd,
@@ -7083,6 +7190,27 @@
 
   vty_out (vty, "%s", VTY_NEWLINE);
 
+#ifdef SUPPORT_REALMS
+
+  /* Default realm */
+  if (CHECK_FLAG (p->config, PEER_CONFIG_REALM)) 
+  {
+    char realmbuf[64];
+    if (p->realm == REALM_PEER_AS)	  
+      vty_out (vty, "  Default realm is peer-as%s",
+  	   VTY_NEWLINE);	    	  
+    else if (p->realm == REALM_ORIGIN_AS)	  
+      vty_out (vty, "  Default realm is origin-as%s",
+	   VTY_NEWLINE);	  
+    else 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++)
@@ -8839,6 +8967,17 @@
   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, &neighbor_realm_origin_peer_cmd);
+  install_element (BGP_NODE, &no_neighbor_realm_cmd);
+  install_element (BGP_NODE, &no_neighbor_realm_origin_peer_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 -Nru quagga-0.98.6.orig/bgpd/bgp_zebra.c quagga-0.98.6/bgpd/bgp_zebra.c
--- quagga-0.98.6.orig/bgpd/bgp_zebra.c	2005-06-15 14:53:56.000000000 +0300
+++ quagga-0.98.6/bgpd/bgp_zebra.c	2006-05-10 10:02:55.000000000 +0300
@@ -662,6 +662,15 @@
 	  SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE);
 	  api.distance = distance;
 	}
+
+#ifdef SUPPORT_REALMS
+      if (info->attr->realmto)
+	{
+	  SET_FLAG (api.message, ZAPI_MESSAGE_REALMTO);
+	  api.realmto = info->attr->realmto;
+	}
+#endif
+
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, 
                        (struct prefix_ipv4 *) p, &api);
     }
diff -Nru quagga-0.98.6.orig/bgpd/bgpd.c quagga-0.98.6/bgpd/bgpd.c
--- quagga-0.98.6.orig/bgpd/bgpd.c	2005-06-15 14:53:56.000000000 +0300
+++ quagga-0.98.6/bgpd/bgpd.c	2006-05-10 10:02:55.000000000 +0300
@@ -632,6 +632,10 @@
   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 determin is this peer IBGP or EBGP */
@@ -708,6 +712,10 @@
   peer->version = BGP_VERSION_4;
   peer->weight = 0;
 
+#ifdef SUPPORT_REALMS
+  peer->realm = 0;
+#endif
+
   /* Set default flags.  */
   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
@@ -1271,6 +1279,13 @@
   /* 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 */
@@ -2884,7 +2899,7 @@
   peer->port = BGP_PORT_DEFAULT;
   return 0;
 }
-
+
 /* neighbor weight. */
 int
 peer_weight_set (struct peer *peer, u_int16_t weight)
@@ -2932,7 +2947,60 @@
     }
   return 0;
 }
-
+
+#ifdef SUPPORT_REALMS
+
+/* neighbor realm. */
+int
+peer_realm_set (struct peer *peer, u_int32_t realm)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  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;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->realm = group->conf->realm;
+    }
+  return 0;
+}
+
+int
+peer_realm_unset (struct peer *peer)
+{
+  struct peer_group *group;
+  struct listnode *nn;
+
+  /* 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;
+  LIST_LOOP (group->peer, peer, nn)
+    {
+      peer->realm = 0;
+    }
+  return 0;
+}
+
+
+#endif
+
 int
 peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
 {
@@ -4368,6 +4436,28 @@
 	  vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
 		   VTY_NEWLINE);
 
+#ifdef SUPPORT_REALMS
+
+#define REALM_PEER_AS	0xFFFFA
+#define REALM_ORIGIN_AS	0xFFFFB
+
+      /* Default realm. */
+      if (CHECK_FLAG (peer->config, PEER_CONFIG_REALM))
+        if (! peer_group_active (peer) ||
+	    g_peer->realm != peer->realm) 
+	{
+	  char realmbuf[64];
+	  if (peer->realm == REALM_PEER_AS)	  
+	    vty_out (vty, " neighbor %s realm peer-as%s", addr,
+		   VTY_NEWLINE);	    	  
+	  else if (peer->realm == REALM_ORIGIN_AS)	  
+	    vty_out (vty, " neighbor %s realm origin-as%s", addr,
+		   VTY_NEWLINE);	  
+	  else vty_out (vty, " neighbor %s realm %s%s", addr, 
+	       rtnl_rtrealm_n2a (peer->realm, realmbuf, sizeof (realmbuf)), VTY_NEWLINE);
+	}
+#endif
+
       /* Route refresh. */
       if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
         if (! peer_group_active (peer) ||
diff -Nru quagga-0.98.6.orig/bgpd/bgpd.h quagga-0.98.6/bgpd/bgpd.h
--- quagga-0.98.6.orig/bgpd/bgpd.h	2005-06-15 14:53:57.000000000 +0300
+++ quagga-0.98.6/bgpd/bgpd.h	2006-05-10 10:02:55.000000000 +0300
@@ -392,6 +392,11 @@
   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;
   u_int32_t v_connect;
@@ -856,6 +861,11 @@
 int peer_weight_set (struct peer *, u_int16_t);
 int peer_weight_unset (struct peer *);
 
+#ifdef SUPPORT_REALMS
+int peer_realm_set (struct peer *, u_int32_t);
+int peer_realm_unset (struct peer *);
+#endif
+
 int peer_timers_set (struct peer *, u_int32_t, u_int32_t);
 int peer_timers_unset (struct peer *);
 
diff -Nru quagga-0.98.6.orig/config.h.in quagga-0.98.6/config.h.in
--- quagga-0.98.6.orig/config.h.in	2006-05-08 18:07:44.000000000 +0300
+++ quagga-0.98.6/config.h.in	2006-05-10 10:02:55.000000000 +0300
@@ -444,6 +444,9 @@
 /* OSPFAPI */
 #undef SUPPORT_OSPF_API
 
+/* Realms support */
+#undef SUPPORT_REALMS
+
 /* SNMP */
 #undef UCD_COMPATIBLE
 
diff -Nru quagga-0.98.6.orig/configure quagga-0.98.6/configure
--- quagga-0.98.6.orig/configure	2006-05-08 18:07:44.000000000 +0300
+++ quagga-0.98.6/configure	2006-05-10 10:06:11.000000000 +0300
@@ -419,7 +419,7 @@
 # Identity of this package.
 PACKAGE_NAME='Quagga'
 PACKAGE_TARNAME='quagga'
-PACKAGE_VERSION='0.98.6'
+PACKAGE_VERSION='0.98.6-realms'
 PACKAGE_STRING='Quagga 0.98.6'
 PACKAGE_BUGREPORT='http://bugzilla.quagga.net'
 
@@ -1042,6 +1042,7 @@
   --enable-vty-group=ARG  set vty sockets to have specified group as owner
   --enable-configfile-mask=ARG  set mask for config files
   --enable-logfile-mask=ARG     set mask for log files
+  --enable-realms         enable REALMS support under Linux
   --disable-rtadv               disable IPV6 router advertisement feature
   --enable-irdp                 enable IRDP server support in zebra
   --disable-capabilities        disable using POSIX capabilities
@@ -1907,7 +1908,7 @@
 
 # Define the identity of the package.
  PACKAGE='quagga'
- VERSION='0.98.6'
+ VERSION='0.98.6-realms'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -9219,6 +9220,11 @@
 
 fi;
 
+# Check whether --enable-realms or --disable-realms was given.
+if test "${enable_realms+set}" = set; then
+  enableval="$enable_realms"
+
+fi;
 # Check whether --enable-rtadv or --disable-rtadv was given.
 if test "${enable_rtadv+set}" = set; then
   enableval="$enable_rtadv"
@@ -10773,6 +10779,19 @@
   ;;
 esac
 
+if test "${enable_realms}" = "yes"; then
+    if test "${opsys}" != "gnu-linux"; then
+	echo "Sorry, only Linux has REALMS support"
+	exit 1
+    fi
+	
+cat >>confdefs.h <<\_ACEOF
+#define SUPPORT_REALMS
+_ACEOF
+		
+fi
+		
+
 case "${enable_vtysh}" in
   "yes") VTYSH="vtysh";
 
diff -Nru quagga-0.98.6.orig/configure.ac quagga-0.98.6/configure.ac
--- quagga-0.98.6.orig/configure.ac	2006-05-08 18:07:19.000000000 +0300
+++ quagga-0.98.6/configure.ac	2006-05-10 10:04:16.000000000 +0300
@@ -8,7 +8,7 @@
 ## $Id: configure.ac,v 1.85.2.14 2005/08/28 15:36:28 hasso Exp $
 AC_PREREQ(2.53)
 
-AC_INIT(Quagga, 0.98.6, [http://bugzilla.quagga.net])
+AC_INIT(Quagga, 0.98.6-realms, [http://bugzilla.quagga.net])
 AC_CONFIG_SRCDIR(lib/zebra.h)
 
 dnl -----------------------------------
@@ -150,7 +150,8 @@
 [  --enable-configfile-mask=ARG  set mask for config files])
 AC_ARG_ENABLE(logfile_mask,
 [  --enable-logfile-mask=ARG     set mask for log files])
-
+AC_ARG_ENABLE(realms,
+[  --enable-realms	   enable REALMS support under Linux])
 AC_ARG_ENABLE(rtadv,
 [  --disable-rtadv               disable IPV6 router advertisement feature])
 AC_ARG_ENABLE(irdp,
@@ -334,6 +335,14 @@
   ;;
 esac
 
+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
+
 dnl ---------------------
 dnl Integrated VTY option
 dnl ---------------------
diff -Nru quagga-0.98.6.orig/lib/ChangeLog quagga-0.98.6/lib/ChangeLog
--- quagga-0.98.6.orig/lib/ChangeLog	2006-03-30 19:24:46.000000000 +0300
+++ quagga-0.98.6/lib/ChangeLog	2006-05-10 10:02:55.000000000 +0300
@@ -30,6 +30,12 @@
 	* routemap.c: [rmap_onmatch_goto] fix crash if continue command
 	  is used, which does not supply an argv[0].
 
+2005-04-24 Calin Velea <vcalinus at gemenii.ro>
+ 	* rt_names.c, rt_names.h: Library for realm name support - original
+ 	  iproute2 version modified to support name database reloading
+ 	* zclient.c, zclient.h: API realmto message
+ 	* zebra.h: Include rt_names.h
+
 2005-03-25 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
 
 	* zebra.h: Must check whether __attribute__ should be defined before
diff -Nru quagga-0.98.6.orig/lib/Makefile.am quagga-0.98.6/lib/Makefile.am
--- quagga-0.98.6.orig/lib/Makefile.am	2005-06-15 14:54:10.000000000 +0300
+++ quagga-0.98.6/lib/Makefile.am	2006-05-10 10:02:55.000000000 +0300
@@ -12,7 +12,7 @@
 	sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
 	filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
 	zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \
-	sigevent.c pqueue.c jhash.c
+	sigevent.c pqueue.c jhash.c rt_names.c
 
 libzebra_la_DEPENDENCIES = @LIB_REGEX@
 
@@ -23,7 +23,7 @@
 	memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
 	str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
 	plist.h zclient.h sockopt.h smux.h md5-gnu.h if_rmap.h keychain.h \
-	privs.h sigevent.h pqueue.h jhash.h zassert.h
+	privs.h sigevent.h pqueue.h jhash.h zassert.h rt_names.h
 
 EXTRA_DIST = regex.c regex-gnu.h
 
diff -Nru quagga-0.98.6.orig/lib/Makefile.in quagga-0.98.6/lib/Makefile.in
--- quagga-0.98.6.orig/lib/Makefile.in	2006-05-08 18:07:54.000000000 +0300
+++ quagga-0.98.6/lib/Makefile.in	2006-05-10 10:02:55.000000000 +0300
@@ -66,7 +66,7 @@
 	sockunion.lo prefix.lo thread.lo if.lo memory.lo buffer.lo \
 	table.lo hash.lo filter.lo routemap.lo distribute.lo stream.lo \
 	str.lo log.lo plist.lo zclient.lo sockopt.lo smux.lo md5.lo \
-	if_rmap.lo keychain.lo privs.lo sigevent.lo pqueue.lo jhash.lo
+	if_rmap.lo keychain.lo privs.lo sigevent.lo pqueue.lo jhash.lo rt_names.lo
 libzebra_la_OBJECTS = $(am_libzebra_la_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -223,7 +223,7 @@
 	sockunion.c prefix.c thread.c if.c memory.c buffer.c table.c hash.c \
 	filter.c routemap.c distribute.c stream.c str.c log.c plist.c \
 	zclient.c sockopt.c smux.c md5.c if_rmap.c keychain.c privs.c \
-	sigevent.c pqueue.c jhash.c
+	sigevent.c pqueue.c jhash.c rt_names.c
 
 libzebra_la_DEPENDENCIES = @LIB_REGEX@
 libzebra_la_LIBADD = @LIB_REGEX@
@@ -232,7 +232,7 @@
 	memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
 	str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
 	plist.h zclient.h sockopt.h smux.h md5-gnu.h if_rmap.h keychain.h \
-	privs.h sigevent.h pqueue.h jhash.h zassert.h
+	privs.h sigevent.h pqueue.h jhash.h zassert.h rt_names.h
 
 EXTRA_DIST = regex.c regex-gnu.h
 all: all-am
@@ -331,8 +331,10 @@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/privs.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/routemap.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigevent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rt_names.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/smux.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockopt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rt_names.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockunion.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/str.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@
diff -Nru quagga-0.98.6.orig/lib/rt_names.c quagga-0.98.6/lib/rt_names.c
--- quagga-0.98.6.orig/lib/rt_names.c	1970-01-01 02:00:00.000000000 +0200
+++ quagga-0.98.6/lib/rt_names.c	2006-05-10 10:02:55.000000000 +0300
@@ -0,0 +1,412 @@
+/*
+ * 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, <kuznet@ms2.inr.ac.ru>
+ *
+ * Fix:		23 Apr 2005 	Calin Velea <vcalinus@gemenii.ro>
+ *		
+ *		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
+ *		
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/time.h>
+
+static void rtnl_tab_initialize(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_rtprot_tab[256] = {
+	"none",
+	"redirect",
+	"kernel",
+	"boot",
+	"static",
+	NULL,
+	NULL,
+	NULL,
+	"gated",
+	"ra",
+	"mrt",
+	"zebra",
+	"bird",
+};
+
+
+
+static int rtnl_rtprot_init;
+
+static void rtnl_rtprot_initialize(void)
+{
+	rtnl_rtprot_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_protos",
+			    rtnl_rtprot_tab, 256);
+}
+
+char * rtnl_rtprot_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtprot_tab[id]) {
+		if (!rtnl_rtprot_init)
+			rtnl_rtprot_initialize();
+	}
+    if (rtnl_rtprot_tab[id])
+		return rtnl_rtprot_tab[id];
+	snprintf(buf, len, "%d", id);
+	return buf;
+}
+
+int rtnl_rtprot_a2n(u_int32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtprot_init)
+		rtnl_rtprot_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtprot_tab[i] &&
+		    strcmp(rtnl_rtprot_tab[i], arg) == 0) {
+			cache = rtnl_rtprot_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
+
+
+static char * rtnl_rtscope_tab[256] = {
+	"global",
+};
+
+static int rtnl_rtscope_init;
+
+static void rtnl_rtscope_initialize(void)
+{
+	rtnl_rtscope_init = 1;
+	rtnl_rtscope_tab[255] = "nowhere";
+	rtnl_rtscope_tab[254] = "host";
+	rtnl_rtscope_tab[253] = "link";
+	rtnl_rtscope_tab[200] = "site";
+	rtnl_tab_initialize("/etc/iproute2/rt_scopes",
+			    rtnl_rtscope_tab, 256);
+}
+
+char * rtnl_rtscope_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtscope_tab[id]) {
+		if (!rtnl_rtscope_init)
+			rtnl_rtscope_initialize();
+	}
+	if (rtnl_rtscope_tab[id])
+		return rtnl_rtscope_tab[id];
+	snprintf(buf, len, "%d", id);
+	return buf;
+}
+
+int rtnl_rtscope_a2n(u_int32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtscope_init)
+		rtnl_rtscope_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtscope_tab[i] &&
+		    strcmp(rtnl_rtscope_tab[i], arg) == 0) {
+			cache = rtnl_rtscope_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
+
+
+static char * rtnl_rtrealm_tab[256] = {
+	"unknown",
+};
+
+static int rtnl_rtrealm_init = 0;
+
+static void rtnl_rtrealm_initialize(void)
+{
+	int i;
+	
+	if(!rtnl_rtrealm_init)
+	    for(i = 1; i < 255; i++)
+		rtnl_rtrealm_tab[i] = NULL;	
+	
+	rtnl_rtrealm_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_realms",
+			    rtnl_rtrealm_tab, 256);
+}
+
+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, 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;
+}
+
+
+
+static char * rtnl_rttable_tab[256] = {
+	"unspec",
+};
+
+static int rtnl_rttable_init;
+
+static void rtnl_rttable_initialize(void)
+{
+	rtnl_rttable_init = 1;
+	rtnl_rttable_tab[255] = "local";
+	rtnl_rttable_tab[254] = "main";
+	rtnl_tab_initialize("/etc/iproute2/rt_tables",
+			    rtnl_rttable_tab, 256);
+}
+
+char * rtnl_rttable_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rttable_tab[id]) {
+		if (!rtnl_rttable_init)
+			rtnl_rttable_initialize();
+	}
+	if (rtnl_rttable_tab[id])
+		return rtnl_rttable_tab[id];
+	snprintf(buf, len, "%d", id);
+	return buf;
+}
+
+int rtnl_rttable_a2n(u_int32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rttable_init)
+		rtnl_rttable_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rttable_tab[i] &&
+		    strcmp(rtnl_rttable_tab[i], arg) == 0) {
+			cache = rtnl_rttable_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	i = strtoul(arg, &end, 0);
+	if (!end || end == arg || *end || i > 255)
+		return -1;
+	*id = i;
+	return 0;
+}
+
+
+static char * rtnl_rtdsfield_tab[256] = {
+	"0",
+};
+
+static int rtnl_rtdsfield_init;
+
+static void rtnl_rtdsfield_initialize(void)
+{
+	rtnl_rtdsfield_init = 1;
+	rtnl_tab_initialize("/etc/iproute2/rt_dsfield",
+			    rtnl_rtdsfield_tab, 256);
+}
+
+char * rtnl_dsfield_n2a(int id, char *buf, int len)
+{
+	if (id<0 || id>=256) {
+		snprintf(buf, len, "%d", id);
+		return buf;
+	}
+	if (!rtnl_rtdsfield_tab[id]) {
+		if (!rtnl_rtdsfield_init)
+			rtnl_rtdsfield_initialize();
+	}
+	if (rtnl_rtdsfield_tab[id])
+		return rtnl_rtdsfield_tab[id];
+	snprintf(buf, len, "0x%02x", id);
+	return buf;
+}
+
+
+int rtnl_dsfield_a2n(u_int32_t *id, char *arg)
+{
+	static char *cache = NULL;
+	static unsigned long res;
+	char *end;
+	int i;
+
+	if (cache && strcmp(cache, arg) == 0) {
+		*id = res;
+		return 0;
+	}
+
+	if (!rtnl_rtdsfield_init)
+	    rtnl_rtdsfield_initialize();
+
+	for (i=0; i<256; i++) {
+		if (rtnl_rtdsfield_tab[i] &&
+		    strcmp(rtnl_rtdsfield_tab[i], arg) == 0) {
+			cache = rtnl_rtdsfield_tab[i];
+			res = i;
+			*id = res;
+			return 0;
+		}
+	}
+
+	res = strtoul(arg, &end, 16);
+	if (!end || end == arg || *end || res > 255)
+		return -1;
+	*id = res;
+	return 0;
+}
+
diff -Nru quagga-0.98.6.orig/lib/rt_names.h quagga-0.98.6/lib/rt_names.h
--- quagga-0.98.6.orig/lib/rt_names.h	1970-01-01 02:00:00.000000000 +0200
+++ quagga-0.98.6/lib/rt_names.h	2006-05-10 10:02:55.000000000 +0300
@@ -0,0 +1,28 @@
+#ifndef RT_NAMES_H_
+#define RT_NAMES_H_ 1
+
+const char* rtnl_rtprot_n2a(int id, char *buf, int len);
+const char* rtnl_rtscope_n2a(int id, char *buf, int len);
+const char* rtnl_rttable_n2a(int id, char *buf, int len);
+const char* rtnl_rtrealm_n2a(int id, char *buf, int len);
+const char* rtnl_dsfield_n2a(int id, char *buf, int len);
+int rtnl_rtprot_a2n(int *id, char *arg);
+int rtnl_rtscope_a2n(int *id, char *arg);
+int rtnl_rttable_a2n(int *id, char *arg);
+int rtnl_rtrealm_a2n(__u32 *id, char *arg);
+int rtnl_dsfield_a2n(__u32 *id, char *arg);
+
+const char *inet_proto_n2a(int proto, char *buf, int len);
+int inet_proto_a2n(char *buf);
+
+
+const char * ll_type_n2a(int type, char *buf, int len);
+
+const char *ll_addr_n2a(unsigned char *addr, int alen, int type, char *buf, int blen);
+int ll_addr_a2n(unsigned char *lladdr, int len, char *arg);
+
+const char * ll_proto_n2a(unsigned short id, char *buf, int len);
+int ll_proto_a2n(unsigned short *id, char *buf);
+
+
+#endif
diff -Nru quagga-0.98.6.orig/lib/version.h quagga-0.98.6/lib/version.h
--- quagga-0.98.6.orig/lib/version.h	2006-05-08 20:15:44.000000000 +0300
+++ quagga-0.98.6/lib/version.h	2006-05-10 10:03:32.000000000 +0300
@@ -26,7 +26,7 @@
 
 #define QUAGGA_PROGNAME   "Quagga"
 
-#define QUAGGA_VERSION     "0.98.6"
+#define QUAGGA_VERSION     "0.98.6-realms"
 
 #define ZEBRA_BUG_ADDRESS "http://bugzilla.quagga.net"
 
diff -Nru quagga-0.98.6.orig/lib/zclient.c quagga-0.98.6/lib/zclient.c
--- quagga-0.98.6.orig/lib/zclient.c	2005-06-15 14:54:18.000000000 +0300
+++ quagga-0.98.6/lib/zclient.c	2006-05-10 10:02:55.000000000 +0300
@@ -391,6 +391,11 @@
   if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC))
     stream_putl (s, api->metric);
 
+#ifdef SUPPORT_REALMS
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_REALMTO))
+    stream_putw (s, api->realmto);
+#endif
+
   /* Put length at the first point of the stream. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
diff -Nru quagga-0.98.6.orig/lib/zclient.h quagga-0.98.6/lib/zclient.h
--- quagga-0.98.6.orig/lib/zclient.h	2005-06-15 14:54:18.000000000 +0300
+++ quagga-0.98.6/lib/zclient.h	2006-05-10 10:02:55.000000000 +0300
@@ -81,6 +81,10 @@
 #define ZAPI_MESSAGE_DISTANCE 0x04
 #define ZAPI_MESSAGE_METRIC   0x08
 
+#ifdef SUPPORT_REALMS
+    #define ZAPI_MESSAGE_REALMTO   0x10
+#endif
+
 /* Zebra IPv4 route message API. */
 struct zapi_ipv4
 {
@@ -99,6 +103,11 @@
   u_char distance;
 
   u_int32_t metric;
+  
+#ifdef SUPPORT_REALMS
+  u_int16_t realmto;
+#endif
+
 };
 
 /* Prototypes of zebra client service functions. */
diff -Nru quagga-0.98.6.orig/lib/zebra.h quagga-0.98.6/lib/zebra.h
--- quagga-0.98.6.orig/lib/zebra.h	2005-06-15 14:54:18.000000000 +0300
+++ quagga-0.98.6/lib/zebra.h	2006-05-10 10:02:55.000000000 +0300
@@ -205,6 +205,10 @@
 #include <libutil.h>
 #endif /* HAVE_LIBUTIL_H */
 
+#ifdef SUPPORT_REALMS
+#include <rt_names.h>
+#endif
+
 #ifdef HAVE_GLIBC_BACKTRACE
 #include <execinfo.h>
 #endif /* HAVE_GLIBC_BACKTRACE */
diff -Nru quagga-0.98.6.orig/zebra/ChangeLog quagga-0.98.6/zebra/ChangeLog
--- quagga-0.98.6.orig/zebra/ChangeLog	2005-09-23 13:41:20.000000000 +0300
+++ quagga-0.98.6/zebra/ChangeLog	2006-05-10 10:02:55.000000000 +0300
@@ -27,6 +27,14 @@
 	* rt_netlink.c (netlink_route_multipath): Fix debug. No useless info
 	  is printed out now and IPv6 info is handeled.
 
+2005-04-24 Calin Velea <vcalinus at gemenii.ro>
+ 	* rt_netlink.c: Modified netlink_route(), netlink_routing_table(),
+ 	  netlink_route_change() to use realms when working with kernel 
+ 	  table
+ 	* zebra_rib.c, zebra_vty.c, zserv.c, connected.c: realm support 
+ 	  for static routes
+ 	* rib.h: Add realm attribute to rib and static_ipv4 structs
+
 2005-04-01 Hasso Tepper <hasso at quagga.net>
 
 	* rt_netlink.c (netlink_talk): Don't assume we use netlink_cmd
diff -Nru quagga-0.98.6.orig/zebra/connected.c quagga-0.98.6/zebra/connected.c
--- quagga-0.98.6.orig/zebra/connected.c	2005-09-23 13:41:20.000000000 +0300
+++ quagga-0.98.6/zebra/connected.c	2006-05-10 10:02:55.000000000 +0300
@@ -82,7 +82,11 @@
   if (prefix_ipv4_any (&p))
     return;
 
+#ifndef SUPPORT_REALMS
   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0);
+#else
+  rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0, 0);
+#endif
 
   rib_update ();
 }
diff -Nru quagga-0.98.6.orig/zebra/rib.h quagga-0.98.6/zebra/rib.h
--- quagga-0.98.6.orig/zebra/rib.h	2005-09-23 13:41:21.000000000 +0300
+++ quagga-0.98.6/zebra/rib.h	2006-05-10 10:02:55.000000000 +0300
@@ -60,6 +60,12 @@
   u_char nexthop_fib_num;
 
   struct nexthop *nexthop;
+  
+#ifdef SUPPORT_REALMS
+  /* Realm information */
+  u_int16_t realmto;
+#endif
+
 };
 
 /* Static route information. */
@@ -91,6 +97,11 @@
  see ZEBRA_FLAG_REJECT
      ZEBRA_FLAG_BLACKHOLE
  */
+ 
+#ifdef SUPPORT_REALMS
+  u_int16_t realmto;
+#endif
+
 };
 
 #ifdef HAVE_IPV6
@@ -213,7 +224,11 @@
 int
 rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, 
 	      struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
+#ifndef SUPPORT_REALMS
 	      u_int32_t, u_char);
+#else
+              u_int32_t, u_char, u_int16_t);
+#endif
 
 int
 rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *);
@@ -235,7 +250,12 @@
 
 int
 static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
+#ifndef SUPPORT_REALMS
        u_char flags, u_char distance, u_int32_t vrf_id);
+#else
+       u_char flags, u_char distance, u_int32_t vrf_id, u_int16_t realmto);
+#endif
+
 
 int
 static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
diff -Nru quagga-0.98.6.orig/zebra/rt_netlink.c quagga-0.98.6/zebra/rt_netlink.c
--- quagga-0.98.6.orig/zebra/rt_netlink.c	2005-09-23 13:41:21.000000000 +0300
+++ quagga-0.98.6/zebra/rt_netlink.c	2006-05-10 10:02:55.000000000 +0300
@@ -686,6 +686,12 @@
   void *dest;
   void *gate;
 
+#ifdef SUPPORT_REALMS
+  u_int32_t rta_flow;
+  u_int16_t realmto = 0;
+#endif
+  
+
   rtm = NLMSG_DATA (h);
 
   if (h->nlmsg_type != RTM_NEWROUTE)
@@ -747,7 +753,19 @@
       memcpy (&p.prefix, dest, 4);
       p.prefixlen = rtm->rtm_dst_len;
 
+#ifndef SUPPORT_REALMS
       rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0);
+#else
+      if (tb[RTA_FLOW])
+       {
+         rta_flow = *(u_int32_t *) RTA_DATA (tb[RTA_FLOW]);
+         realmto = rta_flow & 0xFFFF;
+       }
+
+      rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, index, table, metric, 0,
+                   realmto);
+#endif
+	     
     }
 #ifdef HAVE_IPV6
   if (rtm->rtm_family == AF_INET6)
@@ -879,8 +897,20 @@
                        inet_ntoa (p.prefix), p.prefixlen);
         }
 
-      if (h->nlmsg_type == RTM_NEWROUTE)
+      if (h->nlmsg_type == RTM_NEWROUTE) {
+#ifndef SUPPORT_REALMS
         rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
+#else
+       if (tb[RTA_FLOW])
+     {
+       u_int32_t rta_flow = *(u_int32_t *) RTA_DATA (tb[RTA_FLOW]);
+       u_int16_t realmto = rta_flow & 0xFFFF;
+       rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0,
+                     realmto);
+     }
+#endif
+		
+      }
       else
         rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
     }
@@ -1267,7 +1297,13 @@
 /* Routing table change via netlink interface. */
 int
 netlink_route (int cmd, int family, void *dest, int length, void *gate,
+#ifdef SUPPORT_REALMS
+	       int index, int zebra_flags, int table,
+               u_int16_t realmto, u_int16_t realmfrom)
+#else
                int index, int zebra_flags, int table)
+#endif
+
 {
   int ret;
   int bytelen;
@@ -1327,6 +1363,17 @@
         addattr32 (&req.n, sizeof req, RTA_OIF, index);
     }
 
+#ifdef SUPPORT_REALMS
+  if (realmto || realmfrom)
+    {
+      u_int32_t rta_flow;
+      rta_flow = ((u_int32_t) realmfrom) << 16;
+      rta_flow |= (u_int32_t) realmto;
+
+      addattr32 (&req.n, sizeof req, RTA_FLOW, rta_flow);
+    }
+#endif
+
   /* Destination netlink address. */
   memset (&snl, 0, sizeof snl);
   snl.nl_family = AF_NETLINK;
@@ -1408,6 +1455,11 @@
       goto skip;
     }
 
+#ifdef SUPPORT_REALMS
+  if (rib->realmto)
+      addattr32 (&req.n, sizeof req, RTA_FLOW, rib->realmto);
+#endif
+
   /* Multipath case. */
   if (rib->nexthop_active_num == 1 || MULTIPATH_NUM == 1)
     {
@@ -1754,7 +1806,11 @@
                         int index, int flags, int table)
 {
   return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix,
+#ifndef SUPPORT_REALMS
                         dest->prefixlen, gate, index, flags, table);
+#else
+			dest->prefixlen, gate, index, flags, table, 0, 0);
+#endif
 }
 #endif /* HAVE_IPV6 */
 
diff -Nru quagga-0.98.6.orig/zebra/zebra_rib.c quagga-0.98.6/zebra/zebra_rib.c
--- quagga-0.98.6.orig/zebra/zebra_rib.c	2005-09-23 13:41:21.000000000 +0300
+++ quagga-0.98.6/zebra/zebra_rib.c	2006-05-10 10:02:55.000000000 +0300
@@ -977,7 +977,12 @@
 int
 rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, 
 	      struct in_addr *gate, unsigned int ifindex, u_int32_t vrf_id,
+#ifndef SUPPORT_REALMS
 	      u_int32_t metric, u_char distance)
+#else
+              u_int32_t metric, u_char distance, u_int16_t realmto)
+#endif
+	      
 {
   struct rib *rib;
   struct rib *same = NULL;
@@ -1062,6 +1067,10 @@
   /* Link new rib to node.*/
   rib_addnode (rn, rib);
 
+#ifdef SUPPORT_REALMS
+  rib->realmto = realmto;
+#endif
+
   /* Process this route node. */
   rib_process (rn, same);
 
@@ -1331,6 +1340,10 @@
       rib->distance = si->distance;
       rib->metric = 0;
       rib->nexthop_num = 0;
+#ifdef SUPPORT_REALMS
+      rib->realmto = si->realmto;
+#endif
+
 
       switch (si->type)
         {
@@ -1435,10 +1448,15 @@
   route_unlock_node (rn);
 }
 
+
 /* Add static route into static route configuration. */
 int
 static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname,
+#ifndef SUPPORT_REALMS
 		 u_char flags, u_char distance, u_int32_t vrf_id)
+#else
+		 u_char flags, u_char distance, u_int32_t vrf_id, u_int16_t realmto)
+#endif		
 {
   u_char type = 0;
   struct route_node *rn;
@@ -1493,6 +1511,10 @@
   si->distance = distance;
   si->flags = flags;
 
+#ifdef SUPPORT_REALMS
+  si->realmto = realmto;
+#endif
+
   if (gate)
     si->gate.ipv4 = *gate;
   if (ifname)
diff -Nru quagga-0.98.6.orig/zebra/zebra_vty.c quagga-0.98.6/zebra/zebra_vty.c
--- quagga-0.98.6.orig/zebra/zebra_vty.c	2004-12-18 18:03:29.000000000 +0200
+++ quagga-0.98.6/zebra/zebra_vty.c	2006-05-10 10:02:55.000000000 +0300
@@ -88,12 +88,17 @@
       return '?';
     }
 };
-
+
 /* General fucntion for static route. */
 int
 zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str,
 		   const char *mask_str, const char *gate_str,
+#ifndef SUPPORT_REALMS		   
 		   const char *flag_str, const char *distance_str)
+#else
+                   const char *flag_str, const char *distance_str, const char *realm_str)
+#endif
+		   
 {
   int ret;
   u_char distance;
@@ -103,6 +108,23 @@
   const char *ifname;
   u_char flag = 0;
   
+#ifdef SUPPORT_REALMS
+  u_int16_t realmto = 0;
+  u_int32_t realmid;
+  int res;
+
+  if (realm_str != NULL) {
+    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;
+    }
+    realmto = (u_int16_t)realmid;
+  }
+#endif
+  
+  
   ret = str2prefix (dest_str, &p);
   if (ret <= 0)
     {
@@ -140,7 +162,11 @@
           return CMD_WARNING;
         }
       if (add_cmd)
+#ifndef SUPPORT_REALMS      
         static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0);
+#else
+	static_add_ipv4 (&p, NULL, NULL, ZEBRA_FLAG_BLACKHOLE, distance, 0, realmto);
+#endif	
       else
         static_delete_ipv4 (&p, NULL, NULL, distance, 0);
       return CMD_SUCCESS;
@@ -166,7 +192,11 @@
   if (gate_str == NULL)
   {
     if (add_cmd)
+#ifndef SUPPORT_REALMS
       static_add_ipv4 (&p, NULL, NULL, flag, distance, 0);
+#else
+      static_add_ipv4 (&p, NULL, NULL, flag, distance, 0, realmto);
+#endif
     else
       static_delete_ipv4 (&p, NULL, NULL, distance, 0);
 
@@ -181,8 +211,14 @@
   else
     ifname = gate_str;
 
-  if (add_cmd)
+  if (add_cmd) {
+#ifndef SUPPORT_REALMS
     static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0);
+#else
+        static_add_ipv4 (&p, ifname ? NULL : &gate, ifname, flag, distance, 0, realmto);
+#endif
+
+  }
   else
     static_delete_ipv4 (&p, ifname ? NULL : &gate, ifname, distance, 0);
 
@@ -200,7 +236,11 @@
        "IP gateway interface name\n"
        "Null interface\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, NULL, NULL);
+#endif
 }
 
 DEFUN (ip_route_flags,
@@ -214,7 +254,11 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], NULL, NULL);
+#endif
 }
 
 DEFUN (ip_route_flags2,
@@ -226,7 +270,11 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], NULL, NULL);
+#endif
 }
 
 /* Mask as A.B.C.D format.  */
@@ -241,7 +289,11 @@
        "IP gateway interface name\n"
        "Null interface\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, NULL, NULL);
+#endif
 }
 
 DEFUN (ip_route_mask_flags,
@@ -256,7 +308,11 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], NULL, NULL);
+#endif
 }
 
 DEFUN (ip_route_mask_flags2,
@@ -269,7 +325,11 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], NULL, NULL);
+#endif
 }
 
 /* Distance option value.  */
@@ -284,7 +344,11 @@
        "Null interface\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], NULL);
+#endif
 }
 
 DEFUN (ip_route_flags_distance,
@@ -299,7 +363,12 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, argv[1], argv[2], argv[3], NULL);
+#endif
+
 }
 
 DEFUN (ip_route_flags_distance2,
@@ -312,7 +381,11 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], NULL, NULL, argv[1], argv[2], NULL);
+#endif
 }
 
 DEFUN (ip_route_mask_distance,
@@ -327,7 +400,12 @@
        "Null interface\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], NULL);
+#endif
+
 }
 
 DEFUN (ip_route_mask_flags_distance,
@@ -343,7 +421,12 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], argv[2], argv[3], argv[4], NULL);
+#endif
+
 }
 
 DEFUN (ip_route_mask_flags_distance2,
@@ -357,7 +440,12 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 1, argv[0], argv[1], NULL, argv[2], argv[3], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route, 
@@ -371,7 +459,12 @@
        "IP gateway interface name\n"
        "Null interface\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, NULL, NULL);
+#endif
+
 }
 
 ALIAS (no_ip_route,
@@ -396,7 +489,12 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, NULL, NULL, NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_mask,
@@ -411,7 +509,12 @@
        "IP gateway interface name\n"
        "Null interface\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, NULL, NULL);
+#endif
+
 }
 
 ALIAS (no_ip_route_mask,
@@ -438,7 +541,12 @@
        "Emit an ICMP unreachable when matched\n"
        "Silently discard pkts when matched\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, NULL, NULL, NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_distance,
@@ -453,7 +561,12 @@
        "Null interface\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], NULL, argv[2], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_flags_distance,
@@ -469,7 +582,12 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], NULL, argv[1], argv[2], argv[3], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_flags_distance2,
@@ -483,7 +601,12 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], NULL, NULL, argv[1], argv[2], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_mask_distance,
@@ -499,7 +622,12 @@
        "Null interface\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], NULL, argv[3], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_mask_flags_distance,
@@ -516,7 +644,12 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], argv[1], argv[2], argv[3], argv[4], NULL);
+#endif
+
 }
 
 DEFUN (no_ip_route_mask_flags_distance2,
@@ -531,8 +664,71 @@
        "Silently discard pkts when matched\n"
        "Distance value for this route\n")
 {
+#ifndef SUPPORT_REALMS
   return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3]);
+#else
+  return zebra_static_ipv4 (vty, 0, argv[0], argv[1], NULL, argv[2], argv[3], 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 (vty, 1, argv[0], NULL, argv[1], 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 (vty, 1, argv[0], argv[1], argv[2], 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 (vty, 1, argv[0], NULL, argv[1], NULL, argv[2], 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 (vty, 1, argv[0], argv[1], argv[2], NULL, argv[3], argv[4]);
+}
+#endif /* SUPPORT_REALMS */
+ 
 
 /* New RIB.  Detailed information for IPv4 route. */
 void
@@ -552,6 +748,10 @@
 	vty_out (vty, ", best");
       if (rib->refcnt)
 	vty_out (vty, ", refcnt %ld", rib->refcnt);
+#ifdef SUPPORT_REALMS
+      if (rib->realmto)
+       vty_out (vty, ", realm %5u", rib->realmto);
+#endif
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
        vty_out (vty, ", blackhole");
       if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_REJECT))
@@ -615,7 +815,12 @@
 	    }
 	  if (! CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
 	    vty_out (vty, " inactive");
-
+#ifdef SUPPORT_REALMS
+    	  if (rib->realmto) {
+    	    char realmbuf[50];
+    	    vty_out (vty, " realm %5s", rtnl_rtrealm_n2a (rib->realmto, realmbuf, sizeof (realmbuf)));
+    	  }
+#endif
 	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
 	    {
 	      vty_out (vty, " (recursive");
@@ -1106,6 +1311,13 @@
         if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
           vty_out (vty, " %d", si->distance);
 
+#ifdef SUPPORT_REALMS
+       if (si->realmto) {
+         char realmbuf[11];
+         vty_out (vty, " realm %s", rtnl_rtrealm_n2a (si->realmto, realmbuf, sizeof realmbuf));
+       }
+#endif
+
         vty_out (vty, "%s", VTY_NEWLINE);
 
         write = 1;
@@ -1955,6 +2167,12 @@
   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 -Nru quagga-0.98.6.orig/zebra/zserv.c quagga-0.98.6/zebra/zserv.c
--- quagga-0.98.6.orig/zebra/zserv.c	2005-09-23 13:41:21.000000000 +0300
+++ quagga-0.98.6/zebra/zserv.c	2006-05-10 10:02:56.000000000 +0300
@@ -877,6 +877,13 @@
   if (CHECK_FLAG (message, ZAPI_MESSAGE_METRIC))
     rib->metric = stream_getl (s);
     
+#ifdef SUPPORT_REALMS
+  if (CHECK_FLAG (message, ZAPI_MESSAGE_REALMTO))
+    rib->realmto = stream_getw (s);
+  else
+    rib->realmto = 0;
+#endif
+
   rib_add_ipv4_multipath (&p, rib);
 }
 

