Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 633)
+++ CMakeLists.txt	(revision 639)
@@ -15,5 +15,5 @@
 
 # Version of the API with the library
-SET(FD_PROJECT_VERSION_API 1)
+SET(FD_PROJECT_VERSION_API 2)
 
 # The test framework, using CTest and CDash.
Index: contrib/debian/changelog
===================================================================
--- contrib/debian/changelog	(revision 629)
+++ contrib/debian/changelog	(revision 639)
@@ -1,4 +1,6 @@
 freediameter (1.0.3) UNRELEASED; urgency=low
 
+  * Added parameters to fd_disp_register and fd_sess_handler_create,
+    Bumped API version number accordingly.
   * Fixed a couple of issues for portability (#21, #22, #23)
   * Fixed issue with ListenOn bit ordering (#20)
Index: doc/dbg_interactive.py.sample
===================================================================
--- doc/dbg_interactive.py.sample	(revision 638)
+++ doc/dbg_interactive.py.sample	(revision 639)
@@ -622,5 +622,5 @@
 np.add()
 
-# It is possible to specify a callback for when the connection completes or fails to this peer.
+# It is possible to specify a callback for when the connection completes or fails with this peer.
 # The prototype is as follow:
 def add_cb(peer):
Index: extensions/app_acct/app_acct.c
===================================================================
--- extensions/app_acct/app_acct.c	(revision 403)
+++ extensions/app_acct/app_acct.c	(revision 639)
@@ -46,5 +46,5 @@
 
 /* Callback for incoming Base Accounting Accounting-Request messages */
-static int acct_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+static int acct_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	struct msg * m;
@@ -135,5 +135,5 @@
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_APPLICATION, APPLICATION_BY_NAME, "Diameter Base Accounting", &data.app, ENOENT) );
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Accounting-Request", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( acct_cb, DISP_HOW_CC, &data, NULL ) );
+	CHECK_FCT( fd_disp_register( acct_cb, DISP_HOW_CC, &data, NULL, NULL ) );
 	
 	/* Advertise the support for the Diameter Base Accounting application in the peer */
Index: extensions/app_diameap/diameap_server.c
===================================================================
--- extensions/app_diameap/diameap_server.c	(revision 610)
+++ extensions/app_diameap/diameap_server.c	(revision 639)
@@ -85,5 +85,5 @@
 
 
-void diameap_cli_sess_cleanup(void * arg, char * sid)
+void diameap_cli_sess_cleanup(void * arg, char * sid, void * opaque)
 {
 
@@ -3060,5 +3060,5 @@
 
 static int diameap_server_callback(struct msg ** rmsg, struct avp * ravp,
-		struct session * sess, enum disp_action * action)
+		struct session * sess, void * opaque, enum disp_action * action)
 {
 	TRACE_ENTRY("%p %p %p %p", rmsg, ravp, sess, action);
@@ -3389,5 +3389,5 @@
 
 	/*create handler for sessions */
-	CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup));
+	CHECK_FCT(fd_sess_handler_create(&diameap_server_reg, diameap_cli_sess_cleanup, NULL));
 
 	/* Register the callback */
@@ -3397,5 +3397,5 @@
 
 	/* Register the callback for EAP Application */
-	CHECK_FCT(fd_disp_register(diameap_server_callback, DISP_HOW_CC, &when,
+	CHECK_FCT(fd_disp_register(diameap_server_callback, DISP_HOW_CC, &when, NULL,
 					&handle));
 
@@ -3410,6 +3410,6 @@
 int diameap_stop_server(void)
 {
-	CHECK_FCT(fd_sess_handler_destroy(&diameap_server_reg));
-	CHECK_FCT(fd_disp_unregister(&handle));
+	CHECK_FCT(fd_sess_handler_destroy(&diameap_server_reg, NULL));
+	CHECK_FCT(fd_disp_unregister(&handle, NULL));
 
 	return 0;
Index: extensions/app_radgw/rgwx_acct.c
===================================================================
--- extensions/app_radgw/rgwx_acct.c	(revision 564)
+++ extensions/app_radgw/rgwx_acct.c	(revision 639)
@@ -173,5 +173,5 @@
 	memset(new, 0, sizeof(struct rgwp_config));
 	
-	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free ) );
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) );
 	new->confstr = conffile;
 	
@@ -284,5 +284,5 @@
 	TRACE_ENTRY("%p", state);
 	CHECK_PARAMS_DO( state, return );
-	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl ),  );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
 	free(state);
 	return;
Index: extensions/app_radgw/rgwx_auth.c
===================================================================
--- extensions/app_radgw/rgwx_auth.c	(revision 532)
+++ extensions/app_radgw/rgwx_auth.c	(revision 639)
@@ -139,5 +139,5 @@
 	memset(new, 0, sizeof(struct rgwp_config));
 	
-	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free ) );
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) );
 	new->confstr = confstr;
 	
@@ -225,5 +225,5 @@
 	TRACE_ENTRY("%p", state);
 	CHECK_PARAMS_DO( state, return );
-	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl ),  );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
 	free(state);
 	return;
Index: extensions/app_radgw/rgwx_echodrop.c
===================================================================
--- extensions/app_radgw/rgwx_echodrop.c	(revision 403)
+++ extensions/app_radgw/rgwx_echodrop.c	(revision 639)
@@ -39,5 +39,5 @@
 
 /* If a session is destroyed, empty the list of ed_saved_attribute */
-static void state_delete(void * arg, char * sid) {
+static void state_delete(void * arg, char * sid, void * opaque) {
 	struct fd_list * list = (struct fd_list *)arg;
 	
@@ -69,5 +69,5 @@
 	
 	/* Create the session handler */
-	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete ) );
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, state_delete, NULL ) );
 	
 	/* Parse the configuration file */
@@ -107,5 +107,5 @@
 	TRACE_ENTRY("%p", state);
 	CHECK_PARAMS_DO( state, return );
-	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl ),  );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
 	while (! FD_IS_LIST_EMPTY(&state->attributes) ) {
 		struct fd_list * li = state->attributes.next;
Index: extensions/app_radgw/rgwx_sip.c
===================================================================
--- extensions/app_radgw/rgwx_sip.c	(revision 584)
+++ extensions/app_radgw/rgwx_sip.c	(revision 639)
@@ -262,5 +262,5 @@
 	memset(new, 0, sizeof(struct rgwp_config));
 	
-	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free ) );
+	CHECK_FCT( fd_sess_handler_create( &new->sess_hdl, free, NULL ) );
 	new->confstr = conffile;
 	
