Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/include/ipc/ipc.h	(revision 44a53fd618cd787d80627f587f82cf957587e9c6)
@@ -112,4 +112,23 @@
  * These methods have special behaviour
  */
+/** Clone connection.
+ *
+ * The calling task clones one of its phones for the callee.
+ *
+ * - ARG1 - The caller sets ARG1 to the phone of the cloned connection.
+ *	  - The callee gets the new phone from ARG1.
+ * - on answer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ */
+#define IPC_M_CONNECTION_CLONE	1
+/** Protocol for CONNECT - ME
+ *
+ * Through this call, the recipient learns about the new cloned connection. 
+ * 
+ * - ARG5 - the kernel sets ARG5 to contain the hash of the used phone
+ * - on asnwer, the callee acknowledges the new connection by sending EOK back
+ *   or the kernel closes it
+ */
+#define IPC_M_CONNECT_ME	2
 /** Protocol for CONNECT - TO - ME 
  *
@@ -128,5 +147,5 @@
  *                       (on the receiving side) as ARG5 of the call.
  */
-#define IPC_M_CONNECT_TO_ME	1
+#define IPC_M_CONNECT_TO_ME	3	
 /** Protocol for CONNECT - ME - TO
  *
@@ -146,9 +165,9 @@
  *
  */
-#define IPC_M_CONNECT_ME_TO	2
+#define IPC_M_CONNECT_ME_TO	4	
 /** This message is sent to answerbox when the phone
  * is hung up
  */
-#define IPC_M_PHONE_HUNGUP	3
+#define IPC_M_PHONE_HUNGUP	5
 
 /** Send as_area over IPC.
@@ -160,5 +179,5 @@
  * - ARG1 - dst as_area base adress
  */
-#define IPC_M_SHARE_OUT		4	
+#define IPC_M_SHARE_OUT		6	
 
 /** Receive as_area over IPC.
@@ -172,5 +191,5 @@
  * - ARG2 - flags that will be used for sharing
  */
-#define IPC_M_SHARE_IN		5	
+#define IPC_M_SHARE_IN		7	
 
 /** Send data to another address space over IPC.
@@ -183,5 +202,5 @@
  * - ARG2 - final size of data to be copied
  */
-#define IPC_M_DATA_WRITE	6
+#define IPC_M_DATA_WRITE	8
 
 /** Receive data from another address space over IPC.
@@ -194,5 +213,5 @@
  * - ARG2 - final size of data to be copied
  */
-#define IPC_M_DATA_READ		7
+#define IPC_M_DATA_READ		9
 
 /** Debug the recipient.
@@ -200,5 +219,5 @@
  * - other arguments are specific to the debug method
  */
-#define IPC_M_DEBUG_ALL		8
+#define IPC_M_DEBUG_ALL		10
 
 /* Well-known methods */
Index: kernel/generic/include/ipc/ipcrsc.h
===================================================================
--- kernel/generic/include/ipc/ipcrsc.h	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/include/ipc/ipcrsc.h	(revision 44a53fd618cd787d80627f587f82cf957587e9c6)
@@ -36,6 +36,9 @@
 #define KERN_IPCRSC_H_
 
+#include <proc/task.h>
+#include <ipc/ipc.h>
+
 extern call_t * get_call(unative_t callid);
-extern int phone_alloc(void);
+extern int phone_alloc(task_t *t);
 extern void phone_connect(int phoneid, answerbox_t *box);
 extern void phone_dealloc(int phoneid);
Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision 44a53fd618cd787d80627f587f82cf957587e9c6)
@@ -161,25 +161,27 @@
 }
 
-/** Allocate new phone slot in the current TASK structure.
+/** Allocate new phone slot in the specified task.
+ *
+ * @param t		Task for which to allocate a new phone.
  *
  * @return		New phone handle or -1 if the phone handle limit is
  *			exceeded.
  */
-int phone_alloc(void)
+int phone_alloc(task_t *t)
 {
 	int i;
 
-	spinlock_lock(&TASK->lock);
+	spinlock_lock(&t->lock);
 	for (i = 0; i < IPC_MAX_PHONES; i++) {
-		if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
-		    atomic_get(&TASK->phones[i].active_calls) == 0)
-			TASK->phones[i].state = IPC_PHONE_FREE;
-
-		if (TASK->phones[i].state == IPC_PHONE_FREE) {
-			TASK->phones[i].state = IPC_PHONE_CONNECTING;
+		if (t->phones[i].state == IPC_PHONE_HUNGUP &&
+		    atomic_get(&t->phones[i].active_calls) == 0)
+			t->phones[i].state = IPC_PHONE_FREE;
+
+		if (t->phones[i].state == IPC_PHONE_FREE) {
+			t->phones[i].state = IPC_PHONE_CONNECTING;
 			break;
 		}
 	}
-	spinlock_unlock(&TASK->lock);
+	spinlock_unlock(&t->lock);
 
 	if (i == IPC_MAX_PHONES)
Index: kernel/generic/src/ipc/kbox.c
===================================================================
--- kernel/generic/src/ipc/kbox.c	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/src/ipc/kbox.c	(revision 44a53fd618cd787d80627f587f82cf957587e9c6)
@@ -249,5 +249,5 @@
 	}
 
