json_t *jcfgsettle = NULL;
json_t *jroutesweep = NULL;
json_t *jrouteupdate = NULL;
+ json_t *jrouteconnect = NULL;
if ((!trc) || (!jcfg))
return TR_CFG_BAD_PARAMS;
return TR_CFG_NOPARSE;
}
}
- if (NULL != (jroutesweep = json_object_get(jint, "route_sweep_interval"))) {
+
+ if (NULL != (jrouteconnect = json_object_get(jint, "trp_connect_interval"))) {
+ if (json_is_number(jrouteconnect)) {
+ trc->internal->trp_connect_interval = json_integer_value(jrouteconnect);
+ } else {
+ tr_debug("tr_cfg_parse_internal: Parsing error, trp_connect_interval is not a number.");
+ return TR_CFG_NOPARSE;
+ }
+ } else {
+ /* if not configured, use the default */
+ trc->internal->trp_connect_interval=TR_DEFAULT_TRP_CONNECT_INTERVAL;
+ }
+
+ if (NULL != (jroutesweep = json_object_get(jint, "trp_sweep_interval"))) {
if (json_is_number(jroutesweep)) {
- trc->internal->route_sweep_interval = json_integer_value(jroutesweep);
+ trc->internal->trp_sweep_interval = json_integer_value(jroutesweep);
} else {
- tr_debug("tr_cfg_parse_internal: Parsing error, route_sweep_interval is not a number.");
+ tr_debug("tr_cfg_parse_internal: Parsing error, trp_sweep_interval is not a number.");
return TR_CFG_NOPARSE;
}
+ } else {
+ /* if not configured, use the default */
+ trc->internal->trp_sweep_interval=TR_DEFAULT_TRP_SWEEP_INTERVAL;
}
- if (NULL != (jrouteupdate = json_object_get(jint, "route_update_interval"))) {
+
+ if (NULL != (jrouteupdate = json_object_get(jint, "trp_update_interval"))) {
if (json_is_number(jrouteupdate)) {
- trc->internal->route_update_interval = json_integer_value(jrouteupdate);
+ trc->internal->trp_update_interval = json_integer_value(jrouteupdate);
} else {
- tr_debug("tr_cfg_parse_internal: Parsing error, route_update_interval is not a number.");
+ tr_debug("tr_cfg_parse_internal: Parsing error, trp_update_interval is not a number.");
return TR_CFG_NOPARSE;
}
+ } else {
+ /* if not configured, use the default */
+ trc->internal->trp_update_interval=TR_DEFAULT_TRP_UPDATE_INTERVAL;
}
if (NULL != (jlog = json_object_get(jint, "logging"))) {
}
json_object_set_new(jupdate, "records", jrecords); /* jrecords now a "borrowed" reference */
for (rec=trp_upd_get_inforec(update); rec!=NULL; rec=trp_inforec_get_next(rec)) {
+ tr_debug("tr_msg_encode_trp_upd: encoding inforec.");
jrec=tr_msg_encode_inforec(rec);
if (jrec==NULL) {
json_decref(jupdate); /* also decs jrecords and any elements */
#define TR_DEFAULT_TRPS_PORT 12310
#define TR_DEFAULT_LOG_THRESHOLD LOG_INFO
#define TR_DEFAULT_CONSOLE_THRESHOLD LOG_NOTICE
-
+#define TR_DEFAULT_TRP_CONNECT_INTERVAL 10
+#define TR_DEFAULT_TRP_UPDATE_INTERVAL 120
+#define TR_DEFAULT_TRP_SWEEP_INTERVAL 30
typedef enum tr_cfg_rc {
TR_CFG_SUCCESS = 0, /* No error */
TR_CFG_ERROR, /* General processing error */
int console_threshold;
unsigned int cfg_poll_interval;
unsigned int cfg_settle_count;
- unsigned int route_sweep_interval;
- unsigned int route_update_interval;
+ unsigned int trp_sweep_interval;
+ unsigned int trp_update_interval;
+ unsigned int trp_connect_interval;
} TR_CFG_INTERNAL;
typedef struct tr_cfg {
typedef struct tr_trps_events {
struct tr_socket_event *listen_ev;
struct event *mq_ev;
+ struct event *connect_ev;
struct event *update_ev;
struct event *sweep_ev;
} TR_TRPS_EVENTS;
TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx);
TRP_RC tr_trps_event_init(struct event_base *base, TRPS_INSTANCE *trps, TR_CFG_MGR *cfg_mgr,
TR_TRPS_EVENTS *trps_ev);
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigned int port);
+TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer);
void tr_config_changed(TR_CFG *new_cfg, void *cookie);
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps);
#endif /* TR_TRP_H */
typedef struct trpc_instance TRPC_INSTANCE;
struct trpc_instance {
TRPC_INSTANCE *next;
+ TR_NAME *gssname;
char *server;
unsigned int port;
TRP_CONNECTION *conn;
TR_MQ *mq; /* incoming message queue */
TRP_PTABLE *ptable; /* peer table */
TRP_RTABLE *rtable; /* route table */
+ struct timeval connect_interval; /* interval between connection refreshes */
struct timeval update_interval; /* interval between scheduled updates */
struct timeval sweep_interval; /* interval between route table sweeps */
};
void trpc_append(TRPC_INSTANCE *trpc, TRPC_INSTANCE *new);
char *trpc_get_server(TRPC_INSTANCE *trpc);
void trpc_set_server(TRPC_INSTANCE *trpc, char *server);
+TR_NAME *trpc_get_gssname(TRPC_INSTANCE *trpc);
+void trpc_set_gssname(TRPC_INSTANCE *trpc, TR_NAME *gssname);
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);
TRPS_INSTANCE *trps_new (TALLOC_CTX *mem_ctx);
void trps_free (TRPS_INSTANCE *trps);
+void trps_set_connect_interval(TRPS_INSTANCE *trps, unsigned int interval);
+unsigned int trps_get_connect_interval(TRPS_INSTANCE *trps);
void trps_set_update_interval(TRPS_INSTANCE *trps, unsigned int interval);
unsigned int trps_get_update_interval(TRPS_INSTANCE *trps);
void trps_set_sweep_interval(TRPS_INSTANCE *trps, unsigned int interval);
unsigned int trps_get_sweep_interval(TRPS_INSTANCE *trps);
-TRP_RC trps_send_msg (TRPS_INSTANCE *trps, TR_NAME *peer_gssname, const char *msg);
+TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TRP_PEER *peer);
+TRP_RC trps_send_msg (TRPS_INSTANCE *trps, TRP_PEER *peer, const char *msg);
void trps_add_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *new);
void trps_remove_connection(TRPS_INSTANCE *trps, TRP_CONNECTION *remove);
void trps_add_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *trpc);
#ifndef _TRP_PTABLE_H_
#define _TRP_PTABLE_H_
+#include <time.h>
#include <talloc.h>
#include <trust_router/tr_name.h>
typedef struct trp_peer TRP_PEER;
struct trp_peer {
+ TRP_PEER *next; /* for making a linked list */
char *server;
unsigned int port;
unsigned int linkcost;
- TRP_PEER *next; /* for making a linked list */
+ struct timespec last_conn_attempt;
};
typedef struct trp_ptable {
unsigned int trp_peer_get_port(TRP_PEER *peer);
void trp_peer_set_port(TRP_PEER *peer, unsigned int port);
unsigned int trp_peer_get_linkcost(TRP_PEER *peer);
+struct timespec *trp_peer_get_last_conn_attempt(TRP_PEER *peer);
+void trp_peer_set_last_conn_attempt(TRP_PEER *peer, struct timespec *time);
void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost);
char *trp_peer_to_str(TALLOC_CTX *memctx, TRP_PEER *peer, const char *sep);
void trp_rentry_free(TRP_RENTRY *entry);
void trp_rentry_set_apc(TRP_RENTRY *entry, TR_NAME *apc);
TR_NAME *trp_rentry_get_apc(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_apc(TRP_RENTRY *entry);
void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm);
TR_NAME *trp_rentry_get_realm(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_realm(TRP_RENTRY *entry);
void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr);
TR_NAME *trp_rentry_get_trust_router(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_trust_router(TRP_RENTRY *entry);
void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer);
TR_NAME *trp_rentry_get_peer(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_peer(TRP_RENTRY *entry);
void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric);
unsigned int trp_rentry_get_metric(TRP_RENTRY *entry);
void trp_rentry_set_next_hop(TRP_RENTRY *entry, TR_NAME *next_hop);
TR_NAME *trp_rentry_get_next_hop(TRP_RENTRY *entry);
+TR_NAME *trp_rentry_dup_next_hop(TRP_RENTRY *entry);
void trp_rentry_set_selected(TRP_RENTRY *entry, int sel);
int trp_rentry_get_selected(TRP_RENTRY *entry);
void trp_rentry_set_interval(TRP_RENTRY *entry, int interval);
TRP_BADTYPE, /* typing error */
TRP_UNSUPPORTED, /* unsupported feature */
TRP_BADARG, /* bad argument */
+ TRP_CLOCKERR, /* error reading time */
} TRP_RC;
typedef enum trp_inforec_type {
TR_EXPORT TRP_INFOREC_TYPE trp_inforec_get_type(TRP_INFOREC *rec);
void trp_inforec_set_type(TRP_INFOREC *rec, TRP_INFOREC_TYPE type);
TR_EXPORT TR_NAME *trp_inforec_get_comm(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_comm(TRP_INFOREC *rec);
TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm);
TR_EXPORT TR_NAME *trp_inforec_get_realm(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_realm(TRP_INFOREC *rec);
TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm);
TR_EXPORT TR_NAME *trp_inforec_get_trust_router(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec);
TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router);
TR_EXPORT TR_NAME *trp_inforec_get_next_hop(TRP_INFOREC *rec);
+TR_EXPORT TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec);
TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop);
TR_EXPORT unsigned int trp_inforec_get_metric(TRP_INFOREC *rec);
TRP_RC trp_inforec_set_metric(TRP_INFOREC *rec, unsigned int metric);
retval=1; goto cleanup;
}
+ /* call callback to notify system of new configuration */
+ tr_debug("tr_read_and_apply_config: calling update callback function.");
+ if (cfgwatch->update_cb!=NULL)
+ cfgwatch->update_cb(cfgwatch->cfg_mgr->active, cfgwatch->update_cookie);
+
/* give ownership of the new_fstat_list to caller's context */
if (cfgwatch->fstat_list != NULL) {
/* free the old one */
tr_notice("Configuration file change settled, attempting to update configuration.");
if (0 != tr_read_and_apply_config(cfg_status))
tr_warning("Configuration file update failed. Using previous configuration.");
- else {
- if (cfg_status->update_cb!=NULL)
- cfg_status->update_cb(cfg_status->cfg_mgr->active, cfg_status->update_cookie);
+ else
tr_notice("Configuration updated successfully.");
- }
cfg_status->change_detected=0;
}
}
return 1;
}
+ /***** initialize the trust path query server instance *****/
+ if (NULL == (tr->tids = tids_create (tr))) {
+ tr_crit("Error initializing Trust Path Query Server instance.");
+ return 1;
+ }
+
+ /***** initialize the trust router protocol server instance *****/
+ if (NULL == (tr->trps = trps_new(tr))) {
+ tr_crit("Error initializing Trust Router Protocol Server instance.");
+ return 1;
+ }
+
/***** process configuration *****/
tr->cfgwatch=tr_cfgwatch_create(tr);
if (tr->cfgwatch == NULL) {
}
tr->cfgwatch->config_dir=opts.config_dir;
tr->cfgwatch->cfg_mgr=tr->cfg_mgr;
+ tr->cfgwatch->update_cb=tr_config_changed; /* handle configuration changes */
+ tr->cfgwatch->update_cookie=(void *)(tr->trps);
if (0 != tr_read_and_apply_config(tr->cfgwatch)) {
tr_crit("Error reading configuration, exiting.");
return 1;
}
- tr->cfgwatch->update_cb=tr_config_changed; /* handle configuration changes */
- tr->cfgwatch->update_cookie=(void *)tr;
-
- /***** initialize the trust path query server instance *****/
- if (NULL == (tr->tids = tids_create (tr))) {
- tr_crit("Error initializing Trust Path Query Server instance.");
- return 1;
- }
-
- /***** initialize the trust router protocol server instance *****/
- if (NULL == (tr->trps = trps_new(tr))) {
- tr_crit("Error initializing Trust Router Protocol Server instance.");
- return 1;
- }
/***** Set up the event loop *****/
ev_base=tr_event_loop_init(); /* Set up the event loop */
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
+#include <time.h>
#include <gsscon.h>
#include <tr_rp.h>
#include <trp_internal.h>
+#include <trp_ptable.h>
+#include <trp_rtable.h>
#include <tr_config.h>
#include <tr_event.h>
#include <tr_msg.h>
talloc_free(tmp_ctx);
}
-static void tr_trps_cleanup_thread(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
+static void tr_trps_cleanup_conn(TRPS_INSTANCE *trps, TRP_CONNECTION *conn)
{
/* everything belonging to the thread is in the TRP_CONNECTION
* associated with it */
trps_remove_connection(trps, conn);
+ trp_connection_free(conn);
+ tr_debug("Deleted connection");
+}
+
+#if 0
+static void tr_trpc_abort(TRPC_INSTANCE *trpc)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TR_MQ_MSG *msg=tr_mq_msg_new(tmp_ctx, "trpc_abort");
+ tr_mq_msg_set_payload(msg, (void *)conn, NULL); /* do not pass a free routine */
+ trpc_mq_append(msg); /* gives msg over to the queue to manage */
+
+}
+#endif
+
+static void tr_trps_cleanup_trpc(TRPS_INSTANCE *trps, TRPC_INSTANCE *trpc)
+{
+ /* everything belonging to the thread is in the TRP_CONNECTION
+ * associated with it */
+/* tr_trpc_abort(trpc); */ /* tell trpc to abort */
+ trps_remove_trpc(trps, trpc);
+ trpc_free(trpc);
tr_debug("Deleted connection");
}
while (msg!=NULL) {
s=tr_mq_msg_get_message(msg);
if (0==strcmp(s, "trps_thread_exit")) {
- tr_trps_cleanup_thread(trps,
- talloc_get_type_abort(tr_mq_msg_get_payload(msg),
- TRP_CONNECTION));
+ tr_trps_cleanup_conn(trps,
+ talloc_get_type_abort(tr_mq_msg_get_payload(msg),
+ TRP_CONNECTION));
}
+ else if (0==strcmp(s, "trpc_thread_exit")) {
+ /* trpc connection died */
+ tr_trps_cleanup_trpc(trps,
+ talloc_get_type_abort(tr_mq_msg_get_payload(msg),
+ TRPC_INSTANCE));
+ }
+
else if (0==strcmp(s, "tr_msg")) {
if (trps_handle_tr_msg(trps, tr_mq_msg_get_payload(msg))!=TRP_SUCCESS)
tr_notice("tr_trps_process_mq: error handling message.");
TRPS_INSTANCE *trps=cookie->trps;
struct event *ev=cookie->ev;
- tr_debug("tr_trps_sweep: sweeping routes");
+ tr_debug("tr_trps_sweep: sweeping routes.");
trps_sweep_routes(trps);
/* schedule the event to run again */
event_add(ev, &(trps->sweep_interval));
}
+static void tr_connection_update(int listener, short event, void *arg)
+{
+ struct tr_trps_event_cookie *cookie=talloc_get_type_abort(arg, struct tr_trps_event_cookie);
+ TRPS_INSTANCE *trps=cookie->trps;
+ struct event *ev=cookie->ev;
+
+ tr_debug("tr_connection_update: checking peer connections.");
+ tr_connect_to_peers(trps);
+ /* schedule the event to run again */
+ event_add(ev, &(trps->connect_interval));
+}
+
static int tr_trps_events_destructor(void *obj)
{
TR_TRPS_EVENTS *ev=talloc_get_type_abort(obj, TR_TRPS_EVENTS);
if (ev->mq_ev!=NULL)
event_free(ev->mq_ev);
+ if (ev->connect_ev!=NULL)
+ event_free(ev->connect_ev);
+ if (ev->update_ev!=NULL)
+ event_free(ev->update_ev);
if (ev->sweep_ev!=NULL)
event_free(ev->sweep_ev);
return 0;
if (ev!=NULL) {
ev->listen_ev=talloc(ev, struct tr_socket_event);
ev->mq_ev=NULL;
+ ev->connect_ev=NULL;
ev->update_ev=NULL;
ev->sweep_ev=NULL;
if (ev->listen_ev==NULL) {
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
struct tr_socket_event *listen_ev=NULL;
struct tr_trps_event_cookie *trps_cookie=NULL;
+ struct tr_trps_event_cookie *connection_cookie=NULL;
struct tr_trps_event_cookie *update_cookie=NULL;
struct tr_trps_event_cookie *sweep_cookie=NULL;
TRP_RC retval=TRP_ERROR;
(void *)trps);
tr_mq_set_notify_cb(trps->mq, tr_trps_mq_cb, trps_ev->mq_ev);
+ /* now set up the peer connection timer event */
+ connection_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+ if (connection_cookie == NULL) {
+ tr_debug("tr_trps_event_init: Unable to allocate connection_cookie.");
+ retval=TRP_NOMEM;
+ goto cleanup;
+ }
+ connection_cookie->trps=trps;
+ connection_cookie->cfg_mgr=cfg_mgr;
+ talloc_steal(trps, connection_cookie);
+ trps_ev->connect_ev=event_new(base, -1, EV_TIMEOUT, tr_connection_update, (void *)connection_cookie);
+ connection_cookie->ev=trps_ev->connect_ev; /* in case it needs to frob the event */
+ event_add(trps_ev->connect_ev, &(trps->connect_interval));
+
/* now set up the route update timer event */
update_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
if (update_cookie == NULL) {
}
/* starts a trpc thread to connect to server:port */
-TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, const char *server, unsigned int port)
+TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
TRPC_INSTANCE *trpc=NULL;
goto cleanup;
}
trpc_set_conn(trpc, conn);
- trpc_set_server(trpc, talloc_strdup(trpc, server));
- trpc_set_port(trpc, port);
+ trpc_set_server(trpc, talloc_strdup(trpc, trp_peer_get_server(peer)));
+ trpc_set_port(trpc, trp_peer_get_port(peer));
+ trpc_set_gssname(trpc, trp_peer_get_gssname(peer));
tr_debug("tr_trpc_initiate: allocated connection");
/* start thread */
tr_debug("tr_trpc_initiate: started trpc thread");
trps_add_trpc(trps, trpc);
- talloc_report_full(trps, stderr);
- talloc_report_full(tmp_ctx, stderr);
-
cleanup:
talloc_free(tmp_ctx);
return trpc;
}
+/* decide how often to attempt to connect to a peer */
+static int tr_conn_attempt_due(TRPS_INSTANCE *trps, TRP_PEER *peer, struct timespec *when)
+{
+ return 1; /* currently make an attempt every cycle */
+}
+
+/* open missing connections to peers */
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TRP_PTABLE_ITER *iter=trp_ptable_iter_new(tmp_ctx);
+ TRP_PEER *peer=NULL;
+ TRPC_INSTANCE *trpc=NULL;
+ struct timespec curtime={0,0};
+ TRP_RC rc=TRP_ERROR;
+
+ if (clock_gettime(CLOCK_REALTIME, &curtime)) {
+ tr_err("tr_connect_to_peers: failed to read time.");
+ rc=TRP_CLOCKERR;
+ goto cleanup;
+ }
+
+ for (peer=trp_ptable_iter_first(iter, trps->ptable);
+ peer!=NULL;
+ peer=trp_ptable_iter_next(iter))
+ {
+ if (trps_find_trpc(trps, peer)==NULL) {
+ tr_debug("tr_connect_to_peers: %.*s missing connection.",
+ trp_peer_get_gssname(peer)->len, trp_peer_get_gssname(peer)->buf);
+ /* has it been long enough since we last tried? */
+ if (tr_conn_attempt_due(trps, peer, &curtime)) {
+ trp_peer_set_last_conn_attempt(peer, &curtime); /* we are trying again now */
+ trpc=tr_trpc_initiate(trps, peer);
+ if (trpc==NULL) {
+ tr_err("tr_connect_to_peers: unable to initiate TRP connection to %s:%u.",
+ trp_peer_get_server(peer),
+ trp_peer_get_port(peer));
+ }
+ }
+ }
+ }
+ rc=TRP_SUCCESS;
+
+cleanup:
+ trp_ptable_iter_free(iter);
+ talloc_free(tmp_ctx);
+ return rc;
+}
+
+
/* Called by the config manager after a change to the active configuration.
* Updates configuration of objects that do not know about the config manager. */
void tr_config_changed(TR_CFG *new_cfg, void *cookie)
{
TRPS_INSTANCE *trps=talloc_get_type_abort(cookie, TRPS_INSTANCE);
- trps_set_update_interval(trps, new_cfg->internal->route_update_interval);
- trps_set_sweep_interval(trps, new_cfg->internal->route_sweep_interval);
+ trps_set_connect_interval(trps, new_cfg->internal->trp_connect_interval);
+ trps_set_update_interval(trps, new_cfg->internal->trp_update_interval);
+ trps_set_sweep_interval(trps, new_cfg->internal->trp_sweep_interval);
}
+
trp_connection_set_gssname(new_conn, NULL);
trp_connection_mutex_init(new_conn);
trp_connection_set_status(new_conn, TRP_CONNECTION_DOWN);
+ new_conn->peer=NULL; /* no true set function for this */
thread=talloc(new_conn, pthread_t);
gssctx=talloc(new_conn, gss_ctx_id_t);
if (gssctx==NULL) {
"trustrouter",
&fd,
trp_connection_get_gssctx(conn));
- tr_debug("trp_connection_initiate: connected");
-
if (err) {
+ tr_debug("trp_connection_initiate: connection failed.");
talloc_free(conn);
return TRP_ERROR;
} else {
+ tr_debug("trp_connection_initiate: connected.");
trp_connection_set_fd(conn, fd);
trp_connection_set_peer(conn);
trp_connection_set_status(conn, TRP_CONNECTION_UP);
+#include <time.h>
#include <talloc.h>
#include <trust_router/tr_name.h>
{
TRP_PEER *peer=talloc(memctx, TRP_PEER);
if (peer!=NULL) {
+ peer->next=NULL;
peer->server=NULL;
peer->port=0;
peer->linkcost=TRP_METRIC_INFINITY;
- peer->next=NULL;
+ peer->last_conn_attempt=(struct timespec){0,0};
}
return peer;
}
unsigned int trp_peer_get_linkcost(TRP_PEER *peer)
{
- return peer->linkcost;
+ if (peer!=NULL)
+ return peer->linkcost;
+ else
+ return 1;
}
void trp_peer_set_linkcost(TRP_PEER *peer, unsigned int linkcost)
peer->linkcost=linkcost;
}
+struct timespec *trp_peer_get_last_conn_attempt(TRP_PEER *peer)
+{
+ return &(peer->last_conn_attempt);
+}
+
+void trp_peer_set_last_conn_attempt(TRP_PEER *peer, struct timespec *time)
+{
+ peer->last_conn_attempt=*time;
+}
+
TRP_PTABLE *trp_ptable_new(TALLOC_CTX *memctx)
{
TRP_PTABLE *ptbl=talloc(memctx, TRP_PTABLE);
TRP_PEER *trp_ptable_iter_next(TRP_PTABLE_ITER *iter)
{
- if ((*iter)->next!=NULL)
- *iter=(*iter)->next;
+ *iter=(*iter)->next;
return *iter;
}
return entry->apc;
}
+TR_NAME *trp_rentry_dup_apc(TRP_RENTRY *entry)
+{
+ return tr_dup_name(trp_rentry_get_apc(entry));
+}
+
void trp_rentry_set_realm(TRP_RENTRY *entry, TR_NAME *realm)
{
entry->realm=realm;
return entry->realm;
}
+TR_NAME *trp_rentry_dup_realm(TRP_RENTRY *entry)
+{
+ return tr_dup_name(trp_rentry_get_realm(entry));
+}
+
void trp_rentry_set_trust_router(TRP_RENTRY *entry, TR_NAME *tr)
{
entry->trust_router=tr;
return entry->trust_router;
}
+TR_NAME *trp_rentry_dup_trust_router(TRP_RENTRY *entry)
+{
+ return tr_dup_name(trp_rentry_get_trust_router(entry));
+}
+
void trp_rentry_set_peer(TRP_RENTRY *entry, TR_NAME *peer)
{
entry->peer=peer;
return entry->peer;
}
+TR_NAME *trp_rentry_dup_peer(TRP_RENTRY *entry)
+{
+ return tr_dup_name(trp_rentry_get_peer(entry));
+}
+
void trp_rentry_set_metric(TRP_RENTRY *entry, unsigned int metric)
{
entry->metric=metric;
return entry->next_hop;
}
+TR_NAME *trp_rentry_dup_next_hop(TRP_RENTRY *entry)
+{
+ return tr_dup_name(trp_rentry_get_next_hop(entry));
+}
+
void trp_rentry_set_selected(TRP_RENTRY *entry, int sel)
{
entry->selected=sel;
static TRP_INFOREC *trp_inforec_get_tail(TRP_INFOREC *rec)
{
- while (rec!=NULL)
+ while ((rec->next)!=NULL)
rec=trp_inforec_get_next(rec);
return rec;
}
return NULL;
}
+TR_NAME *trp_inforec_dup_comm(TRP_INFOREC *rec)
+{
+ return tr_dup_name(trp_inforec_get_comm(rec));
+}
+
TRP_RC trp_inforec_set_comm(TRP_INFOREC *rec, TR_NAME *comm)
{
switch (rec->type) {
return NULL;
}
+TR_NAME *trp_inforec_dup_realm(TRP_INFOREC *rec)
+{
+ return tr_dup_name(trp_inforec_get_realm(rec));
+}
+
TRP_RC trp_inforec_set_realm(TRP_INFOREC *rec, TR_NAME *realm)
{
switch (rec->type) {
return NULL;
}
+TR_NAME *trp_inforec_dup_trust_router(TRP_INFOREC *rec)
+{
+ return tr_dup_name(trp_inforec_get_trust_router(rec));
+}
+
TRP_RC trp_inforec_set_trust_router(TRP_INFOREC *rec, TR_NAME *trust_router)
{
switch (rec->type) {
return NULL;
}
+TR_NAME *trp_inforec_dup_next_hop(TRP_INFOREC *rec)
+{
+ return tr_dup_name(trp_inforec_get_next_hop(rec));
+}
+
TRP_RC trp_inforec_set_next_hop(TRP_INFOREC *rec, TR_NAME *next_hop)
{
switch (rec->type) {
void trp_upd_add_inforec(TRP_UPD *upd, TRP_INFOREC *rec)
{
+ tr_debug("trp_upd_add_inforec: adding record.");
if (upd->records==NULL)
upd->records=rec;
else
#include <tr_debug.h>
#include <trp_internal.h>
+static int trpc_destructor(void *object)
+{
+ TRPC_INSTANCE *trpc=talloc_get_type_abort(object, TRPC_INSTANCE);
+ if (trpc->gssname!=NULL)
+ tr_free_name(trpc->gssname);
+ return 0;
+}
/* also allocates the incoming mq */
TRPC_INSTANCE *trpc_new (TALLOC_CTX *mem_ctx)
if (trpc->mq==NULL) {
talloc_free(trpc);
trpc=NULL;
- }
+ } else
+ talloc_set_destructor((void *)trpc, trpc_destructor);
+
}
return trpc;
}
trpc->server=server;
}
+TR_NAME *trpc_get_gssname(TRPC_INSTANCE *trpc)
+{
+ return trpc->gssname;
+}
+
+/* takes responsibility for freeing gssname */
+void trpc_set_gssname(TRPC_INSTANCE *trpc, TR_NAME *gssname)
+{
+ trpc->gssname=gssname;
+}
+
unsigned int trpc_get_port(TRPC_INSTANCE *trpc)
{
return trpc->port;
tr_mq_append(trps->mq, msg);
}
+unsigned int trps_get_connect_interval(TRPS_INSTANCE *trps)
+{
+ return trps->connect_interval.tv_sec;
+}
+
+void trps_set_connect_interval(TRPS_INSTANCE *trps, unsigned int interval)
+{
+ trps->connect_interval.tv_sec=interval;
+ trps->connect_interval.tv_usec=0;
+}
+
unsigned int trps_get_update_interval(TRPS_INSTANCE *trps)
{
return trps->update_interval.tv_sec;
trps->sweep_interval.tv_usec=0;
}
-static TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TR_NAME *peer_gssname)
+TRPC_INSTANCE *trps_find_trpc(TRPS_INSTANCE *trps, TRP_PEER *peer)
{
TRPC_INSTANCE *cur=NULL;
+ TR_NAME *name=NULL;
+ TR_NAME *peer_gssname=trp_peer_get_gssname(peer);
+
for (cur=trps->trpc; cur!=NULL; cur=trpc_get_next(cur)) {
- if (0==tr_name_cmp(peer_gssname,
- trp_connection_get_gssname(trpc_get_conn(cur)))) {
+ name=trpc_get_gssname(cur);
+ if ((name!=NULL) && (0==tr_name_cmp(peer_gssname, name))) {
break;
}
}
+ tr_free_name(peer_gssname);
return cur;
}
trps->trpc=trpc_remove(trps->trpc, remove);
}
-TRP_RC trps_send_msg(TRPS_INSTANCE *trps, TR_NAME *peer_gssname, const char *msg)
+TRP_RC trps_send_msg(TRPS_INSTANCE *trps, TRP_PEER *peer, const char *msg)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
TR_MQ_MSG *mq_msg=NULL;
TRPC_INSTANCE *trpc=NULL;
/* get the connection for this peer */
- trpc=trps_find_trpc(trps, peer_gssname);
+ trpc=trps_find_trpc(trps, peer);
if ((trpc==NULL) || (trpc_get_status(trps->trpc)!=TRP_CONNECTION_UP)) {
/* We could just let these sit on the queue in the hopes that a connection
* is eventually established. However, we'd then have to ensure the queue
}
/* check for valid metric */
- if (trp_metric_is_valid(trp_inforec_get_metric(rec))) {
- tr_debug("trps_validate_inforec: invalid metric.");
+ if (trp_metric_is_invalid(trp_inforec_get_metric(rec))) {
+ tr_debug("trps_validate_inforec: invalid metric (%u).", trp_inforec_get_metric(rec));
return TRP_ERROR;
}
result=talloc_array(memctx, TRP_RENTRY *, trp_rtable_size(trps->rtable));
if (result==NULL) {
talloc_free(apc);
+ *n_update=0;
return NULL;
}
/* Note that we leave the next hop empty since the recipient fills that in.
* This is where we add the link cost (currently always 1) to the next peer. */
- if ((trp_inforec_set_comm(rec, trp_rentry_get_apc(entry)) != TRP_SUCCESS)
- ||(trp_inforec_set_realm(rec, trp_rentry_get_realm(entry)) != TRP_SUCCESS)
- ||(trp_inforec_set_trust_router(rec, trp_rentry_get_trust_router(entry)) != TRP_SUCCESS)
+ if ((trp_inforec_set_comm(rec, trp_rentry_dup_apc(entry)) != TRP_SUCCESS)
+ ||(trp_inforec_set_realm(rec, trp_rentry_dup_realm(entry)) != TRP_SUCCESS)
+ ||(trp_inforec_set_trust_router(rec, trp_rentry_dup_trust_router(entry)) != TRP_SUCCESS)
||(trp_inforec_set_metric(rec, trp_rentry_get_metric(entry)+linkcost) != TRP_SUCCESS)
||(trp_inforec_set_interval(rec, trps_get_update_interval(trps)) != TRP_SUCCESS)) {
tr_err("trps_rentry_to_inforec: error creating route update.");
size_t n_updates=0, ii=0;
char *encoded=NULL;
TRP_RC rc=TRP_ERROR;
+ TR_NAME *peer_gssname=NULL;
if (iter==NULL) {
tr_err("trps_scheduled_update: failed to allocate peer table iterator.");
peer!=NULL;
peer=trp_ptable_iter_next(iter))
{
- tr_debug("trps_scheduled_update: preparing scheduled route update for %.*%s",
- trp_peer_get_gssname(peer)->len, trp_peer_get_gssname(peer)->buf);
- upd=trp_upd_new(tmp_ctx);
+ peer_gssname=trp_peer_get_gssname(peer);
+ tr_debug("trps_scheduled_update: preparing scheduled route update for %.*s",
+ peer_gssname->len, peer_gssname->buf);
/* do not fill in peer, recipient does that */
- update_list=trps_select_updates_for_peer(tmp_ctx, trps, trp_peer_get_gssname(peer), &n_updates);
- for (ii=0; ii<n_updates; ii++) {
- rec=trps_rentry_to_inforec(tmp_ctx, trps, update_list[ii]);
- if (rec==NULL) {
- tr_err("trps_scheduled_update: could not create all update records.");
+ update_list=trps_select_updates_for_peer(tmp_ctx, trps, peer_gssname, &n_updates);
+ tr_free_name(peer_gssname); peer_gssname=NULL;
+ if ((n_updates>0) && (update_list!=NULL)) {
+ tr_debug("trps_scheduled_update: sending %u update records.", (unsigned int)n_updates);
+ upd=trp_upd_new(tmp_ctx);
+
+ for (ii=0; ii<n_updates; ii++) {
+ rec=trps_rentry_to_inforec(tmp_ctx, trps, update_list[ii]);
+ if (rec==NULL) {
+ tr_err("trps_scheduled_update: could not create all update records.");
+ rc=TRP_ERROR;
+ goto cleanup;
+ }
+ trp_upd_add_inforec(upd, rec);
+ }
+ talloc_free(update_list);
+ update_list=NULL;
+
+ /* now encode the update message */
+ tr_msg_set_trp_upd(&msg, upd);
+ encoded=tr_msg_encode(&msg);
+ if (encoded==NULL) {
+ tr_err("trps_scheduled_update: error encoding update.");
rc=TRP_ERROR;
goto cleanup;
}
- trp_upd_add_inforec(upd, rec);
- }
- talloc_free(update_list);
- update_list=NULL;
-
- /* now encode the update message */
- tr_msg_set_trp_upd(&msg, upd);
- encoded=tr_msg_encode(&msg);
- if (encoded==NULL) {
- tr_err("trps_scheduled_update: error encoding update.");
- rc=TRP_ERROR;
- goto cleanup;
- }
- tr_debug("trps_scheduled_update: adding message to queue.");
- if (trps_send_msg(trps, trp_peer_get_gssname(peer), encoded) != TRP_SUCCESS) {
- tr_err("trps_scheduled_update: error queueing update.");
- rc=TRP_ERROR;
- tr_msg_free_encoded(encoded);
+
+ tr_debug("trps_scheduled_update: adding message to queue.");
+ if (trps_send_msg(trps, peer, encoded) != TRP_SUCCESS)
+ tr_err("trps_scheduled_update: error queueing update.");
+ else
+ tr_debug("trps_scheduled_update: update queued successfully.");
+
encoded=NULL;
- goto cleanup;
+ tr_msg_free_encoded(encoded);
+ trp_upd_free(upd);
+ upd=NULL;
}
- tr_debug("trps_scheduled_update: message queued successfully.");
- tr_msg_free_encoded(encoded);
- encoded=NULL;
- trp_upd_free(upd);
- upd=NULL;
}
cleanup: