[svn-commits] twilson: trunk r324487 - in /trunk: ./ channels/ include/asterisk/ main/ tests/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jun 22 14:12:28 CDT 2011


Author: twilson
Date: Wed Jun 22 14:12:24 2011
New Revision: 324487

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=324487
Log:
Merged revisions 324484 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.8

........
  r324484 | twilson | 2011-06-22 13:52:04 -0500 (Wed, 22 Jun 2011) | 20 lines
  
  Stop sending IPv6 link-local scope-ids in SIP messages
  
  The idea behind the patch listed below was used, but in a more targeted manner.
  There are now address stringification functions for addresses that are meant to
  be sent to a remote party. Link-local scope-ids only make sense on the machine
  from which they originate and so are stripped in the new functions.
  
  There is also a host sanitization function added to chan_sip which is used
  for when peer and dialog tohost fields or sip_registry hostnames are used to
  craft a SIP message.
  
  Also added are some basic unit tests for netsock2 address parsing.
  
  (closes issue ASTERISK-17711)
  Reported by: ch_djalel
  Patches:
        asterisk-1.8.3.2-ipv6_ll_scope.patch uploaded by ch_djalel (license 1251)
  
  Review: https://reviewboard.asterisk.org/r/1278/
........

Added:
    trunk/tests/test_netsock2.c
      - copied unchanged from r324484, branches/1.8/tests/test_netsock2.c
Modified:
    trunk/   (props changed)
    trunk/channels/chan_sip.c
    trunk/include/asterisk/netsock2.h
    trunk/main/netsock2.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-1.8-merged' - no diff available.

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=324487&r1=324486&r2=324487
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Jun 22 14:12:24 2011
@@ -3398,7 +3398,7 @@
 	/* z9hG4bK is a magic cookie.  See RFC 3261 section 8.1.1.7 */
 	snprintf(p->via, sizeof(p->via), "SIP/2.0/%s %s;branch=z9hG4bK%08x%s",
 		 get_transport_pvt(p),
-		 ast_sockaddr_stringify(&p->ourip),
+		 ast_sockaddr_stringify_remote(&p->ourip),
 		 (int) p->branch, rport);
 }
 
@@ -5215,7 +5215,7 @@
 	dialog->disallowed_methods = peer->disallowed_methods;
 	ast_cc_copy_config_params(dialog->cc_params, peer->cc_params);
 	if (ast_strlen_zero(dialog->tohost))
-		ast_string_field_set(dialog, tohost, ast_sockaddr_stringify_host(&dialog->sa));
+		ast_string_field_set(dialog, tohost, ast_sockaddr_stringify_host_remote(&dialog->sa));
 	if (!ast_strlen_zero(peer->fromdomain)) {
 		ast_string_field_set(dialog, fromdomain, peer->fromdomain);
 		if (!dialog->initreq.headers) {
@@ -7361,7 +7361,7 @@
 	 * use the handy random string generation function we already have
 	 */
 	ast_str_append(&uri, 0, "%s", generate_random_string(buf, size));
-	ast_str_append(&uri, 0, "@%s", ast_sockaddr_stringify(&pvt->ourip));
+	ast_str_append(&uri, 0, "@%s", ast_sockaddr_stringify_remote(&pvt->ourip));
 	ast_copy_string(buf, ast_str_buffer(uri), size);
 	return buf;
 }
@@ -7371,7 +7371,7 @@
 {
 	char buf[33];
 
-	const char *host = S_OR(pvt->fromdomain, ast_sockaddr_stringify(&pvt->ourip));
+	const char *host = S_OR(pvt->fromdomain, ast_sockaddr_stringify_remote(&pvt->ourip));
 	
 	ast_string_field_build(pvt, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
 
@@ -7382,7 +7382,7 @@
 {
 	char buf[33];
 
-	const char *host = S_OR(fromdomain, ast_sockaddr_stringify_host(ourip));
+	const char *host = S_OR(fromdomain, ast_sockaddr_stringify_host_remote(ourip));
 
 	ast_string_field_build(reg, callid, "%s@%s", generate_random_string(buf, sizeof(buf)), host);
 }
@@ -9850,13 +9850,13 @@
 
 				/* Add rport to first VIA header if requested */
 				snprintf(new, sizeof(new), "%s;received=%s;rport=%d%s%s",
-					leftmost, ast_sockaddr_stringify_addr(&p->recv),
+					leftmost, ast_sockaddr_stringify_addr_remote(&p->recv),
 					ast_sockaddr_port(&p->recv),
 					others ? "," : "", others ? others : "");
 			} else {
 				/* We should *always* add a received to the topmost via */
 				snprintf(new, sizeof(new), "%s;received=%s%s%s",
-					leftmost, ast_sockaddr_stringify_addr(&p->recv),
+					leftmost, ast_sockaddr_stringify_addr_remote(&p->recv),
 					others ? "," : "", others ? others : "");
 			}
 			oh = new;	/* the header to copy */
@@ -10730,7 +10730,7 @@
 		return 0;
 	if (ast_strlen_zero(lid_name))
 		lid_name = lid_num;
-	fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
+	fromdomain = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip));
 
 	lid_num = ast_uri_encode(lid_num, tmp2, sizeof(tmp2), ast_uri_sip_user);
 