@@ -316,5 +316,5 @@
 	CHECK_PARAMS_DO( state, return );
 	
-	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl ),  );
+	CHECK_FCT_DO( fd_sess_handler_destroy( &state->sess_hdl, NULL ),  );
 	
 	nonce_deletelistnonce(state);
Index: extensions/app_sip/app_sip.c
===================================================================
--- extensions/app_sip/app_sip.c	(revision 433)
+++ extensions/app_sip/app_sip.c	(revision 639)
@@ -59,7 +59,7 @@
 struct app_sip_dict sip_dict;
 
-int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
-{
-	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
+{
+	TRACE_ENTRY("%p %p %p %p %p", msg, avp, sess, opaque, act);
 	
 	return 0;
@@ -179,23 +179,23 @@
 	if(as_conf->mode==1)
 	{
-	  //**Command Codes
+	  // **Command Codes
 	  //MAR
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Request", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_MAR_cb, DISP_HOW_CC, &data, &app_sip_MAR_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_MAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_MAR_hdl ) );
 	  //RTA
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Answer", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_RTA_cb, DISP_HOW_CC, &data, &app_sip_RTA_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_RTA_cb, DISP_HOW_CC, &data, NULL, &app_sip_RTA_hdl ) );
 	  //PPA
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Push-Profile-Answer", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_PPA_cb, DISP_HOW_CC, &data, &app_sip_PPA_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_PPA_cb, DISP_HOW_CC, &data, NULL, &app_sip_PPA_hdl ) );
 	  //LIR
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_LIR_cb, DISP_HOW_CC, &data, &app_sip_LIR_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_LIR_hdl ) );
 	  //UAR
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Request", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_UAR_cb, DISP_HOW_CC, &data, &app_sip_UAR_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_UAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_UAR_hdl ) );
 	  //SAR
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Request", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_SAR_cb, DISP_HOW_CC, &data, &app_sip_SAR_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_SAR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SAR_hdl ) );
 	}
 	if(as_conf->mode==2)
@@ -203,8 +203,8 @@
 	  //LIR
 	  CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Request", &data.command, ENOENT) );
-	  CHECK_FCT( fd_disp_register( app_sip_SL_LIR_cb, DISP_HOW_CC, &data, &app_sip_SL_LIR_hdl ) );
+	  CHECK_FCT( fd_disp_register( app_sip_SL_LIR_cb, DISP_HOW_CC, &data, NULL, &app_sip_SL_LIR_hdl ) );
 	}
 	//Callback for unexpected messages
-	CHECK_FCT( fd_disp_register( app_sip_default_cb, DISP_HOW_APPID, &data, &app_sip_default_hdl ) );
+	CHECK_FCT( fd_disp_register( app_sip_default_cb, DISP_HOW_APPID, &data, NULL, &app_sip_default_hdl ) );
 	
 	
@@ -213,5 +213,5 @@
 		return EINVAL;
 	
-	CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, free));
+	CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, free, NULL));
 	
 	//Creation of thread for Registration Termination	
@@ -237,6 +237,6 @@
 	//TODO:unregister other callbacks
 	
-	(void) fd_disp_unregister(&app_sip_MAR_hdl);
-	CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl),return);
+	(void) fd_disp_unregister(&app_sip_MAR_hdl, NULL);
+	CHECK_FCT_DO( fd_sess_handler_destroy(&ds_sess_hdl, NULL),return);
 	
 	
Index: extensions/app_sip/app_sip.h
===================================================================
--- extensions/app_sip/app_sip.h	(revision 468)
+++ extensions/app_sip/app_sip.h	(revision 639)
@@ -140,15 +140,15 @@
 int ds_entry();
 void fd_ext_fini(void);
-int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_MAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_RTA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_PPA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_LIR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_UAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int app_sip_SAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
+int app_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_MAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_RTA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_PPA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_LIR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_UAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int app_sip_SAR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
 
 //Suscriber Locator
-int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act);
-//int app_sip_SL_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act);
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
+//int app_sip_SL_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act);
 
 #define SQL_GETPASSWORD "SELECT `password` FROM ds_users WHERE `username` ='%s'"
Index: extensions/app_sip/locationinfo.c
===================================================================
--- extensions/app_sip/locationinfo.c	(revision 433)
+++ extensions/app_sip/locationinfo.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int app_sip_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
Index: extensions/app_sip/locationinfosl.c
===================================================================
--- extensions/app_sip/locationinfosl.c	(revision 433)
+++ extensions/app_sip/locationinfosl.c	(revision 639)
@@ -37,5 +37,5 @@
 
 //This callback is specific to SUSCRIBER LOCATOR. We must look for the "serving" SIP server
-int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_SL_LIR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
Index: extensions/app_sip/multimediaauth.c
===================================================================
--- extensions/app_sip/multimediaauth.c	(revision 433)
+++ extensions/app_sip/multimediaauth.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int app_sip_MAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_MAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	struct msg *ans, *qry;
Index: extensions/app_sip/pushprofile.c
===================================================================
--- extensions/app_sip/pushprofile.c	(revision 440)
+++ extensions/app_sip/pushprofile.c	(revision 639)
@@ -255,5 +255,5 @@
 
 //Called when an PPA arrive
-int app_sip_PPA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_PPA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	//TODO: PPA reception
Index: extensions/app_sip/registrationtermination.c
===================================================================
--- extensions/app_sip/registrationtermination.c	(revision 440)
+++ extensions/app_sip/registrationtermination.c	(revision 639)
@@ -258,5 +258,5 @@
 
 //Called when an RTA arrive
-int app_sip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	//TODO: RTA reception
Index: extensions/app_sip/serverassignment.c
===================================================================
--- extensions/app_sip/serverassignment.c	(revision 433)
+++ extensions/app_sip/serverassignment.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int app_sip_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_SAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
Index: extensions/app_sip/userauthorization.c
===================================================================
--- extensions/app_sip/userauthorization.c	(revision 433)
+++ extensions/app_sip/userauthorization.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int app_sip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int app_sip_UAR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	TRACE_ENTRY("%p %p %p %p", msg, paramavp, sess, act);
Index: extensions/dbg_interactive/dbg_interactive.c
===================================================================
--- extensions/dbg_interactive/dbg_interactive.c	(revision 625)
+++ extensions/dbg_interactive/dbg_interactive.c	(revision 639)
@@ -67,6 +67,8 @@
 	
 end:	
-	/* Upon exit, issue the order of terminating to fD */
-	CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
+	/* Upon exit, issue the order of terminating to fD, if the interpreter was started without a file */
+	if (!arg) {
+		CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
+	}
 
 	return NULL;
Index: extensions/dbg_interactive/dispatch.i
===================================================================
--- extensions/dbg_interactive/dispatch.i	(revision 638)
+++ extensions/dbg_interactive/dispatch.i	(revision 639)
@@ -40,15 +40,15 @@
 
 %{
-/* store the python callback function here */
-static PyObject * py_dispatch_cb = NULL;
-static int        py_dispatch_cb_n = 0;
 /* call it (will be called from a different thread than the interpreter, when message arrives) */
-static int call_the_python_dispatch_callback(struct msg **msg, struct avp *avp, struct session *session, enum disp_action *action) {
+static int call_the_python_dispatch_callback(struct msg **msg, struct avp *avp, struct session *session, void * pycb, enum disp_action *action) {
 	PyObject *PyMsg, *PyAvp, *PySess;
-	PyObject *result = NULL;
+	PyObject *cb, *result = NULL;
 	int ret = 0;
 	
-	if (!py_dispatch_cb)
+	if (!pycb) {
+		fd_log_debug("Internal error: missing the callback!\n");
 		return ENOTSUP;
+	}
+	cb = pycb;
 	
 	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
@@ -59,5 +59,5 @@
 	
 	/* Call the function */
-	result = PyEval_CallFunction(py_dispatch_cb, "(OOO)", PyMsg, PyAvp, PySess);
+	result = PyEval_CallFunction(cb, "(OOO)", PyMsg, PyAvp, PySess);
 	
 	/* The result is supposedly composed of: [ ret, *msg, *action ] */
@@ -108,13 +108,8 @@
 		struct disp_hdl * hdl = NULL;
 		int ret;
-		if (py_dispatch_cb && (py_dispatch_cb != PyCb)) {
-			DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one dispatch callback is supported at the moment in this extension\n.");
-			return NULL;
-		}
-		py_dispatch_cb = PyCb;
-		py_dispatch_cb_n += 1;
-		Py_XINCREF(py_dispatch_cb);
 		
-		ret = fd_disp_register ( call_the_python_dispatch_callback, how, when, &hdl );
+		Py_XINCREF(PyCb);
+		
+		ret = fd_disp_register ( call_the_python_dispatch_callback, how, when, PyCb, &hdl );
 		if (ret != 0) {
 			DI_ERROR(ret, NULL, NULL);
@@ -125,13 +120,10 @@
 	~disp_hdl() {
 		struct disp_hdl * hdl = self;
-		int ret = fd_disp_unregister(&hdl);
+		PyObject * cb = NULL;
+		int ret = fd_disp_unregister(&hdl, (void *)&cb);
 		if (ret != 0) {
 			DI_ERROR(ret, NULL, NULL);
 		}
-		/* Now free the callback */
-		Py_XDECREF(py_dispatch_cb);
-		py_dispatch_cb_n -= 1;
-		if (!py_dispatch_cb_n)
-			py_dispatch_cb = NULL;
+		Py_XDECREF(cb);
 		return;
 	}
Index: extensions/dbg_interactive/sessions.i
===================================================================
--- extensions/dbg_interactive/sessions.i	(revision 638)
+++ extensions/dbg_interactive/sessions.i	(revision 639)
@@ -39,15 +39,15 @@
 
 %{
-/* store the python callback function here */
-static PyObject * py_cleanup_cb = NULL;
 /* call it (might be called from a different thread than the interpreter, when session times out) */
-static void call_the_python_cleanup_callback(session_state * state, char * sid) {
+static void call_the_python_cleanup_callback(session_state * state, char * sid, void * cb) {
 	PyObject *result;
-	if (!py_cleanup_cb)
+	if (!cb) {
+		fd_log_debug("Internal error: missing callback object!\n");
 		return;
+	}
 	
 	/* Call the function */
 	SWIG_PYTHON_THREAD_BEGIN_BLOCK;
-	result = PyEval_CallFunction(py_cleanup_cb, "(Os)", state, sid);
+	result = PyEval_CallFunction((PyObject *)cb, "(Os)", state, sid);
 	Py_XDECREF(result);
 	SWIG_PYTHON_THREAD_END_BLOCK;
@@ -64,12 +64,8 @@
 		struct session_handler * hdl = NULL;
 		int ret;
-		if (py_cleanup_cb) {
-			DI_ERROR(EINVAL, PyExc_SyntaxError, "Only one session handler at a time is supported at the moment in this extension\n.");
-			return NULL;
-		}
-		py_cleanup_cb = PyCb;
-		Py_XINCREF(py_cleanup_cb);
 		
-		ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback );
+		Py_XINCREF(PyCb);
+		
+		ret = fd_sess_handler_create_internal ( &hdl, call_the_python_cleanup_callback, PyCb );
 		if (ret != 0) {
 			DI_ERROR(ret, NULL, NULL);
@@ -80,11 +76,12 @@
 	~session_handler() {
 		struct session_handler * hdl = self;
-		int ret = fd_sess_handler_destroy(&hdl);
+		PyObject * cb = NULL;
+		
+		int ret = fd_sess_handler_destroy(&hdl, (void *)&cb);
 		if (ret != 0) {
 			DI_ERROR(ret, NULL, NULL);
 		}
 		/* Now free the callback */
-		Py_XDECREF(py_cleanup_cb);
-		py_cleanup_cb = NULL;
+		Py_XDECREF(cb);
 		return;
 	}
Index: extensions/test_app/ta_cli.c
===================================================================
--- extensions/test_app/ta_cli.c	(revision 406)
+++ extensions/test_app/ta_cli.c	(revision 639)
@@ -234,5 +234,5 @@
 int ta_cli_init(void)
 {
-	CHECK_FCT( fd_sess_handler_create(&ta_cli_reg, free) );
+	CHECK_FCT( fd_sess_handler_create(&ta_cli_reg, free, NULL) );
 	
 	CHECK_FCT( fd_sig_register(ta_conf->signal, "test_app.cli", ta_cli_test_message ) );
@@ -245,5 +245,5 @@
 	CHECK_FCT_DO( fd_sig_unregister(ta_conf->signal), /* continue */ );
 	
-	CHECK_FCT_DO( fd_sess_handler_destroy(&ta_cli_reg), /* continue */ );
+	CHECK_FCT_DO( fd_sess_handler_destroy(&ta_cli_reg, NULL), /* continue */ );
 	
 	return;
Index: extensions/test_app/ta_serv.c
===================================================================
--- extensions/test_app/ta_serv.c	(revision 575)
+++ extensions/test_app/ta_serv.c	(revision 639)
@@ -42,5 +42,5 @@
 
 /* Default callback for the application. */
-static int ta_fb_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+static int ta_fb_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	/* This CB should never be called */
@@ -53,5 +53,5 @@
 
 /* Callback for incoming Test-Request messages */
-static int ta_tr_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+static int ta_tr_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	struct msg *ans, *qry;
@@ -120,8 +120,8 @@
 	
 	/* fallback CB if command != Test-Request received */
-	CHECK_FCT( fd_disp_register( ta_fb_cb, DISP_HOW_APPID, &data, &ta_hdl_fb ) );
+	CHECK_FCT( fd_disp_register( ta_fb_cb, DISP_HOW_APPID, &data, NULL, &ta_hdl_fb ) );
 	
 	/* Now specific handler for Test-Request */
-	CHECK_FCT( fd_disp_register( ta_tr_cb, DISP_HOW_CC, &data, &ta_hdl_tr ) );
+	CHECK_FCT( fd_disp_register( ta_tr_cb, DISP_HOW_CC, &data, NULL, &ta_hdl_tr ) );
 	
 	return 0;
@@ -131,8 +131,8 @@
 {
 	if (ta_hdl_fb) {
-		(void) fd_disp_unregister(&ta_hdl_fb);
+		(void) fd_disp_unregister(&ta_hdl_fb, NULL);
 	}
 	if (ta_hdl_tr) {
-		(void) fd_disp_unregister(&ta_hdl_tr);
+		(void) fd_disp_unregister(&ta_hdl_tr, NULL);
 	}
 	
Index: extensions/test_sip/locationinfo.c
===================================================================
--- extensions/test_sip/locationinfo.c	(revision 430)
+++ extensions/test_sip/locationinfo.c	(revision 639)
@@ -125,5 +125,5 @@
 }
 
-int test_sip_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sip_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	
Index: extensions/test_sip/locationinfosl.c
===================================================================
--- extensions/test_sip/locationinfosl.c	(revision 430)
+++ extensions/test_sip/locationinfosl.c	(revision 639)
@@ -127,5 +127,5 @@
 }
 
-int test_sipSL_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sipSL_LIA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	
Index: extensions/test_sip/multimediaauth.c
===================================================================
--- extensions/test_sip/multimediaauth.c	(revision 409)
+++ extensions/test_sip/multimediaauth.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int test_sip_MAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sip_MAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 /*
Index: extensions/test_sip/registrationtermination.c
===================================================================
--- extensions/test_sip/registrationtermination.c	(revision 409)
+++ extensions/test_sip/registrationtermination.c	(revision 639)
@@ -37,5 +37,5 @@
 
 
-int test_sip_RTR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sip_RTR_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	
Index: extensions/test_sip/serverassignment.c
===================================================================
--- extensions/test_sip/serverassignment.c	(revision 432)
+++ extensions/test_sip/serverassignment.c	(revision 639)
@@ -168,5 +168,5 @@
 }
 
-int test_sip_SAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sip_SAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	
Index: extensions/test_sip/test_sip.c
===================================================================
--- extensions/test_sip/test_sip.c	(revision 448)
+++ extensions/test_sip/test_sip.c	(revision 639)
@@ -64,5 +64,5 @@
 struct sip_dict sip_dict;
 
-int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act)
+int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	TRACE_ENTRY("%p %p %p %p", msg, avp, sess, act);
@@ -187,24 +187,24 @@
 	//MAA
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Multimedia-Auth-Answer", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( test_sip_MAA_cb, DISP_HOW_CC, &data, &test_sip_MAA_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_MAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_MAA_hdl ) );
 	
 	//UAA
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "User-Authorization-Answer", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( test_sip_UAA_cb, DISP_HOW_CC, &data, &test_sip_UAA_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_UAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_UAA_hdl ) );
 	
 	//RTR
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( test_sip_RTR_cb, DISP_HOW_CC, &data, &test_sip_RTR_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_RTR_cb, DISP_HOW_CC, &data, NULL, &test_sip_RTR_hdl ) );
 	
 	//LIA
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Location-Info-Answer", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( test_sip_LIA_cb, DISP_HOW_CC, &data, &test_sip_LIA_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_LIA_cb, DISP_HOW_CC, &data, NULL, &test_sip_LIA_hdl ) );
 	
 	//LIA
 	CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Server-Assignment-Answer", &data.command, ENOENT) );
-	CHECK_FCT( fd_disp_register( test_sip_SAA_cb, DISP_HOW_CC, &data, &test_sip_SAA_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_SAA_cb, DISP_HOW_CC, &data, NULL, &test_sip_SAA_hdl ) );
 	
 	//Callback for unexpected messages
-	CHECK_FCT( fd_disp_register( test_sip_default_cb, DISP_HOW_APPID, &data, &test_sip_default_hdl ) );
+	CHECK_FCT( fd_disp_register( test_sip_default_cb, DISP_HOW_APPID, &data, NULL, &test_sip_default_hdl ) );
 	
 	/*
@@ -214,5 +214,5 @@
 	*/
 	
-	CHECK_FCT(fd_sess_handler_create(&ts_sess_hdl, free));
+	CHECK_FCT(fd_sess_handler_create(&ts_sess_hdl, free, NULL));
 	//CHECK_FCT( fd_sig_register(30, "test_sip", (void *)test_sipSL_LIR_cb ) );
 	CHECK_FCT( fd_sig_register(30, "test_sip", (void *)test_sip_SAR_cb ) );
Index: extensions/test_sip/test_sip.h
===================================================================
--- extensions/test_sip/test_sip.h	(revision 427)
+++ extensions/test_sip/test_sip.h	(revision 639)
@@ -115,9 +115,9 @@
 int test_sipSL_LIR_cb();
 
-int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sip_MAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sip_RTR_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sip_UAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sip_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sip_SAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
-int test_sipSL_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act);
+int test_sip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_MAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_RTR_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_UAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sip_SAA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
+int test_sipSL_LIA_cb( struct msg ** msg, struct avp * avp, struct session * sess, void * opaque, enum disp_action * act);
Index: extensions/test_sip/userauthorization.c
===================================================================
--- extensions/test_sip/userauthorization.c	(revision 430)
+++ extensions/test_sip/userauthorization.c	(revision 639)
@@ -159,5 +159,5 @@
 }
 
-int test_sip_UAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act)
+int test_sip_UAA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, void * opaque, enum disp_action * act)
 {
 	
Index: freeDiameter/tests/testdisp.c
===================================================================
--- freeDiameter/tests/testdisp.c	(revision 90)
+++ freeDiameter/tests/testdisp.c	(revision 639)
@@ -36,16 +36,19 @@
 #include "tests.h"
 	
-#define Define_cb( __int, __extra )										\
-int cb_##__int( struct msg ** msg, struct avp * avp, struct session * session, enum disp_action * action )	\
-{														\
-	CHECK( 1, msg ? 1 : 0 );										\
-	CHECK( 1, action ? 1 : 0 );										\
-	CHECK( sess, session );											\
-	*action = DISP_ACT_CONT;										\
-	cbcalled[__int] += 1;											\
-	do {													\
-		__extra ;											\
-	} while (0);												\
-	return 0;												\
+#define Define_cb( __int, __extra )												\
+int cb_##__int( struct msg ** msg, struct avp * avp, struct session * session, void * opaque, enum disp_action * action )	\
+{																\
+	CHECK( 1, msg ? 1 : 0 );												\
+	CHECK( 1, action ? 1 : 0 );												\
+	CHECK( sess, session );													\
+	if (opaque) {														\
+		CHECK( 1, opaque == g_opaque ? 1 : 0 );										\
+	}															\
+	*action = DISP_ACT_CONT;												\
+	cbcalled[__int] += 1;													\
+	do {															\
+		__extra ;													\
+	} while (0);														\
+	return 0;														\
 }
 
@@ -53,4 +56,5 @@
 char cbcalled[NB_CB];
 struct session * sess;
+void * g_opaque = (void *)"test";
 
 /* cb_0 */  Define_cb( 0, );
@@ -142,9 +146,9 @@
 	/* Register first handler, very simple test */
 	{
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, NULL, &hdl[0] ) );
 		CHECK( 1, hdl[0] ? 1 : 0 );
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
 		CHECK( NULL, hdl[0] );
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, NULL, &hdl[0] ) );
 	
 		/* Check this handler is called for a message */
@@ -157,18 +161,18 @@
 		/* Delete the message */
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
 	}
 	
 	/* Handlers for applications */
 	{
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
 		when.app = app1;
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_APPID, &when, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_APPID, &when, NULL, &hdl[1] ) );
 		when.app = app2;
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_APPID, &when, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_APPID, &when, NULL, &hdl[2] ) );
 		when.avp = avp2;
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_APPID, &when, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_APPID, &when, NULL, &hdl[3] ) );
 		when.avp = avp1;
