From 53ab8fd0668d83134baf386020069e81085d13a2 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Fri, 1 Jul 2016 15:24:32 -0400 Subject: [PATCH] Update the routing table when TRP updates are received. --- include/trp_internal.h | 17 +++-- include/trust_router/trp.h | 4 +- tr/tr_main.c | 6 ++ tr/tr_trp.c | 18 ++++- trp/test/rtbl_test.c | 1 + trp/trp_conn.c | 72 ++++++++++++++++-- trp/trp_rtable.c | 16 ++-- trp/trp_upd.c | 8 +- trp/trpc.c | 4 +- trp/trps.c | 181 ++++++++++++++++++++++++++++++--------------- 10 files changed, 237 insertions(+), 90 deletions(-) diff --git a/include/trp_internal.h b/include/trp_internal.h index faa8582..5289980 100644 --- a/include/trp_internal.h +++ b/include/trp_internal.h @@ -8,6 +8,7 @@ #include #include #include +#include #include /* info records */ @@ -59,8 +60,8 @@ struct trp_connection { TRP_CONNECTION *next; pthread_t *thread; /* thread servicing this connection */ int fd; - TR_NAME *peer; /* who is this a connection to? */ TR_NAME *gssname; + TR_NAME *peer; gss_ctx_id_t *gssctx; TRP_CONNECTION_STATUS status; }; @@ -74,7 +75,7 @@ typedef client_cb_fn TRP_AUTH_FUNC; typedef struct trpc_instance TRPC_INSTANCE; struct trpc_instance { TRPC_INSTANCE *next; - const char *server; + char *server; unsigned int port; TRP_CONNECTION *conn; TR_MQ *mq; /* msgs from master to trpc */ @@ -102,6 +103,7 @@ int trp_connection_lock(TRP_CONNECTION *conn); int trp_connection_unlock(TRP_CONNECTION *conn); int trp_connection_get_fd(TRP_CONNECTION *conn); void trp_connection_set_fd(TRP_CONNECTION *conn, int fd); +TR_NAME *trp_connection_get_peer(TRP_CONNECTION *conn); TR_NAME *trp_connection_get_gssname(TRP_CONNECTION *conn); void trp_connection_set_gssname(TRP_CONNECTION *conn, TR_NAME *gssname); gss_ctx_id_t *trp_connection_get_gssctx(TRP_CONNECTION *conn); @@ -114,7 +116,7 @@ TRP_CONNECTION *trp_connection_remove(TRP_CONNECTION *conn, TRP_CONNECTION *remo void trp_connection_append(TRP_CONNECTION *conn, TRP_CONNECTION *new); int trp_connection_auth(TRP_CONNECTION *conn, TRP_AUTH_FUNC auth_callback, void *callback_data); TRP_CONNECTION *trp_connection_accept(TALLOC_CTX *mem_ctx, int listen, TR_NAME *gssname); -TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, const char *server, unsigned int port); +TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, char *server, unsigned int port); TRPC_INSTANCE *trpc_new (TALLOC_CTX *mem_ctx); void trpc_free (TRPC_INSTANCE *trpc); @@ -124,8 +126,8 @@ TRPC_INSTANCE *trpc_get_next(TRPC_INSTANCE *trpc); void trpc_set_next(TRPC_INSTANCE *trpc, TRPC_INSTANCE *next); TRPC_INSTANCE *trpc_remove(TRPC_INSTANCE *trpc, TRPC_INSTANCE *remove); void trpc_append(TRPC_INSTANCE *trpc, TRPC_INSTANCE *new); -const char *trpc_get_server(TRPC_INSTANCE *trpc); -void trpc_set_server(TRPC_INSTANCE *trpc, const char *server); +char *trpc_get_server(TRPC_INSTANCE *trpc); +void trpc_set_server(TRPC_INSTANCE *trpc, char *server); unsigned int trpc_get_port(TRPC_INSTANCE *trpc); void trpc_set_port(TRPC_INSTANCE *trpc, unsigned int port); DH *trpc_get_dh(TRPC_INSTANCE *trpc); @@ -153,9 +155,12 @@ int trps_get_listener(TRPS_INSTANCE *trps, const char *hostname, unsigned int port, void *cookie); -int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName, void *data); TR_MQ_MSG *trps_mq_pop(TRPS_INSTANCE *trps); void trps_mq_append(TRPS_INSTANCE *trps, TR_MQ_MSG *msg); void trps_handle_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *conn); TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg); +TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer); +TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm); +TR_NAME *trps_get_next_hop(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm); + #endif /* TRP_INTERNAL_H */ diff --git a/include/trust_router/trp.h b/include/trust_router/trp.h index 5cda8ad..7867414 100644 --- a/include/trust_router/trp.h +++ b/include/trust_router/trp.h @@ -35,7 +35,7 @@ void trp_upd_free(TRP_UPD *update); TR_EXPORT TRP_INFOREC *trp_upd_get_inforec(TRP_UPD *upd); void trp_upd_set_inforec(TRP_UPD *upd, TRP_INFOREC *rec); TR_EXPORT TR_NAME *trp_upd_get_peer(TRP_UPD *upd); -TRP_RC trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer); +void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer); TR_EXPORT TRP_INFOREC *trp_inforec_new(TALLOC_CTX *mem_ctx, TRP_INFOREC_TYPE type); void trp_inforec_free(TRP_INFOREC *rec); TR_EXPORT TRP_INFOREC *trp_inforec_get_next(TRP_INFOREC *rec); @@ -65,6 +65,6 @@ void trp_req_set_comm(TRP_REQ *req, TR_NAME *comm); TR_EXPORT TR_NAME *trp_req_get_realm(TRP_REQ *req); void trp_req_set_realm(TRP_REQ *req, TR_NAME *realm); TR_EXPORT TR_NAME *trp_req_get_peer(TRP_REQ *req); -TRP_RC trp_req_set_peer(TRP_REQ *req, TR_NAME *peer); +void trp_req_set_peer(TRP_REQ *req, TR_NAME *peer); #endif /* TRP_H */ diff --git a/tr/tr_main.c b/tr/tr_main.c index f6c67d0..91a494d 100644 --- a/tr/tr_main.c +++ b/tr/tr_main.c @@ -124,6 +124,7 @@ static void tr_talloc_log(const char *msg) #endif /* TALLOC_DEBUG_ENABLE */ +#if DEBUG_PING_SELF struct thingy { TRPS_INSTANCE *trps; struct event *ev; @@ -163,6 +164,7 @@ static void debug_ping(evutil_socket_t fd, short what, void *arg) if (count-- > 0) evtimer_add(thingy->ev, &interval); } +#endif /* DEBUG_PING_SELF */ int main(int argc, char *argv[]) { @@ -174,9 +176,11 @@ int main(int argc, char *argv[]) struct tr_socket_event tids_ev; TR_TRPS_EVENTS *trps_ev; struct event *cfgwatch_ev; +#if DEBUG_PING_SELF struct event *debug_ping_ev; struct timeval notime={0, 0}; struct thingy thingy={NULL}; +#endif /* DEBUG_PING_SELF */ /* we're going to be multithreaded, so disable null context tracking */ talloc_set_abort_fn(tr_abort); @@ -269,11 +273,13 @@ int main(int argc, char *argv[]) return 1; } +#if DEBUG_PING_SELF /* for debugging, send a message to peers on a timer */ debug_ping_ev=evtimer_new(ev_base, debug_ping, (void *)&thingy); thingy.trps=tr->trps; thingy.ev=debug_ping_ev; evtimer_add(debug_ping_ev, ¬ime); +#endif /* DEBUG_PING_SELF */ tr_event_loop_run(ev_base); /* does not return until we are done */ diff --git a/tr/tr_trp.c b/tr/tr_trp.c index f085f7d..ac9f905 100644 --- a/tr/tr_trp.c +++ b/tr/tr_trp.c @@ -155,12 +155,22 @@ static void tr_trps_cleanup_thread(TRPS_INSTANCE *trps, TRP_CONNECTION *conn) tr_debug("Deleted connection"); } +static void tr_trps_print_route_table(TRPS_INSTANCE *trps, FILE *f) +{ + char *table=trp_rtable_to_str(NULL, trps->rtable, " | ", NULL); + if (table==NULL) + fprintf(f, "Unable to print route table.\n"); + else { + fprintf(f, "%s\n", table); + talloc_free(table); + } +} + static void tr_trps_process_mq(int socket, short event, void *arg) { TRPS_INSTANCE *trps=talloc_get_type_abort(arg, TRPS_INSTANCE); TR_MQ_MSG *msg=NULL; const char *s=NULL; - char *tmp=NULL; msg=trps_mq_pop(trps); while (msg!=NULL) { @@ -171,7 +181,11 @@ static void tr_trps_process_mq(int socket, short event, void *arg) TRP_CONNECTION)); } else if (0==strcmp(s, "tr_msg")) { - trps_handle_tr_msg(trps, msg); + if (trps_handle_tr_msg(trps, tr_mq_msg_get_payload(msg))!=TRP_SUCCESS) + tr_notice("tr_trps_process_mq: error handling message."); + else { + tr_trps_print_route_table(trps, stderr); + } } else tr_notice("tr_trps_process_mq: unknown message '%s' received.", tr_mq_msg_get_message(msg)); diff --git a/trp/test/rtbl_test.c b/trp/test/rtbl_test.c index d2e3826..7f5d575 100644 --- a/trp/test/rtbl_test.c +++ b/trp/test/rtbl_test.c @@ -4,6 +4,7 @@ #include #include +#include #include char *apc[]={"apc1", "apc2", "apc3"}; diff --git a/trp/trp_conn.c b/trp/trp_conn.c index 9c3d813..53b0a0d 100644 --- a/trp/trp_conn.c +++ b/trp/trp_conn.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -30,14 +31,68 @@ void trp_connection_set_fd(TRP_CONNECTION *conn, int fd) conn->fd=fd; } -TR_NAME *trp_connection_get_peer(TRP_CONNECTION *conn) +/* we use the gss name of the peer to identify it */ +static TRP_RC trp_connection_set_peer(TRP_CONNECTION *conn) { - return conn->peer; + OM_uint32 major_status=0; + OM_uint32 minor_status=0; + gss_name_t source_name=GSS_C_NO_NAME; + gss_name_t target_name=GSS_C_NO_NAME; + gss_buffer_desc peer_display_name={0,NULL}; + int local=0; + + tr_debug("gssctx = %p", trp_connection_get_gssctx(conn)); + tr_debug("*gssctx = %p", *trp_connection_get_gssctx(conn)); + major_status=gss_inquire_context(&minor_status, + *trp_connection_get_gssctx(conn), + &source_name, + &target_name, + NULL, + NULL, + NULL, + &local, + NULL); + + if (major_status != GSS_S_COMPLETE) { + tr_err("trp_connection_set_peer: unable to identify GSS peer."); + if (source_name!=GSS_C_NO_NAME) + gss_release_name(&minor_status, &source_name); + if (target_name!=GSS_C_NO_NAME) + gss_release_name(&minor_status, &target_name); + return TRP_ERROR; + } + + if (local) { + /* we are the source, peer is the target */ + major_status=gss_display_name(&minor_status, target_name, &peer_display_name, NULL); + } else { + /* we are the target, peer is the source */ + major_status=gss_display_name(&minor_status, source_name, &peer_display_name, NULL); + } + gss_release_name(&minor_status, &source_name); + gss_release_name(&minor_status, &target_name); + + conn->peer=tr_new_name(peer_display_name.value); + if (conn->peer==NULL) + tr_err("trp_connection_set_peer: unable to allocate peer name."); + else { + if (conn->peer->len != peer_display_name.length) { + tr_err("trp_connection_set_peer: error converting GSS display name to TR_NAME."); + tr_free_name(conn->peer); + conn->peer=NULL; + } + } + gss_release_buffer(&minor_status, &peer_display_name); + + if (conn->peer==NULL) + return TRP_ERROR; + + return TRP_SUCCESS; } -void trp_connection_set_peer(TRP_CONNECTION *conn, TR_NAME *peer) +TR_NAME *trp_connection_get_peer(TRP_CONNECTION *conn) { - conn->peer=peer; + return conn->peer; } TR_NAME *trp_connection_get_gssname(TRP_CONNECTION *conn) @@ -166,7 +221,6 @@ TRP_CONNECTION *trp_connection_new(TALLOC_CTX *mem_ctx) if (new_conn != NULL) { trp_connection_set_next(new_conn, NULL); trp_connection_set_fd(new_conn, -1); - trp_connection_set_peer(new_conn, NULL); trp_connection_set_gssname(new_conn, NULL); trp_connection_mutex_init(new_conn); trp_connection_set_status(new_conn, TRP_CONNECTION_DOWN); @@ -226,6 +280,9 @@ int trp_connection_auth(TRP_CONNECTION *conn, TRP_AUTH_FUNC auth_callback, void return -1; } + trp_connection_set_peer(conn); + trp_connection_set_status(conn, TRP_CONNECTION_UP); + if (auth) tr_debug("trp_connection_auth: Connection authenticated, fd = %d.", trp_connection_get_fd(conn)); else @@ -249,12 +306,11 @@ TRP_CONNECTION *trp_connection_accept(TALLOC_CTX *mem_ctx, int listen, TR_NAME * conn=trp_connection_new(mem_ctx); trp_connection_set_fd(conn, conn_fd); trp_connection_set_gssname(conn, gssname); - trp_connection_set_status(conn, TRP_CONNECTION_UP); return conn; } /* Initiate connection */ -TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, const char *server, unsigned int port) +TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, char *server, unsigned int port) { int err = 0; int fd=-1; @@ -285,7 +341,7 @@ TRP_RC trp_connection_initiate(TRP_CONNECTION *conn, const char *server, unsigne return TRP_ERROR; } else { trp_connection_set_fd(conn, fd); - trp_connection_set_peer(conn, tr_new_name(server)); + trp_connection_set_peer(conn); trp_connection_set_status(conn, TRP_CONNECTION_UP); return TRP_SUCCESS; } diff --git a/trp/trp_rtable.c b/trp/trp_rtable.c index 97bf923..6cc8e18 100644 --- a/trp/trp_rtable.c +++ b/trp/trp_rtable.c @@ -529,15 +529,17 @@ static char *timespec_to_str(struct timespec *ts) TRP_RENTRY *trp_rtable_get_selected_entry(TRP_RTABLE *rtbl, TR_NAME *apc, TR_NAME *realm) { - size_t n_entries=0; - TRP_RENTRY *entry=trp_rtable_get_realm_entries(rtbl, apc, realm, &n_entries); - if (n_entries==0) - return NULL; + size_t n=0; + TRP_RENTRY **entry=trp_rtable_get_realm_entries(rtbl, apc, realm, &n); + TRP_RENTRY *selected=NULL; - while((entry!=NULL) && (!trp_rentry_get_selected(entry))) - entry=trp_rentry_get_next(entry); + if (n==0) + return NULL; - return entry; + while(n-- && !trp_rentry_get_selected(entry[n])) { } + selected=entry[n]; + talloc_free(entry); + return selected; } /* Pretty print a route table entry to a newly allocated string. If sep is NULL, diff --git a/trp/trp_upd.c b/trp/trp_upd.c index 68ccacf..6865a44 100644 --- a/trp/trp_upd.c +++ b/trp/trp_upd.c @@ -78,7 +78,7 @@ static int trp_inforec_route_destructor(void *object) } if (body->next_hop != NULL) { tr_free_name(body->next_hop); - body->hop=NULL; + body->next_hop=NULL; tr_debug("trp_inforec_route_destructor: freed next_hop"); } @@ -353,7 +353,7 @@ TRP_UPD *trp_upd_new(TALLOC_CTX *mem_ctx) if (new_body!=NULL) { new_body->records=NULL; new_body->peer=NULL; - talloc_set_destructor(new_body, trp_upd_destructor); + talloc_set_destructor((void *)new_body, trp_upd_destructor); } return new_body; } @@ -390,8 +390,10 @@ void trp_upd_set_peer(TRP_UPD *upd, TR_NAME *peer) upd->peer=peer; for (rec=trp_upd_get_inforec(upd); rec!=NULL; rec=trp_inforec_get_next(rec)) { - if (trp_inforec_set_next_hop(rec, cpy=tr_dup_name(peer)) != TRP_SUCCESS) + if (trp_inforec_set_next_hop(rec, cpy=tr_dup_name(peer)) != TRP_SUCCESS) { + tr_err("trp_upd_set_peer: error setting peer."); tr_free_name(cpy); + } } } diff --git a/trp/trpc.c b/trp/trpc.c index 57b7378..4913455 100644 --- a/trp/trpc.c +++ b/trp/trpc.c @@ -85,12 +85,12 @@ void trpc_append(TRPC_INSTANCE *trpc, TRPC_INSTANCE *new) trpc_set_next(trpc_get_tail(trpc), new); } -const char *trpc_get_server(TRPC_INSTANCE *trpc) +char *trpc_get_server(TRPC_INSTANCE *trpc) { return trpc->server; } -void trpc_set_server(TRPC_INSTANCE *trpc, const char *server) +void trpc_set_server(TRPC_INSTANCE *trpc, char *server) { trpc->server=server; } diff --git a/trp/trps.c b/trp/trps.c index c96495d..824d8f9 100644 --- a/trp/trps.c +++ b/trp/trps.c @@ -5,11 +5,20 @@ #include #include -#include -#include +#include #include +#include +#include +static int trps_destructor(void *object) +{ + TRPS_INSTANCE *trps=talloc_get_type_abort(object, TRPS_INSTANCE); + if (trps->rtable!=NULL) + trp_rtable_free(trps->rtable); + return 0; +} + TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx) { TRPS_INSTANCE *trps=talloc(mem_ctx, TRPS_INSTANCE); @@ -24,6 +33,14 @@ TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx) /* failed to allocate mq */ talloc_free(trps); trps=NULL; + } else { + trps->rtable=trp_rtable_new(); + if (trps->rtable==NULL) { + /* failed to allocate rtable */ + talloc_free(trps); + trps=NULL; + } else + talloc_set_destructor((void *)trps, trps_destructor); } } return trps; @@ -114,58 +131,76 @@ TRP_RC trps_send_msg (TRPS_INSTANCE *trps, void *peer, const char *msg) static int trps_listen (TRPS_INSTANCE *trps, int port) { - int rc = 0; - int conn = -1; - int optval = 1; + int rc = 0; + int conn = -1; + int optval = 1; - union { - struct sockaddr_storage storage; - struct sockaddr_in in4; - } addr; + union { + struct sockaddr_storage storage; + struct sockaddr_in in4; + } addr; - struct sockaddr_in *saddr = (struct sockaddr_in *) &addr.in4; + struct sockaddr_in *saddr = (struct sockaddr_in *) &addr.in4; - saddr->sin_port = htons (port); - saddr->sin_family = AF_INET; - saddr->sin_addr.s_addr = INADDR_ANY; + saddr->sin_port = htons (port); + saddr->sin_family = AF_INET; + saddr->sin_addr.s_addr = INADDR_ANY; - if (0 > (conn = socket (AF_INET, SOCK_STREAM, 0))) - return conn; + if (0 > (conn = socket (AF_INET, SOCK_STREAM, 0))) + return conn; - setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); + setsockopt(conn, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - if (0 > (rc = bind (conn, (struct sockaddr *) saddr, sizeof(struct sockaddr_in)))) - return rc; + if (0 > (rc = bind (conn, (struct sockaddr *) saddr, sizeof(struct sockaddr_in)))) + return rc; - if (0 > (rc = listen(conn, 512))) - return rc; + if (0 > (rc = listen(conn, 512))) + return rc; - tr_debug("trps_listen: TRP Server listening on port %d", port); - return conn; + tr_debug("trps_listen: TRP Server listening on port %d", port); + return conn; } +#if 0 /* remove this if I forget to do so */ /* returns EACCES if authorization is denied */ int trps_auth_cb(gss_name_t clientName, gss_buffer_t displayName, void *data) { - TRPS_INSTANCE *inst = (TRPS_INSTANCE *)data; + TRPS_INSTANCE *trps = (TRPS_INSTANCE *)data; int result=0; - if (0!=inst->auth_handler(clientName, displayName, inst->cookie)) { + if (0!=trps->auth_handler(clientName, displayName, trps->cookie)) { tr_debug("trps_auth_cb: client '%.*s' denied authorization.", displayName->length, displayName->value); result=EACCES; /* denied */ } return result; } +#endif /* get the currently selected route if available */ -TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm) +TRP_RENTRY *trps_get_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm, TR_NAME *peer) +{ + return trp_rtable_get_entry(trps->rtable, comm, realm, peer); +} + +TRP_RENTRY *trps_get_selected_route(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm) { return trp_rtable_get_selected_entry(trps->rtable, comm, realm); } +/* copy the result if you want to keep it */ +TR_NAME *trps_get_next_hop(TRPS_INSTANCE *trps, TR_NAME *comm, TR_NAME *realm) +{ + TRP_RENTRY *route=trps_get_selected_route(trps, comm, realm); + if (route==NULL) + return NULL; + + return trp_rentry_get_next_hop(route); +} + + /* mark a route as retracted */ -static TRP_RC trps_retract_route(TRPS_INSTANCE *trps, TRP_RENTRY *entry) +static void trps_retract_route(TRPS_INSTANCE *trps, TRP_RENTRY *entry) { trp_rentry_set_metric(entry, TRP_METRIC_INFINITY); } @@ -181,13 +216,13 @@ static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MS int err=0; char *buf=NULL; size_t buflen = 0; - TR_NAME *peer=NULL + TR_NAME *peer=NULL; tr_debug("trps_read_message: started"); if (err = gsscon_read_encrypted_token(trp_connection_get_fd(conn), *(trp_connection_get_gssctx(conn)), - &buf, - &buflen)) { + &buf, + &buflen)) { tr_debug("trps_read_message: error"); if (buf) free(buf); @@ -206,11 +241,11 @@ static TRP_RC trps_read_message(TRPS_INSTANCE *trps, TRP_CONNECTION *conn, TR_MS /* verify we received a message we support, otherwise drop it now */ switch (tr_msg_get_msg_type(*msg)) { case TRP_UPDATE: - trp_upd_set_peer(tr_msg_get_trp_upd(msg), tr_name_dup(peer)); + trp_upd_set_peer(tr_msg_get_trp_upd(*msg), tr_dup_name(peer)); break; case TRP_REQUEST: - trp_req_set_peer(tr_msg_get_trp_req(msg), tr_name_dup(peer)); + trp_req_set_peer(tr_msg_get_trp_req(*msg), tr_dup_name(peer)); break; default: @@ -299,6 +334,21 @@ void trps_handle_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *conn) talloc_free(tmp_ctx); } +static TRP_RC trps_validate_update(TRPS_INSTANCE *trps, TRP_UPD *upd) +{ + if (trp_upd_get_inforec(upd)==NULL) { + tr_notice("trps_validate_update: received TRP update with no info records."); + return TRP_ERROR; + } + + if (trp_upd_get_peer(upd)==NULL) { + tr_notice("trps_validate_update: received TRP update without origin peer information."); + return TRP_ERROR; + } + + return TRP_SUCCESS; +} + /* ensure that the update could be accepted if feasible */ static TRP_RC trps_validate_inforec(TRPS_INSTANCE *trps, TRP_INFOREC *rec) { @@ -307,9 +357,10 @@ static TRP_RC trps_validate_inforec(TRPS_INSTANCE *trps, TRP_INFOREC *rec) if ((trp_inforec_get_comm(rec)==NULL) || (trp_inforec_get_realm(rec)==NULL) || (trp_inforec_get_trust_router(rec)==NULL) - || (trp_inforec_get_next_hop(rec)==NULL)) + || (trp_inforec_get_next_hop(rec)==NULL)) { tr_debug("trps_validate_inforec: missing record info."); return TRP_ERROR; + } /* check for valid metric */ if ((trp_inforec_get_metric(rec)==TRP_METRIC_INVALID) @@ -326,6 +377,7 @@ static TRP_RC trps_validate_inforec(TRPS_INSTANCE *trps, TRP_INFOREC *rec) break; default: + tr_notice("trps_validate_inforec: unsupported record type."); return TRP_UNSUPPORTED; } @@ -346,27 +398,28 @@ static unsigned int trps_advertised_metric(TRPS_INSTANCE *trps, TR_NAME *comm, T return trp_rentry_get_metric(entry) + trps_cost(trps, peer); } -/* returns TRP_SUCCESS if route is feasible, TRP_ERROR otherwise */ -static TRP_RC trps_check_feasibility(TRPS_INSTANCE *trps, TRP_INFOREC *rec) +static int trps_check_feasibility(TRPS_INSTANCE *trps, TRP_INFOREC *rec) { unsigned int rec_metric=trp_inforec_get_metric(rec); unsigned int new_metric=0; unsigned int current_metric=0; + TR_NAME *next_hop=NULL; /* we check these in the validation stage, but just in case... */ if ((rec_metric==TRP_METRIC_INVALID) || (rec_metric>TRP_METRIC_INFINITY)) - return TRP_ERROR; + return 0; /* retractions (aka infinite metrics) are always feasible */ if (rec_metric==TRP_METRIC_INFINITY) - return TRP_SUCCESS; + return 1; /* updates from our current next hop are always feasible*/ - if (0==tr_name_cmp(trp_inforec_get_next_hop(rec), - trps_next_hop(trps, - trp_inforec_get_comm(rec), - trp_inforec_get_realm(rec)))) { - return TRP_SUCCESS; + next_hop=trps_get_next_hop(trps, + trp_inforec_get_comm(rec), + trp_inforec_get_realm(rec));; + if ((next_hop!=NULL) + && (0==tr_name_cmp(next_hop,trp_inforec_get_next_hop(rec)))) { + return 1; } @@ -378,20 +431,19 @@ static TRP_RC trps_check_feasibility(TRPS_INSTANCE *trps, TRP_INFOREC *rec) trp_inforec_get_next_hop(rec)); new_metric=rec_metric + trps_cost(trps, trp_inforec_get_next_hop(rec)); if (new_metric <= current_metric) - return TRP_SUCCESS; + return 1; else - return TRP_ERROR; + return 0; } -/* uses memory pointed to by *ts, also returns that value */ -static void trps_compute_expiry(unsigned int interval, struct timespec *ts) +/* uses memory pointed to by *ts, also returns that value. On error, its contents are {0,0} */ +static struct timespec *trps_compute_expiry(TRPS_INSTANCE *trps, unsigned int interval, struct timespec *ts) { const unsigned int small_factor=3; /* how many intervals we wait before expiring */ if (0!=clock_gettime(CLOCK_REALTIME, ts)) { - tr_error("trps_compute_expiry: could not read realtime clock."); + tr_err("trps_compute_expiry: could not read realtime clock."); ts->tv_sec=0; ts->tv_nsec=0; - return NULL; } ts->tv_sec += small_factor*interval; return ts; @@ -408,7 +460,7 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec) if (entry==NULL) { entry=trp_rentry_new(NULL); if (entry==NULL) { - tr_error("trps_accept_update: unable to allocate new entry."); + tr_err("trps_accept_update: unable to allocate new entry."); return TRP_NOMEM; } @@ -421,9 +473,9 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec) ||(trp_rentry_get_realm(entry)==NULL) ||(trp_rentry_get_peer(entry)==NULL) ||(trp_rentry_get_trust_router(entry)==NULL) - ||(trp_rentry_next_hop(entry)==NULL)) { + ||(trp_rentry_get_next_hop(entry)==NULL)) { /* at least one field could not be allocated */ - tr_error("trps_accept_update: unable to allocate all fields for entry."); + tr_err("trps_accept_update: unable to allocate all fields for entry."); trp_rentry_free(entry); return TRP_NOMEM; } @@ -434,9 +486,14 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec) * the metric is infinity. An infinite metric can only occur here if we just retracted an existing * route (we never accept retractions as new routes), so there is no risk of leaving the expiry * time unset on a new route entry. */ + tr_debug("trps_accept_update: accepting route update."); trp_rentry_set_metric(entry, trp_inforec_get_metric(rec)); - if (!trps_route_retracted(trps, entry)) - trp_rentry_set_expiry(entry, trps_compute_expiry(trps, trp_inforec_get_interval(rec))); + if (!trps_route_retracted(trps, entry)) { + tr_debug("trps_accept_update: route not retracted, setting expiry timer."); + trp_rentry_set_expiry(entry, trps_compute_expiry(trps, + trp_inforec_get_interval(rec), + trp_rentry_get_expiry(entry))); + } return TRP_SUCCESS; } @@ -444,28 +501,31 @@ static TRP_RC trps_accept_update(TRPS_INSTANCE *trps, TRP_INFOREC *rec) static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd) { unsigned int feas=0; - TRP_INFOREC *rec=trp_upd_get_inforec(upd); + TRP_INFOREC *rec=NULL; TRP_RENTRY *route=NULL; - if (rec==NULL) { - tr_notice("trps_handle_update: received TRP update with no info records."); + if (trps_validate_update(trps, upd) != TRP_SUCCESS) { + tr_notice("trps_handle_update: received invalid TRP update."); return TRP_ERROR; } + rec=trp_upd_get_inforec(upd); for (;rec!=NULL; rec=trp_inforec_get_next(rec)) { - /* validate/sanity check the update */ - if (trps_validate_inforec(trps, upd) != TRP_SUCCESS) { + /* validate/sanity check the record update */ + if (trps_validate_inforec(trps, rec) != TRP_SUCCESS) { tr_notice("trps_handle_update: invalid record in TRP update."); continue; } /* determine feasibility */ feas=trps_check_feasibility(trps, rec); + tr_debug("trps_handle_update: record feasibility=%d", feas); /* do we have an existing route? */ - route=trps_get_route(trps, trp_inforec_get_comm(rec), trp_inforec_get_realm(rec)); + route=trps_get_route(trps, trp_inforec_get_comm(rec), trp_inforec_get_realm(rec), trp_inforec_get_next_hop(rec)); if (route!=NULL) { /* there was a route table entry already */ + tr_debug("trps_handle_updates: route entry already exists."); if (feas) { /* Update is feasible. Accept it. */ trps_accept_update(trps, rec); @@ -479,7 +539,8 @@ static TRP_RC trps_handle_update(TRPS_INSTANCE *trps, TRP_UPD *upd) } } else { /* No existing route table entry. Ignore it unless it is feasible and not a retraction. */ - if (feas && (trp_inforec_get_metric != TRP_METRIC_INFINITY)) + tr_debug("trps_handle_update: no route entry exists yet."); + if (feas && (trp_inforec_get_metric(rec) != TRP_METRIC_INFINITY)) trps_accept_update(trps, rec); } } @@ -490,7 +551,7 @@ TRP_RC trps_handle_tr_msg(TRPS_INSTANCE *trps, TR_MSG *tr_msg) { switch (tr_msg_get_msg_type(tr_msg)) { case TRP_UPDATE: - return trps_handle_update(TRPS_INSTANCE *trps, tr_msg_get_trp_upd(tr_msg)); + return trps_handle_update(trps, tr_msg_get_trp_upd(tr_msg)); case TRP_REQUEST: return TRP_UNSUPPORTED; -- 2.1.4