@@ -11211,12 +11211,12 @@
 		 p->sessionid, p->sessionversion,
 		 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
 			"IP6" : "IP4",
-		 ast_sockaddr_stringify_addr(&dest));
+		 ast_sockaddr_stringify_addr_remote(&dest));
 
 	snprintf(connection, sizeof(connection), "c=IN %s %s\r\n",
 		 (ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
 			"IP6" : "IP4",
-		 ast_sockaddr_stringify_addr(&dest));
+		 ast_sockaddr_stringify_addr_remote(&dest));
 
 	if (add_audio) {
 		if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR) {
@@ -11399,7 +11399,7 @@
 		if (!ast_sockaddr_cmp(&udptldest, &dest)) {
 			ast_str_append(&m_modem, 0, "c=IN %s %s\r\n",
 					(ast_sockaddr_is_ipv6(&dest) && !ast_sockaddr_is_ipv4_mapped(&dest)) ?
-					"IP6" : "IP4", ast_sockaddr_stringify_addr(&udptldest));
+					"IP6" : "IP4", ast_sockaddr_stringify_addr_remote(&udptldest));
 		}
 
 		ast_str_append(&a_modem, 0, "a=T38FaxVersion:%d\r\n", p->t38.our_parms.version);
@@ -11754,10 +11754,10 @@
 
 	if (p->socket.type == SIP_TRANSPORT_UDP) {
 		ast_string_field_build(p, our_contact, "<sip:%s%s%s>", user,
-			ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify(&p->ourip));
+			ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify_remote(&p->ourip));
 	} else {
 		ast_string_field_build(p, our_contact, "<sip:%s%s%s;transport=%s>", user,
-			ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify(&p->ourip),
+			ast_strlen_zero(user) ? "" : "@", ast_sockaddr_stringify_remote(&p->ourip),
 			get_transport(p->socket.type));
 	}
 }
@@ -11798,7 +11798,7 @@
 
 	snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
 