-		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, &hdl[4] ) );
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, NULL, &hdl[4] ) );
 	
 		/* Check the callbacks are called as appropriate */
@@ -206,9 +210,9 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
 	}
 	
@@ -217,14 +221,14 @@
 		when.app = NULL;
 		when.command = NULL;
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
-		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_CC, &when, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_CC, &when, NULL, &hdl[1] ) );
 		when.command = cmd1;
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_CC, &when, &hdl[1] ) ); /* cmd1 */
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_CC, &when, NULL, &hdl[1] ) ); /* cmd1 */
 		when.app = app2;
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_CC, &when, &hdl[2] ) ); /* app2 + cmd1 */
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_CC, &when, NULL, &hdl[2] ) ); /* app2 + cmd1 */
 		when.command = cmd2;
 		when.app = NULL;
 		when.avp = avp1;
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, &hdl[3] ) ); /* cmd2 (avp1 ignored) */
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, NULL, &hdl[3] ) ); /* cmd2 (avp1 ignored) */
 		
 		/* Check the callbacks are called as appropriate */
@@ -269,8 +273,8 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
 	}
 	
@@ -281,19 +285,19 @@
 		when.avp = NULL;
 	
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) ); /* all */
-		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP, &when, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) ); /* all */
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP, &when, NULL, &hdl[1] ) );
 		
 		when.avp = avp1;
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP, &when, &hdl[1] ) ); /* avp1 */
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP, &when, NULL, &hdl[1] ) ); /* avp1 */
 		
 		when.command = cmd1;
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, &hdl[2] ) ); /* avp1 + cmd1 */
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, NULL, &hdl[2] ) ); /* avp1 + cmd1 */
 		
 		when.command = NULL;
 		when.app = app1;
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP, &when, &hdl[3] ) ); /* avp1 + app1 */
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP, &when, NULL, &hdl[3] ) ); /* avp1 + app1 */
 		
 		when.command = cmd1;
