#include <trust_router/tr_dh.h>
#include <tr_mq.h>
#include <tr_msg.h>
+#include <trp_rtable.h>
#include <trust_router/trp.h>
/* info records */
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;
};
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 */
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);
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);
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);
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 */
#include <gsscon.h>
+#include <gssapi.h>
#include <fcntl.h>
#include <talloc.h>
#include <unistd.h>
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)
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);
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
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;
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;
}
#include <gsscon.h>
#include <tr_rp.h>
-#include <tr_debug.h>
-#include <trp_rtable.h>
+#include <trust_router/tr_name.h>
#include <trp_internal.h>
+#include <trp_rtable.h>
+#include <tr_debug.h>
+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);
/* 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;
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);
}
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);
/* 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:
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)
{
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)
break;
default:
+ tr_notice("trps_validate_inforec: unsupported record type.");
return TRP_UNSUPPORTED;
}
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;
}
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;
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;
}
||(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;
}
* 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;
}
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);
}
} 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);
}
}
{
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;