Index: libfdcore/config.c
===================================================================
--- libfdcore/config.c	(revision 1107)
+++ libfdcore/config.c	(revision 1113)
@@ -85,5 +85,5 @@
 	FD_DUMP_HANDLE_OFFSET();
 	
-	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{freeDiameter configuration}(@%p): \n", fd_g_config), return NULL);	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "freeDiameter configuration:\n", fd_g_config), return NULL);	
 	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Default trace level .... : %+d\n", fd_g_debug_lvl), return NULL);
 	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Configuration file ..... : %s\n", fd_g_config->cnf_file), return NULL);
@@ -99,15 +99,15 @@
 		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local endpoints ........ : Default (use all available)\n"), return NULL);
 	} else {
-		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local endpoints ........ : \n"), return NULL);
-		CHECK_MALLOC_DO( fd_ep_dump( FD_DUMP_STD_PARAMS, 29, &fd_g_config->cnf_endpoints ), return NULL);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local endpoints ........ : "), return NULL);
+		CHECK_MALLOC_DO( fd_ep_dump( FD_DUMP_STD_PARAMS, 0, 0, &fd_g_config->cnf_endpoints ), return NULL);
 	}
 	if (FD_IS_LIST_EMPTY(&fd_g_config->cnf_apps)) {
-		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : (none)\n"), return NULL);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : (none)"), return NULL);
 	} else {
 		struct fd_list * li = fd_g_config->cnf_apps.next;
-		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : \n"), return NULL);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Local applications ..... : "), return NULL);
 		while (li != &fd_g_config->cnf_apps) {
 			struct fd_app * app = (struct fd_app *)li;
-			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "                             App: %u\t%s%s\tVnd: %u\n", 
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "App: %u,%s%s,Vnd:%u\t", 
 					app->appid,
 					app->flags.auth ? "Au" : "--",
@@ -118,5 +118,5 @@
 	}
 	
-	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n  Flags : - IP ........... : %s\n", fd_g_config->cnf_flags.no_ip4 ? "DISABLED" : "Enabled"), return NULL);
 	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - IPv6 ......... : %s\n", fd_g_config->cnf_flags.no_ip6 ? "DISABLED" : "Enabled"), return NULL);
 	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "          - Relay app .... : %s\n", fd_g_config->cnf_flags.no_fwd ? "DISABLED" : "Enabled"), return NULL);
@@ -588,5 +588,5 @@
 		
 	} else {
-		TRACE_DEBUG(INFO, "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
+		LOG_D( "Generating fresh Diffie-Hellman parameters of size %d (this takes some time)... ", fd_g_config->cnf_sec_data.dh_bits ?: GNUTLS_DEFAULT_DHBITS);
 		CHECK_GNUTLS_DO( gnutls_dh_params_generate2( 
 					fd_g_config->cnf_sec_data.dh_cache,
Index: libfdcore/endpoints.c
===================================================================
--- libfdcore/endpoints.c	(revision 1093)
+++ libfdcore/endpoints.c	(revision 1113)
@@ -285,9 +285,11 @@
 }
 
-DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, struct fd_endpoint * ep )
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump_one, int preamble, struct fd_endpoint * ep )
 {
 	FD_DUMP_HANDLE_OFFSET();
 	
-	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ep}(@%p): ", ep), return NULL);
+	if (preamble) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{ep}(@%p): ", ep), return NULL);
+	}
 	
 	if (!ep) {
@@ -297,14 +299,14 @@
 	
 	CHECK_MALLOC_DO( fd_sa_dump_node_serv( FD_DUMP_STD_PARAMS, &ep->sa, NI_NUMERICHOST | NI_NUMERICSERV ), return NULL);
-	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {%s%s%s%s%s}",
-			(ep->flags & EP_FL_CONF) 	? "C" : "-",
-			(ep->flags & EP_FL_DISC) 	? "D" : "-",
-			(ep->flags & EP_FL_ADV) 	? "A" : "-",
-			(ep->flags & EP_FL_LL) 		? "L" : "-",
-			(ep->flags & EP_FL_PRIMARY) 	? "P" : "-"), return NULL);
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{%s%s%s%s%s}",
+				(ep->flags & EP_FL_CONF) 	? "C" : "-",
+				(ep->flags & EP_FL_DISC) 	? "D" : "-",
+				(ep->flags & EP_FL_ADV) 	? "A" : "-",
+				(ep->flags & EP_FL_LL) 		? "L" : "-",
+				(ep->flags & EP_FL_PRIMARY) 	? "P" : "-"), return NULL);
 	return *buf;
 }
 
-DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int indent, struct fd_list * eps  )
+DECLARE_FD_DUMP_PROTOTYPE(fd_ep_dump, int preamble, int indent, struct fd_list * eps  )
 {
 	struct fd_list * li;
@@ -312,12 +314,18 @@
 	FD_DUMP_HANDLE_OFFSET();
 	
-	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{eps}(@%p):", indent, "", eps), return NULL);
+	if (preamble) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{eps}(@%p):", indent, "", eps), return NULL);
+	}
 	if (eps) {
 		for (li = eps->next; li != eps; li = li->next) {
 			struct fd_endpoint * ep = (struct fd_endpoint *)li;
-			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s", indent+1, ""), return NULL);
-			CHECK_MALLOC_DO( fd_ep_dump_one( FD_DUMP_STD_PARAMS, ep ), return NULL);
-		}
-	}
-}
-	
+			if (preamble) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n%*s", indent+1, ""), return NULL);
+			} else if (li->prev != eps) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\t"), return NULL);
+			}
+			CHECK_MALLOC_DO( fd_ep_dump_one( FD_DUMP_STD_PARAMS, preamble, ep ), return NULL);
+		}
+	}
+}
+	
Index: libfdcore/extensions.c
===================================================================
--- libfdcore/extensions.c	(revision 1094)
+++ libfdcore/extensions.c	(revision 1113)
@@ -151,5 +151,5 @@
 	{
 		struct fd_ext_info * ext = (struct fd_ext_info *)li;
-		TRACE_DEBUG (INFO, "Loading : %s", ext->filename);
+		LOG_D( "Loading : %s", ext->filename);
 		
 		/* Load the extension */
@@ -162,5 +162,5 @@
 		if (ext->handler == NULL) {
 			/* An error occured */
-			TRACE_ERROR("Loading of extension %s failed: %s", ext->filename, dlerror());
+			LOG_F("Loading of extension %s failed: %s", ext->filename, dlerror());
 			#ifdef DEBUG
 			ext->handler = dlopen(ext->filename, RTLD_LAZY | RTLD_GLOBAL);
@@ -208,5 +208,5 @@
 	}
 
-	TRACE_DEBUG (INFO, "All extensions loaded.");
+	LOG_N("All extensions loaded.");
 	
 	/* We have finished. */
Index: libfdcore/messages.c
===================================================================
--- libfdcore/messages.c	(revision 1103)
+++ libfdcore/messages.c	(revision 1113)
@@ -314,4 +314,27 @@
 }
 
+static int fd_msg_send_int( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data, void (*expirecb)(void *, DiamId_t, size_t, struct msg **), const struct timespec *timeout )
+{
+	struct msg_hdr *hdr;
+	DiamId_t diamid;
+	size_t diamidlen;
+	
+	/* Save the callback in the message, with the timeout */
+	CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data, expirecb, timeout )  );
+	
+	/* If this is a new request, call the HOOK_MESSAGE_LOCAL hook */
+	if ( (fd_msg_hdr(*pmsg, &hdr) == 0)
+	 &&  (hdr->msg_flags & CMD_FLAG_REQUEST)
+	 &&  (fd_msg_source_get(*pmsg, &diamid, &diamidlen) == 0)
+	 &&  (diamid == NULL)) {
+		fd_hook_call(HOOK_MESSAGE_LOCAL, *pmsg, NULL, NULL, fd_msg_pmdl_get(*pmsg));
+	}
+		
+	/* Post the message in the outgoing queue */
+	CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
+	
+	return 0;
+}
+
 /* Send a message and optionaly register a callback for an answer */
 int fd_msg_send ( struct msg ** pmsg, void (*anscb)(void *, struct msg **), void * data )
