diff --git a/apps/sam/c/inc/sam.h b/apps/sam/c/inc/sam.h
index 656ef978abfdaa86bd559b97cf2ccc4f19ecbeb3..5069e9ba93faebc9f69900fb70bc8047151ec8d4 100644
--- a/apps/sam/c/inc/sam.h
+++ b/apps/sam/c/inc/sam.h
@@ -38,9 +38,11 @@ extern "C" {
 #include <stddef.h>
 #include <stdint.h>
 
+
 /*
  * Lengths
  */
+
 /* The maximum length a SAM command can be */
 #define SAM_CMD_LEN 128
 /* The maximum size of a single datagram packet */
@@ -49,18 +51,22 @@ extern "C" {
 #define SAM_LOGMSG_LEN 256
 /* The longest `name' arg for the naming lookup callback */
 #define SAM_NAME_LEN 256
-/* The max size of a single stream packet */
+/* The maximum size of a single stream packet */
 #define SAM_STREAM_PAYLOAD_MAX (32 * 1024)
 /* The length of a base 64 public key - it's actually 516, but +1 for '\0' */
 #define SAM_PUBKEY_LEN 517
-/* A public key SAM command's length */
+/* The maximum length of a SAM command with a public key */
 #define SAM_PKCMD_LEN (SAM_PUBKEY_LEN + SAM_CMD_LEN)
+/* The maximum size of a single raw packet */
+#define SAM_RAW_LEN (32 * 1024)
 /* The maximum length a SAM non-data reply can be */
 #define SAM_REPLY_LEN 1024
 
+
 /*
- * Shorten some standard variable types
+ * Some LibSAM variable types
  */
+
 typedef signed char schar_t;
 typedef unsigned char uchar_t;
 typedef unsigned int uint_t;
@@ -102,57 +108,62 @@ typedef enum {  /* see sam_strerror() for detailed descriptions of these */
 	SAM_TOO_BIG
 } samerr_t;
 
+
 /*
  * Public functions
  */
 
 /* SAM controls - sessions */
-extern sam_sess_t *sam_session_init(sam_sess_t *session);
-extern void		sam_session_free(sam_sess_t **session);
+sam_sess_t *sam_session_init(sam_sess_t *session);
+void		sam_session_free(sam_sess_t **session);
 /* SAM controls - connection */
-extern bool		sam_close(sam_sess_t *session);
-extern samerr_t	sam_connect(sam_sess_t *session, const char *samhost,
-					uint16_t samport, const char *destname, sam_conn_t style,
-					uint_t tunneldepth);
+bool		sam_close(sam_sess_t *session);
+samerr_t	sam_connect(sam_sess_t *session, const char *samhost,
+				uint16_t samport, const char *destname, sam_conn_t style,
+				uint_t tunneldepth);
 /* SAM controls - utilities */
-extern void		sam_naming_lookup(sam_sess_t *session, const char *name);
-extern bool		sam_read_buffer(sam_sess_t *session);
-extern const char *sam_strerror(samerr_t code);
+void		sam_naming_lookup(sam_sess_t *session, const char *name);
+bool		sam_read_buffer(sam_sess_t *session);
+const char *sam_strerror(samerr_t code);
 /* SAM controls - callbacks */
-extern void		(*sam_diedback)(sam_sess_t *session);
-extern void		(*sam_logback)(char *str);
-extern void		(*sam_namingback)(char *name, sam_pubkey_t pubkey,
-					samerr_t result);
+void		(*sam_diedback)(sam_sess_t *session);
+void		(*sam_logback)(char *str);
+void		(*sam_namingback)(char *name, sam_pubkey_t pubkey, samerr_t result);
 
 /* Stream commands */
-extern void		sam_stream_close(sam_sess_t *session, sam_sid_t stream_id);
-extern sam_sid_t sam_stream_connect(sam_sess_t *session,
-					const sam_pubkey_t dest);
-extern samerr_t	sam_stream_send(sam_sess_t *session, sam_sid_t stream_id,
-					const void *data, size_t size);
+void		sam_stream_close(sam_sess_t *session, sam_sid_t stream_id);
+sam_sid_t	sam_stream_connect(sam_sess_t *session, const sam_pubkey_t dest);
+samerr_t	sam_stream_send(sam_sess_t *session, sam_sid_t stream_id,
+				const void *data, size_t size);
 /* Stream commands - callbacks */
-extern void		(*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id,
-					samerr_t reason);
-extern void		(*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id,
-					sam_pubkey_t dest);
-extern void		(*sam_databack)(sam_sess_t *session, sam_sid_t stream_id,
-					void *data, size_t size);
-extern void		(*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id,
-					samerr_t result);
+void		(*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id,
+				samerr_t reason);
+void		(*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id,
+				sam_pubkey_t dest);
+void		(*sam_databack)(sam_sess_t *session, sam_sid_t stream_id,
+				void *data, size_t size);
+void		(*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id,
+				samerr_t result);
 
 /* Stream send queue (experimental) */
-extern void		sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id,
-					sam_sendq_t **sendq, const void *data, size_t dsize);
-extern void		sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id,
-					sam_sendq_t **sendq);
+void		sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id,
+				sam_sendq_t **sendq, const void *data, size_t dsize);
+void		sam_sendq_flush(sam_sess_t *session, sam_sid_t stream_id,
+				sam_sendq_t **sendq);
 
 /* Datagram commands */
-extern samerr_t	sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest,
-					const void *data, size_t size);
-
+samerr_t	sam_dgram_send(sam_sess_t *session, const sam_pubkey_t dest,
+				const void *data, size_t size);
 /* Datagram commands - callbacks */
