#include <talloc.h>
#include <errno.h>
#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_debug.h>
+#include <tr_msg.h>
#include <tr_trp.h>
+#include <tr_debug.h>
-/* hold a trps instance and a config manager */
+/* data for event callbacks */
struct tr_trps_event_cookie {
TRPS_INSTANCE *trps;
TR_CFG_MGR *cfg_mgr;
+ struct event *ev;
};
-
/* callback to schedule event to process messages */
static void tr_trps_mq_cb(TR_MQ *mq, void *arg)
{
event_active(mq_ev, 0, 0);
}
-static int tr_trps_req_handler (TRPS_INSTANCE *trps,
- TRP_REQ *orig_req,
- void *tr_in)
+static void msg_free_helper(void *p)
{
- if (orig_req != NULL)
- free(orig_req);
- return -1; /* not handling anything right now */
+ tr_msg_free_decoded((TR_MSG *)p);
+}
+/* takes a TR_MSG and puts it in a TR_MQ_MSG for processing by the main thread */
+static TRP_RC tr_trps_msg_handler(TRPS_INSTANCE *trps,
+ TRP_CONNECTION *conn,
+ TR_MSG *tr_msg)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TR_MQ_MSG *mq_msg=NULL;
+
+ /* n.b., conn is available here, but do not hold onto the reference
+ * because it may be cleaned up if the originating connection goes
+ * down before the message is processed */
+ mq_msg=tr_mq_msg_new(tmp_ctx, "tr_msg");
+ if (mq_msg==NULL) {
+ return TRP_NOMEM;
+ }
+ tr_mq_msg_set_payload(mq_msg, (void *)tr_msg, msg_free_helper);
+ trps_mq_append(trps, mq_msg);
+ talloc_free(tmp_ctx); /* cleans up the message if it did not get appended correctly */
+ return TRP_SUCCESS;
}
}
/* data passed to thread */
-struct thread_data {
+struct trps_thread_data {
TRP_CONNECTION *conn;
TRPS_INSTANCE *trps;
};
/* thread to handle GSS connections to peers */
-static void *tr_trps_conn_thread(void *arg)
+static void *tr_trps_thread(void *arg)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
- struct thread_data *thread_data=talloc_get_type_abort(arg, struct thread_data);
+ struct trps_thread_data *thread_data=talloc_get_type_abort(arg, struct trps_thread_data);
TRP_CONNECTION *conn=thread_data->conn;
TRPS_INSTANCE *trps=thread_data->trps;
TR_MQ_MSG *msg=NULL;
- tr_debug("tr_trps_conn_thread: started");
- /* try to establish a GSS context */
- if (0!=trp_connection_auth(conn, trps->auth_handler, trps->cookie)) {
- tr_notice("tr_trps_conn_thread: failed to authorize connection");
- pthread_exit(NULL);
- }
- tr_notice("tr_trps_conn_thread: authorized connection");
-
- msg=tr_mq_msg_new(tmp_ctx);
+ tr_debug("tr_trps_thread: started");
+ trps_handle_connection(trps, conn);
+
+ msg=tr_mq_msg_new(tmp_ctx, "trps_thread_exit");
+ tr_mq_msg_set_payload(msg, (void *)conn, NULL); /* do not pass a free routine */
if (msg==NULL)
- tr_err("tr_trps_conn_thread: error allocating TR_MQ_MSG");
+ tr_err("tr_trps_thread: error allocating TR_MQ_MSG");
else
trps_mq_append(trps, msg);
- tr_debug("tr_trps_conn_thread: exit");
+ tr_debug("tr_trps_thread: exit");
talloc_free(tmp_ctx);
return NULL;
}
TRP_CONNECTION *conn=NULL;
TR_NAME *gssname=NULL;
char *name=NULL;
- struct thread_data *thread_data;
+ struct trps_thread_data *thread_data=NULL;
if (0==(event & EV_READ)) {
tr_debug("tr_trps_event_cb: unexpected event on TRPS socket (event=0x%X)", event);
asprintf(&name, "trustrouter@%s", trps->hostname);
gssname=tr_new_name(name);
free(name); name=NULL;
- conn=trp_connection_accept(tmp_ctx, listener, gssname, trps_auth_cb, NULL, trps);
+ conn=trp_connection_accept(tmp_ctx, listener, gssname);
if (conn!=NULL) {
/* need to monitor this fd and trigger events when read becomes possible */
- thread_data=talloc(conn, struct thread_data);
+ thread_data=talloc(conn, struct trps_thread_data);
if (thread_data==NULL) {
- tr_err("tr_trps_event_cb: unable to allocate thread_data");
+ tr_err("tr_trps_event_cb: unable to allocate trps_thread_data");
talloc_free(tmp_ctx);
return;
}
thread_data->conn=conn;
thread_data->trps=trps;
- pthread_create(conn->thread, NULL, tr_trps_conn_thread, thread_data);
- pthread_detach(*(conn->thread)); /* we will not rejoin the thread */
+ pthread_create(trp_connection_get_thread(conn), NULL, tr_trps_thread, thread_data);
+ pthread_detach(*(trp_connection_get_thread(conn))); /* we will not rejoin the thread */
trps_add_connection(trps, conn); /* remember the connection */
}
}
talloc_free(tmp_ctx);
}
+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");
+}
+
+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;
- tr_debug("tr_trps_process_mw: starting");
msg=trps_mq_pop(trps);
while (msg!=NULL) {
- tr_debug("tr_trps_process_mq: received message");
+ s=tr_mq_msg_get_message(msg);
+ if (0==strcmp(s, "trps_thread_exit")) {
+ 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.");
+ 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));
+
tr_mq_msg_free(msg);
msg=trps_mq_pop(trps);
}
- tr_debug("tr_trps_process_mw: ending");
}
+static void tr_trps_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_trps_update: sending scheduled route updates.");
+ trps_scheduled_update(trps);
+ event_add(ev, &(trps->update_interval));
+}
+
+static void tr_trps_sweep(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_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;
+}
TR_TRPS_EVENTS *tr_trps_events_new(TALLOC_CTX *mem_ctx)
{
TR_TRPS_EVENTS *ev=talloc(mem_ctx, TR_TRPS_EVENTS);
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_free(ev);
ev=NULL;
}
+ talloc_set_destructor((void *)ev, tr_trps_events_destructor);
}
return ev;
}
/* Configure the trps instance and set up its event handler.
- * Returns 0 on success, nonzero on failure. Results in
- * trps_ev, which should be allocated by caller. */
-int tr_trps_event_init(struct event_base *base,
+ * Fills in trps_ev, which should be allocated by caller. */
+TRP_RC tr_trps_event_init(struct event_base *base,
TRPS_INSTANCE *trps,
TR_CFG_MGR *cfg_mgr,
TR_TRPS_EVENTS *trps_ev)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
struct tr_socket_event *listen_ev=NULL;
- struct tr_trps_event_cookie *cookie;
- int retval=0;
+ 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;
if (trps_ev == NULL) {
tr_debug("tr_trps_event_init: Null trps_ev.");
- retval=1;
+ retval=TRP_BADARG;
goto cleanup;
}
/* Create the cookie for callbacks. It is part of the trps context, so it will
* be cleaned up when trps is freed by talloc_free. */
- cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
- if (cookie == NULL) {
- tr_debug("tr_trps_event_init: Unable to allocate cookie.");
- retval=1;
+ trps_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+ if (trps_cookie == NULL) {
+ tr_debug("tr_trps_event_init: Unable to allocate trps_cookie.");
+ retval=TRP_NOMEM;
goto cleanup;
}
- cookie->trps=trps;
- cookie->cfg_mgr=cfg_mgr;
- talloc_steal(trps, cookie);
+ trps_cookie->trps=trps;
+ trps_cookie->cfg_mgr=cfg_mgr;
+ talloc_steal(trps, trps_cookie);
/* get a trps listener */
listen_ev->sock_fd=trps_get_listener(trps,
- tr_trps_req_handler,
- tr_trps_gss_handler,
- cfg_mgr->active->internal->hostname,
- cfg_mgr->active->internal->trps_port,
- (void *)cookie);
+ tr_trps_msg_handler,
+ tr_trps_gss_handler,
+ cfg_mgr->active->internal->hostname,
+ cfg_mgr->active->internal->trps_port,
+ (void *)trps_cookie);
if (listen_ev->sock_fd < 0) {
tr_crit("Error opening TRP server socket.");
- retval=1;
+ retval=TRP_ERROR;
goto cleanup;
}
+ trps_cookie->ev=listen_ev->ev; /* in case it needs to frob the event */
/* and its event */
listen_ev->ev=event_new(base,
(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) {
+ tr_debug("tr_trps_event_init: Unable to allocate update_cookie.");
+ retval=TRP_NOMEM;
+ goto cleanup;
+ }
+ update_cookie->trps=trps;
+ update_cookie->cfg_mgr=cfg_mgr;
+ talloc_steal(trps, update_cookie);
+ trps_ev->update_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_update, (void *)update_cookie);
+ update_cookie->ev=trps_ev->update_ev; /* in case it needs to frob the event */
+ event_add(trps_ev->update_ev, &(trps->update_interval));
+
+ /* now set up the route table sweep timer event */
+ sweep_cookie=talloc(tmp_ctx, struct tr_trps_event_cookie);
+ if (sweep_cookie == NULL) {
+ tr_debug("tr_trps_event_init: Unable to allocate sweep_cookie.");
+ retval=TRP_NOMEM;
+ goto cleanup;
+ }
+ sweep_cookie->trps=trps;
+ sweep_cookie->cfg_mgr=cfg_mgr;
+ talloc_steal(trps, sweep_cookie);
+ trps_ev->sweep_ev=event_new(base, -1, EV_TIMEOUT, tr_trps_sweep, (void *)sweep_cookie);
+ sweep_cookie->ev=trps_ev->sweep_ev; /* in case it needs to frob the event */
+ event_add(trps_ev->sweep_ev, &(trps->sweep_interval));
+
+ retval=TRP_SUCCESS;
+
cleanup:
talloc_free(tmp_ctx);
return retval;
}
+
+struct trpc_notify_cb_data {
+ int msg_ready;
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+};
+
+static void tr_trpc_mq_cb(TR_MQ *mq, void *arg)
+{
+ struct trpc_notify_cb_data *cb_data=(struct trpc_notify_cb_data *) arg;
+ pthread_mutex_lock(&(cb_data->mutex));
+ if (!cb_data->msg_ready) {
+ cb_data->msg_ready=1;
+ pthread_cond_signal(&(cb_data->cond));
+ }
+ pthread_mutex_unlock(&(cb_data->mutex));
+}
+
+/* data passed to thread */
+struct trpc_thread_data {
+ TRPC_INSTANCE *trpc;
+ TRPS_INSTANCE *trps;
+};
+static void *tr_trpc_thread(void *arg)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ struct trpc_thread_data *thread_data=talloc_get_type_abort(arg, struct trpc_thread_data);
+ TRPC_INSTANCE *trpc=thread_data->trpc;
+ TRPS_INSTANCE *trps=thread_data->trps;
+ TRP_RC rc=TRP_ERROR;
+ TR_MQ_MSG *msg=NULL;
+ const char *msg_type=NULL;
+ char *encoded_msg=NULL;
+
+ struct trpc_notify_cb_data cb_data={0,
+ PTHREAD_COND_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER};
+
+ tr_debug("tr_trpc_thread: started");
+
+ /* set up the mq for receiving */
+ pthread_mutex_lock(&(cb_data.mutex)); /* hold this lock until we enter the main loop */
+
+ tr_mq_lock(trpc->mq);
+ tr_mq_set_notify_cb(trpc->mq, tr_trpc_mq_cb, (void *) &cb_data);
+ tr_mq_unlock(trpc->mq);
+
+ rc=trpc_connect(trpc);
+ if (rc!=TRP_SUCCESS) {
+ tr_notice("tr_trpc_thread: failed to initiate connection to %s:%d.",
+ trpc_get_server(trpc),
+ trpc_get_port(trpc));
+ } else {
+ while (1) {
+ cb_data.msg_ready=0;
+ pthread_cond_wait(&(cb_data.cond), &(cb_data.mutex));
+ /* verify the condition */
+ if (cb_data.msg_ready) {
+ msg=trpc_mq_pop(trpc);
+ if (msg==NULL) {
+ /* no message in the queue */
+ tr_err("tr_trpc_thread: notified of msg, but queue empty");
+ break;
+ }
+
+ msg_type=tr_mq_msg_get_message(msg);
+
+ if (0==strcmp(msg_type, "trpc_abort")) {
+ tr_mq_msg_free(msg);
+ break; /* exit loop */
+ }
+ else if (0==strcmp(msg_type, "trpc_send")) {
+ encoded_msg=tr_mq_msg_get_payload(msg);
+ if (encoded_msg==NULL)
+ tr_notice("tr_trpc_thread: null outgoing TRP message.");
+ else {
+ rc = trpc_send_msg(trpc, encoded_msg);
+ if (rc!=TRP_SUCCESS) {
+ tr_notice("tr_trpc_thread: trpc_send_msg failed.");
+ tr_mq_msg_free(msg);
+ break;
+ }
+ }
+ }
+ else
+ tr_notice("tr_trpc_thread: unknown message '%s' received.", msg_type);
+
+ tr_mq_msg_free(msg);
+ }
+ }
+ }
+
+ msg=tr_mq_msg_new(tmp_ctx, "trpc_thread_exit");
+ tr_mq_msg_set_payload(msg, (void *)trpc, NULL); /* do not pass a free routine */
+ if (msg==NULL)
+ tr_err("tr_trpc_thread: error allocating TR_MQ_MSG");
+ else
+ trps_mq_append(trps, msg);
+
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+/* starts a trpc thread to connect to server:port */
+TRPC_INSTANCE *tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TRPC_INSTANCE *trpc=NULL;
+ TRP_CONNECTION *conn=NULL;
+ struct trpc_thread_data *thread_data=NULL;
+
+ tr_debug("tr_trpc_initiate entered");
+ trpc=trpc_new(tmp_ctx);
+ if (trpc==NULL) {
+ tr_crit("tr_trpc_initiate: could not allocate TRPC_INSTANCE.");
+ goto cleanup;
+ }
+ tr_debug("tr_trpc_initiate: allocated trpc");
+
+ conn=trp_connection_new(trpc);
+ if (conn==NULL) {
+ tr_crit("tr_trpc_initiate: could not allocate TRP_CONNECTION.");
+ goto cleanup;
+ }
+ trpc_set_conn(trpc, conn);
+ 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 */
+ thread_data=talloc(trpc, struct trpc_thread_data);
+ if (thread_data==NULL) {
+ tr_crit("tr_trpc_initiate: could not allocate struct trpc_thread_data.");
+ goto cleanup;
+ }
+ thread_data->trpc=trpc;
+ thread_data->trps=trps;
+
+ pthread_create(trp_connection_get_thread(conn), NULL, tr_trpc_thread, thread_data);
+ pthread_detach(*(trp_connection_get_thread(conn))); /* we will not rejoin the thread */
+
+ tr_debug("tr_trpc_initiate: started trpc thread");
+ trps_add_trpc(trps, trpc);
+
+ 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_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);
+}
+