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 "asterisk.h"
00030
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 193264 $")
00032
00033 #include "chan_misdn_config.h"
00034
00035 #include "asterisk/config.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/lock.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/strings.h"
00040 #include "asterisk/utils.h"
00041
00042 #define AST_LOAD_CFG ast_config_load
00043 #define AST_DESTROY_CFG ast_config_destroy
00044
00045 #define NO_DEFAULT "<>"
00046 #define NONE 0
00047
00048 #define GEN_CFG 1
00049 #define PORT_CFG 2
00050 #define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec))
00051 #define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec))
00052
00053
00054 static struct ast_jb_conf default_jbconf =
00055 {
00056 .flags = 0,
00057 .max_size = -1,
00058 .resync_threshold = -1,
00059 .impl = "",
00060 };
00061
00062 static struct ast_jb_conf global_jbconf;
00063
00064 enum misdn_cfg_type {
00065 MISDN_CTYPE_STR,
00066 MISDN_CTYPE_INT,
00067 MISDN_CTYPE_BOOL,
00068 MISDN_CTYPE_BOOLINT,
00069 MISDN_CTYPE_MSNLIST,
00070 MISDN_CTYPE_ASTGROUP
00071 };
00072
00073 struct msn_list {
00074 char *msn;
00075 struct msn_list *next;
00076 };
00077
00078 union misdn_cfg_pt {
00079 char *str;
00080 int *num;
00081 struct msn_list *ml;
00082 ast_group_t *grp;
00083 void *any;
00084 };
00085
00086 struct misdn_cfg_spec {
00087 char name[BUFFERSIZE];
00088 enum misdn_cfg_elements elem;
00089 enum misdn_cfg_type type;
00090 char def[BUFFERSIZE];
00091 int boolint_def;
00092 char desc[BUFFERSIZE];
00093 };
00094
00095
00096 static const char ports_description[] =
00097 "Define your ports, e.g. 1,2 (depends on mISDN-driver loading order).";
00098
00099 static const struct misdn_cfg_spec port_spec[] = {
00100 { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE,
00101 "Name of the portgroup." },
00102 { "allowed_bearers", MISDN_CFG_ALLOWED_BEARERS, MISDN_CTYPE_STR, "all", NONE,
00103 "Here you can list which bearer capabilities should be allowed:\n"
00104 "\t all - allow any bearer capability\n"
00105 "\t speech - allow speech\n"
00106 "\t 3_1khz - allow 3.1KHz audio\n"
00107 "\t digital_unrestricted - allow unrestricted digital\n"
00108 "\t digital_restricted - allow restricted digital\n"
00109 "\t video - allow video" },
00110 { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE,
00111 "Set this between -8 and 8 to change the RX Gain." },
00112 { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE,
00113 "Set this between -8 and 8 to change the TX Gain." },
00114 { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE,
00115 "Some telcos especially in NL seem to need this set to yes,\n"
00116 "\talso in Switzerland this seems to be important." },
00117 { "far_alerting", MISDN_CFG_FAR_ALERTING, MISDN_CTYPE_BOOL, "no", NONE,
00118 "If we should generate ringing for chan_sip and others." },
00119 { "pmp_l1_check", MISDN_CFG_PMP_L1_CHECK, MISDN_CTYPE_BOOL, "no", NONE,
00120 "This option defines, if chan_misdn should check the L1 on a PMP\n"
00121 "\tbefore making a group call on it. The L1 may go down for PMP Ports\n"
00122 "\tso we might need this.\n"
00123 "\tBut be aware! a broken or plugged off cable might be used for a group call\n"
00124 "\tas well, since chan_misdn has no chance to distinguish if the L1 is down\n"
00125 "\tbecause of a lost Link or because the Provider shut it down..." },
00126 { "block_on_alarm", MISDN_CFG_ALARM_BLOCK, MISDN_CTYPE_BOOL, "no", NONE ,
00127 "Block this port if we have an alarm on it." },
00128 { "hdlc", MISDN_CFG_HDLC, MISDN_CTYPE_BOOL, "no", NONE,
00129 "Set this to yes, if you want to bridge a mISDN data channel to\n"
00130 "\tanother channel type or to an application." },
00131 { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE,
00132 "Context to use for incoming calls." },
00133 { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE,
00134 "Language." },
00135 { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE,
00136 "Sets the musiconhold class." },
00137 { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE,
00138 "Sets the caller ID." },
00139 { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE,
00140 "Set the method to use for channel selection:\n"
00141 "\t standard - Use the first free channel starting from the lowest number.\n"
00142 "\t standard_dec - Use the first free channel starting from the highest number.\n"
00143 "\t round_robin - Use the round robin algorithm to select a channel. Use this\n"
00144 "\t if you want to balance your load." },
00145 { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE,
00146 "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
00147 "\n"
00148 "\tThere are different types of the dialplan:\n"
00149 "\n"
00150 "\tdialplan -> outgoing Number\n"
00151 "\tlocaldialplan -> callerid\n"
00152 "\tcpndialplan -> connected party number\n"
00153 "\n"
00154 "\tdialplan options:\n"
00155 "\n"
00156 "\t0 - unknown\n"
00157 "\t1 - International\n"
00158 "\t2 - National\n"
00159 "\t4 - Subscriber\n"
00160 "\n"
00161 "\tThis setting is used for outgoing calls." },
00162 { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
00163 "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
00164 "\n"
00165 "\tThere are different types of the dialplan:\n"
00166 "\n"
00167 "\tdialplan -> outgoing Number\n"
00168 "\tlocaldialplan -> callerid\n"
00169 "\tcpndialplan -> connected party number\n"
00170 "\n"
00171 "\tdialplan options:\n"
00172 "\n"
00173 "\t0 - unknown\n"
00174 "\t1 - International\n"
00175 "\t2 - National\n"
00176 "\t4 - Subscriber\n"
00177 "\n"
00178 "\tThis setting is used for outgoing calls." },
00179 { "cpndialplan", MISDN_CFG_CPNDIALPLAN, MISDN_CTYPE_INT, "0", NONE,
00180 "Dialplan means Type Of Number in ISDN Terms (for outgoing calls)\n"
00181 "\n"
00182 "\tThere are different types of the dialplan:\n"
00183 "\n"
00184 "\tdialplan -> outgoing Number\n"
00185 "\tlocaldialplan -> callerid\n"
00186 "\tcpndialplan -> connected party number\n"
00187 "\n"
00188 "\tdialplan options:\n"
00189 "\n"
00190 "\t0 - unknown\n"
00191 "\t1 - International\n"
00192 "\t2 - National\n"
00193 "\t4 - Subscriber\n"
00194 "\n"
00195 "\tThis setting is used for outgoing calls." },
00196 { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE,
00197 "Prefix for national, this is put before the\n"
00198 "\toad if an according dialplan is set by the other end." },
00199 { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE,
00200 "Prefix for international, this is put before the\n"
00201 "\toad if an according dialplan is set by the other end." },
00202 { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE,
00203 "These (presentation and screen) are the exact isdn screening and presentation\n"
00204 "\tindicators.\n"
00205 "\tIf -1 is given for both values, the presentation indicators are used from\n"
00206 "\tAsterisks SetCallerPres application.\n"
00207 "\n"
00208 "\tscreen=0, presentation=0 -> callerid presented not screened\n"
00209 "\tscreen=1, presentation=1 -> callerid presented but screened (the remote end doesn't see it!)" },
00210 { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE,
00211 "These (presentation and screen) are the exact isdn screening and presentation\n"
00212 "\tindicators.\n"
00213 "\tIf -1 is given for both values, the presentation indicators are used from\n"
00214 "\tAsterisks SetCallerPres application.\n"
00215 "\n"
00216 "\tscreen=0, presentation=0 -> callerid presented not screened\n"
00217 "\tscreen=1, presentation=1 -> callerid presented but screened (the remote end doesn't see it!)" },
00218 { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
00219 "Enable this to get into the s dialplan-extension.\n"
00220 "\tThere you can use DigitTimeout if you can't or don't want to use\n"
00221 "\tisdn overlap dial.\n"
00222 "\tNOTE: This will jump into the s extension for every exten!" },
00223 { "nodialtone", MISDN_CFG_NODIALTONE, MISDN_CTYPE_BOOL, "no", NONE,
00224 "Enable this to prevent chan_misdn to generate the dialtone\n"
00225 "\tThis makes only sense together with the always_immediate=yes option\n"
00226 "\tto generate your own dialtone with Playtones or so."},
00227 { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE,
00228 "Enable this if you want callers which called exactly the base\n"
00229 "\tnumber (so no extension is set) to jump into the s extension.\n"
00230 "\tIf the user dials something more, it jumps to the correct extension\n"
00231 "\tinstead." },
00232 { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE,
00233 "Enable this if we should produce DTMF Tones ourselves." },
00234 { "astdtmf", MISDN_CFG_ASTDTMF, MISDN_CTYPE_BOOL, "no", NONE,
00235 "Enable this if you want to use the Asterisk dtmf detector\n"
00236 "instead of the mISDN_dsp/hfcmulti one."
00237 },
00238 { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE,
00239 "Enable this to have support for hold and retrieve." },
00240 { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE,
00241 "Disable this if you don't mind correct handling of Progress Indicators." },
00242 { "incoming_early_audio", MISDN_CFG_INCOMING_EARLY_AUDIO, MISDN_CTYPE_BOOL, "no", NONE,
00243 "Turn this on if you like to send Tone Indications to a Incoming\n"
00244 "\tisdn channel on a TE Port. Rarely used, only if the Telco allows\n"
00245 "\tyou to send indications by yourself, normally the Telco sends the\n"
00246 "\tindications to the remote party." },
00247 { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128,
00248 "This enables echo cancellation with the given number of taps.\n"
00249 "\tBe aware: Move this setting only to outgoing portgroups!\n"
00250 "\tA value of zero turns echo cancellation off.\n"
00251 "\n"
00252 "\tPossible values are: 0,32,64,128,256,yes(=128),no(=0)" },
00253 #ifdef MISDN_1_2
00254 { "pipeline", MISDN_CFG_PIPELINE, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
00255 "Set the configuration string for the mISDN dsp pipeline.\n"
00256 "\n"
00257 "\tExample for enabling the mg2 echo cancellation module with deftaps\n"
00258 "\tset to 128:\n"
00259 "\t\tmg2ec(deftaps=128)" },
00260 #endif
00261 #ifdef WITH_BEROEC
00262 { "bnechocancel", MISDN_CFG_BNECHOCANCEL, MISDN_CTYPE_BOOLINT, "yes", 64,
00263 "echotail in ms (1-200)\n"},
00264 { "bnec_antihowl", MISDN_CFG_BNEC_ANTIHOWL, MISDN_CTYPE_INT, "0", NONE,
00265 "Use antihowl\n"},
00266 { "bnec_nlp", MISDN_CFG_BNEC_NLP, MISDN_CTYPE_BOOL, "yes", NONE,
00267 "Nonlinear Processing (much faster adaption)"},
00268 { "bnec_zerocoeff", MISDN_CFG_BNEC_ZEROCOEFF, MISDN_CTYPE_BOOL, "no", NONE,
00269 "ZeroCoeffeciens\n"},
00270 { "bnec_tonedisabler", MISDN_CFG_BNEC_TD, MISDN_CTYPE_BOOL, "no", NONE,
00271 "Disable Tone\n"},
00272 { "bnec_adaption", MISDN_CFG_BNEC_ADAPT, MISDN_CTYPE_INT, "1", NONE,
00273 "Adaption mode (0=no,1=full,2=fast)\n"},
00274 #endif
00275 { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE,
00276 "Send Setup_Acknowledge on incoming calls anyway (instead of PROCEEDING),\n"
00277 "\tthis requests additional Infos, so we can waitfordigits without much\n"
00278 "\tissues. This works only for PTP Ports" },
00279 { "noautorespond_on_setup", MISDN_CFG_NOAUTORESPOND_ON_SETUP, MISDN_CTYPE_BOOL, "0", NONE,
00280 "Do not send SETUP_ACKNOWLEDGE or PROCEEDING automatically to the calling Party.\n"
00281 "Instead we directly jump into the dialplan. This might be useful for fast call\n"
00282 "rejection, or for some broken switches, that need hangup causes like busy in the.\n"
00283 "RELEASE_COMPLETE Message, instead of the DISCONNECT Message."},
00284 { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "4000", NONE,
00285 "The jitterbuffer." },
00286 { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE,
00287 "Change this threshold to enable dejitter functionality." },
00288 { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE,
00289 "Callgroup." },
00290 { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE,
00291 "Pickupgroup." },
00292 { "max_incoming", MISDN_CFG_MAX_IN, MISDN_CTYPE_INT, "-1", NONE,
00293 "Defines the maximum amount of incoming calls per port for this group.\n"
00294 "\tCalls which exceed the maximum will be marked with the channel variable\n"
00295 "\tMAX_OVERFLOW. It will contain the amount of overflowed calls" },
00296 { "max_outgoing", MISDN_CFG_MAX_OUT, MISDN_CTYPE_INT, "-1", NONE,
00297 "Defines the maximum amount of outgoing calls per port for this group\n"
00298 "\texceeding calls will be rejected" },
00299
00300 { "reject_cause", MISDN_CFG_REJECT_CAUSE, MISDN_CTYPE_INT, "21", NONE,
00301 "Defines the cause with which a 3. call is rejected on PTMP BRI."},
00302 { "faxdetect", MISDN_CFG_FAXDETECT, MISDN_CTYPE_STR, "no", NONE,
00303 "Setup fax detection:\n"
00304 "\t no - no fax detection\n"
00305 "\t incoming - fax detection for incoming calls\n"
00306 "\t outgoing - fax detection for outgoing calls\n"
00307 "\t both - fax detection for incoming and outgoing calls\n"
00308 "\tAdd +nojump to your value (i.e. faxdetect=both+nojump) if you don't want to jump into the\n"
00309 "\tfax-extension but still want to detect the fax and prepare the channel for fax transfer." },
00310 { "faxdetect_timeout", MISDN_CFG_FAXDETECT_TIMEOUT, MISDN_CTYPE_INT, "5", NONE,
00311 "Number of seconds the fax detection should do its job. After the given period of time,\n"
00312 "\twe assume that it's not a fax call and save some CPU time by turning off fax detection.\n"
00313 "\tSet this to 0 if you don't want a timeout (never stop detecting)." },
00314 { "faxdetect_context", MISDN_CFG_FAXDETECT_CONTEXT, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
00315 "Context to jump into if we detect a fax. Don't set this if you want to stay in the current context." },
00316 { "l1watcher_timeout", MISDN_CFG_L1_TIMEOUT, MISDN_CTYPE_BOOLINT, "0", 4,
00317 "Watches the layer 1. If the layer 1 is down, it tries to\n"
00318 "\tget it up. The timeout is given in seconds. with 0 as value it\n"
00319 "\tdoes not watch the l1 at all\n"
00320 "\n"
00321 "\tThis option is only read at loading time of chan_misdn, which\n"
00322 "\tmeans you need to unload and load chan_misdn to change the value,\n"
00323 "\tan Asterisk restart should do the trick." },
00324 { "overlapdial", MISDN_CFG_OVERLAP_DIAL, MISDN_CTYPE_BOOLINT, "0", 4,
00325 "Enables overlap dial for the given amount of seconds.\n"
00326 "\tPossible values are positive integers or:\n"
00327 "\t yes (= 4 seconds)\n"
00328 "\t no (= 0 seconds = disabled)" },
00329 { "nttimeout", MISDN_CFG_NTTIMEOUT, MISDN_CTYPE_BOOL, "no", NONE ,
00330 "Set this to yes if you want calls disconnected in overlap mode\n"
00331 "\twhen a timeout happens." },
00332 { "bridging", MISDN_CFG_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE,
00333 "Set this to yes/no, default is yes.\n"
00334 "This can be used to have bridging enabled in general and to\n"
00335 "disable it for specific ports. It makes sense to disable\n"
00336 "bridging on NT Port where you plan to use the HOLD/RETRIEVE\n"
00337 "features with ISDN phones." },
00338 { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, "*", NONE,
00339 "MSN's for TE ports, listen on those numbers on the above ports, and\n"
00340 "\tindicate the incoming calls to Asterisk.\n"
00341 "\tHere you can give a comma separated list, or simply an '*' for any msn." },
00342 };
00343
00344 static const struct misdn_cfg_spec gen_spec[] = {
00345 { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE,
00346 "Sets the debugging flag:\n"
00347 "\t0 - No Debug\n"
00348 "\t1 - mISDN Messages and * - Messages, and * - State changes\n"
00349 "\t2 - Messages + Message specific Informations (e.g. bearer capability)\n"
00350 "\t3 - very Verbose, the above + lots of Driver specific infos\n"
00351 "\t4 - even more Verbose than 3" },
00352 #ifndef MISDN_1_2
00353 { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE,
00354 "Set the path to the misdn-init.conf (for nt_ptp mode checking)." },
00355 #endif
00356 { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/asterisk/misdn.log", NONE,
00357 "Set the path to the massively growing trace file, if you want that." },
00358 { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE,
00359 "Set this to yes if you want mISDN_dsp to bridge the calls in HW." },
00360 { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE,
00361 "Stops dialtone after getting first digit on NT Port." },
00362 { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE,
00363 "Whether to append overlapdialed Digits to Extension or not." },
00364 { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE,
00365 "Whether to look out for dynamic crypting attempts." },
00366 { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
00367 "What is used for crypting Protocol." },
00368 { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE,
00369 "Keys for cryption, you reference them in the dialplan\n"
00370 "\tLater also in dynamic encr." },
00371 { "ntkeepcalls", MISDN_GEN_NTKEEPCALLS, MISDN_CTYPE_BOOL, "no", NONE,
00372 "avoid dropping calls if the L2 goes down. some Nortel pbx\n"
00373 "do put down the L2/L1 for some milliseconds even if there\n"
00374 "are running calls. with this option you can avoid dropping them" },
00375 { "ntdebugflags", MISDN_GEN_NTDEBUGFLAGS, MISDN_CTYPE_INT, "0", NONE,
00376 "No description yet."},
00377 { "ntdebugfile", MISDN_GEN_NTDEBUGFILE, MISDN_CTYPE_STR, "/var/log/misdn-nt.log", NONE,
00378 "No description yet." }
00379 };
00380
00381
00382
00383 static union misdn_cfg_pt **port_cfg;
00384
00385 static int max_ports;
00386
00387 static union misdn_cfg_pt *general_cfg;
00388
00389 static int *ptp;
00390
00391 static int *map;
00392
00393 static ast_mutex_t config_mutex;
00394
00395 #define CLI_ERROR(name, value, section) ({ \
00396 ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \
00397 "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \
00398 })
00399
00400 static int _enum_array_map (void)
00401 {
00402 int i, j, ok;
00403
00404 for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) {
00405 if (i == MISDN_CFG_PTP)
00406 continue;
00407 ok = 0;
00408 for (j = 0; j < NUM_PORT_ELEMENTS; ++j) {
00409 if (port_spec[j].elem == i) {
00410 map[i] = j;
00411 ok = 1;
00412 break;
00413 }
00414 }
00415 if (!ok) {
00416 ast_log(LOG_WARNING, "Enum element %d in misdn_cfg_elements (port section) has no corresponding element in the config struct!\n", i);
00417 return -1;
00418 }
00419 }
00420 for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) {
00421 ok = 0;
00422 for (j = 0; j < NUM_GEN_ELEMENTS; ++j) {
00423 if (gen_spec[j].elem == i) {
00424 map[i] = j;
00425 ok = 1;
00426 break;
00427 }
00428 }
00429 if (!ok) {
00430 ast_log(LOG_WARNING, "Enum element %d in misdn_cfg_elements (general section) has no corresponding element in the config struct!\n", i);
00431 return -1;
00432 }
00433 }
00434 return 0;
00435 }
00436
00437 static int get_cfg_position (const char *name, int type)
00438 {
00439 int i;
00440
00441 switch (type) {
00442 case PORT_CFG:
00443 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00444 if (!strcasecmp(name, port_spec[i].name))
00445 return i;
00446 }
00447 break;
00448 case GEN_CFG:
00449 for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
00450 if (!strcasecmp(name, gen_spec[i].name))
00451 return i;
00452 }
00453 }
00454
00455 return -1;
00456 }
00457
00458 static inline void misdn_cfg_lock (void)
00459 {
00460 ast_mutex_lock(&config_mutex);
00461 }
00462
00463 static inline void misdn_cfg_unlock (void)
00464 {
00465 ast_mutex_unlock(&config_mutex);
00466 }
00467
00468 static void _free_msn_list (struct msn_list* iter)
00469 {
00470 if (iter->next)
00471 _free_msn_list(iter->next);
00472 if (iter->msn)
00473 ast_free(iter->msn);
00474 ast_free(iter);
00475 }
00476
00477 static void _free_port_cfg (void)
00478 {
00479 int i, j;
00480 int gn = map[MISDN_CFG_GROUPNAME];
00481 union misdn_cfg_pt* free_list[max_ports + 2];
00482
00483 memset(free_list, 0, sizeof(free_list));
00484 free_list[0] = port_cfg[0];
00485 for (i = 1; i <= max_ports; ++i) {
00486 if (port_cfg[i][gn].str) {
00487
00488 for (j = 1; j <= max_ports; ++j) {
00489 if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str)
00490 break;
00491 else if (!free_list[j]) {
00492 free_list[j] = port_cfg[i];
00493 break;
00494 }
00495 }
00496 }
00497 }
00498 for (j = 0; free_list[j]; ++j) {
00499 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
00500 if (free_list[j][i].any) {
00501 if (port_spec[i].type == MISDN_CTYPE_MSNLIST)
00502 _free_msn_list(free_list[j][i].ml);
00503 else
00504 ast_free(free_list[j][i].any);
00505 }
00506 }
00507 }
00508 }
00509
00510 static void _free_general_cfg (void)
00511 {
00512 int i;
00513
00514 for (i = 0; i < NUM_GEN_ELEMENTS; i++)
00515 if (general_cfg[i].any)
00516 ast_free(general_cfg[i].any);
00517 }
00518
00519 void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize)
00520 {
00521 int place;
00522
00523 if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00524 memset(buf, 0, bufsize);
00525 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
00526 return;
00527 }
00528
00529 misdn_cfg_lock();
00530 if (elem == MISDN_CFG_PTP) {
00531 if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize))
00532 memset(buf, 0, bufsize);
00533 } else {
00534 if ((place = map[elem]) < 0) {
00535 memset(buf, 0, bufsize);
00536 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem);
00537 } else {
00538 if (elem < MISDN_CFG_LAST) {
00539 switch (port_spec[place].type) {
00540 case MISDN_CTYPE_STR:
00541 if (port_cfg[port][place].str) {
00542 ast_copy_string(buf, port_cfg[port][place].str, bufsize);
00543 } else if (port_cfg[0][place].str) {
00544 ast_copy_string(buf, port_cfg[0][place].str, bufsize);
00545 } else
00546 memset(buf, 0, bufsize);
00547 break;
00548 default:
00549 if (port_cfg[port][place].any)
00550 memcpy(buf, port_cfg[port][place].any, bufsize);
00551 else if (port_cfg[0][place].any)
00552 memcpy(buf, port_cfg[0][place].any, bufsize);
00553 else
00554 memset(buf, 0, bufsize);
00555 }
00556 } else {
00557 switch (gen_spec[place].type) {
00558 case MISDN_CTYPE_STR:
00559 ast_copy_string(buf, S_OR(general_cfg[place].str, ""), bufsize);
00560 break;
00561 default:
00562 if (general_cfg[place].any)
00563 memcpy(buf, general_cfg[place].any, bufsize);
00564 else
00565 memset(buf, 0, bufsize);
00566 }
00567 }
00568 }
00569 }
00570 misdn_cfg_unlock();
00571 }
00572
00573 enum misdn_cfg_elements misdn_cfg_get_elem(char *name)
00574 {
00575 int pos;
00576
00577
00578 if (!strcmp(name, "ports"))
00579 return MISDN_CFG_GROUPNAME;
00580 if (!strcmp(name, "name"))
00581 return MISDN_CFG_FIRST;
00582
00583 pos = get_cfg_position(name, PORT_CFG);
00584 if (pos >= 0)
00585 return port_spec[pos].elem;
00586
00587 pos = get_cfg_position(name, GEN_CFG);
00588 if (pos >= 0)
00589 return gen_spec[pos].elem;
00590
00591 return MISDN_CFG_FIRST;
00592 }
00593
00594 void misdn_cfg_get_name(enum misdn_cfg_elements elem, void *buf, int bufsize)
00595 {
00596 struct misdn_cfg_spec *spec = NULL;
00597 int place = map[elem];
00598
00599
00600 if (elem == MISDN_CFG_PTP) {
00601 memset(buf, 0, 1);
00602 return;
00603 }
00604
00605
00606 if (elem == MISDN_CFG_GROUPNAME) {
00607 if (!snprintf(buf, bufsize, "ports"))
00608 memset(buf, 0, 1);
00609 return;
00610 }
00611
00612 if ((elem > MISDN_CFG_FIRST) && (elem < MISDN_CFG_LAST))
00613 spec = (struct misdn_cfg_spec *)port_spec;
00614 else if ((elem > MISDN_GEN_FIRST) && (elem < MISDN_GEN_LAST))
00615 spec = (struct misdn_cfg_spec *)gen_spec;
00616
00617 ast_copy_string(buf, spec ? spec[place].name : "", bufsize);
00618 }
00619
00620 void misdn_cfg_get_desc (enum misdn_cfg_elements elem, void *buf, int bufsize, void *buf_default, int bufsize_default)
00621 {
00622 int place = map[elem];
00623 struct misdn_cfg_spec *spec = NULL;
00624
00625
00626 if (elem == MISDN_CFG_GROUPNAME) {
00627 ast_copy_string(buf, ports_description, bufsize);
00628 if (buf_default && bufsize_default)
00629 memset(buf_default, 0, 1);
00630 return;
00631 }
00632
00633 if ((elem > MISDN_CFG_FIRST) && (elem < MISDN_CFG_LAST))
00634 spec = (struct misdn_cfg_spec *)port_spec;
00635 else if ((elem > MISDN_GEN_FIRST) && (elem < MISDN_GEN_LAST))
00636 spec = (struct misdn_cfg_spec *)gen_spec;
00637
00638 if (!spec || !spec[place].desc)
00639 memset(buf, 0, 1);
00640 else {
00641 ast_copy_string(buf, spec[place].desc, bufsize);
00642 if (buf_default && bufsize) {
00643 if (!strcmp(spec[place].def, NO_DEFAULT))
00644 memset(buf_default, 0, 1);
00645 else
00646 ast_copy_string(buf_default, spec[place].def, bufsize_default);
00647 }
00648 }
00649 }
00650
00651 int misdn_cfg_is_msn_valid (int port, char* msn)
00652 {
00653 int re = 0;
00654 struct msn_list *iter;
00655
00656 if (!misdn_cfg_is_port_valid(port)) {
00657 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
00658 return 0;
00659 }
00660
00661 misdn_cfg_lock();
00662 if (port_cfg[port][map[MISDN_CFG_MSNS]].ml)
00663 iter = port_cfg[port][map[MISDN_CFG_MSNS]].ml;
00664 else
00665 iter = port_cfg[0][map[MISDN_CFG_MSNS]].ml;
00666 for (; iter; iter = iter->next)
00667 if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) {
00668 re = 1;
00669 break;
00670 }
00671 misdn_cfg_unlock();
00672
00673 return re;
00674 }
00675
00676 int misdn_cfg_is_port_valid (int port)
00677 {
00678 int gn = map[MISDN_CFG_GROUPNAME];
00679
00680 return (port >= 1 && port <= max_ports && port_cfg[port][gn].str);
00681 }
00682
00683 int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth)
00684 {
00685 int i, re = 0;
00686 char *method ;
00687
00688 misdn_cfg_lock();
00689
00690 method = port_cfg[0][map[MISDN_CFG_METHOD]].str;
00691
00692 for (i = 1; i <= max_ports; i++) {
00693 if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) {
00694 if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group))
00695 method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ?
00696 port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str);
00697 }
00698 }
00699
00700 if (method) {
00701 switch (meth) {
00702 case METHOD_STANDARD: re = !strcasecmp(method, "standard");
00703 break;
00704 case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
00705 break;
00706 case METHOD_STANDARD_DEC: re = !strcasecmp(method, "standard_dec");
00707 break;
00708 }
00709 }
00710 misdn_cfg_unlock();
00711
00712 return re;
00713 }
00714
00715
00716
00717
00718 void misdn_cfg_get_ports_string (char *ports)
00719 {
00720 char tmp[16];
00721 int l, i;
00722 int gn = map[MISDN_CFG_GROUPNAME];
00723
00724 *ports = 0;
00725
00726 misdn_cfg_lock();
00727 for (i = 1; i <= max_ports; i++) {
00728 if (port_cfg[i][gn].str) {
00729 if (ptp[i])
00730 sprintf(tmp, "%dptp,", i);
00731 else
00732 sprintf(tmp, "%d,", i);
00733 strcat(ports, tmp);
00734 }
00735 }
00736 misdn_cfg_unlock();
00737
00738 if ((l = strlen(ports))) {
00739
00740 ports[l-1] = 0;
00741 }
00742 }
00743
00744 void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize)
00745 {
00746 int place;
00747 char tempbuf[BUFFERSIZE] = "";
00748 struct msn_list *iter;
00749
00750 if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) {
00751 *buf = 0;
00752 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
00753 return;
00754 }
00755
00756 place = map[elem];
00757
00758 misdn_cfg_lock();
00759 if (elem == MISDN_CFG_PTP) {
00760 snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no");
00761 }
00762 else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) {
00763 switch (port_spec[place].type) {
00764 case MISDN_CTYPE_INT:
00765 case MISDN_CTYPE_BOOLINT:
00766 if (port_cfg[port][place].num)
00767 snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num);
00768 else if (port_cfg[0][place].num)
00769 snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num);
00770 else
00771 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00772 break;
00773 case MISDN_CTYPE_BOOL:
00774 if (port_cfg[port][place].num)
00775 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no");
00776 else if (port_cfg[0][place].num)
00777 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no");
00778 else
00779 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00780 break;
00781 case MISDN_CTYPE_ASTGROUP:
00782 if (port_cfg[port][place].grp)
00783 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
00784 ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp));
00785 else if (port_cfg[0][place].grp)
00786 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name,
00787 ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp));
00788 else
00789 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00790 break;
00791 case MISDN_CTYPE_MSNLIST:
00792 if (port_cfg[port][place].ml)
00793 iter = port_cfg[port][place].ml;
00794 else
00795 iter = port_cfg[0][place].ml;
00796 if (iter) {
00797 for (; iter; iter = iter->next) {
00798 strncat(tempbuf, iter->msn, sizeof(tempbuf) - strlen(tempbuf) - 1);
00799 }
00800 if (strlen(tempbuf) > 1) {
00801 tempbuf[strlen(tempbuf)-2] = 0;
00802 }
00803 }
00804 snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none");
00805 break;
00806 case MISDN_CTYPE_STR:
00807 if ( port_cfg[port][place].str) {
00808 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str);
00809 } else if (port_cfg[0][place].str) {
00810 snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str);
00811 } else {
00812 snprintf(buf, bufsize, " -> %s:", port_spec[place].name);
00813 }
00814 break;
00815 }
00816 } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) {
00817 switch (gen_spec[place].type) {
00818 case MISDN_CTYPE_INT:
00819 case MISDN_CTYPE_BOOLINT:
00820 if (general_cfg[place].num)
00821 snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num);
00822 else
00823 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00824 break;
00825 case MISDN_CTYPE_BOOL:
00826 if (general_cfg[place].num)
00827 snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no");
00828 else
00829 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00830 break;
00831 case MISDN_CTYPE_STR:
00832 if ( general_cfg[place].str) {
00833 snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str);
00834 } else {
00835 snprintf(buf, bufsize, " -> %s:", gen_spec[place].name);
00836 }
00837 break;
00838 default:
00839 snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name);
00840 break;
00841 }
00842 } else {
00843 *buf = 0;
00844 ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem);
00845 }
00846 misdn_cfg_unlock();
00847 }
00848
00849 int misdn_cfg_get_next_port (int port)
00850 {
00851 int p = -1;
00852 int gn = map[MISDN_CFG_GROUPNAME];
00853
00854 misdn_cfg_lock();
00855 for (port++; port <= max_ports; port++) {
00856 if (port_cfg[port][gn].str) {
00857 p = port;
00858 break;
00859 }
00860 }
00861 misdn_cfg_unlock();
00862
00863 return p;
00864 }
00865
00866 int misdn_cfg_get_next_port_spin (int port)
00867 {
00868 int p = misdn_cfg_get_next_port(port);
00869 return (p > 0) ? p : misdn_cfg_get_next_port(0);
00870 }
00871
00872 static int _parse (union misdn_cfg_pt *dest, const char *value, enum misdn_cfg_type type, int boolint_def)
00873 {
00874 int re = 0;
00875 int len, tmp;
00876 char *valtmp;
00877 char *tmp2 = ast_strdupa(value);
00878
00879 switch (type) {
00880 case MISDN_CTYPE_STR:
00881 if ((len = strlen(value))) {
00882 dest->str = ast_malloc((len + 1) * sizeof(char));
00883 strncpy(dest->str, value, len);
00884 dest->str[len] = 0;
00885 } else {
00886 dest->str = ast_malloc(sizeof(char));
00887 dest->str[0] = 0;
00888 }
00889 break;
00890 case MISDN_CTYPE_INT:
00891 {
00892 int res;
00893
00894 if (strchr(value,'x')) {
00895 res = sscanf(value, "%x", &tmp);
00896 } else {
00897 res = sscanf(value, "%d", &tmp);
00898 }
00899 if (res) {
00900 dest->num = ast_malloc(sizeof(int));
00901 memcpy(dest->num, &tmp, sizeof(int));
00902 } else
00903 re = -1;
00904 }
00905 break;
00906 case MISDN_CTYPE_BOOL:
00907 dest->num = ast_malloc(sizeof(int));
00908 *(dest->num) = (ast_true(value) ? 1 : 0);
00909 break;
00910 case MISDN_CTYPE_BOOLINT:
00911 dest->num = ast_malloc(sizeof(int));
00912 if (sscanf(value, "%d", &tmp)) {
00913 memcpy(dest->num, &tmp, sizeof(int));
00914 } else {
00915 *(dest->num) = (ast_true(value) ? boolint_def : 0);
00916 }
00917 break;
00918 case MISDN_CTYPE_MSNLIST:
00919 for (valtmp = strsep(&tmp2, ","); valtmp; valtmp = strsep(&tmp2, ",")) {
00920 if ((len = strlen(valtmp))) {
00921 struct msn_list *ml = ast_malloc(sizeof(*ml));
00922 ml->msn = ast_calloc(len+1, sizeof(char));
00923 strncpy(ml->msn, valtmp, len);
00924 ml->next = dest->ml;
00925 dest->ml = ml;
00926 }
00927 }
00928 break;
00929 case MISDN_CTYPE_ASTGROUP:
00930 dest->grp = ast_malloc(sizeof(ast_group_t));
00931 *(dest->grp) = ast_get_group(value);
00932 break;
00933 }
00934
00935 return re;
00936 }
00937
00938 static void _build_general_config (struct ast_variable *v)
00939 {
00940 int pos;
00941
00942 for (; v; v = v->next) {
00943 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
00944 continue;
00945 if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) ||
00946 (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0))
00947 CLI_ERROR(v->name, v->value, "general");
00948 }
00949 }
00950
00951 static void _build_port_config (struct ast_variable *v, char *cat)
00952 {
00953 int pos, i;
00954 union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS];
00955 int cfg_for_ports[max_ports + 1];
00956
00957 if (!v || !cat)
00958 return;
00959
00960 memset(cfg_tmp, 0, sizeof(cfg_tmp));
00961 memset(cfg_for_ports, 0, sizeof(cfg_for_ports));
00962
00963 if (!strcasecmp(cat, "default")) {
00964 cfg_for_ports[0] = 1;
00965 }
00966
00967 if (((pos = get_cfg_position("name", PORT_CFG)) < 0) ||
00968 (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) {
00969 CLI_ERROR(v->name, v->value, cat);
00970 return;
00971 }
00972
00973 for (; v; v = v->next) {
00974 if (!strcasecmp(v->name, "ports")) {
00975 char *token, *tmp = ast_strdupa(v->value);
00976 char ptpbuf[BUFFERSIZE] = "";
00977 int start, end;
00978 for (token = strsep(&tmp, ","); token; token = strsep(&tmp, ","), *ptpbuf = 0) {
00979 if (!*token)
00980 continue;
00981 if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) {
00982 for (; start <= end; start++) {
00983 if (start <= max_ports && start > 0) {
00984 cfg_for_ports[start] = 1;
00985 ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00986 } else
00987 CLI_ERROR(v->name, v->value, cat);
00988 }
00989 } else {
00990 if (sscanf(token, "%d%s", &start, ptpbuf)) {
00991 if (start <= max_ports && start > 0) {
00992 cfg_for_ports[start] = 1;
00993 ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0;
00994 } else
00995 CLI_ERROR(v->name, v->value, cat);
00996 } else
00997 CLI_ERROR(v->name, v->value, cat);
00998 }
00999 }
01000 } else {
01001 if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) ||
01002 (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0))
01003 CLI_ERROR(v->name, v->value, cat);
01004 }
01005 }
01006
01007 for (i = 0; i < (max_ports + 1); ++i) {
01008 if (cfg_for_ports[i]) {
01009 memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp));
01010 }
01011 }
01012 }
01013
01014 void misdn_cfg_update_ptp (void)
01015 {
01016 #ifndef MISDN_1_2
01017 char misdn_init[BUFFERSIZE];
01018 char line[BUFFERSIZE];
01019 FILE *fp;
01020 char *tok, *p, *end;
01021 int port;
01022
01023 misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init));
01024
01025 if (!ast_strlen_zero(misdn_init)) {
01026 fp = fopen(misdn_init, "r");
01027 if (fp) {
01028 while(fgets(line, sizeof(line), fp)) {
01029 if (!strncmp(line, "nt_ptp", 6)) {
01030 for (tok = strtok_r(line,",=", &p);
01031 tok;
01032 tok = strtok_r(NULL,",=", &p)) {
01033 port = strtol(tok, &end, 10);
01034 if (end != tok && misdn_cfg_is_port_valid(port)) {
01035 misdn_cfg_lock();
01036 ptp[port] = 1;
01037 misdn_cfg_unlock();
01038 }
01039 }
01040 }
01041 }
01042 fclose(fp);
01043 } else {
01044 ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno));
01045 }
01046 }
01047 #else
01048 int i;
01049 int proto;
01050 char filename[128];
01051 FILE *fp;
01052
01053 for (i = 1; i <= max_ports; ++i) {
01054 snprintf(filename, sizeof(filename), "/sys/class/mISDN-stacks/st-%08x/protocol", i << 8);
01055 fp = fopen(filename, "r");
01056 if (!fp) {
01057 ast_log(LOG_WARNING, "Could not open %s: %s\n", filename, strerror(errno));
01058 continue;
01059 }
01060 if (fscanf(fp, "0x%08x", &proto) != 1)
01061 ast_log(LOG_WARNING, "Could not parse contents of %s!\n", filename);
01062 else
01063 ptp[i] = proto & 1<<5 ? 1 : 0;
01064 fclose(fp);
01065 }
01066 #endif
01067 }
01068
01069 static void _fill_defaults (void)
01070 {
01071 int i;
01072
01073 for (i = 0; i < NUM_PORT_ELEMENTS; ++i) {
01074 if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT))
01075 _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def);
01076 }
01077 for (i = 0; i < NUM_GEN_ELEMENTS; ++i) {
01078 if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT))
01079 _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def);
01080 }
01081 }
01082
01083 void misdn_cfg_reload (void)
01084 {
01085 misdn_cfg_init(0, 1);
01086 }
01087
01088 void misdn_cfg_destroy (void)
01089 {
01090 misdn_cfg_lock();
01091
01092 _free_port_cfg();
01093 _free_general_cfg();
01094
01095 ast_free(port_cfg);
01096 ast_free(general_cfg);
01097 ast_free(ptp);
01098 ast_free(map);
01099
01100 misdn_cfg_unlock();
01101 ast_mutex_destroy(&config_mutex);
01102 }
01103
01104 int misdn_cfg_init(int this_max_ports, int reload)
01105 {
01106 char config[] = "misdn.conf";
01107 char *cat, *p;
01108 int i;
01109 struct ast_config *cfg;
01110 struct ast_variable *v;
01111 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
01112
01113 if (!(cfg = AST_LOAD_CFG(config, config_flags))) {
01114 ast_log(LOG_WARNING, "missing file: misdn.conf\n");
01115 return -1;
01116 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
01117 return 0;
01118
01119 ast_mutex_init(&config_mutex);
01120
01121
01122 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01123
01124 misdn_cfg_lock();
01125
01126 if (this_max_ports) {
01127
01128 max_ports = this_max_ports;
01129 map = ast_calloc(MISDN_GEN_LAST + 1, sizeof(int));
01130 if (_enum_array_map())
01131 return -1;
01132 p = ast_calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *)
01133 + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt));
01134 port_cfg = (union misdn_cfg_pt **)p;
01135 p += (max_ports + 1) * sizeof(union misdn_cfg_pt *);
01136 for (i = 0; i <= max_ports; ++i) {
01137 port_cfg[i] = (union misdn_cfg_pt *)p;
01138 p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt);
01139 }
01140 general_cfg = ast_calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
01141 ptp = ast_calloc(max_ports + 1, sizeof(int));
01142 }
01143 else {
01144
01145 _free_port_cfg();
01146 _free_general_cfg();
01147 memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1));
01148 memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS);
01149 memset(ptp, 0, sizeof(int) * (max_ports + 1));
01150 }
01151
01152 cat = ast_category_browse(cfg, NULL);
01153
01154 while(cat) {
01155 v = ast_variable_browse(cfg, cat);
01156 if (!strcasecmp(cat, "general")) {
01157 _build_general_config(v);
01158 } else {
01159 _build_port_config(v, cat);
01160 }
01161 cat = ast_category_browse(cfg, cat);
01162 }
01163
01164 _fill_defaults();
01165
01166 misdn_cfg_unlock();
01167 AST_DESTROY_CFG(cfg);
01168
01169 return 0;
01170 }
01171
01172 struct ast_jb_conf *misdn_get_global_jbconf() {
01173 return &global_jbconf;
01174 }