mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	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/ ........ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@324487 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -3398,7 +3398,7 @@ static void build_via(struct sip_pvt *p) | ||||
| 	/* 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 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer) | ||||
| 	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 @@ static char *generate_uri(struct sip_pvt *pvt, char *buf, size_t size) | ||||
| 	 * 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 @@ static void build_callid_pvt(struct sip_pvt *pvt) | ||||
| { | ||||
| 	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 @@ static void build_callid_registry(struct sip_registry *reg, const struct ast_soc | ||||
| { | ||||
| 	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 @@ static int copy_via_headers(struct sip_pvt *p, struct sip_request *req, const st | ||||
| 
 | ||||
| 				/* 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 @@ static int add_rpid(struct sip_request *req, struct sip_pvt *p) | ||||
| 		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 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int | ||||
| 		 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 @@ static enum sip_result add_sdp(struct sip_request *resp, struct sip_pvt *p, int | ||||
| 		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 @@ static void build_contact(struct sip_pvt *p) | ||||
| 
 | ||||
| 	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 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho | ||||
| 
 | ||||
| 	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 @@ static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt) | ||||
| 	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 @@ static int transmit_notify_with_mwi(struct sip_pvt *p, int newmsgs, int oldmsgs, | ||||
| 	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); | ||||
| @@ -12923,6 +12923,19 @@ static int sip_reg_timeout(const void *data) | ||||
| 	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
 | ||||
|  * auth = NULL on the initial registration (from sip_reregister()) | ||||
|  */ | ||||
| @@ -13076,19 +13089,19 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char * | ||||
| 		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 @@ static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int d | ||||
| 	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 @@ static int sip_poke_peer(struct sip_peer *peer, int force) | ||||
| 	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); | ||||
|   | ||||
| @@ -152,8 +152,13 @@ int ast_sockaddr_cmp_addr(const struct ast_sockaddr *a, const struct ast_sockadd | ||||
| #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 | ||||
| @@ -199,6 +204,23 @@ static inline char *ast_sockaddr_stringify(const struct ast_sockaddr *addr) | ||||
| 	return ast_sockaddr_stringify_fmt(addr, AST_SOCKADDR_STR_DEFAULT); | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \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 | ||||
|  * | ||||
| @@ -212,6 +234,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); | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \since 1.8 | ||||
|  * | ||||
| @@ -226,6 +265,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); | ||||
| } | ||||
|  | ||||
| /*! | ||||
|  * \since 1.8 | ||||
|  * | ||||
| @@ -409,6 +466,20 @@ int ast_sockaddr_is_ipv4_mapped(const struct ast_sockaddr *addr); | ||||
|  */ | ||||
| int ast_sockaddr_is_ipv4_multicast(const struct ast_sockaddr *addr); | ||||
|  | ||||
| /*! | ||||
|  * \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 | ||||
|  * | ||||
|   | ||||
| @@ -95,7 +95,14 @@ char *ast_sockaddr_stringify_fmt(const struct ast_sockaddr *sa, int format) | ||||
| 		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); | ||||
| @@ -397,6 +404,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) | ||||
| { | ||||
| 	return addr->ss.ss_family == AF_INET6 && | ||||
|   | ||||
							
								
								
									
										127
									
								
								tests/test_netsock2.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								tests/test_netsock2.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| /* | ||||
|  * Asterisk -- An open source telephony toolkit. | ||||
|  * | ||||
|  * Copyright (C) 2011, Digium, Inc. | ||||
|  * | ||||
|  * Terry Wilson <twilson@digium.com> | ||||
|  * | ||||
|  * See http://www.asterisk.org for more information about | ||||
|  * the Asterisk project. Please do not directly contact | ||||
|  * any of the maintainers of this project for assistance; | ||||
|  * the project provides a web site, mailing lists and IRC | ||||
|  * channels for your use. | ||||
|  * | ||||
|  * This program is free software, distributed under the terms of | ||||
|  * the GNU General Public License Version 2. See the LICENSE file | ||||
|  * at the top of the source tree. | ||||
|  */ | ||||
|  | ||||
| /*! | ||||
|  * \file | ||||
|  * \brief Netsock2 Unit Tests | ||||
|  * | ||||
|  * \author Terry Wilson <twilson@digium.com> | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| /*** MODULEINFO | ||||
| 	<depend>TEST_FRAMEWORK</depend> | ||||
|  ***/ | ||||
|  | ||||
| #include "asterisk.h" | ||||
|  | ||||
| ASTERISK_FILE_VERSION(__FILE__, "") | ||||
|  | ||||
| #include "asterisk/test.h" | ||||
| #include "asterisk/module.h" | ||||
| #include "asterisk/netsock2.h" | ||||
| #include "asterisk/logger.h" | ||||
| struct parse_test { | ||||
| 	const char *address; | ||||
| 	int expected_result; | ||||
| }; | ||||
|  | ||||
| AST_TEST_DEFINE(parsing) | ||||
| { | ||||
| 	int res = AST_TEST_PASS; | ||||
| 	struct parse_test test_vals[] = { | ||||
| 		{ "192.168.1.0", 1 }, | ||||
| 		{ "10.255.255.254", 1 }, | ||||
| 		{ "172.18.5.4", 1 }, | ||||
| 		{ "8.8.4.4", 1 }, | ||||
| 		{ "0.0.0.0", 1 }, | ||||
| 		{ "127.0.0.1", 1 }, | ||||
| 		{ "1.256.3.4", 0 }, | ||||
| 		{ "256.0.0.1", 0 }, | ||||
| 		{ "1.2.3.4:5060", 1 }, | ||||
| 		{ "1.2.3.4:99999", 0}, | ||||
| 		{ "::ffff:5.6.7.8", 1 }, | ||||
| 		{ "fdf8:f53b:82e4::53", 1 }, | ||||
| 		{ "fe80::200:5aee:feaa:20a2", 1 }, | ||||
| 		{ "2001::1", 1 }, | ||||
| 		{ "2001:0000:4136:e378:8000:63bf:3fff:fdd2", 1 }, | ||||
| 		{ "2001:0002:6c::430", 1 }, | ||||
| 		{ "2001:10:240:ab::a", 1 }, | ||||
| 		{ "2002:cb0a:3cdd:1::1", 1 }, | ||||
| 		{ "2001:db8:8:4::2", 1 }, /* Documentation only, should never be used */ | ||||
| 		{ "ff01:0:0:0:0:0:0:2", 1 }, /* Multicast */ | ||||
| 		{ "[fdf8:f53b:82e4::53]", 1 }, | ||||
| 		{ "[fe80::200:5aee:feaa:20a2]", 1 }, | ||||
| 		{ "[2001::1]", 1 }, | ||||
| 		{ "[2001:0000:4136:e378:8000:63bf:3fff:fdd2]:5060", 1 }, | ||||
| 		{ "2001:0000:4136:e378:8000:63bf:3fff:fdd2:5060", 0 }, /* port, but no brackets */ | ||||
| 		{ "[2001:0000:4136:e378:8000:63bf:3fff:fdd2]:90000", 0 }, | ||||
| 		{ "[fe80::200:5aee:feaa:20a2%eth0]", 1 }, /* link-local with scope id */ | ||||
| 		{ "[fe80::200::abcd", 0 }, /* multiple zero expansions */ | ||||
| 	}; | ||||
|  | ||||
| 	size_t x; | ||||
| 	struct ast_sockaddr addr = { { 0, 0, } }; | ||||
| 	int parse_result; | ||||
|  | ||||
| 	switch (cmd) { | ||||
| 	case TEST_INIT: | ||||
| 		info->name = "parsing"; | ||||
| 		info->category = "/main/netsock2/"; | ||||
| 		info->summary = "netsock2 parsing unit test"; | ||||
| 		info->description = | ||||
| 			"Test parsing of IPv4 and IPv6 network addresses"; | ||||
| 		return AST_TEST_NOT_RUN; | ||||
| 	case TEST_EXECUTE: | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	for (x = 0; x < ARRAY_LEN(test_vals); x++) { | ||||
| 		if ((parse_result = ast_sockaddr_parse(&addr, test_vals[x].address, 0)) != test_vals[x].expected_result) { | ||||
| 			ast_test_status_update(test, "On '%s' expected %d but got %d\n", test_vals[x].address, test_vals[x].expected_result, parse_result); | ||||
| 			res = AST_TEST_FAIL; | ||||
| 		} | ||||
| 		if (parse_result) { | ||||
| 			struct ast_sockaddr tmp_addr = { { 0, 0, } }; | ||||
| 			const char *tmp; | ||||
|  | ||||
| 			tmp = ast_sockaddr_stringify(&addr); | ||||
| 			ast_sockaddr_parse(&tmp_addr, tmp, 0); | ||||
| 			if (ast_sockaddr_cmp_addr(&addr, &tmp_addr)) { | ||||
| 				ast_test_status_update(test, "Re-parsed stringification did not match: '%s' vs '%s'\n", ast_sockaddr_stringify(&addr), ast_sockaddr_stringify(&tmp_addr)); | ||||
| 				res = AST_TEST_FAIL; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return res; | ||||
| } | ||||
|  | ||||
| static int unload_module(void) | ||||
| { | ||||
| 	AST_TEST_UNREGISTER(parsing); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int load_module(void) | ||||
| { | ||||
| 	AST_TEST_REGISTER(parsing); | ||||
| 	return AST_MODULE_LOAD_SUCCESS; | ||||
| } | ||||
|  | ||||
| AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Netsock2 test module"); | ||||
		Reference in New Issue
	
	Block a user