-		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_AVP, &when, &hdl[4] ) ); /* avp1 + cmd1 + app1 */
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_AVP, &when, NULL, &hdl[4] ) ); /* avp1 + cmd1 + app1 */
 		
 		when.app = NULL;
@@ -301,8 +305,8 @@
 		when.avp = avp2;
 		when.value = enu1;
-		CHECK( 0, fd_disp_register( cb_5, DISP_HOW_AVP, &when, &hdl[5] ) ); /* avp2 */
+		CHECK( 0, fd_disp_register( cb_5, DISP_HOW_AVP, &when, NULL, &hdl[5] ) ); /* avp2 */
 		
 		when.value = enu2;
-		CHECK( 0, fd_disp_register( cb_7, DISP_HOW_AVP, &when, &hdl[6] ) ); /* avp2 */
+		CHECK( 0, fd_disp_register( cb_7, DISP_HOW_AVP, &when, NULL, &hdl[6] ) ); /* avp2 */
 		
 		
@@ -396,11 +400,11 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[6] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[6], NULL ) );
 	}
 		
@@ -412,20 +416,20 @@
 		when.value = NULL;
 		
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) ); /* all */
-		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) ); /* all */
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
 		when.value = enu1;
-		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, &hdl[1] ) );
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
 		when.avp = avp1;
