Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision bd72c3e96c6695500538eeb7ff16155b0844005d)
+++ kernel/generic/src/ipc/ipc.c	(revision b76a22177c4c3a1dbff86603b43c86fa730488e2)
@@ -68,4 +68,5 @@
 	call->callerbox = &TASK->answerbox;
 	call->sender = TASK;
+	call->buffer = NULL;
 }
 
@@ -108,4 +109,7 @@
 {
 	ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
+	/* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
+	if (call->buffer)
+		free(call->buffer);
 	slab_free(ipc_call_slab, call);
 }
@@ -293,5 +297,6 @@
 	
 	spinlock_lock(&phone->lock);
-	if (phone->state == IPC_PHONE_FREE || phone->state == IPC_PHONE_HUNGUP ||
+	if (phone->state == IPC_PHONE_FREE ||
+	    phone->state == IPC_PHONE_HUNGUP ||
 	    phone->state == IPC_PHONE_CONNECTING) {
 		spinlock_unlock(&phone->lock);
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision bd72c3e96c6695500538eeb7ff16155b0844005d)
+++ kernel/generic/src/ipc/sysipc.c	(revision b76a22177c4c3a1dbff86603b43c86fa730488e2)
@@ -50,4 +50,7 @@
 #include <print.h>
 
+/** Maximum buffer size allowed for IPC_M_DATA_SEND requests. */
+#define DATA_SEND_LIMIT		(64 * 1024)
+
 #define GET_CHECK_PHONE(phone, phoneid, err) \
 { \
@@ -86,8 +89,14 @@
 static inline int is_forwardable(unative_t method)
 {
-	if (method == IPC_M_PHONE_HUNGUP || method == IPC_M_AS_AREA_SEND ||
-	    method == IPC_M_AS_AREA_RECV)
-		return 0; /* This message is meant only for the receiver */
-	return 1;
+	switch (method) {
+	case IPC_M_PHONE_HUNGUP:
+	case IPC_M_AS_AREA_SEND:
+	case IPC_M_AS_AREA_RECV:
+	case IPC_M_DATA_SEND:
+		/* This message is meant only for the original recipient. */
+		return 0;
+	default:
+		return 1;
+	}
 }
 
@@ -107,13 +116,14 @@
 static inline int answer_need_old(call_t *call)
 {
-	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME)
+	switch (IPC_GET_METHOD(call->data)) {
+	case IPC_M_CONNECT_TO_ME:
+	case IPC_M_CONNECT_ME_TO:
+	case IPC_M_AS_AREA_SEND:
+	case IPC_M_AS_AREA_RECV:
+	case IPC_M_DATA_SEND:
 		return 1;
-	if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)
-		return 1;
-	if (IPC_GET_METHOD(call->data) == IPC_M_AS_AREA_SEND)
-		return 1;
-	if (IPC_GET_METHOD(call->data) == IPC_M_AS_AREA_RECV)
-		return 1;
-	return 0;
+	default:
+		return 0;
+	}
 }
 
@@ -202,4 +212,21 @@
 			IPC_SET_RETVAL(answer->data, rc);
 		}
+	} else if (IPC_GET_METHOD(*olddata) == IPC_M_DATA_SEND) {
+		if (!IPC_GET_RETVAL(answer->data)) {
+			int rc;
+			uintptr_t dst;
+			uintptr_t size;
+
+			ASSERT(answer->buffer);
+
+			dst = IPC_GET_ARG1(answer->data);
+			size = IPC_GET_ARG3(answer->data);
+
+			rc = copy_to_uspace((void *) dst, answer->buffer, size);
+			if (rc != 0)
+				IPC_SET_RETVAL(answer->data, rc);
+			free(answer->buffer);
+			answer->buffer = NULL;
+		}
 	}
 	return 0;
@@ -216,4 +243,6 @@
 	int newphid;
 	size_t size;
+	uintptr_t src;
+	int rc;
 
 	switch (IPC_GET_METHOD(call->data)) {
@@ -233,4 +262,18 @@
 		IPC_SET_ARG2(call->data, size);
 		break;
+	case IPC_M_DATA_SEND:
+		src = IPC_GET_ARG2(call->data);
+		size = IPC_GET_ARG3(call->data);
+		
+		if ((size <= 0) || (size > DATA_SEND_LIMIT))
+			return ELIMIT;
+		
+		call->buffer = (uint8_t *) malloc(size, 0);
+		rc = copy_from_uspace(call->buffer, (void *) src, size);
+		if (rc != 0) {
+			free(call->buffer);
+			return rc;
+		}
+		break;
 	default:
 		break;
@@ -327,5 +370,6 @@
  * @param phoneid	Phone handle for the call.
  * @param question	Userspace address of call data with the request.
- * @param reply		Userspace address of call data where to store the answer.
+ * @param reply		Userspace address of call data where to store the
+ *			answer.
  *
  * @return		Zero on success or an error code.
