{
TR_RESP_COOKIE *cookie=talloc_get_type_abort(resp_cookie, TR_RESP_COOKIE);
- tr_debug("tr_tidc_resp_handler: Response received! Realm = %s, Community = %s.",
+ tr_debug("tr_tidc_resp_handler: Response received! Realm = %s, Community = %s, result = %s.",
resp->realm->buf,
- resp->comm->buf);
-
- cookie->resp=tid_resp_dup(cookie, resp);
-}
-
-#if 0
-/* Old one, obsolete. */
+ resp->comm->buf,
+ (TID_SUCCESS==resp->result)?"success":"error");
-static void tr_tidc_resp_handler (TIDC_INSTANCE *tidc,
- TID_REQ *req,
- TID_RESP *resp,
- void *resp_cookie)
-{
- tr_debug("tr_tidc_resp_handler: Response received (conn = %d)! Realm = %s, Community = %s.", ((TR_RESP_COOKIE *)resp_cookie)->orig_req->conn, resp->realm->buf, resp->comm->buf);
- req->resp_rcvd = 1;
-
- /* TBD -- handle concatentation of multiple responses to single req */
- tids_send_response(((TR_RESP_COOKIE *)resp_cookie)->tids,
- ((TR_RESP_COOKIE *)resp_cookie)->orig_req,
- resp);
-
- return;
+ if (resp->error_path!=NULL)
+ tr_debug("tr_tids_resp_handler: error_path is set.");
+ cookie->resp=tid_resp_dup(cookie, resp);
}
-#endif /* 0 */
-
/* data for AAA req forwarding threads */
struct tr_tids_fwd_cookie {
{
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
struct tr_tids_fwd_cookie *args=talloc_get_type_abort(arg, struct tr_tids_fwd_cookie);
- TIDC_INSTANCE *tidc=tidc_create(tmp_ctx);
+ TIDC_INSTANCE *tidc=tidc_create();
TR_MQ_MSG *msg=NULL;
TR_RESP_COOKIE *cookie=NULL;
int rc=0;
talloc_steal(tmp_ctx, args); /* take responsibility for the cookie */
+ if (tidc!=NULL)
+ talloc_steal(tmp_ctx, tidc);
+
/* create the cookie we will use for our response */
cookie=talloc(tmp_ctx, TR_RESP_COOKIE);
if (cookie==NULL) {
goto cleanup;
}
cookie->thread_id=args->thread_id;
+ tr_debug("tr_tids_req_fwd_thread: thread %d started.", cookie->thread_id);
/* Create a TID client instance */
if (tidc==NULL) {
success=0;
goto cleanup;
};
+ tr_debug("tr_tids_req_fwd_thread: thread %d opened TID connection to %s.",
+ cookie->thread_id,
+ args->aaa_hostname->buf);
/* Send a TID request. */
if (0 > (rc = tidc_fwd_request(tidc, args->fwd_req, tr_tidc_resp_handler, (void *)cookie))) {
}
/* cookie->resp should now contain our copy of the response */
success=1;
+ tr_debug("tr_tids_req_fwd_thread: thread %d received response.");
cleanup:
/* Notify parent thread of the response, if it's still listening. */
if (0!=tr_tids_fwd_get_mutex(args)) {
- tr_notice("tr_tids_req_fwd_thread: Error acquiring mutex.");
+ tr_notice("tr_tids_req_fwd_thread: thread %d unable to acquire mutex.", cookie->thread_id);
} else if (NULL!=args->mq) {
/* mq is still valid, so we can queue our response */
+ tr_debug("tr_tids_req_fwd_thread: thread %d using valid msg queue.", cookie->thread_id);
if (success)
msg=tr_mq_msg_new(tmp_ctx, TR_TID_MQMSG_SUCCESS, TR_MQ_PRIO_NORMAL);
else
msg=tr_mq_msg_new(tmp_ctx, TR_TID_MQMSG_FAILURE, TR_MQ_PRIO_NORMAL);
if (msg==NULL)
- tr_notice("tr_tids_req_fwd_thread: unable to allocate response msg.");
+ tr_notice("tr_tids_req_fwd_thread: thread %d unable to allocate response msg.", cookie->thread_id);
tr_mq_msg_set_payload(msg, (void *)cookie, NULL);
if (NULL!=cookie)
talloc_steal(msg, cookie); /* attach this to the msg so we can forget about it */
tr_mq_add(args->mq, msg);
talloc_steal(NULL, args); /* take out of our tmp_ctx; master thread now responsible for freeing */
+ tr_debug("tr_tids_req_fwd_thread: thread %d queued response message.", cookie->thread_id);
if (0!=tr_tids_fwd_release_mutex(args))
tr_notice("tr_tids_req_fwd_thread: Error releasing mutex.");
}
if ((r1->result!=TID_SUCCESS) || (r2->result!=TID_SUCCESS))
return TID_ERROR;
- if (r1==NULL) tr_debug("******* r1 null");
- if (r1->realm==NULL) tr_debug("******* r1->realm null");
- if (r1->rp_realm==NULL) tr_debug("******* r1->rp_realm null");
- if (r1->comm==NULL) tr_debug("******* r1->comm null");
- if (r2==NULL) tr_debug("******* r2 null");
- if (r2->realm==NULL) tr_debug("******* r2->realm null");
- if (r2->rp_realm==NULL) tr_debug("******* r2->rp_realm null");
- if (r2->comm==NULL) tr_debug("******* r2->comm null");
-
if ((0!=tr_name_cmp(r1->rp_realm, r2->rp_realm)) ||
(0!=tr_name_cmp(r1->realm, r2->realm)) ||
(0!=tr_name_cmp(r1->comm, r2->comm)))
TR_AAA_SERVER_ITER *aaa_iter=NULL;
pthread_t aaa_thread[TR_TID_MAX_AAA_SERVERS];
struct tr_tids_fwd_cookie *aaa_cookie[TR_TID_MAX_AAA_SERVERS]={NULL};
+ TID_RESP *aaa_resp[TR_TID_MAX_AAA_SERVERS]={NULL};
TR_NAME *apc = NULL;
TID_REQ *fwd_req = NULL;
TR_COMM *cfg_comm = NULL;
tids->req_count++;
/* Duplicate the request, so we can modify and forward it */
- if (NULL == (fwd_req=tid_dup_req(tmp_ctx, orig_req))) {
+ if (NULL == (fwd_req=tid_dup_req(orig_req))) {
tr_debug("tr_tids_req_handler: Unable to duplicate request.");
retval=-1;
goto cleanup;
}
+ talloc_steal(tmp_ctx, fwd_req);
if (NULL == (cfg_comm=tr_comm_table_find_comm(cfg_mgr->active->ctable, orig_req->comm))) {
tr_notice("tr_tids_req_hander: Request for unknown comm: %s.", orig_req->comm->buf);
}
/* send a TID request to the AAA server(s), and get the answer(s) */
+ tr_debug("tr_tids_req_handler: sending TID request(s).");
if (cfg_apc)
expiration_interval = cfg_apc->expiration_interval;
else expiration_interval = cfg_comm->expiration_interval;
retval=-1;
goto cleanup;
}
+ tr_debug("tr_tids_req_handler: message queue allocated.");
/* start threads */
aaa_iter=tr_aaa_server_iter_new(tmp_ctx);
for (n_aaa=0, this_aaa=tr_aaa_server_iter_first(aaa_iter, aaa_servers);
this_aaa!=NULL;
n_aaa++, this_aaa=tr_aaa_server_iter_next(aaa_iter)) {
+ tr_debug("tr_tids_req_handler: Preparing to start thread %d.", n_aaa);
+
aaa_cookie[n_aaa]=talloc(tmp_ctx, struct tr_tids_fwd_cookie);
if (aaa_cookie[n_aaa]==NULL) {
tr_notice("tr_tids_req_handler: unable to allocate cookie for AAA thread %d.", n_aaa);
aaa_cookie[n_aaa]->mq=mq;
aaa_cookie[n_aaa]->aaa_hostname=tr_dup_name(this_aaa->hostname);
aaa_cookie[n_aaa]->dh_params=tr_dh_dup(orig_req->tidc_dh);
- aaa_cookie[n_aaa]->fwd_req=tid_dup_req(aaa_cookie[n_aaa], fwd_req);
+ aaa_cookie[n_aaa]->fwd_req=tid_dup_req(fwd_req);
+ talloc_steal(aaa_cookie[n_aaa], aaa_cookie[n_aaa]->fwd_req);
+ tr_debug("tr_tids_req_handler: cookie %d initialized.", n_aaa);
/* Take the cookie out of tmp_ctx before starting thread. If thread starts, it becomes
- * responsible for freeing it until it queues a response. */
+ * responsible for freeing it until it queues a response. If we did not do this, the possibility
+ * exists that this function exits, freeing the cookie, before the thread takes the cookie
+ * out of our tmp_ctx. This would cause a segfault or talloc error in the thread. */
talloc_steal(NULL, aaa_cookie[n_aaa]);
if (0!=pthread_create(&(aaa_thread[n_aaa]), NULL, tr_tids_req_fwd_thread, aaa_cookie[n_aaa])) {
talloc_steal(tmp_ctx, aaa_cookie[n_aaa]); /* thread start failed; steal this back */
retval=-1;
goto cleanup;
}
+ tr_debug("tr_tids_req_handler: thread %d started.", n_aaa);
}
-
+
/* determine expiration time */
if (0!=tr_mq_pop_timeout(cfg_mgr->active->internal->tid_req_timeout, &ts_abort)) {
tr_notice("tr_tids_req_handler: unable to read clock for timeout.");
}
/* wait for responses */
+ tr_debug("tr_tids_req_handler: waiting for response(s).");
n_responses=0;
n_failed=0;
while (((n_responses+n_failed)<n_aaa) &&
/* process message */
if (0==strcmp(tr_mq_msg_get_message(msg), TR_TID_MQMSG_SUCCESS)) {
payload=talloc_get_type_abort(tr_mq_msg_get_payload(msg), TR_RESP_COOKIE);
+ talloc_steal(tmp_ctx, payload); /* put this back in our context */
+ aaa_resp[payload->thread_id]=payload->resp; /* save pointers to these */
+
if (payload->resp->result==TID_SUCCESS) {
tr_tids_merge_resps(resp, payload->resp);
n_responses++;
/* failure */
n_failed++;
payload=talloc_get_type(tr_mq_msg_get_payload(msg), TR_RESP_COOKIE);
- if (payload==NULL) {
+ if (payload!=NULL)
+ talloc_steal(tmp_ctx, payload); /* put this back in our context */
+ else {
/* this means the thread was unable to allocate a response cookie, and we thus cannot determine which thread it was. This is bad and should never happen in a working system.. Give up. */
tr_notice("tr_tids_req_handler: TID request thread sent invalid reply. Aborting!");
retval=-1;
goto cleanup;
}
- /* Now free the cookie for this thread. Null it so we know we've dealt with it. */
- talloc_free(aaa_cookie[payload->thread_id]);
+ /* Set the cookie pointer to NULL so we know we've dealt with this one. The
+ * cookie itself is in our tmp_ctx, which we'll free before exiting. Let it hang
+ * around in case we are still using pointers to elements of the cookie. */
aaa_cookie[payload->thread_id]=NULL;
tr_mq_msg_free(msg);
break;
}
+ tr_debug("tr_tids_req_handler: done waiting for responses. %d responses, %d failures.",
+ n_responses, n_failed);
/* Inform any remaining threads that we will no longer handle their responses. */
for (ii=0; ii<n_aaa; ii++) {
if (aaa_cookie[ii]!=NULL) {
* reply (by setting their mq pointer to null). However, some may have responded by placing
* a message on the mq after we last checked but before we set their mq pointer to null. These
* will not know that we gave up on them, so we must free their cookies for them. We can just
- * go through any remaining messages on the mq to identify these threads. */
+ * go through any remaining messages on the mq to identify these threads. By putting them in
+ * our context instead of freeing them directly, we ensure we don't accidentally invalidate
+ * any of our own pointers into the structure before this function exits. */
while (NULL!=(msg=tr_mq_pop(mq, NULL))) {
payload=(TR_RESP_COOKIE *)tr_mq_msg_get_payload(msg);
if (aaa_cookie[payload->thread_id]!=NULL)
- talloc_free(aaa_cookie[payload->thread_id]);
+ talloc_steal(tmp_ctx, aaa_cookie[payload->thread_id]);
tr_mq_msg_free(msg);
}
if (n_responses==0) {
- tid_resp_set_result(resp, TID_ERROR);
- tid_resp_set_err_msg(resp, tr_new_name("No successful response from AAA server(s)."));
- tid_resp_set_error_path(resp, orig_req->path);
+ /* No requests succeeded. Forward an error if we got any error responses. */
+ for (ii=0; ii<n_aaa; ii++) {
+ if (aaa_resp[ii]!=NULL)
+ tids_send_response(tids, orig_req, aaa_resp[ii]);
+ else
+ tids_send_err_response(tids, orig_req, "Unable to contact AAA server(s).");
+ }
}
/* success! */