Index: kernel/generic/include/ipc/sysipc_ops.h
===================================================================
--- kernel/generic/include/ipc/sysipc_ops.h	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/include/ipc/sysipc_ops.h	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -40,5 +40,7 @@
 typedef struct {
 	int (* request_preprocess)(call_t *, phone_t *);
+	void (* request_forget)(call_t *);
 	int (* request_process)(call_t *, answerbox_t *);
+	void (* answer_cleanup)(call_t *, ipc_data_t *);
 	int (* answer_preprocess)(call_t *, ipc_data_t *);
 	int (* answer_process)(call_t *);
@@ -48,5 +50,7 @@
 
 extern int null_request_preprocess(call_t *, phone_t *);
+extern void null_request_forget(call_t *);
 extern int null_request_process(call_t *, answerbox_t *);
+extern void null_answer_cleanup(call_t *, ipc_data_t *);
 extern int null_answer_preprocess(call_t *, ipc_data_t *);
 extern int null_answer_process(call_t *);
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ipc.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -45,4 +45,5 @@
 #include <ipc/kbox.h>
 #include <ipc/event.h>
+#include <ipc/sysipc_ops.h>
 #include <errno.h>
 #include <mm/slab.h>
@@ -613,4 +614,9 @@
 	spinlock_unlock(&call->forget_lock);
 	spinlock_unlock(&TASK->active_calls_lock);
+
+	sysipc_ops_t *ops = sysipc_ops_get(call->request_method);
+	if (ops->request_forget)
+		ops->request_forget(call);
+
 	goto restart;
 }
Index: kernel/generic/src/ipc/ops/clnestab.c
===================================================================
--- kernel/generic/src/ipc/ops/clnestab.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/clnestab.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -45,7 +45,20 @@
 }
 
+static void answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
+
+	mutex_lock(&phone->lock);
+	if (phone->state == IPC_PHONE_CONNECTED) {
+		irq_spinlock_lock(&phone->callee->lock, true);
+		list_remove(&phone->link);
+		phone->state = IPC_PHONE_SLAMMED;
+		irq_spinlock_unlock(&phone->callee->lock, true);
+	}
+	mutex_unlock(&phone->lock);
+}
+
 static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
 {
-	phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata);
 
 	if (IPC_GET_RETVAL(answer->data) != EOK) {
@@ -55,12 +68,5 @@
 		 * connection without sending IPC_M_HUNGUP back.
 		 */
-		mutex_lock(&phone->lock);
-		if (phone->state == IPC_PHONE_CONNECTED) {
-			irq_spinlock_lock(&phone->callee->lock, true);
-			list_remove(&phone->link);
-			phone->state = IPC_PHONE_SLAMMED;
-			irq_spinlock_unlock(&phone->callee->lock, true);
-		}
-		mutex_unlock(&phone->lock);
+		answer_cleanup(answer, olddata);
 	}
 	
@@ -70,5 +76,7 @@
 sysipc_ops_t ipc_m_clone_establish_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/conctmeto.c
===================================================================
--- kernel/generic/src/ipc/ops/conctmeto.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/conctmeto.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -54,4 +54,9 @@
 }
 
+static void request_forget(call_t *call)
+{
+	phone_dealloc(call->priv);
+}
+
 static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
 {
@@ -77,5 +82,7 @@
 sysipc_ops_t ipc_m_connect_me_to_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = answer_process,
Index: kernel/generic/src/ipc/ops/concttome.c
===================================================================
--- kernel/generic/src/ipc/ops/concttome.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/concttome.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -55,4 +55,11 @@
 }
 
