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 <stdlib.h>
00031 #include <stdio.h>
00032 #include <string.h>
00033
00034 #include "chan_misdn_config.h"
00035
00036 #include <asterisk/config.h>
00037 #include <asterisk/channel.h>
00038 #include <asterisk/logger.h>
00039 #include <asterisk/lock.h>
00040 #include <asterisk/strings.h>
00041
00042 #include <asterisk/utils.h>
00043 #define AST_LOAD_CFG ast_config_load
00044 #define AST_DESTROY_CFG ast_config_destroy
00045
00046 #define DEF_ECHOCANCEL 128
00047 #define DEF_ECHOTRAINING 1
00048
00049 struct msn_list {
00050 char *msn;
00051 struct msn_list *next;
00052 };
00053
00054 struct port_config {
00055 char *name;
00056 int *rxgain;
00057 int *txgain;
00058 int *te_choose_channel;
00059 char *context;
00060 char *language;
00061 char *callerid;
00062 char *method;
00063 int *dialplan;
00064 int *localdialplan;
00065 char *nationalprefix;
00066 char *internationalprefix;
00067 int *pres;
00068 int *always_immediate;
00069 int *immediate;
00070 int *hold_allowed;
00071 int *early_bconnect;
00072 int *use_callingpres;
00073 int *echocancel;
00074 int *echocancelwhenbridged;
00075 int *echotraining;
00076 struct msn_list *msn_list;
00077 ast_group_t *callgroup;
00078 ast_group_t *pickupgroup;
00079 };
00080
00081 struct general_config {
00082 int *debug;
00083 char *tracefile;
00084 int *trace_calls;
00085 char *trace_dir;
00086 int *bridging;
00087 int *stop_tone_after_first_digit;
00088 int *append_digits2exten;
00089 int *l1_info_ok;
00090 int *clear_l3;
00091 int *dynamic_crypt;
00092 char *crypt_prefix;
00093 char *crypt_keys;
00094 };
00095
00096
00097 static struct port_config **port_cfg;
00098
00099 static int max_ports;
00100
00101 static struct general_config *general_cfg;
00102
00103 static int *ptp;
00104
00105 static ast_mutex_t config_mutex;
00106
00107
00108 static inline void misdn_cfg_lock (void) {
00109 ast_mutex_lock(&config_mutex);
00110 }
00111
00112 static inline void misdn_cfg_unlock (void) {
00113 ast_mutex_unlock(&config_mutex);
00114 }
00115
00116 static void free_msn_list (struct msn_list* iter) {
00117 if (iter->next)
00118 free_msn_list(iter->next);
00119 if (iter->msn)
00120 free(iter->msn);
00121 free(iter);
00122 }
00123
00124 static void free_port_cfg (void) {
00125
00126 struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
00127
00128 int i, j;
00129
00130 for (i = 0; i < max_ports; i++) {
00131 if (port_cfg[i]) {
00132 for (j = 0; j < max_ports && free_list[j]; j++) {
00133 if (free_list[j] && free_list[j] == port_cfg[i])
00134 continue;
00135 free_list[j] = port_cfg[i];
00136 }
00137 }
00138 }
00139
00140 #define FREE_ELEM(elem) ({ \
00141 if (free_list[i]->elem) \
00142 free(free_list[i]->elem); \
00143 })
00144
00145 for (i = 0; i < max_ports; i++) {
00146 if (free_list[i]) {
00147 FREE_ELEM(name);
00148 FREE_ELEM(rxgain);
00149 FREE_ELEM(txgain);
00150 FREE_ELEM(te_choose_channel);
00151 FREE_ELEM(context);
00152 FREE_ELEM(language);
00153 FREE_ELEM(callerid);
00154 FREE_ELEM(method);
00155 FREE_ELEM(dialplan);
00156 FREE_ELEM(localdialplan);
00157 FREE_ELEM(nationalprefix);
00158 FREE_ELEM(internationalprefix);
00159 FREE_ELEM(pres);
00160 FREE_ELEM(always_immediate);
00161 FREE_ELEM(immediate);
00162 FREE_ELEM(hold_allowed);
00163 FREE_ELEM(early_bconnect);
00164 FREE_ELEM(use_callingpres);
00165 FREE_ELEM(echocancel);
00166 FREE_ELEM(echocancelwhenbridged);
00167 FREE_ELEM(echotraining);
00168 if (free_list[i]->msn_list)
00169 free_msn_list(free_list[i]->msn_list);
00170 FREE_ELEM(callgroup);
00171 FREE_ELEM(pickupgroup);
00172 free(free_list[i]);
00173 }
00174 }
00175 free(free_list);
00176 }
00177
00178 static void free_general_cfg (void) {
00179
00180 #define FREE_GEN_ELEM(elem) ({ \
00181 if (general_cfg->elem) \
00182 free(general_cfg->elem); \
00183 })
00184
00185 FREE_GEN_ELEM(debug);
00186 FREE_GEN_ELEM(tracefile);
00187 FREE_GEN_ELEM(trace_calls);
00188 FREE_GEN_ELEM(trace_dir);
00189 FREE_GEN_ELEM(bridging);
00190 FREE_GEN_ELEM(stop_tone_after_first_digit);
00191 FREE_GEN_ELEM(append_digits2exten);
00192 FREE_GEN_ELEM(l1_info_ok);
00193 FREE_GEN_ELEM(clear_l3);
00194 FREE_GEN_ELEM(dynamic_crypt);
00195 FREE_GEN_ELEM(crypt_prefix);
00196 FREE_GEN_ELEM(crypt_keys);
00197 }
00198
00199 #define GET_PORTCFG_STRCPY(item) ({ \
00200 char *temp; \
00201 if (port_cfg[port] && port_cfg[port]->item) \
00202 temp = port_cfg[port]->item; \
00203 else \
00204 temp = port_cfg[0]->item; \
00205 if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \
00206 memset(buf, 0, 1); \
00207 })
00208
00209 #define GET_GENCFG_STRCPY(item) ({ \
00210 if (general_cfg && general_cfg->item) { \
00211 if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \
00212 memset(buf, 0, 1); \
00213 } else \
00214 memset(buf, 0, 1); \
00215 })
00216
00217 #define GET_PORTCFG_MEMCPY(item) ({ \
00218 typeof(port_cfg[0]->item) temp; \
00219 if (port_cfg[port] && port_cfg[port]->item) \
00220 temp = port_cfg[port]->item; \
00221 else \
00222 temp = port_cfg[0]->item; \
00223 if (temp) { \
00224 int l = sizeof(*temp); \
00225 if (l > bufsize) \
00226 memset(buf, 0, bufsize); \
00227 else \
00228 memcpy(buf, temp, l); \
00229 } else \
00230 memset(buf, 0, bufsize); \
00231 })
00232
00233 #define GET_GENCFG_MEMCPY(item) ({ \
00234 if (general_cfg && general_cfg->item) { \
00235 typeof(general_cfg->item) temp = general_cfg->item; \
00236 int l = sizeof(*temp); \
00237 if (l > bufsize) \
00238 memset(buf, 0, bufsize); \
00239 else \
00240 memcpy(buf, temp, l); \
00241 } else \
00242 memset(buf, 0, bufsize); \
00243 })
00244
00245 void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) {
00246
00247 if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
00248 memset(buf, 0, bufsize);
00249 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
00250 return;
00251 }
00252
00253 misdn_cfg_lock();
00254
00255 switch (elem) {
00256
00257
00258
00259 case MISDN_CFG_PTP: if (sizeof(ptp[port]) <= bufsize)
00260 memcpy(buf, &ptp[port], sizeof(ptp[port]));
00261 else
00262 buf = 0;
00263 break;
00264 case MISDN_CFG_GROUPNAME: GET_PORTCFG_STRCPY(name);
00265 break;
00266 case MISDN_CFG_RXGAIN: GET_PORTCFG_MEMCPY(rxgain);
00267 break;
00268 case MISDN_CFG_TXGAIN: GET_PORTCFG_MEMCPY(txgain);
00269 break;
00270 case MISDN_CFG_TE_CHOOSE_CHANNEL:
00271 GET_PORTCFG_MEMCPY(te_choose_channel);
00272 break;
00273 case MISDN_CFG_CONTEXT: GET_PORTCFG_STRCPY(context);
00274 break;
00275 case MISDN_CFG_LANGUAGE: GET_PORTCFG_STRCPY(language);
00276 break;
00277 case MISDN_CFG_CALLERID: GET_PORTCFG_STRCPY(callerid);
00278 break;
00279 case MISDN_CFG_METHOD: GET_PORTCFG_STRCPY(method);
00280 break;
00281 case MISDN_CFG_DIALPLAN: GET_PORTCFG_MEMCPY(dialplan);
00282 break;
00283 case MISDN_CFG_LOCALDIALPLAN: GET_PORTCFG_MEMCPY(localdialplan);
00284 break;
00285 case MISDN_CFG_NATPREFIX: GET_PORTCFG_STRCPY(nationalprefix);
00286 break;
00287 case MISDN_CFG_INTERNATPREFIX:
00288 GET_PORTCFG_STRCPY(internationalprefix);
00289 break;
00290 case MISDN_CFG_PRES: GET_PORTCFG_MEMCPY(pres);
00291 break;
00292 case MISDN_CFG_ALWAYS_IMMEDIATE:
00293 GET_PORTCFG_MEMCPY(always_immediate);
00294 break;
00295 case MISDN_CFG_IMMEDIATE: GET_PORTCFG_MEMCPY(immediate);
00296 break;
00297 case MISDN_CFG_HOLD_ALLOWED:
00298 GET_PORTCFG_MEMCPY(hold_allowed);
00299 break;
00300 case MISDN_CFG_EARLY_BCONNECT:
00301 GET_PORTCFG_MEMCPY(early_bconnect);
00302 break;
00303 case MISDN_CFG_USE_CALLINGPRES:
00304 GET_PORTCFG_MEMCPY(use_callingpres);
00305 break;
00306 case MISDN_CFG_ECHOCANCEL:
00307 GET_PORTCFG_MEMCPY(echocancel );
00308 break;
00309 case MISDN_CFG_ECHOCANCELWHENBRIDGED:
00310 GET_PORTCFG_MEMCPY(echocancelwhenbridged);
00311 break;
00312 case MISDN_CFG_ECHOTRAINING:
00313 GET_PORTCFG_MEMCPY(echotraining);
00314 break;
00315 case MISDN_CFG_CALLGROUP: GET_PORTCFG_MEMCPY(callgroup);
00316 break;
00317 case MISDN_CFG_PICKUPGROUP: GET_PORTCFG_MEMCPY(pickupgroup);
00318 break;
00319
00320
00321
00322 case MISDN_GEN_DEBUG: GET_GENCFG_MEMCPY(debug);
00323 break;
00324 case MISDN_GEN_TRACEFILE: GET_GENCFG_STRCPY(tracefile);
00325 break;
00326 case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls);
00327 break;
00328 case MISDN_GEN_TRACE_DIR: GET_GENCFG_STRCPY(trace_dir);
00329 break;
00330 case MISDN_GEN_BRIDGING: GET_GENCFG_MEMCPY(bridging);
00331 break;
00332 case MISDN_GEN_STOP_TONE: GET_GENCFG_MEMCPY(stop_tone_after_first_digit);
00333 break;
00334 case MISDN_GEN_APPEND_DIGITS2EXTEN:
00335 GET_GENCFG_MEMCPY(append_digits2exten);
00336 break;
00337 case MISDN_GEN_L1_INFO_OK: GET_GENCFG_MEMCPY(l1_info_ok);
00338 break;
00339 case MISDN_GEN_CLEAR_L3: GET_GENCFG_MEMCPY(clear_l3);
00340 break;
00341 case MISDN_GEN_DYNAMIC_CRYPT: GET_GENCFG_MEMCPY(dynamic_crypt);
00342 break;
00343 case MISDN_GEN_CRYPT_PREFIX: GET_GENCFG_STRCPY(crypt_prefix);
00344 break;
00345 case MISDN_GEN_CRYPT_KEYS: GET_GENCFG_STRCPY(crypt_keys);
00346 break;
00347 default: memset(buf, 0, bufsize);
00348 }
00349
00350 misdn_cfg_unlock();
00351 }
00352
00353 int misdn_cfg_is_msn_valid (int port, char* msn) {
00354
00355 if (!misdn_cfg_is_port_valid(port)) {
00356 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
00357 return 0;
00358 }
00359
00360 struct msn_list *iter;
00361
00362 misdn_cfg_lock();
00363
00364 if (port_cfg[port]->msn_list)
00365 iter = port_cfg[port]->msn_list;
00366 else
00367 iter = port_cfg[0]->msn_list;
00368 for (; iter; iter = iter->next)
00369 if (*(iter->msn) == '*' || !strcasecmp(iter->msn, msn)) {
00370 misdn_cfg_unlock();
00371 return 1;
00372 }
00373
00374 misdn_cfg_unlock();
00375
00376 return 0;
00377 }
00378
00379 int misdn_cfg_is_port_valid (int port) {
00380
00381 misdn_cfg_lock();
00382
00383 if (port < 1 || port > max_ports) {
00384 misdn_cfg_unlock();
00385 return 0;
00386 }
00387
00388 int valid = (port_cfg[port] != NULL);
00389
00390 misdn_cfg_unlock();
00391
00392 return valid;
00393 }
00394
00395 int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) {
00396
00397 int i, re = 0;
00398 char *method = NULL;
00399
00400 misdn_cfg_lock();
00401
00402 for (i = 0; i < max_ports; i++) {
00403 if (port_cfg[i]) {
00404 if (!strcasecmp(port_cfg[i]->name, group))
00405 method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method;
00406 }
00407 }
00408
00409 if (method) {
00410 switch (meth) {
00411 case METHOD_STANDARD: re = !strcasecmp(method, "standard");
00412 break;
00413 case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
00414 break;
00415 }
00416 }
00417
00418 misdn_cfg_unlock();
00419
00420 return re;
00421 }
00422
00423 void misdn_cfg_get_ports_string (char *ports) {
00424 *ports = 0;
00425 char tmp[16];
00426 int l;
00427
00428 misdn_cfg_lock();
00429
00430 int i = 1;
00431 for (; i <= max_ports; i++) {
00432 if (port_cfg[i]) {
00433 if (ptp[i])
00434 sprintf(tmp, "%dptp,", i);
00435 else
00436 sprintf(tmp, "%d,", i);
00437 strcat(ports, tmp);
00438 }
00439 }
00440
00441 misdn_cfg_unlock();
00442
00443 if ((l = strlen(ports)))
00444 ports[l-1] = 0;
00445 }
00446
00447 #define GET_CFG_STRING(typestr, type) ({ \
00448 if (port_cfg[port] && port_cfg[port]->type) \
00449 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \
00450 else \
00451 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \
00452 }) \
00453
00454 #define GET_GEN_STRING(typestr, type) ({ \
00455 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \
00456 }) \
00457
00458 #define GET_CFG_INT(typestr, type) ({ \
00459 if (port_cfg[port] && port_cfg[port]->type) \
00460 snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \
00461 else \
00462 snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \
00463 }) \
00464
00465 #define GET_GEN_INT(typestr, type) ({ \
00466 snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \
00467 }) \
00468
00469 #define GET_CFG_BOOL(typestr, type, yes, no) ({ \
00470 int bool; \
00471 if (port_cfg[port] && port_cfg[port]->type) \
00472 bool = *port_cfg[port]->type; \
00473 else \
00474 bool = *port_cfg[0]->type; \
00475 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
00476 }) \
00477
00478 #define GET_CFG_HYBRID(typestr, type, yes, no) ({ \
00479 int bool; \
00480 if (port_cfg[port] && port_cfg[port]->type) \
00481 bool = *port_cfg[port]->type; \
00482 else \
00483 bool = *port_cfg[0]->type; \
00484 if (bool == 1 || bool == 0) \
00485 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
00486 else \
00487 snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \
00488 }) \
00489
00490 #define GET_GEN_BOOL(typestr, type, yes, no) ({ \
00491 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \
00492 }) \
00493
00494 #define GET_CFG_AST_GROUP_T(typestr, type) ({ \
00495 ast_group_t *tmp; \
00496 if (port_cfg[port] && port_cfg[port]->type) \
00497 tmp = port_cfg[port]->type; \
00498 else \
00499 tmp = port_cfg[0]->type; \
00500 if (tmp) { \
00501 char tmpbuf[256]; \
00502 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \
00503 } else \
00504 snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \
00505 }) \
00506
00507 void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) {
00508
00509 if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
00510 *buf = 0;
00511 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
00512 return;
00513 }
00514
00515 char begin[] = " -> ";
00516
00517 misdn_cfg_lock();
00518
00519 switch (elem) {
00520
00521 case MISDN_CFG_PTP: snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no");
00522 break;
00523 case MISDN_CFG_GROUPNAME: GET_CFG_STRING(GROUPNAME, name);
00524 break;
00525 case MISDN_CFG_RXGAIN: GET_CFG_INT(RXGAIN, rxgain);
00526 break;
00527 case MISDN_CFG_TXGAIN: GET_CFG_INT(TXGAIN, txgain);
00528 break;
00529 case MISDN_CFG_TE_CHOOSE_CHANNEL:
00530 GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no);
00531 break;
00532 case MISDN_CFG_CONTEXT: GET_CFG_STRING(CONTEXT, context);
00533 break;
00534 case MISDN_CFG_LANGUAGE: GET_CFG_STRING(LANGUAGE, language);
00535 break;
00536 case MISDN_CFG_CALLERID: GET_CFG_STRING(CALLERID, callerid);
00537 break;
00538 case MISDN_CFG_METHOD: GET_CFG_STRING(METHOD, method);
00539 break;
00540 case MISDN_CFG_DIALPLAN: GET_CFG_INT(DIALPLAN, dialplan);
00541 break;
00542 case MISDN_CFG_LOCALDIALPLAN: GET_CFG_INT(LOCALDIALPLAN, localdialplan);
00543 break;
00544 case MISDN_CFG_NATPREFIX: GET_CFG_STRING(NATIONALPREFIX, nationalprefix);
00545 break;
00546 case MISDN_CFG_INTERNATPREFIX:
00547 GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix);
00548 break;
00549 case MISDN_CFG_PRES: GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened);
00550 break;
00551 case MISDN_CFG_ALWAYS_IMMEDIATE:
00552 GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no);
00553 break;
00554 case MISDN_CFG_IMMEDIATE: GET_CFG_BOOL(IMMEDIATE, immediate, yes, no);
00555 break;
00556 case MISDN_CFG_HOLD_ALLOWED:
00557 GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no);
00558 break;
00559 case MISDN_CFG_EARLY_BCONNECT:
00560 GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no);
00561 break;
00562 case MISDN_CFG_USE_CALLINGPRES:
00563 GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no);
00564 break;
00565 case MISDN_CFG_ECHOCANCEL: GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no);
00566 break;
00567 case MISDN_CFG_ECHOCANCELWHENBRIDGED:
00568 GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no);
00569 break;
00570 case MISDN_CFG_ECHOTRAINING:
00571 GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no);
00572 break;
00573 case MISDN_CFG_CALLGROUP: GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup);
00574 break;
00575 case MISDN_CFG_PICKUPGROUP: GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup);
00576 break;
00577 case MISDN_CFG_MSNS: {
00578 char tmpbuffer[BUFFERSIZE];
00579 tmpbuffer[0] = 0;
00580 struct msn_list *iter;
00581 if (port_cfg[port]->msn_list)
00582 iter = port_cfg[port]->msn_list;
00583 else
00584 iter = port_cfg[0]->msn_list;
00585 if (iter) {
00586 for (; iter; iter = iter->next)
00587 sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn);
00588 tmpbuffer[strlen(tmpbuffer)-2] = 0;
00589 }
00590 snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \
00591 }
00592 break;
00593
00594
00595
00596 case MISDN_GEN_DEBUG: GET_GEN_INT(DEBUG_LEVEL, debug);
00597 break;
00598 case MISDN_GEN_TRACEFILE: GET_GEN_STRING(TRACEFILE, tracefile);
00599 break;
00600 case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false);
00601 break;
00602 case MISDN_GEN_TRACE_DIR: GET_GEN_STRING(TRACE_DIR, trace_dir);
00603 break;
00604 case MISDN_GEN_BRIDGING: GET_GEN_BOOL(BRIDGING, bridging, yes, no);
00605 break;
00606 case MISDN_GEN_STOP_TONE: GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no);
00607 break;
00608 case MISDN_GEN_APPEND_DIGITS2EXTEN:
00609 GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no);
00610 break;
00611 case MISDN_GEN_L1_INFO_OK: GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no);
00612 break;
00613 case MISDN_GEN_CLEAR_L3: GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no);
00614 break;
00615 case MISDN_GEN_DYNAMIC_CRYPT:
00616 GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no);
00617 break;
00618 case MISDN_GEN_CRYPT_PREFIX:
00619 GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix);
00620 break;
00621 case MISDN_GEN_CRYPT_KEYS: GET_GEN_STRING(CRYPT_KEYS, crypt_keys);
00622 break;
00623
00624 default: *buf = 0;
00625 break;
00626 }
00627
00628 misdn_cfg_unlock();
00629 }
00630
00631 int misdn_cfg_get_next_port (int port) {
00632
00633 misdn_cfg_lock();
00634
00635 for (port++; port <= max_ports; port++) {
00636 if (port_cfg[port]) {
00637 misdn_cfg_unlock();
00638 return port;
00639 }
00640 }
00641
00642 misdn_cfg_unlock();
00643
00644 return -1;
00645 }
00646
00647 int misdn_cfg_get_next_port_spin (int port) {
00648
00649 int ret = misdn_cfg_get_next_port(port);
00650
00651 if (ret > 0)
00652 return ret;
00653
00654 return misdn_cfg_get_next_port(0);
00655 }
00656
00657 #define PARSE_GEN_INT(item) ({ \
00658 if (!strcasecmp(v->name, #item)) { \
00659 int temp; \
00660 if (!sscanf(v->value, "%d", &temp)) { \
00661 ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" (generals section) invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value); \
00662 } else { \
00663 general_cfg->item = (int *)malloc(sizeof(int)); \
00664 memcpy(general_cfg->item, &temp, sizeof(int)); \
00665 } \
00666 continue; \
00667 } \
00668 }) \
00669
00670 #define PARSE_GEN_BOOL(item) ({ \
00671 if (!strcasecmp(v->name, #item)) { \
00672 general_cfg->item = (int *)malloc(sizeof(int)); \
00673 *(general_cfg->item) = ast_true(v->value)?1:0; \
00674 continue; \
00675 } \
00676 })
00677
00678 #define PARSE_GEN_STR(item) ({ \
00679 if (!strcasecmp(v->name, #item)) { \
00680 int l = strlen(v->value); \
00681 if (l) { \
00682 general_cfg->item = (char *)calloc(l+1, sizeof(char)); \
00683 strncpy(general_cfg->item,v->value, l); \
00684 } \
00685 continue; \
00686 } \
00687 })
00688
00689 static void build_general_config(struct ast_variable *v) {
00690
00691 if (!v)
00692 return;
00693
00694 for (; v; v = v->next) {
00695
00696 PARSE_GEN_INT(debug);
00697 PARSE_GEN_STR(tracefile);
00698 PARSE_GEN_BOOL(trace_calls);
00699 PARSE_GEN_STR(trace_dir);
00700 PARSE_GEN_BOOL(bridging);
00701 PARSE_GEN_BOOL(stop_tone_after_first_digit);
00702 PARSE_GEN_BOOL(append_digits2exten);
00703 PARSE_GEN_BOOL(l1_info_ok);
00704 PARSE_GEN_BOOL(clear_l3);
00705 PARSE_GEN_BOOL(dynamic_crypt);
00706 PARSE_GEN_STR(crypt_prefix);
00707 PARSE_GEN_STR(crypt_keys);
00708
00709 }
00710 }
00711
00712 #define PARSE_CFG_HYBRID(item, def) ({ \
00713 if (!strcasecmp(v->name, #item)) { \
00714 new->item = (int *)malloc(sizeof(int)); \
00715 if (!sscanf(v->value, "%d", new->item)) { \
00716 if (ast_true(v->value)) \
00717 *new->item = def; \
00718 else \
00719 *new->item = 0; \
00720 } \
00721 continue; \
00722 } \
00723 }) \
00724
00725 #define PARSE_CFG_INT(item) ({ \
00726 if (!strcasecmp(v->name, #item)) { \
00727 new->item = (int *)malloc(sizeof(int)); \
00728 if (!sscanf(v->value, "%d", new->item)) { \
00729 ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" of group \"%s\" invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value, cat); \
00730 free(new->item); \
00731 new->item = NULL; \
00732 } \
00733 continue; \
00734 } \
00735 }) \
00736
00737 #define PARSE_CFG_BOOL(item) ({ \
00738 if (!strcasecmp(v->name, #item)) { \
00739 new->item = (int *)malloc(sizeof(int)); \
00740 *(new->item) = ast_true(v->value)?1:0; \
00741 continue; \
00742 } \
00743 })
00744
00745 #define PARSE_CFG_STR(item) ({ \
00746 if (!strcasecmp(v->name, #item)) { \
00747 int l = strlen(v->value); \
00748 if (l) { \
00749 new->item = (char *)calloc(l+1, sizeof(char)); \
00750 strncpy(new->item,v->value,l); \
00751 } \
00752 continue; \
00753 } \
00754 })
00755
00756 static void build_port_config(struct ast_variable *v, char *cat) {
00757 if (!v || !cat)
00758 return;
00759
00760 int cfg_for_ports[max_ports + 1];
00761 int i = 0;
00762 for (; i < (max_ports + 1); i++) {
00763 cfg_for_ports[i] = 0;
00764 }
00765
00766
00767 if (!strcasecmp(cat, "default")) {
00768 cfg_for_ports[0] = 1;
00769 }
00770
00771 struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config));
00772
00773 {
00774 int l = strlen(cat);
00775 new->name = (char *)calloc(l+1, sizeof(char));
00776 strncpy(new->name, cat, l);
00777 }
00778
00779 for (; v; v=v->next) {
00780 if (!strcasecmp(v->name, "ports")) {
00781
00782 char *iter;
00783 char *value = v->value;
00784 while ((iter = strchr(value, ',')) != NULL) {
00785 *iter = 0;
00786
00787 while (*value && *value == ' ') {
00788 value++;
00789 }
00790
00791
00792 if (*value){
00793 int p = atoi(value);
00794 if (p <= max_ports && p > 0) {
00795 cfg_for_ports[p] = 1;
00796 if (strstr(value, "ptp"))
00797 ptp[p] = 1;
00798 } else
00799 ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
00800 value = ++iter;
00801 }
00802 }
00803
00804
00805 while (*value && *value == ' ') {
00806 value++;
00807 }
00808
00809 if (*value) {
00810 int p = atoi(value);
00811 if (p <= max_ports && p > 0) {
00812 cfg_for_ports[p] = 1;
00813 if (strstr(value, "ptp"))
00814 ptp[p] = 1;
00815 } else
00816 ast_log(LOG_WARNING, "Port value \"%s\" of group %s invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat);
00817 }
00818 continue;
00819 }
00820 PARSE_CFG_STR(context);
00821 PARSE_CFG_INT(dialplan);
00822 PARSE_CFG_INT(localdialplan);
00823 PARSE_CFG_STR(nationalprefix);
00824 PARSE_CFG_STR(internationalprefix);
00825 PARSE_CFG_STR(language);
00826 if (!strcasecmp(v->name, "presentation")) {
00827 if (v->value && strlen(v->value)) {
00828 new->pres = (int *)malloc(sizeof(int));
00829 if (!strcasecmp(v->value, "allowed")) {
00830 *(new->pres) = 1;
00831 }
00832
00833 else {
00834 *(new->pres) = 0;
00835 }
00836 }
00837 continue;
00838 }
00839 PARSE_CFG_INT(rxgain);
00840 PARSE_CFG_INT(txgain);
00841 PARSE_CFG_BOOL(te_choose_channel);
00842 PARSE_CFG_BOOL(immediate);
00843 PARSE_CFG_BOOL(always_immediate);
00844 PARSE_CFG_BOOL(hold_allowed);
00845 PARSE_CFG_BOOL(early_bconnect);
00846 PARSE_CFG_BOOL(use_callingpres);
00847 PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL);
00848 PARSE_CFG_BOOL(echocancelwhenbridged);
00849 PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING);
00850 PARSE_CFG_STR(callerid);
00851 PARSE_CFG_STR(method);
00852 if (!strcasecmp(v->name, "msns")) {
00853
00854 char *iter;
00855 char *value = v->value;
00856
00857 while ((iter = strchr(value, ',')) != NULL) {
00858 *iter = 0;
00859
00860 while (*value && *value == ' ') {
00861 value++;
00862 }
00863
00864 if (*value){
00865 int l = strlen(value);
00866 if (l) {
00867 struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
00868 ml->msn = (char *)calloc(l+1, sizeof(char));
00869 strncpy(ml->msn,value,l);
00870 ml->next = new->msn_list;
00871 new->msn_list = ml;
00872 }
00873 value = ++iter;
00874 }
00875 }
00876
00877
00878 while (*value && *value == ' ') {
00879 value++;
00880 }
00881
00882 if (*value) {
00883 int l = strlen(value);
00884 if (l) {
00885 struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
00886 ml->msn = (char *)calloc(l+1, sizeof(char));
00887 strncpy(ml->msn,value,l);
00888 ml->next = new->msn_list;
00889 new->msn_list = ml;
00890 }
00891 }
00892 continue;
00893 }
00894 if (!strcasecmp(v->name, "callgroup")) {
00895 new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
00896 *(new->callgroup)=ast_get_group(v->value);
00897 continue;
00898 }
00899 if (!strcasecmp(v->name, "pickupgroup")) {
00900 new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
00901 *(new->pickupgroup)=ast_get_group(v->value);
00902 continue;
00903 }
00904 }
00905
00906 for (i = 0; i < (max_ports + 1); i++) {
00907 if (cfg_for_ports[i])
00908 port_cfg[i] = new;
00909 }
00910 }
00911
00912
00913 static void fill_defaults (void) {
00914
00915
00916 if (!general_cfg->debug)
00917 general_cfg->debug = (int*)calloc(1, sizeof(int));
00918 if (!general_cfg->trace_calls)
00919 general_cfg->trace_calls = (int*)calloc(1, sizeof(int));
00920 if (!general_cfg->trace_dir) {
00921 general_cfg->trace_dir = (char *)malloc(10 * sizeof(char));
00922 sprintf(general_cfg->trace_dir, "/var/log/");
00923 }
00924 if (!general_cfg->bridging) {
00925 general_cfg->bridging = (int*)malloc(sizeof(int));
00926 *general_cfg->bridging = 1;
00927 }
00928 if (!general_cfg->stop_tone_after_first_digit) {
00929 general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int));
00930 *general_cfg->stop_tone_after_first_digit = 1;
00931 }
00932 if (!general_cfg->append_digits2exten) {
00933 general_cfg->append_digits2exten = (int*)malloc(sizeof(int));
00934 *general_cfg->append_digits2exten = 1;
00935 }
00936 if (!general_cfg->l1_info_ok) {
00937 general_cfg->l1_info_ok = (int*)malloc(sizeof(int));
00938 *general_cfg->l1_info_ok = 1;
00939 }
00940 if (!general_cfg->clear_l3)
00941 general_cfg->clear_l3 =(int*)calloc(1, sizeof(int));
00942 if (!general_cfg->dynamic_crypt)
00943 general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int));
00944
00945
00946 if (!port_cfg[0])
00947 port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config));
00948 if (!port_cfg[0]->name) {
00949 port_cfg[0]->name = (char *)malloc(8 * sizeof(char));
00950 sprintf(port_cfg[0]->name, "default");
00951 }
00952 if (!port_cfg[0]->rxgain)
00953 port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int));
00954 if (!port_cfg[0]->txgain)
00955 port_cfg[0]->txgain = (int *)calloc(1, sizeof(int));
00956 if (!port_cfg[0]->te_choose_channel)
00957 port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int));
00958 if (!port_cfg[0]->context) {
00959 port_cfg[0]->context = (char *)malloc(8 * sizeof(char));
00960 sprintf(port_cfg[0]->context, "default");
00961 }
00962 if (!port_cfg[0]->language) {
00963 port_cfg[0]->language = (char *)malloc(3 * sizeof(char));
00964 sprintf(port_cfg[0]->language, "en");
00965 }
00966 if (!port_cfg[0]->callerid)
00967 port_cfg[0]->callerid = (char *)calloc(1, sizeof(char));
00968 if (!port_cfg[0]->method) {
00969 port_cfg[0]->method = (char *)malloc(9 * sizeof(char));
00970 sprintf(port_cfg[0]->method, "standard");
00971 }
00972 if (!port_cfg[0]->dialplan)
00973 port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int));
00974 if (!port_cfg[0]->localdialplan)
00975 port_cfg[0]->localdialplan = (int *)calloc(1, sizeof(int));
00976 if (!port_cfg[0]->nationalprefix) {
00977 port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char));
00978 sprintf(port_cfg[0]->nationalprefix, "0");
00979 }
00980 if (!port_cfg[0]->internationalprefix) {
00981 port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char));
00982 sprintf(port_cfg[0]->internationalprefix, "00");
00983 }
00984 if (!port_cfg[0]->pres) {
00985 port_cfg[0]->pres = (int *)malloc(sizeof(int));
00986 *port_cfg[0]->pres = 1;
00987 }
00988 if (!port_cfg[0]->always_immediate)
00989 port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int));
00990 if (!port_cfg[0]->immediate)
00991 port_cfg[0]->immediate = (int *)calloc(1, sizeof(int));
00992 if (!port_cfg[0]->hold_allowed)
00993 port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int));
00994 if (!port_cfg[0]->early_bconnect) {
00995 port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int));
00996 *port_cfg[0]->early_bconnect = 1;
00997 }
00998 if (!port_cfg[0]->echocancel)
00999 port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int));
01000 if (!port_cfg[0]->echocancelwhenbridged)
01001 port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int));
01002 if (!port_cfg[0]->echotraining) {
01003 port_cfg[0]->echotraining=(int *)malloc(sizeof(int));
01004 *port_cfg[0]->echotraining = 1;
01005 }
01006 if (!port_cfg[0]->use_callingpres) {
01007 port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int));
01008 *port_cfg[0]->use_callingpres = 1;
01009 }
01010 if (!port_cfg[0]->msn_list) {
01011 port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list));
01012 port_cfg[0]->msn_list->next = NULL;
01013 port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char));
01014 *(port_cfg[0]->msn_list->msn) = '*';
01015 }
01016 }
01017
01018 void misdn_cfg_reload (void) {
01019 misdn_cfg_init (0);
01020 }
01021
01022 void misdn_cfg_destroy (void) {
01023
01024 misdn_cfg_lock();
01025
01026 free_port_cfg();
01027 free_general_cfg();
01028
01029 free(port_cfg);
01030 free(general_cfg);
01031 free(ptp);
01032
01033 misdn_cfg_unlock();
01034 ast_mutex_destroy(&config_mutex);
01035 }
01036
01037 void misdn_cfg_init (int this_max_ports)
01038 {
01039 char config[]="misdn.conf";
01040
01041 struct ast_config *cfg;
01042 cfg = AST_LOAD_CFG(config);
01043 if (!cfg) {
01044 ast_log(LOG_WARNING,"no misdn.conf ?\n");
01045 return;
01046 }
01047
01048 misdn_cfg_lock();
01049
01050 if (this_max_ports) {
01051
01052 max_ports = this_max_ports;
01053 port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
01054 general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config));
01055 ptp = (int *)calloc(max_ports + 1, sizeof(int));
01056 }
01057 else {
01058 free_port_cfg();
01059 free_general_cfg();
01060 port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1));
01061 general_cfg = memset(general_cfg, 0, sizeof(struct general_config));
01062 ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1));
01063 }
01064
01065 char *cat;
01066 cat = ast_category_browse(cfg, NULL);
01067
01068 while(cat) {
01069 struct ast_variable *v=ast_variable_browse(cfg,cat);
01070 if (!strcasecmp(cat,"general")) {
01071 build_general_config (v);
01072 } else {
01073 build_port_config (v, cat);
01074 }
01075 cat=ast_category_browse(cfg,cat);
01076 }
01077
01078 fill_defaults();
01079
01080 misdn_cfg_unlock();
01081
01082 AST_DESTROY_CFG(cfg);
01083 }