Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 347939)
+++ channels/chan_sip.c	(working copy)
@@ -13526,6 +13526,7 @@
 	struct sip_request req;
 	struct ast_msg_var_iterator *i;
 	const char *var, *val;
+	const char *content_type = NULL;
 
 	build_via(p);
 	initreqprep(&req, p, SIP_MESSAGE, NULL);
@@ -13534,13 +13535,33 @@
 
 	i = ast_msg_var_iterator_init(msg);
 	while (ast_msg_var_iterator_next(msg, i, &var, &val)) {
-		add_header(&req, var, val);
+		if (!strcasecmp(var, "Content-Type")) {
+			/* Save content type */
+			content_type = val;
+		} else if (strcasecmp(var, "To") && strcasecmp(var, "From")) {
+			/* Prevent additions of 'From'/'To' header */
+			add_header(&req, var, val);
+		}
+
 		ast_msg_var_unref_current(i);
 	}
 	ast_msg_var_iterator_destroy(i);
 
-	add_text(&req, ast_msg_get_body(msg));
+	if (NULL == content_type) {
+		/* If "Content-Type" not set from MESSAGE_DATA ,
+		 * get it from original message */
+		content_type = ast_msg_get_var((struct ast_msg *)msg, "Content-Type");
+	}
 
+	if (NULL == content_type) {
+		/* "Content-Type" not set - use default value */
+		content_type = "text/plain;charset=UTF-8";
+	}
+
+	/* XXX Convert \n's to \r\n's XXX */
+	add_header(&req, "Content-Type", content_type);
+	add_content(&req, ast_msg_get_body(msg));
+
 	return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
 }
 
@@ -16460,12 +16481,6 @@
 	int res;
 	char *from, *to;
 