+static void answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	int phoneid = (int) IPC_GET_ARG5(*olddata);
+
+	phone_dealloc(phoneid);
+}
+
 static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
 {
@@ -61,7 +68,5 @@
 	if (IPC_GET_RETVAL(answer->data) != EOK) {
 		/* The connection was not accepted */
-		int phoneid = (int) IPC_GET_ARG5(*olddata);
-	
-		phone_dealloc(phoneid);
+		answer_cleanup(answer, olddata);
 	} else {
 		/* The connection was accepted */
@@ -77,5 +82,7 @@
 sysipc_ops_t ipc_m_connect_to_me_ops = {
 	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = request_process,
+	.answer_cleanup = answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/connclone.c
===================================================================
--- kernel/generic/src/ipc/ops/connclone.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/connclone.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -97,4 +97,25 @@
 }
 
+static void answer_cleanup(call_t *answer, ipc_data_t *olddata)
+{
+	int phoneid = (int) IPC_GET_ARG1(*olddata);
+	phone_t *phone = &TASK->phones[phoneid];
+
+	/*
+	 * In this case, the connection was established at the request
+	 * time and therefore we need to slam the phone.  We don't
+	 * merely hangup as that would result in sending IPC_M_HUNGUP
+	 * to the third party on the other side of the cloned phone.
+	 */
+	mutex_lock(&phone->lock);
+	if (phone->state == IPC_PHONE_CONNECTED) {
+		irq_spinlock_lock(&phone->callee->lock, true);
+		list_remove(&phone->link);
+		phone->state = IPC_PHONE_SLAMMED;
+		irq_spinlock_unlock(&phone->callee->lock, true);
+	}
+	mutex_unlock(&phone->lock);
+}
+
 static int answer_preprocess(call_t *answer, ipc_data_t *olddata)
 {
@@ -103,21 +124,5 @@
 		 * The recipient of the cloned phone rejected the offer.
 		 */
-		int phoneid = (int) IPC_GET_ARG1(*olddata);
-		phone_t *phone = &TASK->phones[phoneid];
-
-		/*
-		 * In this case, the connection was established at the request
-		 * time and therefore we need to slam the phone.  We don't
-		 * merely hangup as that would result in sending IPC_M_HUNGUP
-		 * to the third party on the other side of the cloned phone.
-		 */
-		mutex_lock(&phone->lock);
-		if (phone->state == IPC_PHONE_CONNECTED) {
-			irq_spinlock_lock(&phone->callee->lock, true);
-			list_remove(&phone->link);
-			phone->state = IPC_PHONE_SLAMMED;
-			irq_spinlock_unlock(&phone->callee->lock, true);
-		}
-		mutex_unlock(&phone->lock);
+		answer_cleanup(answer, olddata);
 	}
 
@@ -127,5 +132,7 @@
 sysipc_ops_t ipc_m_connection_clone_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/dataread.c
===================================================================
--- kernel/generic/src/ipc/ops/dataread.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/dataread.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -108,5 +108,7 @@
 sysipc_ops_t ipc_m_data_read_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = answer_process,
Index: kernel/generic/src/ipc/ops/datawrite.c
===================================================================
--- kernel/generic/src/ipc/ops/datawrite.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/datawrite.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -84,6 +84,4 @@
 		}
 	}
-	free(answer->buffer);
-	answer->buffer = NULL;
 
 	return EOK;
@@ -93,5 +91,7 @@
 sysipc_ops_t ipc_m_data_write_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/debug.c
===================================================================
--- kernel/generic/src/ipc/ops/debug.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/debug.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -65,5 +65,7 @@
 	.request_preprocess = null_request_preprocess,
 #endif
+	.request_forget = null_request_forget,
 	.request_process = request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = null_answer_preprocess,
 	.answer_process = answer_process,
Index: kernel/generic/src/ipc/ops/sharein.c
===================================================================
--- kernel/generic/src/ipc/ops/sharein.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/sharein.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -61,5 +61,7 @@
 sysipc_ops_t ipc_m_share_in_ops = {
 	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/shareout.c
===================================================================
--- kernel/generic/src/ipc/ops/shareout.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/shareout.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -82,5 +82,7 @@
 sysipc_ops_t ipc_m_share_out_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/ops/stchngath.c
===================================================================
--- kernel/generic/src/ipc/ops/stchngath.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/ops/stchngath.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -118,5 +118,7 @@
 sysipc_ops_t ipc_m_state_change_authorize_ops = {
 	.request_preprocess = request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = answer_preprocess,
 	.answer_process = null_answer_process,
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/sysipc.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -160,4 +160,5 @@
 {
 	int rc = EOK;
+	sysipc_ops_t *ops;
 
 	spinlock_lock(&answer->forget_lock);
@@ -167,5 +168,9 @@
 		 */
 		spinlock_unlock(&answer->forget_lock);
-		/* TODO: cleanup? */
+
+		ops = sysipc_ops_get(answer->request_method);
+		if (ops->answer_cleanup)
+			ops->answer_cleanup(answer, olddata);
+
 		return rc;
 	} else {
@@ -198,5 +203,5 @@
 	
 
-	sysipc_ops_t *ops = sysipc_ops_get(answer->request_method);
+	ops = sysipc_ops_get(answer->request_method);
 	if (ops->answer_preprocess)
 		rc = ops->answer_preprocess(answer, olddata);
Index: kernel/generic/src/ipc/sysipc_ops.c
===================================================================
--- kernel/generic/src/ipc/sysipc_ops.c	(revision 13dbaa8c10f7b449dfe6e0d387ea4a6ee1c07984)
+++ kernel/generic/src/ipc/sysipc_ops.c	(revision b1e6269e0d19f6fc32213d11e1344dccf38f6bf7)
@@ -64,5 +64,7 @@
 static sysipc_ops_t null_ops = {
 	.request_preprocess = null_request_preprocess,
+	.request_forget = null_request_forget,
 	.request_process = null_request_process,
+	.answer_cleanup = null_answer_cleanup,
 	.answer_preprocess = null_answer_preprocess,
 	.answer_process = null_answer_process,
@@ -74,7 +76,15 @@
 }
 
+void null_request_forget(call_t *call)
+{
+}
+
 int null_request_process(call_t *call, answerbox_t *box)
 {
 	return EOK;
+}
+
+void null_answer_cleanup(call_t *call, ipc_data_t *data)
+{
 }
 
