[asterisk-commits] mnicholson: trunk r304246 - in /trunk: ./ channels/ channels/sip/ channels/si...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 26 14:44:51 CST 2011


Author: mnicholson
Date: Wed Jan 26 14:44:47 2011
New Revision: 304246

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

................
  r304245 | mnicholson | 2011-01-26 14:43:27 -0600 (Wed, 26 Jan 2011) | 20 lines
  
  Merged revisions 304244 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/branches/1.6.2
  
  ................
    r304244 | mnicholson | 2011-01-26 14:42:16 -0600 (Wed, 26 Jan 2011) | 13 lines
    
    Merged revisions 304241 via svnmerge from 
    https://origsvn.digium.com/svn/asterisk/branches/1.4
    
    ........
      r304241 | mnicholson | 2011-01-26 14:38:22 -0600 (Wed, 26 Jan 2011) | 6 lines
      
      This patch modifies chan_sip to route responses to the address the request came from.  It also modifies chan_sip to respect the maddr parameter in the Via header.
      
      ABE-2664
      
      Review: https://reviewboard.asterisk.org/r/1059/
    ........
  ................
................

Modified:
    trunk/   (props changed)
    trunk/channels/chan_sip.c
    trunk/channels/sip/include/reqresp_parser.h
    trunk/channels/sip/include/sip.h
    trunk/channels/sip/reqresp_parser.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=304246&r1=304245&r2=304246
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Jan 26 14:44:47 2011
@@ -7153,17 +7153,20 @@
 	/* If this dialog is created as a result of a request or response, lets store
 	 * some information about it in the dialog. */
 	if (req) {
-		char *sent_by, *branch;
+		struct sip_via *via;
 		const char *cseq = get_header(req, "Cseq");
 		unsigned int seqno;
 
 		/* get branch parameter from initial Request that started this dialog */
-		get_viabranch(ast_strdupa(get_header(req, "Via")), &sent_by, &branch);
-		/* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
-		 * it is not useful to us to have it */
-		if (!ast_strlen_zero(branch) && !strncasecmp(branch, "z9hG4bK", 7)) {
-			ast_string_field_set(p, initviabranch, branch);
-			ast_string_field_set(p, initviasentby, sent_by);
+		via = parse_via(get_header(req, "Via"));
+		if (via) {
+			/* only store the branch if it begins with the magic prefix "z9hG4bK", otherwise
+			 * it is not useful to us to have it */
+			if (!ast_strlen_zero(via->branch) && !strncasecmp(via->branch, "z9hG4bK", 7)) {
+				ast_string_field_set(p, initviabranch, via->branch);
+				ast_string_field_set(p, initviasentby, via->sent_by);
+			}
+			free_via(via);
 		}
 
 		/* Store initial incoming cseq. An error in sscanf here is ignored.  There is no approperiate
@@ -7273,6 +7276,38 @@
 	
 	ast_debug(1, "Allocating new SIP dialog for %s - %s (%s)\n", callid ? callid : p->callid, sip_methods[intended_method].text, p->rtp ? "With RTP" : "No RTP");
 	return p;
+}
+
+static int process_via(struct sip_pvt *p, const struct sip_request *req)
+{
+	struct sip_via *via = parse_via(get_header(req, "Via"));
+
+	if (!via) {
+		ast_log(LOG_ERROR, "error processing via header\n");
+		return -1;
+	}
+
+	if (via->maddr) {
+		if (ast_sockaddr_resolve_first(&p->sa, via->maddr, PARSE_PORT_FORBID)) {
+			ast_log(LOG_WARNING, "Can't find address for maddr '%s'\n", via->maddr);
+			ast_log(LOG_ERROR, "error processing via header\n");
+			free_via(via);
+			return -1;
+		}
+
+		if (via->port) {
+			ast_sockaddr_set_port(&p->sa, via->port);
+		} else {
+			ast_sockaddr_set_port(&p->sa, STANDARD_SIP_PORT);
+		}
+
+		if (ast_sockaddr_is_ipv4_multicast(&p->sa)) {
+			setsockopt(sipsock, IPPROTO_IP, IP_MULTICAST_TTL, &via->ttl, sizeof(via->ttl));
+		}
+	}
+
+	free_via(via);
+	return 0;
 }
 
 /* \brief arguments used for Request/Response to matching */
@@ -7572,6 +7607,7 @@
 			dialog_find_multiple,
 			&tmp_dialog,
 			"pedantic ao2_find in dialogs");
+		struct sip_via *via = NULL;
 
 		args.method = req->method;
 		args.callid = NULL; /* we already matched this. */
@@ -7580,7 +7616,11 @@
 		args.seqno = seqno;
 		/* get via header information. */
 		args.ruri = REQ_OFFSET_TO_STR(req, rlPart2);
-		get_viabranch(ast_strdupa(get_header(req, "Via")), (char **) &args.viasentby, (char **) &args.viabranch);
+		via = parse_via(get_header(req, "Via"));
+		if (via) {
+			args.viasentby = via->sent_by;
+			args.viabranch = via->branch;
+		}
 		/* determine if this is a Request with authentication credentials. */
 		if (!ast_strlen_zero(get_header(req, "Authorization")) ||
 			!ast_strlen_zero(get_header(req, "Proxy-Authorization"))) {
@@ -7604,6 +7644,7 @@
 				sip_pvt_lock(sip_pvt_ptr);
 				ao2_iterator_destroy(iterator);
 				dialog_unref(fork_pvt, "unref fork_pvt");
+				free_via(via);
 				return sip_pvt_ptr; /* return pvt with ref */
 			case SIP_REQ_LOOP_DETECTED:
 				/* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
@@ -7612,6 +7653,7 @@
 				dialog_unref(sip_pvt_ptr, "pvt did not match incoming SIP msg, unref from search.");
 				ao2_iterator_destroy(iterator);
 				dialog_unref(fork_pvt, "unref fork_pvt");
+				free_via(via);
 				return NULL;
 			case SIP_REQ_FORKED:
 				dialog_unref(fork_pvt, "throwing way pvt to fork off of.");
@@ -7633,10 +7675,13 @@
 			if (fork_pvt->method == SIP_INVITE) {
 				forked_invite_init(req, args.totag, fork_pvt, addr);
 				dialog_unref(fork_pvt, "throwing way old forked pvt");
+				free_via(via);
 				return NULL;
 			}
 			fork_pvt = dialog_unref(fork_pvt, "throwing way pvt to fork off of");
 		}
+
+		free_via(via);
 	} /* end of pedantic mode Request/Reponse to Dialog matching */
 
 	/* See if the method is capable of creating a dialog */
@@ -9684,6 +9729,15 @@
 	if (!ast_strlen_zero(p->url)) {
 		add_header(resp, "Access-URL", p->url);
 		ast_string_field_set(p, url, NULL);
+	}
+
+	/* default to routing the response to the address where the request
+	 * came from.  Since we don't have a transport layer, we do this here.
+	 */
+	p->sa = p->recv;
+
+	if (process_via(p, req)) {
+		ast_log(LOG_WARNING, "error processing via header, will send response to originating address\n");
 	}
 
 	return 0;

Modified: trunk/channels/sip/include/reqresp_parser.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/reqresp_parser.h?view=diff&rev=304246&r1=304245&r2=304246
==============================================================================
--- trunk/channels/sip/include/reqresp_parser.h (original)
+++ trunk/channels/sip/include/reqresp_parser.h Wed Jan 26 14:44:47 2011
@@ -166,9 +166,43 @@
 void sip_reqresp_parser_exit(void);
 
 /*!
- * \brief Parse the VIA header into it's parts.
- *
- * \note This will modify the string
- */
-void get_viabranch(char *via, char **sent_by, char **branch);
+ * \brief Parse a Via header
+ *
+ * This function parses the Via header and processes it according to section
+ * 18.2 of RFC 3261 and RFC 3581. Since we don't have a transport layer, we
+ * only care about the maddr and ttl parms.  The received and rport params are
+ * not parsed.
+ *
+ * \note This function fails to parse some odd combinations of SWS in parameter
+ * lists.
+ *
+ * \code
+ * VIA syntax. RFC 3261 section 25.1
+ * Via               =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
+ * via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )
+ * via-params        =  via-ttl / via-maddr
+ *                   / via-received / via-branch
+ *                   / via-extension
+ * via-ttl           =  "ttl" EQUAL ttl
+ * via-maddr         =  "maddr" EQUAL host
+ * via-received      =  "received" EQUAL (IPv4address / IPv6address)
+ * via-branch        =  "branch" EQUAL token
+ * via-extension     =  generic-param
+ * sent-protocol     =  protocol-name SLASH protocol-version
+ *                   SLASH transport
+ * protocol-name     =  "SIP" / token
+ * protocol-version  =  token
+ * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
+ *                   / other-transport
+ * sent-by           =  host [ COLON port ]
+ * ttl               =  1*3DIGIT ; 0 to 255
+ * \endcode
+ */
+struct sip_via *parse_via(const char *header);
+
+/*
+ * \brief Free parsed Via data.
+ */
+void free_via(struct sip_via *v);
+
 #endif

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=304246&r1=304245&r2=304246
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Wed Jan 26 14:44:47 2011
@@ -787,6 +787,17 @@
 struct sip_route {
 	struct sip_route *next;
 	char hop[0];
+};
+
+/*! \brief Structure to store Via information */
+struct sip_via {
+	char *via;
+	const char *protocol;
+	const char *sent_by;
+	const char *branch;
+	const char *maddr;
+	unsigned int port;
+	unsigned char ttl;
 };
 
 /*! \brief Domain data structure.

Modified: trunk/channels/sip/reqresp_parser.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/reqresp_parser.c?view=diff&rev=304246&r1=304245&r2=304246
==============================================================================
--- trunk/channels/sip/reqresp_parser.c (original)
+++ trunk/channels/sip/reqresp_parser.c Wed Jan 26 14:44:47 2011
@@ -2243,123 +2243,159 @@
 	return test_res;
 }
 
-void get_viabranch(char *via, char **sent_by, char **branch)
-{
-	char *tmp;
-
-	if (sent_by) {
-		*sent_by = NULL;
-	}
-	if (branch) {
-		*branch = NULL;
-	}
+void free_via(struct sip_via *v)
+{
+	if (!v) {
+		return;
+	}
+
+	if (v->via) {
+		ast_free(v->via);
+	}
+
+	ast_free(v);
+}
+
+struct sip_via *parse_via(const char *header)
+{
+	struct sip_via *v = ast_calloc(1, sizeof(*v));
+	char *via, *parm;
+
+	if (!v) {
+		return NULL;
+	}
+
+	v->via = ast_strdup(header);
+	v->ttl = 1;
+
+	via = v->via;
+
 	if (ast_strlen_zero(via)) {
-		return;
-	}
-	via = ast_skip_blanks(via);
-	/*
-	 * VIA syntax. RFC 3261 section 6.40.5
-	 * Via = ( "Via" | "v") ":" 1#( sent-protocol sent-by *( ";" via-params ) [ comment ] )
-	 * via-params  = via-hidden | via-ttl | via-maddr | via-received | via-branch
-	 * via-hidden       = "hidden"
-	 * via-ttl          = "ttl" "=" ttl
-	 * via-maddr        = "maddr" "=" maddr
-	 * via-received     = "received" "=" host
-	 * via-branch       = "branch" "=" token
-	 * sent-protocol    = protocol-name "/" protocol-version "/" transport
-	 * protocol-name    = "SIP" | token
-	 * protocol-version = token
-	 * transport        = "UDP" | "TCP" | token
-	 * sent-by          = ( host [ ":" port ] ) | ( concealed-host )
-	 * concealed-host   = token
-	 * ttl              = 1*3DIGIT     ; 0 to 255	
-	 */
-
-	/* chop off ("Via:" | "v:") if present */
-	if (!strncasecmp(via, "Via:", 4)) {
-		via += 4;
-	} else if (!strncasecmp(via, "v:", 2)) {
-		via += 2;
-	}
-	if (ast_strlen_zero(via)) {
-		return;
-	}
+		ast_log(LOG_ERROR, "received request without a Via header\n");
+		free_via(v);
+		return NULL;
+	}
+
+	/* seperate the first via-parm */
+	via = strsep(&via, ",");
 
 	/* chop off sent-protocol */
