182
184
tr_debug("tr_trps_event_cb: unexpected event on TRPS socket (event=0x%X)", event);
184
186
/* create a thread to handle this connection */
185
if (asprintf(&name, "trustrouter@%s", trps->hostname)==-1) {
187
name = talloc_asprintf(tmp_ctx, "trustrouter@%s", trps->hostname);
188
gssname=tr_new_name(name);
189
free(name); name=NULL;
190
conn=trp_connection_accept(tmp_ctx, listener, gssname);
190
gssname=tr_new_name(name); /* name cleaned up with tmp_ctx but need to handl gssname ourselves */
192
conn=trp_connection_accept(tmp_ctx, listener, gssname); /* steals gssname unless it fails */
194
tr_free_name(gssname);
192
196
/* need to monitor this fd and trigger events when read becomes possible */
193
197
thread_data=talloc(conn, struct trps_thread_data);
194
198
if (thread_data==NULL) {
195
199
tr_err("tr_trps_event_cb: unable to allocate trps_thread_data");
196
talloc_free(tmp_ctx);
199
202
thread_data->conn=conn;
200
203
thread_data->trps=trps;
201
trps_add_connection(trps, conn); /* remember the connection */
204
trps_add_connection(trps, conn); /* remember the connection - this puts conn and the thread data in trps's talloc context */
202
205
pthread_create(trp_connection_get_thread(conn), NULL, tr_trps_thread, thread_data);
266
269
TRPS_INSTANCE *trps=talloc_get_type_abort(arg, TRPS_INSTANCE);
267
270
TR_MQ_MSG *msg=NULL;
268
271
const char *s=NULL;
272
TRP_PEER *peer = NULL;
270
275
msg=trps_mq_pop(trps);
271
276
while (msg!=NULL) {
272
277
s=tr_mq_msg_get_message(msg);
273
278
if (0==strcmp(s, TR_MQMSG_TRPS_CONNECTED)) {
274
TR_NAME *gssname=(TR_NAME *)tr_mq_msg_get_payload(msg);
275
TRP_PEER *peer=trps_get_peer_by_gssname(trps, gssname);
277
tr_err("tr_trps_process_mq: incoming connection from unknown peer (%s) reported.", gssname->buf);
279
trp_peer_set_incoming_status(peer, PEER_CONNECTED);
280
tr_err("tr_trps_process_mq: incoming connection from %s established.", gssname->buf);
279
TR_NAME *peer_gssname=(TR_NAME *)tr_mq_msg_get_payload(msg);
280
if (NULL == peer_gssname) {
281
/* This should not happen, we should not be able to establish a connection if we do not
282
* know their GSS name */
283
tr_err("tr_trps_process_mq: incoming connection from unknown GSS name reported.");
285
peer = trps_get_peer_by_gssname(trps, peer_gssname); /* get the peer record */
286
tmp = tr_name_strdup(peer_gssname); /* get the name as a null-terminated string */
288
tr_err("tr_trps_process_mq: incoming connection from unknown peer (%s) reported.", tmp);
290
trp_peer_set_incoming_status(peer, PEER_CONNECTED);
291
tr_info("tr_trps_process_mq: incoming connection from %s established.", tmp);
283
296
else if (0==strcmp(s, TR_MQMSG_TRPS_DISCONNECTED)) {
284
297
TRP_CONNECTION *conn=talloc_get_type_abort(tr_mq_msg_get_payload(msg), TRP_CONNECTION);
285
TR_NAME *gssname=trp_connection_get_gssname(conn);
286
TRP_PEER *peer=trps_get_peer_by_gssname(trps, gssname);
288
tr_err("tr_trps_process_mq: incoming connection from unknown peer (%s) lost.",
289
trp_connection_get_gssname(conn)->buf);
298
TR_NAME *peer_gssname=trp_connection_get_peer(conn);
300
if (NULL == peer_gssname) {
301
/* If the GSS auth failed, then we don't know the peer's GSS name. */
302
tr_info("tr_trps_process_mq: incoming connection failed to auth.");
291
trp_peer_set_incoming_status(peer, PEER_DISCONNECTED);
292
tr_trps_cleanup_conn(trps, conn);
293
tr_err("tr_trps_process_mq: incoming connection from %s lost.", gssname->buf);
304
/* We do know the peer's GSS name, see if we recognize it. */
305
peer = trps_get_peer_by_gssname(trps, peer_gssname); /* get the peer record */
306
tmp = tr_name_strdup(peer_gssname); /* get the name as a null-terminated string */
308
tr_err("tr_trps_process_mq: incoming connection from unknown peer (%.*s) lost.", tmp);
310
trp_peer_set_incoming_status(peer, PEER_DISCONNECTED);
311
tr_trps_cleanup_conn(trps, conn);
312
tr_info("tr_trps_process_mq: incoming connection from %s lost.", tmp);
296
317
else if (0==strcmp(s, TR_MQMSG_TRPC_CONNECTED)) {
297
318
TR_NAME *svcname=(TR_NAME *)tr_mq_msg_get_payload(msg);
298
TRP_PEER *peer=trps_get_peer_by_servicename(trps, svcname);
300
tr_err("tr_trps_process_mq: outgoing connection to unknown peer (%s) reported.", svcname->buf);
302
trp_peer_set_outgoing_status(peer, PEER_CONNECTED);
303
tr_err("tr_trps_process_mq: outgoing connection to %s established.", svcname->buf);
319
if (NULL == svcname) {
320
/* This should not happen because we shouldn't be reporting a connection unless we were
321
* able to auth the service name. */
322
tr_err("tr_trps_process_mq: outgoing connection established to unknown GSS service name.");
324
peer = trps_get_peer_by_servicename(trps, svcname);
325
tmp = tr_name_strdup(svcname);
327
tr_err("tr_trps_process_mq: outgoing connection to unknown peer (%s) reported.", tmp);
329
trp_peer_set_outgoing_status(peer, PEER_CONNECTED);
330
tr_info("tr_trps_process_mq: outgoing connection to %s established.", tmp);
306
335
else if (0==strcmp(s, TR_MQMSG_TRPC_DISCONNECTED)) {
307
/* trpc connection died */
308
336
TRPC_INSTANCE *trpc=talloc_get_type_abort(tr_mq_msg_get_payload(msg), TRPC_INSTANCE);
309
TR_NAME *gssname=trpc_get_gssname(trpc);
310
TRP_PEER *peer=trps_get_peer_by_servicename(trps, gssname);
312
tr_err("tr_trps_process_mq: outgoing connection to unknown peer (%s) lost.", gssname->buf);
314
trp_peer_set_outgoing_status(peer, PEER_DISCONNECTED);
315
tr_err("tr_trps_process_mq: outgoing connection to %s lost.", gssname->buf);
316
tr_trps_cleanup_trpc(trps, trpc);
337
TR_NAME *svcname=trpc_get_gssname(trpc);
338
if (NULL == svcname) {
339
tr_info("tr_trps_process_mq: outgoing connection to unknown GSS service name lost.");
341
peer = trps_get_peer_by_servicename(trps, svcname);
342
tmp = tr_name_strdup(svcname);
344
tr_err("tr_trps_process_mq: outgoing connection to unknown peer (%s) lost.", tmp);
346
trp_peer_set_outgoing_status(peer, PEER_DISCONNECTED);
347
tr_info("tr_trps_process_mq: outgoing connection to %s lost.", tmp);
348
tr_trps_cleanup_trpc(trps, trpc);
320
354
else if (0==strcmp(s, TR_MQMSG_MSG_RECEIVED)) {
321
355
if (trps_handle_tr_msg(trps, tr_mq_msg_get_payload(msg))!=TRP_SUCCESS)
322
tr_notice("tr_trps_process_mq: error handling message.");
356
tr_err("tr_trps_process_mq: error handling message.");
325
359
tr_notice("tr_trps_process_mq: unknown message '%s' received.", tr_mq_msg_get_message(msg));
552
struct trpc_notify_cb_data {
555
pthread_mutex_t mutex;
558
static void tr_trpc_mq_cb(TR_MQ *mq, void *arg)
560
struct trpc_notify_cb_data *cb_data=(struct trpc_notify_cb_data *) arg;
561
pthread_mutex_lock(&(cb_data->mutex));
562
if (!cb_data->msg_ready) {
563
cb_data->msg_ready=1;
564
pthread_cond_signal(&(cb_data->cond));
566
pthread_mutex_unlock(&(cb_data->mutex));
569
585
/* data passed to thread */
570
586
struct trpc_thread_data {
571
587
TRPC_INSTANCE *trpc;
572
588
TRPS_INSTANCE *trps;
592
* Thread for handling TRPC (outgoing) connections
594
* Opens a connection to a peer. If successful, notifies the trps thread by
595
* posting a TR_MQMSG_TRPC_CONNECTED message to the trps message queue.
596
* It then waits for messages on trpc->mq. Normally these will be TR_MQMSG_TRPC_SEND
597
* messages, which this thread forwards to the peer. If its connection is lost or
598
* a TR_MQMSG_ABORT message is received on trpc->mq, the thread sends a
599
* TR_MQMSG_TRPC_DISCONNECTED message to the trps thread, then cleans up and
602
* The trps may continue queueing messages for this client even when the
603
* connection is down. To prevent the queue from growing endlessly, this thread
604
* should clear its queue after failed connection attempts.
574
606
static void *tr_trpc_thread(void *arg)
576
608
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
582
614
const char *msg_type=NULL;
583
615
char *encoded_msg=NULL;
584
616
TR_NAME *peer_gssname=NULL;
617
struct timespec wait_until = {0};
588
struct trpc_notify_cb_data cb_data={0,
589
PTHREAD_COND_INITIALIZER,
590
PTHREAD_MUTEX_INITIALIZER};
592
620
tr_debug("tr_trpc_thread: started");
594
/* set up the mq for receiving */
595
pthread_mutex_lock(&(cb_data.mutex)); /* hold this lock until we enter the main loop */
597
tr_mq_lock(trpc->mq);
598
tr_mq_set_notify_cb(trpc->mq, tr_trpc_mq_cb, (void *) &cb_data);
599
tr_mq_unlock(trpc->mq);
622
/* Try to make the outgoing connection */
601
623
rc=trpc_connect(trpc);
602
624
if (rc!=TRP_SUCCESS) {
603
625
tr_notice("tr_trpc_thread: failed to initiate connection to %s:%d.",
604
626
trpc_get_server(trpc),
605
627
trpc_get_port(trpc));
628
trpc_mq_clear(trpc); /* clear the queue even though we did not connect */
630
/* Retrieve the GSS name used by the peer for authentication */
607
631
peer_gssname=trp_connection_get_peer(trpc_get_conn(trpc));
608
632
if (peer_gssname==NULL) {
609
633
tr_err("tr_trpc_thread: could not duplicate peer_gssname.");
610
634
talloc_free(tmp_ctx);
613
tr_debug("tr_trpc_thread: connected to peer %s", peer_gssname->buf);
637
tr_debug("tr_trpc_thread: connected to peer %.*s",
638
peer_gssname->len, peer_gssname->buf);
615
msg=tr_mq_msg_new(tmp_ctx, TR_MQMSG_TRPC_CONNECTED, TR_MQ_PRIO_HIGH);
640
msg= tr_mq_msg_new(tmp_ctx, TR_MQMSG_TRPC_CONNECTED);
616
641
tr_mq_msg_set_payload(msg, (void *)tr_dup_name(peer_gssname), tr_free_name_helper);
618
643
tr_err("tr_trpc_thread: error allocating TR_MQ_MSG");
622
647
trps_mq_add(trps, msg); /* steals msg context */
650
/* Loop until we get an abort message or until the connection is lost. */
625
651
while(!exit_loop) {
627
pthread_cond_wait(&(cb_data.cond), &(cb_data.mutex));
628
/* verify the condition */
629
if (cb_data.msg_ready) {
630
for (msg=trpc_mq_pop(trpc),n_sent=0; msg!=NULL; msg=trpc_mq_pop(trpc),n_sent++) {
631
msg_type=tr_mq_msg_get_message(msg);
652
/* Wait up to 10 minutes for a message to be queued to send to the peer.
653
* Log a warning if we go longer than that, but don't give up. */
654
if (tr_mq_pop_timeout(10 * 60, &wait_until) != 0) {
655
tr_err("tr_trpc_thread: unable to set abort timeout");
656
break; /* immediately exit the loop, don't go through cleanup */
633
if (0==strcmp(msg_type, TR_MQMSG_ABORT)) {
637
else if (0==strcmp(msg_type, TR_MQMSG_TRPC_SEND)) {
638
encoded_msg=tr_mq_msg_get_payload(msg);
639
if (encoded_msg==NULL)
640
tr_notice("tr_trpc_thread: null outgoing TRP message.");
642
rc = trpc_send_msg(trpc, encoded_msg);
643
if (rc!=TRP_SUCCESS) {
644
tr_notice("tr_trpc_thread: trpc_send_msg failed.");
659
/* Pop a message from the queue. */
660
msg = trpc_mq_pop(trpc, &wait_until);
662
msg_type = tr_mq_msg_get_message(msg);
663
if (0 == strcmp(msg_type, TR_MQMSG_ABORT)) {
664
tr_debug("tr_trpc_thread: received abort message from main thread.");
666
} else if (0 == strcmp(msg_type, TR_MQMSG_TRPC_SEND)) {
667
encoded_msg = tr_mq_msg_get_payload(msg);
668
if (encoded_msg == NULL)
669
tr_notice("tr_trpc_thread: null outgoing TRP message.");
671
rc = trpc_send_msg(trpc, encoded_msg);
672
if (rc == TRP_SUCCESS) {
673
tr_debug("tr_trpc_thread: sent message.");
675
tr_notice("tr_trpc_thread: trpc_send_msg failed.");
676
/* Assume this means we lost the connection. */
651
tr_notice("tr_trpc_thread: unknown message '%s' received.", msg_type);
681
tr_notice("tr_trpc_thread: unknown message '%s' received.", msg_type);
656
tr_err("tr_trpc_thread: notified of msg, but queue empty");
658
tr_debug("tr_trpc_thread: sent %d messages.", n_sent);
685
tr_warning("tr_trpc_thread: no outgoing messages to %.*s for 10 minutes",
686
peer_gssname->len, peer_gssname->buf);
663
tr_debug("tr_trpc_thread: exiting.");
664
msg=tr_mq_msg_new(tmp_ctx, TR_MQMSG_TRPC_DISCONNECTED, TR_MQ_PRIO_HIGH);
691
/* Send a DISCONNECTED message to the main thread */
692
msg= tr_mq_msg_new(tmp_ctx, TR_MQMSG_TRPC_DISCONNECTED);
665
693
tr_mq_msg_set_payload(msg, (void *)trpc, NULL); /* do not pass a free routine */
695
/* can't notify main thread */
667
696
tr_err("tr_trpc_thread: error allocating TR_MQ_MSG");
669
698
trps_mq_add(trps, msg);
671
trpc_mq_clear(trpc); /* clear any queued messages */
673
701
talloc_free(tmp_ctx);
702
tr_debug("tr_trpc_thread: thread terminating.");
677
/* convert an IDP realm into routing table entries. Outputs number in *n_routes */
707
* convert an IDP realm into routing table entries.
709
* @param mem_ctx talloc context for the result
710
* @param realm IDP realm whose routes should be generated
711
* @param trust_router hostname for TRP connections to us
712
* @param trust_router_port TRP port of our trust router
713
* @param n_routes (output) the number of routes in the returned array
714
* @return Pointer to an array of pointers to routes
678
716
static TRP_ROUTE **tr_make_local_routes(TALLOC_CTX *mem_ctx,
718
const char *trust_router,
719
int trust_router_port,
683
722
TALLOC_CTX *tmp_ctx=talloc_new(NULL);
684
723
TR_APC *comm=NULL;
870
906
tr->cfgwatch->settling_time.tv_sec=new_cfg->internal->cfg_settling_time;
871
907
tr->cfgwatch->settling_time.tv_usec=0;
909
/* These need to be updated */
910
tr->tids->hostname = new_cfg->internal->hostname;
911
tr->mons->hostname = new_cfg->internal->hostname;
913
/* Update the authorized monitoring gss names */
914
if (tr->mons->authorized_gss_names) {
915
tr_debug("tr_config_changed: freeing tr->mons->authorized_gss_names");
916
tr_gss_names_free(tr->mons->authorized_gss_names);
918
if (new_cfg->internal->monitoring_credentials != NULL) {
919
tr->mons->authorized_gss_names = tr_gss_names_dup(tr->mons, new_cfg->internal->monitoring_credentials);
921
tr->mons->authorized_gss_names = tr_gss_names_new(tr->mons);
923
if (tr->mons->authorized_gss_names == NULL) {
924
tr_err("tr_config_changed: Error configuring monitoring credentials");
873
927
trps_set_connect_interval(trps, new_cfg->internal->trp_connect_interval);
874
928
trps_set_update_interval(trps, new_cfg->internal->trp_update_interval);
875
929
trps_set_sweep_interval(trps, new_cfg->internal->trp_sweep_interval);