-		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, &hdl[1] ) );
+		CHECK( EINVAL, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
 		when.avp = avp2;
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, &hdl[1] ) ); /* avp2, enu1 */
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) ); /* avp2, enu1 */
 		
 		when.command = cmd1;
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP_ENUMVAL, &when, &hdl[2] ) ); /* avp2, enu1 + cmd1 */
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[2] ) ); /* avp2, enu1 + cmd1 */
 		
 		when.command = NULL;
 		when.app = app1;
 		when.value = enu2;
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP_ENUMVAL, &when, &hdl[3] ) ); /* avp2, enu2 + app1 */
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[3] ) ); /* avp2, enu2 + app1 */
 		
 		/* Check the callbacks are called as appropriate */
@@ -498,17 +502,17 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
 	}
 	
 	/* Test behavior of handlers */
 	{
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, &hdl[1] ) );
-		CHECK( 0, fd_disp_register( cb_6, DISP_HOW_ANY, &when, &hdl[2] ) );
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, &hdl[3] ) );
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, &hdl[4] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_6, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
 		
 		memset(cbcalled, 0, sizeof(cbcalled));
@@ -522,15 +526,15 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
-		
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, &hdl[1] ) );
-		CHECK( 0, fd_disp_register( cb_8, DISP_HOW_ANY, &when, &hdl[2] ) );
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, &hdl[3] ) );
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, &hdl[4] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_8, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
 		
 		memset(cbcalled, 0, sizeof(cbcalled));
@@ -544,15 +548,15 @@
 		CHECK( NULL, msg );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
-		
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, &hdl[1] ) );
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, &hdl[2] ) );
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, &hdl[3] ) );
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, &hdl[4] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_ANY, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_ANY, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_ANY, &when, NULL, &hdl[4] ) );
 		
 		memset(cbcalled, 0, sizeof(cbcalled));
@@ -567,9 +571,9 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
 	}
 		
@@ -581,9 +585,9 @@
 		when.value = enu2;
 		
-		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, &hdl[0] ) );
-		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, &hdl[1] ) );
-		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, &hdl[2] ) );
-		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, &hdl[3] ) );
-		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, &hdl[4] ) );
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, &when, NULL, &hdl[0] ) );
+		CHECK( 0, fd_disp_register( cb_1, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[1] ) );
+		CHECK( 0, fd_disp_register( cb_2, DISP_HOW_AVP, &when, NULL, &hdl[2] ) );
+		CHECK( 0, fd_disp_register( cb_3, DISP_HOW_CC, &when, NULL, &hdl[3] ) );
+		CHECK( 0, fd_disp_register( cb_4, DISP_HOW_APPID, &when, NULL, &hdl[4] ) );
 		
 		memset(cbcalled, 0, sizeof(cbcalled));
@@ -598,5 +602,5 @@
 		CHECK( 0, fd_msg_free( msg ) );
 		
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, &hdl[5] ) );
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_ANY, &when, NULL, &hdl[5] ) );
 		memset(cbcalled, 0, sizeof(cbcalled));
 		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
@@ -609,7 +613,7 @@
 		CHECK( 1, cbcalled[9] );
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP_ENUMVAL, &when, &hdl[5] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP_ENUMVAL, &when, NULL, &hdl[5] ) );
 		memset(cbcalled, 0, sizeof(cbcalled));
 		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
@@ -622,7 +626,7 @@
 		CHECK( 1, cbcalled[9] );
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP, &when, &hdl[5] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_AVP, &when, NULL, &hdl[5] ) );
 		memset(cbcalled, 0, sizeof(cbcalled));
 		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
@@ -635,7 +639,7 @@
 		CHECK( 1, cbcalled[9] );
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_CC, &when, &hdl[5] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_CC, &when, NULL, &hdl[5] ) );
 		memset(cbcalled, 0, sizeof(cbcalled));
 		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
@@ -648,7 +652,7 @@
 		CHECK( 1, cbcalled[9] );
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		
-		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_APPID, &when, &hdl[5] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_register( cb_9, DISP_HOW_APPID, &when, NULL, &hdl[5] ) );
 		memset(cbcalled, 0, sizeof(cbcalled));
 		msg = new_msg( 2, cmd2, avp1, avp2, 2 );
@@ -661,11 +665,11 @@
 		CHECK( 1, cbcalled[9] );
 		CHECK( 0, fd_msg_free( msg ) );
-		CHECK( 0, fd_disp_unregister( &hdl[5] ) );
-		
-		CHECK( 0, fd_disp_unregister( &hdl[0] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[1] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[2] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[3] ) );
-		CHECK( 0, fd_disp_unregister( &hdl[4] ) );
+		CHECK( 0, fd_disp_unregister( &hdl[5], NULL ) );
+		
+		CHECK( 0, fd_disp_unregister( &hdl[0], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[1], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[2], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[3], NULL ) );
+		CHECK( 0, fd_disp_unregister( &hdl[4], NULL ) );
 	}			
 	
@@ -698,4 +702,22 @@
 	}
 	
+	/* Test opaque pointer management */
+	{
+		void * ptr;
+		CHECK( 0, fd_disp_register( cb_0, DISP_HOW_ANY, NULL, g_opaque, &hdl[0] ) );
+	
+		/* Check this handler is called for a message */
+		msg = new_msg( 0, cmd1, avp1, NULL, 0 );
+		memset(cbcalled, 0, sizeof(cbcalled));
+		CHECK( 0, fd_msg_dispatch ( &msg, sess, &action, &ec ) );
+		CHECK( 1, cbcalled[0] );
+		CHECK( DISP_ACT_CONT, action );
+		
+		/* Delete the message */
+		CHECK( 0, fd_msg_free( msg ) );
+		CHECK( 0, fd_disp_unregister( &hdl[0], &ptr ) );
+		CHECK( 1, ptr == g_opaque ? 1 : 0 );
+	}
+	
 	/* That's all for the tests yet */
 	PASSTEST();
