Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 398d9671b5107efb3b6f884686352163ff7547c4)
+++ kernel/generic/include/ipc/ipc.h	(revision 7918fce8437f1dba2cd4f238080fa7e5d648a549)
@@ -139,26 +139,38 @@
 #define IPC_M_PHONE_HUNGUP	3
 
-/** Send as_area over IPC 
- * - ARG1 - src as_area base address
- * - ARG2 - size of src as_area (filled automatically by kernel)
+/** Send as_area over IPC.
+ * - ARG1 - source as_area base address
+ * - ARG2 - size of source as_area (filled automatically by kernel)
  * - ARG3 - flags of the as_area being sent
  * 
- * on answer:
+ * on answer, the recipient must set:
  * - ARG1 - dst as_area base adress
  */
 #define IPC_M_AS_AREA_SEND	4	
 
-/** Get as_area over IPC
- * - ARG1 - dst as_area base address
- * - ARG2 - dst as_area size
+/** Receive as_area over IPC.
+ * - ARG1 - destination as_area base address
+ * - ARG2 - destination as_area size
  * - ARG3 - user defined argument
  * 
- * on answer, the server must set:
- *
- * - ARG1 - src as_area base address
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - source as_area base address
  * - ARG2 - flags that will be used for sharing
  */
 #define IPC_M_AS_AREA_RECV	5	
 
+/** Send data to another address space over IPC.
+ * - ARG1 - destination address space virtual address, may be overriden by the
+ *	    recipient
+ * - ARG2 - source address space virtual address
+ * - ARG3 - size of data to be copied, may be overriden by the recipient
+ *
+ * on answer, the recipient must set:
+ *
+ * - ARG1 - final destination address space virtual address
+ * - ARG3 - final size of data to be copied
+ */
+#define IPC_M_DATA_SEND		6
 
 /* Well-known methods */
@@ -243,4 +255,7 @@
 	/** Data passed from/to userspace. */
 	ipc_data_t data;
+
+	/** Buffer for IPC_M_DATA_SEND. */
+	uint8_t *buffer;
 } call_t;
 
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 398d9671b5107efb3b6f884686352163ff7547c4)
+++ kernel/generic/src/ipc/ipc.c	(revision 7918fce8437f1dba2cd4f238080fa7e5d648a549)
@@ -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 398d9671b5107efb3b6f884686352163ff7547c4)
+++ kernel/generic/src/ipc/sysipc.c	(revision 7918fce8437f1dba2cd4f238080fa7e5d648a549)
@@ -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.
