#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 <fcntl.h>
Go to the source code of this file.
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 void | stun_close_sock (void) |
static int | stun_monitor_request (const void *blarg) |
static void | stun_purge_socket (void) |
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND } |
struct { | |
sockaddr_in externaladdr | |
unsigned int externaladdr_known:1 | |
ast_mutex_t lock | |
unsigned int monitor_enabled:1 | |
unsigned int refresh | |
sockaddr_in stunaddr | |
int stunsock | |
} | args |
static struct ast_module_info * | ast_module_info = &__mod_info |
static const int | DEFAULT_MONITOR_REFRESH = 30 |
static struct ast_sched_thread * | sched |
static const char | stun_conf_file [] = "res_stun_monitor.conf" |
Definition in file res_stun_monitor.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 310 of file res_stun_monitor.c.
static int __reload | ( | int | startup | ) | [static] |
Definition at line 259 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().
00260 { 00261 int res; 00262 00263 ast_mutex_lock(&args.lock); 00264 if (!(res = load_config(startup)) && args.monitor_enabled) { 00265 res = stun_start_monitor(); 00266 } 00267 ast_mutex_unlock(&args.lock); 00268 00269 if ((res == -1) || !args.monitor_enabled) { 00270 args.monitor_enabled = 0; 00271 stun_stop_monitor(); 00272 } 00273 00274 return res; 00275 }
static void __unreg_module | ( | void | ) | [static] |
Definition at line 310 of file res_stun_monitor.c.
static int load_config | ( | int | startup | ) | [static] |
Definition at line 208 of file res_stun_monitor.c.
References args, ast_config_load2(), ast_log(), ast_parse_arg(), ast_set_flag, ast_variable_browse(), CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_variable::name, ast_variable::next, PARSE_INADDR, STANDARD_STUN_PORT, and ast_variable::value.
00209 { 00210 struct ast_flags config_flags = { 0, }; 00211 struct ast_config *cfg; 00212 struct ast_variable *v; 00213 00214 if (!startup) { 00215 ast_set_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED); 00216 } 00217 00218 if (!(cfg = ast_config_load2(stun_conf_file, "res_stun_monitor", config_flags)) || 00219 cfg == CONFIG_STATUS_FILEINVALID) { 00220 ast_log(LOG_ERROR, "Unable to load config %s\n", stun_conf_file); 00221 return -1; 00222 } 00223 00224 if (cfg == CONFIG_STATUS_FILEUNCHANGED && !startup) { 00225 return 0; 00226 } 00227 00228 /* set defaults */ 00229 args.monitor_enabled = 0; 00230 memset(&args.stunaddr, 0, sizeof(args.stunaddr)); 00231 args.refresh = DEFAULT_MONITOR_REFRESH; 00232 00233 for (v = ast_variable_browse(cfg, "general"); v; v = v->next) { 00234 if (!strcasecmp(v->name, "stunaddr")) { 00235 args.stunaddr.sin_port = htons(STANDARD_STUN_PORT); 00236 if (ast_parse_arg(v->value, PARSE_INADDR, &args.stunaddr)) { 00237 ast_log(LOG_WARNING, "Invalid STUN server address: %s\n", v->value); 00238 } else { 00239 ast_log(LOG_NOTICE, "STUN monitor enabled: %s\n", v->value); 00240 args.monitor_enabled = 1; 00241 } 00242 } else if (!strcasecmp(v->name, "stunrefresh")) { 00243 if ((sscanf(v->value, "%30u", &args.refresh) != 1) || !args.refresh) { 00244 ast_log(LOG_WARNING, "Invalid stunrefresh value '%s', must be an integer > 0 at line %d\n", v->value, v->lineno); 00245 args.refresh = DEFAULT_MONITOR_REFRESH; 00246 } else { 00247 ast_log(LOG_NOTICE, "STUN Monitor set to refresh every %d seconds\n", args.refresh); 00248 } 00249 } else { 00250 ast_log(LOG_WARNING, "SIP STUN: invalid config option %s at line %d\n", v->value, v->lineno); 00251 } 00252 } 00253 00254 ast_config_destroy(cfg); 00255 00256 return 0; 00257 }
static int load_module | ( | void | ) | [static] |
Definition at line 289 of file res_stun_monitor.c.
References __reload(), args, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_destroy, ast_mutex_init, sched, and stun_stop_monitor().
00290 { 00291 ast_mutex_init(&args.lock); 00292 args.stunsock = -1; 00293 memset(&args.externaladdr, 0, sizeof(args.externaladdr)); 00294 args.externaladdr_known = 0; 00295 sched = NULL; 00296 if (__reload(1)) { 00297 stun_stop_monitor(); 00298 ast_mutex_destroy(&args.lock); 00299 return AST_MODULE_LOAD_DECLINE; 00300 } 00301 00302 return AST_MODULE_LOAD_SUCCESS; 00303 }
static int reload | ( | void | ) | [static] |
Definition at line 277 of file res_stun_monitor.c.
References __reload().
00278 { 00279 return __reload(0); 00280 }
static void stun_close_sock | ( | void | ) | [inline, static] |
Definition at line 54 of file res_stun_monitor.c.
References args.
Referenced by stun_start_monitor(), and stun_stop_monitor().
00055 { 00056 if (args.stunsock != -1) { 00057 close(args.stunsock); 00058 args.stunsock = -1; 00059 memset(&args.externaladdr, 0, sizeof(args.externaladdr)); 00060 args.externaladdr_known = 0; 00061 } 00062 }
static int stun_monitor_request | ( | const void * | blarg | ) | [static] |
Definition at line 86 of file res_stun_monitor.c.
References args, ast_event_destroy(), AST_EVENT_IE_END, AST_EVENT_NETWORK_CHANGE, ast_event_new(), ast_event_queue(), ast_inet_ntoa(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_stun_request(), LOG_ERROR, LOG_NOTICE, and stun_purge_socket().
Referenced by stun_start_monitor().
00087 { 00088 int res; 00089 int generate_event = 0; 00090 struct sockaddr_in answer = { 0, }; 00091 00092 00093 /* once the stun socket goes away, this scheduler item will go away as well */ 00094 ast_mutex_lock(&args.lock); 00095 if (args.stunsock == -1) { 00096 ast_log(LOG_ERROR, "STUN monitor: can not send STUN request, socket is not open\n"); 00097 goto monitor_request_cleanup; 00098 } 00099 00100 stun_purge_socket(); 00101 00102 if (!(ast_stun_request(args.stunsock, &args.stunaddr, NULL, &answer)) && 00103 (memcmp(&args.externaladdr, &answer, sizeof(args.externaladdr)))) { 00104 const char *newaddr = ast_strdupa(ast_inet_ntoa(answer.sin_addr)); 00105 int newport = ntohs(answer.sin_port); 00106 00107 ast_log(LOG_NOTICE, "STUN MONITOR: Old external address/port %s:%d now seen as %s:%d \n", 00108 ast_inet_ntoa(args.externaladdr.sin_addr), ntohs(args.externaladdr.sin_port), 00109 newaddr, newport); 00110 00111 memcpy(&args.externaladdr, &answer, sizeof(args.externaladdr)); 00112 00113 if (args.externaladdr_known) { 00114 /* the external address was already known, and has changed... generate event. */ 00115 generate_event = 1; 00116 00117 } else { 00118 /* this was the first external address we found, do not alert listeners 00119 * until this address changes to something else. */ 00120 args.externaladdr_known = 1; 00121 } 00122 } 00123 00124 if (generate_event) { 00125 struct ast_event *event = ast_event_new(AST_EVENT_NETWORK_CHANGE, AST_EVENT_IE_END); 00126 if (!event) { 00127 ast_log(LOG_ERROR, "STUN monitor: could not create AST_EVENT_NETWORK_CHANGE event.\n"); 00128 goto monitor_request_cleanup; 00129 } 00130 if (ast_event_queue(event)) { 00131 ast_event_destroy(event); 00132 event = NULL; 00133 ast_log(LOG_ERROR, "STUN monitor: could not queue AST_EVENT_NETWORK_CHANGE event.\n"); 00134 goto monitor_request_cleanup; 00135 } 00136 } 00137 00138 monitor_request_cleanup: 00139 /* always refresh this scheduler item. It will be removed elsewhere when 00140 * it is supposed to go away */ 00141 res = args.refresh * 1000; 00142 ast_mutex_unlock(&args.lock); 00143 00144 return res; 00145 }
static void stun_purge_socket | ( | void | ) | [static] |
Definition at line 71 of file res_stun_monitor.c.
References args.
Referenced by stun_monitor_request().
00072 { 00073 int flags = fcntl(args.stunsock, F_GETFL); 00074 int res = 0; 00075 unsigned char reply_buf[1024]; 00076 00077 fcntl(args.stunsock, F_SETFL, flags | O_NONBLOCK); 00078 while (res != -1) { 00079 /* throw away everything in the buffer until we reach the end. */ 00080 res = recv(args.stunsock, reply_buf, sizeof(reply_buf), 0); 00081 } 00082 fcntl(args.stunsock, F_SETFL, flags & ~O_NONBLOCK); 00083 }
static int stun_start_monitor | ( | void | ) | [static] |
Definition at line 164 of file res_stun_monitor.c.
References args, ast_connect(), ast_log(), ast_sched_thread_add_variable(), ast_sched_thread_create(), ast_sched_thread_destroy(), ast_sockaddr_from_sin, ast_sockaddr_stringify(), errno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sched, stun_close_sock(), and stun_monitor_request().
Referenced by __reload().
00165 { 00166 struct ast_sockaddr dst; 00167 /* clean up any previous open socket */ 00168 stun_close_sock(); 00169 00170 /* create destination ast_sockaddr */ 00171 ast_sockaddr_from_sin(&dst, &args.stunaddr); 00172 00173 /* open new socket binding */ 00174 args.stunsock = socket(AF_INET, SOCK_DGRAM, 0); 00175 if (args.stunsock < 0) { 00176 ast_log(LOG_WARNING, "Unable to create STUN socket: %s\n", strerror(errno)); 00177 return -1; 00178 } 00179 00180 if (ast_connect(args.stunsock, &dst) != 0) { 00181 ast_log(LOG_WARNING, "SIP STUN Failed to connect to %s\n", ast_sockaddr_stringify(&dst)); 00182 stun_close_sock(); 00183 return -1; 00184 } 00185 00186 /* if scheduler thread is not started, make sure to start it now */ 00187 if (sched) { 00188 return 0; /* already started */ 00189 } 00190 00191 if (!(sched = ast_sched_thread_create())) { 00192 ast_log(LOG_ERROR, "Failed to create stun monitor scheduler thread\n"); 00193 stun_close_sock(); 00194 return -1; 00195 } 00196 00197 if (ast_sched_thread_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) { 00198 ast_log(LOG_ERROR, "Unable to schedule STUN network monitor \n"); 00199 sched = ast_sched_thread_destroy(sched); 00200 stun_close_sock(); 00201 return -1; 00202 } 00203 00204 ast_log(LOG_NOTICE, "STUN monitor started\n"); 00205 return 0; 00206 }
static void stun_stop_monitor | ( | void | ) | [static] |
Definition at line 150 of file res_stun_monitor.c.
References ast_log(), ast_sched_thread_destroy(), LOG_NOTICE, sched, and stun_close_sock().
Referenced by __reload(), load_module(), and unload_module().
00151 { 00152 if (sched) { 00153 sched = ast_sched_thread_destroy(sched); 00154 ast_log(LOG_NOTICE, "STUN monitor stopped\n"); 00155 } 00156 /* it is only safe to destroy the socket without holding arg->lock 00157 * after the sched thread is destroyed */ 00158 stun_close_sock(); 00159 }
static int unload_module | ( | void | ) | [static] |
Definition at line 282 of file res_stun_monitor.c.
References args, ast_mutex_destroy, and stun_stop_monitor().
00283 { 00284 stun_stop_monitor(); 00285 ast_mutex_destroy(&args.lock); 00286 return 0; 00287 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND } [static] |
Definition at line 310 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(), 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_park_call(), ast_pbx_run_args(), ast_queue_log(), astman_get_variables(), asyncgoto_exec(), background_detect_exec(), build_profile(), builtin_atxfer(), builtin_automixmonitor(), builtin_automonitor(), builtin_blindtransfer(), calendar_query_exec(), calendar_query_result_exec(), callerid_read(), callerid_write(), cc_do_state_change(), cc_failed(), 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(), config_handler(), connectedline_write(), controlplayback_exec(), count_exec(), cut_internal(), dahdi_accept_r2_call_exec(), dahdi_send_callrerouting_facility_exec(), 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(), eivr_comm(), 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(), func_args(), 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_core_set_debug_channel(), handle_gosub(), handle_verbose(), hint_read(), iconv_read(), import_helper(), isAnsweringMachine(), isexten_function_read(), jb_debug_output(), jb_error_output(), jb_warning_output(), listfilter(), load_config(), load_module(), log_exec(), login_exec(), manager_park(), masq_park_call(), masq_park_call_announce(), math(), misdn_call(), misdn_check_l2l1(), misdn_facility_exec(), misdn_request(), mixmonitor_exec(), my_pri_make_cc_dialstring(), originate_exec(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), oss_call(), oss_request(), page_exec(), park_call_exec(), park_call_full(), park_space_reserve(), parkandannounce_exec(), parkcall_helper(), pbx_builtin_answer(), pbx_builtin_background(), pbx_builtin_resetcdr(), pbx_builtin_setvar_multiple(), pbx_builtin_waitexten(), peek_read(), pickup_by_name_cb(), pickupchan_exec(), play_moh_exec(), playback_exec(), pp_each_extension_helper(), pp_each_user_helper(), pqm_exec(), privacy_exec(), pvalAppCallWalkArgs(), pvalMacroCallWalkArgs(), ql_exec(), queue_exec(), queue_function_memberpenalty_read(), queue_function_memberpenalty_write(), rcvfax_exec(), realtime_handler(), realtime_multi_handler(), realtimefield_read(), receivefax_exec(), record_exec(), redirecting_write(), 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(), shared_read(), shared_write(), shift_pop(), sig_pri_call(), sig_pri_extract_called_num_subaddr(), sip_request_call(), sip_tcptls_client_args_destructor(), sla_handle_dial_state_event(), sla_station_exec(), sla_trunk_exec(), smdi_msg_read(), smdi_msg_retrieve_read(), sndfax_exec(), softhangup_exec(), speech_background(), speech_load(), srv_result_read(), start_moh_exec(), start_monitor_exec(), stun_close_sock(), stun_monitor_request(), stun_purge_socket(), stun_start_monitor(), transfer_exec(), tryexec_exec(), unload_module(), unshift_push(), upqm_exec(), userevent_exec(), verbose_exec(), vm_box_exists(), vm_exec(), vm_execmain(), and zapateller_exec().
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 310 of file res_stun_monitor.c.
const int DEFAULT_MONITOR_REFRESH = 30 [static] |
Definition at line 39 of file res_stun_monitor.c.
struct sockaddr_in externaladdr |
current perceived external address.
Definition at line 46 of file res_stun_monitor.c.
unsigned int externaladdr_known |
Definition at line 51 of file res_stun_monitor.c.
Definition at line 47 of file res_stun_monitor.c.
unsigned int monitor_enabled |
Definition at line 50 of file res_stun_monitor.c.
unsigned int refresh |
struct ast_sched_thread* sched [static] |
Definition at line 42 of file res_stun_monitor.c.
const char stun_conf_file[] = "res_stun_monitor.conf" [static] |
Definition at line 41 of file res_stun_monitor.c.
struct sockaddr_in stunaddr |
The stun address we send requests to
Definition at line 45 of file res_stun_monitor.c.
int stunsock |
Definition at line 49 of file res_stun_monitor.c.