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 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <errno.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/pbx.h>
00041 #include <asterisk/strings.h>
00042 #include <asterisk/utils.h>
00043
00044 #define AST_LOAD_CFG ast_config_load
00045 #define AST_DESTROY_CFG ast_config_destroy
00046
00047 #define NO_DEFAULT "<>"
00048 #define NONE 0
00049
00050 #define GEN_CFG 1
00051 #define PORT_CFG 2
00052 #define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
00053 #define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
00054
00055 enum misdn_cfg_type {
00056 MISDN_CTYPE_STR,
00057 MISDN_CTYPE_INT,
00058 MISDN_CTYPE_BOOL,
00059 MISDN_CTYPE_BOOLINT,
00060 MISDN_CTYPE_MSNLIST,
00061 MISDN_CTYPE_ASTGROUP
00062 };
00063
00064 struct msn_list {
00065 char *msn;
00066 struct msn_list *next;
00067 };
00068
00069 union misdn_cfg_pt {
00070 char *str;
00071 int *num;
00072 struct msn_list *ml;
00073 ast_group_t *grp;
00074 void *any;
00075 };
00076
00077 struct misdn_cfg_spec {
00078 char name[BUFFERSIZE];
00079 enum misdn_cfg_elements elem;
00080 enum misdn_cfg_type type;
00081 char def[BUFFERSIZE];
00082 int boolint_def;
00083 };
00084
00085 static const struct misdn_cfg_spec port_spec[] = {
00086 { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE },
00087 { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE },
00088 { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE },
00089 { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE },
00090 { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE },
00091 { "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE },
00092 { "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "yes", NONE },
00093 { "reject_cause", MISDN_CFG_REJECT_CAUSE, MISDN_CTYPE_INT, "21", NONE },
00094 { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "yes", NONE },
00095 { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE },
00096 { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE },
00097 { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE },
00098 { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE },
00099 { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE },
00100 { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE },
00101 { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00102 { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00103 { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE },
00104 { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE },
00105 { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE },
00106 { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE },
00107 { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE },
00108 { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
00109 { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE },
00110 { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE },
00111 { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE },
00112 { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE },
00113 { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE },
00114 { "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE },
00115 { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 },
00116 { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE },
00117 { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE },
00118 { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE },
00119 { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
00120 { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE },
00121 { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE }
00122 };
00123
00124 static const struct misdn_cfg_spec gen_spec[] = {
00125 { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE },
00126 { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE },
00127 { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE },
00128 { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE },
00129 { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE },
00130 { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE },
00131 { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE },
00132 { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
00133 { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE },
00134 { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE },
00135 { "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE }
00136 };
00137
00138
00139 static union misdn_cfg_pt **port_cfg;
00140
00141 static int max_ports;
00142
00143 static union misdn_cfg_pt *general_cfg;
00144
00145 static int *ptp;
00146
00147 static int *map;
00148
00149 static ast_mutex_t config_mutex;
00150
00151 #define CLI_ERROR(name, value, section) ({ \
00152 ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
00153 "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
00154 })
00155
00156 static void _enum_array_map (void)
00157 {
00158 int i, j;
00159
00160 for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
00161 if (i == MISDN_CFG_PTP)
00162 continue;
00163 for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
00164 if (port_spec[j].elem == i) {
00165 map[i] = j;
00166 break;
00167 }
00168 }
00169 }
00170 for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
00171 for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
00172 if (gen_spec[j].elem == i) {
00173 map[i] = j;
00174 break;
00175 }
00176 }
00177 }
00178 }
00179
00180 static int get_cfg_position (char *name, int type)
00181 {
00182 int i;
00183
00184 switch (type) {
00185 case PORT_CFG:
00186 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00187 if (!strcasecmp(name, port_spec[i].name))
00188 return i;
00189 }
00190 break;
00191 case GEN_CFG:
00192 for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
00193 if (!strcasecmp(name, gen_spec[i].name))
00194 return i;
00195 }
00196 }
00197
00198 return -1;
00199 }
00200
00201 static inline void misdn_cfg_lock (void)
00202 {
00203 ast_mutex_lock(&config_mutex);
00204 }
00205
00206 static inline void misdn_cfg_unlock (void)
00207 {
00208 ast_mutex_unlock(&config_mutex);
00209 }
00210
00211 static void _free_msn_list (struct msn_list* iter)
00212 {
00213 if (iter->next)
00214 _free_msn_list(iter->next);
00215 if (iter->msn)
00216 free(iter->msn);
00217 free(iter);
00218 }
00219
00220 static void _free_port_cfg (void)
00221 {
00222 int i, j;
00223 int gn = map[MISDN_CFG_GROUPNAME];
00224 union misdn_cfg_pt* free_list[max_ports + 2];
00225
00226 memset(free_list, 0, sizeof(free_list));
00227 free_list[0] = port_cfg[0];
00228 for (i = 1; i <= max_ports; ++i) {
00229 if (port_cfg[i][gn].str) {
00230
00231 for (j = 1; j <= max_ports; ++j) {
00232 if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
00233 break;
00234 else if (!free_list[j]) {
00235 free_list[j] = port_cfg[i];
00236 break;
00237 }
00238 }
00239 }
00240 }
00241 for (j = 0; free_list[j]; ++j) {
00242 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00243 if (free_list[j][i].any) {
00244 if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
00245 _free_msn_list(free_list[j][i].ml);
00246 else
00247 free(free_list[j][i].any);
00248 }
00249 }
00250 }
00251 }
00252
00253 static void _free_general_cfg (void)
00254 {
00255 int i;
00256
00257 for (i = 0; i < NUM_GEN_ELEMENTS; i++)
00258 if (general_cfg[i].any)
00259 free(general_cfg[i].any);
00260 }
00261
00262 void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
00263 {
00264 int place;
00265
00266 if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00267 memset(buf, 0, bufsize);
00268 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
00269 return;
00270 }
00271
00272 misdn_cfg_lock();
00273 if (elem == MISDN_CFG_PTP) {
00274 if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
00275 memset(buf, 0, bufsize);
00276 } else {
00277 if ((place = map[elem]) < 0) {
00278 memset (buf, 0, bufsize);
00279 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
00280 } else {
00281 if (elem < MISDN_CFG_LAST) {
00282 switch (port_spec[place].type) {
00283 case MISDN_CTYPE_STR:
00284 if (port_cfg[port][place].str) {
00285 if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize))
00286 memset(buf, 0, 1);
00287 } else if (port_cfg[0][place].str) {
00288 if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize))
00289 memset(buf, 0, 1);
00290 }
00291 break;
00292 default:
00293 if (port_cfg[port][place].any)
00294 memcpy(buf, port_cfg[port][place].any, bufsize);
00295 else if (port_cfg[0][place].any)
00296 memcpy(buf, port_cfg[0][place].any, bufsize);
00297 else
00298 memset(buf, 0, bufsize);
00299 }
00300 } else {
00301 switch (gen_spec[place].type) {
00302 case MISDN_CTYPE_STR:
00303 if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize))
00304 memset(buf, 0, 1);
00305 break;
00306 default:
00307 if (general_cfg[place].any)
00308 memcpy(buf, general_cfg[place].any, bufsize);
00309 else
00310 memset(buf, 0, bufsize);
00311 }
00312 }
00313 }
00314 }
00315 misdn_cfg_unlock();
00316 }
00317
00318 int misdn_cfg_is_msn_valid (int port, char* msn)
00319 {
00320 int re = 0;
00321 struct msn_list *iter;
00322
00323 if (!misdn_cfg_is_port_valid(port)) {
00324 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
00325 return 0;
00326 }
00327
00328 misdn_cfg_lock();
00329 if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
00330 iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
00331 else
00332 iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
00333 for (; iter; iter = iter->next)
00334 if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
00335 re = 1;
00336 break;
00337 }
00338 misdn_cfg_unlock();
00339
00340 return re;
00341 }
00342
00343 int misdn_cfg_is_port_valid (int port)
00344 {
00345 return (port >= 1 && port <= max_ports);
00346 }
00347
00348 int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
00349 {
00350 int i, re = 0;
00351 char *method = NULL;
00352
00353 misdn_cfg_lock();
00354 for (i = 1; i <= max_ports; i++) {
00355 if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
00356 if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
00357 method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
00358 port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
00359 }
00360 }
00361 if (method) {
00362 switch (meth) {
00363 case METHOD_STANDARD: re = !strcasecmp(method, "standard");
00364 break;
00365 case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
00366 break;
00367 }
00368 }
00369 misdn_cfg_unlock();
00370
00371 return re;
00372 }
00373
00374 void misdn_cfg_get_ports_string (char *ports)
00375 {
00376 char tmp[16];
00377 int l, i;
00378 int gn = map[MISDN_CFG_GROUPNAME];
00379
00380 *ports = 0;
00381
00382 misdn_cfg_lock();
00383 for (i = 1; i <= max_ports; i++) {
00384 if (port_cfg[i][gn].str) {
00385 if (ptp[i])
00386 sprintf(tmp, "%dptp,", i);
00387 else
00388 sprintf(tmp, "%d,", i);
00389 strcat(ports, tmp);
00390 }
00391 }
00392 misdn_cfg_unlock();
00393
00394 if ((l = strlen(ports)))
00395 ports[l-1] = 0;
00396 }
00397
00398 void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
00399 {
00400 int place;
00401 char tempbuf[BUFFERSIZE] = "";
00402 struct msn_list *iter;
00403
00404 if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00405 *buf = 0;
00406 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
00407 return;
00408 }
00409
00410 place = map[elem];
00411
00412 misdn_cfg_lock();
00413 if (elem == MISDN_CFG_PTP) {
00414 snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
00415 }
00416 else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
00417 switch (port_spec[place].type) {
00418 case MISDN_CTYPE_INT:
00419 case MISDN_CTYPE_BOOLINT:
00420 if (port_cfg[port][place].num)
00421 snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
00422 else if (port_cfg[0][place].num)
00423 snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
00424 else
00425 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00426 break;
00427 case MISDN_CTYPE_BOOL:
00428 if (port_cfg[port][place].num)
00429 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
00430 else if (port_cfg[0][place].num)
00431 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
00432 else
00433 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00434 break;
00435 case MISDN_CTYPE_ASTGROUP:
00436 if (port_cfg[port][place].grp)
00437 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
00438 ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
00439 else if (port_cfg[0][place].grp)
00440 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
00441 ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
00442 else
00443 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00444 break;
00445 case MISDN_CTYPE_MSNLIST:
00446 if (port_cfg[port][place].ml)
00447 iter = port_cfg[port][place].ml;
00448 else
00449 iter = port_cfg[0][place].ml;
00450 if (iter) {
00451 for (; iter; iter = iter->next)
00452 sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn);
00453 tempbuf[strlen(tempbuf)-2] = 0;
00454 }
00455 snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
00456 break;
00457 case MISDN_CTYPE_STR:
00458 if ( port_cfg[port][place].str) {
00459 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
00460 } else if (port_cfg[0][place].str) {
00461 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
00462 } else {
00463 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00464 }
00465 break;
00466 }
00467 } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
00468 switch (gen_spec[place].type) {
00469 case MISDN_CTYPE_INT:
00470 case MISDN_CTYPE_BOOLINT:
00471 if (general_cfg[place].num)
00472 snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
00473 else
00474 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00475 break;
00476 case MISDN_CTYPE_BOOL:
00477 if (general_cfg[place].num)
00478 snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
00479 else
00480 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00481 break;
00482 case MISDN_CTYPE_STR:
00483 if ( general_cfg[place].str) {
00484 snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
00485 } else {
00486 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00487 }
00488 break;
00489 default:
00490 snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
00491 break;
00492 }
00493 } else {
00494 *buf = 0;
00495 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
00496 }
00497 misdn_cfg_unlock();
00498 }
00499
00500 int misdn_cfg_get_next_port (int port)
00501 {
00502 int p = -1;
00503 int gn = map[MISDN_CFG_GROUPNAME];
00504
00505 misdn_cfg_lock();
00506 for (port++; port <= max_ports; port++) {
00507 if (port_cfg[port][gn].str) {
00508 p = port;
00509 break;
00510 }
00511 }
00512 misdn_cfg_unlock();
00513
00514 return p;
00515 }
00516
00517 int misdn_cfg_get_next_port_spin (int port)
00518 {
00519 int p = misdn_cfg_get_next_port(port);
00520 return (p > 0) ? p : misdn_cfg_get_next_port(0);
00521 }
00522
00523 static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def)
00524 {
00525 int re = 0;
00526 int len, tmp;
00527 char *valtmp;
00528
00529 switch (type) {
00530 case MISDN_CTYPE_STR:
00531 if ((len = strlen(value))) {
00532 dest->str = (char *)malloc((len + 1) * sizeof(char));
00533 strncpy(dest->str, value, len);
00534 dest->str[len] = 0;
00535 } else {
00536 dest->str = (char *)malloc( sizeof(char));
00537 dest->str[0] = 0;
00538 }
00539 break;
00540 case MISDN_CTYPE_INT:
00541 {
00542 char *pat;
00543 if (strchr(value,'x'))
00544 pat="%x";
00545 else
00546 pat="%d";
00547 if (sscanf(value, pat, &tmp)) {
00548 dest->num = (int *)malloc(sizeof(int));
00549 memcpy(dest->num, &tmp, sizeof(int));
00550 } else
00551 re = -1;
00552 }
00553 break;
00554 case MISDN_CTYPE_BOOL:
00555 dest->num = (int *)malloc(sizeof(int));
00556 *(dest->num) = (ast_true(value) ? 1 : 0);
00557 break;
00558 case MISDN_CTYPE_BOOLINT:
00559 dest->num = (int *)malloc(sizeof(int));
00560 if (sscanf(value, "%d", &tmp)) {
00561 memcpy(dest->num, &tmp, sizeof(int));
00562 } else {
00563 *(dest->num) = (ast_true(value) ? boolint_def : 0);
00564 }
00565 break;
00566 case MISDN_CTYPE_MSNLIST:
00567 for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) {
00568 if ((len = strlen(valtmp))) {
00569 struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list));
00570 ml->msn = (char *)calloc(len+1, sizeof(char));
00571 strncpy(ml->msn, valtmp, len);
00572 ml->next = dest->ml;
00573 dest->ml = ml;
00574 }
00575 }
00576 break;
00577 case MISDN_CTYPE_ASTGROUP:
00578 dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t));
00579 *(dest->grp) = ast_get_group(value);
00580 break;
00581 }
00582
00583 return re;
00584 }
00585
00586 static void _build_general_config (struct ast_variable *v)
00587 {
00588 int pos;
00589
00590 for (; v; v = v->next) {
00591 if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
00592 (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
00593 CLI_ERROR(v->name, v->value, "general");
00594 }
00595 }
00596
00597 static void _build_port_config (struct ast_variable *v, char *cat)
00598 {
00599 int pos, i;
00600 union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
00601 int cfg_for_ports[max_ports + 1];
00602
00603 if (!v || !cat)
00604 return;
00605
00606 memset(cfg_tmp, 0, sizeof(cfg_tmp));
00607 memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
00608
00609 if (!strcasecmp(cat, "default")) {
00610 cfg_for_ports[0] = 1;
00611 }
00612
00613 if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
00614 (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
00615 CLI_ERROR(v->name, v->value, cat);
00616 return;
00617 }
00618
00619 for (; v; v = v->next) {
00620 if (!strcasecmp(v->name, "ports")) {
00621 char *token;
00622 char ptpbuf[BUFFERSIZE] = "";
00623 int start, end;
00624 for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) {
00625 if (!*token)
00626 continue;
00627 if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
00628 for (; start <= end; start++) {
00629 if (start <= max_ports && start > 0) {
00630 cfg_for_ports[start] = 1;
00631 ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00632 } else
00633 CLI_ERROR(v->name, v->value, cat);
00634 }
00635 } else {
00636 if (sscanf(token, "%d%s", &start, ptpbuf)) {
00637 if (start <= max_ports && start > 0) {
00638 cfg_for_ports[start] = 1;
00639 ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00640 } else
00641 CLI_ERROR(v->name, v->value, cat);
00642 } else
00643 CLI_ERROR(v->name, v->value, cat);
00644 }
00645 }
00646 } else {
00647 if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
00648 (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
00649 CLI_ERROR(v->name, v->value, cat);
00650 }
00651 }
00652
00653 for (i = 0; i < (max_ports + 1); ++i) {
00654 if (cfg_for_ports[i]) {
00655 memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
00656 }
00657 }
00658 }
00659
00660 void misdn_cfg_update_ptp (void)
00661 {
00662 char misdn_init[BUFFERSIZE];
00663 char line[BUFFERSIZE];
00664 FILE *fp;
00665 char *tok, *p, *end;
00666 int port;
00667
00668 misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
00669
00670 if (misdn_init) {
00671 fp = fopen(misdn_init, "r");
00672 if (fp) {
00673 while(fgets(line, sizeof(line), fp)) {
00674 if (!strncmp(line, "nt_ptp", 6)) {
00675 for (tok = strtok_r(line,",=", &p);
00676 tok;
00677 tok = strtok_r(NULL,",=", &p)) {
00678 port = strtol(tok, &end, 10);
00679 if (end != tok && misdn_cfg_is_port_valid(port)) {
00680 misdn_cfg_lock();
00681 ptp[port] = 1;
00682 misdn_cfg_unlock();
00683 }
00684 }
00685 }
00686 }
00687 fclose(fp);
00688 } else {
00689 ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
00690 }
00691 }
00692 }
00693
00694 static void _fill_defaults (void)
00695 {
00696 int i;
00697
00698 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00699 if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
00700 _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
00701 }
00702 for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
00703 if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
00704 _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
00705 }
00706 }
00707
00708 void misdn_cfg_reload (void)
00709 {
00710 misdn_cfg_init (0);
00711 }
00712
00713 void misdn_cfg_destroy (void)
00714 {
00715 misdn_cfg_lock();
00716
00717 _free_port_cfg();
00718 _free_general_cfg();
00719
00720 free(port_cfg);
00721 free(general_cfg);
00722 free(ptp);
00723 free(map);
00724
00725 misdn_cfg_unlock();
00726 ast_mutex_destroy(&config_mutex);
00727 }
00728
00729 void misdn_cfg_init (int this_max_ports)
00730 {
00731 char config[] = "misdn.conf";
00732 char *cat, *p;
00733 int i;
00734 struct ast_config *cfg;
00735 struct ast_variable *v;
00736
00737 if (!(cfg = AST_LOAD_CFG(config))) {
00738 ast_log(LOG_WARNING,"no misdn.conf ?\n");
00739 return;
00740 }
00741
00742 misdn_cfg_lock();
00743
00744 if (this_max_ports) {
00745
00746 max_ports = this_max_ports;
00747 p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
00748 + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
00749 port_cfg = (union misdn_cfg_pt **)p;
00750 p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
00751 for (i = 0; i <= max_ports; ++i) {
00752 port_cfg[i] = (union misdn_cfg_pt *)p;
00753 p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
00754 }
00755 general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
00756 ptp = (int *)calloc(max_ports + 1, sizeof(int));
00757 map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int));
00758 _enum_array_map();
00759 }
00760 else {
00761
00762 _free_port_cfg();
00763 _free_general_cfg();
00764 memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
00765 memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
00766 memset(ptp, 0, sizeof(int) * (max_ports + 1));
00767 }
00768
00769 cat = ast_category_browse(cfg, NULL);
00770
00771 while(cat) {
00772 v = ast_variable_browse(cfg, cat);
00773 if (!strcasecmp(cat,"general")) {
00774 _build_general_config(v);
00775 } else {
00776 _build_port_config(v, cat);
00777 }
00778 cat = ast_category_browse(cfg,cat);
00779 }
00780
00781 _fill_defaults();
00782
00783 misdn_cfg_unlock();
00784 AST_DESTROY_CFG(cfg);
00785 }