--- channels/chan_sip.c	2013-02-02 14:43:10.534574000 +0100
+++ channels/chan_sip.c	2013-02-02 15:28:07.528415343 +0100
@@ -1921,6 +1921,7 @@
 	
 	/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
 	enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */
+	struct sockaddr_in externip;		/*!< Extern IP per peer */
 };
 
 
@@ -3877,6 +3878,18 @@
 static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us, struct sip_pvt *p)
 {
 	struct sockaddr_in theirs;
+	struct sockaddr_in *externaddr;
+	struct sip_peer *peer;
+
+	/* 
+	 * Pick which externaddr to use. "externaddr" is a new option for per-peer settings
+	 * We check with configured peer devices if any has "externaddr"(peer->externip), that matches "them"(p->sa).
+	 * Otherwise, use the default one. 
+	 *  
+	 */
+	peer = find_peer(NULL, &p->sa, TRUE, FINDPEERS, FALSE, p->socket.type);
+	externaddr = (peer) ? (peer->externip.sin_addr.s_addr ? &peer->externip : &externip) : &externip;
+		
 	/* Set want_remap to non-zero if we want to remap 'us' to an externally
 	 * reachable IP address and port. This is done if:
 	 * 1. we have a localaddr list (containing 'internal' addresses marked
@@ -3895,9 +3908,9 @@
 	/* now ask the system what would it use to talk to 'them' */
 	ast_ouraddrfor(them, &us->sin_addr);
 	theirs.sin_addr = *them;
-
+	
 	want_remap = localaddr &&
-		(externip.sin_addr.s_addr || stunaddr.sin_addr.s_addr) &&
+		(externaddr->sin_addr.s_addr || stunaddr.sin_addr.s_addr) &&
 		ast_apply_ha(localaddr, &theirs) == AST_SENSE_ALLOW ;
 
 	if (want_remap &&
@@ -3905,15 +3918,15 @@
 		/* if we used externhost or stun, see if it is time to refresh the info */
 		if (externexpire && time(NULL) >= externexpire) {
 			if (stunaddr.sin_addr.s_addr) {
-				ast_stun_request(sipsock, &stunaddr, NULL, &externip);
+				ast_stun_request(sipsock, &stunaddr, NULL, externaddr);
 			} else {
-				if (ast_parse_arg(externhost, PARSE_INADDR, &externip))
+				if (ast_parse_arg(externhost, PARSE_INADDR, externaddr))
 					ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
 			}
 			externexpire = time(NULL) + externrefresh;
 		}
-		if (externip.sin_addr.s_addr)
-			*us = externip;
+		if (externaddr->sin_addr.s_addr)
+			*us = *externaddr;
 		else
 			ast_log(LOG_WARNING, "stun failed\n");
 		ast_debug(1, "Target address %s is not local, substituting externip\n", 
@@ -24453,6 +24466,7 @@
 	ast_string_field_set(peer, mohinterpret, default_mohinterpret);
 	ast_string_field_set(peer, mohsuggest, default_mohsuggest);
 	peer->addr.sin_family = AF_INET;
+	memset(&peer->externip,0, sizeof(peer->externip));
 	peer->defaddr.sin_family = AF_INET;
 	peer->capability = global_capability;
 	peer->maxcallbitrate = default_maxcallbitrate;
@@ -24668,6 +24682,18 @@
 						peer->default_outbound_transport = peer->transports;
 					}
 				}
+			} else if (!strcasecmp(v->name, "externaddr")) {
+				if (localaddr == NULL) {
+					ast_log(LOG_ERROR, "Externaddr for peer %s not enabled, since we have no local networks configured in [general]\n", peer->name);
+				} else {
+					if (!ast_strlen_zero(v->value) && ast_parse_arg(v->value, PARSE_INADDR, &peer->externip)) {
+						ast_log(LOG_WARNING, "Invalid address for externaddr keyword: %s for peer %s\n", v->value, peer->name);
+					}
+					else if (!peer->externip.sin_port && bindaddr.sin_port) {					  
+						peer->externip.sin_port = bindaddr.sin_port;
+					}					
+				}
+					
 			} else if (realtime && !strcasecmp(v->name, "regseconds")) {
 				ast_get_time_t(v->value, &regseconds, 0, NULL);
 			} else if (realtime && !strcasecmp(v->name, "name")) {
@@ -25668,7 +25694,7 @@
 			if (ha_error)
 				ast_log(LOG_ERROR, "Bad localnet configuration value line %d : %s\n", v->lineno, v->value);
 		} else if (!strcasecmp(v->name, "externip")) {
-			if (ast_parse_arg(v->value, PARSE_INADDR, &externip))
+			if (!ast_strlen_zero(v->value) && ast_parse_arg(v->value, PARSE_INADDR, &externip))
 				ast_log(LOG_WARNING, "Invalid address for externip keyword: %s\n", v->value);
 			externexpire = 0;
 			/* If no port was specified use the value of bindport */