Index: freeDiameter/tests/testsess.c
===================================================================
--- freeDiameter/tests/testsess.c	(revision 403)
+++ freeDiameter/tests/testsess.c	(revision 639)
@@ -45,7 +45,8 @@
 	char *  sid; 	/* the session with which the data was registered */
 	int  *  freed;	/* location where to write the freed status */
+	void *  opaque; /* if opaque was provided, this is the value we expect */
 };
 
-static void mycleanup( struct mystate * data, char * sid )
+static void mycleanup( struct mystate * data, char * sid, void * opaque )
 {
 	/* sanity */
@@ -56,4 +57,7 @@
 	if (data->freed)
 		*(data->freed) += 1;
+	if (data->opaque) {
+		CHECK( 1, opaque == data->opaque ? 1 : 0 );  
+	}
 	/* Now, free the data */
 	free(data->sid);
@@ -73,4 +77,6 @@
 	return new;
 }
+
+void * g_opaque = (void *)"test";
 	
 
@@ -88,8 +94,10 @@
 	/* Test functions related to handlers (simple situation) */
 	{
-		CHECK( 0, fd_sess_handler_create ( &hdl1, mycleanup ) );
-		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup ) );
-		CHECK( 0, fd_sess_handler_destroy( &hdl2 ) );
-		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup ) );
+		void * testptr = NULL;
+		CHECK( 0, fd_sess_handler_create ( &hdl1, mycleanup, NULL ) );
+		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, NULL ) );
+		CHECK( 0, fd_sess_handler_destroy( &hdl2, &testptr ) );
+		CHECK( 1, testptr == NULL ? 1 : 0 );
+		CHECK( 0, fd_sess_handler_create ( &hdl2, mycleanup, g_opaque ) );
 		#if 0
 		fd_sess_dump_hdl(0, hdl1);
@@ -237,4 +245,5 @@
 		int freed[6];
 		struct timespec timeout;
+		void * testptr = NULL;
 		
 		/* Create three sessions */
@@ -267,6 +276,6 @@
 		CHECK( NULL, tms );
 		
-		mycleanup(ms[0], str1);
-		mycleanup(ms[1], str1);
+		mycleanup(ms[0], str1, NULL);
+		mycleanup(ms[1], str1, NULL);
 		
 		/* Now create 6 states */
@@ -281,4 +290,5 @@
 		ms[4] = new_state(str1, &freed[4]);
 		ms[5] = new_state(str1, &freed[5]);
+		ms[5]->opaque = g_opaque;
 		str2 = strdup(str1);
 		CHECK( 1, str2 ? 1 : 0 );
@@ -308,5 +318,5 @@
 		
 		/* Destroy handler 2 */
-		CHECK( 0, fd_sess_handler_destroy( &hdl2 ) );
+		CHECK( 0, fd_sess_handler_destroy( &hdl2, &testptr ) );
 		CHECK( 0, freed[0] );
 		CHECK( 1, freed[1] );
@@ -315,4 +325,5 @@
 		CHECK( 1, freed[4] );
 		CHECK( 1, freed[5] );
+		CHECK( 1, testptr == g_opaque ? 1 : 0 );
 		
 		#if 1
@@ -349,5 +360,5 @@
 		CHECK( 0, fd_sess_state_retrieve( hdl1, sess1, &tms ) );
 		CHECK( 0, fd_sess_getsid(sess1, &str1) );
-		mycleanup(tms, str1);
+		mycleanup(tms, str1, NULL);
 	}
 	
Index: include/freeDiameter/libfreeDiameter.h
===================================================================
--- include/freeDiameter/libfreeDiameter.h	(revision 638)
+++ include/freeDiameter/libfreeDiameter.h	(revision 639)
@@ -1559,4 +1559,5 @@
  *  handler	: location where the new handler must be stored.
  *  cleanup	: a callback function that must be called when the session with associated data is destroyed.
+ *  opaque      : A pointer that is passed to the cleanup callback -- the content is never examined by the framework.
  *
  * DESCRIPTION: 
@@ -1570,8 +1571,8 @@
  *  ENOMEM	: Not enough memory to complete the operation
  */
-int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, char * sid) );
+int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, char * sid, void * opaque), void * opaque );
 /* Macro to avoid casting everywhere */
-#define fd_sess_handler_create( _handler, _cleanup ) \
-	fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, char *))(_cleanup) )
+#define fd_sess_handler_create( _handler, _cleanup, _opaque ) \
+	fd_sess_handler_create_internal( (_handler), (void (*)(session_state *, char *, void *))(_cleanup), (void *)(_opaque) )
 
 	
@@ -1581,4 +1582,5 @@
  * PARAMETERS:
  *  handler	: location of an handler created by fd_sess_handler_create.
+ *  opaque      : the opaque pointer registered with the callback is restored here (if ! NULL).
  *
  * DESCRIPTION: 
@@ -1591,5 +1593,5 @@
  *  ENOMEM	: Not enough memory to complete the operation
  */
-int fd_sess_handler_destroy ( struct session_handler ** handler );
+int fd_sess_handler_destroy ( struct session_handler ** handler, void **opaque );
 
 
@@ -2526,4 +2528,5 @@
  *  avp 	: for callbacks registered with DISP_HOW_AVP or DISP_HOW_AVP_ENUMVAL, direct link to the triggering AVP.
  *  session	: if the message contains a Session-Id AVP, the corresponding session object, NULL otherwise.
+ *  opaque      : An opaque pointer that is registered along the session handler.
  *  action	: upon return, this tells the daemon what to do next.
  *
@@ -2557,4 +2560,5 @@
  *  how	  	  : How the callback must be registered.
  *  when          : Values that must match, depending on the how argument.
+ *  opaque        : A pointer that is passed back to the handler. The content is not interpreted by the framework.
  *  handle        : On success, a handler to the registered callback is stored here if not NULL. 
  *		   This handler can be used to unregister the cb.
@@ -2568,6 +2572,6 @@
  *  ENOMEM	: Not enough memory to complete the operation
  */
