Fri Aug 17 00:17:48 2018

Asterisk developer's documentation


res_stun_monitor.c File Reference

STUN Network Monitor. More...

#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 = "ac1f6a56484a8820659555499174e588" , .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_infoast_module_info = &__mod_info
static struct ast_sched_threadsched
static const char stun_conf_file [] = "res_stun_monitor.conf"

Detailed Description

STUN Network Monitor.

Author:
David Vossel <dvossel@digium.com>

Definition in file res_stun_monitor.c.


Define Documentation

#define DEFAULT_MONITOR_REFRESH   30

Default refresh period in seconds

Definition at line 44 of file res_stun_monitor.c.

Referenced by load_config().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 388 of file res_stun_monitor.c.

static int __reload ( int  startup  )  [static]

Definition at line 342 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().

00343 {
00344    int res;
00345 
00346    ast_mutex_lock(&args.lock);
00347    if (!(res = load_config(startup)) && args.monitor_enabled) {
00348       res = stun_start_monitor();
00349    }
00350    ast_mutex_unlock(&args.lock);
00351 
00352    if (res < 0 || !args.monitor_enabled) {
00353       stun_stop_monitor();
00354    }
00355 
00356    return res;
00357 }

static void __unreg_module ( void   )  [static]

Definition at line 388 of file res_stun_monitor.c.

static int load_config ( int  startup  )  [static]

Definition at line 293 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.

Referenced by __reload().

00294 {
00295    struct ast_flags config_flags = { 0, };
00296    struct ast_config *cfg;
00297    struct ast_variable *v;
00298 
00299    if (!startup) {
00300       ast_set_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
00301    }
00302 
00303    cfg = ast_config_load2(stun_conf_file, "res_stun_monitor", config_flags);
00304    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
00305       ast_log(LOG_WARNING, "Unable to load config %s\n", stun_conf_file);
00306       return -1;
00307    }
00308    if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00309       return 0;
00310    }
00311 
00312    /* clean up any previous open socket */
00313    stun_close_sock();
00314    args.stun_poll_failed_gripe = 0;
00315 
00316    /* set defaults */
00317    args.monitor_enabled = 0;
00318    args.refresh = DEFAULT_MONITOR_REFRESH;
00319 
00320    for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
00321       if (!strcasecmp(v->name, "stunaddr")) {
00322          if (setup_stunaddr(v->value)) {
00323             ast_log(LOG_WARNING, "Invalid STUN server address: %s at line %d\n",
00324                v->value, v->lineno);
00325          }
00326       } else if (!strcasecmp(v->name, "stunrefresh")) {
00327          if ((sscanf(v->value, "%30u", &args.refresh) != 1) || !args.refresh) {
00328             ast_log(LOG_WARNING, "Invalid stunrefresh value '%s', must be an integer > 0 at line %d\n", v->value, v->lineno);
00329             args.refresh = DEFAULT_MONITOR_REFRESH;
00330          }
00331       } else {
00332          ast_log(LOG_WARNING, "Invalid config option %s at line %d\n",
00333             v->value, v->lineno);
00334       }
00335    }
00336 
00337    ast_config_destroy(cfg);
00338 
00339    return 0;
00340 }

static int load_module ( void   )  [static]

Definition at line 371 of file res_stun_monitor.c.

References __reload(), args, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_destroy, and ast_mutex_init.

00372 {
00373    ast_mutex_init(&args.lock);
00374    args.stun_sock = -1;
00375    if (__reload(1)) {
00376       ast_mutex_destroy(&args.lock);
00377       return AST_MODULE_LOAD_DECLINE;
00378    }
00379 
00380    return AST_MODULE_LOAD_SUCCESS;
00381 }

static int reload ( void   )  [static]

Definition at line 359 of file res_stun_monitor.c.

References __reload().

00360 {
00361    return __reload(0);
00362 }

