diff options
author | Calin Velea <vcalinus@gemenii.ro> | 2007-04-09 15:29:51 -0500 |
---|---|---|
committer | Jeffrey C. Ollie <jeff@ocjtech.us> | 2007-04-09 15:29:51 -0500 |
commit | 8d3e3ccfd0d0cb82b253f937339d1c6189a2bf54 (patch) | |
tree | b8bc9ff4aad0c8e7933e91895f6f3cf7d93f8e24 | |
parent | c15deb1b7428a2baedfb615b1a41fe28d48c598c (diff) | |
download | quagga-8d3e3ccfd0d0cb82b253f937339d1c6189a2bf54.tar.bz2 quagga-8d3e3ccfd0d0cb82b253f937339d1c6189a2bf54.tar.xz |
Appying patch from http://vcalinus.gemenii.ro/quagga-0.99.5-realms.diffquagga-0.99.5-realms.diff
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | bgpd/ChangeLog | 13 | ||||
-rw-r--r-- | bgpd/bgp_attr.c | 10 | ||||
-rw-r--r-- | bgpd/bgp_attr.h | 6 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 110 | ||||
-rw-r--r-- | bgpd/bgp_routemap.c | 170 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 141 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 9 | ||||
-rw-r--r-- | bgpd/bgpd.c | 99 | ||||
-rw-r--r-- | bgpd/bgpd.h | 10 | ||||
-rwxr-xr-x | configure.ac | 13 | ||||
-rw-r--r-- | lib/ChangeLog | 8 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/rt_names.c | 412 | ||||
-rw-r--r-- | lib/rt_names.h | 28 | ||||
-rw-r--r-- | lib/zclient.c | 5 | ||||
-rw-r--r-- | lib/zclient.h | 7 | ||||
-rw-r--r-- | lib/zebra.h | 4 | ||||
-rw-r--r-- | zebra/ChangeLog | 10 | ||||
-rw-r--r-- | zebra/connected.c | 5 | ||||
-rw-r--r-- | zebra/rib.h | 20 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 58 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 21 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 222 | ||||
-rw-r--r-- | zebra/zserv.c | 6 |
25 files changed, 1391 insertions, 9 deletions
@@ -108,6 +108,15 @@ * Makefile.am (EXTRA_DIST): add INSTALL.quagga.txt, because people that patch releases need to know about autoconf required versions. +2005-07-30 Calin Velea <vcalinus@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-30 Louis Lagendijk <louis.lagendijk@gmail.com> * configure.ac: Actually test whether libc has IPv6 support. diff --git a/bgpd/ChangeLog b/bgpd/ChangeLog index b27132c9..13d6777a 100644 --- a/bgpd/ChangeLog +++ b/bgpd/ChangeLog @@ -570,6 +570,19 @@ (peer_create) use XSTRDUP * bgp_packet.c: (bgp_stream_dup) deleted, stream_dup should be used (various) update -> s/bgp_stream_dup/stream_dup + +2005-04-24 Calin Velea <vcalinus@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-04-11 Andrew J. Schorr <ajschorr@alumni.princeton.edu> diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 4c72d80a..72d66b52 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -299,6 +299,11 @@ attrhash_key_make (struct attr *attr) 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); @@ -337,6 +342,11 @@ attrhash_cmp (struct attr *attr1, struct attr *attr2) && 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 --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 777869ce..6f6a1262 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -87,6 +87,12 @@ struct attr as_t aggregator_as; u_char origin; u_char mp_nexthop_len; + +#ifdef SUPPORT_REALMS + /* Realm used */ + u_int16_t realmto; +#endif + }; /* Router Reflector related structure. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5623cadc..20276b49 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -493,6 +493,19 @@ bgp_cluster_filter (struct peer *peer, struct attr *attr) } 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) + +#endif static int bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, @@ -502,6 +515,44 @@ bgp_input_modifier (struct peer *peer, struct prefix *p, struct attr *attr, struct bgp_info info; route_map_result_t ret; +#ifdef SUPPORT_REALMS + + u_int16_t realm_value = 0; + struct aspath *aspath; + + struct assegment *assegment; + + + /* Apply default realm value. */ + aspath = attr->aspath; + + if (peer->realm == REALM_PEER_AS) + { + realm_value = peer->as; + + } + else if (peer->realm == REALM_ORIGIN_AS) + { + if (aspath == NULL || aspath->segments == NULL) + return RMAP_PERMIT; + + assegment = aspath->segments; + + while (assegment) { + int i; + + for (i = 0; i < assegment->length; i++) + realm_value = assegment->as[i]; + + assegment = assegment->next; + } + } + else realm_value = (u_int16_t)(peer->realm & 0xFFFF); + + attr->realmto = realm_value; + +#endif + filter = &peer->filter[afi][safi]; /* Apply default weight value. */ @@ -573,6 +624,46 @@ bgp_import_modifier (struct peer *rsclient, struct peer *peer, struct bgp_info info; route_map_result_t ret; +#ifdef SUPPORT_REALMS + + u_int16_t realm_value = 0; + struct aspath *aspath; + + struct assegment *assegment; + + + /* Apply default realm value. */ + aspath = attr->aspath; + + if (peer->realm == REALM_PEER_AS) + { + realm_value = peer->as; + + } + else if (peer->realm == REALM_ORIGIN_AS) + { + if (aspath == NULL || aspath->segments == NULL) + return RMAP_PERMIT; + + assegment = aspath->segments; + + while (assegment) { + int i; + + for (i = 0; i < assegment->length; i++) + realm_value = assegment->as[i]; + + assegment = assegment->next; + } + } + else realm_value = (u_int16_t)(peer->realm & 0xFFFF); + + attr->realmto = realm_value; + +#endif + + + filter = &rsclient->filter[afi][safi]; /* Apply default weight value. */ @@ -5153,6 +5244,10 @@ route_vty_out (struct vty *vty, struct prefix *p, 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, "%s ", attr->aspath); @@ -5214,6 +5309,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, vty_out (vty, "%7d ",attr->weight); +#ifdef SUPPORT_REALMS + vty_out (vty, "%7u ", attr->realmto); +#endif + /* Print aspath */ if (attr->aspath) aspath_print_vty (vty, "%s ", attr->aspath); @@ -5501,6 +5600,13 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, 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 */ @@ -5541,7 +5647,11 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, #define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,%s 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 806a5072..e660568c 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1119,6 +1119,112 @@ struct route_map_rule_cmd route_set_metric_cmd = 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) + +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; + struct aspath *aspath; + + 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->segments == NULL) + return RMAP_OKAY; + + realm_value = bgp_info->peer->as; + + } + else if (*realm == REALM_ORIGIN_AS) + { + if (aspath == NULL || aspath->segments == NULL) + return RMAP_PERMIT; + + assegment = aspath->segments; + + while (assegment) { + int i; + + for (i = 0; i < assegment->length; i++) + realm_value = assegment->as[i]; + + assegment = assegment->next; + } + } + 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 + */ +static 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; +} + +static void +route_set_realm_free (void *rule) +{ + XFREE (MTYPE_ROUTE_MAP_COMPILED, rule); +} + +/* Set realms rule structure. */ +struct route_map_rule_cmd route_set_realm_cmd = +{ + "realm", + route_set_realm, + route_set_realm_compile, + route_set_realm_free, +}; +#endif + /* `set as-path prepend ASPATH' */ @@ -2827,6 +2933,59 @@ ALIAS (no_set_metric, "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>", @@ -3554,6 +3713,10 @@ 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_origin_cmd); route_map_install_set (&route_set_atomic_aggregate_cmd); @@ -3622,6 +3785,13 @@ bgp_route_map_init (void) 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 --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index ec4b6c22..93096dc0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2985,7 +2985,114 @@ ALIAS (no_neighbor_weight, 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.*/ +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 (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; +} + +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]); +} + +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, @@ -7431,6 +7538,27 @@ bgp_show_peer (struct vty *vty, struct peer *p) vty_out (vty, "%s", VTY_NEWLINE); +#ifdef SUPPORT_REALMS + + /* Default realm */ + if (CHECK_FLAG (p->config, PEER_CONFIG_REALM)) + { + char realmbuf[64]; + 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++) @@ -9242,6 +9370,17 @@ 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, &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 --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 0cb9e0e2..a25297ab 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -640,6 +640,15 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp) 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 --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 8ed598d2..6256c54a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -631,6 +631,10 @@ peer_global_config_reset (struct peer *peer) peer->keepalive = 0; peer->connect = 0; peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; + +#ifdef SUPPORT_REALMS + peer->realm = 0; +#endif } /* Check peer's AS number and determin is this peer IBGP or EBGP */ @@ -774,6 +778,10 @@ peer_new () peer->ostatus = Idle; 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++) @@ -1370,6 +1378,13 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer, /* Weight */ peer->weight = conf->weight; +#ifdef CONFIG_REALMS + + /* Realm */ + peer->realm = conf->realm; + +#endif + /* peer flags apply */ peer->flags = conf->flags; /* peer af_flags apply */ @@ -3016,7 +3031,60 @@ peer_weight_unset (struct peer *peer) } return 0; } - + +#ifdef SUPPORT_REALMS + +/* neighbor realm. */ +int +peer_realm_set (struct peer *peer, u_int32_t realm) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + SET_FLAG (peer->config, PEER_CONFIG_REALM); + peer->realm = realm; + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + peer->realm = group->conf->realm; + } + return 0; +} + +int +peer_realm_unset (struct peer *peer) +{ + struct peer_group *group; + struct listnode *node, *nnode; + + /* Set default realm. */ + if (peer_group_active (peer)) + peer->realm = peer->group->conf->realm; + else + peer->realm = 0; + + UNSET_FLAG (peer->config, PEER_CONFIG_REALM); + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + /* peer-group member updates. */ + group = peer->group; + for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) + { + peer->realm = 0; + } + return 0; +} + + +#endif + int peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime) { @@ -4451,6 +4519,35 @@ 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 + +#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 + + + + + + + + /* 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 9e2aa3e0..dc451e78 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -410,6 +410,11 @@ struct peer 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; @@ -889,6 +894,11 @@ extern int peer_weight_unset (struct peer *); extern int peer_timers_set (struct peer *, u_int32_t, u_int32_t); extern int peer_timers_unset (struct peer *); +#ifdef SUPPORT_REALMS +extern int peer_realm_set (struct peer *, u_int32_t); +extern int peer_realm_unset (struct peer *); +#endif + extern int peer_timers_connect_set (struct peer *, u_int32_t); extern int peer_timers_connect_unset (struct peer *); diff --git a/configure.ac b/configure.ac index 4f5956e0..7c0b5df7 100755 --- a/configure.ac +++ b/configure.ac @@ -8,7 +8,7 @@ ## $Id$ AC_PREREQ(2.53) -AC_INIT(Quagga, 0.99.5, [http://bugzilla.quagga.net]) +AC_INIT(Quagga, 0.99.5-realms, [http://bugzilla.quagga.net]) AC_CONFIG_SRCDIR(lib/zebra.h) dnl ----------------------------------- @@ -224,7 +224,8 @@ AC_ARG_ENABLE(configfile_mask, [ --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, @@ -432,6 +433,14 @@ case "$host" in ;; 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 --git a/lib/ChangeLog b/lib/ChangeLog index 01f45ba5..e2c25ca6 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -483,6 +483,14 @@ * memtypes.c: Add MTYPE_BGP_PROCESS_QUEUE and MTYPE_BGP_CLEAR_NODE_QUEUE +2005-04-24 Calin Velea <vcalinus@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-05-24 Paul Jakma <paul@dishone.st> * memtypes.h: update this auto-built file. (maybe we should just diff --git a/lib/Makefile.am b/lib/Makefile.am index 315e919b..2bd25235 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -12,7 +12,7 @@ libzebra_la_SOURCES = \ 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 memtypes.c workqueue.c + sigevent.c pqueue.c jhash.c memtypes.c workqueue.c rt_names.c BUILT_SOURCES = memtypes.h route_types.h @@ -27,7 +27,7 @@ pkginclude_HEADERS = \ 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.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ - workqueue.h route_types.h + workqueue.h route_types.h rt_names.h EXTRA_DIST = regex.c regex-gnu.h memtypes.awk route_types.awk route_types.txt diff --git a/lib/rt_names.c b/lib/rt_names.c new file mode 100644 index 00000000..6ed2d7ab --- /dev/null +++ b/lib/rt_names.c @@ -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 --git a/lib/rt_names.h b/lib/rt_names.h new file mode 100644 index 00000000..6ac29204 --- /dev/null +++ b/lib/rt_names.h @@ -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 --git a/lib/zclient.c b/lib/zclient.c index a253af61..b6858fab 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -475,6 +475,11 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p, if (CHECK_FLAG (api->message, ZAPI_MESSAGE_METRIC)) stream_putl (s, api->metric); +#ifdef SUPPORT_REALMS + if (CHECK_FLAG (api->message, ZAPI_MESSAGE_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 --git a/lib/zclient.h b/lib/zclient.h index 69ada144..749f1182 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -87,6 +87,10 @@ struct zclient #define ZAPI_MESSAGE_DISTANCE 0x04 #define ZAPI_MESSAGE_METRIC 0x08 +#ifdef SUPPORT_REALMS + #define ZAPI_MESSAGE_REALMTO 0x10 +#endif + /* Zserv protocol message header */ struct zserv_header { @@ -117,6 +121,9 @@ struct zapi_ipv4 u_char distance; u_int32_t metric; +#ifdef SUPPORT_REALMS + u_int16_t realmto; +#endif }; /* Prototypes of zebra client service functions. */ diff --git a/lib/zebra.h b/lib/zebra.h index 2e2f8cda..2b7ff442 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -232,6 +232,10 @@ typedef int socklen_t; #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 --git a/zebra/ChangeLog b/zebra/ChangeLog index 62287d0b..9a26750f 100644 --- a/zebra/ChangeLog +++ b/zebra/ChangeLog @@ -558,7 +558,17 @@ (remainder) Sanitise refcounting of route_node's. Convert to rib_queue_add, rib_addnode and rib_delnode. Change XMALLOC/memset to XCALLOC. Remove calls to nexthop_delete and nexthop_free. + +2005-04-24 Calin Velea <vcalinus@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-10 Paul Jakma <paul@dishone.st> * if_ioctl_solaris.c: (if_lookup_linklocal) fix order of args diff --git a/zebra/connected.c b/zebra/connected.c index 44002e76..2b31aa3a 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -200,8 +200,13 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) if (prefix_ipv4_any (&p)) return; +#ifndef SUPPORT_REALMS rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0); +#else + rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN, + ifp->metric, 0, 0); +#endif rib_update (); } diff --git a/zebra/rib.h b/zebra/rib.h index 04fbbecf..dd1bfbbc 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -73,6 +73,12 @@ struct rib u_char nexthop_num; u_char nexthop_active_num; u_char nexthop_fib_num; + +#ifdef SUPPORT_REALMS + /* Realm information */ + u_int16_t realmto; +#endif + }; /* Static route information. */ @@ -104,6 +110,11 @@ struct static_ipv4 see ZEBRA_FLAG_REJECT ZEBRA_FLAG_BLACKHOLE */ + +#ifdef SUPPORT_REALMS + u_int16_t realmto; +#endif + }; #ifdef HAVE_IPV6 @@ -226,7 +237,11 @@ extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t i * also implicitly withdraw equal prefix of same type. */ extern int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct in_addr *gate, unsigned int ifindex, +#ifndef SUPPORT_REALMS u_int32_t vrf_id, u_int32_t, u_char); +#else + u_int32_t vrf_id, u_int32_t, u_char, u_int16_t); +#endif extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *); @@ -246,7 +261,12 @@ extern void rib_init (void); extern 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 + extern int static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 216625e9..5e19ec6a 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -738,6 +738,12 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) 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) @@ -799,7 +805,19 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) 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) @@ -931,8 +949,20 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) 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); } @@ -1330,7 +1360,13 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) /* 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; @@ -1390,6 +1426,17 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, 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; @@ -1467,6 +1514,11 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, 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) { @@ -1813,7 +1865,11 @@ kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, unsigned 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 --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index acad065a..8d4e732c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1232,7 +1232,12 @@ rib_delnode (struct route_node *rn, struct rib *rib) 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; @@ -1315,6 +1320,10 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, /* Link new rib to node.*/ rib_addnode (rn, rib); +#ifdef SUPPORT_REALMS + rib->realmto = realmto; +#endif + /* Free implicit route.*/ if (same) rib_delnode (rn, same); @@ -1558,6 +1567,10 @@ static_install_ipv4 (struct prefix *p, struct static_ipv4 *si) rib->distance = si->distance; rib->metric = 0; rib->nexthop_num = 0; +#ifdef SUPPORT_REALMS + rib->realmto = si->realmto; +#endif + switch (si->type) { @@ -1661,7 +1674,11 @@ static_uninstall_ipv4 (struct prefix *p, struct static_ipv4 *si) /* 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; @@ -1716,6 +1733,10 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, si->distance = distance; si->flags = flags; +#ifdef SUPPORT_REALMS + si->realmto = realmto; +#endif + if (gate) si->gate.ipv4 = *gate; if (ifname) diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 68e6f920..33906e3d 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -33,7 +33,12 @@ static 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; @@ -43,6 +48,23 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, 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) { @@ -80,7 +102,11 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, 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; @@ -106,7 +132,11 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, 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); @@ -121,8 +151,14 @@ zebra_static_ipv4 (struct vty *vty, int add_cmd, const char *dest_str, 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); @@ -140,7 +176,11 @@ DEFUN (ip_route, "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, @@ -154,7 +194,11 @@ DEFUN (ip_route_flags, "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, @@ -166,7 +210,11 @@ DEFUN (ip_route_flags2, "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. */ @@ -181,7 +229,11 @@ DEFUN (ip_route_mask, "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, @@ -196,7 +248,11 @@ DEFUN (ip_route_mask_flags, "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, @@ -209,7 +265,11 @@ DEFUN (ip_route_mask_flags2, "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. */ @@ -224,7 +284,11 @@ DEFUN (ip_route_distance, "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, @@ -239,7 +303,12 @@ DEFUN (ip_route_flags_distance, "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, @@ -252,7 +321,11 @@ DEFUN (ip_route_flags_distance2, "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, @@ -267,7 +340,12 @@ DEFUN (ip_route_mask_distance, "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, @@ -283,7 +361,12 @@ DEFUN (ip_route_mask_flags_distance, "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, @@ -297,7 +380,12 @@ DEFUN (ip_route_mask_flags_distance2, "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, @@ -311,7 +399,12 @@ DEFUN (no_ip_route, "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, @@ -336,7 +429,12 @@ DEFUN (no_ip_route_flags2, "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, @@ -351,7 +449,12 @@ DEFUN (no_ip_route_mask, "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, @@ -378,7 +481,12 @@ DEFUN (no_ip_route_mask_flags2, "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, @@ -393,7 +501,12 @@ DEFUN (no_ip_route_distance, "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, @@ -409,7 +522,12 @@ DEFUN (no_ip_route_flags_distance, "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, @@ -423,7 +541,12 @@ DEFUN (no_ip_route_flags_distance2, "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, @@ -439,7 +562,12 @@ DEFUN (no_ip_route_mask_distance, "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, @@ -456,7 +584,12 @@ DEFUN (no_ip_route_mask_flags_distance, "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, @@ -471,9 +604,72 @@ DEFUN (no_ip_route_mask_flags_distance2, "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. */ static void vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) @@ -492,6 +688,10 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) 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)) @@ -555,7 +755,12 @@ vty_show_ip_route_detail (struct vty *vty, struct route_node *rn) } 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"); @@ -1046,6 +1251,13 @@ static_config_ipv4 (struct vty *vty) 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; @@ -1895,6 +2107,12 @@ zebra_vty_init (void) install_element (CONFIG_NODE, &no_ip_route_mask_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags_cmd); install_element (CONFIG_NODE, &no_ip_route_mask_flags2_cmd); +#ifdef SUPPORT_REALMS + install_element (CONFIG_NODE, &ip_route_realm_cmd); + install_element (CONFIG_NODE, &ip_route_mask_realm_cmd); + install_element (CONFIG_NODE, &ip_route_pref_realm_cmd); + install_element (CONFIG_NODE, &ip_route_mask_pref_realm_cmd); +#endif install_element (CONFIG_NODE, &ip_route_distance_cmd); install_element (CONFIG_NODE, &ip_route_flags_distance_cmd); install_element (CONFIG_NODE, &ip_route_flags_distance2_cmd); diff --git a/zebra/zserv.c b/zebra/zserv.c index 1703d3f5..1713c536 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -803,6 +803,12 @@ zread_ipv4_add (struct zserv *client, u_short length) /* Table */ rib->table=zebrad.rtm_table_default; +#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); return 0; } |