00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <sys/time.h>
00037 #include <sys/types.h>
00038 #include <netdb.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <netinet/tcp.h>
00042 #include <arpa/inet.h>
00043 #include <signal.h>
00044 #include <errno.h>
00045 #include <unistd.h>
00046
00047 #include "asterisk.h"
00048
00049 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 71288 $")
00050
00051 #include "asterisk/channel.h"
00052 #include "asterisk/file.h"
00053 #include "asterisk/manager.h"
00054 #include "asterisk/config.h"
00055 #include "asterisk/callerid.h"
00056 #include "asterisk/lock.h"
00057 #include "asterisk/logger.h"
00058 #include "asterisk/options.h"
00059 #include "asterisk/cli.h"
00060 #include "asterisk/app.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/md5.h"
00063 #include "asterisk/acl.h"
00064 #include "asterisk/utils.h"
00065
00066 struct fast_originate_helper {
00067 char tech[AST_MAX_MANHEADER_LEN];
00068 char data[AST_MAX_MANHEADER_LEN];
00069 int timeout;
00070 char app[AST_MAX_APP];
00071 char appdata[AST_MAX_MANHEADER_LEN];
00072 char cid_name[AST_MAX_MANHEADER_LEN];
00073 char cid_num[AST_MAX_MANHEADER_LEN];
00074 char context[AST_MAX_CONTEXT];
00075 char exten[AST_MAX_EXTENSION];
00076 char idtext[AST_MAX_MANHEADER_LEN];
00077 char account[AST_MAX_ACCOUNT_CODE];
00078 int priority;
00079 struct ast_variable *vars;
00080 };
00081
00082 static int enabled = 0;
00083 static int portno = DEFAULT_MANAGER_PORT;
00084 static int asock = -1;
00085 static int displayconnects = 1;
00086
00087 static pthread_t t;
00088 AST_MUTEX_DEFINE_STATIC(sessionlock);
00089 static int block_sockets = 0;
00090
00091 static struct permalias {
00092 int num;
00093 char *label;
00094 } perms[] = {
00095 { EVENT_FLAG_SYSTEM, "system" },
00096 { EVENT_FLAG_CALL, "call" },
00097 { EVENT_FLAG_LOG, "log" },
00098 { EVENT_FLAG_VERBOSE, "verbose" },
00099 { EVENT_FLAG_COMMAND, "command" },
00100 { EVENT_FLAG_AGENT, "agent" },
00101 { EVENT_FLAG_USER, "user" },
00102 { -1, "all" },
00103 { 0, "none" },
00104 };
00105
00106 static struct mansession *sessions = NULL;
00107 static struct manager_action *first_action = NULL;
00108 AST_MUTEX_DEFINE_STATIC(actionlock);
00109
00110
00111
00112
00113
00114 int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
00115 {
00116
00117
00118 int res=0;
00119 struct pollfd fds[1];
00120 while(len) {
00121 res = write(fd, s, len);
00122 if ((res < 0) && (errno != EAGAIN)) {
00123 return -1;
00124 }
00125 if (res < 0) res = 0;
00126 len -= res;
00127 s += res;
00128 res = 0;
00129 if (len) {
00130 fds[0].fd = fd;
00131 fds[0].events = POLLOUT;
00132
00133 res = poll(fds, 1, timeoutms);
00134 if (res < 1)
00135 return -1;
00136 }
00137 }
00138 return res;
00139 }
00140
00141
00142 static char *authority_to_str(int authority, char *res, int reslen)
00143 {
00144 int running_total = 0, i;
00145 memset(res, 0, reslen);
00146 for (i=0; i<sizeof(perms) / sizeof(perms[0]) - 1; i++) {
00147 if (authority & perms[i].num) {
00148 if (*res) {
00149 strncat(res, ",", (reslen > running_total) ? reslen - running_total : 0);
00150 running_total++;
00151 }
00152 strncat(res, perms[i].label, (reslen > running_total) ? reslen - running_total : 0);
00153 running_total += strlen(perms[i].label);
00154 }
00155 }
00156 if (ast_strlen_zero(res)) {
00157 ast_copy_string(res, "<none>", reslen);
00158 }
00159 return res;
00160 }
00161
00162 static char *complete_show_mancmd(char *line, char *word, int pos, int state)
00163 {
00164 struct manager_action *cur = first_action;
00165 int which = 0;
00166
00167 ast_mutex_lock(&actionlock);
00168 while (cur) {
00169 if (!strncasecmp(word, cur->action, strlen(word))) {
00170 if (++which > state) {
00171 char *ret = strdup(cur->action);
00172 ast_mutex_unlock(&actionlock);
00173 return ret;
00174 }
00175 }
00176 cur = cur->next;
00177 }
00178 ast_mutex_unlock(&actionlock);
00179 return NULL;
00180 }
00181
00182 static int handle_showmancmd(int fd, int argc, char *argv[])
00183 {
00184 struct manager_action *cur = first_action;
00185 char authority[80];
00186 int num;
00187
00188 if (argc != 4)
00189 return RESULT_SHOWUSAGE;
00190 ast_mutex_lock(&actionlock);
00191 while (cur) {
00192 for (num = 3; num < argc; num++) {
00193 if (!strcasecmp(cur->action, argv[num])) {
00194 ast_cli(fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", cur->action, cur->synopsis, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->description ? cur->description : "");
00195 }
00196 }
00197 cur = cur->next;
00198 }
00199
00200 ast_mutex_unlock(&actionlock);
00201 return RESULT_SUCCESS;
00202 }
00203
00204
00205
00206 static int handle_showmancmds(int fd, int argc, char *argv[])
00207 {
00208 struct manager_action *cur = first_action;
00209 char authority[80];
00210 char *format = " %-15.15s %-15.15s %-55.55s\n";
00211
00212 ast_mutex_lock(&actionlock);
00213 ast_cli(fd, format, "Action", "Privilege", "Synopsis");
00214 ast_cli(fd, format, "------", "---------", "--------");
00215 while (cur) {
00216 ast_cli(fd, format, cur->action, authority_to_str(cur->authority, authority, sizeof(authority) -1), cur->synopsis);
00217 cur = cur->next;
00218 }
00219
00220 ast_mutex_unlock(&actionlock);
00221 return RESULT_SUCCESS;
00222 }
00223
00224
00225
00226 static int handle_showmanconn(int fd, int argc, char *argv[])
00227 {
00228 struct mansession *s;
00229 char iabuf[INET_ADDRSTRLEN];
00230 char *format = " %-15.15s %-15.15s\n";
00231 ast_mutex_lock(&sessionlock);
00232 s = sessions;
00233 ast_cli(fd, format, "Username", "IP Address");
00234 while (s) {
00235 ast_cli(fd, format,s->username, ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
00236 s = s->next;
00237 }
00238
00239 ast_mutex_unlock(&sessionlock);
00240 return RESULT_SUCCESS;
00241 }
00242
00243 static char showmancmd_help[] =
00244 "Usage: show manager command <actionname>\n"
00245 " Shows the detailed description for a specific Asterisk manager interface command.\n";
00246
00247 static char showmancmds_help[] =
00248 "Usage: show manager commands\n"
00249 " Prints a listing of all the available Asterisk manager interface commands.\n";
00250
00251 static char showmanconn_help[] =
00252 "Usage: show manager connected\n"
00253 " Prints a listing of the users that are currently connected to the\n"
00254 "Asterisk manager interface.\n";
00255
00256 static struct ast_cli_entry show_mancmd_cli =
00257 { { "show", "manager", "command", NULL },
00258 handle_showmancmd, "Show a manager interface command", showmancmd_help, complete_show_mancmd };
00259
00260 static struct ast_cli_entry show_mancmds_cli =
00261 { { "show", "manager", "commands", NULL },
00262 handle_showmancmds, "List manager interface commands", showmancmds_help };
00263
00264 static struct ast_cli_entry show_manconn_cli =
00265 { { "show", "manager", "connected", NULL },
00266 handle_showmanconn, "Show connected manager interface users", showmanconn_help };
00267
00268 static void free_session(struct mansession *s)
00269 {
00270 struct eventqent *eqe;
00271 if (s->fd > -1)
00272 close(s->fd);
00273 ast_mutex_destroy(&s->__lock);
00274 while(s->eventq) {
00275 eqe = s->eventq;
00276 s->eventq = s->eventq->next;
00277 free(eqe);
00278 }
00279 free(s);
00280 }
00281
00282 static void destroy_session(struct mansession *s)
00283 {
00284 struct mansession *cur, *prev = NULL;
00285 ast_mutex_lock(&sessionlock);
00286 cur = sessions;
00287 while(cur) {
00288 if (cur == s)
00289 break;
00290 prev = cur;
00291 cur = cur->next;
00292 }
00293 if (cur) {
00294 if (prev)
00295 prev->next = cur->next;
00296 else
00297 sessions = cur->next;
00298 free_session(s);
00299 } else
00300 ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
00301 ast_mutex_unlock(&sessionlock);
00302
00303 }
00304
00305 char *astman_get_header(struct message *m, char *var)
00306 {
00307 char cmp[80];
00308 int x;
00309 snprintf(cmp, sizeof(cmp), "%s: ", var);
00310 for (x=0;x<m->hdrcount;x++)
00311 if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
00312 return m->headers[x] + strlen(cmp);
00313 return "";
00314 }
00315
00316 struct ast_variable *astman_get_variables(struct message *m)
00317 {
00318 int varlen, x, y;
00319 struct ast_variable *head = NULL, *cur;
00320 char *var, *val;
00321 unsigned int var_count;
00322 char *vars[32];
00323
00324 varlen = strlen("Variable: ");
00325
00326 for (x = 0; x < m->hdrcount; x++) {
00327 if (strncasecmp("Variable: ", m->headers[x], varlen))
00328 continue;
00329
00330 if (!(var = ast_strdupa(m->headers[x] + varlen)))
00331 return head;
00332
00333 if ((var_count = ast_app_separate_args(var, '|', vars, sizeof(vars) / sizeof(vars[0])))) {
00334 for (y = 0; y < var_count; y++) {
00335 if (!vars[y])
00336 continue;
00337 var = val = ast_strdupa(vars[y]);
00338 strsep(&val, "=");
00339 if (!val || ast_strlen_zero(var))
00340 continue;
00341 cur = ast_variable_new(var, val);
00342 if (head) {
00343 cur->next = head;
00344 head = cur;
00345 } else
00346 head = cur;
00347 }
00348 }
00349 }
00350
00351 return head;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 void astman_send_error(struct mansession *s, struct message *m, char *error)
00363 {
00364 char *id = astman_get_header(m,"ActionID");
00365
00366 ast_cli(s->fd, "Response: Error\r\n");
00367 if (!ast_strlen_zero(id))
00368 ast_cli(s->fd, "ActionID: %s\r\n",id);
00369 ast_cli(s->fd, "Message: %s\r\n\r\n", error);
00370 }
00371
00372 void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg)
00373 {
00374 char *id = astman_get_header(m,"ActionID");
00375
00376 ast_cli(s->fd, "Response: %s\r\n", resp);
00377 if (!ast_strlen_zero(id))
00378 ast_cli(s->fd, "ActionID: %s\r\n",id);
00379 if (msg)
00380 ast_cli(s->fd, "Message: %s\r\n\r\n", msg);
00381 else
00382 ast_cli(s->fd, "\r\n");
00383 }
00384
00385 void astman_send_ack(struct mansession *s, struct message *m, char *msg)
00386 {
00387 astman_send_response(s, m, "Success", msg);
00388 }
00389
00390
00391
00392
00393
00394
00395 static int ast_instring(char *bigstr, char *smallstr, char delim)
00396 {
00397 char *val = bigstr, *next;
00398
00399 do {
00400 if ((next = strchr(val, delim))) {
00401 if (!strncmp(val, smallstr, (next - val)))
00402 return 1;
00403 else
00404 continue;
00405 } else
00406 return !strcmp(smallstr, val);
00407
00408 } while (*(val = (next + 1)));
00409
00410 return 0;
00411 }
00412
00413 static int get_perm(char *instr)
00414 {
00415 int x = 0, ret = 0;
00416
00417 if (!instr)
00418 return 0;
00419
00420 for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++)
00421 if (ast_instring(instr, perms[x].label, ','))
00422 ret |= perms[x].num;
00423
00424 return ret;
00425 }
00426
00427 static int ast_is_number(char *string)
00428 {
00429 int ret = 1, x = 0;
00430
00431 if (!string)
00432 return 0;
00433
00434 for (x=0; x < strlen(string); x++) {
00435 if (!(string[x] >= 48 && string[x] <= 57)) {
00436 ret = 0;
00437 break;
00438 }
00439 }
00440
00441 return ret ? atoi(string) : 0;
00442 }
00443
00444 static int ast_strings_to_mask(char *string)
00445 {
00446 int x, ret = -1;
00447
00448 x = ast_is_number(string);
00449
00450 if (x) {
00451 ret = x;
00452 } else if (ast_strlen_zero(string)) {
00453 ret = -1;
00454 } else if (ast_false(string)) {
00455 ret = 0;
00456 } else if (ast_true(string)) {
00457 ret = 0;
00458 for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++)
00459 ret |= perms[x].num;
00460 } else {
00461 ret = 0;
00462 for (x=0; x<sizeof(perms) / sizeof(perms[0]); x++) {
00463 if (ast_instring(string, perms[x].label, ','))
00464 ret |= perms[x].num;
00465 }
00466 }
00467
00468 return ret;
00469 }
00470
00471
00472
00473
00474
00475
00476 static int set_eventmask(struct mansession *s, char *eventmask)
00477 {
00478 int maskint = ast_strings_to_mask(eventmask);
00479
00480 ast_mutex_lock(&s->__lock);
00481 if (maskint >= 0)
00482 s->send_events = maskint;
00483 ast_mutex_unlock(&s->__lock);
00484
00485 return maskint;
00486 }
00487
00488 static int authenticate(struct mansession *s, struct message *m)
00489 {
00490 struct ast_config *cfg;
00491 char iabuf[INET_ADDRSTRLEN];
00492 char *cat;
00493 char *user = astman_get_header(m, "Username");
00494 char *pass = astman_get_header(m, "Secret");
00495 char *authtype = astman_get_header(m, "AuthType");
00496 char *key = astman_get_header(m, "Key");
00497 char *events = astman_get_header(m, "Events");
00498
00499 cfg = ast_config_load("manager.conf");
00500 if (!cfg)
00501 return -1;
00502 cat = ast_category_browse(cfg, NULL);
00503 while(cat) {
00504 if (strcasecmp(cat, "general")) {
00505
00506 if (!strcasecmp(cat, user)) {
00507 struct ast_variable *v;
00508 struct ast_ha *ha = NULL;
00509 char *password = NULL;
00510 v = ast_variable_browse(cfg, cat);
00511 while (v) {
00512 if (!strcasecmp(v->name, "secret")) {
00513 password = v->value;
00514 } else if (!strcasecmp(v->name, "permit") ||
00515 !strcasecmp(v->name, "deny")) {
00516 ha = ast_append_ha(v->name, v->value, ha);
00517 } else if (!strcasecmp(v->name, "writetimeout")) {
00518 int val = atoi(v->value);
00519
00520 if (val < 100)
00521 ast_log(LOG_WARNING, "Invalid writetimeout value '%s' at line %d\n", v->value, v->lineno);
00522 else
00523 s->writetimeout = val;
00524 }
00525
00526 v = v->next;
00527 }
00528 if (ha && !ast_apply_ha(ha, &(s->sin))) {
00529 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), user);
00530 ast_free_ha(ha);
00531 ast_config_destroy(cfg);
00532 return -1;
00533 } else if (ha)
00534 ast_free_ha(ha);
00535 if (!strcasecmp(authtype, "MD5")) {
00536 if (!ast_strlen_zero(key) &&
00537 !ast_strlen_zero(s->challenge) && !ast_strlen_zero(password)) {
00538 int x;
00539 int len=0;
00540 char md5key[256] = "";
00541 struct MD5Context md5;
00542 unsigned char digest[16];
00543 MD5Init(&md5);
00544 MD5Update(&md5, (unsigned char *) s->challenge, strlen(s->challenge));
00545 MD5Update(&md5, (unsigned char *) password, strlen(password));
00546 MD5Final(digest, &md5);
00547 for (x=0;x<16;x++)
00548 len += sprintf(md5key + len, "%2.2x", digest[x]);
00549 if (!strcmp(md5key, key))
00550 break;
00551 else {
00552 ast_config_destroy(cfg);
00553 return -1;
00554 }
00555 }
00556 } else if (password && !strcasecmp(password, pass)) {
00557 break;
00558 } else {
00559 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), user);
00560 ast_config_destroy(cfg);
00561 return -1;
00562 }
00563 }
00564 }
00565 cat = ast_category_browse(cfg, cat);
00566 }
00567 if (cat) {
00568 ast_copy_string(s->username, cat, sizeof(s->username));
00569 s->readperm = get_perm(ast_variable_retrieve(cfg, cat, "read"));
00570 s->writeperm = get_perm(ast_variable_retrieve(cfg, cat, "write"));
00571 ast_config_destroy(cfg);
00572 if (events)
00573 set_eventmask(s, events);
00574 return 0;
00575 }
00576 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), user);
00577 ast_config_destroy(cfg);
00578 return -1;
00579 }
00580
00581
00582 static char mandescr_ping[] =
00583 "Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the "
00584 " manager connection open.\n"
00585 "Variables: NONE\n";
00586
00587 static int action_ping(struct mansession *s, struct message *m)
00588 {
00589 astman_send_response(s, m, "Pong", NULL);
00590 return 0;
00591 }
00592
00593 static char mandescr_listcommands[] =
00594 "Description: Returns the action name and synopsis for every\n"
00595 " action that is available to the user\n"
00596 "Variables: NONE\n";
00597
00598 static int action_listcommands(struct mansession *s, struct message *m)
00599 {
00600 struct manager_action *cur = first_action;
00601 char idText[256] = "";
00602 char temp[BUFSIZ];
00603 char *id = astman_get_header(m,"ActionID");
00604
00605 if (!ast_strlen_zero(id))
00606 snprintf(idText,256,"ActionID: %s\r\n",id);
00607 ast_cli(s->fd, "Response: Success\r\n%s", idText);
00608 ast_mutex_lock(&actionlock);
00609 while (cur) {
00610 if ((s->writeperm & cur->authority) == cur->authority)
00611 ast_cli(s->fd, "%s: %s (Priv: %s)\r\n", cur->action, cur->synopsis, authority_to_str(cur->authority, temp, sizeof(temp)) );
00612 cur = cur->next;
00613 }
00614 ast_mutex_unlock(&actionlock);
00615 ast_cli(s->fd, "\r\n");
00616
00617 return 0;
00618 }
00619
00620 static char mandescr_events[] =
00621 "Description: Enable/Disable sending of events to this manager\n"
00622 " client.\n"
00623 "Variables:\n"
00624 " EventMask: 'on' if all events should be sent,\n"
00625 " 'off' if no events should be sent,\n"
00626 " 'system,call,log' to select which flags events should have to be sent.\n";
00627
00628 static int action_events(struct mansession *s, struct message *m)
00629 {
00630 char *mask = astman_get_header(m, "EventMask");
00631 int res;
00632
00633 res = set_eventmask(s, mask);
00634 if (res > 0)
00635 astman_send_response(s, m, "Events On", NULL);
00636 else if (res == 0)
00637 astman_send_response(s, m, "Events Off", NULL);
00638
00639 return 0;
00640 }
00641
00642 static char mandescr_logoff[] =
00643 "Description: Logoff this manager session\n"
00644 "Variables: NONE\n";
00645
00646 static int action_logoff(struct mansession *s, struct message *m)
00647 {
00648 astman_send_response(s, m, "Goodbye", "Thanks for all the fish.");
00649 return -1;
00650 }
00651
00652 static char mandescr_hangup[] =
00653 "Description: Hangup a channel\n"
00654 "Variables: \n"
00655 " Channel: The channel name to be hungup\n";
00656
00657 static int action_hangup(struct mansession *s, struct message *m)
00658 {
00659 struct ast_channel *c = NULL;
00660 char *name = astman_get_header(m, "Channel");
00661 if (ast_strlen_zero(name)) {
00662 astman_send_error(s, m, "No channel specified");
00663 return 0;
00664 }
00665 c = ast_get_channel_by_name_locked(name);
00666 if (!c) {
00667 astman_send_error(s, m, "No such channel");
00668 return 0;
00669 }
00670 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
00671 ast_mutex_unlock(&c->lock);
00672 astman_send_ack(s, m, "Channel Hungup");
00673 return 0;
00674 }
00675
00676 static char mandescr_setvar[] =
00677 "Description: Set a global or local channel variable.\n"
00678 "Variables: (Names marked with * are required)\n"
00679 " Channel: Channel to set variable for\n"
00680 " *Variable: Variable name\n"
00681 " *Value: Value\n";
00682
00683 static int action_setvar(struct mansession *s, struct message *m)
00684 {
00685 struct ast_channel *c = NULL;
00686 char *name = astman_get_header(m, "Channel");
00687 char *varname = astman_get_header(m, "Variable");
00688 char *varval = astman_get_header(m, "Value");
00689
00690 if (ast_strlen_zero(varname)) {
00691 astman_send_error(s, m, "No variable specified");
00692 return 0;
00693 }
00694
00695 if (!ast_strlen_zero(name)) {
00696 c = ast_get_channel_by_name_locked(name);
00697 if (!c) {
00698 astman_send_error(s, m, "No such channel");
00699 return 0;
00700 }
00701 }
00702
00703 pbx_builtin_setvar_helper(c, varname, varval ? varval : "");
00704
00705 if (c)
00706 ast_mutex_unlock(&c->lock);
00707
00708 astman_send_ack(s, m, "Variable Set");
00709
00710 return 0;
00711 }
00712
00713 static char mandescr_getvar[] =
00714 "Description: Get the value of a global or local channel variable.\n"
00715 "Variables: (Names marked with * are required)\n"
00716 " Channel: Channel to read variable from\n"
00717 " *Variable: Variable name\n"
00718 " ActionID: Optional Action id for message matching.\n";
00719
00720 static int action_getvar(struct mansession *s, struct message *m)
00721 {
00722 struct ast_channel *c = NULL;
00723 char *name = astman_get_header(m, "Channel");
00724 char *varname = astman_get_header(m, "Variable");
00725 char *id = astman_get_header(m,"ActionID");
00726 char *varval;
00727 char *varval2=NULL;
00728
00729 if (!strlen(varname)) {
00730 astman_send_error(s, m, "No variable specified");
00731 return 0;
00732 }
00733
00734 if (strlen(name)) {
00735 c = ast_get_channel_by_name_locked(name);
00736 if (!c) {
00737 astman_send_error(s, m, "No such channel");
00738 return 0;
00739 }
00740 }
00741
00742 varval=pbx_builtin_getvar_helper(c,varname);
00743 if (varval)
00744 varval2 = ast_strdupa(varval);
00745 if (!varval2)
00746 varval2 = "";
00747 if (c)
00748 ast_mutex_unlock(&c->lock);
00749 ast_cli(s->fd, "Response: Success\r\n"
00750 "Variable: %s\r\nValue: %s\r\n" ,varname,varval2);
00751 if (!ast_strlen_zero(id))
00752 ast_cli(s->fd, "ActionID: %s\r\n",id);
00753 ast_cli(s->fd, "\r\n");
00754
00755 return 0;
00756 }
00757
00758
00759
00760
00761 static int action_status(struct mansession *s, struct message *m)
00762 {
00763 char *id = astman_get_header(m,"ActionID");
00764 char *name = astman_get_header(m,"Channel");
00765 char idText[256] = "";
00766 struct ast_channel *c;
00767 char bridge[256];
00768 struct timeval now = ast_tvnow();
00769 long elapsed_seconds=0;
00770 int all = ast_strlen_zero(name);
00771
00772 if (!ast_strlen_zero(id))
00773 snprintf(idText,256,"ActionID: %s\r\n",id);
00774 if (all)
00775 c = ast_channel_walk_locked(NULL);
00776 else {
00777 c = ast_get_channel_by_name_locked(name);
00778 if (!c) {
00779 astman_send_error(s, m, "No such channel");
00780 return 0;
00781 }
00782 }
00783 astman_send_ack(s, m, "Channel status will follow");
00784
00785 while(c) {
00786 if (c->_bridge)
00787 snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->_bridge->name);
00788 else
00789 bridge[0] = '\0';
00790 if (c->pbx) {
00791 if (c->cdr) {
00792 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
00793 }
00794 ast_cli(s->fd,
00795 "Event: Status\r\n"
00796 "Privilege: Call\r\n"
00797 "Channel: %s\r\n"
00798 "CallerID: %s\r\n"
00799 "CallerIDName: %s\r\n"
00800 "Account: %s\r\n"
00801 "State: %s\r\n"
00802 "Context: %s\r\n"
00803 "Extension: %s\r\n"
00804 "Priority: %d\r\n"
00805 "Seconds: %ld\r\n"
00806 "%s"
00807 "Uniqueid: %s\r\n"
00808 "%s"
00809 "\r\n",
00810 c->name,
00811 c->cid.cid_num ? c->cid.cid_num : "<unknown>",
00812 c->cid.cid_name ? c->cid.cid_name : "<unknown>",
00813 c->accountcode,
00814 ast_state2str(c->_state), c->context,
00815 c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, idText);
00816 } else {
00817 ast_cli(s->fd,
00818 "Event: Status\r\n"
00819 "Privilege: Call\r\n"
00820 "Channel: %s\r\n"
00821 "CallerID: %s\r\n"
00822 "CallerIDName: %s\r\n"
00823 "Account: %s\r\n"
00824 "State: %s\r\n"
00825 "%s"
00826 "Uniqueid: %s\r\n"
00827 "%s"
00828 "\r\n",
00829 c->name,
00830 c->cid.cid_num ? c->cid.cid_num : "<unknown>",
00831 c->cid.cid_name ? c->cid.cid_name : "<unknown>",
00832 c->accountcode,
00833 ast_state2str(c->_state), bridge, c->uniqueid, idText);
00834 }
00835 ast_mutex_unlock(&c->lock);
00836 if (!all)
00837 break;
00838 c = ast_channel_walk_locked(c);
00839 }
00840 ast_cli(s->fd,
00841 "Event: StatusComplete\r\n"
00842 "%s"
00843 "\r\n",idText);
00844 return 0;
00845 }
00846
00847 static char mandescr_redirect[] =
00848 "Description: Redirect (transfer) a call.\n"
00849 "Variables: (Names marked with * are required)\n"
00850 " *Channel: Channel to redirect\n"
00851 " ExtraChannel: Second call leg to transfer (optional)\n"
00852 " *Exten: Extension to transfer to\n"
00853 " *Context: Context to transfer to\n"
00854 " *Priority: Priority to transfer to\n"
00855 " ActionID: Optional Action id for message matching.\n";
00856
00857
00858 static int action_redirect(struct mansession *s, struct message *m)
00859 {
00860 char *name = astman_get_header(m, "Channel");
00861 char *name2 = astman_get_header(m, "ExtraChannel");
00862 char *exten = astman_get_header(m, "Exten");
00863 char *context = astman_get_header(m, "Context");
00864 char *priority = astman_get_header(m, "Priority");
00865 struct ast_channel *chan, *chan2 = NULL;
00866 int pi = 0;
00867 int res;
00868
00869 if (ast_strlen_zero(name)) {
00870 astman_send_error(s, m, "Channel not specified");
00871 return 0;
00872 }
00873 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) {
00874 astman_send_error(s, m, "Invalid priority\n");
00875 return 0;
00876 }
00877 chan = ast_get_channel_by_name_locked(name);
00878 if (!chan) {
00879 char buf[BUFSIZ];
00880 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name);
00881 astman_send_error(s, m, buf);
00882 return 0;
00883 }
00884 if (ast_check_hangup(chan)) {
00885 astman_send_error(s, m, "Redirect failed, channel hung up.\n");
00886 ast_mutex_unlock(&chan->lock);
00887 return 0;
00888 }
00889 if (!ast_strlen_zero(name2))
00890 chan2 = ast_get_channel_by_name_locked(name2);
00891 if (chan2 && ast_check_hangup(chan2)) {
00892 astman_send_error(s, m, "Redirect failed, extra channel hung up.\n");
00893 ast_mutex_unlock(&chan->lock);
00894 ast_mutex_unlock(&chan2->lock);
00895 return 0;
00896 }
00897 res = ast_async_goto(chan, context, exten, pi);
00898 if (!res) {
00899 if (!ast_strlen_zero(name2)) {
00900 if (chan2)
00901 res = ast_async_goto(chan2, context, exten, pi);
00902 else
00903 res = -1;
00904 if (!res)
00905 astman_send_ack(s, m, "Dual Redirect successful");
00906 else
00907 astman_send_error(s, m, "Secondary redirect failed");
00908 } else
00909 astman_send_ack(s, m, "Redirect successful");
00910 } else
00911 astman_send_error(s, m, "Redirect failed");
00912 if (chan)
00913 ast_mutex_unlock(&chan->lock);
00914 if (chan2)
00915 ast_mutex_unlock(&chan2->lock);
00916 return 0;
00917 }
00918
00919 static char mandescr_command[] =
00920 "Description: Run a CLI command.\n"
00921 "Variables: (Names marked with * are required)\n"
00922 " *Command: Asterisk CLI command to run\n"
00923 " ActionID: Optional Action id for message matching.\n";
00924
00925