add netmask detection for nat discovery work

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13549 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2009-06-02 16:55:10 +00:00
parent 552e4d851d
commit b82984fe97
19 changed files with 143 additions and 48 deletions

View File

@ -1,26 +1,18 @@
<configuration name="acl.conf" description="Network Lists">
<network-lists>
<!--
These ACL's are automatically created on startup.
<list name="dl-candidates" default="allow">
<node type="deny" cidr="10.0.0.0/8"/>
<node type="deny" cidr="172.16.0.0/12"/>
<node type="deny" cidr="192.168.0.0/16"/>
</list>
<list name="rfc1918" default="deny">
<node type="allow" cidr="10.0.0.0/8"/>
<node type="allow" cidr="172.16.0.0/12"/>
<node type="allow" cidr="192.168.0.0/16"/>
</list>
rfc1918.auto - RFC1918 Space
nat.auto - RFC1918 Minus your local lan.
localnet.auto - ACL for your local lan.
-->
<list name="lan" default="allow">
<node type="deny" cidr="192.168.42.0/24"/>
<node type="allow" cidr="192.168.42.42/32"/>
</list>
<list name="strict" default="deny">
<node type="allow" cidr="208.102.123.124/32"/>
</list>
<!--
This will traverse the directory adding all users
with the cidr= tag to this ACL, when this ACL matches

View File

@ -26,6 +26,6 @@
<!-- <param name="vad" value="out"/> -->
<param name="vad" value="both"/>
<!--<param name="avatar" value="/path/to/tiny.jpg"/>-->
<!--<param name="candidate-acl" value="dl-candidates"/>-->
<!--<param name="candidate-acl" value="rfc1918.auto"/>-->
</x-profile>
</include>

View File

@ -16,6 +16,6 @@
<!--<param name="avatar" value="/path/to/tiny.jpg"/>-->
<!--If you have ODBC support and a working dsn you can use it instead of SQLite-->
<!--<param name="odbc-dsn" value="dsn:user:pass"/>-->
<!--<param name="candidate-acl" value="dl-candidates"/>-->
<!--<param name="candidate-acl" value="rfc1918.auto"/>-->
</x-profile>
</include>

View File

@ -232,7 +232,8 @@ typedef enum {
SCF_CRASH_PROT = (1 << 3),
SCF_VG = (1 << 4),
SCF_RESTART = (1 << 5),
SCF_SHUTDOWN_REQUESTED = (1 << 6)
SCF_SHUTDOWN_REQUESTED = (1 << 6),
SCF_USE_AUTO_NAT = (1 << 7)
} switch_core_flag_enum_t;
typedef uint32_t switch_core_flag_t;

View File

