| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  |  * Copyright (C) 1999 - 2006, Digium, Inc. | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-07-19 23:17:02 +00:00
										 |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Various sorts of access control | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2006-03-28 13:58:34 +00:00
										 |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-17 14:45:46 +00:00
										 |  |  | #include "asterisk/network.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <net/route.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-08 02:24:02 +00:00
										 |  |  | #if defined(SOLARIS)
 | 
					
						
							| 
									
										
										
										
											2004-12-14 23:36:30 +00:00
										 |  |  | #include <sys/sockio.h>
 | 
					
						
							| 
									
										
										
										
											2008-01-24 16:47:10 +00:00
										 |  |  | #include <net/if.h>
 | 
					
						
							| 
									
										
										
										
											2008-02-01 16:01:22 +00:00
										 |  |  | #elif defined(HAVE_GETIFADDRS)
 | 
					
						
							| 
									
										
										
										
											2008-01-24 16:47:10 +00:00
										 |  |  | #include <ifaddrs.h>
 | 
					
						
							| 
									
										
										
										
											2005-09-08 02:24:02 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-22 13:11:34 +00:00
										 |  |  | #include "asterisk/acl.h"
 | 
					
						
							|  |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							|  |  |  | #include "asterisk/lock.h"
 | 
					
						
							|  |  |  | #include "asterisk/srv.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-01 16:01:22 +00:00
										 |  |  | #if (!defined(SOLARIS) && !defined(HAVE_GETIFADDRS))
 | 
					
						
							|  |  |  | static int get_local_address(struct in_addr *ourip) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | static void score_address(const struct sockaddr_in *sin, struct in_addr *best_addr, int *best_score) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const char *address; | 
					
						
							|  |  |  | 	int score; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	address = ast_inet_ntoa(sin->sin_addr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* RFC 1700 alias for the local network */ | 
					
						
							|  |  |  | 	if (address[0] == '0') | 
					
						
							|  |  |  | 		score = -25; | 
					
						
							|  |  |  | 	/* RFC 1700 localnet */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "127", 3) == 0) | 
					
						
							|  |  |  | 		score = -20; | 
					
						
							|  |  |  | 	/* RFC 1918 non-public address space */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "10.", 3) == 0) | 
					
						
							|  |  |  | 		score = -5; | 
					
						
							|  |  |  | 	/* RFC 1918 non-public address space */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "172", 3) == 0) { | 
					
						
							|  |  |  | 		/* 172.16.0.0 - 172.19.255.255, but not 172.160.0.0 - 172.169.255.255 */ | 
					
						
							|  |  |  | 		if (address[4] == '1' && address[5] >= '6' && address[6] == '.') | 
					
						
							|  |  |  | 			score = -5; | 
					
						
							|  |  |  | 		/* 172.20.0.0 - 172.29.255.255, but not 172.200.0.0 - 172.255.255.255 nor 172.2.0.0 - 172.2.255.255 */ | 
					
						
							|  |  |  | 		else if (address[4] == '2' && address[6] == '.') | 
					
						
							|  |  |  | 			score = -5; | 
					
						
							|  |  |  | 		/* 172.30.0.0 - 172.31.255.255 */ | 
					
						
							|  |  |  | 		else if (address[4] == '3' && address[5] <= '1') | 
					
						
							|  |  |  | 			score = -5; | 
					
						
							|  |  |  | 		/* All other 172 addresses are public */ | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			score = 0; | 
					
						
							|  |  |  | 	/* RFC 2544 Benchmark test range */ | 
					
						
							|  |  |  | 	} else if (strncmp(address, "198.1", 5) == 0 && address[5] >= '8' && address[6] == '.') | 
					
						
							|  |  |  | 		score = -10; | 
					
						
							|  |  |  | 	/* RFC 1918 non-public address space */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "192.168", 7) == 0) | 
					
						
							|  |  |  | 		score = -5; | 
					
						
							|  |  |  | 	/* RFC 3330 Zeroconf network */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "169.254", 7) == 0) | 
					
						
							|  |  |  | 		/*!\note Better score than a test network, but not quite as good as RFC 1918
 | 
					
						
							|  |  |  | 		 * address space.  The reason is that some Linux distributions automatically | 
					
						
							|  |  |  | 		 * configure a Zeroconf address before trying DHCP, so we want to prefer a | 
					
						
							|  |  |  | 		 * DHCP lease to a Zeroconf address. | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		score = -10; | 
					
						
							|  |  |  | 	/* RFC 3330 Test network */ | 
					
						
							|  |  |  | 	else if (strncmp(address, "192.0.2.", 8) == 0) | 
					
						
							|  |  |  | 		score = -15; | 
					
						
							|  |  |  | 	/* Every other address should be publically routable */ | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		score = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (score > *best_score) { | 
					
						
							|  |  |  | 		*best_score = score; | 
					
						
							|  |  |  | 		memcpy(best_addr, &sin->sin_addr, sizeof(*best_addr)); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int get_local_address(struct in_addr *ourip) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int s, res = -1; | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #ifdef SOLARIS
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	struct lifreq *ifr = NULL; | 
					
						
							|  |  |  | 	struct lifnum ifn; | 
					
						
							|  |  |  | 	struct lifconf ifc; | 
					
						
							|  |  |  | 	struct sockaddr_in *sa; | 
					
						
							|  |  |  | 	char *buf = NULL; | 
					
						
							|  |  |  | 	int bufsz, x; | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #endif /* SOLARIS */
 | 
					
						
							|  |  |  | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	struct ifaddrs *ifap, *ifaphead; | 
					
						
							|  |  |  | 	int rtnerr; | 
					
						
							|  |  |  | 	const struct sockaddr_in *sin; | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #endif /* BSD_OR_LINUX */
 | 
					
						
							| 
									
										
										
										
											2008-01-24 16:47:10 +00:00
										 |  |  | 	struct in_addr best_addr; | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	int best_score = -100; | 
					
						
							| 
									
										
										
										
											2008-01-24 16:47:10 +00:00
										 |  |  | 	memset(&best_addr, 0, sizeof(best_addr)); | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	rtnerr = getifaddrs(&ifaphead); | 
					
						
							|  |  |  | 	if (rtnerr) { | 
					
						
							|  |  |  | 		perror(NULL); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif /* BSD_OR_LINUX */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	s = socket(AF_INET, SOCK_STREAM, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (s > 0) { | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 		for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-27 19:26:45 +00:00
										 |  |  | 			if (ifap->ifa_addr && ifap->ifa_addr->sa_family == AF_INET) { | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 				sin = (const struct sockaddr_in *) ifap->ifa_addr; | 
					
						
							|  |  |  | 				score_address(sin, &best_addr, &best_score); | 
					
						
							|  |  |  | 				res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (best_score == 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #endif /* BSD_OR_LINUX */
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* There is no reason whatsoever that this shouldn't work on Linux or BSD also. */ | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #ifdef SOLARIS
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 		/* Get a count of interfaces on the machine */ | 
					
						
							|  |  |  | 		ifn.lifn_family = AF_INET; | 
					
						
							|  |  |  | 		ifn.lifn_flags = 0; | 
					
						
							|  |  |  | 		ifn.lifn_count = 0; | 
					
						
							|  |  |  | 		if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) { | 
					
						
							|  |  |  | 			close(s); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bufsz = ifn.lifn_count * sizeof(struct lifreq); | 
					
						
							|  |  |  | 		if (!(buf = malloc(bufsz))) { | 
					
						
							|  |  |  | 			close(s); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		memset(buf, 0, bufsz); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Get a list of interfaces on the machine */ | 
					
						
							|  |  |  | 		ifc.lifc_len = bufsz; | 
					
						
							|  |  |  | 		ifc.lifc_buf = buf; | 
					
						
							|  |  |  | 		ifc.lifc_family = AF_INET; | 
					
						
							|  |  |  | 		ifc.lifc_flags = 0; | 
					
						
							|  |  |  | 		if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) { | 
					
						
							|  |  |  | 			close(s); | 
					
						
							|  |  |  | 			free(buf); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-02 18:31:11 +00:00
										 |  |  | 		for (ifr = ifc.lifc_req, x = 0; x < ifn.lifn_count; ifr++, x++) { | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 			sa = (struct sockaddr_in *)&(ifr->lifr_addr); | 
					
						
							| 
									
										
										
										
											2008-01-24 16:47:10 +00:00
										 |  |  | 			score_address(sa, &best_addr, &best_score); | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 			res = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (best_score == 0) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		free(buf); | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #endif /* SOLARIS */
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		close(s); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__linux__) || defined(__Darwin__)
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	freeifaddrs(ifaphead); | 
					
						
							| 
									
										
										
										
											2008-01-22 20:42:47 +00:00
										 |  |  | #endif /* BSD_OR_LINUX */
 | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (res == 0 && ourip) | 
					
						
							|  |  |  | 		memcpy(ourip, &best_addr, sizeof(*ourip)); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-02-01 16:01:22 +00:00
										 |  |  | #endif /* HAVE_GETIFADDRS */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | /* Free HA structure */ | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | void ast_free_ha(struct ast_ha *ha) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_ha *hal; | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	while (ha) { | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 		hal = ha; | 
					
						
							|  |  |  | 		ha = ha->next; | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(hal); | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | /* Copy HA structure */ | 
					
						
							|  |  |  | static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to) | 
					
						
							| 
									
										
										
										
											2004-06-22 20:11:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr)); | 
					
						
							|  |  |  | 	memcpy(&to->netmask, &from->netmask, sizeof(from->netmask)); | 
					
						
							|  |  |  | 	to->sense = from->sense; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Create duplicate of ha structure */ | 
					
						
							|  |  |  | static struct ast_ha *ast_duplicate_ha(struct ast_ha *original) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-14 22:28:01 +00:00
										 |  |  | 	struct ast_ha *new_ha; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((new_ha = ast_malloc(sizeof(*new_ha)))) { | 
					
						
							|  |  |  | 		/* Copy from original to new object */ | 
					
						
							|  |  |  | 		ast_copy_ha(original, new_ha); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	return new_ha; | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Create duplicate HA link list */ | 
					
						
							|  |  |  | /*  Used in chan_sip2 templates */ | 
					
						
							|  |  |  | struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	struct ast_ha *start = original; | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 	struct ast_ha *ret = NULL; | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 	struct ast_ha *link, *prev = NULL; | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	while (start) { | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 		link = ast_duplicate_ha(start);  /* Create copy of this object */ | 
					
						
							| 
									
										
										
										
											2004-05-27 21:31:25 +00:00
										 |  |  | 		if (prev) | 
					
						
							|  |  |  | 			prev->next = link;		/* Link previous to this object */ | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-28 13:58:34 +00:00
										 |  |  | 		if (!ret) | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 			ret = link;		/* Save starting point */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-22 20:11:15 +00:00
										 |  |  | 		start = start->next;		/* Go to next object */ | 
					
						
							|  |  |  | 		prev = link;			/* Save pointer to this object */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	return ret;    			/* Return start of list */ | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-14 13:18:40 +00:00
										 |  |  | struct ast_ha *ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error) | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-14 22:28:01 +00:00
										 |  |  | 	struct ast_ha *ha; | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 	char *nm; | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 	struct ast_ha *prev = NULL; | 
					
						
							|  |  |  | 	struct ast_ha *ret; | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 	int x; | 
					
						
							| 
									
										
										
										
											2007-10-22 13:36:13 +00:00
										 |  |  | 	char *tmp = ast_strdupa(stuff); | 
					
						
							| 
									
										
										
										
											2006-02-14 22:28:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 	ret = path; | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	while (path) { | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 		prev = path; | 
					
						
							|  |  |  | 		path = path->next; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ha = ast_malloc(sizeof(*ha)); | 
					
						
							|  |  |  | 	if (!ha) | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nm = strchr(tmp, '/'); | 
					
						
							|  |  |  | 	if (!nm) { | 
					
						
							|  |  |  | 		/* assume /32. Yes, htonl does not do anything for this particular mask
 | 
					
						
							|  |  |  | 		   but we better use it to show we remember about byte order */ | 
					
						
							|  |  |  | 		ha->netmask.s_addr = htonl(0xFFFFFFFF); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		*nm = '\0'; | 
					
						
							|  |  |  | 		nm++; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-01-10 21:43:17 +00:00
										 |  |  | 		if (!strchr(nm, '.')) { | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 			if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) | 
					
						
							|  |  |  | 				ha->netmask.s_addr = htonl(0xFFFFFFFF << (32 - x)); | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				ast_log(LOG_WARNING, "Invalid CIDR in %s\n", stuff); | 
					
						
							|  |  |  | 				ast_free(ha); | 
					
						
							|  |  |  | 				if (error) | 
					
						
							|  |  |  | 					*error = 1; | 
					
						
							|  |  |  | 				return ret; | 
					
						
							| 
									
										
										
										
											2004-01-10 21:43:17 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else if (!inet_aton(nm, &ha->netmask)) { | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "Invalid mask in %s\n", stuff); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 			ast_free(ha); | 
					
						
							| 
									
										
										
										
											2007-01-01 19:20:46 +00:00
										 |  |  | 			if (error) | 
					
						
							|  |  |  | 				*error = 1; | 
					
						
							| 
									
										
										
										
											2006-10-13 23:03:36 +00:00
										 |  |  | 			return ret; | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-10-18 07:23:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!inet_aton(tmp, &ha->netaddr)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Invalid IP address in %s\n", stuff); | 
					
						
							|  |  |  | 		ast_free(ha); | 
					
						
							|  |  |  | 		if (error) | 
					
						
							|  |  |  | 			*error = 1; | 
					
						
							|  |  |  | 		return ret; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ha->netaddr.s_addr &= ha->netmask.s_addr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ha->sense = strncasecmp(sense, "p", 1) ? AST_SENSE_DENY : AST_SENSE_ALLOW; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ha->next = NULL; | 
					
						
							|  |  |  | 	if (prev) { | 
					
						
							|  |  |  | 		prev->next = ha; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ret = ha; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_debug(1, "%s/%s sense %d appended to acl for peer\n", ast_strdupa(ast_inet_ntoa(ha->netaddr)), ast_strdupa(ast_inet_ntoa(ha->netmask)), ha->sense); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-05 06:14:25 +00:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* Start optimistic */ | 
					
						
							|  |  |  | 	int res = AST_SENSE_ALLOW; | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	while (ha) { | 
					
						
							| 
									
										
										
										
											2007-07-19 12:38:13 +00:00
										 |  |  | #if 0	/* debugging code */
 | 
					
						
							| 
									
										
										
										
											2004-06-30 16:56:51 +00:00
										 |  |  | 		char iabuf[INET_ADDRSTRLEN]; | 
					
						
							|  |  |  | 		char iabuf2[INET_ADDRSTRLEN]; | 
					
						
							| 
									
										
										
										
											2004-05-27 20:53:02 +00:00
										 |  |  | 		/* DEBUG */ | 
					
						
							| 
									
										
										
										
											2006-07-21 17:31:28 +00:00
										 |  |  | 		ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf)); | 
					
						
							|  |  |  | 		ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2)); | 
					
						
							| 
									
										
										
										
											2007-06-14 19:39:12 +00:00
										 |  |  | 		ast_debug(1, "##### Testing %s with %s\n", iabuf, iabuf2); | 
					
						
							| 
									
										
										
										
											2007-07-19 12:38:13 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 		/* For each rule, if this address and the netmask = the net address
 | 
					
						
							|  |  |  | 		   apply the current rule */ | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 		if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr) | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 			res = ha->sense; | 
					
						
							|  |  |  | 		ha = ha->next; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-03 23:34:45 +00:00
										 |  |  | int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service) | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct hostent *hp; | 
					
						
							| 
									
										
										
										
											2004-04-22 00:20:34 +00:00
										 |  |  | 	struct ast_hostent ahp; | 
					
						
							| 
									
										
										
										
											2004-12-03 23:34:45 +00:00
										 |  |  | 	char srv[256]; | 
					
						
							|  |  |  | 	char host[256]; | 
					
						
							|  |  |  | 	int tportno = ntohs(sin->sin_port); | 
					
						
							|  |  |  | 	if (service) { | 
					
						
							|  |  |  | 		snprintf(srv, sizeof(srv), "%s.%s", service, value); | 
					
						
							|  |  |  | 		if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) { | 
					
						
							|  |  |  | 			sin->sin_port = htons(tportno); | 
					
						
							|  |  |  | 			value = host; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-04-22 00:20:34 +00:00
										 |  |  | 	hp = ast_gethostbyname(value, &ahp); | 
					
						
							| 
									
										
										
										
											2002-05-30 01:40:29 +00:00
										 |  |  | 	if (hp) { | 
					
						
							|  |  |  | 		memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr)); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | struct dscp_codepoint { | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | 	unsigned int space; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* IANA registered DSCP codepoints */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct dscp_codepoint dscp_pool1[] = { | 
					
						
							|  |  |  | 	{ "CS0", 0x00 }, | 
					
						
							|  |  |  | 	{ "CS1", 0x08 }, | 
					
						
							|  |  |  | 	{ "CS2", 0x10 }, | 
					
						
							|  |  |  | 	{ "CS3", 0x18 }, | 
					
						
							|  |  |  | 	{ "CS4", 0x20 }, | 
					
						
							|  |  |  | 	{ "CS5", 0x28 }, | 
					
						
							|  |  |  | 	{ "CS6", 0x30 }, | 
					
						
							|  |  |  | 	{ "CS7", 0x38 }, | 
					
						
							|  |  |  | 	{ "AF11", 0x0A }, | 
					
						
							|  |  |  | 	{ "AF12", 0x0C }, | 
					
						
							|  |  |  | 	{ "AF13", 0x0E }, | 
					
						
							|  |  |  | 	{ "AF21", 0x12 }, | 
					
						
							|  |  |  | 	{ "AF22", 0x14 }, | 
					
						
							|  |  |  | 	{ "AF23", 0x16 }, | 
					
						
							|  |  |  | 	{ "AF31", 0x1A }, | 
					
						
							|  |  |  | 	{ "AF32", 0x1C }, | 
					
						
							|  |  |  | 	{ "AF33", 0x1E }, | 
					
						
							|  |  |  | 	{ "AF41", 0x22 }, | 
					
						
							|  |  |  | 	{ "AF42", 0x24 }, | 
					
						
							|  |  |  | 	{ "AF43", 0x26 }, | 
					
						
							|  |  |  | 	{ "EF", 0x2E }, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2007-04-30 16:16:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int ast_str2cos(const char *value, unsigned int *cos)  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int fval; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (sscanf(value, "%d", &fval) == 1) { | 
					
						
							|  |  |  | 		if (fval < 8) { | 
					
						
							|  |  |  |     		    *cos = fval; | 
					
						
							|  |  |  | 		    return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | int ast_str2tos(const char *value, unsigned int *tos) | 
					
						
							| 
									
										
										
										
											2005-08-09 16:41:28 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int fval; | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | 	unsigned int x; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (sscanf(value, "%i", &fval) == 1) { | 
					
						
							|  |  |  | 		*tos = fval & 0xFF; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:40:28 +00:00
										 |  |  | 	for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) { | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | 		if (!strcasecmp(value, dscp_pool1[x].name)) { | 
					
						
							|  |  |  | 			*tos = dscp_pool1[x].space << 2; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-21 22:23:49 +00:00
										 |  |  | 	return -1; | 
					
						
							| 
									
										
										
										
											2005-08-09 16:41:28 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | const char *ast_tos2str(unsigned int tos) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	unsigned int x; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-08 16:40:28 +00:00
										 |  |  | 	for (x = 0; x < ARRAY_LEN(dscp_pool1); x++) { | 
					
						
							| 
									
										
										
										
											2006-09-21 22:23:49 +00:00
										 |  |  | 		if (dscp_pool1[x].space == (tos >> 2)) | 
					
						
							|  |  |  | 			return dscp_pool1[x].name; | 
					
						
							| 
									
										
										
										
											2006-03-28 03:28:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return "unknown"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-03 23:34:45 +00:00
										 |  |  | int ast_get_ip(struct sockaddr_in *sin, const char *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return ast_get_ip_or_srv(sin, value, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-05-04 05:52:52 +00:00
										 |  |  | int ast_ouraddrfor(struct in_addr *them, struct in_addr *us) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2004-12-18 21:54:58 +00:00
										 |  |  | 	int s; | 
					
						
							|  |  |  | 	struct sockaddr_in sin; | 
					
						
							|  |  |  | 	socklen_t slen; | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-18 21:54:58 +00:00
										 |  |  | 	s = socket(PF_INET, SOCK_DGRAM, 0); | 
					
						
							| 
									
										
										
										
											2005-07-08 14:27:39 +00:00
										 |  |  | 	if (s < 0) { | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Cannot create socket\n"); | 
					
						
							| 
									
										
										
										
											2003-10-22 03:10:34 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-01-11 17:08:52 +00:00
										 |  |  | 	sin.sin_family = AF_INET; | 
					
						
							|  |  |  | 	sin.sin_port = 5060; | 
					
						
							| 
									
										
										
										
											2004-12-18 21:54:58 +00:00
										 |  |  | 	sin.sin_addr = *them; | 
					
						
							|  |  |  | 	if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Cannot connect\n"); | 
					
						
							| 
									
										
										
										
											2004-12-28 07:44:13 +00:00
										 |  |  | 		close(s); | 
					
						
							| 
									
										
										
										
											2003-10-22 03:10:34 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-12-18 21:54:58 +00:00
										 |  |  | 	slen = sizeof(sin); | 
					
						
							|  |  |  | 	if (getsockname(s, (struct sockaddr *)&sin, &slen)) { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Cannot get socket name\n"); | 
					
						
							| 
									
										
										
										
											2004-12-28 07:44:13 +00:00
										 |  |  | 		close(s); | 
					
						
							| 
									
										
										
										
											2003-10-22 03:10:34 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2003-10-22 04:09:28 +00:00
										 |  |  | 	close(s); | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 	ast_debug(3, "Found IP address for this socket\n"); | 
					
						
							| 
									
										
										
										
											2004-12-18 21:54:58 +00:00
										 |  |  | 	*us = sin.sin_addr; | 
					
						
							| 
									
										
										
										
											2003-05-04 05:52:52 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2005-01-11 17:08:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	char ourhost[MAXHOSTNAMELEN] = ""; | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | 	struct ast_hostent ahp; | 
					
						
							|  |  |  | 	struct hostent *hp; | 
					
						
							|  |  |  | 	struct in_addr saddr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* just use the bind address if it is nonzero */ | 
					
						
							|  |  |  | 	if (ntohl(bindaddr.sin_addr.s_addr)) { | 
					
						
							|  |  |  | 		memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip)); | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 		ast_debug(3, "Attached to given IP address\n"); | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	/* try to use our hostname */ | 
					
						
							| 
									
										
										
										
											2005-07-19 23:35:45 +00:00
										 |  |  | 	if (gethostname(ourhost, sizeof(ourhost) - 1)) { | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | 		ast_log(LOG_WARNING, "Unable to get hostname\n"); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		hp = ast_gethostbyname(ourhost, &ahp); | 
					
						
							|  |  |  | 		if (hp) { | 
					
						
							|  |  |  | 			memcpy(ourip, hp->h_addr, sizeof(*ourip)); | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 			ast_debug(3, "Found one IP address based on local hostname %s.\n", ourhost); | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-11-19 08:41:14 +00:00
										 |  |  | 	ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n"); | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | 	/* A.ROOT-SERVERS.NET. */ | 
					
						
							|  |  |  | 	if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2008-01-22 17:15:08 +00:00
										 |  |  | 	return get_local_address(ourip); | 
					
						
							| 
									
										
										
										
											2005-02-09 03:22:42 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-07-10 19:05:48 +00:00
										 |  |  | 
 |