chan_misdn_config.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2005, Christian Richter
  5. *
  6. * Christian Richter <crich@beronet.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. *
  18. */
  19. /*!
  20. * \file
  21. *
  22. * \brief chan_misdn configuration management
  23. * \author Christian Richter <crich@beronet.com>
  24. *
  25. * \ingroup channel_drivers
  26. */
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include "chan_misdn_config.h"
  30. #include <asterisk/config.h>
  31. #include <asterisk/channel.h>
  32. #include <asterisk/logger.h>
  33. #include <asterisk/lock.h>
  34. #include <asterisk/strings.h>
  35. #include <asterisk/utils.h>
  36. #define AST_LOAD_CFG ast_config_load
  37. #define AST_DESTROY_CFG ast_config_destroy
  38. #define DEF_ECHOCANCEL 128
  39. #define DEF_ECHOTRAINING 1
  40. struct msn_list {
  41. char *msn;
  42. struct msn_list *next;
  43. };
  44. struct port_config {
  45. char *name;
  46. int *rxgain;
  47. int *txgain;
  48. int *te_choose_channel;
  49. char *context;
  50. char *language;
  51. char *callerid;
  52. char *method;
  53. int *dialplan;
  54. char *nationalprefix;
  55. char *internationalprefix;
  56. int *pres;
  57. int *always_immediate;
  58. int *immediate;
  59. int *hold_allowed;
  60. int *early_bconnect;
  61. int *use_callingpres;
  62. int *echocancel;
  63. int *echocancelwhenbridged;
  64. int *echotraining;
  65. struct msn_list *msn_list;
  66. ast_group_t *callgroup; /* Call group */
  67. ast_group_t *pickupgroup; /* Pickup group */
  68. };
  69. struct general_config {
  70. int *debug;
  71. char *tracefile;
  72. int *trace_calls;
  73. char *trace_dir;
  74. int *bridging;
  75. int *stop_tone_after_first_digit;
  76. int *append_digits2exten;
  77. int *l1_info_ok;
  78. int *clear_l3;
  79. int *dynamic_crypt;
  80. char *crypt_prefix;
  81. char *crypt_keys;
  82. };
  83. /* array of port configs, default is at position 0. */
  84. static struct port_config **port_cfg;
  85. /* max number of available ports, is set on init */
  86. static int max_ports;
  87. /* general config */
  88. static struct general_config *general_cfg;
  89. /* storing the ptp flag separated to save memory */
  90. static int *ptp;
  91. static ast_mutex_t config_mutex;
  92. static inline void misdn_cfg_lock (void) {
  93. ast_mutex_lock(&config_mutex);
  94. }
  95. static inline void misdn_cfg_unlock (void) {
  96. ast_mutex_unlock(&config_mutex);
  97. }
  98. static void free_msn_list (struct msn_list* iter) {
  99. if (iter->next)
  100. free_msn_list(iter->next);
  101. if (iter->msn)
  102. free(iter->msn);
  103. free(iter);
  104. }
  105. static void free_port_cfg (void) {
  106. struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
  107. int i, j;
  108. for (i = 0; i < max_ports; i++) {
  109. if (port_cfg[i]) {
  110. for (j = 0; j < max_ports && free_list[j]; j++) {
  111. if (free_list[j] && free_list[j] == port_cfg[i])
  112. continue; /* already in list */
  113. free_list[j] = port_cfg[i];
  114. }
  115. }
  116. }
  117. #define FREE_ELEM(elem) ({ \
  118. if (free_list[i]->elem) \
  119. free(free_list[i]->elem); \
  120. })
  121. for (i = 0; i < max_ports; i++) {
  122. if (free_list[i]) {
  123. FREE_ELEM(name);
  124. FREE_ELEM(rxgain);
  125. FREE_ELEM(txgain);
  126. FREE_ELEM(te_choose_channel);
  127. FREE_ELEM(context);
  128. FREE_ELEM(language);
  129. FREE_ELEM(callerid);
  130. FREE_ELEM(method);
  131. FREE_ELEM(dialplan);
  132. FREE_ELEM(nationalprefix);
  133. FREE_ELEM(internationalprefix);
  134. FREE_ELEM(pres);
  135. FREE_ELEM(always_immediate);
  136. FREE_ELEM(immediate);
  137. FREE_ELEM(hold_allowed);
  138. FREE_ELEM(early_bconnect);
  139. FREE_ELEM(use_callingpres);
  140. FREE_ELEM(echocancel);
  141. FREE_ELEM(echocancelwhenbridged);
  142. FREE_ELEM(echotraining);
  143. if (free_list[i]->msn_list)
  144. free_msn_list(free_list[i]->msn_list);
  145. FREE_ELEM(callgroup);
  146. FREE_ELEM(pickupgroup);
  147. free(free_list[i]);
  148. }
  149. }
  150. free(free_list);
  151. }
  152. static void free_general_cfg (void) {
  153. #define FREE_GEN_ELEM(elem) ({ \
  154. if (general_cfg->elem) \
  155. free(general_cfg->elem); \
  156. })
  157. FREE_GEN_ELEM(debug);
  158. FREE_GEN_ELEM(tracefile);
  159. FREE_GEN_ELEM(trace_calls);
  160. FREE_GEN_ELEM(trace_dir);
  161. FREE_GEN_ELEM(bridging);
  162. FREE_GEN_ELEM(stop_tone_after_first_digit);
  163. FREE_GEN_ELEM(append_digits2exten);
  164. FREE_GEN_ELEM(l1_info_ok);
  165. FREE_GEN_ELEM(clear_l3);
  166. FREE_GEN_ELEM(dynamic_crypt);
  167. FREE_GEN_ELEM(crypt_prefix);
  168. FREE_GEN_ELEM(crypt_keys);
  169. }
  170. #define GET_PORTCFG_STRCPY(item) ({ \
  171. char *temp; \
  172. if (port_cfg[port] && port_cfg[port]->item) \
  173. temp = port_cfg[port]->item; \
  174. else \
  175. temp = port_cfg[0]->item; \
  176. if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \
  177. memset(buf, 0, 1); \
  178. })
  179. #define GET_GENCFG_STRCPY(item) ({ \
  180. if (general_cfg && general_cfg->item) { \
  181. if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \
  182. memset(buf, 0, 1); \
  183. } else \
  184. memset(buf, 0, 1); \
  185. })
  186. #define GET_PORTCFG_MEMCPY(item) ({ \
  187. typeof(port_cfg[0]->item) temp; \
  188. if (port_cfg[port] && port_cfg[port]->item) \
  189. temp = port_cfg[port]->item; \
  190. else \
  191. temp = port_cfg[0]->item; \
  192. if (temp) { \
  193. int l = sizeof(*temp); \
  194. if (l > bufsize) \
  195. memset(buf, 0, bufsize); \
  196. else \
  197. memcpy(buf, temp, l); \
  198. } else \
  199. memset(buf, 0, bufsize); \
  200. })
  201. #define GET_GENCFG_MEMCPY(item) ({ \
  202. if (general_cfg && general_cfg->item) { \
  203. typeof(general_cfg->item) temp = general_cfg->item; \
  204. int l = sizeof(*temp); \
  205. if (l > bufsize) \
  206. memset(buf, 0, bufsize); \
  207. else \
  208. memcpy(buf, temp, l); \
  209. } else \
  210. memset(buf, 0, bufsize); \
  211. })
  212. void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) {
  213. if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
  214. memset(buf, 0, bufsize);
  215. ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port);
  216. return;
  217. }
  218. misdn_cfg_lock();
  219. switch (elem) {
  220. /* port config elements */
  221. case MISDN_CFG_PTP: if (sizeof(ptp[port]) <= bufsize)
  222. memcpy(buf, &ptp[port], sizeof(ptp[port]));
  223. else
  224. buf = 0; /* error, should not happen */
  225. break;
  226. case MISDN_CFG_GROUPNAME: GET_PORTCFG_STRCPY(name);
  227. break;
  228. case MISDN_CFG_RXGAIN: GET_PORTCFG_MEMCPY(rxgain);
  229. break;
  230. case MISDN_CFG_TXGAIN: GET_PORTCFG_MEMCPY(txgain);
  231. break;
  232. case MISDN_CFG_TE_CHOOSE_CHANNEL:
  233. GET_PORTCFG_MEMCPY(te_choose_channel);
  234. break;
  235. case MISDN_CFG_CONTEXT: GET_PORTCFG_STRCPY(context);
  236. break;
  237. case MISDN_CFG_LANGUAGE: GET_PORTCFG_STRCPY(language);
  238. break;
  239. case MISDN_CFG_CALLERID: GET_PORTCFG_STRCPY(callerid);
  240. break;
  241. case MISDN_CFG_METHOD: GET_PORTCFG_STRCPY(method);
  242. break;
  243. case MISDN_CFG_DIALPLAN: GET_PORTCFG_MEMCPY(dialplan);
  244. break;
  245. case MISDN_CFG_NATPREFIX: GET_PORTCFG_STRCPY(nationalprefix);
  246. break;
  247. case MISDN_CFG_INTERNATPREFIX:
  248. GET_PORTCFG_STRCPY(internationalprefix);
  249. break;
  250. case MISDN_CFG_PRES: GET_PORTCFG_MEMCPY(pres);
  251. break;
  252. case MISDN_CFG_ALWAYS_IMMEDIATE:
  253. GET_PORTCFG_MEMCPY(always_immediate);
  254. break;
  255. case MISDN_CFG_IMMEDIATE: GET_PORTCFG_MEMCPY(immediate);
  256. break;
  257. case MISDN_CFG_HOLD_ALLOWED:
  258. GET_PORTCFG_MEMCPY(hold_allowed);
  259. break;
  260. case MISDN_CFG_EARLY_BCONNECT:
  261. GET_PORTCFG_MEMCPY(early_bconnect);
  262. break;
  263. case MISDN_CFG_USE_CALLINGPRES:
  264. GET_PORTCFG_MEMCPY(use_callingpres);
  265. break;
  266. case MISDN_CFG_ECHOCANCEL:
  267. GET_PORTCFG_MEMCPY(echocancel );
  268. break;
  269. case MISDN_CFG_ECHOCANCELWHENBRIDGED:
  270. GET_PORTCFG_MEMCPY(echocancelwhenbridged);
  271. break;
  272. case MISDN_CFG_ECHOTRAINING:
  273. GET_PORTCFG_MEMCPY(echotraining);
  274. break;
  275. case MISDN_CFG_CALLGROUP: GET_PORTCFG_MEMCPY(callgroup);
  276. break;
  277. case MISDN_CFG_PICKUPGROUP: GET_PORTCFG_MEMCPY(pickupgroup);
  278. break;
  279. /* general config elements */
  280. case MISDN_GEN_DEBUG: GET_GENCFG_MEMCPY(debug);
  281. break;
  282. case MISDN_GEN_TRACEFILE: GET_GENCFG_STRCPY(tracefile);
  283. break;
  284. case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls);
  285. break;
  286. case MISDN_GEN_TRACE_DIR: GET_GENCFG_STRCPY(trace_dir);
  287. break;
  288. case MISDN_GEN_BRIDGING: GET_GENCFG_MEMCPY(bridging);
  289. break;
  290. case MISDN_GEN_STOP_TONE: GET_GENCFG_MEMCPY(stop_tone_after_first_digit);
  291. break;
  292. case MISDN_GEN_APPEND_DIGITS2EXTEN:
  293. GET_GENCFG_MEMCPY(append_digits2exten);
  294. break;
  295. case MISDN_GEN_L1_INFO_OK: GET_GENCFG_MEMCPY(l1_info_ok);
  296. break;
  297. case MISDN_GEN_CLEAR_L3: GET_GENCFG_MEMCPY(clear_l3);
  298. break;
  299. case MISDN_GEN_DYNAMIC_CRYPT: GET_GENCFG_MEMCPY(dynamic_crypt);
  300. break;
  301. case MISDN_GEN_CRYPT_PREFIX: GET_GENCFG_STRCPY(crypt_prefix);
  302. break;
  303. case MISDN_GEN_CRYPT_KEYS: GET_GENCFG_STRCPY(crypt_keys);
  304. break;
  305. default: memset(buf, 0, bufsize);
  306. }
  307. misdn_cfg_unlock();
  308. }
  309. int misdn_cfg_is_msn_valid (int port, char* msn) {
  310. if (!misdn_cfg_is_port_valid(port)) {
  311. ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port);
  312. return 0;
  313. }
  314. struct msn_list *iter;
  315. misdn_cfg_lock();
  316. if (port_cfg[port]->msn_list)
  317. iter = port_cfg[port]->msn_list;
  318. else
  319. iter = port_cfg[0]->msn_list;
  320. for (; iter; iter = iter->next)
  321. if (*(iter->msn) == '*' || !strcasecmp(iter->msn, msn)) {
  322. misdn_cfg_unlock();
  323. return 1;
  324. }
  325. misdn_cfg_unlock();
  326. return 0;
  327. }
  328. int misdn_cfg_is_port_valid (int port) {
  329. misdn_cfg_lock();
  330. if (port < 1 || port > max_ports) {
  331. misdn_cfg_unlock();
  332. return 0;
  333. }
  334. int valid = (port_cfg[port] != NULL);
  335. misdn_cfg_unlock();
  336. return valid;
  337. }
  338. int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) {
  339. int i, re = 0;
  340. char *method = NULL;
  341. misdn_cfg_lock();
  342. for (i = 0; i < max_ports; i++) {
  343. if (port_cfg[i]) {
  344. if (!strcasecmp(port_cfg[i]->name, group))
  345. method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method;
  346. }
  347. }
  348. if (method) {
  349. switch (meth) {
  350. case METHOD_STANDARD: re = !strcasecmp(method, "standard");
  351. break;
  352. case METHOD_ROUND_ROBIN: re = !strcasecmp(method, "round_robin");
  353. break;
  354. }
  355. }
  356. misdn_cfg_unlock();
  357. return re;
  358. }
  359. void misdn_cfg_get_ports_string (char *ports) {
  360. *ports = 0;
  361. char tmp[16];
  362. int l;
  363. misdn_cfg_lock();
  364. int i = 1;
  365. for (; i <= max_ports; i++) {
  366. if (port_cfg[i]) {
  367. if (ptp[i])
  368. sprintf(tmp, "%dptp,", i);
  369. else
  370. sprintf(tmp, "%d,", i);
  371. strcat(ports, tmp);
  372. }
  373. }
  374. misdn_cfg_unlock();
  375. if ((l = strlen(ports)))
  376. ports[l-1] = 0;
  377. }
  378. #define GET_CFG_STRING(typestr, type) ({ \
  379. if (port_cfg[port] && port_cfg[port]->type) \
  380. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \
  381. else \
  382. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \
  383. }) \
  384. #define GET_GEN_STRING(typestr, type) ({ \
  385. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \
  386. }) \
  387. #define GET_CFG_INT(typestr, type) ({ \
  388. if (port_cfg[port] && port_cfg[port]->type) \
  389. snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \
  390. else \
  391. snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \
  392. }) \
  393. #define GET_GEN_INT(typestr, type) ({ \
  394. snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \
  395. }) \
  396. #define GET_CFG_BOOL(typestr, type, yes, no) ({ \
  397. int bool; \
  398. if (port_cfg[port] && port_cfg[port]->type) \
  399. bool = *port_cfg[port]->type; \
  400. else \
  401. bool = *port_cfg[0]->type; \
  402. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
  403. }) \
  404. #define GET_CFG_HYBRID(typestr, type, yes, no) ({ \
  405. int bool; \
  406. if (port_cfg[port] && port_cfg[port]->type) \
  407. bool = *port_cfg[port]->type; \
  408. else \
  409. bool = *port_cfg[0]->type; \
  410. if (bool == 1 || bool == 0) \
  411. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \
  412. else \
  413. snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \
  414. }) \
  415. #define GET_GEN_BOOL(typestr, type, yes, no) ({ \
  416. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \
  417. }) \
  418. #define GET_CFG_AST_GROUP_T(typestr, type) ({ \
  419. ast_group_t *tmp; \
  420. if (port_cfg[port] && port_cfg[port]->type) \
  421. tmp = port_cfg[port]->type; \
  422. else \
  423. tmp = port_cfg[0]->type; \
  424. if (tmp) { \
  425. char tmpbuf[256]; \
  426. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \
  427. } else \
  428. snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \
  429. }) \
  430. void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) {
  431. if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) {
  432. *buf = 0;
  433. ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port);
  434. return;
  435. }
  436. char begin[] = " -> ";
  437. misdn_cfg_lock();
  438. switch (elem) {
  439. case MISDN_CFG_PTP: snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no");
  440. break;
  441. case MISDN_CFG_GROUPNAME: GET_CFG_STRING(GROUPNAME, name);
  442. break;
  443. case MISDN_CFG_RXGAIN: GET_CFG_INT(RXGAIN, rxgain);
  444. break;
  445. case MISDN_CFG_TXGAIN: GET_CFG_INT(TXGAIN, txgain);
  446. break;
  447. case MISDN_CFG_TE_CHOOSE_CHANNEL:
  448. GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no);
  449. break;
  450. case MISDN_CFG_CONTEXT: GET_CFG_STRING(CONTEXT, context);
  451. break;
  452. case MISDN_CFG_LANGUAGE: GET_CFG_STRING(LANGUAGE, language);
  453. break;
  454. case MISDN_CFG_CALLERID: GET_CFG_STRING(CALLERID, callerid);
  455. break;
  456. case MISDN_CFG_METHOD: GET_CFG_STRING(METHOD, method);
  457. break;
  458. case MISDN_CFG_DIALPLAN: GET_CFG_INT(DIALPLAN, dialplan);
  459. break;
  460. case MISDN_CFG_NATPREFIX: GET_CFG_STRING(NATIONALPREFIX, nationalprefix);
  461. break;
  462. case MISDN_CFG_INTERNATPREFIX:
  463. GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix);
  464. break;
  465. case MISDN_CFG_PRES: GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened);
  466. break;
  467. case MISDN_CFG_ALWAYS_IMMEDIATE:
  468. GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no);
  469. break;
  470. case MISDN_CFG_IMMEDIATE: GET_CFG_BOOL(IMMEDIATE, immediate, yes, no);
  471. break;
  472. case MISDN_CFG_HOLD_ALLOWED:
  473. GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no);
  474. break;
  475. case MISDN_CFG_EARLY_BCONNECT:
  476. GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no);
  477. break;
  478. case MISDN_CFG_USE_CALLINGPRES:
  479. GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no);
  480. break;
  481. case MISDN_CFG_ECHOCANCEL: GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no);
  482. break;
  483. case MISDN_CFG_ECHOCANCELWHENBRIDGED:
  484. GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no);
  485. break;
  486. case MISDN_CFG_ECHOTRAINING:
  487. GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no);
  488. break;
  489. case MISDN_CFG_CALLGROUP: GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup);
  490. break;
  491. case MISDN_CFG_PICKUPGROUP: GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup);
  492. break;
  493. case MISDN_CFG_MSNS: {
  494. char tmpbuffer[BUFFERSIZE];
  495. tmpbuffer[0] = 0;
  496. struct msn_list *iter;
  497. if (port_cfg[port]->msn_list)
  498. iter = port_cfg[port]->msn_list;
  499. else
  500. iter = port_cfg[0]->msn_list;
  501. if (iter) {
  502. for (; iter; iter = iter->next)
  503. sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn);
  504. tmpbuffer[strlen(tmpbuffer)-2] = 0;
  505. }
  506. snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \
  507. }
  508. break;
  509. /* general config elements */
  510. case MISDN_GEN_DEBUG: GET_GEN_INT(DEBUG_LEVEL, debug);
  511. break;
  512. case MISDN_GEN_TRACEFILE: GET_GEN_STRING(TRACEFILE, tracefile);
  513. break;
  514. case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false);
  515. break;
  516. case MISDN_GEN_TRACE_DIR: GET_GEN_STRING(TRACE_DIR, trace_dir);
  517. break;
  518. case MISDN_GEN_BRIDGING: GET_GEN_BOOL(BRIDGING, bridging, yes, no);
  519. break;
  520. case MISDN_GEN_STOP_TONE: GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no);
  521. break;
  522. case MISDN_GEN_APPEND_DIGITS2EXTEN:
  523. GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no);
  524. break;
  525. case MISDN_GEN_L1_INFO_OK: GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no);
  526. break;
  527. case MISDN_GEN_CLEAR_L3: GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no);
  528. break;
  529. case MISDN_GEN_DYNAMIC_CRYPT:
  530. GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no);
  531. break;
  532. case MISDN_GEN_CRYPT_PREFIX:
  533. GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix);
  534. break;
  535. case MISDN_GEN_CRYPT_KEYS: GET_GEN_STRING(CRYPT_KEYS, crypt_keys);
  536. break;
  537. default: *buf = 0;
  538. break;
  539. }
  540. misdn_cfg_unlock();
  541. }
  542. int misdn_cfg_get_next_port (int port) {
  543. misdn_cfg_lock();
  544. for (port++; port <= max_ports; port++) {
  545. if (port_cfg[port]) {
  546. misdn_cfg_unlock();
  547. return port;
  548. }
  549. }
  550. misdn_cfg_unlock();
  551. return -1;
  552. }
  553. int misdn_cfg_get_next_port_spin (int port) {
  554. int ret = misdn_cfg_get_next_port(port);
  555. if (ret > 0)
  556. return ret;
  557. return misdn_cfg_get_next_port(0);
  558. }
  559. #define PARSE_GEN_INT(item) ({ \
  560. if (!strcasecmp(v->name, #item)) { \
  561. int temp; \
  562. if (!sscanf(v->value, "%d", &temp)) { \
  563. 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); \
  564. } else { \
  565. general_cfg->item = (int *)malloc(sizeof(int)); \
  566. memcpy(general_cfg->item, &temp, sizeof(int)); \
  567. } \
  568. continue; \
  569. } \
  570. }) \
  571. #define PARSE_GEN_BOOL(item) ({ \
  572. if (!strcasecmp(v->name, #item)) { \
  573. general_cfg->item = (int *)malloc(sizeof(int)); \
  574. *(general_cfg->item) = ast_true(v->value)?1:0; \
  575. continue; \
  576. } \
  577. })
  578. #define PARSE_GEN_STR(item) ({ \
  579. if (!strcasecmp(v->name, #item)) { \
  580. int l = strlen(v->value); \
  581. if (l) { \
  582. general_cfg->item = (char *)calloc(l+1, sizeof(char)); \
  583. strncpy(general_cfg->item,v->value, l); \
  584. } \
  585. continue; \
  586. } \
  587. })
  588. static void build_general_config(struct ast_variable *v) {
  589. if (!v)
  590. return;
  591. for (; v; v = v->next) {
  592. PARSE_GEN_INT(debug);
  593. PARSE_GEN_STR(tracefile);
  594. PARSE_GEN_BOOL(trace_calls);
  595. PARSE_GEN_STR(trace_dir);
  596. PARSE_GEN_BOOL(bridging);
  597. PARSE_GEN_BOOL(stop_tone_after_first_digit);
  598. PARSE_GEN_BOOL(append_digits2exten);
  599. PARSE_GEN_BOOL(l1_info_ok);
  600. PARSE_GEN_BOOL(clear_l3);
  601. PARSE_GEN_BOOL(dynamic_crypt);
  602. PARSE_GEN_STR(crypt_prefix);
  603. PARSE_GEN_STR(crypt_keys);
  604. }
  605. }
  606. #define PARSE_CFG_HYBRID(item, def) ({ \
  607. if (!strcasecmp(v->name, #item)) { \
  608. new->item = (int *)malloc(sizeof(int)); \
  609. if (!sscanf(v->value, "%d", new->item)) { \
  610. if (ast_true(v->value)) \
  611. *new->item = def; \
  612. else \
  613. *new->item = 0; \
  614. } \
  615. continue; \
  616. } \
  617. }) \
  618. #define PARSE_CFG_INT(item) ({ \
  619. if (!strcasecmp(v->name, #item)) { \
  620. new->item = (int *)malloc(sizeof(int)); \
  621. if (!sscanf(v->value, "%d", new->item)) { \
  622. 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); \
  623. free(new->item); \
  624. new->item = NULL; \
  625. } \
  626. continue; \
  627. } \
  628. }) \
  629. #define PARSE_CFG_BOOL(item) ({ \
  630. if (!strcasecmp(v->name, #item)) { \
  631. new->item = (int *)malloc(sizeof(int)); \
  632. *(new->item) = ast_true(v->value)?1:0; \
  633. continue; \
  634. } \
  635. })
  636. #define PARSE_CFG_STR(item) ({ \
  637. if (!strcasecmp(v->name, #item)) { \
  638. int l = strlen(v->value); \
  639. if (l) { \
  640. new->item = (char *)calloc(l+1, sizeof(char)); \
  641. strncpy(new->item,v->value,l); \
  642. } \
  643. continue; \
  644. } \
  645. })
  646. static void build_port_config(struct ast_variable *v, char *cat) {
  647. if (!v || !cat)
  648. return;
  649. int cfg_for_ports[max_ports + 1];
  650. int i = 0;
  651. for (; i < (max_ports + 1); i++) {
  652. cfg_for_ports[i] = 0;
  653. }
  654. /* we store the default config at position 0 */
  655. if (!strcasecmp(cat, "default")) {
  656. cfg_for_ports[0] = 1;
  657. }
  658. struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config));
  659. {
  660. int l = strlen(cat);
  661. new->name = (char *)calloc(l+1, sizeof(char));
  662. strncpy(new->name, cat, l);
  663. }
  664. for (; v; v=v->next) {
  665. if (!strcasecmp(v->name, "ports")) {
  666. /* TODO check for value not beeing set, like PORTS= */
  667. char *iter;
  668. char *value = v->value;
  669. while ((iter = strchr(value, ',')) != NULL) {
  670. *iter = 0;
  671. /* strip spaces */
  672. while (*value && *value == ' ') {
  673. value++;
  674. }
  675. /* TODO check for char not 0-9 */
  676. if (*value){
  677. int p = atoi(value);
  678. if (p <= max_ports && p > 0) {
  679. cfg_for_ports[p] = 1;
  680. if (strstr(value, "ptp"))
  681. ptp[p] = 1;
  682. } else
  683. 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);
  684. value = ++iter;
  685. }
  686. }
  687. /* the remaining or the only one */
  688. /* strip spaces */
  689. while (*value && *value == ' ') {
  690. value++;
  691. }
  692. /* TODO check for char not 0-9 */
  693. if (*value) {
  694. int p = atoi(value);
  695. if (p <= max_ports && p > 0) {
  696. cfg_for_ports[p] = 1;
  697. if (strstr(value, "ptp"))
  698. ptp[p] = 1;
  699. } else
  700. 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);
  701. }
  702. continue;
  703. }
  704. PARSE_CFG_STR(context);
  705. PARSE_CFG_INT(dialplan);
  706. PARSE_CFG_STR(nationalprefix);
  707. PARSE_CFG_STR(internationalprefix);
  708. PARSE_CFG_STR(language);
  709. if (!strcasecmp(v->name, "presentation")) {
  710. if (v->value && strlen(v->value)) {
  711. new->pres = (int *)malloc(sizeof(int));
  712. if (!strcasecmp(v->value, "allowed")) {
  713. *(new->pres) = 1;
  714. }
  715. /* TODO: i assume if it is not "allowed", it is "not_screened" */
  716. else {
  717. *(new->pres) = 0;
  718. }
  719. }
  720. continue;
  721. }
  722. PARSE_CFG_INT(rxgain);
  723. PARSE_CFG_INT(txgain);
  724. PARSE_CFG_BOOL(te_choose_channel);
  725. PARSE_CFG_BOOL(immediate);
  726. PARSE_CFG_BOOL(always_immediate);
  727. PARSE_CFG_BOOL(hold_allowed);
  728. PARSE_CFG_BOOL(early_bconnect);
  729. PARSE_CFG_BOOL(use_callingpres);
  730. PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL);
  731. PARSE_CFG_BOOL(echocancelwhenbridged);
  732. PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING);
  733. PARSE_CFG_STR(callerid);
  734. PARSE_CFG_STR(method);
  735. if (!strcasecmp(v->name, "msns")) {
  736. /* TODO check for value not beeing set, like msns= */
  737. char *iter;
  738. char *value = v->value;
  739. while ((iter = strchr(value, ',')) != NULL) {
  740. *iter = 0;
  741. /* strip spaces */
  742. while (*value && *value == ' ') {
  743. value++;
  744. }
  745. /* TODO check for char not 0-9 */
  746. if (*value){
  747. int l = strlen(value);
  748. if (l) {
  749. struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
  750. ml->msn = (char *)calloc(l+1, sizeof(char));
  751. strncpy(ml->msn,value,l);
  752. ml->next = new->msn_list;
  753. new->msn_list = ml;
  754. }
  755. value = ++iter;
  756. }
  757. }
  758. /* the remaining or the only one */
  759. /* strip spaces */
  760. while (*value && *value == ' ') {
  761. value++;
  762. }
  763. /* TODO check for char not 0-9 */
  764. if (*value) {
  765. int l = strlen(value);
  766. if (l) {
  767. struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list));
  768. ml->msn = (char *)calloc(l+1, sizeof(char));
  769. strncpy(ml->msn,value,l);
  770. ml->next = new->msn_list;
  771. new->msn_list = ml;
  772. }
  773. }
  774. continue;
  775. }
  776. if (!strcasecmp(v->name, "callgroup")) {
  777. new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
  778. *(new->callgroup)=ast_get_group(v->value);
  779. continue;
  780. }
  781. if (!strcasecmp(v->name, "pickupgroup")) {
  782. new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t));
  783. *(new->pickupgroup)=ast_get_group(v->value);
  784. continue;
  785. }
  786. }
  787. /* store the new config in our array of port configs */
  788. for (i = 0; i < (max_ports + 1); i++) {
  789. if (cfg_for_ports[i])
  790. port_cfg[i] = new;
  791. }
  792. }
  793. static void fill_defaults (void) {
  794. /* general defaults */
  795. if (!general_cfg->debug)
  796. general_cfg->debug = (int*)calloc(1, sizeof(int));
  797. if (!general_cfg->trace_calls)
  798. general_cfg->trace_calls = (int*)calloc(1, sizeof(int));
  799. if (!general_cfg->trace_dir) {
  800. general_cfg->trace_dir = (char *)malloc(10 * sizeof(char));
  801. sprintf(general_cfg->trace_dir, "/var/log/");
  802. }
  803. if (!general_cfg->bridging) {
  804. general_cfg->bridging = (int*)malloc(sizeof(int));
  805. *general_cfg->bridging = 1;
  806. }
  807. if (!general_cfg->stop_tone_after_first_digit) {
  808. general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int));
  809. *general_cfg->stop_tone_after_first_digit = 1;
  810. }
  811. if (!general_cfg->append_digits2exten) {
  812. general_cfg->append_digits2exten = (int*)malloc(sizeof(int));
  813. *general_cfg->append_digits2exten = 1;
  814. }
  815. if (!general_cfg->l1_info_ok) {
  816. general_cfg->l1_info_ok = (int*)malloc(sizeof(int));
  817. *general_cfg->l1_info_ok = 1;
  818. }
  819. if (!general_cfg->clear_l3)
  820. general_cfg->clear_l3 =(int*)calloc(1, sizeof(int));
  821. if (!general_cfg->dynamic_crypt)
  822. general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int));
  823. /* defaults for default port config */
  824. if (!port_cfg[0])
  825. port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config));
  826. if (!port_cfg[0]->name) {
  827. port_cfg[0]->name = (char *)malloc(8 * sizeof(char));
  828. sprintf(port_cfg[0]->name, "default");
  829. }
  830. if (!port_cfg[0]->rxgain)
  831. port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int));
  832. if (!port_cfg[0]->txgain)
  833. port_cfg[0]->txgain = (int *)calloc(1, sizeof(int));
  834. if (!port_cfg[0]->te_choose_channel)
  835. port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int));
  836. if (!port_cfg[0]->context) {
  837. port_cfg[0]->context = (char *)malloc(8 * sizeof(char));
  838. sprintf(port_cfg[0]->context, "default");
  839. }
  840. if (!port_cfg[0]->language) {
  841. port_cfg[0]->language = (char *)malloc(3 * sizeof(char));
  842. sprintf(port_cfg[0]->language, "en");
  843. }
  844. if (!port_cfg[0]->callerid)
  845. port_cfg[0]->callerid = (char *)calloc(1, sizeof(char));
  846. if (!port_cfg[0]->method) {
  847. port_cfg[0]->method = (char *)malloc(9 * sizeof(char));
  848. sprintf(port_cfg[0]->method, "standard");
  849. }
  850. if (!port_cfg[0]->dialplan)
  851. port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int));
  852. if (!port_cfg[0]->nationalprefix) {
  853. port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char));
  854. sprintf(port_cfg[0]->nationalprefix, "0");
  855. }
  856. if (!port_cfg[0]->internationalprefix) {
  857. port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char));
  858. sprintf(port_cfg[0]->internationalprefix, "00");
  859. }
  860. if (!port_cfg[0]->pres) {
  861. port_cfg[0]->pres = (int *)malloc(sizeof(int));
  862. *port_cfg[0]->pres = 1;
  863. }
  864. if (!port_cfg[0]->always_immediate)
  865. port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int));
  866. if (!port_cfg[0]->immediate)
  867. port_cfg[0]->immediate = (int *)calloc(1, sizeof(int));
  868. if (!port_cfg[0]->hold_allowed)
  869. port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int));
  870. if (!port_cfg[0]->early_bconnect) {
  871. port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int));
  872. *port_cfg[0]->early_bconnect = 1;
  873. }
  874. if (!port_cfg[0]->echocancel)
  875. port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int));
  876. if (!port_cfg[0]->echocancelwhenbridged)
  877. port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int));
  878. if (!port_cfg[0]->echotraining) {
  879. port_cfg[0]->echotraining=(int *)malloc(sizeof(int));
  880. *port_cfg[0]->echotraining = 1;
  881. }
  882. if (!port_cfg[0]->use_callingpres) {
  883. port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int));
  884. *port_cfg[0]->use_callingpres = 1;
  885. }
  886. if (!port_cfg[0]->msn_list) {
  887. port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list));
  888. port_cfg[0]->msn_list->next = NULL;
  889. port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char));
  890. *(port_cfg[0]->msn_list->msn) = '*';
  891. }
  892. }
  893. void misdn_cfg_reload (void) {
  894. misdn_cfg_init (0);
  895. }
  896. void misdn_cfg_destroy (void) {
  897. misdn_cfg_lock();
  898. free_port_cfg();
  899. free_general_cfg();
  900. free(port_cfg);
  901. free(general_cfg);
  902. free(ptp);
  903. misdn_cfg_unlock();
  904. ast_mutex_destroy(&config_mutex);
  905. }
  906. void misdn_cfg_init (int this_max_ports)
  907. {
  908. char config[]="misdn.conf";
  909. struct ast_config *cfg;
  910. cfg = AST_LOAD_CFG(config);
  911. if (!cfg) {
  912. ast_log(LOG_WARNING,"no misdn.conf ?\n");
  913. return;
  914. }
  915. misdn_cfg_lock();
  916. if (this_max_ports) {
  917. /* this is the first run */
  918. max_ports = this_max_ports;
  919. port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *));
  920. general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config));
  921. ptp = (int *)calloc(max_ports + 1, sizeof(int));
  922. }
  923. else {
  924. free_port_cfg();
  925. free_general_cfg();
  926. port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1));
  927. general_cfg = memset(general_cfg, 0, sizeof(struct general_config));
  928. ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1));
  929. }
  930. char *cat;
  931. cat = ast_category_browse(cfg, NULL);
  932. while(cat) {
  933. struct ast_variable *v=ast_variable_browse(cfg,cat);
  934. if (!strcasecmp(cat,"general")) {
  935. build_general_config (v);
  936. } else {
  937. build_port_config (v, cat);
  938. }
  939. cat=ast_category_browse(cfg,cat);
  940. }
  941. fill_defaults();
  942. misdn_cfg_unlock();
  943. AST_DESTROY_CFG(cfg);
  944. }