[Freeswitch-svn] [commit] r7966 - in freeswitch/trunk: conf/autoload_configs conf/sip_profiles src src/include src/mod/applications/mod_commands src/mod/applications/mod_dptools src/mod/endpoints/mod_sofia src/mod/event_handlers/mod_event_socket
Freeswitch SVN
anthm at freeswitch.org
Wed Mar 26 18:14:10 EDT 2008
Author: anthm
Date: Wed Mar 26 18:14:09 2008
New Revision: 7966
Modified:
freeswitch/trunk/conf/autoload_configs/event_socket.conf.xml
freeswitch/trunk/conf/sip_profiles/default.xml
freeswitch/trunk/src/include/switch_apr.h
freeswitch/trunk/src/include/switch_core.h
freeswitch/trunk/src/include/switch_types.h
freeswitch/trunk/src/include/switch_utils.h
freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
freeswitch/trunk/src/switch_apr.c
freeswitch/trunk/src/switch_core.c
freeswitch/trunk/src/switch_utils.c
Log:
add acl stuff
Modified: freeswitch/trunk/conf/autoload_configs/event_socket.conf.xml
==============================================================================
--- freeswitch/trunk/conf/autoload_configs/event_socket.conf.xml (original)
+++ freeswitch/trunk/conf/autoload_configs/event_socket.conf.xml Wed Mar 26 18:14:09 2008
@@ -3,5 +3,6 @@
<param name="listen-ip" value="127.0.0.1"/>
<param name="listen-port" value="8021"/>
<param name="password" value="ClueCon"/>
+ <!--<param name="apply-inbound-acl" value="lan"/>-->
</settings>
</configuration>
Modified: freeswitch/trunk/conf/sip_profiles/default.xml
==============================================================================
--- freeswitch/trunk/conf/sip_profiles/default.xml (original)
+++ freeswitch/trunk/conf/sip_profiles/default.xml Wed Mar 26 18:14:09 2008
@@ -29,6 +29,8 @@
<param name="rtp-ip" value="$${local_ip_v4}"/>
<param name="sip-ip" value="$${local_ip_v4}"/>
<param name="hold-music" value="$${moh_uri}"/>
+ <!--<param name="apply-inbound-acl" value="lan"/>-->
+ <!--<param name="apply-register-acl" value="lan"/>-->
<!--<param name="dtmf-type" value="info"/>-->
<param name="record-template" value="$${base_dir}/recordings/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
<!--enable to use presense and mwi -->
Modified: freeswitch/trunk/src/include/switch_apr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_apr.h (original)
+++ freeswitch/trunk/src/include/switch_apr.h Wed Mar 26 18:14:09 2008
@@ -1232,7 +1232,7 @@
SWITCH_DECLARE(switch_status_t) switch_socket_create_pollfd(switch_pollfd_t ** poll, switch_socket_t * sock, int16_t flags, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_match_glob(const char *pattern, switch_array_header_t **result, switch_memory_pool_t *p);
-
+SWITCH_DECLARE(switch_status_t) switch_socket_addr_get(switch_sockaddr_t **sa, switch_bool_t remote, switch_socket_t *sock);
/** @} */
Modified: freeswitch/trunk/src/include/switch_core.h
==============================================================================
--- freeswitch/trunk/src/include/switch_core.h (original)
+++ freeswitch/trunk/src/include/switch_core.h Wed Mar 26 18:14:09 2008
@@ -1591,6 +1591,8 @@
SWITCH_DECLARE(void) switch_core_setrlimits(void);
SWITCH_DECLARE(void) switch_time_sync(void);
SWITCH_DECLARE(time_t) switch_timestamp(time_t *t);
+SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload);
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip(const char *ip_str, const char *list_name);
///\}
Modified: freeswitch/trunk/src/include/switch_types.h
==============================================================================
--- freeswitch/trunk/src/include/switch_types.h (original)
+++ freeswitch/trunk/src/include/switch_types.h Wed Mar 26 18:14:09 2008
@@ -1259,6 +1259,9 @@
struct HashElem;
typedef struct HashElem switch_hash_index_t;
+struct switch_network_list;
+typedef struct switch_network_list switch_network_list_t;
+
#define SWITCH_API_VERSION 1
#define SWITCH_MODULE_LOAD_ARGS (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool)
Modified: freeswitch/trunk/src/include/switch_utils.h
==============================================================================
--- freeswitch/trunk/src/include/switch_utils.h (original)
+++ freeswitch/trunk/src/include/switch_utils.h Wed Mar 26 18:14:09 2008
@@ -84,6 +84,7 @@
!strcasecmp(expr, "true") ||\
!strcasecmp(expr, "enabled") ||\
!strcasecmp(expr, "active") ||\
+!strcasecmp(expr, "allow") ||\
atoi(expr))) ? SWITCH_TRUE : SWITCH_FALSE
/*!
\brief find local ip of the box
@@ -347,6 +348,14 @@
SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, const char *from, const char *headers, const char *body, const char *file);
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_add_cidr(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok);
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok);
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip(switch_network_list_t *list, uint32_t ip);
+#define switch_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net == _ip)
+
+
/* malloc or DIE macros */
#ifdef NDEBUG
#define switch_malloc(ptr, len) (void)( (!!(ptr = malloc(len))) || (fprintf(stderr,"ABORT! Malloc failure at: %s:%s", __FILE__, __LINE__),abort(), 0), ptr )
Modified: freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_commands/mod_commands.c Wed Mar 26 18:14:09 2008
@@ -271,6 +271,63 @@
return SWITCH_STATUS_SUCCESS;
}
+SWITCH_STANDARD_API(reload_acl_function)
+{
+ const char *err;
+ switch_xml_t xml_root;
+
+ if (session) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (cmd && !strcmp(cmd, "reloadxml")) {
+ if ((xml_root = switch_xml_open_root(1, &err))) {
+ switch_xml_free(xml_root);
+ }
+ }
+
+ switch_load_network_lists(SWITCH_TRUE);
+
+ stream->write_function(stream, "+OK acl reloaded\n");
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_STANDARD_API(acl_function)
+{
+ int argc;
+ char *mydata = NULL, *argv[3];
+
+ if (!cmd) {
+ goto error;
+ }
+
+ mydata = strdup(cmd);
+ switch_assert(mydata);
+
+ argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+
+ if (argc < 2) {
+ goto error;
+ }
+
+ if (switch_check_network_list_ip(argv[0], argv[1])) {
+ stream->write_function(stream, "true");
+ goto ok;
+ }
+
+error:
+
+ stream->write_function(stream, "false");
+
+ok:
+
+ switch_safe_free(mydata);
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+
SWITCH_STANDARD_API(regex_function)
{
switch_regex_t *re = NULL;
@@ -2186,6 +2243,7 @@
SWITCH_ADD_API(commands_api_interface, "killchan", "Kill Channel (depricated)", kill_function, KILL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_kill", "Kill Channel", kill_function, KILL_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_park", "Park Channel", park_function, PARK_SYNTAX);
+ SWITCH_ADD_API(commands_api_interface, "reloadacl", "Reload ACL", reload_acl_function, "[reloadxml]");
SWITCH_ADD_API(commands_api_interface, "reloadxml", "Reload XML", reload_function, "");
SWITCH_ADD_API(commands_api_interface, "unload", "Unload Module", unload_function, LOAD_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "load", "Load Module", load_function, LOAD_SYNTAX);
@@ -2226,6 +2284,7 @@
SWITCH_ADD_API(commands_api_interface, "is_lan_addr", "see if an ip is a lan addr", lan_addr_function, "<ip>");
SWITCH_ADD_API(commands_api_interface, "cond", "Eval a conditional", cond_function, "<expr> ? <true val> : <false val>");
SWITCH_ADD_API(commands_api_interface, "regex", "Eval a regex", regex_function, "<data>|<pattern>[|<subst string>]");
+ SWITCH_ADD_API(commands_api_interface, "acl", "compater an ip to an acl list", acl_function, "<ip> <list_name>");
SWITCH_ADD_API(commands_api_interface, "uuid_chat", "Send a chat message", uuid_chat, UUID_CHAT_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "find_user_xml", "find a user", find_user_function, "<key> <user> <domain>");
SWITCH_ADD_API(commands_api_interface, "user_exists", "find a user", user_exists_function, "<key> <user> <domain>");
Modified: freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c
==============================================================================
--- freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c (original)
+++ freeswitch/trunk/src/mod/applications/mod_dptools/mod_dptools.c Wed Mar 26 18:14:09 2008
@@ -200,6 +200,28 @@
switch_core_session_send_dtmf_string(session, (const char *) data);
}
+SWITCH_STANDARD_APP(check_acl_function)
+{
+ int argc;
+ char *argv[2] = { 0 };
+ char *mydata;
+ switch_call_cause_t cause = SWITCH_CAUSE_CALL_REJECTED;
+
+ if (!switch_strlen_zero(data) && (mydata = switch_core_session_strdup(session, data))) {
+ if ((argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) > 1) {
+ if (!switch_check_network_list_ip(argv[0], argv[1])) {
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ if (argc > 2) {
+ cause = switch_channel_str2cause(argv[2]);
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call failed acl check for ip %s on list %s\n", argv[0], argv[1]);
+ switch_channel_hangup(channel, cause);
+ }
+ }
+ }
+
+}
+
SWITCH_STANDARD_APP(transfer_function)
{
int argc;
@@ -1760,6 +1782,8 @@
SWITCH_ADD_API(api_interface, "presence", "presence", presence_api_function, "<user> <rpid> <message>");
SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "transfer", "Transfer a channel", TRANSFER_LONG_DESC, transfer_function, "<exten> [<dialplan> <context>]", SAF_SUPPORT_NOMEDIA);
+ SWITCH_ADD_APP(app_interface, "check_acl", "Check an ip against an ACL list",
+ "Check an ip against an ACL list", check_acl_function, "<ip> <acl | cidr>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "sleep", "Pause a channel", SLEEP_LONG_DESC, sleep_function, "<pausemilliseconds>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "<delay ms>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "strftime", NULL, NULL, strftime_function, NULL, SAF_SUPPORT_NOMEDIA);
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h Wed Mar 26 18:14:09 2008
@@ -46,6 +46,8 @@
#include <switch_odbc.h>
#endif
+#define SOFIA_MAX_ACL 100
+
#define MODNAME "mod_sofia"
static const switch_state_handler_table_t noop_state_handler = { 0 };
struct sofia_gateway;
@@ -308,6 +310,11 @@
char *odbc_pass;
switch_odbc_handle_t *master_odbc;
switch_queue_t *sql_queue;
+ char *acl[SOFIA_MAX_ACL];
+ uint32_t acl_count;
+ char *reg_acl[SOFIA_MAX_ACL];
+ uint32_t reg_acl_count;
+
};
struct private_object {
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c Wed Mar 26 18:14:09 2008
@@ -1195,6 +1195,18 @@
profile->username = switch_core_strdup(profile->pool, val);
} else if (!strcasecmp(var, "context")) {
profile->context = switch_core_strdup(profile->pool, val);
+ } else if (!strcasecmp(var, "apply-inbound-acl")) {
+ if (profile->acl_count < SOFIA_MAX_ACL) {
+ profile->acl[profile->acl_count++] = switch_core_strdup(profile->pool, val);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
+ }
+ } else if (!strcasecmp(var, "apply-register-acl")) {
+ if (profile->reg_acl_count < SOFIA_MAX_ACL) {
+ profile->reg_acl[profile->reg_acl_count++] = switch_core_strdup(profile->pool, val);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
+ }
} else if (!strcasecmp(var, "alias")) {
sip_alias_node_t *node;
if ((node = switch_core_alloc(profile->pool, sizeof(*node)))) {
@@ -2478,6 +2490,18 @@
get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+ if (profile->acl_count) {
+ int x = 0;
+ for (x = 0 ; x < profile->acl_count; x++) {
+ if (!switch_check_network_list_ip(network_ip, profile->acl[x])) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl %s\n", network_ip, profile->acl[x]);
+ nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
+ return;
+ }
+ }
+ }
+
+
if ((profile->pflags & PFLAG_AUTH_CALLS) || (!(profile->pflags & PFLAG_BLIND_AUTH) && (sip->sip_proxy_authorization || sip->sip_authorization))) {
if (strcmp(network_ip, profile->sipip)) {
if (sofia_reg_handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key), &v_event)) {
Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c (original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c Wed Mar 26 18:14:09 2008
@@ -655,6 +655,23 @@
{
char key[128] = "";
switch_event_t *v_event = NULL;
+ char network_ip[80];
+ su_addrinfo_t *my_addrinfo = msg_addrinfo(nua_current_request(nua));
+
+ if (profile->reg_acl_count) {
+ int x = 0;
+
+ get_addr(network_ip, sizeof(network_ip), &((struct sockaddr_in *) my_addrinfo->ai_addr)->sin_addr);
+
+ for (x = 0 ; x < profile->reg_acl_count; x++) {
+ if (!switch_check_network_list_ip(network_ip, profile->reg_acl[x])) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl %s\n", network_ip, profile->reg_acl[x]);
+ nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END());
+ goto end;
+ }
+ }
+ }
+
if (!(profile->mflags & MFLAG_REGISTER)) {
nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS(nua), TAG_END());
Modified: freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c
==============================================================================
--- freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c (original)
+++ freeswitch/trunk/src/mod/event_handlers/mod_event_socket/mod_event_socket.c Wed Mar 26 18:14:09 2008
@@ -71,6 +71,9 @@
switch_core_session_t *session;
int lost_events;
int lost_logs;
+ switch_sockaddr_t *sa;
+ char remote_ip[50];
+ switch_port_t remote_port;
struct listener *next;
};
@@ -84,6 +87,8 @@
uint8_t ready;
} listen_list;
+#define MAX_ACL 100
+
static struct {
switch_mutex_t *mutex;
char *ip;
@@ -91,6 +96,8 @@
char *password;
int done;
int threads;
+ char *acl[MAX_ACL];
+ uint32_t acl_count;
} prefs;
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip);
@@ -1052,18 +1059,44 @@
switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL;
+
switch_mutex_lock(listen_list.mutex);
prefs.threads++;
switch_mutex_unlock(listen_list.mutex);
switch_assert(listener != NULL);
+ if (prefs.acl_count && listener->sa && !switch_strlen_zero(listener->remote_ip)) {
+ int x = 0;
+
+ for (x = 0 ; x < prefs.acl_count; x++) {
+ if (!switch_check_network_list_ip(listener->remote_ip, prefs.acl[x])) {
+ const char message[] = "Access Denied, go away.\n";
+ int mlen = strlen(message);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl %s\n", listener->remote_ip, prefs.acl[x]);
+
+ switch_snprintf(buf, sizeof(buf), "Content-Type: rude/rejection\nContent-Length %d\n\n", mlen);
+ len = strlen(buf);
+ switch_socket_send(listener->sock, buf, &len);
+ len = mlen;
+ switch_socket_send(listener->sock, message, &len);
+ goto done;
+ }
+ }
+ }
+
+
if ((session = listener->session)) {
channel = switch_core_session_get_channel(session);
switch_core_session_read_lock(session);
}
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open\n");
+ if (switch_strlen_zero(listener->remote_ip)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open\n");
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Open from %s:%d\n", listener->remote_ip, listener->remote_port);
+ }
switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE);
switch_set_flag_locked(listener, LFLAG_RUNNING);
@@ -1230,6 +1263,12 @@
prefs.port = (uint16_t) atoi(val);
} else if (!strcmp(var, "password")) {
set_pref_pass(val);
+ } else if (!strcasecmp(var, "apply-inbound-acl")) {
+ if (prefs.acl_count < MAX_ACL) {
+ prefs.acl[prefs.acl_count++] = strdup(val);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", MAX_ACL);
+ }
}
}
}
@@ -1259,6 +1298,7 @@
switch_sockaddr_t *sa;
switch_socket_t *inbound_socket = NULL;
listener_t *listener;
+ int x = 0;
memset(&listen_list, 0, sizeof(listen_list));
config();
@@ -1335,6 +1375,9 @@
listener->format = EVENT_FORMAT_PLAIN;
switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool);
switch_core_hash_init(&listener->event_hash, listener->pool);
+ switch_socket_addr_get(&listener->sa, SWITCH_TRUE, listener->sock);
+ switch_get_addr(listener->remote_ip, sizeof(listener->remote_ip), listener->sa);
+ listener->remote_port = switch_sockaddr_get_port(listener->sa);
launch_listener_thread(listener);
}
@@ -1349,6 +1392,11 @@
switch_core_destroy_memory_pool(&listener_pool);
}
+
+ for (x = 0 ; x < prefs.acl_count; x++) {
+ switch_safe_free(prefs.acl[x]);
+ }
+
fail:
return SWITCH_STATUS_TERM;
}
Modified: freeswitch/trunk/src/switch_apr.c
==============================================================================
--- freeswitch/trunk/src/switch_apr.c (original)
+++ freeswitch/trunk/src/switch_apr.c Wed Mar 26 18:14:09 2008
@@ -521,6 +521,11 @@
/* socket stubs */
+SWITCH_DECLARE(switch_status_t) switch_socket_addr_get(switch_sockaddr_t **sa, switch_bool_t remote, switch_socket_t *sock)
+{
+ return apr_socket_addr_get(sa, remote, sock);
+}
+
SWITCH_DECLARE(switch_status_t) switch_socket_create(switch_socket_t ** new_sock, int family, int type, int protocol, switch_memory_pool_t *pool)
{
return apr_socket_create(new_sock, family, type, protocol, pool);
Modified: freeswitch/trunk/src/switch_core.c
==============================================================================
--- freeswitch/trunk/src/switch_core.c (original)
+++ freeswitch/trunk/src/switch_core.c Wed Mar 26 18:14:09 2008
@@ -686,6 +686,132 @@
return;
}
+typedef struct {
+ switch_memory_pool_t *pool;
+ switch_hash_t *hash;
+} switch_ip_list_t;
+
+static switch_ip_list_t IP_LIST = { 0 };
+
+SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip(const char *ip_str, const char *list_name)
+{
+ switch_network_list_t *list;
+ uint32_t ip, net, mask, bits;
+ switch_bool_t ok = SWITCH_FALSE;
+
+ switch_mutex_lock(runtime.global_mutex);
+ inet_pton(AF_INET, ip_str, &ip);
+
+ if ((list = switch_core_hash_find(IP_LIST.hash, list_name))) {
+ ok = switch_network_list_validate_ip(list, ip);
+ } else if (strchr(list_name, '/')) {
+ switch_parse_cidr(list_name, &net, &mask, &bits);
+ ok = switch_test_subnet(ip, net, mask);
+ }
+ switch_mutex_unlock(runtime.global_mutex);
+
+ return ok;
+}
+
+
+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_mutex_lock(runtime.global_mutex);
+
+ if (IP_LIST.hash) {
+ switch_core_hash_destroy(&IP_LIST.hash);
+ }
+
+ if (IP_LIST.pool) {
+ switch_core_destroy_memory_pool(&IP_LIST.pool);
+ }
+
+ memset(&IP_LIST, 0, sizeof(IP_LIST));
+ switch_core_new_memory_pool(&IP_LIST.pool);
+ switch_core_hash_init(&IP_LIST.hash, IP_LIST.pool);
+
+ 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) {
+ const char *name = switch_xml_attr(x_list, "name");
+ const char *dft = switch_xml_attr(x_list, "default");
+ switch_bool_t default_type = SWITCH_TRUE;
+
+ if (switch_strlen_zero(name)) {
+ continue;
+ }
+
+ if (dft) {
+ default_type = switch_true(dft);
+ }
+
+ if (switch_network_list_create(&list, default_type, IP_LIST.pool) != SWITCH_STATUS_SUCCESS) {
+ abort();
+ }
+
+ if (reload) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Created ip list %s default (%s)\n", name, default_type ? "allow" : "deny");
+ }
+
+
+ for (x_node = switch_xml_child(x_list, "node"); x_node; x_node = x_node->next) {
+ const char *cidr = NULL, *host = NULL, *mask = NULL;
+ switch_bool_t ok = default_type;
+ const char *type = switch_xml_attr(x_node, "type");
+
+ if (type) {
+ ok = switch_true(type);
+ }
+
+ cidr = switch_xml_attr(x_node, "cidr");
+ host = switch_xml_attr(x_node, "host");
+ mask = switch_xml_attr(x_node, "mask");
+
+ if (cidr) {
+ if (switch_network_list_add_cidr(list, cidr, ok) == SWITCH_STATUS_SUCCESS) {
+ if (reload) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);
+ }
+ } else {
+ if (reload) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,
+ "Error Adding %s (%s) to list %s\n", cidr, ok ? "allow" : "deny", name);
+ }
+ }
+ } else if (host && mask) {
+ if (switch_network_list_add_host_mask(list, host, mask, ok) == SWITCH_STATUS_SUCCESS) {
+ if (reload) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
+ "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE,
+ "Adding %s/%s (%s) to list %s\n", host, mask, ok ? "allow" : "deny", name);
+ }
+ }
+ }
+
+ switch_core_hash_insert(IP_LIST.hash, name, list);
+ }
+ }
+ }
+
+ switch_xml_free(xml);
+ }
+
+ switch_mutex_unlock(runtime.global_mutex);
+}
+
SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switch_bool_t console, const char **err)
{
switch_xml_t xml = NULL, cfg = NULL;
@@ -733,7 +859,7 @@
apr_terminate();
return SWITCH_STATUS_MEMERR;
}
-
+
if ((xml = switch_xml_open_cfg("switch.conf", &cfg, NULL))) {
switch_xml_t settings, param;
@@ -795,6 +921,7 @@
switch_core_hash_insert(runtime.global_vars, varr, vall);
}
}
+
switch_xml_free(xml);
}
@@ -914,6 +1041,7 @@
#endif
signal(SIGHUP, handle_SIGHUP);
+ switch_load_network_lists(SWITCH_FALSE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Bringing up environment.\n");
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Loading Modules.\n");
Modified: freeswitch/trunk/src/switch_utils.c
==============================================================================
--- freeswitch/trunk/src/switch_utils.c (original)
+++ freeswitch/trunk/src/switch_utils.c Wed Mar 26 18:14:09 2008
@@ -38,6 +38,138 @@
#include "private/switch_core_pvt.h"
#define ESCAPE_META '\\'
+struct switch_network_node {
+ uint32_t ip;
+ uint32_t mask;
+ uint32_t bits;
+ switch_bool_t ok;
+ struct switch_network_node *next;
+};
+typedef struct switch_network_node switch_network_node_t;
+
+struct switch_network_list {
+ struct switch_network_node *node_head;
+ switch_bool_t default_type;
+ switch_memory_pool_t *pool;
+};
+
+
+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_network_list_t *new_list;
+
+ if (!pool) {
+ switch_core_new_memory_pool(&pool);
+ }
+
+ new_list = switch_core_alloc(pool, sizeof(**list));
+ new_list->pool = pool;
+ new_list->default_type = default_type;
+
+ *list = new_list;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip(switch_network_list_t *list, uint32_t ip)
+{
+ switch_network_node_t *node;
+ switch_bool_t ok = list->default_type;
+ uint32_t bits = 0;
+
+ for (node = list->node_head; node; node = node->next) {
+ if (node->bits > bits && switch_test_subnet(ip, node->ip, node->mask)) {
+ if (node->ok) {
+ ok = SWITCH_TRUE;
+ } else {
+ ok = SWITCH_FALSE;
+ }
+ bits = node->bits;
+ }
+ }
+
+ return ok;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_cidr(switch_network_list_t *list, const char *cidr_str, switch_bool_t ok)
+{
+ uint32_t ip, mask, bits;
+ switch_network_node_t *node;
+
+ if (switch_parse_cidr(cidr_str, &ip, &mask, &bits)) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ node = switch_core_alloc(list->pool, sizeof(*node));
+
+ node->ip = ip;
+ node->mask = mask;
+ node->ok = ok;
+ node->bits = bits;
+
+ node->next = list->node_head;
+ list->node_head = node;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_network_list_add_host_mask(switch_network_list_t *list, const char *host, const char *mask_str, switch_bool_t ok)
+{
+ int ip, mask;
+ switch_network_node_t *node;
+
+ inet_pton(AF_INET, host, &ip);
+ inet_pton(AF_INET, mask_str, &mask);
+
+ node = switch_core_alloc(list->pool, sizeof(*node));
+
+ node->ip = ip;
+ node->mask = 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->next = list->node_head;
+ list->node_head = node;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_DECLARE(int) switch_parse_cidr(const char *string, uint32_t *ip, uint32_t *mask, uint32_t *bitp)
+{
+ char host[128] = "";
+ char *bit_str;
+ int32_t bits;
+
+ strncpy(host, string, sizeof(host) - 1);
+ bit_str = strchr(host, '/');
+
+ if (!bit_str) {
+ return -1;
+ }
+
+ *bit_str++ = '\0';
+ bits = atoi(bit_str);
+
+ if (bits < 0 || bits > 32) {
+ return -2;
+ }
+
+ bits = atoi(bit_str);
+ inet_pton(AF_INET, host, ip);
+ *mask = 0xFFFFFFFF & ~(0xFFFFFFFF << bits);
+ *bitp = bits;
+
+ return 0;
+}
+
+
SWITCH_DECLARE(char *) switch_find_end_paren(const char *s, char open, char close)
{
const char *e = NULL;
More information about the Freeswitch-svn
mailing list