-	via = ast_skip_blanks(via);
-	strsep(&via, " \t\r\n");
-	if (ast_strlen_zero(via)) {
-		return;
+	v->protocol = strsep(&via, " \t\r\n");
+	if (ast_strlen_zero(v->protocol)) {
+		ast_log(LOG_ERROR, "missing sent-protocol in Via header\n");
+		free_via(v);
+		return NULL;
+	}
+	v->protocol = ast_skip_blanks(v->protocol);
+
+	if (via) {
+		via = ast_skip_blanks(via);
 	}
 
 	/* chop off sent-by */
-	via = ast_skip_blanks(via);
-	*sent_by = strsep(&via, "; \t\r\n");
-	if (ast_strlen_zero(via)) {
-		return;
-	}
-
-	/* now see if there is a branch parameter in there */
-	if (!ast_strlen_zero(via) && (tmp = strstr(via, "branch="))) {
-		/* find the branch ID */
-		via = ast_skip_blanks(tmp + 7);
-
-		/* chop off the branch parameter */
-		*branch = strsep(&via, "; \t\r\n");
-	}
-}
-
-AST_TEST_DEFINE(get_viabranch_test)
+	v->sent_by = strsep(&via, "; \t\r\n");
+	if (ast_strlen_zero(v->sent_by)) {
+		ast_log(LOG_ERROR, "missing sent-by in Via header\n");
+		free_via(v);
+		return NULL;
+	}
+	v->sent_by = ast_skip_blanks(v->sent_by);
+
+	/* store the port */
+	if ((parm = strchr(v->sent_by, ':'))) {
+		char *endptr;
+
+		v->port = strtol(++parm, &endptr, 10);
+	}
+
+	/* evaluate any via-parms */
+	while ((parm = strsep(&via, "; \t\r\n"))) {
+		char *c;
+		if ((c = strstr(parm, "maddr="))) {
+			v->maddr = ast_skip_blanks(c + sizeof("maddr=") - 1);
+		} else if ((c = strstr(parm, "branch="))) {
+			v->branch = ast_skip_blanks(c + sizeof("branch=") - 1);
+		} else if ((c = strstr(parm, "ttl="))) {
+			char *endptr;
+			c = ast_skip_blanks(c + sizeof("ttl=") - 1);
+			v->ttl = strtol(c, &endptr, 10);
+
+			/* make sure we got a valid ttl value */
+			if (c == endptr) {
+				v->ttl = 1;
+			}
+		}
+	}
+
+	return v;
+}
+
+AST_TEST_DEFINE(parse_via_test)
 {
 	int res = AST_TEST_PASS;
 	int i = 1;
-	char *sent_by, *branch;
+	struct sip_via *via;
 	struct testdata {
 		char *in;
+		char *expected_protocol;
 		char *expected_branch;
 		char *expected_sent_by;
+		char *expected_maddr;
+		unsigned int expected_port;
+		unsigned char expected_ttl;
+		int expected_null;
 		AST_LIST_ENTRY(testdata) list;
 	};
 	struct testdata *testdataptr;
 	static AST_LIST_HEAD_NOLOCK(testdataliststruct, testdata) testdatalist;
 	struct testdata t1 = {
-		.in = "Via: SIP/2.0/UDP host:port;branch=thebranch",
+		.in = "SIP/2.0/UDP host:port;branch=thebranch",
+		.expected_protocol = "SIP/2.0/UDP",
+		.expected_sent_by = "host:port",
 		.expected_branch = "thebranch",
-		.expected_sent_by = "host:port"
 	};
 	struct testdata t2 = {
-		.in = "SIP/2.0/UDP host:port;branch=thebranch",
+		.in = "SIP/2.0/UDP host:port",
+		.expected_protocol = "SIP/2.0/UDP",
+		.expected_sent_by = "host:port",
+		.expected_branch = "",
+	};
+	struct testdata t3 = {
+		.in = "SIP/2.0/UDP",
+		.expected_null = 1,
+	};
+	struct testdata t4 = {
+		.in = "BLAH/BLAH/BLAH host:port;branch=",
+		.expected_protocol = "BLAH/BLAH/BLAH",
+		.expected_sent_by = "host:port",
+		.expected_branch = "",
+	};
+	struct testdata t5 = {
+		.in = "SIP/2.0/UDP host:5060;branch=thebranch;maddr=224.0.0.1;ttl=1",
+		.expected_protocol = "SIP/2.0/UDP",
+		.expected_sent_by = "host:5060",
+		.expected_port = 5060,
 		.expected_branch = "thebranch",
-		.expected_sent_by = "host:port"
-	};
-	struct testdata t3 = {
-		.in = "SIP/2.0/UDP host:port",
-		.expected_branch = "",
-		.expected_sent_by = "host:port"
-	};
-	struct testdata t4 = {
-		.in = "BLAH/BLAH/BLAH            host:port        ;    branch=        thebranch ;;;;;;;",
+		.expected_maddr = "224.0.0.1",
+		.expected_ttl = 1,
+	};
+	struct testdata t6 = {
+		.in = "SIP/2.0/UDP      host:5060;\n   branch=thebranch;\r\n  maddr=224.0.0.1;   ttl=1",
+		.expected_protocol = "SIP/2.0/UDP",
+		.expected_sent_by = "host:5060",
+		.expected_port = 5060,
 		.expected_branch = "thebranch",
-		.expected_sent_by = "host:port"
-	};
-	struct testdata t5 = {
-		.in = "v: BLAH/BLAH/BLAH",
-		.expected_branch = "",
-		.expected_sent_by = ""
-	};
-	struct testdata t6 = {
-		.in = "BLAH/BLAH/BLAH host:port;branch=",
-		.expected_branch = "",
-		.expected_sent_by = "host:port"
+		.expected_maddr = "224.0.0.1",
+		.expected_ttl = 1,
 	};
 	switch (cmd) {
 	case TEST_INIT:
-		info->name = "get_viabranch_test";
+		info->name = "parse_via_test";
 		info->category = "/channels/chan_sip/";
-		info->summary = "Tests getting sent-by and branch parameter from via";
+		info->summary = "Tests parsing the Via header";
 		info->description =
-				"Runs through various test situations in which a sent-by and"
-				" branch parameter must be extracted from a VIA header";
+				"Runs through various test situations in which various "
+				" parameters parameter must be extracted from a VIA header";
 		return AST_TEST_NOT_RUN;
 	case TEST_EXECUTE:
 		break;
@@ -2374,15 +2410,91 @@
 
 
 	AST_LIST_TRAVERSE(&testdatalist, testdataptr, list) {
-		get_viabranch(ast_strdupa(testdataptr->in), &sent_by, &branch);
-		if ((ast_strlen_zero(sent_by) && !ast_strlen_zero(testdataptr->expected_sent_by)) ||
-			(ast_strlen_zero(branch) && !ast_strlen_zero(testdataptr->expected_branch)) ||
-			(!ast_strlen_zero(sent_by) && strcmp(sent_by, testdataptr->expected_sent_by)) ||
-			(!ast_strlen_zero(branch) && strcmp(branch, testdataptr->expected_branch))) {
-			ast_test_status_update(test, "TEST#%d FAILED:  VIA = \"%s\" parsed sent-by = \"%s\" parsed branch = \"%s\"\n",
-			i, testdataptr->in, sent_by, branch);
+		via = parse_via(testdataptr->in);
+		if (!via) {
+		        if (!testdataptr->expected_null) {
+				ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+					"failed to parse header\n",
+				i, testdataptr->in);
+				res = AST_TEST_FAIL;
+			}
+			i++;
+			continue;
+		}
+
+		if (testdataptr->expected_null) {
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"successfully parased invalid via header\n",
+			i, testdataptr->in);
 			res = AST_TEST_FAIL;
-		}
+			free_via(via);
+			i++;
+			continue;
+		}
+
+		if ((ast_strlen_zero(via->protocol) && !ast_strlen_zero(testdataptr->expected_protocol))
+			|| (!ast_strlen_zero(via->protocol) && strcmp(via->protocol, testdataptr->expected_protocol))) {
+
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed protocol = \"%s\"\n"
+				"expected = \"%s\"\n"
+				"failed to parse protocol\n",
+			i, testdataptr->in, via->protocol, testdataptr->expected_protocol);
+			res = AST_TEST_FAIL;
+		}
+
+		if ((ast_strlen_zero(via->sent_by) && !ast_strlen_zero(testdataptr->expected_sent_by))
+			|| (!ast_strlen_zero(via->sent_by) && strcmp(via->sent_by, testdataptr->expected_sent_by))) {
+
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed sent_by = \"%s\"\n"
+				"expected = \"%s\"\n"
+				"failed to parse sent-by\n",
+			i, testdataptr->in, via->sent_by, testdataptr->expected_sent_by);
+			res = AST_TEST_FAIL;
+		}
+
+		if (testdataptr->expected_port && testdataptr->expected_port != via->port) {
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed port = \"%d\"\n"
+				"expected = \"%d\"\n"
+				"failed to parse port\n",
+			i, testdataptr->in, via->port, testdataptr->expected_port);
+			res = AST_TEST_FAIL;
+		}
+
+		if ((ast_strlen_zero(via->branch) && !ast_strlen_zero(testdataptr->expected_branch))
+			|| (!ast_strlen_zero(via->branch) && strcmp(via->branch, testdataptr->expected_branch))) {
+
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed branch = \"%s\"\n"
+				"expected = \"%s\"\n"
+				"failed to parse branch\n",
+			i, testdataptr->in, via->branch, testdataptr->expected_branch);
+			res = AST_TEST_FAIL;
+		}
+
+		if ((ast_strlen_zero(via->maddr) && !ast_strlen_zero(testdataptr->expected_maddr))
+			|| (!ast_strlen_zero(via->maddr) && strcmp(via->maddr, testdataptr->expected_maddr))) {
+
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed maddr = \"%s\"\n"
+				"expected = \"%s\"\n"
+				"failed to parse maddr\n",
+			i, testdataptr->in, via->maddr, testdataptr->expected_maddr);
+			res = AST_TEST_FAIL;
+		}
+
+		if (testdataptr->expected_ttl && testdataptr->expected_ttl != via->ttl) {
+			ast_test_status_update(test, "TEST#%d FAILED: VIA = \"%s\"\n"
+				"parsed ttl = \"%d\"\n"
+				"expected = \"%d\"\n"
+				"failed to parse ttl\n",
+			i, testdataptr->in, via->ttl, testdataptr->expected_ttl);
+			res = AST_TEST_FAIL;
+		}
+
+		free_via(via);
 		i++;
 	}
 	return res;