@@ -320,11 +343,5 @@
 	CHECK_PARAMS( pmsg );
 	
-	/* Save the callback in the message */
-	CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data, NULL, NULL /* we should maybe use a safeguard here like 1 hour or so? */ )  );
-	
-	/* Post the message in the outgoing queue */
-	CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
-	
-	return 0;
+	return fd_msg_send_int(pmsg, anscb, data, NULL, NULL);
 }
 
@@ -335,11 +352,5 @@
 	CHECK_PARAMS( pmsg && expirecb && timeout );
 	
-	/* Save the callback in the message, with the timeout */
-	CHECK_FCT(  fd_msg_anscb_associate( *pmsg, anscb, data, expirecb, timeout )  );
-	
-	/* Post the message in the outgoing queue */
-	CHECK_FCT( fd_fifo_post(fd_g_outgoing, pmsg) );
-	
-	return 0;
+	return fd_msg_send_int(pmsg, anscb, data, expirecb, timeout);
 }
 
Index: libfdcore/p_ce.c
===================================================================
--- libfdcore/p_ce.c	(revision 1103)
+++ libfdcore/p_ce.c	(revision 1113)
@@ -650,5 +650,5 @@
 	*recv_cnx = NULL;
 	if (*cer) {
-		//fd_msg_log(FD_MSG_LOG_DROPPED, *cer, "An error occurred while rejecting a CER.");
+		fd_hook_call(HOOK_MESSAGE_DROPPED, *cer, NULL, "An error occurred while rejecting this CER.", fd_msg_pmdl_get(*cer));
 		fd_msg_free(*cer);
 		*cer = NULL;
Index: libfdcore/p_out.c
===================================================================
--- libfdcore/p_out.c	(revision 1103)
+++ libfdcore/p_out.c	(revision 1113)
@@ -98,5 +98,5 @@
 	CHECK_FCT_DO(fd_fifo_post(fd_g_outgoing, &msg),
 		{
-			//fd_msg_log( FD_MSG_LOG_DROPPED, msg, "An error occurred while attempting to requeue this message during cancellation of the sending function");
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, "An error occurred while attempting to requeue this message during cancellation of the sending function", fd_msg_pmdl_get(msg));
 			CHECK_FCT_DO(fd_msg_free(msg), /* What can we do more? */);
 		} );