-	newphid = phone_alloc();
+	newphid = phone_alloc(TASK);
 	if (newphid < 0) {
 		mutex_unlock(&ta->kb.cleanup_lock);
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/src/ipc/sysipc.c	(revision 44a53fd618cd787d80627f587f82cf957587e9c6)
@@ -94,4 +94,6 @@
 {
 	switch (method) {
+	case IPC_M_CONNECTION_CLONE:
+	case IPC_M_CONNECT_ME:
 	case IPC_M_PHONE_HUNGUP:
 		/* This message is meant only for the original recipient. */
@@ -141,4 +143,6 @@
 {
 	switch (IPC_GET_METHOD(call->data)) {
+	case IPC_M_CONNECTION_CLONE:
+	case IPC_M_CONNECT_ME:
 	case IPC_M_CONNECT_TO_ME:
 	case IPC_M_CONNECT_ME_TO:
@@ -183,7 +187,46 @@
 		return 0;
 
-	if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
+	if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) {
+		phoneid = IPC_GET_ARG1(*olddata);
+		phone_t *phone = &TASK->phones[phoneid]; 
+		if (IPC_GET_RETVAL(answer->data) != EOK) {
+			/*
+			 * The recipient of the cloned phone rejected the offer.
+			 * 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) {
+				spinlock_lock(&phone->callee->lock);
+				list_remove(&phone->link);
+				phone->state = IPC_PHONE_SLAMMED;
+				spinlock_unlock(&phone->callee->lock);
+			}
+			mutex_unlock(&phone->lock);
+		}
+	} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) {
+		phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata);
+		if (IPC_GET_RETVAL(answer->data) != EOK) {
+			/*
+			 * The other party on the cloned phoned rejected our
+			 * request for connection on the protocol level.
+			 * We need to break the connection without sending
+			 * IPC_M_HUNGUP back.
+			 */
+			mutex_lock(&phone->lock);
+			if (phone->state == IPC_PHONE_CONNECTED) {
+				spinlock_lock(&phone->callee->lock);
+				list_remove(&phone->link);
+				phone->state = IPC_PHONE_SLAMMED;
+				spinlock_unlock(&phone->callee->lock);
+			}
+			mutex_unlock(&phone->lock);
+		}
+	} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) {
 		phoneid = IPC_GET_ARG5(*olddata);
-		if (IPC_GET_RETVAL(answer->data)) {
+		if (IPC_GET_RETVAL(answer->data) != EOK) {
 			/* The connection was not accepted */
 			phone_dealloc(phoneid);
@@ -197,5 +240,5 @@
 	} else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) {
 		/* If the users accepted call, connect */
-		if (!IPC_GET_RETVAL(answer->data)) {
+		if (IPC_GET_RETVAL(answer->data) == EOK) {
 			ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata),
 			    &TASK->answerbox);
@@ -309,6 +352,46 @@
 
 	switch (IPC_GET_METHOD(call->data)) {
+	case IPC_M_CONNECTION_CLONE: {
+		phone_t *cloned_phone;
+		GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
+		    return ENOENT);
+		if (cloned_phone < phone) {
+			mutex_lock(&cloned_phone->lock);
+			mutex_lock(&phone->lock);
+		} else {
+			mutex_lock(&phone->lock);
+			mutex_lock(&cloned_phone->lock);
+		}
+		if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
+		    phone->state != IPC_PHONE_CONNECTED) {
+			mutex_unlock(&cloned_phone->lock);
+			mutex_unlock(&phone->lock);
+			return EINVAL;
+		}
+		/*
+		 * We can be pretty sure now that both tasks exist and we are
+		 * connected to them. As we continue to hold the phone locks,
+		 * we are effectively preventing them from finishing their
+		 * potential cleanup.
+		 */
+		newphid = phone_alloc(phone->callee->task);
+		if (newphid < 0) {
+			mutex_unlock(&cloned_phone->lock);
+			mutex_unlock(&phone->lock);
+			return ELIMIT;
+		}
+		ipc_phone_connect(&phone->callee->task->phones[newphid],
+		    cloned_phone->callee);
+		mutex_unlock(&cloned_phone->lock);
+		mutex_unlock(&phone->lock);
+		/* Set the new phone for the callee. */
+		IPC_SET_ARG1(call->data, newphid);
+		break;
+	}
+	case IPC_M_CONNECT_ME:
+		IPC_SET_ARG5(call->data, (unative_t) phone);
+		break;
 	case IPC_M_CONNECT_ME_TO:
-		newphid = phone_alloc();
+		newphid = phone_alloc(TASK);
 		if (newphid < 0)
 			return ELIMIT;
@@ -400,5 +483,5 @@
 
 	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
-		phoneid = phone_alloc();
+		phoneid = phone_alloc(TASK);
 		if (phoneid < 0) { /* Failed to allocate phone */
 			IPC_SET_RETVAL(call->data, ELIMIT);
