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