00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <stdio.h>
00015
#include <stdlib.h>
00016
#include <pthread.h>
00017
#include <string.h>
00018
#include <sys/time.h>
00019
#include <sys/types.h>
00020
#include <netdb.h>
00021
#include <sys/socket.h>
00022
#include <netinet/in.h>
00023
#include <netinet/tcp.h>
00024
#include <arpa/inet.h>
00025
#include <signal.h>
00026
#include <errno.h>
00027
#include <unistd.h>
00028
#include <sys/poll.h>
00029
#include <asterisk/channel.h>
00030
#include <asterisk/file.h>
00031
#include <asterisk/manager.h>
00032
#include <asterisk/config.h>
00033
#include <asterisk/lock.h>
00034
#include <asterisk/logger.h>
00035
#include <asterisk/options.h>
00036
#include <asterisk/cli.h>
00037
#include <asterisk/app.h>
00038
#include <asterisk/pbx.h>
00039
#include <asterisk/md5.h>
00040
#include <asterisk/acl.h>
00041
#include <asterisk/utils.h>
00042
00043 struct fast_originate_helper
00044 {
00045 char tech[256];
00046 char data[256];
00047 int timeout;
00048 char app[256];
00049 char appdata[256];
00050 char callerid[256];
00051 char variable[256];
00052 char account[256];
00053 char context[256];
00054 char exten[256];
00055 int priority;
00056 };
00057
00058
static int enabled = 0;
00059
static int portno =
DEFAULT_MANAGER_PORT;
00060
static int asock = -1;
00061
static pthread_t t;
00062
AST_MUTEX_DEFINE_STATIC(sessionlock);
00063
static int block_sockets = 0;
00064
00065
static struct permalias {
00066
int num;
00067
char *label;
00068 } perms[] = {
00069 {
EVENT_FLAG_SYSTEM,
"system" },
00070 {
EVENT_FLAG_CALL,
"call" },
00071 {
EVENT_FLAG_LOG,
"log" },
00072 {
EVENT_FLAG_VERBOSE,
"verbose" },
00073 {
EVENT_FLAG_COMMAND,
"command" },
00074 {
EVENT_FLAG_AGENT,
"agent" },
00075 {
EVENT_FLAG_USER,
"user" },
00076 { -1,
"all" },
00077 };
00078
00079
static struct mansession *sessions = NULL;
00080
static struct manager_action *first_action = NULL;
00081
AST_MUTEX_DEFINE_STATIC(actionlock);
00082
00083 int ast_carefulwrite(
int fd,
char *s,
int len,
int timeoutms)
00084 {
00085
00086
00087
int res=0;
00088
struct pollfd fds[1];
00089
while(len) {
00090 res = write(fd,
s, len);
00091
if ((res < 0) && (errno != EAGAIN)) {
00092
return -1;
00093 }
00094
if (res < 0) res = 0;
00095 len -= res;
00096
s += res;
00097 fds[0].
fd = fd;
00098 fds[0].
events =
POLLOUT;
00099
00100 res =
poll(fds, 1, timeoutms);
00101
if (res < 1)
00102
return -1;
00103 }
00104
return res;
00105 }
00106
00107
static char *complete_show_mancmd(
char *line,
char *word,
int pos,
int state)
00108 {
00109
struct manager_action *cur = first_action;
00110
int which = 0;
00111
00112
ast_mutex_lock(&actionlock);
00113
while (cur) {
00114
if (!strncasecmp(word, cur->action, strlen(word))) {
00115
if (++which > state) {
00116
char *ret =
strdup(cur->action);
00117
ast_mutex_unlock(&actionlock);
00118
return ret;
00119 }
00120 }
00121 cur = cur->next;
00122 }
00123
ast_mutex_unlock(&actionlock);
00124
return NULL;
00125 }
00126
00127
static int handle_showmancmd(
int fd,
int argc,
char *argv[])
00128 {
00129
struct manager_action *cur = first_action;
00130
int num;
00131
00132
if (argc != 4)
00133
return RESULT_SHOWUSAGE;
00134
ast_mutex_lock(&actionlock);
00135
while (cur) {
00136
for (num = 3; num < argc; num++) {
00137
if (!strcasecmp(cur->action, argv[num])) {
00138
ast_cli(fd,
"Action: %s\nSynopsis: %s\n%s\n", cur->action, cur->synopsis, cur->description ? cur->description :
"");
00139 }
00140 }
00141 cur = cur->next;
00142 }
00143
00144
ast_mutex_unlock(&actionlock);
00145
return RESULT_SUCCESS;
00146 }
00147
00148
static int handle_showmancmds(
int fd,
int argc,
char *argv[])
00149 {
00150
struct manager_action *cur = first_action;
00151
char *format =
" %-15.15s %-45.45s\n";
00152
00153
ast_mutex_lock(&actionlock);
00154
ast_cli(fd, format,
"Action",
"Synopsis");
00155
while (cur) {
00156
ast_cli(fd, format, cur->action, cur->synopsis);
00157 cur = cur->next;
00158 }
00159
00160
ast_mutex_unlock(&actionlock);
00161
return RESULT_SUCCESS;
00162 }
00163
00164
static int handle_showmanconn(
int fd,
int argc,
char *argv[])
00165 {
00166
struct mansession *
s;
00167
char *format =
" %-15.15s %-15.15s\n";
00168
ast_mutex_lock(&sessionlock);
00169
s = sessions;
00170
ast_cli(fd, format,
"Username",
"IP Address");
00171
while (
s) {
00172
ast_cli(fd, format,
s->username, inet_ntoa(
s->sin.sin_addr));
00173
s =
s->next;
00174 }
00175
00176
ast_mutex_unlock(&sessionlock);
00177
return RESULT_SUCCESS;
00178 }
00179
00180
static char showmancmd_help[] =
00181
"Usage: show manager command <actionname>\n"
00182
" Shows the detailed description for a specific manager command.\n";
00183
00184
static char showmancmds_help[] =
00185
"Usage: show manager commands\n"
00186
" Prints a listing of all the available manager commands.\n";
00187
00188
static char showmanconn_help[] =
00189
"Usage: show manager connected\n"
00190
" Prints a listing of the users that are connected to the\n"
00191
"manager interface.\n";
00192
00193
static struct ast_cli_entry show_mancmd_cli =
00194 { {
"show",
"manager",
"command", NULL },
00195 handle_showmancmd,
"Show manager command", showmancmd_help, complete_show_mancmd };
00196
00197
static struct ast_cli_entry show_mancmds_cli =
00198 { {
"show",
"manager",
"commands", NULL },
00199 handle_showmancmds,
"Show manager commands", showmancmds_help };
00200
00201
static struct ast_cli_entry show_manconn_cli =
00202 { {
"show",
"manager",
"connected", NULL },
00203 handle_showmanconn,
"Show connected manager users", showmanconn_help };
00204
00205
static void destroy_session(
struct mansession *s)
00206 {
00207
struct mansession *cur, *prev = NULL;
00208
ast_mutex_lock(&sessionlock);
00209 cur = sessions;
00210
while(cur) {
00211
if (cur ==
s)
00212
break;
00213 prev = cur;
00214 cur = cur->
next;
00215 }
00216
if (cur) {
00217
if (prev)
00218 prev->
next = cur->
next;
00219
else
00220 sessions = cur->
next;
00221
if (
s->fd > -1)
00222 close(
s->fd);
00223
free(s);
00224 }
else
00225
ast_log(LOG_WARNING,
"Trying to delete non-existant session %p?\n", s);
00226
ast_mutex_unlock(&sessionlock);
00227
00228 }
00229
00230 char *
astman_get_header(
struct message *m,
char *var)
00231 {
00232
char cmp[80];
00233
int x;
00234 snprintf(cmp,
sizeof(cmp),
"%s: ", var);
00235
for (x=0;x<m->
hdrcount;x++)
00236
if (!strncasecmp(cmp, m->
headers[x], strlen(cmp)))
00237
return m->
headers[x] + strlen(cmp);
00238
return "";
00239 }
00240
00241 void astman_send_error(
struct mansession *s,
struct message *m,
char *error)
00242 {
00243
char *
id =
astman_get_header(m,
"ActionID");
00244
ast_mutex_lock(&
s->lock);
00245
ast_cli(
s->fd,
"Response: Error\r\n");
00246
if (
id && !ast_strlen_zero(
id))
00247
ast_cli(
s->fd,
"ActionID: %s\r\n",
id);
00248
ast_cli(
s->fd,
"Message: %s\r\n\r\n", error);
00249
ast_mutex_unlock(&
s->lock);
00250 }
00251
00252 void astman_send_response(
struct mansession *s,
struct message *m,
char *resp,
char *msg)
00253 {
00254
char *
id =
astman_get_header(m,
"ActionID");
00255
ast_mutex_lock(&
s->lock);
00256
ast_cli(
s->fd,
"Response: %s\r\n", resp);
00257
if (
id && !ast_strlen_zero(
id))
00258
ast_cli(
s->fd,
"ActionID: %s\r\n",
id);
00259
if (msg)
00260
ast_cli(
s->fd,
"Message: %s\r\n\r\n", msg);
00261
else
00262
ast_cli(
s->fd,
"\r\n");
00263
ast_mutex_unlock(&
s->lock);
00264 }
00265
00266 void astman_send_ack(
struct mansession *s,
struct message *m,
char *msg)
00267 {
00268
astman_send_response(
s, m,
"Success", msg);
00269 }
00270
00271
static int get_perm(
char *instr)
00272 {
00273
char tmp[256];
00274
char *c;
00275
int x;
00276
int ret = 0;
00277
char *stringp=NULL;
00278
if (!instr)
00279
return 0;
00280 strncpy(tmp, instr,
sizeof(tmp) - 1);
00281 stringp=tmp;
00282 c = strsep(&stringp,
",");
00283
while(c) {
00284
for (x=0;x<
sizeof(perms) /
sizeof(perms[0]);x++) {
00285
if (!strcasecmp(perms[x].label, c))
00286 ret |= perms[x].num;
00287 }
00288 c = strsep(&stringp,
",");
00289 }
00290
return ret;
00291 }
00292
00293
static int set_eventmask(
struct mansession *s,
char *eventmask)
00294 {
00295
if (!eventmask)
00296
return -1;
00297
if (!strcasecmp(eventmask,
"on") ||
ast_true(eventmask)) {
00298
ast_mutex_lock(&
s->lock);
00299
s->send_events = 1;
00300
ast_mutex_unlock(&
s->lock);
00301
return 1;
00302 }
else if (!strcasecmp(eventmask,
"off") ||
ast_false(eventmask)) {
00303
ast_mutex_lock(&
s->lock);
00304
s->send_events = 0;
00305
ast_mutex_unlock(&
s->lock);
00306
return 0;
00307 }
00308
return -1;
00309 }
00310
00311
static int authenticate(
struct mansession *s,
struct message *m)
00312 {
00313
struct ast_config *cfg;
00314
char *cat;
00315
char *user =
astman_get_header(m,
"Username");
00316
char *pass =
astman_get_header(m,
"Secret");
00317
char *authtype =
astman_get_header(m,
"AuthType");
00318
char *
key =
astman_get_header(m,
"Key");
00319
char *events =
astman_get_header(m,
"Events");
00320
00321 cfg =
ast_load(
"manager.conf");
00322
if (!cfg)
00323
return -1;
00324 cat =
ast_category_browse(cfg, NULL);
00325
while(cat) {
00326
if (strcasecmp(cat,
"general")) {
00327
00328
if (!strcasecmp(cat, user)) {
00329
struct ast_variable *v;
00330
struct ast_ha *ha = NULL;
00331
char *password = NULL;
00332 v =
ast_variable_browse(cfg, cat);
00333
while (v) {
00334
if (!strcasecmp(v->name,
"secret")) {
00335 password = v->value;
00336 }
else if (!strcasecmp(v->name,
"permit") ||
00337 !strcasecmp(v->name,
"deny")) {
00338 ha =
ast_append_ha(v->name, v->value, ha);
00339 }
00340 v = v->next;
00341 }
00342
if (ha && !
ast_apply_ha(ha, &(
s->sin))) {
00343
ast_log(LOG_NOTICE,
"%s failed to pass IP ACL as '%s'\n", inet_ntoa(
s->sin.sin_addr), user);
00344
ast_free_ha(ha);
00345
ast_destroy(cfg);
00346
return -1;
00347 }
else if (ha)
00348
ast_free_ha(ha);
00349
if (!strcasecmp(authtype,
"MD5")) {
00350
if (
key && !ast_strlen_zero(key) &&
s->challenge) {
00351
int x;
00352
int len=0;
00353
char md5key[256] =
"";
00354
struct MD5Context md5;
00355
unsigned char digest[16];
00356
MD5Init(&md5);
00357
MD5Update(&md5,
s->challenge, strlen(
s->challenge));
00358
MD5Update(&md5, password, strlen(password));
00359
MD5Final(digest, &md5);
00360
for (x=0;x<16;x++)
00361 len += sprintf(md5key + len,
"%2.2x", digest[x]);
00362
if (!strcmp(md5key, key))
00363
break;
00364
else {
00365
ast_destroy(cfg);
00366
return -1;
00367 }
00368 }
00369 }
else if (password && !strcasecmp(password, pass)) {
00370
break;
00371 }
else {
00372
ast_log(LOG_NOTICE,
"%s failed to authenticate as '%s'\n", inet_ntoa(
s->sin.sin_addr), user);
00373
ast_destroy(cfg);
00374
return -1;
00375 }
00376 }
00377 }
00378 cat =
ast_category_browse(cfg, cat);
00379 }
00380
if (cat) {
00381 strncpy(
s->username, cat,
sizeof(
s->username) - 1);
00382
s->readperm = get_perm(
ast_variable_retrieve(cfg, cat,
"read"));
00383
s->writeperm = get_perm(
ast_variable_retrieve(cfg, cat,
"write"));
00384
ast_destroy(cfg);
00385
if (events)
00386 set_eventmask(s, events);
00387
return 0;
00388 }
00389
ast_log(LOG_NOTICE,
"%s tried to authenticate with non-existant user '%s'\n", inet_ntoa(
s->sin.sin_addr), user);
00390
ast_destroy(cfg);
00391
return -1;
00392 }
00393
00394
static char mandescr_ping[] =
00395
"Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the "
00396
" manager connection open.\n"
00397
"Variables: NONE\n";
00398
00399
static int action_ping(
struct mansession *s,
struct message *m)
00400 {
00401
astman_send_response(s, m,
"Pong", NULL);
00402
return 0;
00403 }
00404
00405
static char mandescr_listcommands[] =
00406
"Description: Returns the action name and synopsis for every\n"
00407
" action that is available to the user\n"
00408
"Variables: NONE\n";
00409
00410
static int action_listcommands(
struct mansession *s,
struct message *m)
00411 {
00412
struct manager_action *cur = first_action;
00413
char idText[256] =
"";
00414
char *
id =
astman_get_header(m,
"ActionID");
00415
00416
if (
id && !ast_strlen_zero(
id))
00417 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00418
ast_cli(
s->fd,
"Response: Success\r\n%s", idText);
00419
ast_mutex_lock(&actionlock);
00420
while (cur) {
00421
if ((
s->writeperm & cur->authority) == cur->authority)
00422
ast_cli(
s->fd,
"%s: %s\r\n", cur->action, cur->synopsis);
00423 cur = cur->next;
00424 }
00425
ast_mutex_unlock(&actionlock);
00426
ast_cli(
s->fd,
"\r\n");
00427
00428
return 0;
00429 }
00430
00431
static int action_events(
struct mansession *s,
struct message *m)
00432 {
00433
char *mask =
astman_get_header(m,
"EventMask");
00434
int res;
00435
00436 res = set_eventmask(s, mask);
00437
if (res > 0)
00438
astman_send_response(s, m,
"Events On", NULL);
00439
else if (res == 0)
00440
astman_send_response(s, m,
"Events Off", NULL);
00441
else
00442
astman_send_response(s, m,
"EventMask parse error", NULL);
00443
return 0;
00444 }
00445
00446
static int action_logoff(
struct mansession *s,
struct message *m)
00447 {
00448
astman_send_response(s, m,
"Goodbye",
"Thanks for all the fish.");
00449
return -1;
00450 }
00451
00452
static int action_hangup(
struct mansession *s,
struct message *m)
00453 {
00454
struct ast_channel *c = NULL;
00455
char *name =
astman_get_header(m,
"Channel");
00456
if (ast_strlen_zero(name)) {
00457
astman_send_error(s, m,
"No channel specified");
00458
return 0;
00459 }
00460 c =
ast_channel_walk_locked(NULL);
00461
while(c) {
00462
if (!strcasecmp(c->name, name)) {
00463
break;
00464 }
00465
ast_mutex_unlock(&c->lock);
00466 c =
ast_channel_walk_locked(c);
00467 }
00468
if (!c) {
00469
astman_send_error(s, m,
"No such channel");
00470
return 0;
00471 }
00472
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
00473
ast_mutex_unlock(&c->lock);
00474
astman_send_ack(s, m,
"Channel Hungup");
00475
return 0;
00476 }
00477
00478
static int action_setvar(
struct mansession *s,
struct message *m)
00479 {
00480
struct ast_channel *c = NULL;
00481
char *name =
astman_get_header(m,
"Channel");
00482
char *varname =
astman_get_header(m,
"Variable");
00483
char *varval =
astman_get_header(m,
"Value");
00484
00485
if (!strlen(name)) {
00486
astman_send_error(s, m,
"No channel specified");
00487
return 0;
00488 }
00489
if (!strlen(varname)) {
00490
astman_send_error(s, m,
"No variable specified");
00491
return 0;
00492 }
00493
00494 c =
ast_channel_walk_locked(NULL);
00495
while(c) {
00496
if (!strcasecmp(c->name, name)) {
00497
break;
00498 }
00499
ast_mutex_unlock(&c->lock);
00500 c =
ast_channel_walk_locked(c);
00501 }
00502
if (!c) {
00503
astman_send_error(s, m,
"No such channel");
00504
return 0;
00505 }
00506
00507
pbx_builtin_setvar_helper(c,varname,varval);
00508
00509
ast_mutex_unlock(&c->lock);
00510
astman_send_ack(s, m,
"Variable Set");
00511
return 0;
00512 }
00513
00514
static int action_getvar(
struct mansession *s,
struct message *m)
00515 {
00516
struct ast_channel *c = NULL;
00517
char *name =
astman_get_header(m,
"Channel");
00518
char *varname =
astman_get_header(m,
"Variable");
00519
char *varval;
00520
00521
if (!strlen(name)) {
00522
astman_send_error(s, m,
"No channel specified");
00523
return 0;
00524 }
00525
if (!strlen(varname)) {
00526
astman_send_error(s, m,
"No variable specified");
00527
return 0;
00528 }
00529
00530 c =
ast_channel_walk_locked(NULL);
00531
while(c) {
00532
if (!strcasecmp(c->name, name)) {
00533
break;
00534 }
00535
ast_mutex_unlock(&c->lock);
00536 c =
ast_channel_walk_locked(c);
00537 }
00538
if (!c) {
00539
astman_send_error(s, m,
"No such channel");
00540
return 0;
00541 }
00542
00543 varval=
pbx_builtin_getvar_helper(c,varname);
00544
00545
ast_mutex_unlock(&c->lock);
00546
ast_cli(
s->fd,
"Response: Success\r\n"
00547
"%s: %s",varname,varval);
00548
00549
return 0;
00550 }
00551
00552
00553
static int action_status(
struct mansession *s,
struct message *m)
00554 {
00555
char *
id =
astman_get_header(m,
"ActionID");
00556
char idText[256] =
"";
00557
struct ast_channel *c;
00558
char bridge[256];
00559
astman_send_ack(s, m,
"Channel status will follow");
00560 c =
ast_channel_walk_locked(NULL);
00561
if (
id && !ast_strlen_zero(
id))
00562 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00563
while(c) {
00564
if (c->bridge)
00565 snprintf(bridge,
sizeof(bridge),
"Link: %s\r\n", c->bridge->name);
00566
else
00567 strcpy(bridge,
"");
00568
if (c->pbx) {
00569
ast_cli(
s->fd,
00570
"Event: Status\r\n"
00571
"Channel: %s\r\n"
00572
"CallerID: %s\r\n"
00573
"State: %s\r\n"
00574
"Context: %s\r\n"
00575
"Extension: %s\r\n"
00576
"Priority: %d\r\n"
00577
"%s"
00578
"Uniqueid: %s\r\n"
00579
"%s"
00580
"\r\n",
00581 c->name, c->callerid ? c->callerid :
"<unknown>",
00582
ast_state2str(c->_state), c->context,
00583 c->exten, c->priority, bridge, c->uniqueid, idText);
00584 }
else {
00585
ast_cli(
s->fd,
00586
"Event: Status\r\n"
00587
"Channel: %s\r\n"
00588
"CallerID: %s\r\n"
00589
"State: %s\r\n"
00590
"%s"
00591
"Uniqueid: %s\r\n"
00592
"%s"
00593
"\r\n",
00594 c->name, c->callerid ? c->callerid :
"<unknown>",
00595
ast_state2str(c->_state), bridge, c->uniqueid, idText);
00596 }
00597
ast_mutex_unlock(&c->lock);
00598 c =
ast_channel_walk_locked(c);
00599 }
00600
ast_cli(
s->fd,
00601
"Event: StatusComplete\r\n"
00602
"%s"
00603
"\r\n",idText);
00604
return 0;
00605 }
00606
00607
static int action_redirect(
struct mansession *s,
struct message *m)
00608 {
00609
char *name =
astman_get_header(m,
"Channel");
00610
char *name2 =
astman_get_header(m,
"ExtraChannel");
00611
char *exten =
astman_get_header(m,
"Exten");
00612
char *context =
astman_get_header(m,
"Context");
00613
char *priority =
astman_get_header(m,
"Priority");
00614
struct ast_channel *chan, *chan2 = NULL;
00615
int pi = 0;
00616
int res;
00617
if (!name || ast_strlen_zero(name)) {
00618
astman_send_error(s, m,
"Channel not specified");
00619
return 0;
00620 }
00621
if (!ast_strlen_zero(priority) && (sscanf(priority,
"%d", &pi) != 1)) {
00622
astman_send_error(s, m,
"Invalid priority\n");
00623
return 0;
00624 }
00625 chan =
ast_get_channel_by_name_locked(name);
00626
if (!chan) {
00627
astman_send_error(s, m,
"Channel not existant");
00628
return 0;
00629 }
00630
if (!ast_strlen_zero(name2))
00631 chan2 =
ast_get_channel_by_name_locked(name2);
00632 res =
ast_async_goto(chan, context, exten, pi);
00633
if (!res) {
00634
if (!ast_strlen_zero(name2)) {
00635
if (chan2)
00636 res =
ast_async_goto(chan2, context, exten, pi);
00637
else
00638 res = -1;
00639
if (!res)
00640
astman_send_ack(s, m,
"Dual Redirect successful");
00641
else
00642
astman_send_error(s, m,
"Secondary redirect failed");
00643 }
else
00644
astman_send_ack(s, m,
"Redirect successful");
00645 }
else
00646
astman_send_error(s, m,
"Redirect failed");
00647
if (chan)
00648
ast_mutex_unlock(&chan->lock);
00649
if (chan2)
00650
ast_mutex_unlock(&chan2->lock);
00651
return 0;
00652 }
00653
00654
static int action_command(
struct mansession *s,
struct message *m)
00655 {
00656
char *cmd =
astman_get_header(m,
"Command");
00657
char *
id =
astman_get_header(m,
"ActionID");
00658
ast_mutex_lock(&
s->lock);
00659
s->blocking = 1;
00660
ast_mutex_unlock(&
s->lock);
00661
ast_cli(
s->fd,
"Response: Follows\r\n");
00662
if (
id && !ast_strlen_zero(
id))
00663
ast_cli(
s->fd,
"ActionID: %s\r\n",
id);
00664
00665
ast_cli_command(
s->fd, cmd);
00666
ast_cli(
s->fd,
"--END COMMAND--\r\n\r\n");
00667
ast_mutex_lock(&
s->lock);
00668
s->blocking = 0;
00669
ast_mutex_unlock(&
s->lock);
00670
return 0;
00671 }
00672
00673
static void *fast_originate(
void *data)
00674 {
00675
struct fast_originate_helper *in = data;
00676
int res;
00677
int reason = 0;
00678
if (!ast_strlen_zero(in->app)) {
00679 res =
ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, !ast_strlen_zero(in->callerid) ? in->callerid : NULL, in->variable, in->account);
00680 }
else {
00681 res =
ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, !ast_strlen_zero(in->callerid) ? in->callerid : NULL, in->variable, in->account);
00682 }
00683
free(in);
00684
return NULL;
00685 }
00686
00687
static char mandescr_originate[] =
00688
"Description: Generates an outgoing call to a Extension/Context/Priority or\n"
00689
" Application/Data\n"
00690
"Variables: (Names marked with * are required)\n"
00691
" *Channel: Channel name to call\n"
00692
" Exten: Extension to use (requires 'Context' and 'Priority')\n"
00693
" Context: Context to use (requires 'Exten' and 'Priority')\n"
00694
" Priority: Priority to use (requires 'Exten' and 'Context')\n"
00695
" Application: Application to use\n"
00696
" Data: Data to use (requires 'Application')\n"
00697
" Timeout: How long to wait for call to be answered (in ms)\n"
00698
" CallerID: Caller ID to be set on the outgoing channel\n"
00699
" Variable: Channel variable to set (VAR1=value1|VAR2=value2)\n"
00700
" Account: Account code\n"
00701
" Async: Set to 'true' for fast origination\n";
00702
00703
static int action_originate(
struct mansession *s,
struct message *m)
00704 {
00705
char *name =
astman_get_header(m,
"Channel");
00706
char *exten =
astman_get_header(m,
"Exten");
00707
char *context =
astman_get_header(m,
"Context");
00708
char *priority =
astman_get_header(m,
"Priority");
00709
char *timeout =
astman_get_header(m,
"Timeout");
00710
char *callerid =
astman_get_header(m,
"CallerID");
00711
char *variable =
astman_get_header(m,
"Variable");
00712
char *account =
astman_get_header(m,
"Account");
00713
char *app =
astman_get_header(m,
"Application");
00714
char *appdata =
astman_get_header(m,
"Data");
00715
char *async =
astman_get_header(m,
"Async");
00716
char *tech, *data;
00717
int pi = 0;
00718
int res;
00719
int to = 30000;
00720
int reason = 0;
00721
char tmp[256];
00722 pthread_t th;
00723 pthread_attr_t attr;
00724
if (!name) {
00725
astman_send_error(s, m,
"Channel not specified");
00726
return 0;
00727 }
00728
if (!ast_strlen_zero(priority) && (sscanf(priority,
"%d", &pi) != 1)) {
00729
astman_send_error(s, m,
"Invalid priority\n");
00730
return 0;
00731 }
00732
if (!ast_strlen_zero(timeout) && (sscanf(timeout,
"%d", &to) != 1)) {
00733
astman_send_error(s, m,
"Invalid timeout\n");
00734
return 0;
00735 }
00736 strncpy(tmp, name,
sizeof(tmp) - 1);
00737 tech = tmp;
00738 data = strchr(tmp,
'/');
00739
if (!data) {
00740
astman_send_error(s, m,
"Invalid channel\n");
00741
return 0;
00742 }
00743 *data =
'\0';
00744 data++;
00745
if (
ast_true(async))
00746 {
00747
struct fast_originate_helper *fast =
malloc(
sizeof(
struct fast_originate_helper));
00748
if (!fast)
00749 {
00750 res = -1;
00751 }
00752
else
00753 {
00754 memset(fast, 0,
sizeof(
struct fast_originate_helper));
00755 strncpy(fast->tech, tech,
sizeof(fast->tech) - 1);
00756 strncpy(fast->data, data,
sizeof(fast->data) - 1);
00757 strncpy(fast->app, app,
sizeof(fast->app) - 1);
00758 strncpy(fast->appdata, appdata,
sizeof(fast->appdata) - 1);
00759 strncpy(fast->callerid, callerid,
sizeof(fast->callerid) - 1);
00760 strncpy(fast->variable, variable,
sizeof(fast->variable) - 1);
00761 strncpy(fast->account, account,
sizeof(fast->account) - 1);
00762 strncpy(fast->context, context,
sizeof(fast->context) - 1);
00763 strncpy(fast->exten, exten,
sizeof(fast->exten) - 1);
00764 fast->timeout = to;
00765 fast->priority = pi;
00766 pthread_attr_init(&attr);
00767 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00768
if (pthread_create(&th, &attr, fast_originate, fast))
00769 {
00770 res = -1;
00771 }
00772
else
00773 {
00774 res = 0;
00775 }
00776 }
00777 }
else if (!ast_strlen_zero(app)) {
00778 res =
ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 0, !ast_strlen_zero(callerid) ? callerid : NULL, variable, account);
00779 }
else {
00780
if (exten && context && pi)
00781 res =
ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 0, !ast_strlen_zero(callerid) ? callerid : NULL, variable, account);
00782
else {
00783
astman_send_error(s, m,
"Originate with 'Exten' requires 'Context' and 'Priority'");
00784
return 0;
00785 }
00786 }
00787
if (!res)
00788
astman_send_ack(s, m,
"Originate successfully queued");
00789
else
00790
astman_send_error(s, m,
"Originate failed");
00791
return 0;
00792 }
00793
00794
static int action_mailboxstatus(
struct mansession *s,
struct message *m)
00795 {
00796
char *mailbox =
astman_get_header(m,
"Mailbox");
00797
char *
id =
astman_get_header(m,
"ActionID");
00798
char idText[256] =
"";
00799
if (!mailbox || ast_strlen_zero(mailbox)) {
00800
astman_send_error(s, m,
"Mailbox not specified");
00801
return 0;
00802 }
00803
if (
id && !ast_strlen_zero(
id))
00804 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00805
ast_cli(
s->fd,
"Response: Success\r\n"
00806
"%s"
00807
"Message: Mailbox Status\r\n"
00808
"Mailbox: %s\r\n"
00809
"Waiting: %d\r\n\r\n", idText, mailbox,
ast_app_has_voicemail(mailbox));
00810
return 0;
00811 }
00812
00813
static int action_mailboxcount(
struct mansession *s,
struct message *m)
00814 {
00815
char *mailbox =
astman_get_header(m,
"Mailbox");
00816
char *
id =
astman_get_header(m,
"ActionID");
00817
char idText[256] =
"";
00818
int newmsgs = 0, oldmsgs = 0;
00819
if (!mailbox || ast_strlen_zero(mailbox)) {
00820
astman_send_error(s, m,
"Mailbox not specified");
00821
return 0;
00822 }
00823
ast_app_messagecount(mailbox, &newmsgs, &oldmsgs);
00824
if (
id && !ast_strlen_zero(
id)) {
00825 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00826 }
00827
ast_cli(
s->fd,
"Response: Success\r\n"
00828
"%s"
00829
"Message: Mailbox Message Count\r\n"
00830
"Mailbox: %s\r\n"
00831
"NewMessages: %d\r\n"
00832
"OldMessages: %d\r\n"
00833
"\r\n",
00834 idText,mailbox, newmsgs, oldmsgs);
00835
return 0;
00836 }
00837
00838
static int action_extensionstate(
struct mansession *s,
struct message *m)
00839 {
00840
char *exten =
astman_get_header(m,
"Exten");
00841
char *context =
astman_get_header(m,
"Context");
00842
char *
id =
astman_get_header(m,
"ActionID");
00843
char idText[256] =
"";
00844
char hint[256] =
"";
00845
int status;
00846
if (!exten || ast_strlen_zero(exten)) {
00847
astman_send_error(s, m,
"Extension not specified");
00848
return 0;
00849 }
00850
if (!context || ast_strlen_zero(context))
00851 context =
"default";
00852 status =
ast_extension_state(NULL, context, exten);
00853
ast_get_hint(hint,
sizeof(hint) - 1, NULL, context, exten);
00854
if (
id && !ast_strlen_zero(
id)) {
00855 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00856 }
00857
ast_cli(
s->fd,
"Response: Success\r\n"
00858
"%s"
00859
"Message: Extension Status\r\n"
00860
"Exten: %s\r\n"
00861
"Context: %s\r\n"
00862
"Hint: %s\r\n"
00863
"Status: %d\r\n\r\n",
00864 idText,exten, context, hint, status);
00865
return 0;
00866 }
00867
00868
static int action_timeout(
struct mansession *s,
struct message *m)
00869 {
00870
struct ast_channel *c = NULL;
00871
char *name =
astman_get_header(m,
"Channel");
00872
int timeout = atoi(
astman_get_header(m,
"Timeout"));
00873
if (ast_strlen_zero(name)) {
00874
astman_send_error(s, m,
"No channel specified");
00875
return 0;
00876 }
00877
if (!timeout) {
00878
astman_send_error(s, m,
"No timeout specified");
00879
return 0;
00880 }
00881 c =
ast_channel_walk_locked(NULL);
00882
while(c) {
00883
if (!strcasecmp(c->name, name)) {
00884
break;
00885 }
00886
ast_mutex_unlock(&c->lock);
00887 c =
ast_channel_walk_locked(c);
00888 }
00889
if (!c) {
00890
astman_send_error(s, m,
"No such channel");
00891
return 0;
00892 }
00893
ast_channel_setwhentohangup(c, timeout);
00894
ast_mutex_unlock(&c->lock);
00895
astman_send_ack(s, m,
"Timeout Set");
00896
return 0;
00897 }
00898
00899
static int process_message(
struct mansession *s,
struct message *m)
00900 {
00901
char action[80];
00902
struct manager_action *tmp = first_action;
00903
char *
id =
astman_get_header(m,
"ActionID");
00904
char idText[256] =
"";
00905
00906 strncpy(action,
astman_get_header(m,
"Action"),
sizeof(action));
00907
ast_log( LOG_DEBUG,
"Manager received command '%s'\n", action );
00908
00909
if (ast_strlen_zero(action)) {
00910
astman_send_error(s, m,
"Missing action in request");
00911
return 0;
00912 }
00913
if (
id && !ast_strlen_zero(
id)) {
00914 snprintf(idText,256,
"ActionID: %s\r\n",
id);
00915 }
00916
if (!
s->authenticated) {
00917
if (!strcasecmp(action,
"Challenge")) {
00918
char *authtype;
00919 authtype =
astman_get_header(m,
"AuthType");
00920
if (!strcasecmp(authtype,
"MD5")) {
00921
if (!
s->challenge || ast_strlen_zero(
s->challenge)) {
00922
ast_mutex_lock(&
s->lock);
00923 snprintf(
s->challenge,
sizeof(
s->challenge),
"%d", rand());
00924
ast_mutex_unlock(&
s->lock);
00925 }
00926
ast_cli(
s->fd,
"Response: Success\r\n"
00927
"%s"
00928
"Challenge: %s\r\n\r\n",
00929 idText,
s->challenge);
00930
return 0;
00931 }
else {
00932
astman_send_error(s, m,
"Must specify AuthType");
00933
return 0;
00934 }
00935 }
else if (!strcasecmp(action,
"Login")) {
00936
if (authenticate(s, m)) {
00937 sleep(1);
00938
astman_send_error(s, m,
"Authentication failed");
00939
return -1;
00940 }
else {
00941
s->authenticated = 1;
00942
if (
option_verbose > 1)
00943
ast_verbose(VERBOSE_PREFIX_2
"Manager '%s' logged on from %s\n",
s->username, inet_ntoa(
s->sin.sin_addr));
00944
ast_log(LOG_EVENT,
"Manager '%s' logged on from %s\n",
s->username, inet_ntoa(
s->sin.sin_addr));
00945
astman_send_ack(s, m,
"Authentication accepted");
00946 }
00947 }
else if (!strcasecmp(action,
"Logoff")) {
00948
astman_send_ack(s, m,
"See ya");
00949
return -1;
00950 }
else
00951
astman_send_error(s, m,
"Authentication Required");
00952 }
else {
00953
while( tmp ) {
00954
if (!strcasecmp(action, tmp->action)) {
00955
if ((
s->writeperm & tmp->authority) == tmp->authority) {
00956
if (tmp->func(s, m))
00957
return -1;
00958 }
else {
00959
astman_send_error(s, m,
"Permission denied");
00960 }
00961
return 0;
00962 }
00963 tmp = tmp->next;
00964 }
00965
astman_send_error(s, m,
"Invalid/unknown command");
00966 }
00967
return 0;
00968 }
00969
00970
static int get_input(
struct mansession *s,
char *output)
00971 {
00972
00973
int res;
00974
int x;
00975
struct pollfd fds[1];
00976
for (x=1;x<
s->inlen;x++) {
00977
if ((
s->inbuf[x] ==
'\n') && (
s->inbuf[x-1] ==
'\r')) {
00978
00979 memcpy(output,
s->inbuf, x + 1);
00980
00981 output[x+1] =
'\0';
00982
00983 memmove(
s->inbuf,
s->inbuf + x + 1,
s->inlen - x);
00984
s->inlen -= (x + 1);
00985
return 1;
00986 }
00987 }
00988
if (
s->inlen >=
sizeof(
s->inbuf) - 1) {
00989
ast_log(LOG_WARNING,
"Dumping long line with no return from %s: %s\n", inet_ntoa(
s->sin.sin_addr),
s->inbuf);
00990
s->inlen = 0;
00991 }
00992 fds[0].
fd =
s->fd;
00993 fds[0].
events =
POLLIN;
00994 res =
poll(fds, 1, -1);
00995
if (res < 0) {
00996
ast_log(LOG_WARNING,
"Select returned error: %s\n", strerror(errno));
00997 }
else if (res > 0) {
00998
ast_mutex_lock(&
s->lock);
00999 res = read(
s->fd,
s->inbuf +
s->inlen,
sizeof(
s->inbuf) - 1 -
s->inlen);
01000
ast_mutex_unlock(&
s->lock);
01001
if (res < 1)
01002
return -1;
01003 }
01004
s->inlen += res;
01005
s->inbuf[
s->inlen] =
'\0';
01006
return 0;
01007 }
01008
01009
static void *session_do(
void *data)
01010 {
01011
struct mansession *
s = data;
01012
struct message m;
01013
int res;
01014
01015
ast_mutex_lock(&
s->lock);
01016
ast_cli(
s->fd,
"Asterisk Call Manager/1.0\r\n");
01017
ast_mutex_unlock(&
s->lock);
01018 memset(&m, 0,
sizeof(&m));
01019
for (;;) {
01020 res = get_input(s, m.
headers[m.
hdrcount]);
01021
if (res > 0) {
01022
01023
if (strlen(m.
headers[m.
hdrcount]) < 2)
01024
continue;
01025 m.
headers[m.
hdrcount][strlen(m.
headers[m.
hdrcount]) - 2] =
'\0';
01026
if (ast_strlen_zero(m.
headers[m.
hdrcount])) {
01027
if (process_message(s, &m))
01028
break;
01029 memset(&m, 0,
sizeof(&m));
01030 }
else if (m.
hdrcount <
MAX_HEADERS - 1)
01031 m.
hdrcount++;
01032 }
else if (res < 0)
01033
break;
01034 }
01035
if (
s->authenticated) {
01036
if (
option_verbose > 1)
01037
ast_verbose(VERBOSE_PREFIX_2
"Manager '%s' logged off from %s\n",
s->username, inet_ntoa(
s->sin.sin_addr));
01038
ast_log(LOG_EVENT,
"Manager '%s' logged off from %s\n",
s->username, inet_ntoa(
s->sin.sin_addr));
01039 }
else {
01040
if (
option_verbose > 1)
01041
ast_verbose(VERBOSE_PREFIX_2
"Connect attempt from '%s' unable to authenticate\n", inet_ntoa(
s->sin.sin_addr));
01042
ast_log(LOG_EVENT,
"Failed attempt from %s\n", inet_ntoa(
s->sin.sin_addr));
01043 }
01044 destroy_session(s);
01045
return NULL;
01046 }
01047
01048
static void *accept_thread(
void *ignore)
01049 {
01050
int as;
01051
struct sockaddr_in sin;
01052
int sinlen;
01053
struct mansession *
s;
01054
struct protoent *p;
01055
int arg = 1;
01056
int flags;
01057 pthread_attr_t attr;
01058
01059 pthread_attr_init(&attr);
01060 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01061
01062
for (;;) {
01063 sinlen =
sizeof(sin);
01064 as = accept(asock, (
struct sockaddr *)&sin, &sinlen);
01065
if (as < 0) {
01066
ast_log(LOG_NOTICE,
"Accept returned -1: %s\n", strerror(errno));
01067
continue;
01068 }
01069 p = getprotobyname(
"tcp");
01070
if( p ) {
01071
if( setsockopt(as, p->p_proto, TCP_NODELAY, (
char *)&arg,
sizeof(arg) ) < 0 ) {
01072
ast_log(LOG_WARNING,
"Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
01073 }
01074 }
01075
s =
malloc(
sizeof(
struct mansession));
01076
if (!
s) {
01077
ast_log(LOG_WARNING,
"Failed to allocate management session: %s\n", strerror(errno));
01078
continue;
01079 }
01080 memset(s, 0,
sizeof(
struct mansession));
01081 memcpy(&
s->sin, &sin,
sizeof(sin));
01082
01083
if(! block_sockets) {
01084
01085 flags = fcntl(as, F_GETFL);
01086 fcntl(as, F_SETFL, flags | O_NONBLOCK);
01087 }
01088 ast_mutex_init(&
s->lock);
01089
s->fd = as;
01090
s->send_events = 1;
01091
ast_mutex_lock(&sessionlock);
01092
s->next = sessions;
01093 sessions =
s;
01094
ast_mutex_unlock(&sessionlock);
01095
if (pthread_create(&t, &attr, session_do, s))
01096 destroy_session(s);
01097 }
01098 pthread_attr_destroy(&attr);
01099
return NULL;
01100 }
01101
01102 int manager_event(
int category,
char *event,
char *fmt, ...)
01103 {
01104
struct mansession *
s;
01105
char tmp[4096];
01106 va_list ap;
01107
01108
ast_mutex_lock(&sessionlock);
01109
s = sessions;
01110
while(
s) {
01111
if (((
s->readperm & category) == category) &&
s->send_events) {
01112
ast_mutex_lock(&
s->lock);
01113
if (!
s->blocking) {
01114
ast_cli(
s->fd,
"Event: %s\r\n", event);
01115 va_start(ap, fmt);
01116 vsnprintf(tmp,
sizeof(tmp), fmt, ap);
01117 va_end(ap);
01118
ast_carefulwrite(
s->fd,tmp,strlen(tmp),100);
01119
ast_cli(
s->fd,
"\r\n");
01120 }
01121
ast_mutex_unlock(&
s->lock);
01122 }
01123
s =
s->next;
01124 }
01125
ast_mutex_unlock(&sessionlock);
01126
return 0;
01127 }
01128
01129 int ast_manager_unregister(
char *action ) {
01130
struct manager_action *cur = first_action, *prev = first_action;
01131
01132
ast_mutex_lock(&actionlock);
01133
while( cur ) {
01134
if (!strcasecmp(action, cur->action)) {
01135 prev->next = cur->next;
01136
free(cur);
01137
if (
option_verbose > 1)
01138
ast_verbose(
VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action);
01139
ast_mutex_unlock(&actionlock);
01140
return 0;
01141 }
01142 prev = cur;
01143 cur = cur->next;
01144 }
01145
ast_mutex_unlock(&actionlock);
01146
return 0;
01147 }
01148
01149
static int manager_state_cb(
char *context,
char *exten,
int state,
void *data)
01150 {
01151
01152
manager_event(EVENT_FLAG_CALL,
"ExtensionStatus",
"Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state);
01153
return 0;
01154 }
01155
01156
static int ast_manager_register_struct(
struct manager_action *act)
01157 {
01158
struct manager_action *cur = first_action, *prev = NULL;
01159
int ret;
01160
01161
ast_mutex_lock(&actionlock);
01162
while(cur) {
01163 ret = strcasecmp(cur->action, act->
action);
01164
if (ret == 0) {
01165
ast_log(LOG_WARNING,
"Manager: Action '%s' already registered\n", act->
action);
01166
ast_mutex_unlock(&actionlock);
01167
return -1;
01168 }
else if (ret > 0) {
01169
01170
if (prev) {
01171 act->
next = prev->
next;
01172 prev->
next = act;
01173 }
else {
01174 act->
next = first_action;
01175 first_action = act;
01176 }
01177
break;
01178 }
01179 prev = cur;
01180 cur = cur->
next;
01181 }
01182
01183
if (!cur) {
01184
if (prev)
01185 prev->
next = act;
01186
else
01187 first_action = act;
01188 act->
next = NULL;
01189 }
01190
01191
if (
option_verbose > 1)
01192
ast_verbose(VERBOSE_PREFIX_2
"Manager registered action %s\n", act->
action);
01193
ast_mutex_unlock(&actionlock);
01194
return 0;
01195 }
01196
01197 int ast_manager_register2(
char *action,
int auth,
int (*func)(
struct mansession *s,
struct message *m),
char *synopsis,
char *description)
01198 {
01199
struct manager_action *cur;
01200
01201 cur =
malloc(
sizeof(
struct manager_action));
01202
if (!cur) {
01203
ast_log(
LOG_WARNING,
"Manager: out of memory trying to register action\n");
01204
ast_mutex_unlock(&actionlock);
01205
return -1;
01206 }
01207 cur->action = action;
01208 cur->authority = auth;
01209 cur->func = func;
01210 cur->synopsis = synopsis;
01211 cur->description =
description;
01212 cur->next = NULL;
01213
01214 ast_manager_register_struct(cur);
01215
01216
return 0;
01217 }
01218
01219
static int registered = 0;
01220
01221 int init_manager(
void)
01222 {
01223
struct ast_config *cfg;
01224
char *
val;
01225
int oldportno = portno;
01226
static struct sockaddr_in ba;
01227
int x = 1;
01228
if (!registered) {
01229
01230
ast_manager_register2(
"Ping", 0, action_ping,
"Ping", mandescr_ping);
01231
ast_manager_register(
"Events", 0, action_events,
"Contol Event Flow" );
01232
ast_manager_register(
"Logoff", 0, action_logoff,
"Logoff Manager" );
01233
ast_manager_register(
"Hangup",
EVENT_FLAG_CALL, action_hangup,
"Hangup Channel" );
01234
ast_manager_register(
"Status",
EVENT_FLAG_CALL, action_status,
"Status" );
01235
ast_manager_register(
"Setvar",
EVENT_FLAG_CALL, action_setvar,
"Set Channel Variable" );
01236
ast_manager_register(
"Getvar",
EVENT_FLAG_CALL, action_getvar,
"Gets a Channel Variable" );
01237
ast_manager_register(
"Redirect",
EVENT_FLAG_CALL, action_redirect,
"Redirect" );
01238
ast_manager_register2(
"Originate",
EVENT_FLAG_CALL, action_originate,
"Originate Call", mandescr_originate);
01239
ast_manager_register(
"MailboxStatus",
EVENT_FLAG_CALL, action_mailboxstatus,
"Check Mailbox" );
01240
ast_manager_register(
"Command",
EVENT_FLAG_COMMAND, action_command,
"Execute Command" );
01241
ast_manager_register(
"ExtensionState",
EVENT_FLAG_CALL, action_extensionstate,
"Check Extension Status" );
01242
ast_manager_register(
"AbsoluteTimeout",
EVENT_FLAG_CALL, action_timeout,
"Set Absolute Timeout" );
01243
ast_manager_register(
"MailboxCount",
EVENT_FLAG_CALL, action_mailboxcount,
"Check Mailbox Message Count" );
01244
ast_manager_register2(
"ListCommands", 0, action_listcommands,
"List available manager commands", mandescr_listcommands);
01245
01246
ast_cli_register(&show_mancmd_cli);
01247
ast_cli_register(&show_mancmds_cli);
01248
ast_cli_register(&show_manconn_cli);
01249
ast_extension_state_add(NULL, NULL, manager_state_cb, NULL);
01250 registered = 1;
01251 }
01252 portno =
DEFAULT_MANAGER_PORT;
01253 cfg =
ast_load(
"manager.conf");
01254
if (!cfg) {
01255
ast_log(
LOG_NOTICE,
"Unable to open management configuration manager.conf. Call management disabled.\n");
01256
return 0;
01257 }
01258 memset(&ba, 0,
sizeof(ba));
01259 val =
ast_variable_retrieve(cfg,
"general",
"enabled");
01260
if (val)
01261 enabled =
ast_true(val);
01262
01263 val =
ast_variable_retrieve(cfg,
"general",
"block-sockets");
01264
if(val)
01265 block_sockets =
ast_true(val);
01266
01267
if ((val =
ast_variable_retrieve(cfg,
"general",
"port"))) {
01268
if (sscanf(val,
"%d", &portno) != 1) {
01269
ast_log(
LOG_WARNING,
"Invalid port number '%s'\n", val);
01270 portno =
DEFAULT_MANAGER_PORT;
01271 }
01272 }
else if ((val =
ast_variable_retrieve(cfg,
"general",
"portno"))) {
01273
if (sscanf(val,
"%d", &portno) != 1) {
01274
ast_log(
LOG_WARNING,
"Invalid port number '%s'\n", val);
01275 portno =
DEFAULT_MANAGER_PORT;
01276 }
01277
ast_log(
LOG_NOTICE,
"Use of portno in manager.conf deprecated. Please use 'port=%s' instead.\n", val);
01278 }
01279
01280 ba.sin_family = AF_INET;
01281 ba.sin_port = htons(portno);
01282 memset(&ba.sin_addr, 0,
sizeof(ba.sin_addr));
01283
01284
if ((val =
ast_variable_retrieve(cfg,
"general",
"bindaddr"))) {
01285
if (!inet_aton(val, &ba.sin_addr)) {
01286
ast_log(
LOG_WARNING,
"Invalid address '%s' specified, using 0.0.0.0\n", val);
01287 memset(&ba.sin_addr, 0,
sizeof(ba.sin_addr));
01288 }
01289 }
01290
01291
if ((asock > -1) && ((portno != oldportno) || !enabled)) {
01292
#if 0
01293
01294 close(asock);
01295 asock = -1;
01296
#else
01297
ast_log(
LOG_WARNING,
"Unable to change management port / enabled\n");
01298
#endif
01299
}
01300
ast_destroy(cfg);
01301
01302
01303
if (!enabled) {
01304
return 0;
01305 }
01306
if (asock < 0) {
01307 asock = socket(AF_INET, SOCK_STREAM, 0);
01308
if (asock < 0) {
01309
ast_log(
LOG_WARNING,
"Unable to create socket: %s\n", strerror(errno));
01310
return -1;
01311 }
01312 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x,
sizeof(x));
01313
if (bind(asock, (
struct sockaddr *)&ba,
sizeof(ba))) {
01314
ast_log(
LOG_WARNING,
"Unable to bind socket: %s\n", strerror(errno));
01315 close(asock);
01316 asock = -1;
01317
return -1;
01318 }
01319
if (listen(asock, 2)) {
01320
ast_log(
LOG_WARNING,
"Unable to listen on socket: %s\n", strerror(errno));
01321 close(asock);
01322 asock = -1;
01323
return -1;
01324 }
01325
if (
option_verbose)
01326
ast_verbose(
"Asterisk Management interface listening on port %d\n", portno);
01327 pthread_create(&t, NULL, accept_thread, NULL);
01328 }
01329
return 0;
01330 }
01331
01332 int reload_manager(
void)
01333 {
01334
manager_event(
EVENT_FLAG_SYSTEM,
"Reload",
"Message: Reload Requested\r\n");
01335
return init_manager();
01336 }