-	d = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
+	d = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip));
 	if (p->owner) {
 		if ((ast_party_id_presentation(&p->owner->connected.id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
 			l = p->owner->connected.id.number.valid ? p->owner->connected.id.number.str : NULL;
@@ -11962,11 +11962,11 @@
 	if (!pvt->owner->redirecting.from.name.valid
 		|| ast_strlen_zero(diverting_name)) {
 		snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number,
-				ast_sockaddr_stringify_host(&pvt->ourip), reason);
+				ast_sockaddr_stringify_host_remote(&pvt->ourip), reason);
 	} else {
 		snprintf(header_text, sizeof(header_text), "\"%s\" <sip:%s@%s>;reason=%s",
 				diverting_name, diverting_number,
-				ast_sockaddr_stringify_host(&pvt->ourip), reason);
+				ast_sockaddr_stringify_host_remote(&pvt->ourip), reason);
 	}
 
 	add_header(req, "Diversion", header_text);
@@ -12593,7 +12593,7 @@
 	struct sip_request req;
 	struct ast_str *out = ast_str_alloca(500);
 	int ourport = (p->fromdomainport) ? p->fromdomainport : ast_sockaddr_port(&p->ourip);
-	const char *domain = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
+	const char *domain = S_OR(p->fromdomain, ast_sockaddr_stringify_host_remote(&p->ourip));
 	const char *exten = S_OR(vmexten, default_vmexten);
 
 	initreqprep(&req, p, SIP_NOTIFY, NULL);
@@ -12921,6 +12921,19 @@
 	manager_event(EVENT_FLAG_SYSTEM, "Registry", "ChannelType: SIP\r\nUsername: %s\r\nDomain: %s\r\nStatus: %s\r\n", r->username, r->hostname, regstate2str(r->regstate));
 	registry_unref(r, "unreffing registry_unref r");
 	return 0;
+}
+
+static const char *sip_sanitized_host(const char *host)
+{
+	struct ast_sockaddr addr = { { 0, 0, }, };
+
+	/* peer/sip_pvt->tohost and sip_registry->hostname should never have a port
+	 * in them, so we use PARSE_PORT_FORBID here. If this lookup fails, we return
+	 * the original host which is most likely a host name and not an IP. */
+	if (!ast_sockaddr_parse(&addr, host, PARSE_PORT_FORBID)) {
+		return host;
+	}
+	return ast_sockaddr_stringify_host_remote(&addr);
 }
 
 /*! \brief Transmit register to SIP proxy or UA
@@ -13076,19 +13089,19 @@
 		ast_debug(1, "Scheduled a registration timeout for %s id  #%d \n", r->hostname, r->timeout);
 	}
 
-	snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, S_OR(r->regdomain,p->tohost), p->tag);
+	snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", r->username, S_OR(r->regdomain, sip_sanitized_host(p->tohost)), p->tag);
 	if (!ast_strlen_zero(p->theirtag)) {
-		snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, S_OR(r->regdomain,p->tohost), p->theirtag);
+		snprintf(to, sizeof(to), "<sip:%s@%s>;tag=%s", r->username, S_OR(r->regdomain, sip_sanitized_host(p->tohost)), p->theirtag);
 	} else {
-		snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, S_OR(r->regdomain,p->tohost));
+		snprintf(to, sizeof(to), "<sip:%s@%s>", r->username, S_OR(r->regdomain, sip_sanitized_host(p->tohost)));
 	}
 
 	/* Fromdomain is what we are registering to, regardless of actual
   	   host name from SRV */
 	if (portno && portno != STANDARD_SIP_PORT) {
-		snprintf(addr, sizeof(addr), "sip:%s:%d", S_OR(p->fromdomain,S_OR(r->regdomain,r->hostname)), portno);
+		snprintf(addr, sizeof(addr), "sip:%s:%d", S_OR(p->fromdomain,S_OR(r->regdomain, sip_sanitized_host(r->hostname))), portno);
 	} else {
-		snprintf(addr, sizeof(addr), "sip:%s", S_OR(p->fromdomain,S_OR(r->regdomain,r->hostname)));
+		snprintf(addr, sizeof(addr), "sip:%s", S_OR(p->fromdomain,S_OR(r->regdomain, sip_sanitized_host(r->hostname))));
 	}
 
 	ast_string_field_set(p, uri, addr);
@@ -19068,7 +19081,7 @@
 	else if (!ast_strlen_zero(p->uri))
 		ast_copy_string(uri, p->uri, sizeof(uri));
 	else
-		snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host(&p->sa));
+		snprintf(uri, sizeof(uri), "sip:%s@%s", p->username, ast_sockaddr_stringify_host_remote(&p->sa));
 
 	snprintf(cnonce, sizeof(cnonce), "%08lx", ast_random());
 
@@ -26072,7 +26085,7 @@
 	if (!ast_strlen_zero(peer->tohost))
 		ast_string_field_set(p, tohost, peer->tohost);
 	else
-		ast_string_field_set(p, tohost, ast_sockaddr_stringify_host(&peer->addr));
+		ast_string_field_set(p, tohost, ast_sockaddr_stringify_host_remote(&peer->addr));
 
 	/* Recalculate our side, and recalculate Call ID */
 	ast_sip_ouraddrfor(&p->sa, &p->ourip, p);

Modified: trunk/include/asterisk/netsock2.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/netsock2.h?view=diff&rev=324487&r1=324486&r2=324487
==============================================================================
--- trunk/include/asterisk/netsock2.h (original)
+++ trunk/include/asterisk/netsock2.h Wed Jun 22 14:12:24 2011
@@ -152,8 +152,13 @@
 #define AST_SOCKADDR_STR_ADDR		(1 << 0)
 #define AST_SOCKADDR_STR_PORT		(1 << 1)
 #define AST_SOCKADDR_STR_BRACKETS	(1 << 2)
