/* prototypes */
TRP_RC tr_trps_event_init(struct event_base *base, struct tr_instance *tr);
TRP_RC tr_add_local_routes(TRPS_INSTANCE *trps, TR_CFG *cfg);
-TRP_RC tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer);
+TRP_RC tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer, struct event *ev);
void tr_config_changed(TR_CFG *new_cfg, void *cookie);
-TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps);
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps, struct event *ev);
#endif /* TR_TRP_H */
TRP_RC trps_sweep_routes(TRPS_INSTANCE *trps);
TRP_RC trps_add_route(TRPS_INSTANCE *trps, TRP_ROUTE *route);
TRP_RC trps_add_peer(TRPS_INSTANCE *trps, TRP_PEER *peer);
-TRP_PEER *trps_get_peer(TRPS_INSTANCE *trps, TR_NAME *gssname);
+TRP_PEER *trps_get_peer_by_gssname(TRPS_INSTANCE *trps, TR_NAME *gssname);
+TRP_PEER *trps_get_peer_by_servicename(TRPS_INSTANCE *trps, TR_NAME *servicename);
TRP_RC trps_update(TRPS_INSTANCE *trps, TRP_UPDATE_TYPE type);
int trps_peer_connected(TRPS_INSTANCE *trps, TRP_PEER *peer);
+TRP_RC trps_wildcard_route_req(TRPS_INSTANCE *trps, TR_NAME *peer_gssname);
#endif /* TRP_INTERNAL_H */
TRP_PEER *next; /* for making a linked list */
char *server;
TR_NAME *gssname;
+ TR_NAME *servicename;
unsigned int port;
unsigned int linkcost;
struct timespec last_conn_attempt;
void trp_ptable_free(TRP_PTABLE *ptbl);
TRP_RC trp_ptable_add(TRP_PTABLE *ptbl, TRP_PEER *newpeer);
TRP_RC trp_ptable_remove(TRP_PTABLE *ptbl, TRP_PEER *peer);
-TRP_PEER *trp_ptable_find(TRP_PTABLE *ptbl, TR_NAME *gssname);
+TRP_PEER *trp_ptable_find_gssname(TRP_PTABLE *ptbl, TR_NAME *gssname);
+TRP_PEER *trp_ptable_find_servicename(TRP_PTABLE *ptbl, TR_NAME *servicename);
char *trp_ptable_to_str(TALLOC_CTX *memctx, TRP_PTABLE *ptbl, const char *sep, const char *lineterm);
TRP_PTABLE_ITER *trp_ptable_iter_new(TALLOC_CTX *mem_ctx);
void trp_peer_set_gssname(TRP_PEER *peer, TR_NAME *gssname);
TR_NAME *trp_peer_get_gssname(TRP_PEER *peer);
TR_NAME *trp_peer_dup_gssname(TRP_PEER *peer);
+TR_NAME *trp_peer_get_servicename(TRP_PEER *peer);
+TR_NAME *trp_peer_dup_servicename(TRP_PEER *peer);
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);
TR_EXPORT TR_NAME *trp_req_get_peer(TRP_REQ *req);
void trp_req_set_peer(TRP_REQ *req, TR_NAME *peer);
int trp_req_is_wildcard(TRP_REQ *req);
+TRP_RC trp_req_make_wildcard(TRP_REQ *req);
#endif /* TRP_H */
}
/* look up the TRPS peer matching the GSS name */
- if (NULL==trps_get_peer(trps, &name)) {
+ if (NULL==trps_get_peer_by_gssname(trps, &name)) {
tr_warning("tr_trps_gss_handler: Connection attempt from unknown peer (GSS name: %.*s).", name.len, name.buf);
return -1;
}
struct event *ev=cookie->ev;
tr_debug("tr_connection_update: checking peer connections.");
- tr_connect_to_peers(trps);
+ tr_connect_to_peers(trps, ev);
/* schedule the event to run again */
event_add(ev, &(trps->connect_interval));
}
TR_MQ_MSG *msg=NULL;
const char *msg_type=NULL;
char *encoded_msg=NULL;
+ TR_NAME *peer_gssname=NULL;
struct trpc_notify_cb_data cb_data={0,
PTHREAD_COND_INITIALIZER,
tr_mq_unlock(trpc->mq);
rc=trpc_connect(trpc);
-/* talloc_report_full(trpc, stderr);*/
if (rc!=TRP_SUCCESS) {
- /* was tr_notice --jlr */
- fprintf(stderr, "tr_trpc_thread: failed to initiate connection to %s:%d.",
- trpc_get_server(trpc),
- trpc_get_port(trpc));
- fflush(stderr);
+ tr_notice("tr_trpc_thread: failed to initiate connection to %s:%d.",
+ trpc_get_server(trpc),
+ trpc_get_port(trpc));
} else {
- tr_debug("tr_trpc_thread: connected to peer %s", trpc->conn->peer->buf);
- while (1) {
+ peer_gssname=tr_dup_name(trp_connection_get_peer(trpc_get_conn(trpc)));
+ if (peer_gssname==NULL) {
+ tr_err("tr_trpc_thread: could not duplicate peer_gssname.");
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ tr_debug("tr_trpc_thread: connected to peer %s", peer_gssname->buf);
+
+ while(1) {
cb_data.msg_ready=0;
pthread_cond_wait(&(cb_data.cond), &(cb_data.mutex));
/* verify the condition */
return entries;
}
+struct tr_wildcard_cookie {
+ TRPS_INSTANCE *trps;
+ TR_NAME *peer_servicename;
+};
+
+/* can only be called once, talloc_frees its argument cookie on termination */
+static void tr_send_wildcard(int listener, short event, void *arg)
+{
+ struct tr_wildcard_cookie *cook=talloc_get_type_abort(arg, struct tr_wildcard_cookie);
+
+ /* queue a route request for all route to every peer */
+ if (TRP_SUCCESS!=trps_wildcard_route_req(cook->trps, cook->peer_servicename))
+ tr_err("tr_send_wildcard: error sending wildcard route request.");
+
+ tr_free_name(cook->peer_servicename);
+ talloc_free(cook);
+}
+
struct tr_trpc_status_change_cookie {
+ struct event_base *evbase;
TRPS_INSTANCE *trps;
TRPC_INSTANCE *trpc;
TRP_PEER *peer;
static void tr_trpc_status_change(TRP_CONNECTION *conn, void *cookie)
{
struct tr_trpc_status_change_cookie *cook=talloc_get_type_abort(cookie, struct tr_trpc_status_change_cookie);
+ struct event_base *evbase=cook->evbase;
+ TRPS_INSTANCE *trps=cook->trps;
TRP_PEER *peer=cook->peer;
TR_NAME *gssname=trp_peer_get_gssname(peer);
-
- if (trp_connection_get_status(conn)==TRP_CONNECTION_UP)
+ struct timeval zero_time={0,0};
+ struct tr_wildcard_cookie *wc_cookie=NULL;
+
+ if (trp_connection_get_status(conn)==TRP_CONNECTION_UP) {
tr_debug("tr_trpc_status_change: connection to %.*s now up.", gssname->len, gssname->buf);
- else
+ /* add a one-off event to send a wildcard request from the main thread */
+ wc_cookie=talloc(trps, struct tr_wildcard_cookie);
+ if (wc_cookie==NULL) {
+ tr_err("tr_trpc_status_change: error allocating wildcard cookie.");
+ return;
+ }
+ wc_cookie->trps=trps;
+ wc_cookie->peer_servicename=trp_peer_dup_servicename(peer);
+ if (0!=event_base_once(evbase, -1, EV_TIMEOUT, tr_send_wildcard, wc_cookie, &zero_time)) {
+ tr_err("tr_trpc_status_change: error queueing wildcard route request event.");
+ }
+ } else
tr_debug("tr_trpc_status_change: connection to %.*s now down.", gssname->len, gssname->buf);
}
/* starts a trpc thread to connect to server:port */
-TRP_RC tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer)
+TRP_RC tr_trpc_initiate(TRPS_INSTANCE *trps, TRP_PEER *peer, struct event *ev)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
TRPC_INSTANCE *trpc=NULL;
rc=TRP_NOMEM;
goto cleanup;
}
+ status_change_cookie->evbase=event_get_base(ev);
status_change_cookie->trps=trps;
status_change_cookie->trpc=trpc;
status_change_cookie->peer=peer;
rc=TRP_SUCCESS;
cleanup:
- talloc_report_full(tmp_ctx, stderr);
talloc_free(tmp_ctx);
return rc;
}
}
/* open missing connections to peers */
-TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps)
+TRP_RC tr_connect_to_peers(TRPS_INSTANCE *trps, struct event *ev)
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
TRP_PTABLE_ITER *iter=trp_ptable_iter_new(tmp_ctx);
/* 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 */
- if (tr_trpc_initiate(trps, peer)!=TRP_SUCCESS) {
+ if (tr_trpc_initiate(trps, peer, ev)!=TRP_SUCCESS) {
tr_err("tr_connect_to_peers: unable to initiate TRP connection to %s:%u.",
trp_peer_get_server(peer),
trp_peer_get_port(peer));
- }
+ }
}
}
}
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,
if (conn->peer==NULL)
return TRP_ERROR;
-
+
+ tr_debug("trp_connection_set_peer: set peer for %p to %.*s (%p).", conn, conn->peer->len, conn->peer->buf, conn->peer);
return TRP_SUCCESS;
}
void trp_connection_close(TRP_CONNECTION *conn)
{
- close(trp_connection_get_fd(conn));
+ if ((conn->status!=TRP_CONNECTION_DOWN) && (conn->fd>0))
+ close(trp_connection_get_fd(conn));
trp_connection_set_fd(conn, -1);
trp_connection_set_status(conn, TRP_CONNECTION_DOWN);
}
&fd,
trp_connection_get_gssctx(conn));
if (err) {
- tr_debug("trp_connection_initiate: connection failed.");
+ tr_err("trp_connection_initiate: connection failed.");
return TRP_ERROR;
} else {
tr_debug("trp_connection_initiate: connected.");
trp_connection_set_fd(conn, fd);
- trp_connection_set_peer(conn);
+ if (trp_connection_set_peer(conn)!=TRP_SUCCESS) {
+ tr_err("trp_connection_initiate: error setting peer gssname.");
+ trp_connection_close(conn);
+ return TRP_ERROR;
+ }
trp_connection_set_status(conn, TRP_CONNECTION_UP);
return TRP_SUCCESS;
}
static int trp_peer_destructor(void *object)
{
TRP_PEER *peer=talloc_get_type_abort(object, TRP_PEER);
+ if (peer->servicename!=NULL)
+ tr_free_name(peer->servicename);
if (peer->gssname!=NULL)
tr_free_name(peer->gssname);
return 0;
if (peer!=NULL) {
peer->next=NULL;
peer->server=NULL;
+ peer->servicename=NULL;
peer->gssname=NULL;
peer->port=0;
peer->linkcost=TRP_LINKCOST_DEFAULT;
return peer->server;
}
+static void trp_peer_set_servicename(TRP_PEER *peer, const char *server)
+{
+ char *name=NULL;
+ if (peer->servicename !=NULL)
+ tr_free_name(peer->servicename);
+
+ if (server!=NULL)
+ name=talloc_asprintf(NULL, "trustrouter/%s", server);
+
+ if (name!=NULL) {
+ peer->servicename=tr_new_name(name);
+ talloc_free(name);
+ } else {
+ peer->servicename=NULL;
+ }
+}
+
/* copies input; on error, peer->gssname will be null */
void trp_peer_set_server(TRP_PEER *peer, char *server)
{
peer->server=talloc_strdup(peer, server); /* will be null on error */
+ trp_peer_set_servicename(peer, server);
}
void trp_peer_set_gssname(TRP_PEER *peer, TR_NAME *gssname)
return tr_dup_name(peer->gssname);
}
+/* get the service name (i.e., gssname we see when we connect to this peer) */
+TR_NAME *trp_peer_get_servicename(TRP_PEER *peer)
+{
+ return peer->servicename;
+}
+
+/* get a copy of the servicename, caller must free via tr_free_name */
+TR_NAME *trp_peer_dup_servicename(TRP_PEER *peer)
+{
+ return tr_dup_name(peer->servicename);
+}
+
unsigned int trp_peer_get_port(TRP_PEER *peer)
{
return peer->port;
return TRP_ERROR;
}
-TRP_PEER *trp_ptable_find(TRP_PTABLE *ptbl, TR_NAME *gssname)
+TRP_PEER *trp_ptable_find_gssname(TRP_PTABLE *ptbl, TR_NAME *gssname)
{
TRP_PEER *cur=ptbl->head;
while ((cur!=NULL) && (0 != tr_name_cmp(trp_peer_get_gssname(cur), gssname)))
return cur;
}
+TRP_PEER *trp_ptable_find_servicename(TRP_PTABLE *ptbl, TR_NAME *servicename)
+{
+ TRP_PEER *cur=ptbl->head;
+ while ((cur!=NULL) && (0 != tr_name_cmp(trp_peer_get_servicename(cur), servicename)))
+ cur=cur->next;
+ return cur;
+}
+
char *trp_peer_to_str(TALLOC_CTX *memctx, TRP_PEER *peer, const char *sep)
{
if (sep==NULL)
{
return (req!=NULL) && trp_req_name_is_wildcard(req->comm) && trp_req_name_is_wildcard(req->realm);
}
+
+TRP_RC trp_req_make_wildcard(TRP_REQ *req)
+{
+ if (req==NULL)
+ return TRP_BADARG;
+
+ req->comm=tr_new_name("");
+ if (req->comm==NULL)
+ return TRP_NOMEM;
+
+ req->realm=tr_new_name("");
+ if (req->realm==NULL) {
+ tr_free_name(req->comm);
+ req->comm=NULL;
+ return TRP_NOMEM;
+ }
+
+ return TRP_SUCCESS;
+}
trp_connection_close(conn);
} else {
tr_notice("trps_handle_connection: authorized connection");
-
+
/* loop as long as the connection exists */
while (trp_connection_get_status(conn)==TRP_CONNECTION_UP) {
rc=trps_read_message(trps, conn, &msg);
if (trp_route_is_local(route))
linkcost=0;
else {
- linkcost=trp_peer_get_linkcost(trps_get_peer(trps,
- trp_route_get_next_hop(route)));
+ linkcost=trp_peer_get_linkcost(trps_get_peer_by_gssname(trps,
+ trp_route_get_next_hop(route)));
}
/* Note that we leave the next hop empty since the recipient fills that in.
size_t n_updates=0, ii=0;
char *encoded=NULL;
TRP_RC rc=TRP_ERROR;
- TRP_PEER *peer=trps_get_peer(trps, peer_gssname);
+ TRP_PEER *peer=trps_get_peer_by_gssname(trps, peer_gssname);
if (!trps_peer_connected(trps, peer)) {
tr_debug("trps_update_one_peer: no TRP connection to %.*s, skipping.",
peer_gssname->len, peer_gssname->buf);
goto cleanup;
}
- if (update_type==TRP_UPDATE_TRIGGERED) {
+ switch (update_type) {
+ case TRP_UPDATE_TRIGGERED:
tr_debug("trps_update_one_peer: preparing triggered route update for %.*s",
peer_gssname->len, peer_gssname->buf);
- } else {
+ break;
+ case TRP_UPDATE_SCHEDULED:
tr_debug("trps_update_one_peer: preparing scheduled route update for %.*s",
peer_gssname->len, peer_gssname->buf);
+ break;
+ case TRP_UPDATE_REQUESTED:
+ tr_debug("trps_update_one_peer: preparing requested route update for %.*s",
+ peer_gssname->len, peer_gssname->buf);
}
- /* do not fill in peer, recipient does that */
+ /* do not fill in peer, recipient does that */
if ((comm==NULL) && (realm==NULL)) {
/* do all realms */
update_list=trps_select_updates_for_peer(tmp_ctx,
}
*update_list=trps_select_realm_update(trps, comm, realm, peer_gssname);
if (*update_list==NULL) {
- /* no update to send */
- rc=TRP_SUCCESS;
- goto cleanup;
+ /* we have no actual update to send back, MUST send a retraction */
+ tr_debug("trps_update_one_peer: community/realm without route requested, sending mandatory retraction.");
+ *update_list=trp_route_new(update_list);
+ trp_route_set_apc(*update_list, tr_dup_name(comm));
+ trp_route_set_realm(*update_list, tr_dup_name(realm));
+ trp_route_set_peer(*update_list, tr_new_name(""));
+ trp_route_set_metric(*update_list, TRP_METRIC_INFINITY);
+ trp_route_set_trust_router(*update_list, tr_new_name(""));
+ trp_route_set_next_hop(*update_list, tr_new_name(""));
}
n_updates=1;
} else {
else
tr_debug("trps_update_one_peer: update queued successfully.");
- encoded=NULL;
tr_msg_free_encoded(encoded);
+ encoded=NULL;
trp_upd_free(upd);
upd=NULL;
}
return trp_ptable_add(trps->ptable, peer);
}
-TRP_PEER *trps_get_peer(TRPS_INSTANCE *trps, TR_NAME *gssname)
+TRP_PEER *trps_get_peer_by_gssname(TRPS_INSTANCE *trps, TR_NAME *gssname)
{
- return trp_ptable_find(trps->ptable, gssname);
+ return trp_ptable_find_gssname(trps->ptable, gssname);
+}
+
+TRP_PEER *trps_get_peer_by_servicename(TRPS_INSTANCE *trps, TR_NAME *servicename)
+{
+ return trp_ptable_find_servicename(trps->ptable, servicename);
}
int trps_peer_connected(TRPS_INSTANCE *trps, TRP_PEER *peer)
}
}
+/* send wildcard route request to a peer */
+TRP_RC trps_wildcard_route_req(TRPS_INSTANCE *trps, TR_NAME *peer_servicename)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TRP_PEER *peer=trps_get_peer_by_servicename(trps, peer_servicename);
+ TR_MSG msg; /* not a pointer */
+ TRP_REQ *req=trp_req_new(tmp_ctx);
+ char *encoded=NULL;
+ TRP_RC rc=TRP_ERROR;
+
+ if (peer==NULL) {
+ tr_err("trps_wildcard_route_req: unknown peer (%.*s).", peer_servicename->len, peer_servicename->buf);
+ rc=TRP_BADARG;
+ goto cleanup;
+ }
+ if ((req==NULL) || (trp_req_make_wildcard(req)!=TRP_SUCCESS)) {
+ tr_err("trps_wildcard_route_req: unable to create wildcard TRP request.");
+ rc=TRP_NOMEM;
+ goto cleanup;
+ }
+
+ tr_msg_set_trp_req(&msg, req);
+ encoded=tr_msg_encode(&msg);
+ if (encoded==NULL) {
+ tr_err("trps_wildcard_route_req: error encoding wildcard TRP request.");
+ rc=TRP_ERROR;
+ goto cleanup;
+ }
+
+ tr_debug("trps_wildcard_route_req: adding message to queue.");
+ if (trps_send_msg(trps, peer, encoded) != TRP_SUCCESS) {
+ tr_err("trps_wildcard_route_req: error queueing request.");
+ rc=TRP_ERROR;
+ } else {
+ tr_debug("trps_wildcard_route_req: request queued successfully.");
+ rc=TRP_SUCCESS;
+ }
+ tr_crit("got here");
+cleanup:
+ if (encoded!=NULL)
+ tr_msg_free_encoded(encoded);
+ if (req!=NULL)
+ trp_req_free(req);
+
+ talloc_free(tmp_ctx);
+ return rc;
+}