static int setup_stunaddr ( const char *  value  )  [static]

Definition at line 243 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().

00244 {
00245    char *val;
00246    char *host_str;
00247    char *port_str;
00248    unsigned int port;
00249    struct ast_sockaddr stun_addr;
00250 
00251    if (ast_strlen_zero(value)) {
00252       /* Setting to an empty value disables STUN monitoring. */
00253       args.monitor_enabled = 0;
00254       return 0;
00255    }
00256 
00257    val = ast_strdupa(value);
00258    if (!ast_sockaddr_split_hostport(val, &host_str, &port_str, 0)
00259       || ast_strlen_zero(host_str)) {
00260       return -1;
00261    }
00262 
00263    /* Determine STUN port */
00264    if (ast_strlen_zero(port_str)
00265       || 1 != sscanf(port_str, "%30u", &port)) {
00266       port = STANDARD_STUN_PORT;
00267    }
00268 
00269    host_str = ast_strdup(host_str);
00270    if (!host_str) {
00271       return -1;
00272    }
00273 
00274    /* Lookup STUN address. */
00275    memset(&stun_addr, 0, sizeof(stun_addr));
00276    stun_addr.ss.ss_family = AF_INET;
00277    if (ast_get_ip(&stun_addr, host_str)) {
00278       ast_log(LOG_WARNING, "Unable to lookup STUN server '%s'\n", host_str);
00279       ast_free(host_str);
00280       return -1;
00281    }
00282 
00283    /* Save STUN server information. */
00284    ast_free((char *) args.server_hostname);
00285    args.server_hostname = host_str;
00286    args.stun_port = port;
00287 
00288    /* Enable STUN monitor */
00289    args.monitor_enabled = 1;
00290    return 0;
00291 }

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(), 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 212 of file res_stun_monitor.c.

References args, ast_log(), ast_sched_thread_add_variable(), ast_sched_thread_create(), ast_sched_thread_destroy(), LOG_ERROR, LOG_NOTICE, and stun_monitor_request().

Referenced by __reload().

00213 {
00214    /* if scheduler thread is not started, make sure to start it now */
00215    if (sched) {
00216       return 0; /* already started */
00217    }
00218 
00219    if (!(sched = ast_sched_thread_create())) {
00220       ast_log(LOG_ERROR, "Failed to create stun monitor scheduler thread\n");
00221       return -1;
00222    }
00223 
00224    if (ast_sched_thread_add_variable(sched, (args.refresh * 1000), stun_monitor_request, NULL, 1) < 0) {
00225       ast_log(LOG_ERROR, "Unable to schedule STUN network monitor \n");
00226       sched = ast_sched_thread_destroy(sched);
00227       return -1;
00228    }
00229 
00230    ast_log(LOG_NOTICE, "STUN monitor started\n");
00231    return 0;
00232 }

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_thread_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       sched = ast_sched_thread_destroy(sched);
00200       ast_log(LOG_NOTICE, "STUN monitor stopped\n");
00201    }
00202 }

static int unload_module ( void   )  [static]

Definition at line 364 of file res_stun_monitor.c.

References args, ast_mutex_destroy, and stun_stop_monitor().

00365 {
00366    stun_stop_monitor();
00367    ast_mutex_destroy(&args.lock);
00368    return 0;
00369 }


Variable Documentation

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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DEPEND } [static]

Definition at line 388 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(), 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_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_warning_output(), listfilter(), load_config(), load_module(), log_exec(), login_exec(), man_do_variable_value(), math(), misdn_call(), misdn_check_l2l1(), misdn_facility_exec(), misdn_request(), mixmonitor_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_memberpenalty_read(), queue_function_memberpenalty_write(), queue_function_queuememberpaused(), queue_function_queuememberstatus(), 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(), stackpeek_read(), start_monitor_exec(), 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().

Definition at line 388 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_thread* 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.


Generated on 17 Aug 2018 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1