-int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, enum disp_action *), 
-			enum disp_how how, struct disp_when * when, struct disp_hdl ** handle );
+int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *), 
+			enum disp_how how, struct disp_when * when, void * opaque, struct disp_hdl ** handle );
 
 /*
@@ -2576,4 +2580,5 @@
  * PARAMETERS:
  *  handle       : Location of the handle of the callback that must be unregistered.
+ *  opaque       : If not NULL, the opaque data that was registered is restored here.
  *
  * DESCRIPTION: 
@@ -2584,5 +2589,5 @@
  *  EINVAL 	: A parameter is invalid.
  */
-int fd_disp_unregister ( struct disp_hdl ** handle );
+int fd_disp_unregister ( struct disp_hdl ** handle, void ** opaque );
 
 /* Destroy all handlers */
Index: libfreeDiameter/dispatch.c
===================================================================
--- libfreeDiameter/dispatch.c	(revision 398)
+++ libfreeDiameter/dispatch.c	(revision 639)
@@ -56,5 +56,6 @@
 	enum disp_how	 how;	/* Copy of registration parameter */
 	struct disp_when when;	/* Copy of registration parameter */
-	int		(*cb)( struct msg **, struct avp *, struct session *, enum disp_action *);	/* The callback itself */
+	int		(*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *);	/* The callback itself */
+	void            *opaque; /* opaque data passed back to the callback */
 };
 
@@ -93,5 +94,5 @@
 		
 		/* We have a match, the cb must be called. */
-		CHECK_FCT( (*hdl->cb)(msg, avp, sess, action) );
+		CHECK_FCT( (*hdl->cb)(msg, avp, sess, hdl->opaque, action) );
 		
 		if (*action != DISP_ACT_CONT)
@@ -109,6 +110,6 @@
 
 /* Create a new handler and link it */
-int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, enum disp_action *), 
-			enum disp_how how, struct disp_when * when, struct disp_hdl ** handle )
+int fd_disp_register ( int (*cb)( struct msg **, struct avp *, struct session *, void *, enum disp_action *), 
+			enum disp_how how, struct disp_when * when, void * opaque, struct disp_hdl ** handle )
 {
 	struct fd_list * cb_list = NULL;
@@ -171,4 +172,5 @@
 	}
 	new->cb = cb;
+	new->opaque = opaque;
 	
 	/* Now, link this new element in the appropriate lists */
@@ -186,5 +188,5 @@
 
 /* Delete a handler */
-int fd_disp_unregister ( struct disp_hdl ** handle )
+int fd_disp_unregister ( struct disp_hdl ** handle, void ** opaque )
 {
 	struct disp_hdl * del;
@@ -199,4 +201,7 @@
 	CHECK_POSIX( pthread_rwlock_unlock(&fd_disp_lock) );
 	
+	if (opaque)
+		*opaque = del->opaque;
+	
 	free(del);
 	return 0;
@@ -208,5 +213,5 @@
 	TRACE_ENTRY("");
 	while (!FD_IS_LIST_EMPTY(&all_handlers)) {
-		CHECK_FCT_DO( fd_disp_unregister((void *)&(all_handlers.next->o)), /* continue */ );
+		CHECK_FCT_DO( fd_disp_unregister((void *)&(all_handlers.next->o), NULL), /* continue */ );
 	}
 	return;
Index: libfreeDiameter/sessions.c
===================================================================
--- libfreeDiameter/sessions.c	(revision 557)
+++ libfreeDiameter/sessions.c	(revision 639)
@@ -69,5 +69,6 @@
 	int		  eyec;	/* An eye catcher also used to ensure the object is valid, must be SH_EYEC */
 	int		  id;	/* A unique integer to identify this handler */
-	void 		(*cleanup)(session_state *, char *); /* The cleanup function to be called for cleaning a state */
+	void 		(*cleanup)(session_state *, char *, void *); /* The cleanup function to be called for cleaning a state */
+	void             *opaque; /* a value that is passed as is to the cleanup callback */
 };
 
@@ -253,5 +254,5 @@
 
 /* Create a new handler */
-int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, char * sid) )
+int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state * state, char * sid, void * opaque), void * opaque )
 {
 	struct session_handler *new;
@@ -270,4 +271,5 @@
 	new->eyec = SH_EYEC;
 	new->cleanup = cleanup;
+	new->opaque = opaque;
 	
 	*handler = new;
@@ -277,5 +279,5 @@
 /* Destroy a handler, and all states attached to this handler. This operation is very slow but we don't care since it's rarely used. 
  * Note that it's better to call this function after all sessions have been deleted... */
-int fd_sess_handler_destroy ( struct session_handler ** handler )
+int fd_sess_handler_destroy ( struct session_handler ** handler, void ** opaque )
 {
 	struct session_handler * del;
@@ -323,9 +325,12 @@
 		struct state * st = (struct state *)(deleted_states.next->o);
 		TRACE_DEBUG(FULL, "Calling cleanup handler for session '%s' and data %p", st->sid, st->state);
-		(*del->cleanup)(st->state, st->sid);
+		(*del->cleanup)(st->state, st->sid, del->opaque);
 		free(st->sid);
 		fd_list_unlink(&st->chain);
 		free(st);
 	}
+	
+	if (opaque)
+		*opaque = del->opaque;
 	
 	/* Free the handler */
@@ -583,5 +588,5 @@
 		fd_list_unlink(&st->chain);
 		TRACE_DEBUG(FULL, "Calling handler %p cleanup for state registered with session '%s'", st->hdl, sess->sid);
-		(*st->hdl->cleanup)(st->state, sess->sid);
+		(*st->hdl->cleanup)(st->state, sess->sid, st->hdl->opaque);
 		free(st);
 	}
@@ -805,5 +810,5 @@
 		fd_log_debug("\t  %*s  Invalid session handler object\n", level, "");
 	} else {
-		fd_log_debug("\t  %*s  id %d, cleanup %p\n", level, "", handler->id, handler->cleanup);
+		fd_log_debug("\t  %*s  id %d, cleanup %p, opaque %p\n", level, "", handler->id, handler->cleanup, handler->opaque);
 	}
 	fd_log_debug("\t  %*s -- end of handler @%p --\n", level, "", handler);
