Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 203104)
+++ channels/chan_sip.c	(working copy)
@@ -2080,6 +2080,7 @@
 		AST_STRING_FIELD(md5secret);	/*!< Password in md5 */
 		AST_STRING_FIELD(callback);	/*!< Contact extension */
 		AST_STRING_FIELD(random);
+		AST_STRING_FIELD(peername);	/*!< Peer registering to */
 	);
 	enum sip_transport transport;	/*!< Transport for this registration UDP, TCP or TLS */
 	int portno;			/*!<  Optional port override */
@@ -7315,33 +7316,41 @@
 	enum sip_transport transport = SIP_TRANSPORT_UDP;
 	char buf[256] = "";
 	char *username = NULL;
-	char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *buf2=NULL;
-	char *callback=NULL;
+	char *hostname=NULL, *secret=NULL, *authuser=NULL, *expire=NULL, *tmp=NULL;
+	char *callback=NULL, *peername=NULL;
 
 	if (!value)
 		return -1;
-
 	ast_copy_string(buf, value, sizeof(buf));
-	buf2 = strrchr(buf, '@');
+	tmp = strrchr(buf, '@');
 
 	/* split [/extension][~expiry] */
-	expire = strchr(buf2, '~');
+	expire = strchr(tmp, '~');
 	if (expire)
 		*expire++ = '\0';
-	callback = strrchr(buf2, '/');
+	callback = strrchr(tmp, '/');
 	if (callback)
 		*callback++ = '\0';
 	if (ast_strlen_zero(callback))
 		callback = "s";
 
-	sip_parse_host(buf, lineno, &username, &portnum, &transport);
+	/* split [peername?][transport://] */
+	tmp = strrchr(buf, '?');
+	if (tmp) {
+		*tmp++ = '\0';
+		peername = buf;
+	} else {
+		tmp = buf;
+	}
+	/* tmp is set at the beginning of [transport://] */
+	sip_parse_host(tmp, lineno, &username, &portnum, &transport);
 
 	/* First split around the last '@' then parse the two components. */
 	hostname = strrchr(username, '@'); /* allow @ in the first part */
 	if (hostname)
 		*hostname++ = '\0';
 	if (ast_strlen_zero(username) || ast_strlen_zero(hostname)) {
-		ast_log(LOG_WARNING, "Format for registration is [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
+		ast_log(LOG_WARNING, "Format for registration is [peername?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
 		return -1;
 	}
 
@@ -7384,6 +7393,9 @@
 		ast_string_field_set(reg, authuser, authuser);
 	if (secret)
 		ast_string_field_set(reg, secret, secret);
+	if (peername) {
+		ast_string_field_set(reg, peername, peername);
+	}
 	reg->transport = transport;
 	reg->expire = -1;
 	reg->expiry = (expire ? atoi(expire) : default_expiry);
@@ -11425,6 +11437,8 @@
 		}
 	} else {
 		/* Build callid for registration if we haven't registered before */
+		struct sip_peer *peer = NULL;
+
 		if (!r->callid_valid) {
 			build_callid_registry(r, internip.sin_addr, default_fromdomain);
 			r->callid_valid = TRUE;
@@ -11438,8 +11452,15 @@
 		if (p->do_history)
 			append_history(p, "RegistryInit", "Account: %s@%s", r->username, r->hostname);
 
-		ref_proxy(p, obproxy_get(p, NULL));
-
+		if (!ast_strlen_zero(r->peername)) {
+			if (!(peer = find_peer(r->peername, NULL, 1, FINDPEERS, FALSE))) {
+				ast_log(LOG_WARNING, "Could not find peer %s in transmit_register\n", r->peername);
+			}
+		}
+		ref_proxy(p, obproxy_get(p, peer)); /* it is ok to pass a NULL peer into obproxy_get() */
+		if (peer) {
+			unref_peer(peer, "transmit_registration: from find_peer operation");
+		}
 		/* Use port number specified if no SRV record was found */
 		if (!r->us.sin_port && r->portno)
 			r->us.sin_port = htons(r->portno);
@@ -24349,8 +24370,7 @@
 	ast_free_ha(oldha);
 	if (!ast_strlen_zero(callback)) { /* build string from peer info */
 		char *reg_string;
-
-		if (asprintf(&reg_string, "%s:%s@%s/%s", peer->username, peer->remotesecret ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) {
+		if (asprintf(&reg_string, "%s?%s:%s@%s/%s", peer->name, peer->username, peer->remotesecret ? peer->remotesecret : peer->secret, peer->tohost, callback) < 0) {
 			ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
 		} else	if (reg_string) {
 			sip_register(reg_string, 0); /* XXX TODO: count in registry_count */
Index: configs/sip.conf.sample
===================================================================
--- configs/sip.conf.sample	(revision 203104)
+++ configs/sip.conf.sample	(working copy)
@@ -475,7 +475,7 @@
 ;----------------------------------------- OUTBOUND SIP REGISTRATIONS  ------------------------
 ; Asterisk can register as a SIP user agent to a SIP proxy (provider)
 ; Format for the register statement is:
-;       register => [transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
+;       register => [peername?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
 ;
 ;
 ;
