Index: kernel/generic/src/ipc/ipcrsc.c
===================================================================
--- kernel/generic/src/ipc/ipcrsc.c	(revision 287e83f9b1d052d373437f8888bca9dcebd88cfc)
+++ kernel/generic/src/ipc/ipcrsc.c	(revision b0ea8a9a9eb43c04d7bf02648685fd9a966f84b1)
@@ -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 b0ea8a9a9eb43c04d7bf02648685fd9a966f84b1)
@@ -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 b0ea8a9a9eb43c04d7bf02648685fd9a966f84b1)
@@ -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);