@@ -131,5 +131,7 @@
 			{
 				if (msg) {
-					//fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error: Problem while sending (%s)", strerror(ret) );
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Error while sending this message: s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
 					fd_msg_free(msg);
 				}
@@ -183,5 +185,7 @@
 			{
 				if (msg) {
-					//fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Internal error: Problem while sending (%s)", strerror(ret) );
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Error while sending this message: s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, *msg, NULL, buf, fd_msg_pmdl_get(*msg));
 					fd_msg_free(*msg);
 					*msg = NULL;
Index: libfdcore/p_psm.c
===================================================================
--- libfdcore/p_psm.c	(revision 1104)
+++ libfdcore/p_psm.c	(revision 1113)
@@ -241,5 +241,5 @@
 			case FDEVP_CNX_INCOMING: {
 				struct cnx_incoming * evd = ev->data;
-				//fd_msg_log( FD_MSG_LOG_DROPPED, evd->cer, "Message discarded while cleaning peer state machine queue." );
+				fd_hook_call(HOOK_MESSAGE_DROPPED, evd->cer, NULL, "Message discarded while cleaning peer state machine queue.", fd_msg_pmdl_get(evd->cer));
 				CHECK_FCT_DO( fd_msg_free(evd->cer), /* continue */);
 				fd_cnx_destroy(evd->cnx);
@@ -577,4 +577,5 @@
 					char buf[128];
 					snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(cur_state));
+					LOG_E("%s",buf); 
 					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
 					fd_msg_free(msg);
@@ -590,6 +591,9 @@
 			if (ret != EBADMSG) {
 				CHECK_FCT_DO( ret, 
-					{ 
-						LOG_E("%s: An unexpected error occurred while parsing a link-local message", peer->p_hdr.info.pi_diamid); 
+					{
+						char buf[256];
+						snprintf(buf, sizeof(buf), "%s: An unexpected error occurred while parsing a link-local message", peer->p_hdr.info.pi_diamid); 
+						LOG_E("%s",buf); 
+						fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
 						fd_msg_free(msg); 
 						goto psm_end; 
@@ -600,11 +604,16 @@
 					CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, FD_CNX_ORDERED),  );
 					if (error) {
+						char buf[256];
 						/* Only if an error occurred & the message was not saved / dumped */
-						LOG_E("%s: error sending a message", peer->p_hdr.info.pi_diamid); 
+						snprintf(buf, sizeof(buf), "%s: error sending a message", peer->p_hdr.info.pi_diamid); 
+						LOG_E("%s",buf); 
+						fd_hook_call(HOOK_MESSAGE_DROPPED, error, peer, buf, fd_msg_pmdl_get(error));
 						CHECK_FCT_DO( fd_msg_free(error), goto psm_end);
 					}
 				} else {
+					char buf[256];
 					/* We received an invalid answer, let's disconnect */
-					LOG_E("%s: Received invalid answer to Base protocol message, disconnecting...", peer->p_hdr.info.pi_diamid);
+					snprintf(buf, sizeof(buf), "%s: Received invalid answer to Base protocol message, disconnecting...", peer->p_hdr.info.pi_diamid);
+					LOG_E("%s",buf); 
 					CHECK_FCT_DO( fd_msg_free(msg), goto psm_end);
 					CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset );
@@ -657,5 +666,8 @@
 				/* Cleanup the message if not done */
 				if (msg) {
-					//fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received un-handled non-routable command from peer '%s'.", peer->p_hdr.info.pi_diamid );
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Received un-handled non-routable command from peer '%s'.", peer->p_hdr.info.pi_diamid);
+					LOG_E("%s",buf);
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
 					CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
 					msg = NULL;
@@ -665,5 +677,8 @@
 		/* At this point the message must have been fully handled already */
 		if (msg) {
-			//fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error ('%s'): unhandled message.", peer->p_hdr.info.pi_diamid );
+			char buf[256];
+			snprintf(buf, sizeof(buf), "Internal error ('%s'): unhandled message.", peer->p_hdr.info.pi_diamid);
+			LOG_E("%s",buf);
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, buf, fd_msg_pmdl_get(msg));
 			fd_msg_free(msg);
 		}
@@ -732,5 +747,5 @@
 			char * buf = NULL;
 			size_t len = 0;
-			LOG_D("New remote endpoint(s): %s",  fd_ep_dump(&buf, &len, NULL, 6, &peer->p_hdr.info.pi_endpoints) ?: "error");
+			LOG_D("New remote endpoint(s): %s",  fd_ep_dump(&buf, &len, NULL, 0, 0, &peer->p_hdr.info.pi_endpoints) ?: "error");
 			free(buf);
 		}
Index: libfdcore/p_sr.c
===================================================================
--- libfdcore/p_sr.c	(revision 1110)
+++ libfdcore/p_sr.c	(revision 1113)
@@ -119,5 +119,5 @@
 	/* If the callback did not dispose of the message, do it now */
 	if (ed->request) {
-		//fd_msg_log(FD_MSG_LOG_DROPPED, ed->request, "Expiration period completed without an answer, and the expiry callback did not dispose of the message.");
+		fd_hook_call(HOOK_MESSAGE_DROPPED, ed->request, NULL, "Expiration period completed without an answer, and the expiry callback did not dispose of the message.", fd_msg_pmdl_get(ed->request));
 		CHECK_FCT_DO( fd_msg_free(ed->request), /* ignore */ );
 	}
@@ -323,13 +323,17 @@
 				hdr->msg_flags |= CMD_FLAG_RETRANSMIT;
 			
+			fd_hook_call(HOOK_MESSAGE_FAILOVER, sr->req, (struct fd_peer *)srlist->srs.o, NULL, fd_msg_pmdl_get(sr->req));
+			
 			/* Requeue for sending to another peer */
 			CHECK_FCT_DO( ret = fd_fifo_post(fd_g_outgoing, &sr->req),
 				{
-					//fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Internal error: error while requeuing during failover: %s", strerror(ret) );
+					char buf[256];
+					snprintf(buf, sizeof(buf), "Internal error: error while requeuing during failover: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, sr->req, NULL, buf, fd_msg_pmdl_get(sr->req));
 					CHECK_FCT_DO(fd_msg_free(sr->req), /* What can we do more? */)
 				});
 		} else {
 			/* Just free the request. */
-			//fd_msg_log( FD_MSG_LOG_DROPPED, sr->req, "Sent & unanswered local message discarded during failover." );
+			/* fd_hook_call(HOOK_MESSAGE_DROPPED, sr->req, NULL, "Sent & unanswered local message discarded during failover.", fd_msg_pmdl_get(sr->req)); */
 			CHECK_FCT_DO(fd_msg_free(sr->req), /* Ignore */);
 		}
Index: libfdcore/peers.c
===================================================================
--- libfdcore/peers.c	(revision 1103)
+++ libfdcore/peers.c	(revision 1113)
@@ -242,8 +242,9 @@
 	/* Requeue all messages in the "out" queue */
 	while ( fd_fifo_tryget(peer->p_tosend, &m) == 0 ) {
+		fd_hook_call(HOOK_MESSAGE_FAILOVER, m, peer, NULL, fd_msg_pmdl_get(m));
 		CHECK_FCT_DO(fd_fifo_post(fd_g_outgoing, &m), 
 			{
 				/* fallback: destroy the message */
-				//fd_msg_log(FD_MSG_LOG_DROPPED, m, "Internal error: unable to requeue this message during failover process");
+				fd_hook_call(HOOK_MESSAGE_DROPPED, m, NULL, "Internal error: unable to requeue this message during failover process", fd_msg_pmdl_get(m));
 				CHECK_FCT_DO(fd_msg_free(m), /* What can we do more? */)
 			} );
Index: libfdcore/queues.c
===================================================================
--- libfdcore/queues.c	(revision 1078)
+++ libfdcore/queues.c	(revision 1113)
@@ -74,5 +74,5 @@
 		
 		/* We got one! */
-		//fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Message lost because framework is terminating." );
+		fd_hook_call(HOOK_MESSAGE_DROPPED, msg, NULL, "Message lost because framework is terminating.", fd_msg_pmdl_get(msg));
 		fd_msg_free(msg);
 	}
Index: libfdcore/routing_dispatch.c
===================================================================
--- libfdcore/routing_dispatch.c	(revision 1103)
+++ libfdcore/routing_dispatch.c	(revision 1113)
@@ -393,5 +393,7 @@
 
 			if (!peer) {
-				//fd_msg_log(FD_MSG_LOG_DROPPED, *pmsg, "Unable to send error '%s' to deleted peer '%s' in reply to this message.", error_code, id);
+				char buf[256];
+				snprintf(buf, sizeof(buf), "Unable to send error '%s' to deleted peer '%s' in reply to this message.", error_code, id);
+				fd_hook_call(HOOK_MESSAGE_DROPPED, *pmsg, NULL, buf, fd_msg_pmdl_get(*pmsg));
 				fd_msg_free(*pmsg);
 				*pmsg = NULL;
@@ -496,5 +498,5 @@
 
 	/* Now, call any callback registered for the message */
-	CHECK_FCT( fd_msg_dispatch ( &msgptr, sess, &action, &ec) );
+	CHECK_FCT( fd_msg_dispatch ( &msgptr, sess, &action, &ec, &em, &error) );
 
 	/* Now, act depending on msg and action and ec */
@@ -505,4 +507,5 @@
 				if (!fd_g_config->cnf_flags.no_fwd) {
 					/* requeue to fd_g_outgoing */
+					fd_hook_call(HOOK_MESSAGE_ROUTING_FORWARD, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 					CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) );
 					break;
@@ -519,5 +522,5 @@
 				
 				if (!is_req) {
-					//fd_msg_log( FD_MSG_LOG_DROPPED, msgptr,  "Internal error: Answer received to locally issued request, but not handled by any handler.");
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Internal error: Answer received to locally issued request, but not handled by any handler.", fd_msg_pmdl_get(msgptr));
 					fd_msg_free(msgptr);
 					break;
@@ -532,4 +535,7 @@
 				CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) );
 		}
+	} else if (em) {
+		fd_hook_call(HOOK_MESSAGE_DROPPED, error, NULL, em, fd_msg_pmdl_get(error));
+		fd_msg_free(error);
 	}
 	