@ -172,7 +172,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame);
\return SWITCH_STATUS_SUCCESSS for success, otherwise failure
*/
SWITCH_DECLARE(switch_status_t) switch_find_local_ip(_Out_opt_bytecapcount_(len)
char *buf, _In_ int len, _In_ int family);
char *buf, _In_ int len, _In_ int *mask, _In_ int family);
/*!
\brief find the char representation of an ip adress
@ -550,7 +550,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *fr
SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close);
SWITCH_DECLARE(int) switch_parse_cidr(const char *string, uint32_t *ip, uint32_t *mask, uint32_t *bitp);
SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, switch_bool_t default_type, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok, const char *token);
#define switch_network_list_add_cidr(_list, _cidr_str, _ok) switch_network_list_add_cidr_token(_list, _cidr_str, _ok, NULL)

View File

@ -608,7 +608,7 @@ SWITCH_STANDARD_API(stun_function)
if (pip) {
switch_copy_string(ip_buf, pip, sizeof(ip_buf));
} else {
switch_find_local_ip(ip_buf, sizeof(ip_buf), AF_INET);
switch_find_local_ip(ip_buf, sizeof(ip_buf), NULL, AF_INET);
}
switch_core_new_memory_pool(&pool);

View File

@ -172,7 +172,7 @@ SWITCH_STANDARD_APP(bcast_function)
if ((var = switch_channel_get_variable(channel, "esf_broadcast_ip"))) {
esf_broadcast_ip = switch_core_session_strdup(session, var);
} else {
switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET);
switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET);
esf_broadcast_ip = guess_ip;
}

View File

@ -1484,7 +1484,7 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t
tech_pvt->codec_ms = atoi(argv[5]);
}
switch_find_local_ip(ip, sizeof(ip), AF_INET);
switch_find_local_ip(ip, sizeof(ip), NULL, AF_INET);
if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
NULL,

View File

@ -2215,7 +2215,7 @@ static switch_status_t load_config(void)
memset(&globals, 0, sizeof(globals));
globals.running = 1;
switch_find_local_ip(globals.guess_ip, sizeof(globals.guess_ip), AF_INET);
switch_find_local_ip(globals.guess_ip, sizeof(globals.guess_ip), NULL, AF_INET);
switch_core_hash_init(&globals.profile_hash, module_pool);

View File

@ -1755,7 +1755,7 @@ static switch_status_t place_call(char **argv, int argc, switch_stream_handle_t
tech_pvt->codec_ms = atoi(argv[5]);
}
switch_find_local_ip(ip, sizeof(ip), AF_INET);
switch_find_local_ip(ip, sizeof(ip), NULL, AF_INET);
if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
NULL, dialplan, cid_name, cid_num, ip, NULL, NULL, NULL, modname, NULL, dest)) != 0) {

View File

@ -3204,7 +3204,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)
mod_sofia_globals.pool = pool;
switch_mutex_init(&mod_sofia_globals.mutex, SWITCH_MUTEX_NESTED, mod_sofia_globals.pool);
switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), AF_INET);
switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), &mod_sofia_globals.guess_mask, AF_INET);
switch_set_string(mod_sofia_globals.guess_mask_str, inet_ntoa(*(struct in_addr *)&mod_sofia_globals.guess_mask));
gethostname(mod_sofia_globals.hostname, sizeof(mod_sofia_globals.hostname));

View File

@ -268,6 +268,8 @@ struct mod_sofia_globals {
switch_event_node_t *roster_node;
switch_event_node_t *custom_node;
switch_event_node_t *mwi_node;
int guess_mask;
char guess_mask_str[16];
int debug_presence;
int auto_restart;
};

View File

@ -627,7 +627,7 @@ void event_handler(switch_event_t *event)
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), AF_INET);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm) "

View File

@ -1045,7 +1045,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), AF_INET);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
"user_agent,server_user,server_host,profile_name,hostname,network_ip,network_port,sip_username,sip_realm) "

View File

@ -171,7 +171,7 @@ void WINAPI ServiceCtrlHandler(DWORD control)
/* the main service entry point */
void WINAPI service_main(DWORD numArgs, char **args)
{
switch_core_flag_t flags = SCF_USE_SQL;
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT;
const char *err = NULL; /* error value for return from freeswitch initialization */
/* we have to initialize the service-specific stuff */
memset(&status, 0, sizeof(SERVICE_STATUS));
@ -274,7 +274,7 @@ int main(int argc, char *argv[])
int alt_dirs = 0;
int known_opt;
int high_prio = 0;
switch_core_flag_t flags = SCF_USE_SQL;
switch_core_flag_t flags = SCF_USE_SQL | SCF_USE_AUTO_NAT;
int ret = 0;
switch_status_t destroy_status;
switch_file_t *fd;
@ -306,6 +306,7 @@ int main(int argc, char *argv[])
"\t-hp -- enable high priority settings\n"
"\t-vg -- run under valgrind\n"
"\t-nosql -- disable internal sql scoreboard\n"
"\t-nonat -- disable auto nat detection\n"
"\t-stop -- stop freeswitch\n"
"\t-nc -- do not output to a console and background\n"
"\t-c -- output to a console and stay in the foreground\n"
@ -463,6 +464,11 @@ int main(int argc, char *argv[])
known_opt++;
}
if (argv[x] && !strcmp(argv[x], "-nonat")) {
flags &= ~SCF_USE_AUTO_NAT;
known_opt++;
}
if (argv[x] && !strcmp(argv[x], "-vg")) {
flags |= SCF_VG;
known_opt++;

View File

@ -95,9 +95,10 @@ static void check_ip(void) {
char old_ip4[256] = "";
char old_ip6[256] = "";
int ok4 = 1, ok6 = 1;
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), AF_INET);
switch_find_local_ip(guess_ip6, sizeof(guess_ip6), AF_INET6);
int mask = 0;
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), &mask, AF_INET);
switch_find_local_ip(guess_ip6, sizeof(guess_ip6), NULL, AF_INET6);
if (!*main_ip4) {
switch_set_string(main_ip4, guess_ip4);
@ -106,6 +107,7 @@ static void check_ip(void) {
switch_set_string(old_ip4, main_ip4);
switch_set_string(main_ip4, guess_ip4);
switch_core_set_variable("local_ip_v4", guess_ip4);
switch_core_set_variable("local_mask_v4", inet_ntoa(*(struct in_addr *)&mask));
}
}
@ -861,9 +863,16 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_
SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
{
switch_xml_t xml = NULL, x_lists = NULL, x_list = NULL, x_node = NULL, cfg = NULL;
switch_network_list_t *list;
switch_network_list_t *rfc_list, *list;
char guess_ip[16] = "";
int mask = 0;
char guess_mask[16] = "";
char *tmp_name;
int ip_tmp = 0;
switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
switch_set_string(guess_mask, inet_ntoa(*(struct in_addr *)&mask));
switch_mutex_lock(runtime.global_mutex);
if (IP_LIST.hash) {
@ -878,6 +887,44 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
switch_core_new_memory_pool(&IP_LIST.pool);
switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool);
tmp_name = "rfc1918.auto";
switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
tmp_name = "nat.auto";
switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_TRUE);
switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_TRUE);
switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_TRUE);
switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list);
tmp_name = "localnet.auto";
switch_network_list_create(&list, tmp_name, SWITCH_FALSE, IP_LIST.pool);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name);
if (switch_network_list_add_host_mask(list, guess_ip, guess_mask, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Adding %s/%s (allow) to list %s\n", guess_ip, guess_mask, tmp_name);
}
switch_core_hash_insert(IP_LIST.hash, tmp_name, list);
switch_inet_pton(AF_INET, guess_ip, &ip_tmp);
ip_tmp = htonl(ip_tmp);
tmp_name = "nat.auto";
if (switch_network_list_validate_ip_token(rfc_list, ip_tmp, NULL)) {
switch_network_list_add_host_mask(rfc_list, guess_ip, guess_mask, SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
"Adding %s/%s (deny) to list %s\n", guess_ip, guess_mask, tmp_name);
}
if ((xml = switch_xml_open_cfg("acl.conf", &cfg, NULL))) {
if ((x_lists = switch_xml_child(cfg, "network-lists"))) {
for (x_list = switch_xml_child(x_lists, "list"); x_list; x_list = x_list->next) {
@ -893,7 +940,7 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload)
default_type = switch_true(dft);
}
if (switch_network_list_create(&list, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {
if (switch_network_list_create(&list, name, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {
abort();
}
@ -1075,6 +1122,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
switch_uuid_t uuid;
char guess_ip[256];
char *dir_path;
int mask = 0;
memset(&runtime, 0, sizeof(runtime));
@ -1128,16 +1176,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc
runtime.flags = flags;
runtime.sps_total = 30;
switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET);
switch_find_local_ip(guess_ip, sizeof(guess_ip), &mask, AF_INET);
switch_core_set_variable("local_ip_v4", guess_ip);
switch_find_local_ip(guess_ip, sizeof(guess_ip), AF_INET6);
switch_core_set_variable("local_mask_v4", inet_ntoa(*(struct in_addr *)&mask));
switch_find_local_ip(guess_ip, sizeof(guess_ip), NULL, AF_INET6);
switch_core_set_variable("local_ip_v6", guess_ip);
switch_core_set_variable("base_dir", SWITCH_GLOBAL_dirs.base_dir);
switch_core_set_serial();
switch_event_init(runtime.memory_pool);
switch_nat_init(runtime.memory_pool);
if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
switch_nat_init(runtime.memory_pool);
}
if (switch_xml_init(runtime.memory_pool, err) != SWITCH_STATUS_SUCCESS) {
apr_terminate();
@ -1559,7 +1612,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void)
switch_scheduler_task_thread_stop();
switch_rtp_shutdown();
switch_nat_shutdown();
if (switch_test_flag((&runtime), SCF_USE_AUTO_NAT)) {
switch_nat_shutdown();
}
switch_xml_destroy();
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Closing Event Engine.\n");

View File

@ -574,8 +574,8 @@ SWITCH_DECLARE(switch_status_t) switch_event_init(switch_memory_pool_t *pool)
switch_threadattr_create(&thd_attr, pool);
gethostname(hostname, sizeof(hostname));
switch_find_local_ip(guess_ip_v4, sizeof(guess_ip_v4), AF_INET);
switch_find_local_ip(guess_ip_v6, sizeof(guess_ip_v6), AF_INET6);
switch_find_local_ip(guess_ip_v4, sizeof(guess_ip_v4), NULL, AF_INET);
switch_find_local_ip(guess_ip_v6, sizeof(guess_ip_v6), NULL, AF_INET6);
switch_queue_create(&EVENT_QUEUE[0], POOL_COUNT_MAX + 10, THRUNTIME_POOL);

View File

@ -144,7 +144,7 @@ SWITCH_DECLARE(void) switch_nat_init(switch_memory_pool_t *pool)
memset(&nat_globals, 0, sizeof(nat_globals));
nat_globals.pool = pool;
switch_find_local_ip(nat_globals.pvt_addr, sizeof(nat_globals.pvt_addr), AF_INET);
switch_find_local_ip(nat_globals.pvt_addr, sizeof(nat_globals.pvt_addr), NULL, AF_INET);
init_pmp();

View File

@ -44,6 +44,7 @@ struct switch_network_node {
uint32_t bits;
switch_bool_t ok;
char *token;
char *str;
struct switch_network_node *next;
};
typedef struct switch_network_node switch_network_node_t;
@ -52,6 +53,7 @@ struct switch_network_list {
struct switch_network_node *node_head;
switch_bool_t default_type;
switch_memory_pool_t *pool;
char *name;
};
#ifndef WIN32
@ -119,7 +121,7 @@ SWITCH_DECLARE(switch_status_t) switch_frame_free(switch_frame_t **frame)
return SWITCH_STATUS_SUCCESS;
}
SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, switch_bool_t default_type, switch_memory_pool_t *pool)
SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t **list, const char *name, switch_bool_t default_type, switch_memory_pool_t *pool)
{
switch_network_list_t *new_list;
@ -130,6 +132,7 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_create(switch_network_list_t
new_list = switch_core_alloc(pool, sizeof(**list));
new_list->pool = pool;
new_list->default_type = default_type;
new_list->name = switch_core_strdup(new_list->pool, name);
*list = new_list;
@ -176,6 +179,7 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr_token(switch_networ
node->mask = mask;
node->ok = ok;
node->bits = bits;
node->str = switch_core_strdup(list->pool, cidr_str);
if (!switch_strlen_zero(token)) {
node->token = switch_core_strdup(list->pool, token);
@ -197,15 +201,16 @@ SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network
node = switch_core_alloc(list->pool, sizeof(*node));
node->ip = ip;
node->mask = mask;
node->ip = ntohl(ip);
node->mask = ntohl(mask);
node->ok = ok;
/* http://graphics.stanford.edu/~seander/bithacks.html */
mask = mask - ((mask >> 1) & 0x55555555);
mask = (mask & 0x33333333) + ((mask >> 2) & 0x33333333);
node->bits = (((mask + (mask >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
node->str = switch_core_sprintf(list->pool, "%s:%s", host, mask_str);
node->next = list->node_head;
list->node_head = node;
@ -735,7 +740,33 @@ SWITCH_DECLARE(const char *) switch_stristr(const char *instr, const char *str)
return NULL;
}
SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int family)
#ifndef WIN32
#include <ifaddrs.h>
static int get_netmask(struct sockaddr_in *me, int *mask)
{
struct ifaddrs *ifaddrs, *i = NULL;
if (getifaddrs(&ifaddrs) < 0) {
return -1;
}
for(i = ifaddrs; i; i = i->ifa_next) {
struct sockaddr_in *s = (struct sockaddr_in *)i->ifa_addr;
struct sockaddr_in *m = (struct sockaddr_in *)i->ifa_netmask;
if (s->sin_addr.s_addr == me->sin_addr.s_addr) {
*mask = m->sin_addr.s_addr;
return 0;
}
}
return -2;
}
#endif
SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int *mask, int family)
{
switch_status_t status = SWITCH_STATUS_FALSE;
char *base;
@ -758,7 +789,6 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int fam
if (len < 16) {
return status;
}
switch (family) {
case AF_INET:
@ -790,6 +820,10 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int fam
return status;
}
if (mask) {
*mask = 0; // find the right one
}
closesocket(tmp_socket);
freeaddrinfo(address_info);
@ -832,6 +866,10 @@ SWITCH_DECLARE(switch_status_t) switch_find_local_ip(char *buf, int len, int fam
}
switch_copy_string(buf, get_addr(abuf, sizeof(abuf), (struct sockaddr*)&iface_out, sizeof(iface_out)), len);
if (mask) {
get_netmask((struct sockaddr_in*)&iface_out, mask);
}
status = SWITCH_STATUS_SUCCESS;
}
break;