178#define DEFAULT_REALM "asterisk"
206#define MGR_SHOW_TERMINAL_WIDTH 80
211#define EVENT_FLAG_SHUTDOWN -1
223#define MAX_BLACKLIST_CMD_LEN 2
227 {{
"module",
"load",
NULL }},
228 {{
"module",
"unload",
NULL }},
229 {{
"restart",
"gracefully",
NULL }},
417 const char *filter_pattern,
struct ao2_container *includefilters,
444 ao2_t_ref(act, +1,
"found action object");
489 size_t index,
struct ast_str **res,
499 const char *parent_key,
struct ast_str **res,
504 ast_str_set(&key_str, 0,
"%s/%s", parent_key, key);
527 if (exclusion_cb && key && exclusion_cb(key)) {
541 key, j, res, exclusion_cb);
550 key, res, exclusion_cb);
565#define manager_event_sessions(sessions, category, event, contents , ...) \
566 __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__)
568#define any_manager_listeners(sessions) \
569 ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks))
650 "class_type", class_type,
777#define MAX_AUTH_PERM_STRING 150
784 strstr(evaluating,
"SHELL") ||
785 strstr(evaluating,
"EVAL")
826 if (authority &
perms[i].num) {
846static int ast_instring(
const char *bigstr,
const char *smallstr,
const char delim)
848 const char *
val = bigstr, *next;
851 if ((next = strchr(
val, delim))) {
852 if (!strncmp(
val, smallstr, (next -
val))) {
858 return !strcmp(smallstr,
val);
860 }
while (*(
val = (next + 1)));
894 for (p =
string; *p; p++) {
895 if (*p < '0' || *p >
'9') {
921 ast_debug(1,
"Mansession: %p refcount now %d\n", s, refcount - 1);
929 if (
entry->regex_filter) {
930 regfree(
entry->regex_filter);
958 ao2_t_ref(
session->includefilters, -1,
"decrement ref for include container, should be last one");
962 ao2_t_ref(
session->excludefilters, -1,
"decrement ref for exclude container, should be last one");
1050 if (!strcasecmp(
user->username,
name)) {
1069 ret =
user->displayconnects;
1086 const char *auth_str;
1088 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
1089 char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
1094 e->
command =
"manager show command";
1096 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
1097 " Shows the detailed description for a specific Asterisk manager interface command.\n";
1100 l = strlen(
a->word);
1103 if (!strncasecmp(
a->word, cur->
action, l)) {
1132 for (num = 3; num <
a->argc; num++) {
1133 if (!strcasecmp(cur->
action,
a->argv[num])) {
1146 if (!syntax || !
synopsis || !description || !arguments
1147 || !seealso || !privilege || !responses) {
1155 ast_cli(
a->fd,
"Allocation failure.\n");
1161 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",
1162 syntax_title, syntax,
1164 description_title, description,
1165 arguments_title, arguments,
1166 seealso_title, seealso,
1167 privilege_title, privilege,
1168 list_responses_title);
1171 ast_cli(
a->fd,
"%s\n\n", responses);
1180 ast_cli(
a->fd,
"%s", final_response_title);
1183 ast_cli(
a->fd,
"%s\n\n", responses);
1199 ast_cli(
a->fd,
"Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
1216 e->
command =
"manager set debug [on|off]";
1217 e->
usage =
"Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
1225 }
else if (
a->argc == 4) {
1226 if (!strcasecmp(
a->argv[3],
"on")) {
1228 }
else if (!strcasecmp(
a->argv[3],
"off")) {
1247 e->
command =
"manager show user";
1249 " Usage: manager show user <user>\n"
1250 " Display all information related to the manager user specified.\n";
1253 l = strlen(
a->word);
1259 if (!strncasecmp(
a->word,
user->username, l)) {
1276 ast_cli(
a->fd,
"There is no manager called %s\n",
a->argv[3]);
1288 " displayconnects: %s\n"
1289 "allowmultiplelogin: %s\n",
1291 (
user->secret ?
"<Set>" :
"(N/A)"),
1295 (
user->displayconnects ?
"yes" :
"no"),
1296 (
user->allowmultiplelogin ?
"yes" :
"no"));
1298 for (v =
user->chanvars ; v ; v = v->
next) {
1316 e->
command =
"manager show users";
1318 "Usage: manager show users\n"
1319 " Prints a listing of all managers that are currently configured on that\n"
1333 ast_cli(
a->fd,
"There are no manager users.\n");
1338 ast_cli(
a->fd,
"\nusername\n--------\n");
1347 ast_cli(
a->fd,
"-------------------\n"
1348 "%d manager users configured.\n", count_amu);
1357 int space_remaining;
1358#define HSMC_FORMAT " %-*.*s %-.*s\n"
1361 e->
command =
"manager show commands";
1363 "Usage: manager show commands\n"
1364 " Prints a listing of all the available Asterisk manager interface commands.\n";
1372 int incoming_len = strlen(cur->
action);
1373 if (incoming_len > name_len) {
1374 name_len = incoming_len;
1379 if (space_remaining < 0) {
1380 space_remaining = 0;
1405 e->
command =
"manager kick session";
1407 "Usage: manager kick session <file descriptor>\n"
1408 " Kick an active Asterisk Manager Interface session\n";
1418 fd = atoi(
a->argv[3]);
1420 ast_cli(
a->fd,
"Invalid AMI file descriptor: %s\n",
a->argv[3]);
1433 ast_cli(
a->fd,
"Manager session using file descriptor %d has already been kicked\n", fd);
1440 ast_cli(
a->fd,
"Kicking manager session connected using file descriptor %d\n", fd);
1444 pthread_kill(
session->waiting_thread, SIGURG);
1459 ast_cli(
a->fd,
"No manager session found using file descriptor %d\n", fd);
1469 time_t now = time(
NULL);
1470#define HSMCONN_FORMAT1 " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-10.10s %-10.10s\n"
1471#define HSMCONN_FORMAT2 " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-10.10d %-10.10d\n"
1477 e->
command =
"manager show connected";
1479 "Usage: manager show connected\n"
1480 " Prints a listing of the users that are currently connected to the\n"
1481 "Asterisk manager interface.\n";
1487 ast_cli(
a->fd,
HSMCONN_FORMAT1,
"Username",
"IP Address",
"Start",
"Elapsed",
"FileDes",
"HttpCnt",
"ReadPerms",
"WritePerms");
1497 (
int) (
session->sessionstart),
1498 (
int) (now -
session->sessionstart),
1509 ast_cli(
a->fd,
"%d users connected.\n", count);
1521 e->
command =
"manager show eventq";
1523 "Usage: manager show eventq\n"
1524 " Prints a listing of all events pending in the Asterisk manger\n"
1534 ast_cli(
a->fd,
"Event:\n%s", s->eventdata);
1548 e->
command =
"manager reload";
1550 "Usage: manager reload\n"
1551 " Reloads the manager configuration.\n";
1576#define GET_HEADER_FIRST_MATCH 0
1577#define GET_HEADER_LAST_MATCH 1
1578#define GET_HEADER_SKIP_EMPTY 2
1595 int x, l = strlen(
var);
1602 for (x = 0; x < m->
hdrcount; x++) {
1603 const char *h = m->
headers[x];
1604 if (!strncasecmp(
var, h, l) && h[l] ==
':') {
1605 const char *
value = h + l + 1;
1688 for (y = 0; y <
args.argc; y++) {
1693 if (!
args.vars[y]) {
1728 static const char var_hdr[] =
"Variable:";
1731 varlen = strlen(var_hdr);
1732 for (x = 0; x < m->
hdrcount; x++) {
1733 if (strncasecmp(var_hdr, m->
headers[x], varlen)) {
1770 curlen = strlen(src);
1771 for (x = 0; x < curlen; x++) {
1773 if (src[x] ==
'\r' && x+1 < curlen && src[x+1] ==
'\n')
1775 else if (src[x] ==
'\n')
1794 if (!strcasecmp(action,
"login")) {
1817 if (!act_found->
module || mod_ref) {
1818 ret = act_found->
func(&s, &m);
1824 ao2_t_ref(act_found, -1,
"done with found action object");
1852 len = strlen(
string);
1876#define ASTMAN_APPEND_BUF_INITSIZE 256
1883 ast_verbose(
"No connection stream in astman_append, should not happen\n");
1910 ast_verbose(
"No connection stream in astman_append, should not happen\n");
1924#define MSG_MOREDATA ((char *)astman_send_response)
2031 "EventList: Complete\r\n"
2032 "ListItems: %d\r\n",
2097 char session_id[32];
2101 .common.service =
"AMI",
2102 .common.account_id = username,
2104 .common.local_addr = {
2108 .common.remote_addr = {
2112 .common.session_id = session_id,
2115 snprintf(session_id,
sizeof(session_id),
"%p", s);
2122 char session_id[32];
2126 .common.service =
"AMI",
2127 .common.account_id = username,
2129 .common.local_addr = {
2133 .common.remote_addr = {
2137 .common.session_id = session_id,
2140 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2147 char session_id[32];
2151 .common.service =
"AMI",
2152 .common.account_id = username,
2154 .common.local_addr = {
2158 .common.remote_addr = {
2162 .common.session_id = session_id,
2165 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2172 char session_id[32];
2176 .common.service =
"AMI",
2179 .common.local_addr = {
2183 .common.remote_addr = {
2187 .common.session_id = session_id,
2190 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2197 char session_id[32];
2198 char request_type[64];
2202 .common.service =
"AMI",
2205 .common.local_addr = {
2209 .common.remote_addr = {
2213 .common.session_id = session_id,
2218 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2226 char session_id[32];
2231 .common.service =
"AMI",
2234 .common.local_addr = {
2238 .common.remote_addr = {
2242 .common.session_id = session_id,
2247 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2254 const char *response,
const char *expected_response)
2256 char session_id[32];
2260 .common.service =
"AMI",
2263 .common.local_addr = {
2267 .common.remote_addr = {
2271 .common.session_id = session_id,
2278 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2285 char session_id[32];
2289 .common.service =
"AMI",
2292 .common.local_addr = {
2296 .common.remote_addr = {
2300 .common.session_id = session_id,
2303 snprintf(session_id,
sizeof(session_id),
"%p", s->
session);
2321 regex_t *regex_filter;
2342 char md5key[256] =
"";
2344 unsigned char digest[16];
2350 for (x = 0; x < 16; x++)
2351 len += sprintf(md5key +
len,
"%02hhx", digest[x]);
2352 if (!strcmp(md5key, key)) {
2358 ast_debug(1,
"MD5 authentication is not possible. challenge: '%s'\n",
2361 }
else if (
user->secret) {
2362 if (!strcmp(password,
user->secret)) {
2384 if (
user->chanvars) {
2391 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
2398 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
2424 "Timestamp: %ld.%06lu\r\n"
2426 (
long) now.tv_sec, (
unsigned long) now.tv_usec);
2453 char *stripped_filename;
2464 if (stripped_filename[0] ==
'/') {
2465 real_path = realpath(stripped_filename,
NULL);
2470 real_path = realpath(path,
NULL);
2490 const char *category_name;
2507 }
else if (ret == -1) {
2527 astman_append(s,
"Category-%06d: %s\r\n", catcount, category_name);
2584 if (catcount == 0) {
2598 if (*
in ==
'\\' || *
in ==
'\"') {
2629 const char *category_name;
2705 for (x = 0; x < 100000; x++) {
2706 unsigned int object = 0;
2710 int ignoreerror = 0;
2718 snprintf(hdr,
sizeof(hdr),
"Action-%06d", x);
2723 snprintf(hdr,
sizeof(hdr),
"Cat-%06d", x);
2730 snprintf(hdr,
sizeof(hdr),
"Var-%06d", x);
2733 snprintf(hdr,
sizeof(hdr),
"Value-%06d", x);
2741 snprintf(hdr,
sizeof(hdr),
"Match-%06d", x);
2744 snprintf(hdr,
sizeof(hdr),
"Line-%06d", x);
2747 snprintf(hdr,
sizeof(hdr),
"Options-%06d", x);
2754 if (!strcasecmp(
"allowdups", token)) {
2758 if (!strcasecmp(
"template", token)) {
2762 if (!strcasecmp(
"ignoreerror", token)) {
2785 if (!strcasecmp(action,
"newcat")) {
2787 char *tmpl_name =
NULL;
2827 if (category !=
NULL) {
2838 }
else if (!strcasecmp(action,
"renamecat")) {
2854 }
else if (!strcasecmp(action,
"delcat")) {
2861 if (!foundcat && !ignoreerror) {
2865 }
else if (!strcasecmp(action,
"emptycat")) {
2876 }
else if (!strcasecmp(action,
"update")) {
2900 }
else if (!strcasecmp(action,
"delete")) {
2920 if (!foundvar && !ignoreerror) {
2924 }
else if (!strcasecmp(action,
"append")) {
2936 if (
object || (
match && !strcasecmp(
match,
"object"))) {
2947 }
else if (!strcasecmp(action,
"insert")) {
2987 const char *preserve_effective_context_string =
astman_get_header(m,
"PreserveEffectiveContext");
3098 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
3104 sscanf(timeouts,
"%30i", &timeout);
3125 time_t now = time(
NULL);
3131 if (timeout < 0 || timeout >
max) {
3143 ast_debug(1,
"Starting waiting for an event!\n");
3145 for (x = 0; x < timeout || timeout < 0; x++) {
3174 ast_debug(1,
"Finished waiting for an event!\n");
3194 "Event: WaitEventComplete\r\n"
3200 ast_debug(1,
"Abandoning event request!\n");
3233 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
3245 if (!strcasecmp(
perms[x].label,
"all") && res ==
perms[x].
num) {
3250 "Events: On\r\n\r\n", id_text);
3251 }
else if (res == 0)
3253 "Events: Off\r\n\r\n", id_text);
3259 "Events: On\r\n\r\n", id_text);
3262 "Events: Off\r\n\r\n", id_text);
3301 long lastreloaded = 0;
3307 uptime =
tmp.tv_sec;
3312 lastreloaded =
tmp.tv_sec;
3318 "LastReload: %ld\r\n"
3319 "Status: Fully Booted\r\n\r\n", cat_str, uptime, lastreloaded);
3328 if (!strcasecmp(authtype,
"MD5")) {
3355 int channels_matched = 0;
3363 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
3368 if (cause_validator) {
3369 causecode = cause_validator(name_or_regex, cause);
3372 causecode = strtol(cause, &endptr, 10);
3373 if (causecode < 0 || causecode > 127 || *endptr !=
'\0') {
3383 if (name_or_regex[0] !=
'/') {
3391 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
3397 hangup_handler(
c, causecode);
3409 if (!regex_string) {
3416 astman_send_error(s, m,
"Regex format invalid, Channel param should be /regex/");
3422 if (regcomp(®exbuf,
ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
3437 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
3443 hangup_handler(
c, causecode);
3447 "Event: ChannelHungup\r\n"
3508 char workspace[1024];
3528 workspace[0] =
'\0';
3529 if (varname[strlen(varname) - 1] ==
')') {
3533 ast_func_read(
c, (
char *) varname, workspace,
sizeof(workspace));
3535 ast_log(
LOG_ERROR,
"Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
3537 ast_func_read(
c, (
char *) varname, workspace,
sizeof(workspace));
3549 astman_append(s,
"Variable: %s\r\nValue: %s\r\n\r\n", varname,
S_OR(varval,
""));
3557 long elapsed_seconds;
3575 if (!snapshot_str) {
3579 if (all_variables) {
3584 if (!variable_str) {
3593 for (i = 0; i < varc; i++) {
3594 char valbuf[512], *ret =
NULL;
3596 if (vars[i][strlen(vars[i]) - 1] ==
')') {
3597 if (
ast_func_read(chan, vars[i], valbuf,
sizeof(valbuf)) < 0) {
3605 ast_str_append(&variable_str, 0,
"Variable: %s=%s\r\n", vars[i], ret);
3609 if (all_variables) {
3623 "Privilege: Call\r\n"
3627 "EffectiveConnectedLineNum: %s\r\n"
3628 "EffectiveConnectedLineName: %s\r\n"
3629 "TimeToHangup: %ld\r\n"
3631 "Application: %s\r\n"
3633 "Nativeformats: %s\r\n"
3634 "Readformat: %s\r\n"
3636 "Writeformat: %s\r\n"
3637 "Writetrans: %s\r\n"
3638 "Callgroup: %llu\r\n"
3639 "Pickupgroup: %llu\r\n"
3660 (
long)elapsed_seconds,
3674 int all_variables = 0;
3687 all_variables =
ast_true(all_chan_variables);
3712 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
3764 obj_size = payload_size +
sizeof(*obj);
3773 memcpy(obj->
payload, payload, payload_size);
3807 const char *content_type)
3904 if (sscanf(
priority,
"%30d", &pi) != 1) {
3922 if (sscanf(priority2,
"%30d", &pi2) != 1) {
3933 snprintf(
buf,
sizeof(
buf),
"Channel does not exist: %s",
name);
3957 snprintf(
buf,
sizeof(
buf),
"ExtraChannel does not exist: %s", name2);
4134 if (!feature_code) {
4156 char *cmd_copy, *cur_cmd;
4168 cmd_words[i] = cur_cmd;
4193 char *
buf =
NULL, *final_buf =
NULL, *delim, *output;
4194 char template[] =
"/tmp/ast-ami-XXXXXX";
4208 if ((fd = mkstemp(
template)) < 0) {
4217 if ((
len = lseek(fd, 0, SEEK_END)) < 0) {
4218 astman_append(s,
"Message: Failed to determine number of characters: %s\r\n", strerror(
errno));
4219 goto action_command_cleanup;
4226 if (!
buf || !final_buf) {
4228 goto action_command_cleanup;
4231 if (lseek(fd, 0, SEEK_SET) < 0) {
4232 astman_append(s,
"Message: Failed to set position on temporary file: %s\r\n", strerror(
errno));
4233 goto action_command_cleanup;
4236 if (read(fd,
buf,
len) < 0) {
4237 astman_append(s,
"Message: Failed to read from temporary file: %s\r\n", strerror(
errno));
4238 goto action_command_cleanup;
4243 final_buf[
len] =
'\0';
4246 if (
len && final_buf[
len - 1] ==
'\n') {
4247 final_buf[
len - 1] =
'\0';
4253 while ((output =
strsep(&delim,
"\n"))) {
4257action_command_cleanup:
4315 .uniqueid2 =
in->otherchannelid
4320 in->timeout,
in->app,
in->appdata, &reason,
4324 in->vars,
in->account, &chan, &assignedids);
4327 in->timeout,
in->context,
in->exten,
in->priority, &reason,
4331 in->vars,
in->account, &chan,
in->early_media, &assignedids);
4344 "Application: %s\r\n"
4348 "CallerIDNum: %s\r\n"
4349 "CallerIDName: %s\r\n",
4350 in->idtext, res ?
"Failure" :
"Success",
4352 in->app,
in->appdata, reason,
4354 S_OR(
in->cid_num,
"<unknown>"),
4355 S_OR(
in->cid_name,
"<unknown>")
4366 "CallerIDNum: %s\r\n"
4367 "CallerIDName: %s\r\n",
4368 in->idtext, res ?
"Failure" :
"Success",
4370 in->context,
in->exten, reason,
4372 S_OR(
in->cid_num,
"<unknown>"),
4373 S_OR(
in->cid_name,
"<unknown>")
4388 const char *unitamount;
4389 const char *unittype;
4401 entry->valid_amount = 1;
4405 entry->valid_type = 1;
4421 const char *association_num =
astman_get_header(m,
"ChargingAssociationNumber");
4429 unsigned int _currencyamount = 0;
4430 int _association_id = 0;
4431 unsigned int _association_plan = 0;
4437 goto aocmessage_cleanup;
4442 if (!strcasecmp(chargetype,
"NA")) {
4444 }
else if (!strcasecmp(chargetype,
"Free")) {
4446 }
else if (!strcasecmp(chargetype,
"Currency")) {
4448 }
else if (!strcasecmp(chargetype,
"Unit")) {
4452 goto aocmessage_cleanup;
4457 if (
ast_strlen_zero(currencyamount) || (sscanf(currencyamount,
"%30u", &_currencyamount) != 1)) {
4458 astman_send_error(s, m,
"Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
4459 goto aocmessage_cleanup;
4463 astman_send_error(s, m,
"ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
4464 goto aocmessage_cleanup;
4465 }
else if (!strcasecmp(mult,
"onethousandth")) {
4467 }
else if (!strcasecmp(mult,
"onehundredth")) {
4469 }
else if (!strcasecmp(mult,
"onetenth")) {
4471 }
else if (!strcasecmp(mult,
"one")) {
4473 }
else if (!strcasecmp(mult,
"ten")) {
4475 }
else if (!strcasecmp(mult,
"hundred")) {
4477 }
else if (!strcasecmp(mult,
"thousand")) {
4481 goto aocmessage_cleanup;
4488 goto aocmessage_cleanup;
4492 if (!
ast_strlen_zero(totaltype) && !strcasecmp(totaltype,
"subtotal")) {
4498 }
else if (!strcasecmp(aocbillingid,
"Normal")) {
4500 }
else if (!strcasecmp(aocbillingid,
"ReverseCharge")) {
4502 }
else if (!strcasecmp(aocbillingid,
"CreditCard")) {
4506 goto aocmessage_cleanup;
4511 }
else if (!strcasecmp(aocbillingid,
"Normal")) {
4513 }
else if (!strcasecmp(aocbillingid,
"ReverseCharge")) {
4515 }
else if (!strcasecmp(aocbillingid,
"CreditCard")) {
4517 }
else if (!strcasecmp(aocbillingid,
"CallFwdUnconditional")) {
4519 }
else if (!strcasecmp(aocbillingid,
"CallFwdBusy")) {