+ if (cookie==NULL)
+ return -1;
+
+ return (pthread_mutex_unlock(&(cookie->mutex)));
+}
+
+/* values for messages */
+#define TR_TID_MQMSG_SUCCESS "tid success"
+#define TR_TID_MQMSG_FAILURE "tid failure"
+
+/* Thread main for sending and receiving a request to a single AAA server */
+static void *tr_tids_req_fwd_thread(void *arg)
+{
+ 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();
+ TR_MQ_MSG *msg=NULL;
+ TR_RESP_COOKIE *cookie=NULL;
+ int rc=0;
+ int success=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) {
+ tr_notice("tr_tids_req_fwd_thread: unable to allocate response cookie.");
+ success=0;
+ 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) {
+ tr_crit("tr_tids_req_fwd_thread: Unable to allocate TIDC instance.");
+ /*tids_send_err_response(tids, orig_req, "Memory allocation failure");*/
+ /* TODO: encode reason for failure */
+ success=0;
+ goto cleanup;
+ }
+
+ /* Set-up TID connection */
+ if (-1==(args->fwd_req->conn = tidc_open_connection(tidc,
+ args->aaa_hostname->buf,
+ TID_PORT, /* TODO: make this configurable */
+ &(args->fwd_req->gssctx)))) {
+ tr_notice("tr_tids_req_fwd_thread: Error in tidc_open_connection.");
+ /* tids_send_err_response(tids, orig_req, "Can't open connection to next hop TIDS"); */
+ /* TODO: encode reason for failure */
+ 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))) {
+ tr_notice("Error from tidc_fwd_request, rc = %d.", rc);
+ success=0;
+ goto cleanup;
+ }
+ /* 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: 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: 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.");
+ }
+
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+/* Merges r2 into r1 if they are compatible. */
+static TID_RC tr_tids_merge_resps(TID_RESP *r1, TID_RESP *r2)
+{
+ /* ensure these are compatible replies */
+ if ((r1->result!=TID_SUCCESS) || (r2->result!=TID_SUCCESS))
+ return TID_ERROR;
+
+ 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)))
+ return TID_ERROR;
+
+ tid_srvr_blk_add(r1->servers, tid_srvr_blk_dup(r1, r2->servers));
+ return TID_SUCCESS;
+}
+
+/**
+ * Process a TID request
+ *
+ * Return value of -1 means to send a TID_ERROR response. Fill in resp->err_msg or it will
+ * be returned as a generic error.
+ *
+ * @param tids
+ * @param orig_req
+ * @param resp
+ * @param cookie_in
+ * @return
+ */
+static int tr_tids_req_handler(TIDS_INSTANCE *tids,
+ TID_REQ *orig_req,
+ TID_RESP *resp,
+ void *cookie_in)
+{
+ TALLOC_CTX *tmp_ctx=talloc_new(NULL);
+ TR_AAA_SERVER *aaa_servers=NULL, *this_aaa=NULL;
+ int n_aaa=0;
+ int idp_shared=0;
+ 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_RP_CLIENT *rp_client=NULL;
+ TR_RP_CLIENT_ITER *rpc_iter=NULL;