From ae1e51c8573bb11f97c402b9d5daed2e6bc5b0b2 Mon Sep 17 00:00:00 2001
From: "Kevin P. Fleming" <kpfleming@digium.com>
Date: Mon, 29 Aug 2005 23:03:07 +0000
Subject: [PATCH] use proper next hop in strict routing mode (issue #3609)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6443 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 channels/chan_sip.c | 75 +++++++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 30 deletions(-)

diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index c86b0bded1..f43fd73ab6 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -3809,6 +3809,7 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
 	char newto[256];
 	char *c, *n;
 	char *ot, *of;
+	int is_strict = 0;	/* Strict routing flag */
 
 	memset(req, 0, sizeof(struct sip_request));
 	
@@ -3823,17 +3824,23 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
 		p->branch ^= rand();
 		build_via(p, p->via, sizeof(p->via));
 	}
+
+
+	/* Check for strict or loose router */
+	if (p->route && !ast_strlen_zero(p->route->hop) && strstr(p->route->hop,";lr") == NULL)
+		is_strict = 1;
+
 	if (sipmethod == SIP_CANCEL) {
 		c = p->initreq.rlPart2;	/* Use original URI */
 	} else if (sipmethod == SIP_ACK) {
 		/* Use URI from Contact: in 200 OK (if INVITE) 
 		(we only have the contacturi on INVITEs) */
 		if (!ast_strlen_zero(p->okcontacturi))
-			c = p->okcontacturi;
-		else
-			c = p->initreq.rlPart2;
+			c = is_strict ? p->route->hop : p->okcontacturi;
+ 		else
+ 			c = p->initreq.rlPart2;
 	} else if (!ast_strlen_zero(p->okcontacturi)) {
-		c = p->okcontacturi; /* Use for BYE, REFER or REINVITE */
+			c = is_strict ? p->route->hop : p->okcontacturi; /* Use for BYE or REINVITE */
 	} else if (!ast_strlen_zero(p->uri)) {
 		c = p->uri;
 	} else {
@@ -3852,7 +3859,10 @@ static int reqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod, in
 	add_header(req, "Via", p->via);
 	if (p->route) {
 		set_destination(p, p->route->hop);
-		add_route(req, p->route->next);
+		if (is_strict)
+			add_route(req, p->route->next);
+		else
+			add_route(req, p->route);
 	}
 
 	ot = get_header(orig, "To");
@@ -5486,33 +5496,38 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
 			rr += len;
 		}
 	}
-	/* 2nd append the Contact: if there is one */
-	/* Can be multiple Contact headers, comma separated values - we just take the first */
-	contact = get_header(req, "Contact");
-	if (!ast_strlen_zero(contact)) {
-		ast_log(LOG_DEBUG, "build_route: Contact hop: %s\n", contact);
-		/* Look for <: delimited address */
-		c = strchr(contact, '<');
-		if (c) {
-			/* Take to > */
-			++c;
-			len = strcspn(c, ">") + 1;
-		} else {
-			/* No <> - just take the lot */
-			c = contact;
-			len = strlen(contact) + 1;
-		}
-		thishop = malloc(sizeof(*thishop) + len);
-		if (thishop) {
-			ast_copy_string(thishop->hop, c, len);
-			thishop->next = NULL;
-			/* Goes at the end */
-			if (tail)
-				tail->next = thishop;
-			else
-				head = thishop;
+
+	/* Only append the contact if we are dealing with a strict router */
+	if (!head || (!ast_strlen_zero(head->hop) && strstr(head->hop,";lr") == NULL) ) {
+		/* 2nd append the Contact: if there is one */
+		/* Can be multiple Contact headers, comma separated values - we just take the first */
+		contact = get_header(req, "Contact");
+		if (!ast_strlen_zero(contact)) {
+			ast_log(LOG_DEBUG, "build_route: Contact hop: %s\n", contact);
+			/* Look for <: delimited address */
+			c = strchr(contact, '<');
+			if (c) {
+				/* Take to > */
+				++c;
+				len = strcspn(c, ">") + 1;
+			} else {
+				/* No <> - just take the lot */
+				c = contact;
+				len = strlen(contact) + 1;
+			}
+			thishop = malloc(sizeof(*thishop) + len);
+			if (thishop) {
+				strcpy(thishop->hop, c);
+				thishop->next = NULL;
+				/* Goes at the end */
+				if (tail)
+					tail->next = thishop;
+				else
+					head = thishop;
+			}
 		}
 	}
+
 	/* Store as new route */
 	p->route = head;
 
-- 
GitLab