From b32a87b23bde95e7ac8592cc56873e4b6b60036b Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Sun, 29 Apr 2018 13:23:46 -0400 Subject: [PATCH] Consistently use peer label to ID peers when enforcing split horizon We were incorrectly comparing the peer label (which is "hostname:port") with the GSS name of our route's source (i.e., "credential@apc.x") when checking whether we were about to advertise a route back to the trust router that announced it to us. That broke split horizon enforcement. --- trp/trps.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/trp/trps.c b/trp/trps.c index 83461d9..d6c86bc 100644 --- a/trp/trps.c +++ b/trp/trps.c @@ -1324,26 +1324,62 @@ cleanup: } /* select the correct route to comm/realm to be announced to peer */ -static TRP_ROUTE *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer_gssname) +static TRP_ROUTE *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer_label) { - TRP_ROUTE *route; + TRP_ROUTE *route = NULL; + TRP_PEER *route_peer = NULL; + TR_NAME *route_peer_label = NULL; /* Take the currently selected route unless it is through the peer we're sending the update to. - * I.e., enforce the split horizon rule. */ + * I.e., enforce the split horizon rule. Start by looking up the currently selected route. */ route=trp_rtable_get_selected_entry(trps->rtable, comm, realm); if (route==NULL) { /* No selected route, this should only happen if the only route has been retracted, * in which case we do not want to advertise it. */ return NULL; } - tr_debug("trps_select_realm_update: %s vs %s", peer_gssname->buf, - trp_route_get_peer(route)->buf); - if (0==tr_name_cmp(peer_gssname, trp_route_get_peer(route))) { - tr_debug("trps_select_realm_update: matched, finding alternate route"); - /* the selected entry goes through the peer we're reporting to, choose an alternate */ - route=trps_find_best_route(trps, comm, realm, peer_gssname); - if ((route==NULL) || (!trp_metric_is_finite(trp_route_get_metric(route)))) - return NULL; /* don't advertise a nonexistent or retracted route */ + + /* Check whether it's local. */ + if (trp_route_is_local(route)) { + /* It is always ok to announce a local route */ + tr_debug("trps_select_realm_update: selected route for %.*s/%.*s is local", + realm->len, realm->buf, + comm->len, comm->buf); + } else { + /* It's not local. Get the route's peer and check whether it's the same place we + * got the selected route from. Peer should always correspond to an entry in our + * peer table. */ + tr_debug("trps_select_realm_update: selected route for %.*s/%.*s is not local", + realm->len, realm->buf, + comm->len, comm->buf); + route_peer = trp_ptable_find_gss_name(trps->ptable, trp_route_get_peer(route)); + if (route_peer == NULL) { + tr_err("trps_select_realm_update: unknown peer GSS name (%.*s) for selected route for %.*s/%.*s", + trp_route_get_peer(route)->len, trp_route_get_peer(route)->buf, + realm->len, realm->buf, + comm->len, comm->buf); + return NULL; + } + route_peer_label = trp_peer_get_label(route_peer); + if (route_peer_label == NULL) { + tr_err("trps_select_realm_update: error retrieving peer label for selected route for %.*s/%.*s", + realm->len, realm->buf, + comm->len, comm->buf); + return NULL; + } + + /* see if these match */ + tr_debug("trps_select_realm_update: %.*s vs %.*s", + peer_label->len, peer_label->buf, + route_peer_label->len, route_peer_label->buf); + + if (0==tr_name_cmp(peer_label, route_peer_label)) { + /* the selected entry goes through the peer we're reporting to, choose an alternate */ + tr_debug("trps_select_realm_update: matched, finding alternate route"); + route=trps_find_best_route(trps, comm, realm, peer_label); + if ((route==NULL) || (!trp_metric_is_finite(trp_route_get_metric(route)))) + return NULL; /* don't advertise a nonexistent or retracted route */ + } } return route; } @@ -1352,7 +1388,7 @@ static TRP_ROUTE *trps_select_realm_update(TRPS_INSTANCE *trps, TR_NAME *comm, T static TRP_RC trps_select_route_updates_for_peer(TALLOC_CTX *mem_ctx, GPtrArray *updates, TRPS_INSTANCE *trps, - TR_NAME *peer_gssname, + TR_NAME *peer_label, int triggered) { size_t n_comm=0; @@ -1369,7 +1405,7 @@ static TRP_RC trps_select_route_updates_for_peer(TALLOC_CTX *mem_ctx, for (ii=0; iirtable, comm[ii], &n_realm); for (jj=0; jj