-#define AST_SOCKADDR_STR_HOST		AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_BRACKETS
-#define AST_SOCKADDR_STR_DEFAULT	AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_PORT
+#define AST_SOCKADDR_STR_REMOTE		(1 << 3)
+#define AST_SOCKADDR_STR_HOST		(AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_BRACKETS)
+#define AST_SOCKADDR_STR_DEFAULT	(AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_PORT)
+#define AST_SOCKADDR_STR_ADDR_REMOTE     (AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_REMOTE)
+#define AST_SOCKADDR_STR_HOST_REMOTE     (AST_SOCKADDR_STR_HOST | AST_SOCKADDR_STR_REMOTE)
+#define AST_SOCKADDR_STR_DEFAULT_REMOTE  (AST_SOCKADDR_STR_DEFAULT | AST_SOCKADDR_STR_REMOTE)
+#define AST_SOCKADDR_STR_FORMAT_MASK     (AST_SOCKADDR_STR_ADDR | AST_SOCKADDR_STR_PORT | AST_SOCKADDR_STR_BRACKETS)
 
 /*!
  * \since 1.8
@@ -203,6 +208,23 @@
  * \since 1.8
  *
  * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() with default format
+ *
+ * \note This address will be suitable for passing to a remote machine via the
+ * application layer. For example, the scope-id on a link-local IPv6 address
+ * will be stripped.
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_remote(const struct ast_sockaddr *addr)
+{
+	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_DEFAULT_REMOTE);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
  * Wrapper around ast_sockaddr_stringify_fmt() to return an address only
  *
  * \return same as ast_sockaddr_stringify_fmt()
@@ -210,6 +232,23 @@
 static inline char *ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
 {
 	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_ADDR);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() to return an address only
+ *
+ * \note This address will be suitable for passing to a remote machine via the
+ * application layer. For example, the scope-id on a link-local IPv6 address
+ * will be stripped.
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_addr_remote(const struct ast_sockaddr *addr)
+{
+	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_ADDR_REMOTE);
 }
 
 /*!
@@ -224,6 +263,24 @@
 static inline char *ast_sockaddr_stringify_host(const struct ast_sockaddr *addr)
 {
 	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_HOST);
+}
+
+/*!
+ * \since 1.8
+ *
+ * \brief
+ * Wrapper around ast_sockaddr_stringify_fmt() to return an address only,
+ * suitable for a URL (with brackets for IPv6).
+ *
+ * \note This address will be suitable for passing to a remote machine via the
+ * application layer. For example, the scope-id on a link-local IPv6 address
+ * will be stripped.
+ *
+ * \return same as ast_sockaddr_stringify_fmt()
+ */
+static inline char *ast_sockaddr_stringify_host_remote(const struct ast_sockaddr *addr)
+{
+	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_HOST_REMOTE);
 }
 
 /*!
@@ -413,6 +470,20 @@
  * \since 1.8
  *
  * \brief
+ * Determine if this is a link-local IPv6 address
+ *
+ * \warning You should rarely need this function. Only use if you know what
+ * you're doing.
+ *
+ * \retval 1 This is a link-local IPv6 address.
+ * \retval 0 This is link-local IPv6 address.
+ */
+int ast_sockaddr_is_ipv6_link_local(const struct ast_sockaddr *addr);
+
+/*!
+ * \since 1.8
+ *
+ * \brief
  * Determine if this is an IPv6 address
  *
  * \warning You should rarely need this function. Only use if you know what

Modified: trunk/main/netsock2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/netsock2.c?view=diff&rev=324487&r1=324486&r2=324487
==============================================================================
--- trunk/main/netsock2.c (original)
+++ trunk/main/netsock2.c Wed Jun 22 14:12:24 2011
@@ -95,7 +95,14 @@
 		return "";
 	}
 
-	switch (format)  {
+	if ((format & AST_SOCKADDR_STR_REMOTE) == AST_SOCKADDR_STR_REMOTE) {
+		char *p;
+		if (ast_sockaddr_is_ipv6_link_local(sa) && (p = strchr(host, '%'))) {
+			*p = '\0';
+		}
+	}
+
+	switch ((format & AST_SOCKADDR_STR_FORMAT_MASK))  {
 	case AST_SOCKADDR_STR_DEFAULT:
 		ast_str_set(&str, 0, sa_tmp->ss.ss_family == AF_INET6 ?
 				"[%s]:%s" : "%s:%s", host, port);
@@ -395,6 +402,12 @@
 int ast_sockaddr_is_ipv4_multicast(const struct ast_sockaddr *addr)
 {
 	return ((ast_sockaddr_ipv4(addr) & 0xf0000000) == 0xe0000000);
+}
+
+int ast_sockaddr_is_ipv6_link_local(const struct ast_sockaddr *addr)
+{
+	const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr->ss;
+	return ast_sockaddr_is_ipv6(addr) && IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr);
 }
 
 int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)




More information about the svn-commits mailing list