-	if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
-		transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
-		if (!p->owner)
-			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		return;
-	}
 
 	if (!(buf = ast_str_thread_get(&sip_msg_buf, 128))) {
 		transmit_response(p, "500 Internal Server Error", req);
@@ -16496,6 +16511,13 @@
 	ast_str_truncate(buf, len);
 
 	if (p->owner) {
+		if (strncmp(content_type, "text/plain", strlen("text/plain"))) { /* No text/plain attachment */
+			transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */
+			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
+			return;
+		}
+
+
 		if (sip_debug_test_pvt(p))
 			ast_verbose("SIP Text message received: '%s'\n", ast_str_buffer(buf));
 		memset(&f, 0, sizeof(f));
@@ -16509,6 +16531,11 @@
 		return;
 	}
 
+	/* 
+	 * At this point Message outside of a call
+	 * p->owner is NULL, no additiob check required
+	 */
+
 	if (!sip_cfg.accept_outofcall_message) {
 		/* Message outside of a call, we do not support that */
 		ast_debug(1, "MESSAGE outside of a call administratively disabled.\n");
@@ -16576,9 +16603,7 @@
 
 	if (!(msg = ast_msg_alloc())) {
 		transmit_response(p, "500 Internal Server Error", req);
-		if (!p->owner) {
-			sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
-		}
+		sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
 		return;
 	}
 
@@ -16586,7 +16611,7 @@
 	from = ast_strdupa(sip_get_header(req, "From"));
 
 	res = ast_msg_set_to(msg, "%s", to);
-	res |= ast_msg_set_from(msg, "%s", get_in_brackets(from));
+	res |= ast_msg_set_from(msg, "%s", from);
 	res |= ast_msg_set_body(msg, "%s", ast_str_buffer(buf));
 	res |= ast_msg_set_context(msg, "%s", p->context);
 
@@ -24385,6 +24410,7 @@
 	struct sip_pvt *pvt;
 	int res;
 	char *to_uri, *to_host, *to_user;
+	const char *str_maxforwards;
 	struct sip_peer *peer_ptr;
 
 	if (!(pvt = sip_alloc(NULL, NULL, 0, SIP_MESSAGE, NULL))) {
@@ -24392,6 +24418,7 @@
 	}
 
 	to_uri = ast_strdupa(to);
+	to_uri = get_in_brackets(to_uri);
 	parse_uri(to_uri, "sip:,sips:", &to_user, NULL, &to_host, NULL);
 
 	if (ast_strlen_zero(to_host)) {
@@ -24400,32 +24427,35 @@
 		dialog_unref(pvt, "MESSAGE(to) is invalid for SIP");
 		return -1;
 	}
+	if (ast_strlen_zero(from)) {
+		ast_log(LOG_WARNING, "Can't get From for MESSAGE\n");
+		dialog_unlink_all(pvt);
+		dialog_unref(pvt, "Can't get From for MESSAGE");
+		return -1;
+	}
 
-	if (!ast_strlen_zero(from)) {
-		if ((peer_ptr = sip_find_peer(from, NULL, 0, 1, 0, 0))) {
-			ast_string_field_set(pvt, fromname, S_OR(peer_ptr->cid_name, peer_ptr->name));
-			ast_string_field_set(pvt, fromuser, S_OR(peer_ptr->cid_num, peer_ptr->name));
-			sip_unref_peer(peer_ptr, "sip_unref_peer, from sip_msg_send, sip_find_peer");
-		} else if (strchr(from, '<')) { /* from is callerid-style */
-			char *sender;
-			char *name = NULL, *location = NULL, *user = NULL, *domain = NULL;
-
-			sender = ast_strdupa(from);
-			ast_callerid_parse(sender, &name, &location);
-			ast_string_field_set(pvt, fromname, name);
-			if (strchr(location, ':')) { /* Must be a URI */
-				parse_uri(location, "sip:,sips:", &user, NULL, &domain, NULL);
-				SIP_PEDANTIC_DECODE(user);
-				SIP_PEDANTIC_DECODE(domain);
-				extract_host_from_hostport(&domain);
-				ast_string_field_set(pvt, fromuser, user);
-				ast_string_field_set(pvt, fromdomain, domain);
-			} else { /* Treat it as an exten/user */
-				ast_string_field_set(pvt, fromuser, location);
-			}
-		} else { /* assume we just have the name, use defaults for the rest */
-			ast_string_field_set(pvt, fromname, from);
+	if ((peer_ptr = sip_find_peer(from, NULL, 0, 1, 0, 0))) {
+		ast_string_field_set(pvt, fromname, S_OR(peer_ptr->cid_name, peer_ptr->name));
+		ast_string_field_set(pvt, fromuser, S_OR(peer_ptr->cid_num, peer_ptr->name));
+		sip_unref_peer(peer_ptr, "sip_unref_peer, from sip_msg_send, sip_find_peer");
+	} else if (strchr(from, '<')) { /* from_uri is callerid-style */
+		char *sender;
+		char *name = NULL, *location = NULL, *user = NULL, *domain = NULL;
+		sender = ast_strdupa(from);
+		ast_callerid_parse(sender, &name, &location);
+		ast_string_field_set(pvt, fromname, name);
+		if (strchr(location, ':')) { /* Must be a URI */
+			parse_uri(location, "sip:,sips:", &user, NULL, &domain, NULL);
+			SIP_PEDANTIC_DECODE(user);
+			SIP_PEDANTIC_DECODE(domain);
+			extract_host_from_hostport(&domain);
+			ast_string_field_set(pvt, fromuser, user);
+			ast_string_field_set(pvt, fromdomain, domain);
+		} else { /* Treat it as an exten/user */
+			ast_string_field_set(pvt, fromuser, location);
 		}
+	} else { /* assume we just have the name, use defaults for the rest */
+		ast_string_field_set(pvt, fromname, from);
 	}
 
 	sip_pvt_lock(pvt);
@@ -24446,6 +24476,15 @@
 
 	/* XXX Does pvt->expiry need to be set? */
 
+	/* Decrement Max-Forwards for SIP loop prevention */
+	str_maxforwards = ast_msg_get_var((struct ast_msg *)msg, "Max-Forwards");
+	if(str_maxforwards != NULL) {
+		pvt->maxforwards = atoi(str_maxforwards);
+		if (pvt->maxforwards > 0) {
+			pvt->maxforwards--;
+		}
+	}
+
 	res = transmit_message_with_msg(pvt, msg);
 
 	sip_pvt_unlock(pvt);
Index: main/message.c
===================================================================
--- main/message.c	(revision 347939)
+++ main/message.c	(working copy)
@@ -1013,7 +1013,7 @@
 	ast_rwlock_rdlock(&tech_holder->tech_lock);
 	if (tech_holder->tech) {
 		res = tech_holder->tech->msg_send(msg, S_OR(args.to, ""),
-							S_OR(args.from, ""));
+							S_OR(args.from, ast_str_buffer(msg->from)));
 	}
 	ast_rwlock_unlock(&tech_holder->tech_lock);
 	ao2_unlock(msg);