@@ -555,4 +561,5 @@
 	/* Handle incorrect bits */
 	if (is_req && is_err) {
+		fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "R & E bits were set", fd_msg_pmdl_get(msgptr));
 		CHECK_FCT( return_error( &msgptr, "DIAMETER_INVALID_HDR_BITS", "R & E bits were set", NULL) );
 		return 0;
@@ -573,6 +580,5 @@
 		/* Check if we have local support for the message application */
 		if ( (hdr->msg_appl == 0) || (hdr->msg_appl == AI_RELAY) ) {
-			TRACE_DEBUG(INFO, "Received a routable message with application id 0 or " _stringize(AI_RELAY) " (relay),"
-					  " returning DIAMETER_APPLICATION_UNSUPPORTED");
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Received a routable message with application id 0 or " _stringize(AI_RELAY) " (relay)", fd_msg_pmdl_get(msgptr));
 			CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", "Routable message with application id 0 or relay", NULL) );
 			return 0;
@@ -601,7 +607,9 @@
 							{
 								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
 									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
 									return 0;
 								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Host AVP", fd_msg_pmdl_get(msgptr));
 									return ret;
 								}
@@ -621,7 +629,9 @@
 							{
 								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
 									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
 									return 0;
 								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing Destination-Realm AVP", fd_msg_pmdl_get(msgptr));
 									return ret;
 								}
@@ -643,7 +653,9 @@
 							{
 								if (error_info.pei_errcode) {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, error_info.pei_message ?: error_info.pei_errcode, fd_msg_pmdl_get(msgptr));
 									CHECK_FCT( return_error( &msgptr, error_info.pei_errcode, error_info.pei_message, error_info.pei_avp) );
 									return 0;
 								} else {
+									fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Unspecified error while parsing User-Name AVP", fd_msg_pmdl_get(msgptr));
 									return ret;
 								}
@@ -668,4 +680,5 @@
 		/* Handle the missing routing AVPs first */
 		if ( is_dest_realm == UNKNOWN ) {
+			fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Non-routable message not supported (invalid bit ? missing Destination-Realm ?)", fd_msg_pmdl_get(msgptr));
 			CHECK_FCT( return_error( &msgptr, "DIAMETER_COMMAND_UNSUPPORTED", "Non-routable message not supported (invalid bit ? missing Destination-Realm ?)", NULL) );
 			return 0;
@@ -676,7 +689,9 @@
 			if (is_local_app == YES) {
 				/* Ok, give the message to the dispatch thread */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 				CHECK_FCT( fd_fifo_post(fd_g_local, &msgptr) );
 			} else {
 				/* We don't support the application, reply an error */
+				fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Application unsupported", fd_msg_pmdl_get(msgptr));
 				CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", NULL, NULL) );
 			}
@@ -687,4 +702,5 @@
 		if ((is_dest_host == NO) || (is_dest_realm == NO)) {
 			if (fd_g_config->cnf_flags.no_fwd) {
+				fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "Message for another realm/host", fd_msg_pmdl_get(msgptr));
 				CHECK_FCT( return_error( &msgptr, "DIAMETER_UNABLE_TO_DELIVER", "I am not a Diameter agent", NULL) );
 				return 0;
@@ -700,4 +716,5 @@
 					{
 						/* If the process failed, we assume it is because of the AVP format */
+						fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msgptr, NULL, "Failed to process decorated NAI", fd_msg_pmdl_get(msgptr));
 						CHECK_FCT( return_error( &msgptr, "DIAMETER_INVALID_AVP_VALUE", "Failed to process decorated NAI", un) );
 						return 0;
@@ -713,4 +730,5 @@
 			if (is_local_app == YES) {
 				/* Handle localy since we are able to */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 				CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
 				return 0;
@@ -719,4 +737,5 @@
 			if (fd_g_config->cnf_flags.no_fwd) {
 				/* We return an error */
+				fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "Application unsupported", fd_msg_pmdl_get(msgptr));
 				CHECK_FCT( return_error( &msgptr, "DIAMETER_APPLICATION_UNSUPPORTED", NULL, NULL) );
 				return 0;
@@ -736,4 +755,5 @@
 		if ((!qry_src) && (!is_err)) {
 			/* The message is a normal answer to a request issued localy, we do not call the callbacks chain on it. */
+			fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 			CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
 			return 0;
@@ -764,7 +784,11 @@
 			CHECK_FCT_DO( ret = (*rh->rt_fwd_cb)(rh->cbdata, &msgptr),
 				{
-					//fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: a FWD routing callback returned an error (%s)", strerror(ret));
+					char buf[256];
+					snprintf(buf, sizeof(buf), "A FWD routing callback returned an error: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
 					fd_msg_free(msgptr);
 					msgptr = NULL;
+					break;
 				} );
 		}
@@ -780,6 +804,8 @@
 	/* Now pass the message to the next step: either forward to another peer, or dispatch to local extensions */
 	if (is_req || qry_src) {
+		fd_hook_call(HOOK_MESSAGE_ROUTING_FORWARD, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 		CHECK_FCT(fd_fifo_post(fd_g_outgoing, &msgptr) );
 	} else {
+		fd_hook_call(HOOK_MESSAGE_ROUTING_LOCAL, msgptr, NULL, NULL, fd_msg_pmdl_get(msgptr));
 		CHECK_FCT(fd_fifo_post(fd_g_local, &msgptr) );
 	}
@@ -823,5 +849,8 @@
 		CHECK_FCT( fd_peer_getbyid( qry_src, qry_src_len, 0, (void *) &peer ) );
 		if (fd_peer_getstate(peer) != STATE_OPEN) {
-			//fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Unable to forward answer to deleted / closed peer '%s'.", qry_src);
+			char buf[128];
+			snprintf(buf, sizeof(buf), "Unable to forward answer to deleted / closed peer '%s'.", qry_src);
+			fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+			fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
 			fd_msg_free(msgptr);
 			return 0;
@@ -908,5 +937,8 @@
 			CHECK_FCT_DO( ret = (*rh->rt_out_cb)(rh->cbdata, msgptr, candidates),
 				{
-					//fd_msg_log( FD_MSG_LOG_DROPPED, msgptr, "Internal error: an OUT routing callback returned an error (%s)", strerror(ret));
+					char buf[256];
+					snprintf(buf, sizeof(buf), "An OUT routing callback returned an error: %s", strerror(ret));
+					fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
+					fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, buf, fd_msg_pmdl_get(msgptr));
 					fd_msg_free(msgptr);
 					msgptr = NULL;
@@ -956,5 +988,5 @@
 	/* If the message has not been sent, return an error */
 	if (msgptr) {
-		//fd_msg_log( FD_MSG_LOG_NODELIVER, msgptr, "No suitable candidate to route the message to." );
+		fd_hook_call(HOOK_MESSAGE_ROUTING_ERROR, msgptr, NULL, "No remaining suitable candidate to route the message to", fd_msg_pmdl_get(msgptr));
 		return_error( &msgptr, "DIAMETER_UNABLE_TO_DELIVER", "No suitable candidate to route the message to", NULL);
 	}
Index: libfdcore/server.c
===================================================================
--- libfdcore/server.c	(revision 1103)
+++ libfdcore/server.c	(revision 1113)
@@ -94,5 +94,5 @@
 
 /* Dump all servers information */
-DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump)
+DECLARE_FD_DUMP_PROTOTYPE(fd_servers_dump, int details)
 {
 	struct fd_list * li, *cli;
@@ -104,22 +104,27 @@
 		enum s_state st = get_status(s);
 		
-		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{server}(@%p)'%s': %s, %s, %s", s, fd_cnx_getid(s->conn), 
-				IPPROTO_NAME( s->proto ),
-				s->secur ? "Secur" : "NotSecur",
-				(st == NOT_CREATED) ? "Thread not created" :
-				((st == RUNNING) ? "Thread running" :
-				((st == TERMINATED) ? "Thread terminated" :
-							  "Thread status unknown"))), return NULL);
-		/* Dump the client list of this server */
-		CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), );
-		for (cli = s->clients.next; cli != &s->clients; cli = cli->next) {
-			struct client * c = (struct client *)cli;
-			char bufts[128];
-			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n  {client}(@%p)'%s': to:%s", c, fd_cnx_getid(c->conn), fd_log_time(&c->ts, bufts, sizeof(bufts))), break);
-		}
-		CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), );
-		
-		if (li->next != &FD_SERVERS) {
-			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+		if (details) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{server}(@%p)'%s': %s, %s, %s", s, fd_cnx_getid(s->conn), 
+					IPPROTO_NAME( s->proto ),
+					s->secur ? "Secur" : "NotSecur",
+					(st == NOT_CREATED) ? "Thread not created" :
+					((st == RUNNING) ? "Thread running" :
+					((st == TERMINATED) ? "Thread terminated" :
+								  "Thread status unknown"))), return NULL);
+			/* Dump the client list of this server */
+			CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), );
+			for (cli = s->clients.next; cli != &s->clients; cli = cli->next) {
+				struct client * c = (struct client *)cli;
+				char bufts[128];
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n  {client}(@%p)'%s': to:%s", c, fd_cnx_getid(c->conn), fd_log_time(&c->ts, bufts, sizeof(bufts))), break);
+			}
+			CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), );
+
+			if (li->next != &FD_SERVERS) {
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+			}
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%s,%s)  ", fd_cnx_getid(s->conn), 
+					IPPROTO_NAME( s->proto ), s->secur ? "Secur" : "NotSecur"), return NULL);
 		}
 	}
@@ -446,5 +451,5 @@
 		size_t len = 0, offset = 0;
 		CHECK_MALLOC_DO( fd_dump_extend( &buf, &len, &offset , "Local server address(es): "), );
-		CHECK_MALLOC_DO( fd_ep_dump(  &buf, &len, &offset, 5, &fd_g_config->cnf_endpoints ), );
+		CHECK_MALLOC_DO( fd_ep_dump(  &buf, &len, &offset, 0, 0, &fd_g_config->cnf_endpoints ), );
 		LOG_N("%s", buf ?: "Error dumping addresses");
 		free(buf);
