Line 0
Link Here
|
|
|
1 |
/* |
2 |
* Asterisk -- A telephony toolkit for Linux. |
3 |
* |
4 |
* res_config_ldap.c <ldap plugin for RealTime configuration engine> |
5 |
* |
6 |
* Todo: |
7 |
* - config_ldap for the static stuff |
8 |
* - useful default base dn |
9 |
* - testing / bugfixing :-) |
10 |
* - check for mem leaks |
11 |
* |
12 |
* v0.7 - (12-12-05) - test res and strncat cleanup |
13 |
* v0.6 - (25-11-05) - less verbose output |
14 |
* v0.5 - (24-11-05) - makefile cleanups |
15 |
* v0.4 - (22-09-05) - improved reconnect ( Norbert Graf ) |
16 |
* v0.3 - (18-09-05) - sort by initfield |
17 |
* - use ldap_initialize() |
18 |
* v0.2 - (14-09-05) - prepend ast to config values |
19 |
* - minor bugfixes & cleanups |
20 |
* v0.1 - (11-09-05) - Initial version based on res_config_mysql from asterisk-addons |
21 |
*/ |
22 |
|
23 |
#include <asterisk/channel.h> |
24 |
#include <asterisk/logger.h> |
25 |
#include <asterisk/config.h> |
26 |
#include <asterisk/module.h> |
27 |
#include <asterisk/lock.h> |
28 |
#include <asterisk/options.h> |
29 |
#include <asterisk/cli.h> |
30 |
#include <asterisk/utils.h> |
31 |
#include <stdlib.h> |
32 |
#include <stdio.h> |
33 |
#include <string.h> |
34 |
#include <ldap.h> |
35 |
|
36 |
static char *res_config_ldap_desc = "LDAP RealTime Configuration Driver"; |
37 |
|
38 |
AST_MUTEX_DEFINE_STATIC(ldap_lock); |
39 |
#define RES_CONFIG_LDAP_CONF "res_ldap.conf" |
40 |
#define QUERY_SIZE 512 |
41 |
#define OPTION_SIZE 100 |
42 |
static char ldapuri[80]; |
43 |
static char ldapuser[80]; |
44 |
static char ldappass[80]; |
45 |
static char ldapbasedn[80]; |
46 |
static int connected; |
47 |
static time_t connect_time; |
48 |
static int errorcount = 0; |
49 |
static int parse_config(void); |
50 |
static LDAP *ldap_reconnect(); |
51 |
void ldap_disconnect(LDAP *ldap); |
52 |
static int realtime_ldap_status(int fd, int argc, char **argv); |
53 |
int ldap_get_value_s(LDAP *ldap, const char *ldapbasedn,const char filter[QUERY_SIZE], char *attrs[], char *attrvalues[]); |
54 |
|
55 |
typedef struct list |
56 |
{ |
57 |
char *string[QUERY_SIZE]; |
58 |
char *members[QUERY_SIZE]; |
59 |
struct list *next; |
60 |
} context; |
61 |
|
62 |
context *anf = NULL; |
63 |
|
64 |
STANDARD_LOCAL_USER; |
65 |
|
66 |
LOCAL_USER_DECL; |
67 |
|
68 |
static char cli_realtime_ldap_status_usage[] = |
69 |
"Usage: realtime ldap status\n" |
70 |
" Shows connection information for the LDAP RealTime driver\n"; |
71 |
|
72 |
static struct ast_cli_entry cli_realtime_ldap_status = { |
73 |
{ "realtime", "ldap", "status", NULL }, realtime_ldap_status, |
74 |
"Shows connection information for the LDAP RealTime driver", cli_realtime_ldap_status_usage, NULL }; |
75 |
|
76 |
static struct ast_variable *realtime_ldap(const char *database, const char *table, va_list ap) |
77 |
{ |
78 |
int numFields; |
79 |
char *chunk; |
80 |
char *op; |
81 |
struct ast_variable *var=NULL, *prev=NULL; |
82 |
const char *newparam, *newval; |
83 |
char query[QUERY_SIZE]; |
84 |
char query2[QUERY_SIZE]; |
85 |
int i=0; |
86 |
int j=0; |
87 |
int search; |
88 |
LDAPMessage *res, *res2; |
89 |
BerElement *ber; |
90 |
char **values; |
91 |
char *attr; |
92 |
LDAP *ldap; |
93 |
|
94 |
ast_log(LOG_DEBUG, "realtime_ldap\n"); |
95 |
|
96 |
if(!table) { |
97 |
ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n"); |
98 |
return NULL; |
99 |
} |
100 |
|
101 |
/* Get the first parameter and first value in our list of passed paramater/value pairs */ |
102 |
newparam = va_arg(ap, const char *); |
103 |
newval = va_arg(ap, const char *); |
104 |
if(!newparam || !newval) { |
105 |
ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); |
106 |
return NULL; |
107 |
} |
108 |
|
109 |
/* Create the first part of the query using the first parameter/value pairs we just extracted |
110 |
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ |
111 |
|
112 |
if(!strchr(newparam, ' ')) op = "="; else op = ""; |
113 |
|
114 |
snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s%s%s))", table, newparam, op, newval); |
115 |
while((newparam = va_arg(ap, const char *))) { |
116 |
i++; |
117 |
newval = va_arg(ap, const char *); |
118 |
if(!strchr(newparam, ' ')) op = "="; else op = ""; |
119 |
snprintf(query + strlen(query), sizeof(query) - strlen(query), "(ast%s%s%s))", newparam, op, newval); |
120 |
} |
121 |
va_end(ap); |
122 |
query2[0] = '\0'; |
123 |
for ( j=0; j<i; j++ ) |
124 |
strncat(query2, "&", sizeof(query2)-1); |
125 |
|
126 |
strncat(query2, query, sizeof(query2)-1); |
127 |
|
128 |
ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query2); |
129 |
/* We now have our complete statement; Lets connect to the server and execute it. */ |
130 |
ldap = ldap_reconnect(); |
131 |
if(!ldap) { |
132 |
return NULL; |
133 |
} |
134 |
ast_mutex_lock(&ldap_lock); |
135 |
search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query2, NULL, 0, &res); |
136 |
if(search != LDAP_SUCCESS) { |
137 |
ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n"); |
138 |
ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", query2); |
139 |
if ( res != NULL ) { |
140 |
ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(search)); |
141 |
} |
142 |
ldap_disconnect(ldap); |
143 |
ast_mutex_unlock(&ldap_lock); |
144 |
return NULL; |
145 |
} |
146 |
numFields = ldap_count_entries(ldap, res); |
147 |
if ( numFields > 0 ) { |
148 |
res2 = ldap_first_entry(ldap, res); |
149 |
while(res2) { |
150 |
attr = ldap_first_attribute(ldap, res, &ber); |
151 |
while (attr) { |
152 |
if ( attr && !strncmp(attr, "ast", 3) ) { |
153 |
values = ldap_get_values(ldap, res, attr); |
154 |
attr += 3; |
155 |
i = 0; |
156 |
while(values[i]) { |
157 |
chunk = strsep((char **) &values[i], ";"); |
158 |
if(chunk && !ast_strlen_zero(ast_strip(chunk))) { |
159 |
// ast_log(LOG_WARNING, "%s-%s\n", attr, chunk); |
160 |
if(prev) { |
161 |
prev->next = ast_variable_new(attr, chunk); |
162 |
if (prev->next) { |
163 |
prev = prev->next; |
164 |
} |
165 |
} else { |
166 |
prev = var = ast_variable_new(attr, chunk); |
167 |
} |
168 |
} |
169 |
i++; |
170 |
} |
171 |
} |
172 |
/* ldap_value_free(values); */ |
173 |
/* ldap_memfree(attr-3); */ |
174 |
attr = ldap_next_attribute(ldap, res, ber); |
175 |
} |
176 |
res = ldap_next_entry(ldap, res2); |
177 |
ldap_memfree(res2); |
178 |
res2 = res; |
179 |
} |
180 |
} else { |
181 |
ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any entries in table %s.\n", table); |
182 |
} |
183 |
ldap_msgfree(res); |
184 |
ldap_disconnect(ldap); |
185 |
ast_mutex_unlock(&ldap_lock); |
186 |
|
187 |
return var; |
188 |
} |
189 |
|
190 |
static struct ast_config *realtime_multi_ldap(const char *database, const char *table, va_list ap) |
191 |
{ |
192 |
int numFields, i, j, search = 0; |
193 |
char query[QUERY_SIZE]; |
194 |
char query2[QUERY_SIZE]; |
195 |
const char *initfield = NULL; |
196 |
char *chunk; |
197 |
char *op; |
198 |
const char *newparam, *newval; |
199 |
struct ast_realloca ra; |
200 |
struct ast_variable *var=NULL; |
201 |
struct ast_config *cfg = NULL; |
202 |
struct ast_category *cat = NULL; |
203 |
LDAPMessage *res, *res2; |
204 |
BerElement *ber; |
205 |
char **values; |
206 |
char *attr; |
207 |
LDAP *ldap; |
208 |
|
209 |
ast_log(LOG_DEBUG, "realtime_multi_ldap\n"); |
210 |
if(!table) { |
211 |
ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n"); |
212 |
return NULL; |
213 |
} |
214 |
|
215 |
memset(&ra, 0, sizeof(ra)); |
216 |
|
217 |
cfg = ast_config_new(); |
218 |
if (!cfg) { |
219 |
/* If I can't alloc memory at this point, why bother doing anything else? */ |
220 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
221 |
return NULL; |
222 |
} |
223 |
|
224 |
/* Get the first parameter and first value in our list of passed paramater/value pairs */ |
225 |
newparam = va_arg(ap, const char *); |
226 |
newval = va_arg(ap, const char *); |
227 |
if(!newparam || !newval) { |
228 |
ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); |
229 |
return NULL; |
230 |
} |
231 |
|
232 |
initfield = ast_strdupa(newparam); |
233 |
if(initfield && (op = strchr(initfield, ' '))) { |
234 |
*op = '\0'; |
235 |
} |
236 |
|
237 |
/* Create the first part of the query using the first parameter/value pairs we just extracted |
238 |
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ |
239 |
|
240 |
if(!strchr(newparam, ' ')) op = "="; else op = ""; |
241 |
snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s%s%s))", table, newparam, op, newval); |
242 |
while((newparam = va_arg(ap, const char *))) { |
243 |
i++; |
244 |
newval = va_arg(ap, const char *); |
245 |
if(!strchr(newparam, ' ')) op = "="; else op = ""; |
246 |
snprintf(query + strlen(query), sizeof(query) - strlen(query), "(ast%s%s%s))", newparam, op, newval); |
247 |
} |
248 |
va_end(ap); |
249 |
query2[0] = '\0'; |
250 |
for ( j=0; j<i; j++ ) |
251 |
strncat(query2, "(&", sizeof(query2)-1); |
252 |
|
253 |
strncat(query2, query, sizeof(query2)-1); |
254 |
|
255 |
va_end(ap); |
256 |
|
257 |
ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query); |
258 |
|
259 |
/* We now have our complete statement; Lets connect to the server and execute it. */ |
260 |
ldap = ldap_reconnect(); |
261 |
if(!ldap) { |
262 |
return NULL; |
263 |
} |
264 |
|
265 |
ast_mutex_lock(&ldap_lock); |
266 |
search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query2, NULL, 0, &res); |
267 |
if(search != LDAP_SUCCESS) { |
268 |
ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n"); |
269 |
ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", query2); |
270 |
if ( res != NULL ) { |
271 |
ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(search)); |
272 |
} |
273 |
ast_mutex_unlock(&ldap_lock); |
274 |
ldap_disconnect(ldap); |
275 |
return NULL; |
276 |
} |
277 |
|
278 |
if (initfield) { |
279 |
ldap_sort_entries(ldap, &res, initfield, strcasecmp); |
280 |
} |
281 |
|
282 |
numFields = ldap_count_entries(ldap, res); |
283 |
if ( numFields > 0 ) { |
284 |
res2 = ldap_first_entry(ldap, res); |
285 |
while(res2) { |
286 |
var = NULL; |
287 |
cat = ast_category_new(""); |
288 |
if(!cat) { |
289 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
290 |
continue; |
291 |
} |
292 |
|
293 |
attr = ldap_first_attribute(ldap, res, &ber); |
294 |
while (attr) { |
295 |
if ( !strncmp(attr, "ast", 3) ) { |
296 |
values = ldap_get_values(ldap, res, attr); |
297 |
attr += 3; |
298 |
i = 0; |
299 |
while(values[i]) { |
300 |
chunk = strsep((char **) &values[i], ";"); |
301 |
if(chunk && !ast_strlen_zero(ast_strip(chunk))) { |
302 |
if(initfield && !strcmp(initfield, attr)) { |
303 |
ast_category_rename(cat, chunk); |
304 |
} |
305 |
var = ast_variable_new(attr, chunk); |
306 |
ast_variable_append(cat, var); |
307 |
} |
308 |
i++; |
309 |
} |
310 |
} |
311 |
ldap_value_free(values); |
312 |
attr = ldap_next_attribute(ldap, res, ber); |
313 |
} |
314 |
ast_category_append(cfg, cat); |
315 |
res = ldap_next_entry(ldap, res2); |
316 |
ldap_memfree(res2); |
317 |
res2 = res; |
318 |
} |
319 |
} else { |
320 |
ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any rows in table %s.\n", table); |
321 |
} |
322 |
|
323 |
ldap_msgfree(res); |
324 |
ldap_disconnect(ldap); |
325 |
ast_mutex_unlock(&ldap_lock); |
326 |
return cfg; |
327 |
} |
328 |
|
329 |
static int update_ldap(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
330 |
{ |
331 |
char query[QUERY_SIZE]; |
332 |
//char query2[QUERY_SIZE]; |
333 |
char buf[256]; |
334 |
const char *newparam, *newval; |
335 |
char *dn; |
336 |
LDAPMessage *res, *res2; |
337 |
LDAPMod mod_change; |
338 |
LDAPMod *all_changes[2]; |
339 |
char *mod_vals[] = {"", NULL}; |
340 |
int search, numFields; |
341 |
LDAP *ldap; |
342 |
|
343 |
all_changes[0] = &mod_change; |
344 |
all_changes[1] = NULL; |
345 |
|
346 |
|
347 |
ast_log(LOG_DEBUG, "update_ldap\n"); |
348 |
|
349 |
mod_change.mod_op = LDAP_MOD_REPLACE; |
350 |
mod_change.mod_values = mod_vals; |
351 |
mod_change.mod_type = buf; |
352 |
|
353 |
if(!table) { |
354 |
ast_log(LOG_WARNING, "LDAP RealTime: No table specified.\n"); |
355 |
return -1; |
356 |
} |
357 |
|
358 |
/* Get the first parameter and first value in our list of passed paramater/value pairs */ |
359 |
newparam = va_arg(ap, const char *); |
360 |
newval = va_arg(ap, const char *); |
361 |
if(!newparam || !newval) { |
362 |
ast_log(LOG_WARNING, "LDAP RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); |
363 |
return -1; |
364 |
} |
365 |
|
366 |
/* Create the first part of the query using the first parameter/value pairs we just extracted |
367 |
If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ |
368 |
|
369 |
|
370 |
snprintf(query, sizeof(query), "(&(objectClass=ast%s)(ast%s=%s))", table, keyfield, lookup); |
371 |
ast_log(LOG_WARNING, "LDAP RealTime: Retrieve LDAP: %s\n", query); |
372 |
|
373 |
/* We now have our complete statement; Lets connect to the server and execute it. */ |
374 |
ldap = ldap_reconnect(); |
375 |
if(!ldap) { |
376 |
return -1; |
377 |
} |
378 |
|
379 |
ast_mutex_lock(&ldap_lock); |
380 |
search = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, query, NULL, 0, &res); |
381 |
if(search != LDAP_SUCCESS) { |
382 |
ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n"); |
383 |
ast_log(LOG_DEBUG, "LDAP RealTime: Query: %s\n", query); |
384 |
if ( res != NULL ) { |
385 |
ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(ldap_result2error(ldap, res, 1))); |
386 |
} |
387 |
ast_mutex_unlock(&ldap_lock); |
388 |
ldap_disconnect(ldap); |
389 |
return -1; |
390 |
} |
391 |
|
392 |
numFields = ldap_count_entries(ldap, res); |
393 |
if ( numFields > 0 ) { |
394 |
res2 = ldap_first_entry(ldap, res); |
395 |
while(res2) { |
396 |
dn = ldap_get_dn(ldap, res2); |
397 |
ast_log(LOG_DEBUG, "LDAP RealTime: --%s\n", dn); |
398 |
do { |
399 |
ast_log(LOG_WARNING, "LDAP RealTime update: --%s --%s\n", newparam, newval); |
400 |
snprintf(buf, sizeof(buf), "ast%s", newparam); |
401 |
mod_vals[0] = (char *) newval; |
402 |
ldap_modify_s(ldap, dn, all_changes); |
403 |
} while((newparam = va_arg(ap, const char *)) && (newval = va_arg(ap, const char *))); |
404 |
res = ldap_next_entry(ldap, res2); |
405 |
ldap_memfree(res2); |
406 |
res2 = res; |
407 |
} |
408 |
} |
409 |
ldap_disconnect(ldap); |
410 |
ast_mutex_unlock(&ldap_lock); |
411 |
|
412 |
/* get better return value */ |
413 |
return 1; |
414 |
} |
415 |
|
416 |
context *get_config(LDAP *ldap, const char *ldapbasedn, const char filter[QUERY_SIZE], char *attrs[], char *doubleEntries) |
417 |
{ |
418 |
int numFields; |
419 |
char *chunk, *dn, *attr, **values; |
420 |
int i = 0; |
421 |
int j = 0; |
422 |
int k = 0; |
423 |
long ldapSearchResult = 0; |
424 |
LDAPMessage *res, *res2; |
425 |
BerElement *ber; |
426 |
context *start = NULL, *p = NULL; |
427 |
|
428 |
/* Is the ldapbasedn set? */ |
429 |
if(!ldapbasedn) { |
430 |
ast_log(LOG_DEBUG, "No BaseDN specified.\n"); |
431 |
return NULL; |
432 |
} |
433 |
|
434 |
/* Dose we have a filter */ |
435 |
if(!filter || !strlen(filter)) { |
436 |
ast_log(LOG_DEBUG, "No Filter specified.\n"); |
437 |
return NULL; |
438 |
} |
439 |
|
440 |
if(!ldap) { |
441 |
ast_log(LOG_DEBUG, "No connection!\n"); |
442 |
return NULL; |
443 |
} |
444 |
|
445 |
/* lets search the statement */ |
446 |
ldapSearchResult = ldap_search_s(ldap, ldapbasedn, LDAP_SCOPE_SUBTREE, filter, attrs , 0, &res); |
447 |
if(ldapSearchResult != LDAP_SUCCESS) { |
448 |
ast_log(LOG_WARNING, "LDAP RealTime: Failed to query database. Check debug for more info.\n"); |
449 |
ast_log(LOG_WARNING, "LDAP RealTime: Query: %s\n", filter); |
450 |
if ( res != NULL ) { |
451 |
ast_log(LOG_WARNING, "LDAP RealTime: Query Failed because: %s\n", ldap_err2string(ldap_result2error(ldap, res, 1))); |
452 |
} |
453 |
return NULL; |
454 |
} |
455 |
|
456 |
numFields = ldap_count_entries(ldap, res); |
457 |
if ( numFields > 0 ) { |
458 |
/* sort the result */ |
459 |
ldap_sort_entries(ldap, &res, attrs[1], strcasecmp); |
460 |
res2 = ldap_first_entry(ldap, res); |
461 |
while(res2) { |
462 |
attr = ldap_first_attribute(ldap, res, &ber); |
463 |
/* initialize a new context */ |
464 |
if((p = (context*)malloc(sizeof(context)))) { |
465 |
/* initialize field */ |
466 |
for(i=0; attrs[i] != NULL; i++) { |
467 |
p->string[i] = strdup(""); |
468 |
p->members[i] = strdup(""); |
469 |
} |
470 |
p->string[i] = NULL; |
471 |
p->members[i] = NULL; |
472 |
|
473 |
/* set field values */ |
474 |
dn = ldap_get_dn(ldap, res); |
475 |
/* if we must look for a "dn" */ |
476 |
for(i = 0; attrs[i] != NULL; i++) |
477 |
if(!strcasecmp(attrs[i], "dn")) { |
478 |
p->string[i] = strdup(dn); |
479 |
break; |
480 |
} |
481 |
|
482 |
k = 0; |
483 |
while (attr) { |
484 |
values = ldap_get_values(ldap, res, attr); |
485 |
i = 0; |
486 |
|
487 |
while(values[i]) { |
488 |
chunk = strsep((char **) &values[i], ";"); |
489 |
if(chunk && !ast_strlen_zero(ast_strip(chunk))) { |
490 |
for(j = 0; attrs[j] != NULL; j++) { |
491 |
if(!strcmp(attr, attrs[j]) || !strcmp(chunk, attrs[0])) { |
492 |
ast_log(LOG_DEBUG, "%s-%s\n", attr, chunk); |
493 |
if(!strcmp(attr, doubleEntries)) { |
494 |
p->members[k] = strdup(chunk); |
495 |
k++; |
496 |
break; |
497 |
} else { |
498 |
p->string[j] = strdup(chunk); |
499 |
break; |
500 |
} |
501 |
} |
502 |
} |
503 |
} |
504 |
i++; |
505 |
} |
506 |
ldap_value_free(values); |
507 |
ldap_memfree(attr); |
508 |
attr = ldap_next_attribute(ldap, res, ber); |
509 |
} |
510 |
/* set the last element */ |
511 |
p->members[k] = NULL; |
512 |
res = ldap_next_entry(ldap, res2); |
513 |
ldap_memfree(res2); |
514 |
res2 = res; |
515 |
p->next=start; |
516 |
start = p; |
517 |
} else |
518 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
519 |
} |
520 |
} else { |
521 |
ast_log(LOG_DEBUG, "LDAP RealTime: Could not find any entries in DN \'%s\' with filter \'%s\'.\n", ldapbasedn, filter); |
522 |
} |
523 |
/* free all stuff */ |
524 |
ldap_msgfree(res); |
525 |
free(chunk); |
526 |
free(dn); |
527 |
free(attr); |
528 |
ast_mutex_unlock(&ldap_lock); |
529 |
|
530 |
return start; |
531 |
} |
532 |
|
533 |
void rm_context() |
534 |
{ |
535 |
context *p; |
536 |
|
537 |
while(anf != NULL) { |
538 |
p = anf; |
539 |
anf = p->next; |
540 |
free(p); |
541 |
} |
542 |
} |
543 |
|
544 |
context *del_akt_context(context *p) |
545 |
{ |
546 |
context *q; |
547 |
|
548 |
if(p == anf) { |
549 |
anf = p->next; |
550 |
return anf; |
551 |
} else { |
552 |
q = anf; |
553 |
while(q->next != p) |
554 |
q = q->next; |
555 |
q->next = p->next; |
556 |
} |
557 |
free(p); |
558 |
return q->next; |
559 |
} |
560 |
|
561 |
context *search_context(const char *stringToSearch, int index) |
562 |
{ |
563 |
context *p = anf; |
564 |
|
565 |
while(p) { |
566 |
if(!strcmp(p->string[index], stringToSearch)) |
567 |
break; |
568 |
p = p->next; |
569 |
} |
570 |
|
571 |
return p; |
572 |
} |
573 |
|
574 |
|
575 |
static struct ast_config *config_ldap(const char *database, const char *table, const char *file, struct ast_config *cfg) |
576 |
{ |
577 |
int i, j, barrier; |
578 |
char *attrs[OPTION_SIZE], *options[OPTION_SIZE], filter[QUERY_SIZE], *var_val = NULL, *old_context = NULL; |
579 |
struct ast_variable *var=NULL; |
580 |
struct ast_category *cat = NULL; |
581 |
LDAP *ldap; |
582 |
context *p = NULL; |
583 |
FILE *datei; |
584 |
char a[QUERY_SIZE], b[QUERY_SIZE]; |
585 |
|
586 |
/* Is it my config file ("res_ldap.conf")? */ |
587 |
if(!file || !strcmp(file, RES_CONFIG_LDAP_CONF)) { |
588 |
ast_log(LOG_WARNING, "LDAP RealTime: Cannot configure myself.\n"); |
589 |
return NULL; |
590 |
|
591 |
} else { |
592 |
if((datei = fopen(database, "rt"))) { |
593 |
ast_log(LOG_WARNING, "LDAP RealTime: Reading LDAP-Fields from File: \'%s\'.\n", database); |
594 |
|
595 |
i = 0; |
596 |
while(!feof(datei)) { |
597 |
fscanf(datei, "%s\t%s\n", a, b); |
598 |
if(i+1 >= OPTION_SIZE) { |
599 |
ast_log(LOG_ERROR, "LDAP RealTime: Out of memory! %i\n",i); |
600 |
fclose(datei); |
601 |
/* free fields */ |
602 |
for(j = 0; j < i; j++) |
603 |
free(attrs[j]); |
604 |
for(j = 0; j < i; j++) |
605 |
free(options[j]); |
606 |
return NULL; |
607 |
} |
608 |
attrs[i] = strdup(a); |
609 |
options[i] = strdup(b); |
610 |
i++; |
611 |
} |
612 |
fclose(datei); |
613 |
attrs[i] = NULL; |
614 |
options[i] = NULL; |
615 |
|
616 |
/* show the field entrys */ |
617 |
for(i=0; options[i]; i++) |
618 |
ast_log(LOG_DEBUG, "%s=%s\n", attrs[i], options[i]); |
619 |
|
620 |
} else { |
621 |
ast_log(LOG_WARNING, "LDAP RealTime: Fail to open file \'%s\'. Using defaults!\n", database); |
622 |
|
623 |
if(!strcmp(file, "voicemail.conf")) { |
624 |
/* fields we wont to get from ldap |
625 |
We don't care about global options! |
626 |
(need no new objct) */ |
627 |
attrs[0] = strdup("astVoicemailGeneralConfig"); options[0] = strdup("objectClass"); // objectClass for the generals |
628 |
attrs[1] = strdup("astVoicemailContext"); options[1] = strdup("Context"); |
629 |
/* General options */ |
630 |
attrs[2] = strdup("astVoicemailFormat"); options[2] = strdup("Format"); |
631 |
attrs[3] = strdup("astVoicemailServeremail"); options[3] = strdup("Serveremail"); |
632 |
attrs[4] = strdup("astVoicemailAttach"); options[4] = strdup("Attach"); // Is general and MailBox option |
633 |
attrs[5] = strdup("astVoicemailMaxmsg"); options[5] = strdup("Maxmsg"); |
634 |
attrs[6] = strdup("astVoicemailMaxmessage"); options[6] = strdup("Maxmessage"); |
635 |
attrs[7] = strdup("astVoicemailMinmessage"); options[7] = strdup("Minmessage"); |
636 |
attrs[8] = strdup("astVoicemailMaxgreet"); options[8] = strdup("Maxgreet"); |
637 |
attrs[9] = strdup("astVoicemailSkipms"); options[9] = strdup("Skipms"); |
638 |
attrs[10] = strdup("astVoicemailMaxsilence"); options[10] = strdup("Maxsilence"); |
639 |
attrs[11] = strdup("astVoicemailMaxlogins"); options[11] = strdup("Maxlogins"); |
640 |
attrs[12] = strdup("astVoicemailExternnotify"); options[12] = strdup("Externnotify"); |
641 |
attrs[13] = strdup("astVoicemailExternpass"); options[13] = strdup("Externpass"); |
642 |
attrs[14] = strdup("astVoicemailDirectoryintro"); options[14] = strdup("Directoryintro"); |
643 |
attrs[15] = strdup("astVoicemailCharset"); options[15] = strdup("Charset"); |
644 |
attrs[16] = strdup("astVoicemailAdsifdn"); options[16] = strdup("Adsifdn"); |
645 |
attrs[17] = strdup("astVoicemailAdsisec"); options[17] = strdup("Adsisec"); |
646 |
attrs[18] = strdup("astVoicemailAdsiver"); options[18] = strdup("Adsiver"); |
647 |
attrs[19] = strdup("astVoicemailPbxskip"); options[19] = strdup("Pbxskip"); |
648 |
attrs[20] = strdup("astVoicemailFromstring"); options[20] = strdup("Fromstring"); |
649 |
attrs[21] = strdup("astVoicemailUsedirectory"); options[21] = strdup("Usedirectory"); |
650 |
attrs[22] = strdup("astVoicemailEmailsubject"); options[22] = strdup("Emailsubject"); |
651 |
attrs[23] = strdup("astVoicemailEmailbody"); options[23] = strdup("Emailbody"); |
652 |
attrs[24] = strdup("astVoicemailEmaildateformat"); options[24] = strdup("Emaildateformat"); |
653 |
attrs[25] = strdup("astVoicemailMailcmd"); options[25] = strdup("Mailcmd"); |
654 |
attrs[26] = strdup("astVoicemailTz"); options[26] = strdup("Tz"); |
655 |
/* MailBox spezific */ |
656 |
attrs[27] = strdup("astVoicemailSaycid"); options[27] = strdup("Saycid"); |
657 |
attrs[28] = strdup("astVoicemailCidinternalContexts"); options[28] = strdup("CidinternalContexts"); |
658 |
attrs[29] = strdup("astVoicemailSayduration"); options[29] = strdup("Sayduration"); |
659 |
attrs[30] = strdup("astVoicemailSaydurationm"); options[30] = strdup("Saydurationm"); |
660 |
attrs[31] = strdup("astVoicemailDialout"); options[31] = strdup("Dialout"); |
661 |
attrs[32] = strdup("astVoicemailSendvoicemail"); options[32] = strdup("Sendvoicemail"); |
662 |
attrs[33] = strdup("astVoicemailSearchcontexts"); options[33] = strdup("Searchcontexts"); |
663 |
attrs[34] = strdup("astVoicemailCallback"); options[34] = strdup("Callback"); |
664 |
attrs[35] = strdup("astVoicemailReview"); options[35] = strdup("Review"); |
665 |
attrs[36] = strdup("astVoicemailOperator"); options[36] = strdup("Operator"); |
666 |
attrs[37] = strdup("astVoicemailEnvelope"); options[37] = strdup("Envelope"); |
667 |
attrs[38] = strdup("astVoicemailDelete"); options[38] = strdup("Delete"); |
668 |
attrs[39] = strdup("astVoicemailNextaftercmd"); options[39] = strdup("Nextaftercmd"); |
669 |
attrs[40] = strdup("astVoicemailForcename"); options[40] = strdup("Forcename"); |
670 |
attrs[41] = strdup("astVoicemailForcegreetings"); options[41] = strdup("Forcegreetings"); |
671 |
attrs[42] = strdup("astVoicemailHidefromdir"); options[42] = strdup("Hidefromdir"); |
672 |
/* Fix Mailbox identifiers */ |
673 |
attrs[43] = strdup("astVoicemailVoiceboxNr"); options[43] = strdup("VoiceboxNr"); // <mailbox_Nr> => |
674 |
attrs[44] = strdup("astVoicemailPassword"); options[44] = strdup("Password"); // <password> |
675 |
attrs[45] = strdup("cn"); options[45] = strdup("Mailbox"); // <name> we get from somewhere |
676 |
attrs[46] = strdup("mail"); options[46] = strdup("Email"); // <email> we get from somewhere |
677 |
attrs[47] = strdup("astVoicemailPager"); options[47] = strdup("Pager"); // <pager> |
678 |
attrs[48] = NULL; options[48]= NULL; |
679 |
|
680 |
} else if(!strcmp(file, "queues.conf")) { |
681 |
/* fields we wont to get from ldap |
682 |
(need a new object) */ |
683 |
attrs[0] = strdup("astQueueGeneralConfig"); options[0] = strdup("objectClass"); // objectClass for the generals |
684 |
attrs[1] = strdup("astQueueContext"); options[1] = strdup("Context"); |
685 |
/* General options */ |
686 |
attrs[2] = strdup("astQueuePersistentmembers"); options[2] = strdup("astQueuePersistentmembers"); |
687 |
/* Queue spezific */ |
688 |
attrs[3] = strdup("astQueueMusiconhold"); options[3] = strdup("Musiconhold"); |
689 |
attrs[4] = strdup("astQueueAnnounce"); options[4] = strdup("Announce"); |
690 |
attrs[5] = strdup("astQueueStrategy"); options[5] = strdup("Strategy"); |
691 |
attrs[6] = strdup("astQueueDervicelevel"); options[6] = strdup("Dervicelevel"); |
692 |
attrs[7] = strdup("astQueueGoToContext"); options[7] = strdup("Context"); |
693 |
attrs[8] = strdup("astQueueTimeout"); options[8] = strdup("Timeout"); |
694 |
attrs[9] = strdup("astQueueRetry"); options[9] = strdup("Retry"); |
695 |
attrs[10] = strdup("astQueueWeight"); options[10] = strdup("Weight"); |
696 |
attrs[11] = strdup("astQueueWrapuptime"); options[11] = strdup("Wrapuptime"); |
697 |
attrs[12] = strdup("astQueueMaxlen"); options[12] = strdup("Maxlen"); |
698 |
attrs[13] = strdup("astQueueAnnounceFrequency"); options[13] = strdup("Announce-frequency"); |
699 |
attrs[14] = strdup("astQueuePeriodicAnnounceFrequency"); options[14] = strdup("Periodic-announce-frequency"); |
700 |
attrs[15] = strdup("astQueueAnnounceHoldtime"); options[15] = strdup("Announce-holdtime"); |
701 |
attrs[16] = strdup("astQueueAnnounceRoundSeconds"); options[16] = strdup("Announce-round-seconds"); |
702 |
attrs[17] = strdup("astQueueQueueYouarenext"); options[17] = strdup("Queue-youarenext"); |
703 |
attrs[18] = strdup("astQueueQueueThereare"); options[18] = strdup("Queue-thereare"); |
704 |
attrs[19] = strdup("astQueueQueueCallswaiting"); options[19] = strdup("Queue-callswaiting"); |
705 |
attrs[20] = strdup("astQueueQueueHoldtime"); options[20] = strdup("Queue-holdtime"); |
706 |
attrs[21] = strdup("astQueueQueueMinutes"); options[21] = strdup("Queue-minutes"); |
707 |
attrs[22] = strdup("astQueueQueueSeconds"); options[22] = strdup("Queue-seconds"); |
708 |
attrs[23] = strdup("astQueueQueueThankyou"); options[23] = strdup("Queue-thankyou"); |
709 |
attrs[24] = strdup("astQueueQueueLessthan"); options[24] = strdup("Queue-lessthan"); |
710 |
attrs[25] = strdup("astQueueQueueReporthold"); options[25] = strdup("Queue-reporthold"); |
711 |
attrs[26] = strdup("astQueuePeriodicAnnounce"); options[26] = strdup("Periodic-announce"); |
712 |
attrs[27] = strdup("astQueueMonitorFormat"); options[27] = strdup("Monitor-format"); |
713 |
attrs[28] = strdup("astQueueMonitorJoin"); options[28] = strdup("Monitor-join"); |
714 |
attrs[29] = strdup("astQueueJoinempty"); options[29] = strdup("Joinempty"); |
715 |
attrs[30] = strdup("astQueueLeavewhenempty"); options[30] = strdup("Leavewhenempty"); |
716 |
attrs[31] = strdup("astQueueEventwhencalled"); options[31] = strdup("Eventwhencalled"); |
717 |
attrs[32] = strdup("astQueueEventmemberstatusoff"); options[32] = strdup("Eventmemberstatusoff"); |
718 |
attrs[33] = strdup("astQueueReportholdtime"); options[33] = strdup("Reportholdtime"); |
719 |
attrs[34] = strdup("astQueueMemberdelay"); options[34] = strdup("Memberdelay"); |
720 |
attrs[35] = strdup("astQueueTimeoutrestart"); options[35] = strdup("Timeoutrestart"); |
721 |
/* the QueueMembers */ |
722 |
attrs[36] = strdup("astQueueMember"); options[36]= strdup("member"); // must be the last field element! |
723 |
attrs[37] = NULL; options[37]= NULL; |
724 |
|
725 |
} else if(!strcmp(file, "agents.conf")) { |
726 |
/* fields we wont to get from ldap |
727 |
(need a new object) */ |
728 |
attrs[0] = strdup("astAgentGeneralConfig"); options[0] = strdup("objectClass"); // objectClass for the generals |
729 |
attrs[1] = strdup("astAgentContext"); options[1] = strdup("Context"); |
730 |
/* General options */ |
731 |
attrs[2] = strdup("astAgentPersistentagents"); options[2] = strdup("Persistentagents"); |
732 |
/* Agent spezific */ |
733 |
attrs[3] = strdup("astAgentAutologoff"); options[3] = strdup("Autologoff"); |
734 |
attrs[4] = strdup("astAgentAckcall"); options[4] = strdup("Ackcall"); |
735 |
attrs[5] = strdup("astAgentWrapuptime"); options[5] = strdup("Wrapuptime"); |
736 |
attrs[6] = strdup("astAgentMusiconhold"); options[6] = strdup("Musiconhold"); |
737 |
attrs[7] = strdup("astAgentUpdatecdr"); options[7] = strdup("Updatecdr"); |
738 |
attrs[8] = strdup("astAgentGroup"); options[8] = strdup("Group"); |
739 |
attrs[9] = strdup("astAgentRecordagentcalls"); options[9] = strdup("Recordagentcalls"); |
740 |
attrs[10] = strdup("astAgentRecordformat"); options[10]= strdup("Recordformat"); |
741 |
attrs[11] = strdup("astAgentCreatelink"); options[11]= strdup("Createlink"); |
742 |
attrs[12] = strdup("astAgentUrlprefix"); options[12]= strdup("Urlprefix"); |
743 |
attrs[13] = strdup("astAgentSavecallsin"); options[13]= strdup("Savecallsin"); |
744 |
attrs[14] = strdup("astAgentCustombeep"); options[14]= strdup("Custom_beep"); |
745 |
/* The agent parameters */ |
746 |
attrs[15] = strdup("astAgentAgentID"); options[15]= strdup("AgentID"); |
747 |
attrs[16] = strdup("astAgentAgentPassword"); options[16]= strdup("AgentPassword"); |
748 |
attrs[17] = strdup("cn"); options[17]= strdup("AgentDiscription"); |
749 |
attrs[18] = NULL; options[18]= NULL; |
750 |
|
751 |
} else if(!strcmp(file, "meetme.conf")) { |
752 |
/* fields we wont to get from ldap */ |
753 |
attrs[0] = strdup("astMeetMeGeneralConfig"); options[0] = strdup("objectClass"); // objectClass for the generals |
754 |
attrs[1] = strdup("astMeetMeContext"); options[1] = strdup("Context"); |
755 |
/* General options */ |
756 |
attrs[2] = strdup("astMeetMeAudiobuffers"); options[2] = strdup("Audiobuffers"); |
757 |
/* MeetMe spezific */ |
758 |
/* The MeetMe options */ |
759 |
attrs[3] = strdup("astMeetMeConfno"); options[3] = strdup("Confno"); // must value if is it not a emty context |
760 |
attrs[4] = strdup("astMeetMePincode"); options[4] = strdup("Pincode"); |
761 |
attrs[5] = strdup("astMeetMeAdminpin"); options[5] = strdup("Adminpin"); |
762 |
attrs[6] = NULL; options[6] = NULL; |
763 |
|
764 |
} else { |
765 |
ast_log(LOG_WARNING, "LDAP RealTime: Useing of %s not supported!.\n",file); |
766 |
return NULL; |
767 |
} |
768 |
} |
769 |
} |
770 |
|
771 |
/* generate the query */ |
772 |
snprintf(filter, sizeof(filter), "(|(objectClass=%s)(objectClass=%s))", table, attrs[0]); |
773 |
|
774 |
/* We now have our complete statement; Lets connect to the server and execute it. */ |
775 |
ast_mutex_lock(&ldap_lock); |
776 |
ldap = ldap_reconnect(); |
777 |
if(!ldap) { |
778 |
/* free all stuff */ |
779 |
for(i = 0; attrs[i]; i++) |
780 |
free(attrs[i]); |
781 |
for(i = 0; options[i]; i++) |
782 |
free(options[i]); |
783 |
ast_mutex_unlock(&ldap_lock); |
784 |
return NULL; |
785 |
} |
786 |
|
787 |
/* Seting up barrier */ |
788 |
for(i = 0; options[i]; i++) |
789 |
if(!strcasecmp(options[i], "VoiceboxNr") || !strcasecmp(options[i], "AgentID") || !strcasecmp(options[i], "Confno") || !strcasecmp(options[i], "member")) { |
790 |
barrier = i; |
791 |
break; |
792 |
} |
793 |
|
794 |
/* Lets get available contexts */ |
795 |
anf = get_config(ldap, ldapbasedn, filter, attrs, !strcmp(file, "queues.conf") ? attrs[barrier] : ""); |
796 |
|
797 |
/* Get the context "general" */ |
798 |
if((p = search_context("general", 1))) { |
799 |
if (!(cat = ast_category_new(p->string[1]))) { |
800 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
801 |
} else { |
802 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
803 |
/* Add the options */ |
804 |
for(i = 2; i < barrier; i++) { |
805 |
if(strlen(p->string[i])) { |
806 |
var = ast_variable_new(options[i], p->string[i]); |
807 |
ast_variable_append(cat, var); |
808 |
ast_verbose("\t'%s = %s'\n", options[i], p->string[i]); |
809 |
} |
810 |
} |
811 |
/* We not longer need the akt. context */ |
812 |
del_akt_context(p); |
813 |
/* add the category "general" */ |
814 |
ast_category_append(cfg, cat); |
815 |
cat = NULL; |
816 |
} |
817 |
} else { |
818 |
ast_log(LOG_WARNING, "LDAP RealTime: Couldn't finde the \"general\" part.\n"); |
819 |
} |
820 |
|
821 |
if(!strcmp(file, "agents.conf") || !strcmp(file, "meetme.conf")) { |
822 |
if(!strcmp(file, "agents.conf") && (p = search_context("agents", 1))) { |
823 |
if (!(cat = ast_category_new(p->string[1]))) { |
824 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
825 |
} else { |
826 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
827 |
/* A general config only for agents */ |
828 |
if(strlen(p->string[0])) { |
829 |
/* Add the options */ |
830 |
for(i = 2; i < barrier; i++) { |
831 |
if(strlen(p->string[i])) { |
832 |
var = ast_variable_new(options[i], p->string[i]); |
833 |
ast_variable_append(cat, var); |
834 |
ast_verbose("\t'%s = %s'\n", options[i], p->string[i]); |
835 |
} |
836 |
} |
837 |
/* We not longer need the list element */ |
838 |
del_akt_context(p); |
839 |
} |
840 |
} |
841 |
} |
842 |
|
843 |
/* clear all elements we don't need */ |
844 |
p = anf; |
845 |
while(p) { |
846 |
if(!strcmp(attrs[0], p->string[0])) { |
847 |
p = del_akt_context(p); |
848 |
continue; |
849 |
} |
850 |
p = p->next; |
851 |
} |
852 |
p = anf; |
853 |
|
854 |
/* Add the contextes "rooms" / "agents" without global options */ |
855 |
if(!cat && p) { |
856 |
if(!strcmp(file, "meetme.conf")) p->string[1] = strdup("rooms"); else p->string[1] = strdup("agents"); |
857 |
if (!(cat = ast_category_new(p->string[1]))) |
858 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
859 |
else |
860 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
861 |
} |
862 |
|
863 |
/* Add the spezific entries */ |
864 |
while(p && cat) { |
865 |
/* generate values */ |
866 |
var_val = strdup(p->string[barrier]); |
867 |
for(i=barrier+1; options[i]; i++){ |
868 |
if(strlen(p->string[i]) != 0) { |
869 |
if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen(p->string[i]) + 1))) { |
870 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
871 |
continue; |
872 |
} |
873 |
var_val = strcat(strcat(var_val, ","), p->string[i]); |
874 |
} else { |
875 |
if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + 1))) { |
876 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
877 |
continue; |
878 |
} |
879 |
var_val = strcat(var_val, ","); |
880 |
} |
881 |
} |
882 |
/* add a new entry to the category */ |
883 |
var = ast_variable_new(!strcmp(file, "agents.conf") ? "agent" : "conf", var_val); |
884 |
ast_variable_append(cat, var); |
885 |
ast_verbose("\t'%s => %s'\n", !strcmp(file, "agents.conf") ? "agent" : "conf", var_val); |
886 |
p = p->next; |
887 |
} |
888 |
/* add the category "agents/rooms" */ |
889 |
if(cat) |
890 |
ast_category_append(cfg, cat); |
891 |
|
892 |
} else if(!strcmp(file, "voicemail.conf") && (p = anf)) { |
893 |
/* clear all elements we don't need */ |
894 |
while(p) { |
895 |
if(!strcmp(attrs[0], p->string[0])) { |
896 |
p = del_akt_context(p); |
897 |
continue; |
898 |
} |
899 |
p = p->next; |
900 |
} |
901 |
|
902 |
/* Add the rest contexts without global options */ |
903 |
if((p = anf)) { |
904 |
if (!(cat = ast_category_new(p->string[1]))) { |
905 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
906 |
} |
907 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
908 |
old_context = strdup(p->string[1]); |
909 |
} |
910 |
while(p) { |
911 |
if(strcmp(old_context, p->string[1])) { |
912 |
/* add the category */ |
913 |
ast_category_append(cfg, cat); |
914 |
if (!(cat = ast_category_new(p->string[1]))) { |
915 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
916 |
continue; |
917 |
} |
918 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
919 |
old_context = strdup(p->string[1]); |
920 |
} |
921 |
|
922 |
/* generate the first part of the value */ |
923 |
var_val = strdup( p->string[barrier+1]); |
924 |
for(i=barrier+2; p->string[i]; i++) |
925 |
if(strlen( p->string[i]) == 0) { |
926 |
if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + 1))) { |
927 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
928 |
continue; |
929 |
} |
930 |
strcat(var_val, ","); |
931 |
} else { |
932 |
if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen( p->string[i]) + 1))) { |
933 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
934 |
continue; |
935 |
} |
936 |
strcat(strcat(var_val, ","), p->string[i]); |
937 |
} |
938 |
|
939 |
/* generate the second part of the value */ |
940 |
for(i=2; i < barrier; i++) |
941 |
if(strlen( p->string[i]) != 0) { |
942 |
if (!(var_val = (char *)realloc(var_val, strlen(var_val) + 1 + strlen(options[i]) + 1 + strlen( p->string[i]) + 1))) { |
943 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
944 |
continue; |
945 |
} |
946 |
strcat(strcat(strcat(strcat(var_val, ","), options[i]), "="), p->string[i]); |
947 |
} |
948 |
/* add a new entry to the category */ |
949 |
var = ast_variable_new(p->string[barrier], var_val); |
950 |
ast_variable_append(cat, var); |
951 |
ast_verbose("\t'%s => %s'\n", p->string[barrier], var_val); |
952 |
p = p->next; |
953 |
} |
954 |
/* add the category */ |
955 |
if(anf) |
956 |
ast_category_append(cfg, cat); |
957 |
|
958 |
} else if(!strcmp(file, "queues.conf") && (p = anf)) { |
959 |
while(p) { |
960 |
if (!(cat = ast_category_new(p->string[1]))) { |
961 |
ast_log(LOG_WARNING, "Out of memory!\n"); |
962 |
} else { |
963 |
ast_verbose(" -- Add context: '%s'\n", p->string[1]); |
964 |
/* add options */ |
965 |
for(i = 2; p->string[i]; i++) { |
966 |
if(strlen(p->string[i]) != 0) { |
967 |
var = ast_variable_new(options[i], p->string[i]); |
968 |
ast_variable_append(cat, var); |
969 |
ast_verbose("\t'%s = %s'\n", options[i], p->string[i]); |
970 |
} |
971 |
} |
972 |
|
973 |
/* Add QueueMembers */ |
974 |
for(i = 0; p->members[i]; i++) { |
975 |
var = ast_variable_new(options[barrier], p->members[i]); |
976 |
ast_variable_append(cat, var); |
977 |
ast_verbose("\t'%s = %s'\n", options[barrier], p->members[i]); |
978 |
} |
979 |
} |
980 |
/* add the category */ |
981 |
ast_category_append(cfg, cat); |
982 |
p = p->next; |
983 |
} |
984 |
} |
985 |
|
986 |
/* free all stuff */ |
987 |
rm_context(); |
988 |
for(i = 0; attrs[i]; i++) |
989 |
free(attrs[i]); |
990 |
for(i = 0; options[i]; i++) |
991 |
free(options[i]); |
992 |
free(var_val); |
993 |
free(old_context); |
994 |
ldap_disconnect(ldap); |
995 |
ast_mutex_unlock(&ldap_lock); |
996 |
|
997 |
return cfg; |
998 |
} |
999 |
|
1000 |
static struct ast_config_engine ldap_engine = { |
1001 |
.name = "ldap", |
1002 |
.load_func = config_ldap, |
1003 |
.realtime_func = realtime_ldap, |
1004 |
.realtime_multi_func = realtime_multi_ldap, |
1005 |
.update_func = update_ldap |
1006 |
}; |
1007 |
|
1008 |
int load_module (void) |
1009 |
{ |
1010 |
parse_config(); |
1011 |
|
1012 |
if(!ldap_reconnect()) { |
1013 |
ast_log(LOG_WARNING, "LDAP RealTime: Couldn't establish connection. Check debug.\n"); |
1014 |
ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect\n"); |
1015 |
} |
1016 |
|
1017 |
ast_config_engine_register(&ldap_engine); |
1018 |
if(option_verbose) { |
1019 |
ast_verbose("LDAP RealTime driver loaded.\n"); |
1020 |
} |
1021 |
ast_cli_register(&cli_realtime_ldap_status); |
1022 |
|
1023 |
return 0; |
1024 |
} |
1025 |
|
1026 |
int unload_module (void) |
1027 |
{ |
1028 |
/* Aquire control before doing anything to the module itself. */ |
1029 |
ast_mutex_lock(&ldap_lock); |
1030 |
|
1031 |
ast_cli_unregister(&cli_realtime_ldap_status); |
1032 |
ast_config_engine_deregister(&ldap_engine); |
1033 |
if(option_verbose) { |
1034 |
ast_verbose("LDAP RealTime unloaded.\n"); |
1035 |
} |
1036 |
|
1037 |
STANDARD_HANGUP_LOCALUSERS; |
1038 |
|
1039 |
/* Unlock so something else can destroy the lock. */ |
1040 |
ast_mutex_unlock(&ldap_lock); |
1041 |
|
1042 |
return 0; |
1043 |
} |
1044 |
|
1045 |
int reload (void) |
1046 |
{ |
1047 |
/* Aquire control before doing anything to the module itself. */ |
1048 |
ast_mutex_lock(&ldap_lock); |
1049 |
|
1050 |
connected = 0; |
1051 |
parse_config(); |
1052 |
|
1053 |
/* Need to unlock so that ldap_reconnect can regain the lock. */ |
1054 |
ast_mutex_unlock(&ldap_lock); |
1055 |
|
1056 |
if(!ldap_reconnect()) { |
1057 |
ast_log(LOG_WARNING, "LDAP RealTime: Couldn't establish connection. Check debug.\n"); |
1058 |
ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect\n"); |
1059 |
} |
1060 |
|
1061 |
ast_verbose(VERBOSE_PREFIX_2 "LDAP RealTime reloaded.\n"); |
1062 |
|
1063 |
return 0; |
1064 |
} |
1065 |
|
1066 |
int parse_config (void) |
1067 |
{ |
1068 |
struct ast_config *config; |
1069 |
char *s; |
1070 |
|
1071 |
config = ast_config_load(RES_CONFIG_LDAP_CONF); |
1072 |
|
1073 |
if(config) { |
1074 |
if(!(s=ast_variable_retrieve(config, "general", "ldapuser"))) { |
1075 |
ast_log(LOG_WARNING, "LDAP RealTime: No database user found, using 'asterisk' as default.\n"); |
1076 |
strncpy(ldapuser, "asterisk", sizeof(ldapuser) - 1); |
1077 |
} else { |
1078 |
strncpy(ldapuser, s, sizeof(ldapuser) - 1); |
1079 |
} |
1080 |
|
1081 |
if(!(s=ast_variable_retrieve(config, "general", "ldappass"))) { |
1082 |
ast_log(LOG_WARNING, "LDAP RealTime: No database password found, using 'asterisk' as default.\n"); |
1083 |
strncpy(ldappass, "asterisk", sizeof(ldappass) - 1); |
1084 |
} else { |
1085 |
strncpy(ldappass, s, sizeof(ldappass) - 1); |
1086 |
} |
1087 |
|
1088 |
if(!(s=ast_variable_retrieve(config, "general", "ldapuri"))) { |
1089 |
ast_log(LOG_WARNING, "LDAP RealTime: No database host found, using localhost via socket.\n"); |
1090 |
strncpy(ldapuri, "ldap://localhost", sizeof(ldapuri) - 1); |
1091 |
} else { |
1092 |
strncpy(ldapuri, s, sizeof(ldapuri) - 1); |
1093 |
} |
1094 |
|
1095 |
if(!(s=ast_variable_retrieve(config, "general", "ldapbasedn"))) { |
1096 |
ast_log(LOG_WARNING, "LDAP RealTime: No base dn found, using 'asterisk' as default.\n"); |
1097 |
strncpy(ldapbasedn, "asterisk", sizeof(ldapbasedn) - 1); |
1098 |
} else { |
1099 |
strncpy(ldapbasedn, s, sizeof(ldapbasedn) - 1); |
1100 |
} |
1101 |
} |
1102 |
ast_config_destroy(config); |
1103 |
|
1104 |
ast_log(LOG_WARNING, "LDAP RealTime Host: %s\n", ldapuri); |
1105 |
ast_log(LOG_WARNING, "LDAP RealTime User: %s\n", ldapuser); |
1106 |
ast_log(LOG_WARNING, "LDAP RealTime Base DN: %s\n", ldapbasedn); |
1107 |
|
1108 |
return 1; |
1109 |
} |
1110 |
|
1111 |
char *description (void) |
1112 |
{ |
1113 |
return res_config_ldap_desc; |
1114 |
} |
1115 |
|
1116 |
int usecount (void) |
1117 |
{ |
1118 |
/* Try and get a lock. If unsuccessful, than that means another thread is using the ldap object. */ |
1119 |
if(ast_mutex_trylock(&ldap_lock)) { |
1120 |
ast_log(LOG_DEBUG, "LDAP RealTime: Module usage count is 1.\n"); |
1121 |
return 1; |
1122 |
} |
1123 |
ast_mutex_unlock(&ldap_lock); |
1124 |
return 0; |
1125 |
} |
1126 |
|
1127 |
char *key () |
1128 |
{ |
1129 |
return ASTERISK_GPL_KEY; |
1130 |
} |
1131 |
|
1132 |
void ldap_disconnect(LDAP *ldap) |
1133 |
{ |
1134 |
|
1135 |
ldap_unbind_s(ldap); |
1136 |
} |
1137 |
|
1138 |
static LDAP *ldap_reconnect() |
1139 |
{ |
1140 |
int ver = LDAP_VERSION3; |
1141 |
int deref = LDAP_DEREF_ALWAYS; |
1142 |
int ldap_err; |
1143 |
LDAP *ldap; |
1144 |
|
1145 |
ast_mutex_lock(&ldap_lock); |
1146 |
|
1147 |
//if(!connected) { |
1148 |
if(strlen(ldapuri) && strlen(ldapuser) && strlen(ldappass) && strlen(ldapbasedn)) { |
1149 |
ldap_err = ldap_initialize(&ldap, ldapuri); |
1150 |
if(ldap_err != LDAP_SUCCESS || !ldap) { |
1151 |
ast_log(LOG_WARNING, "LDAP connection failed (host=%s)!\n", ldapuri); |
1152 |
connected = 0; |
1153 |
ast_mutex_unlock(&ldap_lock); |
1154 |
return NULL; |
1155 |
} |
1156 |
ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ver); |
1157 |
ldap_err = ldap_simple_bind_s(ldap, ldapuser, ldappass); |
1158 |
if(ldap_err == LDAP_SUCCESS) { |
1159 |
ast_log(LOG_WARNING, "LDAP RealTime: Successfully connected to LDAP.\n"); |
1160 |
connected = 1; |
1161 |
connect_time = time(NULL); |
1162 |
ast_mutex_unlock(&ldap_lock); |
1163 |
errorcount = 0; |
1164 |
return ldap; |
1165 |
} else if(ldap_err == LDAP_PROTOCOL_ERROR) { |
1166 |
if(ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ver) == -1 || |
1167 |
ldap_set_option(ldap, LDAP_OPT_DEREF, &deref) == -1) { |
1168 |
ast_log(LOG_ERROR, "LDAP RealTime: Failed to connect LDAP server %s on %s. Check debug for more info.\n", ldapbasedn, ldapuri); |
1169 |
ast_log(LOG_DEBUG, "LDAP RealTime: Cannot Connect: %s\n", ldap_err2string(ldap_err)); |
1170 |
connected = 0; |
1171 |
ast_mutex_unlock(&ldap_lock); |
1172 |
return NULL; |
1173 |
} else { |
1174 |
ast_log(LOG_DEBUG, "LDAP RealTime: Using LDAP_VERSION3 but successfully connected to LDAP.\n"); |
1175 |
connected = 1; |
1176 |
errorcount = 0; |
1177 |
connect_time = time(NULL); |
1178 |
ast_mutex_unlock(&ldap_lock); |
1179 |
return ldap; |
1180 |
} |
1181 |
} else { |
1182 |
ast_log(LOG_ERROR, "LDAP failed to bind (host=%s, user=%s %s %d)!\n",ldapuri, ldapuser, ldap_err2string(ldap_err), errorcount); |
1183 |
ldap_unbind(ldap); |
1184 |
errorcount++; |
1185 |
ast_mutex_unlock(&ldap_lock); |
1186 |
if ( errorcount < 3 ) { |
1187 |
usleep(50000); |
1188 |
return ldap_reconnect(); |
1189 |
} |
1190 |
return NULL; |
1191 |
} |
1192 |
|
1193 |
} else { |
1194 |
ast_log(LOG_ERROR, "LDAP RealTime: Not all Parameters of \"res_ldap.conf\" are set!\n"); |
1195 |
connected = 0; |
1196 |
ast_mutex_unlock(&ldap_lock); |
1197 |
free(ldap); |
1198 |
return NULL; |
1199 |
} |
1200 |
|
1201 |
/*} else { |
1202 |
ldap_err = ldap_simple_bind_s(ldap, ldapuser, ldappass); |
1203 |
if(ldap_err != LDAP_SUCCESS) { |
1204 |
connected = 0; |
1205 |
ast_log(LOG_ERROR, "LDAP RealTime: Server Error: %s\n", ldap_err2string(ldap_err)); |
1206 |
ast_mutex_unlock(&ldap_lock); |
1207 |
return 0; |
1208 |
} |
1209 |
|
1210 |
connected = 1; |
1211 |
|
1212 |
ast_log(LOG_WARNING, "LDAP RealTime: Everything is fine.\n"); |
1213 |
ast_mutex_unlock(&ldap_lock); |
1214 |
return 1; |
1215 |
}*/ |
1216 |
} |
1217 |
|
1218 |
static int realtime_ldap_status(int fd, int argc, char **argv) |
1219 |
{ |
1220 |
char status[256], status2[100] = ""; |
1221 |
int ctime = time(NULL) - connect_time; |
1222 |
|
1223 |
if(ldap_reconnect()) { |
1224 |
if ( ldapuri && ldapbasedn ) { |
1225 |
snprintf(status, 255, "Connected to %s base dn=%s", ldapuri, ldapbasedn); |
1226 |
} |
1227 |
|
1228 |
if(ldapuser && *ldapuser) { |
1229 |
snprintf(status2, 99, " with username %s", ldapuser); |
1230 |
} |
1231 |
|
1232 |
if (ctime > 31536000) { |
1233 |
ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60); |
1234 |
} else if (ctime > 86400) { |
1235 |
ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60); |
1236 |
} else if (ctime > 3600) { |
1237 |
ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60); |
1238 |
} else if (ctime > 60) { |
1239 |
ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60); |
1240 |
} else { |
1241 |
ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime); |
1242 |
} |
1243 |
|
1244 |
return RESULT_SUCCESS; |
1245 |
} else { |
1246 |
return RESULT_FAILURE; |
1247 |
} |
1248 |
} |