62 #include <sys/types.h>
1490 #define DEFAULT_REALM "asterisk"
1508 #ifdef TEST_FRAMEWORK
1513 #define MGR_SHOW_TERMINAL_WIDTH 80
1515 #define MAX_VARS 128
1518 #define EVENT_FLAG_SHUTDOWN -1
1530 #define MAX_BLACKLIST_CMD_LEN 2
1531 static const struct {
1534 {{
"module",
"load",
NULL }},
1535 {{
"module",
"unload",
NULL }},
1536 {{
"restart",
"gracefully",
NULL }},
1718 ao2_t_ref(act, +1,
"found action object");
1763 size_t index,
struct ast_str **res,
1773 const char *parent_key,
struct ast_str **res,
1778 ast_str_set(&key_str, 0,
"%s/%s", parent_key, key);
1801 if (exclusion_cb && key && exclusion_cb(key)) {
1815 key, j, res, exclusion_cb);
1824 key, res, exclusion_cb);
1839 #define manager_event_sessions(sessions, category, event, contents , ...) \
1840 __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__)
1842 #define any_manager_listeners(sessions) \
1843 ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks))
1899 if (!event_buffer) {
1923 "class_type", class_type,
2050 #define MAX_AUTH_PERM_STRING 150
2057 strstr(evaluating,
"SHELL") ||
2058 strstr(evaluating,
"EVAL")
2099 if (authority &
perms[i].num) {
2119 static int ast_instring(
const char *bigstr,
const char *smallstr,
const char delim)
2121 const char *
val = bigstr, *next;
2124 if ((next = strchr(
val, delim))) {
2125 if (!strncmp(
val, smallstr, (next -
val))) {
2131 return !strcmp(smallstr,
val);
2133 }
while (*(
val = (next + 1)));
2167 for (p =
string; *p; p++) {
2168 if (*p < '0' || *p >
'9') {
2173 return atoi(
string);
2192 int refcount =
ao2_ref(s, -1);
2194 ast_debug(1,
"Mansession: %p refcount now %d\n", s, refcount - 1);
2201 regex_t *regex_filter = obj;
2202 regfree(regex_filter);
2225 ao2_t_ref(
session->whitefilters, -1,
"decrement ref for white container, should be last one");
2229 ao2_t_ref(
session->blackfilters, -1,
"decrement ref for black container, should be last one");
2317 if (!strcasecmp(
user->username,
name)) {
2336 ret =
user->displayconnects;
2353 const char *auth_str;
2355 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
2356 char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
2361 e->
command =
"manager show command";
2363 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
2364 " Shows the detailed description for a specific Asterisk manager interface command.\n";
2367 l = strlen(
a->word);
2370 if (!strncasecmp(
a->word, cur->
action, l)) {
2399 for (num = 3; num <
a->argc; num++) {
2400 if (!strcasecmp(cur->
action,
a->argv[num])) {
2413 if (!syntax || !
synopsis || !description || !arguments
2414 || !seealso || !privilege || !responses) {
2422 ast_cli(
a->fd,
"Allocation failure.\n");
2428 ast_cli(
a->fd,
"%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s",
2429 syntax_title, syntax,
2431 description_title, description,
2432 arguments_title, arguments,
2433 seealso_title, seealso,
2434 privilege_title, privilege,
2435 list_responses_title);
2438 ast_cli(
a->fd,
"%s\n\n", responses);
2447 ast_cli(
a->fd,
"%s", final_response_title);
2450 ast_cli(
a->fd,
"%s\n\n", responses);
2466 ast_cli(
a->fd,
"Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
2483 e->
command =
"manager set debug [on|off]";
2484 e->
usage =
"Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
2492 }
else if (
a->argc == 4) {
2493 if (!strcasecmp(
a->argv[3],
"on")) {
2495 }
else if (!strcasecmp(
a->argv[3],
"off")) {
2514 e->
command =
"manager show user";
2516 " Usage: manager show user <user>\n"
2517 " Display all information related to the manager user specified.\n";
2520 l = strlen(
a->word);
2526 if (!strncasecmp(
a->word,
user->username, l)) {
2543 ast_cli(
a->fd,
"There is no manager called %s\n",
a->argv[3]);
2555 " displayconnects: %s\n"
2556 "allowmultiplelogin: %s\n",
2558 (
user->secret ?
"<Set>" :
"(N/A)"),
2562 (
user->displayconnects ?
"yes" :
"no"),
2563 (
user->allowmultiplelogin ?
"yes" :
"no"));
2565 for (v =
user->chanvars ; v ; v = v->
next) {
2583 e->
command =
"manager show users";
2585 "Usage: manager show users\n"
2586 " Prints a listing of all managers that are currently configured on that\n"
2600 ast_cli(
a->fd,
"There are no manager users.\n");
2605 ast_cli(
a->fd,
"\nusername\n--------\n");
2614 ast_cli(
a->fd,
"-------------------\n"
2615 "%d manager users configured.\n", count_amu);
2624 int space_remaining;
2625 #define HSMC_FORMAT " %-*.*s %-.*s\n"
2628 e->
command =
"manager show commands";
2630 "Usage: manager show commands\n"
2631 " Prints a listing of all the available Asterisk manager interface commands.\n";
2639 int incoming_len = strlen(cur->
action);
2640 if (incoming_len > name_len) {
2641 name_len = incoming_len;
2646 if (space_remaining < 0) {
2647 space_remaining = 0;
2666 time_t now = time(
NULL);
2667 #define HSMCONN_FORMAT1 " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
2668 #define HSMCONN_FORMAT2 " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
2674 e->
command =
"manager show connected";
2676 "Usage: manager show connected\n"
2677 " Prints a listing of the users that are currently connected to the\n"
2678 "Asterisk manager interface.\n";
2684 ast_cli(
a->fd,
HSMCONN_FORMAT1,
"Username",
"IP Address",
"Start",
"Elapsed",
"FileDes",
"HttpCnt",
"Read",
"Write");
2694 (
int) (
session->sessionstart),
2695 (
int) (now -
session->sessionstart),
2706 ast_cli(
a->fd,
"%d users connected.\n", count);
2718 e->
command =
"manager show eventq";
2720 "Usage: manager show eventq\n"
2721 " Prints a listing of all events pending in the Asterisk manger\n"
2731 ast_cli(
a->fd,
"Event:\n%s", s->eventdata);
2745 e->
command =
"manager reload";
2747 "Usage: manager reload\n"
2748 " Reloads the manager configuration.\n";
2773 #define GET_HEADER_FIRST_MATCH 0
2774 #define GET_HEADER_LAST_MATCH 1
2775 #define GET_HEADER_SKIP_EMPTY 2
2792 int x, l = strlen(
var);
2799 for (x = 0; x < m->
hdrcount; x++) {
2800 const char *h = m->
headers[x];
2801 if (!strncasecmp(
var, h, l) && h[l] ==
':') {
2802 const char *
value = h + l + 1;
2885 for (y = 0; y <
args.argc; y++) {
2890 if (!
args.vars[y]) {
2925 static const char var_hdr[] =
"Variable:";
2928 varlen = strlen(var_hdr);
2929 for (x = 0; x < m->
hdrcount; x++) {
2930 if (strncasecmp(var_hdr, m->
headers[x], varlen)) {
2967 curlen = strlen(src);
2968 for (x = 0; x < curlen; x++) {
2970 if (src[x] ==
'\r' && x+1 < curlen && src[x+1] ==
'\n')
2972 else if (src[x] ==
'\n')
2991 if (!strcasecmp(action,
"login")) {
3014 if (!act_found->
module || mod_ref) {
3015 ret = act_found->
func(&s, &m);
3021 ao2_t_ref(act_found, -1,
"done with found action object");
3049 len = strlen(
string);
3073 #define ASTMAN_APPEND_BUF_INITSIZE 256
3080 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3107 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3121 #define MSG_MOREDATA ((char *)astman_send_response)
3228 "EventList: Complete\r\n"
3229 "ListItems: %d\r\n",
3294 char session_id[32];
3298 .common.service =
"AMI",
3299 .common.account_id = username,
3301 .common.local_addr = {
3305 .common.remote_addr = {
3309 .common.session_id = session_id,
3312 snprintf(session_id,
sizeof(session_id),
"%p", s);
3319 char session_id[32];
3323 .common.service =
"AMI",
3324 .common.account_id = username,
3326 .common.local_addr = {
3330 .common.remote_addr = {
3334 .common.session_id = session_id,
3337 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3344 char session_id[32];
3348 .common.service =
"AMI",
3349 .common.account_id = username,
3351 .common.local_addr = {
3355 .common.remote_addr = {
3359 .common.session_id = session_id,
3362 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3369 char session_id[32];
3373 .common.service =
"AMI",
3376 .common.local_addr = {
3380 .common.remote_addr = {
3384 .common.session_id = session_id,
3387 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3394 char session_id[32];
3395 char request_type[64];
3399 .common.service =
"AMI",
3402 .common.local_addr = {
3406 .common.remote_addr = {
3410 .common.session_id = session_id,
3415 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3423 char session_id[32];
3428 .common.service =
"AMI",
3431 .common.local_addr = {
3435 .common.remote_addr = {
3439 .common.session_id = session_id,
3444 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3451 const char *response,
const char *expected_response)
3453 char session_id[32];
3457 .common.service =
"AMI",
3460 .common.local_addr = {
3464 .common.remote_addr = {
3468 .common.session_id = session_id,
3475 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3482 char session_id[32];
3486 .common.service =
"AMI",
3489 .common.local_addr = {
3493 .common.remote_addr = {
3497 .common.session_id = session_id,
3500 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
3518 regex_t *regex_filter;
3539 char md5key[256] =
"";
3541 unsigned char digest[16];
3547 for (x = 0; x < 16; x++)
3548 len += sprintf(md5key +
len,
"%02hhx", digest[x]);
3549 if (!strcmp(md5key, key)) {
3555 ast_debug(1,
"MD5 authentication is not possible. challenge: '%s'\n",
3558 }
else if (
user->secret) {
3559 if (!strcmp(password,
user->secret)) {
3581 if (
user->chanvars) {
3588 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3595 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3621 "Timestamp: %ld.%06lu\r\n"
3623 (
long) now.tv_sec, (
unsigned long) now.tv_usec);
3633 const char *category_name;
3660 astman_append(s,
"Category-%06d: %s\r\n", catcount, category_name);
3717 if (catcount == 0) {
3731 if (*
in ==
'\\' || *
in ==
'\"') {
3762 const char *category_name;
3833 for (x = 0; x < 100000; x++) {
3834 unsigned int object = 0;
3838 int ignoreerror = 0;
3846 snprintf(hdr,
sizeof(hdr),
"Action-%06d", x);
3851 snprintf(hdr,
sizeof(hdr),
"Cat-%06d", x);
3858 snprintf(hdr,
sizeof(hdr),
"Var-%06d", x);
3861 snprintf(hdr,
sizeof(hdr),
"Value-%06d", x);
3869 snprintf(hdr,
sizeof(hdr),
"Match-%06d", x);
3872 snprintf(hdr,
sizeof(hdr),
"Line-%06d", x);
3875 snprintf(hdr,
sizeof(hdr),
"Options-%06d", x);
3882 if (!strcasecmp(
"allowdups", token)) {
3886 if (!strcasecmp(
"template", token)) {
3890 if (!strcasecmp(
"ignoreerror", token)) {
3913 if (!strcasecmp(action,
"newcat")) {
3915 char *tmpl_name =
NULL;
3955 if (category !=
NULL) {
3966 }
else if (!strcasecmp(action,
"renamecat")) {
3982 }
else if (!strcasecmp(action,
"delcat")) {
3989 if (!foundcat && !ignoreerror) {
3993 }
else if (!strcasecmp(action,
"emptycat")) {
4004 }
else if (!strcasecmp(action,
"update")) {
4028 }
else if (!strcasecmp(action,
"delete")) {
4048 if (!foundvar && !ignoreerror) {
4052 }
else if (!strcasecmp(action,
"append")) {
4064 if (
object || (
match && !strcasecmp(
match,
"object"))) {
4075 }
else if (!strcasecmp(action,
"insert")) {
4115 const char *preserve_effective_context_string =
astman_get_header(m,
"PreserveEffectiveContext");
4221 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4227 sscanf(timeouts,
"%30i", &timeout);
4248 time_t now = time(
NULL);
4254 if (timeout < 0 || timeout >
max) {
4266 ast_debug(1,
"Starting waiting for an event!\n");
4268 for (x = 0; x < timeout || timeout < 0; x++) {
4297 ast_debug(1,
"Finished waiting for an event!\n");
4317 "Event: WaitEventComplete\r\n"
4323 ast_debug(1,
"Abandoning event request!\n");
4356 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
4368 if (!strcasecmp(
perms[x].label,
"all") && res ==
perms[x].
num) {
4373 "Events: On\r\n\r\n", id_text);
4374 }
else if (res == 0)
4376 "Events: Off\r\n\r\n", id_text);
4382 "Events: On\r\n\r\n", id_text);
4385 "Events: Off\r\n\r\n", id_text);
4424 long lastreloaded = 0;
4430 uptime =
tmp.tv_sec;
4435 lastreloaded =
tmp.tv_sec;
4441 "LastReload: %ld\r\n"
4442 "Status: Fully Booted\r\n\r\n", cat_str, uptime, lastreloaded);
4451 if (!strcasecmp(authtype,
"MD5")) {
4476 int channels_matched = 0;
4484 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4491 causecode = strtol(cause, &endptr, 10);
4492 if (causecode < 0 || causecode > 127 || *endptr !=
'\0') {
4502 if (name_or_regex[0] !=
'/') {
4510 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4528 if (!regex_string) {
4535 astman_send_error(s, m,
"Regex format invalid, Channel param should be /regex/");
4541 if (regcomp(®exbuf,
ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
4556 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4566 "Event: ChannelHungup\r\n"
4621 char workspace[1024];
4641 workspace[0] =
'\0';
4642 if (varname[strlen(varname) - 1] ==
')') {
4646 ast_func_read(
c, (
char *) varname, workspace,
sizeof(workspace));
4648 ast_log(
LOG_ERROR,
"Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
4650 ast_func_read(
c, (
char *) varname, workspace,
sizeof(workspace));
4662 astman_append(s,
"Variable: %s\r\nValue: %s\r\n\r\n", varname,
S_OR(varval,
""));
4670 long elapsed_seconds;
4688 if (!snapshot_str) {
4692 if (all_variables) {
4697 if (!variable_str) {
4706 for (i = 0; i < varc; i++) {
4707 char valbuf[512], *ret =
NULL;
4709 if (vars[i][strlen(vars[i]) - 1] ==
')') {
4710 if (
ast_func_read(chan, vars[i], valbuf,
sizeof(valbuf)) < 0) {
4718 ast_str_append(&variable_str, 0,
"Variable: %s=%s\r\n", vars[i], ret);
4722 if (all_variables) {
4736 "Privilege: Call\r\n"
4740 "EffectiveConnectedLineNum: %s\r\n"
4741 "EffectiveConnectedLineName: %s\r\n"
4742 "TimeToHangup: %ld\r\n"
4744 "Application: %s\r\n"
4746 "Nativeformats: %s\r\n"
4747 "Readformat: %s\r\n"
4749 "Writeformat: %s\r\n"
4750 "Writetrans: %s\r\n"
4751 "Callgroup: %llu\r\n"
4752 "Pickupgroup: %llu\r\n"
4773 (
long)elapsed_seconds,
4787 int all_variables = 0;
4800 all_variables =
ast_true(all_chan_variables);
4825 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
4877 obj_size = payload_size +
sizeof(*obj);
4886 memcpy(obj->
payload, payload, payload_size);
4920 const char *content_type)
5017 if (sscanf(
priority,
"%30d", &pi) != 1) {
5035 if (sscanf(priority2,
"%30d", &pi2) != 1) {
5046 snprintf(
buf,
sizeof(
buf),
"Channel does not exist: %s",
name);
5070 snprintf(
buf,
sizeof(
buf),
"ExtraChannel does not exist: %s", name2);