#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/event.h"
#include "asterisk/sched.h"
#include "asterisk/config.h"
#include "asterisk/stun.h"
#include "asterisk/netsock2.h"
#include "asterisk/lock.h"
#include "asterisk/acl.h"
#include <fcntl.h>

Go to the source code of this file.
Defines | |
| #define | DEFAULT_MONITOR_REFRESH 30 |
Functions | |
| static void | __reg_module (void) |
| static int | __reload (int startup) |
| static void | __unreg_module (void) |
| static int | load_config (int startup) |
| static int | load_module (void) |
| static int | reload (void) |
| static int | setup_stunaddr (const char *value) |
| static void | stun_close_sock (void) |
| static int | stun_monitor_request (const void *blarg) |
| static int | stun_start_monitor (void) |
| static void | stun_stop_monitor (void) |
| static int | unload_module (void) |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "STUN Network Monitor" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND } |
| struct { | |
| struct sockaddr_in external_addr | |
| unsigned int external_addr_known:1 | |
| ast_mutex_t lock | |
| unsigned int monitor_enabled:1 | |
| unsigned int refresh | |
| const char * server_hostname | |
| unsigned int stun_poll_failed_gripe:1 | |
| unsigned int stun_port | |
| int stun_sock | |
| } | args |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static struct ast_sched_context * | sched |
| static const char | stun_conf_file [] = "res_stun_monitor.conf" |
Definition in file res_stun_monitor.c.
| #define DEFAULT_MONITOR_REFRESH 30 |
Default refresh period in seconds
Definition at line 44 of file res_stun_monitor.c.
Referenced by load_config().
| static void __reg_module | ( | void | ) | [static] |
Definition at line 398 of file res_stun_monitor.c.
| static int __reload | ( | int | startup | ) | [static] |
Definition at line 352 of file res_stun_monitor.c.
References args, ast_mutex_lock, ast_mutex_unlock, load_config(), stun_start_monitor(), and stun_stop_monitor().
Referenced by load_module(), and reload().
00353 { 00354 int res; 00355 00356 ast_mutex_lock(&args.lock); 00357 if (!(res = load_config(startup)) && args.monitor_enabled) { 00358 res = stun_start_monitor(); 00359 } 00360 ast_mutex_unlock(&args.lock); 00361 00362 if (res < 0 || !args.monitor_enabled) { 00363 stun_stop_monitor(); 00364 } 00365 00366 return res; 00367 }
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 398 of file res_stun_monitor.c.
| static int load_config | ( | int | startup | ) | [static] |
Definition at line 303 of file res_stun_monitor.c.
References args, ast_config_destroy(), ast_config_load2(), ast_log(), ast_set_flag, ast_variable_browse(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, DEFAULT_MONITOR_REFRESH, ast_variable::lineno, LOG_WARNING, ast_variable::name, ast_variable::next, setup_stunaddr(), stun_close_sock(), and ast_variable::value.
00304 { 00305 struct ast_flags config_flags = { 0, }; 00306 struct ast_config *cfg; 00307 struct ast_variable *v; 00308 00309 if (!startup) { 00310 ast_set_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 00311 } 00312 00313 cfg = ast_config_load2(stun_conf_file, "res_stun_monitor", config_flags); 00314 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) { 00315 ast_log(LOG_WARNING, "Unable to load config %s\n", stun_conf_file); 00316 return -1; 00317 } 00318 if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 00319 return 0; 00320 } 00321 00322 /* clean up any previous open socket */ 00323 stun_close_sock(); 00324 args.stun_poll_failed_gripe = 0; 00325 00326 /* set defaults */ 00327 args.monitor_enabled = 0; 00328 args.refresh = DEFAULT_MONITOR_REFRESH; 00329 00330 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00331 if (!strcasecmp(v->name, "stunaddr")) { 00332 if (setup_stunaddr(v->value)) { 00333 ast_log(LOG_WARNING, "Invalid STUN server address: %s at line %d\n", 00334 v->value, v->lineno); 00335 } 00336 } else if (!strcasecmp(v->name, "stunrefresh")) { 00337 if ((sscanf(v->value, "%30u", &args.refresh) != 1) || !args.refresh) { 00338 ast_log(LOG_WARNING, "Invalid stunrefresh value '%s', must be an integer > 0 at line %d\n", v->value, v->lineno); 00339 args.refresh = DEFAULT_MONITOR_REFRESH; 00340 } 00341 } else { 00342 ast_log(LOG_WARNING, "Invalid config option %s at line %d\n", 00343 v->value, v->lineno); 00344 } 00345 } 00346 00347 ast_config_destroy(cfg); 00348 00349 return 0; 00350 }
| static int load_module | ( | void | ) | [static] |
Definition at line 381 of file res_stun_monitor.c.
References __reload(), args, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_destroy, and ast_mutex_init.
00382 { 00383 ast_mutex_init(&args.lock); 00384 args.stun_sock = -1; 00385 if (__reload(1)) { 00386 ast_mutex_destroy(&args.lock); 00387 return AST_MODULE_LOAD_DECLINE; 00388 } 00389 00390 return AST_MODULE_LOAD_SUCCESS; 00391 }
| static int reload | ( | void | ) | [static] |
Definition at line 369 of file res_stun_monitor.c.
References __reload().
00370 { 00371 return __reload(0); 00372 }
| static int setup_stunaddr | ( | const char * | value | ) | [static] |
Definition at line 253 of file res_stun_monitor.c.
References args, ast_free, ast_get_ip(), ast_log(), ast_sockaddr_split_hostport(), ast_strdup, ast_strdupa, ast_strlen_zero(), LOG_WARNING, ast_sockaddr::ss, and STANDARD_STUN_PORT.
Referenced by load_config().
00254 { 00255 char *val; 00256 char *host_str; 00257 char *port_str; 00258 unsigned int port; 00259 struct ast_sockaddr stun_addr; 00260 00261 if (ast_strlen_zero(value)) { 00262 /* Setting to an empty value disables STUN monitoring. */ 00263 args.monitor_enabled = 0; 00264 return 0; 00265 } 00266 00267 val = ast_strdupa(value); 00268 if (!ast_sockaddr_split_hostport(val, &host_str, &port_str, 0) 00269 || ast_strlen_zero(host_str)) { 00270 return -1; 00271 } 00272 00273 /* Determine STUN port */ 00274 if (ast_strlen_zero(port_str) 00275 || 1 != sscanf(port_str, "%30u", &port)) { 00276 port = STANDARD_STUN_PORT; 00277 } 00278 00279 host_str = ast_strdup(host_str); 00280 if (!host_str) { 00281 return -1; 00282 } 00283 00284 /* Lookup STUN address. */ 00285 memset(&stun_addr, 0, sizeof(stun_addr)); 00286 stun_addr.ss.ss_family = AF_INET; 00287 if (ast_get_ip(&stun_addr, host_str)) { 00288 ast_log(LOG_WARNING, "Unable to lookup STUN server '%s'\n", host_str); 00289 ast_free(host_str); 00290 return -1; 00291 } 00292 00293 /* Save STUN server information. */ 00294 ast_free((char *) args.server_hostname); 00295 args.server_hostname = host_str; 00296 args.stun_port = port; 00297 00298 /* Enable STUN monitor */ 00299 args.monitor_enabled = 1; 00300 return 0; 00301 }
| static void stun_close_sock | ( | void | ) | [static] |
Definition at line 70 of file res_stun_monitor.c.
References args.
Referenced by load_config(), stun_monitor_request(), stun_start_monitor(), and stun_stop_monitor().
00071 { 00072 if (0 <= args.stun_sock) { 00073 close(args.stun_sock); 00074 args.stun_sock = -1; 00075 } 00076 }
| static int stun_monitor_request | ( | const void * | blarg | ) | [static] |
Definition at line 79 of file res_stun_monitor.c.
References args, ast_connect(), ast_event_destroy(), AST_EVENT_IE_END, AST_EVENT_NETWORK_CHANGE, ast_event_new(), ast_event_queue(), ast_get_ip(), ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_sockaddr_set_port, ast_sockaddr_stringify(), ast_strdupa, ast_stun_request(), errno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_sockaddr::ss, and stun_close_sock().
Referenced by stun_start_monitor().
00080 { 00081 int res; 00082 struct sockaddr_in answer; 00083 static const struct sockaddr_in no_addr = { 0, }; 00084 00085 ast_mutex_lock(&args.lock); 00086 if (!args.monitor_enabled) { 00087 goto monitor_request_cleanup; 00088 } 00089 00090 if (args.stun_sock < 0) { 00091 struct ast_sockaddr stun_addr; 00092 00093 /* STUN socket not open. Refresh the server DNS address resolution. */ 00094 if (!args.server_hostname) { 00095 /* No STUN hostname? */ 00096 goto monitor_request_cleanup; 00097 } 00098 00099 /* Lookup STUN address. */ 00100 memset(&stun_addr, 0, sizeof(stun_addr)); 00101 stun_addr.ss.ss_family = AF_INET; 00102 if (ast_get_ip(&stun_addr, args.server_hostname)) { 00103 /* Lookup failed. */ 00104 ast_log(LOG_WARNING, "Unable to lookup STUN server '%s'\n", 00105 args.server_hostname); 00106 goto monitor_request_cleanup; 00107 } 00108 ast_sockaddr_set_port(&stun_addr, args.stun_port); 00109 00110 /* open socket binding */ 00111 args.stun_sock = socket(AF_INET, SOCK_DGRAM, 0); 00112 if (args.stun_sock < 0) { 00113 ast_log(LOG_WARNING, "Unable to create STUN socket: %s\n", strerror(errno)); 00114 goto monitor_request_cleanup; 00115 } 00116 if (ast_connect(args.stun_sock, &stun_addr)) { 00117 ast_log(LOG_WARNING, "STUN Failed to connect to %s: %s\n", 00118 ast_sockaddr_stringify(&stun_addr), strerror(errno)); 00119 stun_close_sock(); 00120 goto monitor_request_cleanup; 00121 } 00122 } 00123 00124 res = ast_stun_request(args.stun_sock, NULL, NULL, &answer); 00125 if (res) { 00126 /* 00127 * STUN request timed out or errored. 00128 * 00129 * Refresh the server DNS address resolution next time around. 00130 */ 00131 if (!args.stun_poll_failed_gripe) { 00132 args.stun_poll_failed_gripe = 1; 00133 ast_log(LOG_WARNING, "STUN poll %s. Re-evaluating STUN server address.\n", 00134 res < 0 ? "failed" : "got no response"); 00135 } 00136 stun_close_sock(); 00137 } else { 00138 args.stun_poll_failed_gripe = 0; 00139 if (memcmp(&no_addr, &answer, sizeof(no_addr)) 00140 && memcmp(&args.external_addr, &answer, sizeof(args.external_addr))) { 00141 const char *newaddr = ast_strdupa(ast_inet_ntoa(answer.sin_addr)); 00142 int newport = ntohs(answer.sin_port); 00143 00144 ast_log(LOG_NOTICE, "Old external address/port %s:%d now seen as %s:%d.\n", 00145 ast_inet_ntoa(args.external_addr.sin_addr), 00146 ntohs(args.external_addr.sin_port), newaddr, newport); 00147 00148 args.external_addr = answer; 00149 00150 if (args.external_addr_known) { 00151 struct ast_event *event; 00152 00153 /* 00154 * The external address was already known, and has changed... 00155 * generate event. 00156 */ 00157 event = ast_event_new(AST_EVENT_NETWORK_CHANGE, AST_EVENT_IE_END); 00158 if (!event) { 00159 ast_log(LOG_ERROR, "Could not create AST_EVENT_NETWORK_CHANGE event.\n"); 00160 } else if (ast_event_queue(event)) { 00161 ast_event_destroy(event); 00162 ast_log(LOG_ERROR, "Could not queue AST_EVENT_NETWORK_CHANGE event.\n"); 00163 } 00164 } else { 00165 /* this was the first external address we found, do not alert listeners 00166 * until this address changes to something else. */ 00167 args.external_addr_known = 1; 00168 } 00169 } 00170 } 00171 00172 monitor_request_cleanup: 00173 /* always refresh this scheduler item. It will be removed elsewhere when 00174 * it is supposed to go away */ 00175 res = args.refresh * 1000; 00176 ast_mutex_unlock(&args.lock); 00177 00178 return res; 00179 }
| static int stun_start_monitor | ( | void | ) | [static] |
Definition at line 213 of file res_stun_monitor.c.
References args, ast_log(), ast_sched_add_variable(), ast_sched_context_create(), ast_sched_context_destroy(), ast_sched_start_thread(), LOG_ERROR, LOG_NOTICE, stun_close_sock(), and stun_monitor_request().
Referenced by __reload().
00214 { 00215 /* if scheduler thread is not started, make sure to start it now */ 00216 if (sched) { 00217 return 0; /* already started */ 00218 } 00219 00220 if (!(sched = ast_sched_context_create())) { 00221 ast_log(LOG_ERROR, "Failed to create stun monitor scheduler context\n"); 00222 return -1; 00223 } 00224 00225 if (ast_sched_start_thread(sched)) { 00226 ast_sched_context_destroy(sched); 00227 sched = NULL; 00228 stun_close_sock(); 00229 return -1; 00230 } 00231 00232 if (ast_sched_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) { 00233 ast_log(LOG_ERROR, "Unable to schedule STUN network monitor \n"); 00234 ast_sched_context_destroy(sched); 00235 sched = NULL; 00236 return -1; 00237 } 00238 00239 ast_log(LOG_NOTICE, "STUN monitor started\n"); 00240 00241 return 0; 00242 }
| static void stun_stop_monitor | ( | void | ) | [static] |
Definition at line 189 of file res_stun_monitor.c.
References args, ast_free, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_sched_context_destroy(), LOG_NOTICE, and stun_close_sock().
Referenced by __reload(), and unload_module().
00190 { 00191 ast_mutex_lock(&args.lock); 00192 args.monitor_enabled = 0; 00193 ast_free((char *) args.server_hostname); 00194 args.server_hostname = NULL; 00195 stun_close_sock(); 00196 ast_mutex_unlock(&args.lock); 00197 00198 if (sched) { 00199 ast_sched_context_destroy(sched); 00200 sched = NULL; 00201 ast_log(LOG_NOTICE, "STUN monitor stopped\n"); 00202 } 00203 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 374 of file res_stun_monitor.c.
References args, ast_mutex_destroy, and stun_stop_monitor().
00375 { 00376 stun_stop_monitor(); 00377 ast_mutex_destroy(&args.lock); 00378 return 0; 00379 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "STUN Network Monitor" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND } [static] |
Definition at line 398 of file res_stun_monitor.c.
struct { ... } args [static] |
Referenced by __reload(), acf_curl_helper(), acf_isexten_exec(), acf_jabberreceive_read(), acf_jabberstatus_read(), acf_meetme_info(), acf_odbc_read(), acf_odbc_write(), acf_rand_exec(), acf_strftime(), acf_strptime(), acf_transaction_read(), acf_transaction_write(), acf_version_exec(), acf_vmcount_exec(), add_agent(), add_cfg_entry(), add_rt_cfg_entry(), add_rt_multi_cfg_entry(), admin_exec(), adsi_process(), aelsub_exec(), aes_helper(), agi_exec_full(), aji_join_exec(), aji_leave_exec(), aji_send_exec(), aji_sendgroup_exec(), aji_status_exec(), answer_exec_enable(), app_exec(), aqm_exec(), ast_cc_agent_status_response(), ast_cli_command_full(), ast_eivr_senddtmf(), ast_func_read(), ast_func_read2(), ast_func_write(), ast_queue_log(), asyncgoto_exec(), background_detect_exec(), bridge_exec(), build_profile(), builtin_automixmonitor(), builtin_automonitor(), calendar_query_exec(), calendar_query_result_exec(), callerid_read(), cc_do_state_change(), cc_request_state_change(), cc_status_response(), cdr_read(), cdr_write(), celgenuserevent_exec(), chanavail_exec(), channel_admin_exec(), channel_set_debug(), chanspy_exec(), cli_odbc_read(), cli_odbc_write(), conf_exec(), confbridge_exec(), config_function_read(), controlplayback_exec(), count_exec(), cut_internal(), dahdi_call(), dahdiras_exec(), determine_starting_point(), dial_exec_full(), dial_trunk(), dialgroup_write(), dictate_exec(), directory_exec(), disa_exec(), dundi_query_read(), dundi_result_read(), dundifunc_read(), enable_jack_hook(), enum_query_read(), enum_result_read(), exec_exec(), extenspy_exec(), festival_exec(), file_count_line(), file_read(), file_write(), filter(), find_call(), find_conf(), find_realtime_gw(), func_args(), func_confbridge_info(), func_header_read(), function_agent(), function_db_delete(), function_db_exists(), function_db_read(), function_db_write(), function_enum(), function_fieldnum_helper(), function_fieldqty_helper(), function_realtime_read(), function_realtime_readdestroy(), function_realtime_write(), function_txtcidname(), gosubif_exec(), handle_verbose(), hint_read(), iconv_read(), import_helper(), isAnsweringMachine(), isexten_function_read(), jb_debug_output(), jb_error_output(), jb_framedata_init(), jb_warning_output(), listfilter(), load_config(), load_module(), log_exec(), login_exec(), man_do_variable_value(), manager_mixmonitor(), math(), misdn_call(), misdn_check_l2l1(), misdn_facility_exec(), misdn_request(), mixmonitor_exec(), msg_send_exec(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), oss_call(), oss_request(), page_exec(), parkandannounce_exec(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_setvar_multiple(), pbx_builtin_waitexten(), peek_read(), pickup_by_name_cb(), pickupchan_exec(), playback_exec(), pp_each_extension_helper(), pp_each_user_helper(), pqm_exec(), privacy_exec(), process_applicationmap_line(), ql_exec(), queue_exec(), queue_function_mem_read(), queue_function_mem_write(), queue_function_memberpenalty_read(), queue_function_memberpenalty_write(), rcvfax_exec(), realtimefield_read(), receivefax_exec(), record_exec(), reg_source_db(), regex(), reload_single_member(), replace(), retrydial_exec(), rqm_exec(), run_station(), saycountedadj_exec(), saycountednoun_exec(), sayunixtime_exec(), senddtmf_exec(), sendfax_exec(), sendurl_exec(), setup_stunaddr(), shared_read(), shared_write(), shift_pop(), sip_acf_channel_read(), sip_request_call(), sip_tcptls_client_args_destructor(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sndfax_exec(), softhangup_exec(), speech_background(), speech_load(), srv_result_read(), start_monitor_exec(), static_realtime_cb(), stop_mixmonitor_exec(), strreplace(), stun_close_sock(), stun_monitor_request(), stun_start_monitor(), stun_stop_monitor(), transfer_exec(), tryexec_exec(), unload_module(), unshift_push(), upqm_exec(), userevent_exec(), verbose_exec(), vm_box_exists(), vm_exec(), vm_execmain(), volume_write(), and zapateller_exec().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 398 of file res_stun_monitor.c.
| struct sockaddr_in external_addr |
Current perceived external address.
Definition at line 53 of file res_stun_monitor.c.
| unsigned int external_addr_known |
TRUE if the perceived external address is valid/known.
Definition at line 65 of file res_stun_monitor.c.
STUN monitor protection lock.
Definition at line 51 of file res_stun_monitor.c.
| unsigned int monitor_enabled |
TRUE if the STUN monitor is enabled.
Definition at line 63 of file res_stun_monitor.c.
| unsigned int refresh |
Number of seconds between polls to the STUN server for the external address.
Definition at line 59 of file res_stun_monitor.c.
Referenced by iax2_ack_registry().
struct ast_sched_context* sched [static] |
Definition at line 47 of file res_stun_monitor.c.
| const char* server_hostname |
STUN server host name.
Definition at line 55 of file res_stun_monitor.c.
const char stun_conf_file[] = "res_stun_monitor.conf" [static] |
Definition at line 46 of file res_stun_monitor.c.
| unsigned int stun_poll_failed_gripe |
TRUE if we have already griped about a STUN poll failing.
Definition at line 67 of file res_stun_monitor.c.
| unsigned int stun_port |
Port of STUN server to use
Definition at line 57 of file res_stun_monitor.c.
| int stun_sock |
Monitoring STUN socket.
Definition at line 61 of file res_stun_monitor.c.
1.5.6