@@ -2399,7 +2511,7 @@
 	AST_TEST_REGISTER(parse_contact_header_test);
 	AST_TEST_REGISTER(sip_parse_options_test);
 	AST_TEST_REGISTER(sip_uri_cmp_test);
-	AST_TEST_REGISTER(get_viabranch_test);
+	AST_TEST_REGISTER(parse_via_test);
 }
 void sip_request_parser_unregister_tests(void)
 {
@@ -2412,7 +2524,7 @@
 	AST_TEST_UNREGISTER(parse_contact_header_test);
 	AST_TEST_UNREGISTER(sip_parse_options_test);
 	AST_TEST_UNREGISTER(sip_uri_cmp_test);
-	AST_TEST_UNREGISTER(get_viabranch_test);
+	AST_TEST_UNREGISTER(parse_via_test);
 }
 
 int sip_reqresp_parser_init(void)

Modified: trunk/include/asterisk/netsock2.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/netsock2.h?view=diff&rev=304246&r1=304245&r2=304246
==============================================================================
--- trunk/include/asterisk/netsock2.h (original)
+++ trunk/include/asterisk/netsock2.h Wed Jan 26 14:44:47 2011
@@ -386,6 +386,20 @@
 int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr);
 
 /*!
+ * \since 1.10
+ *
+ * \brief
+ * Determine if an IPv4 address is a multicast address
+ *
+ * \parm addr the address to check
+ *
+ * This function checks if an address is in the 224.0.0.0/4 network block.
+ *
+ * \return non-zero if this is a multicast address
+ */
+int ast_sockaddr_is_ipv4_multicast(const struct ast_sockaddr *addr);
+
+/*!
  * \since 1.8
  *
  * \brief

Modified: trunk/main/netsock2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/netsock2.c?view=diff&rev=304246&r1=304245&r2=304246
==============================================================================
--- trunk/main/netsock2.c (original)
+++ trunk/main/netsock2.c Wed Jan 26 14:44:47 2011
@@ -381,6 +381,11 @@
 	return addr->len && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr);
 }
 
+int ast_sockaddr_is_ipv4_multicast(const struct ast_sockaddr *addr)
+{
+	return ((ast_sockaddr_ipv4(addr) & 0xf0000000) == 0xe0000000);
+}
+
 int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
 {
 	return addr->ss.ss_family == AF_INET6 &&




More information about the asterisk-commits mailing list