Index: extensions/dbg_rt/dbg_rt.c
===================================================================
--- extensions/dbg_rt/dbg_rt.c	(revision 1127)
+++ extensions/dbg_rt/dbg_rt.c	(revision 1216)
@@ -59,7 +59,8 @@
 
 /* Path selection debug callback */
-static int dbgrt_out_cb(void * cbdata, struct msg * msg, struct fd_list * candidates)
+static int dbgrt_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
 	struct fd_list * li;
+	struct msg * msg = *pmsg;
 	char * buf = NULL; size_t buflen;
 	
Index: extensions/rt_default/rt_default.c
===================================================================
--- extensions/rt_default/rt_default.c	(revision 741)
+++ extensions/rt_default/rt_default.c	(revision 1216)
@@ -41,6 +41,7 @@
 
 /* The callback called on new messages */
-static int rtd_out(void * cbdata, struct msg * msg, struct fd_list * candidates)
+static int rtd_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
+	struct msg * msg = *pmsg;
 	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
 	
Index: extensions/rt_ereg/rtereg.c
===================================================================
--- extensions/rt_ereg/rtereg.c	(revision 1127)
+++ extensions/rt_ereg/rtereg.c	(revision 1216)
@@ -126,6 +126,7 @@
 
 /* The callback called on new messages */
-static int rtereg_out(void * cbdata, struct msg * msg, struct fd_list * candidates)
-{
+static int rtereg_out(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
 	struct avp * avp = NULL;
 	
Index: extensions/rt_load_balance/rt_load_balance.c
===================================================================
--- extensions/rt_load_balance/rt_load_balance.c	(revision 1043)
+++ extensions/rt_load_balance/rt_load_balance.c	(revision 1216)
@@ -37,7 +37,8 @@
 
 /* The callback for load balancing the requests across the peers */
-static int rt_load_balancing(void * cbdata, struct msg * msg, struct fd_list * candidates)
+static int rt_load_balancing(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
 	struct fd_list *lic;
+	struct msg * msg = *pmsg;
 	
 	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
Index: extensions/rt_redirect/redir_out.c
===================================================================
--- extensions/rt_redirect/redir_out.c	(revision 1127)
+++ extensions/rt_redirect/redir_out.c	(revision 1216)
@@ -38,5 +38,5 @@
 
 /* Find the data pertinent to a type in the input data */
-static int get_data_to_match(enum redir_h_u type, struct msg * msg, union matchdata * data, int * nodata)
+static int get_data_to_match(enum redir_h_u type, struct msg *msg, union matchdata * data, int * nodata)
 {
 	TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata);
@@ -220,7 +220,8 @@
 
 /* OUT callback */
-int redir_out_cb(void * cbdata, struct msg * msg, struct fd_list * candidates)
+int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
 	int i, ret = 0;
+	struct msg * msg = *pmsg;
 	
 	TRACE_ENTRY("%p %p %p", cbdata, msg, candidates);
Index: extensions/rt_redirect/rt_redir.h
===================================================================
--- extensions/rt_redirect/rt_redir.h	(revision 740)
+++ extensions/rt_redirect/rt_redir.h	(revision 1216)
@@ -171,3 +171,3 @@
 
 /* Out callback */
-int redir_out_cb(void * cbdata, struct msg * msg, struct fd_list * candidates);
+int redir_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates);
Index: extensions/test_rt_any/test_rt_any.c
===================================================================
--- extensions/test_rt_any/test_rt_any.c	(revision 741)
+++ extensions/test_rt_any/test_rt_any.c	(revision 1216)
@@ -41,6 +41,7 @@
 
 /* The callback */
-static int tra_out_cb(void * cbdata, struct msg * msg, struct fd_list * candidates)
+static int tra_out_cb(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
 {
+	struct msg * msg = *pmsg;
 	struct fd_list * li;
 	
Index: include/freeDiameter/libfdcore.h
===================================================================
--- include/freeDiameter/libfdcore.h	(revision 1194)
+++ include/freeDiameter/libfdcore.h	(revision 1216)
@@ -763,5 +763,5 @@
  *  ENOMEM	: Not enough memory to complete the operation
  */
-int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler );
+int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg ** pmsg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler );
 /*
  * CALLBACK:	rt_out_cb
@@ -769,5 +769,5 @@
  * PARAMETERS:
  *  cbdata	: pointer to some data that was registered with the callback.
- *  msg 	: The message that must be sent.
+ *  pmsg 	: pointer to the message that must be sent. upon return if *msg is NULL, the processing stops and the message is not sent.
  *  list        : The list of peers to which the message may be sent to, as returned by fd_rtd_candidate_extract
  *
Index: libfdcore/routing_dispatch.c
===================================================================
--- libfdcore/routing_dispatch.c	(revision 1212)
+++ libfdcore/routing_dispatch.c	(revision 1216)
@@ -58,5 +58,5 @@
 	union {
 		int (*rt_fwd_cb)(void * cbdata, struct msg ** msg);
-		int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates);
+		int (*rt_out_cb)(void * cbdata, struct msg ** msg, struct fd_list * candidates);
 	};
 };	
@@ -135,5 +135,5 @@
 
 /* Register a new OUT callback */
-int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg * msg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler )
+int fd_rt_out_register ( int (*rt_out_cb)(void * cbdata, struct msg ** pmsg, struct fd_list * candidates), void * cbdata, int priority, struct fd_rt_out_hdl ** handler )
 {
 	struct rt_hdl * new;
@@ -189,6 +189,7 @@
 
 /* Prevent sending to peers that do not support the message application */
-static int dont_send_if_no_common_app(void * cbdata, struct msg * msg, struct fd_list * candidates)
-{
+static int dont_send_if_no_common_app(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
 	struct fd_list * li;
 	struct msg_hdr * hdr;
@@ -221,6 +222,7 @@
 
 /* Detect if the Destination-Host and Destination-Realm match the peer */
-static int score_destination_avp(void * cbdata, struct msg * msg, struct fd_list * candidates)
-{
+static int score_destination_avp(void * cbdata, struct msg ** pmsg, struct fd_list * candidates)
+{
+	struct msg * msg = *pmsg;
 	struct fd_list * li;
 	struct avp * avp;
@@ -959,9 +961,9 @@
 
 		/* We call the cb by reverse priority order */
-		for (	li = rt_out_list.prev ; li != &rt_out_list ; li = li->prev ) {
+		for (	li = rt_out_list.prev ; (msgptr != NULL) && (li != &rt_out_list) ; li = li->prev ) {
 			struct rt_hdl * rh = (struct rt_hdl *)li;
 
 			TRACE_DEBUG(ANNOYING, "Calling next OUT callback on %p : %p (prio %d)", msgptr, rh->rt_out_cb, rh->prio);
-			CHECK_FCT_DO( ret = (*rh->rt_out_cb)(rh->cbdata, msgptr, candidates),
+			CHECK_FCT_DO( ret = (*rh->rt_out_cb)(rh->cbdata, &msgptr, candidates),
 				{
 					char buf[256];
@@ -971,5 +973,4 @@
 					fd_msg_free(msgptr);
 					msgptr = NULL;
-					break;
 				} );
 		}
@@ -978,8 +979,6 @@
 		CHECK_FCT( pthread_rwlock_unlock( &rt_out_lock ) );
 
-		/* If an error occurred, skip to the next message */
+		/* If an error occurred or the callback disposed of the message, go to next message */
 		if (! msgptr) {
-			if (rtd)
-				fd_rtd_free(&rtd);
 			return 0;
 		}
