00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 346700 $")
00033
00034 #include "asterisk/module.h"
00035 #include "asterisk/event.h"
00036 #include "asterisk/sched.h"
00037 #include "asterisk/config.h"
00038 #include "asterisk/stun.h"
00039 #include "asterisk/netsock2.h"
00040 #include "asterisk/lock.h"
00041 #include "asterisk/acl.h"
00042 #include <fcntl.h>
00043
00044 #define DEFAULT_MONITOR_REFRESH 30
00045
00046 static const char stun_conf_file[] = "res_stun_monitor.conf";
00047 static struct ast_sched_thread *sched;
00048
00049 static struct {
00050
00051 ast_mutex_t lock;
00052
00053 struct sockaddr_in external_addr;
00054
00055 const char *server_hostname;
00056
00057 unsigned int stun_port;
00058
00059 unsigned int refresh;
00060
00061 int stun_sock;
00062
00063 unsigned int monitor_enabled:1;
00064
00065 unsigned int external_addr_known:1;
00066
00067 unsigned int stun_poll_failed_gripe:1;
00068 } args;
00069
00070 static void stun_close_sock(void)
00071 {
00072 if (0 <= args.stun_sock) {
00073 close(args.stun_sock);
00074 args.stun_sock = -1;
00075 }
00076 }
00077
00078
00079 static int stun_monitor_request(const void *blarg)
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
00094 if (!args.server_hostname) {
00095
00096 goto monitor_request_cleanup;
00097 }
00098
00099
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
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
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
00128
00129
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
00155
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
00166
00167 args.external_addr_known = 1;
00168 }
00169 }
00170 }
00171
00172 monitor_request_cleanup:
00173
00174
00175 res = args.refresh * 1000;
00176 ast_mutex_unlock(&args.lock);
00177
00178 return res;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 static void stun_stop_monitor(void)
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 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 static int stun_start_monitor(void)
00213 {
00214
00215 if (sched) {
00216 return 0;
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 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 static int setup_stunaddr(const char *value)
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
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
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
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
00284 ast_free((char *) args.server_hostname);
00285 args.server_hostname = host_str;
00286 args.stun_port = port;
00287
00288
00289 args.monitor_enabled = 1;
00290 return 0;
00291 }
00292
00293 static int load_config(int startup)
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
00313 stun_close_sock();
00314 args.stun_poll_failed_gripe = 0;
00315
00316
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 }
00341
00342 static int __reload(int startup)
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 }
00358
00359 static int reload(void)
00360 {
00361 return __reload(0);
00362 }
00363
00364 static int unload_module(void)
00365 {
00366 stun_stop_monitor();
00367 ast_mutex_destroy(&args.lock);
00368 return 0;
00369 }
00370
00371 static int load_module(void)
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 }
00382
00383 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "STUN Network Monitor",
00384 .load = load_module,
00385 .unload = unload_module,
00386 .reload = reload,
00387 .load_pri = AST_MODPRI_CHANNEL_DEPEND
00388 );