-extern void		(*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest,
-					void *data, size_t size);
+void		(*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data,
+				size_t size);
+
+/* Raw commands */
+samerr_t	sam_raw_send(sam_sess_t *session, const sam_pubkey_t dest,
+				const void *data, size_t size);
+/* Raw commands - callbacks */
+void		(*sam_rawback)(sam_sess_t *session, void *data, size_t size);
+
 
 #ifdef __cplusplus
 }
diff --git a/apps/sam/c/src/sam.c b/apps/sam/c/src/sam.c
index 820811b8047263e7e9e23edf975856196db8d12c..33243b6886eb0c20b0e36db1f64513f757b16d9f 100644
--- a/apps/sam/c/src/sam.c
+++ b/apps/sam/c/src/sam.c
@@ -55,28 +55,40 @@ static ssize_t		sam_write(sam_sess_t *session, const void *buf, size_t n);
  * Callback functions
  * Note: if you add a new callback be sure to check for non-NULL in sam_connect
  */
+
 /* a peer closed the connection */
 void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason)
 	= NULL;
+
 /* a peer connected to us */
 void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id,
 	sam_pubkey_t dest) = NULL;
+
 /* a peer sent some stream data (`data' MUST be freed) */
 void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, void *data,
 	size_t size) = NULL;
+
 /* a peer sent some datagram data (`data' MUST be freed) */
 void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data,
 	size_t size) = NULL;
+
 /* we lost the connection to the SAM host */
 void (*sam_diedback)(sam_sess_t *session) = NULL;
+
 /* logging callback */
 void (*sam_logback)(char *str) = NULL;
+
 /* naming lookup reply - `pubkey' will be NULL if `result' isn't SAM_OK */
 void (*sam_namingback)(char *name, sam_pubkey_t pubkey, samerr_t result) = NULL;
+
 /* our connection to a peer has completed */
 void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id,
 	samerr_t result) = NULL;
 
+/* a peer sent some raw data (`data' MUST be freed) */
+void (*sam_rawback)(sam_sess_t *session, void *data, size_t size) = NULL;
+
+
 /*
  * Closes the connection to the SAM host
  *
@@ -155,7 +167,11 @@ samerr_t sam_connect(sam_sess_t *session, const char *samhost, uint16_t samport,
 			return SAM_CALLBACKS_UNSET;
 		}
 	} else if (style == SAM_RAW) {
-		abort();  /* not implemented yet */
+		if (sam_diedback == NULL || sam_logback == NULL
+				|| sam_namingback == NULL || sam_rawback == NULL) {
+			SAMLOGS("Please set callback functions before connecting");
+			return SAM_CALLBACKS_UNSET;
+		}
 	} else {
 		SAMLOGS("Unknown connection style");
 		return SAM_BAD_STYLE;
@@ -295,6 +311,7 @@ static void sam_parse(sam_sess_t *session, char *s)
 #define SAM_NAMING_REPLY_OK "NAMING REPLY RESULT=OK"
 #define SAM_NAMING_REPLY_IK "NAMING REPLY RESULT=INVALID_KEY"
 #define SAM_NAMING_REPLY_KNF "NAMING REPLY RESULT=KEY_NOT_FOUND"
+#define SAM_RAW_RECEIVED_REPLY "RAW RECEIVED"
 #define SAM_STREAM_CLOSED_REPLY "STREAM CLOSED"
 #define SAM_STREAM_CONNECTED_REPLY "STREAM CONNECTED"
 #define SAM_STREAM_RECEIVED_REPLY "STREAM RECEIVED"
@@ -305,6 +322,10 @@ static void sam_parse(sam_sess_t *session, char *s)
 #define SAM_STREAM_STATUS_REPLY_IK "STREAM STATUS RESULT=INVALID_KEY"
 #define SAM_STREAM_STATUS_REPLY_TO "STREAM STATUS RESULT=TIMEOUT"
 
+	/*
+	 * TODO: add raw parsing
+	 */
+
 	if (strncmp(s, SAM_DGRAM_RECEIVED_REPLY,
 			strlen(SAM_DGRAM_RECEIVED_REPLY)) == 0) {
 		char *p;
@@ -518,6 +539,42 @@ static void sam_parse(sam_sess_t *session, char *s)
 	return;
 }
 
+/*
+ * Sends data to a destination in a raw packet
+ *
+ * dest - base 64 destination of who we're sending to
+ * data - the data we're sending
+ * size - the size of the data
+ *
+ * Returns: SAM_OK on success
+ */
+samerr_t sam_raw_send(sam_sess_t *session, const sam_pubkey_t dest,
+	const void *data, size_t size)
+{
+	assert(session != NULL);
+	char cmd[SAM_PKCMD_LEN];
+
+	if (size < 1 || size > SAM_RAW_PAYLOAD_MAX) {
+#ifdef NO_Z_FORMAT
+		SAMLOG("Invalid data send size (%u bytes)", size);
+#else
+		SAMLOG("Invalid data send size (%zu bytes)", size);
+#endif
+		return SAM_TOO_BIG;
+	}
+#ifdef NO_Z_FORMAT
+	snprintf(cmd, sizeof cmd, "RAW SEND DESTINATION=%s SIZE=%u\n",
+		dest, size);
+#else
+	snprintf(cmd, sizeof cmd, "RAW SEND DESTINATION=%s SIZE=%zu\n",
+		dest, size);
+#endif
+	sam_write(session, cmd, strlen(cmd));
+	sam_write(session, data, size);
+
+	return SAM_OK;
+}
+
 /*
  * Reads and callbacks everything in the SAM network buffer until it is clear
  *