62 #include <sys/types.h>
93 #include "asterisk/stasis_message_router.h"
94 #include "asterisk/stasis_channels.h"
95 #include "asterisk/stasis_bridges.h"
99 #include "asterisk/features_config.h"
1575 UNSPECIFIED_CATEGORY,
1576 UNSPECIFIED_ARGUMENT,
1587 enum add_filter_result {
1589 FILTER_ALLOC_FAILED,
1590 FILTER_COMPILE_FAIL,
1623 static
int displayconnects = 1;
1624 static
int allowmultiplelogin = 1;
1625 static
int timestampevents;
1626 static
int httptimeout = 60;
1627 static
int broken_events_action = 0;
1628 static
int manager_enabled = 0;
1629 static
int subscribed = 0;
1630 static
int webmanager_enabled = 0;
1632 static
int authtimeout;
1633 static
int authlimit;
1634 static
char *manager_channelvars;
1635 static
char *manager_disabledevents;
1637 #define DEFAULT_REALM "asterisk"
1640 static int unauth_sessions = 0;
1660 #ifdef TEST_FRAMEWORK
1665 #define MGR_SHOW_TERMINAL_WIDTH 80
1667 #define MAX_VARS 128
1670 #define EVENT_FLAG_SHUTDOWN -1
1682 #define MAX_BLACKLIST_CMD_LEN 2
1683 static const struct {
1684 const char *words[AST_MAX_CMD_LEN];
1685 } command_blacklist[] = {
1686 {{
"module",
"load", NULL }},
1687 {{
"module",
"unload", NULL }},
1688 {{
"restart",
"gracefully", NULL }},
1693 static void acl_change_stasis_subscribe(
void)
1695 if (!acl_change_sub) {
1697 acl_change_stasis_cb, NULL);
1703 static void acl_change_stasis_unsubscribe(
void)
1749 struct timeval sessionstart_tv;
1769 unsigned int kicked:1;
1775 enum mansession_message_parsing {
1777 MESSAGE_LINE_TOO_LONG
1789 enum mansession_message_parsing parsing;
1790 unsigned int write_error:1;
1835 static int __attribute__((format(printf, 9, 0))) __manager_event_sessions(
1848 static
int match_filter(struct
mansession *s,
char *eventdata);
1864 static struct manager_action *action_find(const
char *
name)
1866 struct manager_action *act;
1869 AST_RWLIST_TRAVERSE(&actions, act, list) {
1870 if (!strcasecmp(name, act->
action)) {
1871 ao2_t_ref(act, +1,
"found action object");
1890 static void manager_json_value_str_append(
struct ast_json *value,
const char *key,
1894 case AST_JSON_STRING:
1897 case AST_JSON_INTEGER:
1903 case AST_JSON_FALSE:
1912 static void manager_json_to_ast_str(
struct ast_json *obj,
const char *key,
1915 static void manager_json_array_with_key(
struct ast_json *obj,
const char* key,
1916 size_t index,
struct ast_str **res,
1919 struct ast_str *key_str = ast_str_alloca(64);
1925 static void manager_json_obj_with_key(
struct ast_json *obj,
const char* key,
1926 const char *parent_key,
struct ast_str **res,
1930 struct ast_str *key_str = ast_str_alloca(64);
1931 ast_str_set(&key_str, 0,
"%s/%s", parent_key, key);
1937 manager_json_to_ast_str(obj, key, res, exclusion_cb);
1940 void manager_json_to_ast_str(
struct ast_json *obj,
const char *key,
1954 if (exclusion_cb && key && exclusion_cb(key)) {
1960 manager_json_value_str_append(obj, key, res);
1968 key, j, res, exclusion_cb);
1977 key, res, exclusion_cb);
1986 manager_json_to_ast_str(blob, NULL, &res, exclusion_cb);
1992 #define manager_event_sessions(sessions, category, event, contents , ...) \
1993 __manager_event_sessions(sessions, category, event, 0, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, contents , ## __VA_ARGS__)
1995 #define any_manager_listeners(sessions) \
1996 ((sessions && ao2_container_count(sessions)) || !AST_RWLIST_EMPTY(&manager_hooks))
2010 if (!any_manager_listeners(sessions)) {
2012 ao2_cleanup(sessions);
2019 ao2_cleanup(sessions);
2026 ao2_cleanup(sessions);
2040 if (!any_manager_listeners(sessions)) {
2042 ao2_cleanup(sessions);
2052 if (!event_buffer) {
2053 ast_log(AST_LOG_WARNING,
"Error while creating payload for event %s\n", type);
2054 ao2_cleanup(sessions);
2057 manager_event_sessions(sessions, class_type, type,
2059 ast_free(event_buffer);
2060 ao2_cleanup(sessions);
2076 "class_type", class_type,
2097 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list);
2105 AST_RWLIST_REMOVE(&manager_hooks, hook, list);
2111 return manager_enabled;
2116 return (webmanager_enabled && manager_enabled);
2125 struct eventqent *ret;
2128 ret = AST_RWLIST_LAST(&all_events);
2145 struct eventqent *ev;
2149 while ( (ev = AST_RWLIST_FIRST(&all_events)) &&
2150 ev->
usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) {
2151 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next);
2155 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) {
2157 if (!AST_RWLIST_NEXT(ev, eq_next)) {
2163 AST_RWLIST_REMOVE_CURRENT(eq_next);
2167 AST_RWLIST_TRAVERSE_SAFE_END;
2179 { EVENT_FLAG_SYSTEM,
"system" },
2180 { EVENT_FLAG_CALL,
"call" },
2181 { EVENT_FLAG_LOG,
"log" },
2182 { EVENT_FLAG_VERBOSE,
"verbose" },
2183 { EVENT_FLAG_COMMAND,
"command" },
2184 { EVENT_FLAG_AGENT,
"agent" },
2185 { EVENT_FLAG_USER,
"user" },
2186 { EVENT_FLAG_CONFIG,
"config" },
2187 { EVENT_FLAG_DTMF,
"dtmf" },
2188 { EVENT_FLAG_REPORTING,
"reporting" },
2189 { EVENT_FLAG_CDR,
"cdr" },
2190 { EVENT_FLAG_DIALPLAN,
"dialplan" },
2191 { EVENT_FLAG_ORIGINATE,
"originate" },
2192 { EVENT_FLAG_AGI,
"agi" },
2193 { EVENT_FLAG_CC,
"cc" },
2194 { EVENT_FLAG_AOC,
"aoc" },
2195 { EVENT_FLAG_TEST,
"test" },
2196 { EVENT_FLAG_SECURITY,
"security" },
2197 { EVENT_FLAG_MESSAGE,
"message" },
2203 #define MAX_AUTH_PERM_STRING 150
2208 if (!(writepermlist & EVENT_FLAG_SYSTEM)
2210 strstr(evaluating,
"SHELL") ||
2211 strstr(evaluating,
"EVAL")
2226 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
2227 if ((authority & perms[i].num) == perms[i].num) {
2251 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) {
2252 if (authority & perms[i].num) {
2272 static int ast_instring(
const char *bigstr,
const char *smallstr,
const char delim)
2274 const char *
val = bigstr, *next;
2277 if ((next = strchr(val, delim))) {
2278 if (!strncmp(val, smallstr, (next - val))) {
2284 return !strcmp(smallstr, val);
2286 }
while (*(val = (next + 1)));
2291 static int get_perm(
const char *instr)
2299 for (x = 0; x < ARRAY_LEN(perms); x++) {
2301 ret |= perms[x].num;
2316 if (ast_strlen_zero(
string)) {
2320 for (p =
string; *p; p++) {
2321 if (*p < '0' || *p >
'9') {
2326 return atoi(
string);
2333 for (x = 0; x < ARRAY_LEN(perms); x++) {
2334 ret |= perms[x].num;
2338 return get_perm(
string);
2345 int refcount =
ao2_ref(s, -1);
2346 if (manager_debug) {
2347 ast_debug(1,
"Mansession: %p refcount now %d\n", s, refcount - 1);
2352 static void event_filter_destructor(
void *obj)
2354 regex_t *regex_filter = obj;
2355 regfree(regex_filter);
2358 static void session_destructor(
void *obj)
2361 struct eventqent *eqe = session->
last_ev;
2378 ao2_t_ref(session->
whitefilters, -1,
"decrement ref for white container, should be last one");
2382 ao2_t_ref(session->
blackfilters, -1,
"decrement ref for black container, should be last one");
2394 newsession = ao2_alloc(
sizeof(*newsession), session_destructor);
2422 static int mansession_cmp_fn(
void *obj,
void *arg,
int flags)
2442 static int check_manager_session_inuse(
const char *name)
2450 session = ao2_find(sessions, (
char *) name, 0);
2467 struct ast_manager_user *
user = NULL;
2469 AST_RWLIST_TRAVERSE(&users, user, list) {
2470 if (!strcasecmp(user->username, name)) {
2484 struct ast_manager_user *
user = NULL;
2502 struct manager_action *cur;
2506 const char *auth_str;
2508 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
2509 char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
2514 e->
command =
"manager show command";
2516 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n"
2517 " Shows the detailed description for a specific Asterisk manager interface command.\n";
2520 l = strlen(a->word);
2522 AST_RWLIST_TRAVERSE(&actions, cur, list) {
2523 if (!strncasecmp(a->word, cur->
action, l)) {
2533 return CLI_SHOWUSAGE;
2540 term_color(synopsis_title,
"[Synopsis]\n", COLOR_MAGENTA, 0, 40);
2541 term_color(description_title,
"[Description]\n", COLOR_MAGENTA, 0, 40);
2542 term_color(syntax_title,
"[Syntax]\n", COLOR_MAGENTA, 0, 40);
2543 term_color(seealso_title,
"[See Also]\n", COLOR_MAGENTA, 0, 40);
2544 term_color(arguments_title,
"[Arguments]\n", COLOR_MAGENTA, 0, 40);
2545 term_color(privilege_title,
"[Privilege]\n", COLOR_MAGENTA, 0, 40);
2546 term_color(final_response_title,
"[Final Response]\n", COLOR_MAGENTA, 0, 40);
2547 term_color(list_responses_title,
"[List Responses]\n", COLOR_MAGENTA, 0, 40);
2551 AST_RWLIST_TRAVERSE(&actions, cur, list) {
2552 for (num = 3; num < a->argc; num++) {
2553 if (!strcasecmp(cur->
action, a->argv[num])) {
2566 if (!syntax || !synopsis || !description || !arguments
2567 || !seealso || !privilege || !responses) {
2570 ast_free(description);
2571 ast_free(arguments);
2573 ast_free(privilege);
2574 ast_free(responses);
2575 ast_cli(a->fd,
"Allocation failure.\n");
2581 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",
2582 syntax_title, syntax,
2583 synopsis_title, synopsis,
2584 description_title, description,
2585 arguments_title, arguments,
2586 seealso_title, seealso,
2587 privilege_title, privilege,
2588 list_responses_title);
2591 ast_cli(a->fd,
"%s\n\n", responses);
2595 ast_cli(a->fd,
"Event: %s\n", temp->
name);
2596 print_event_instance(a, temp);
2600 ast_cli(a->fd,
"%s", final_response_title);
2603 ast_cli(a->fd,
"%s\n\n", responses);
2611 ast_free(description);
2612 ast_free(arguments);
2614 ast_free(privilege);
2615 ast_free(responses);
2619 ast_cli(a->fd,
"Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n",
2636 e->
command =
"manager set debug [on|off]";
2637 e->
usage =
"Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n";
2644 ast_cli(a->fd,
"manager debug is %s\n", manager_debug?
"on" :
"off");
2645 }
else if (a->argc == 4) {
2646 if (!strcasecmp(a->argv[3],
"on")) {
2648 }
else if (!strcasecmp(a->argv[3],
"off")) {
2651 return CLI_SHOWUSAGE;
2659 struct ast_manager_user *
user = NULL;
2667 e->
command =
"manager show user";
2669 " Usage: manager show user <user>\n"
2670 " Display all information related to the manager user specified.\n";
2673 l = strlen(a->word);
2678 AST_RWLIST_TRAVERSE(&users, user, list) {
2679 if (!strncasecmp(a->word, user->username, l)) {
2690 return CLI_SHOWUSAGE;
2696 ast_cli(a->fd,
"There is no manager called %s\n", a->argv[3]);
2701 ast_cli(a->fd,
"\n");
2708 " displayconnects: %s\n"
2709 "allowmultiplelogin: %s\n",
2710 S_OR(user->username,
"(N/A)"),
2711 (user->
secret ?
"<Set>" :
"(N/A)"),
2717 ast_cli(a->fd,
" Variables: \n");
2719 ast_cli(a->fd,
" %s = %s\n", v->
name, v->
value);
2732 struct ast_manager_user *user = NULL;
2736 e->
command =
"manager show users";
2738 "Usage: manager show users\n"
2739 " Prints a listing of all managers that are currently configured on that\n"
2746 return CLI_SHOWUSAGE;
2752 if (AST_RWLIST_EMPTY(&users)) {
2753 ast_cli(a->fd,
"There are no manager users.\n");
2758 ast_cli(a->fd,
"\nusername\n--------\n");
2760 AST_RWLIST_TRAVERSE(&users, user, list) {
2761 ast_cli(a->fd,
"%s\n", user->username);
2767 ast_cli(a->fd,
"-------------------\n"
2768 "%d manager users configured.\n", count_amu);
2775 struct manager_action *cur;
2777 int space_remaining;
2778 #define HSMC_FORMAT " %-*.*s %-.*s\n"
2781 e->
command =
"manager show commands";
2783 "Usage: manager show commands\n"
2784 " Prints a listing of all the available Asterisk manager interface commands.\n";
2791 AST_RWLIST_TRAVERSE(&actions, cur, list) {
2792 int incoming_len = strlen(cur->
action);
2793 if (incoming_len > name_len) {
2794 name_len = incoming_len;
2798 space_remaining = MGR_SHOW_TERMINAL_WIDTH - name_len - 4;
2799 if (space_remaining < 0) {
2800 space_remaining = 0;
2803 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len,
"Action", space_remaining,
"Synopsis");
2804 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len,
"------", space_remaining,
"--------");
2806 AST_RWLIST_TRAVERSE(&actions, cur, list) {
2807 ast_cli(a->fd, HSMC_FORMAT, name_len, name_len, cur->
action, space_remaining, cur->
synopsis);
2825 e->
command =
"manager kick session";
2827 "Usage: manager kick session <file descriptor>\n"
2828 " Kick an active Asterisk Manager Interface session\n";
2835 return CLI_SHOWUSAGE;
2838 fd = atoi(a->argv[3]);
2840 ast_cli(a->fd,
"Invalid AMI file descriptor: %s\n", a->argv[3]);
2848 while ((session = ao2_iterator_next(&i))) {
2853 ast_cli(a->fd,
"Manager session using file descriptor %d has already been kicked\n", fd);
2854 ao2_unlock(session);
2860 ast_cli(a->fd,
"Kicking manager session connected using file descriptor %d\n", fd);
2867 ao2_unlock(session);
2872 ao2_unlock(session);
2879 ast_cli(a->fd,
"No manager session found using file descriptor %d\n", fd);
2889 time_t now = time(NULL);
2890 #define HSMCONN_FORMAT1 " %-15.15s %-55.55s %-10.10s %-10.10s %-8.8s %-8.8s %-10.10s %-10.10s\n"
2891 #define HSMCONN_FORMAT2 " %-15.15s %-55.55s %-10d %-10d %-8d %-8d %-10.10d %-10.10d\n"
2897 e->
command =
"manager show connected";
2899 "Usage: manager show connected\n"
2900 " Prints a listing of the users that are currently connected to the\n"
2901 "Asterisk manager interface.\n";
2907 ast_cli(a->fd, HSMCONN_FORMAT1,
"Username",
"IP Address",
"Start",
"Elapsed",
"FileDes",
"HttpCnt",
"ReadPerms",
"WritePerms");
2913 while ((session = ao2_iterator_next(&i))) {
2915 ast_cli(a->fd, HSMCONN_FORMAT2, session->
username,
2924 ao2_unlock(session);
2929 ast_cli(a->fd,
"%d users connected.\n", count);
2938 struct eventqent *s;
2941 e->
command =
"manager show eventq";
2943 "Usage: manager show eventq\n"
2944 " Prints a listing of all events pending in the Asterisk manger\n"
2951 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) {
2952 ast_cli(a->fd,
"Usecount: %d\n", s->
usecount);
2953 ast_cli(a->fd,
"Category: %d\n", s->category);
2954 ast_cli(a->fd,
"Event:\n%s", s->eventdata);
2961 static int reload_module(
void);
2968 e->
command =
"manager reload";
2970 "Usage: manager reload\n"
2971 " Reloads the manager configuration.\n";
2977 return CLI_SHOWUSAGE;
2983 static struct eventqent *advance_event(
struct eventqent *e)
2985 struct eventqent *next;
2988 if ((next = AST_RWLIST_NEXT(e, eq_next))) {
2996 #define GET_HEADER_FIRST_MATCH 0
2997 #define GET_HEADER_LAST_MATCH 1
2998 #define GET_HEADER_SKIP_EMPTY 2
3015 int x, l = strlen(var);
3016 const char *result =
"";
3022 for (x = 0; x < m->hdrcount; x++) {
3023 const char *h = m->headers[x];
3024 if (!strncasecmp(var, h, l) && h[l] ==
':') {
3025 const char *value = h + l + 1;
3028 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) {
3031 if (mode & GET_HEADER_LAST_MATCH) {
3064 for (v = params; v && m->hdrcount < ARRAY_LEN(m->headers); v = v->
next) {
3076 while (m->hdrcount) {
3078 ast_free((
void *) m->headers[m->hdrcount]);
3079 m->headers[m->hdrcount] = NULL;
3108 for (y = 0; y < args.argc; y++) {
3113 if (!args.vars[y]) {
3116 var = val = args.vars[y];
3120 if (!val || ast_strlen_zero(var)) {
3125 cur = ast_variable_new(var, val,
"");
3142 enum variable_orders order)
3148 static const char var_hdr[] =
"Variable:";
3151 varlen = strlen(var_hdr);
3152 for (x = 0; x < m->hdrcount; x++) {
3153 if (strncasecmp(var_hdr, m->headers[x], varlen)) {
3156 head = man_do_variable_value(head, m->headers[x] + varlen);
3159 if (order == ORDER_NATURAL) {
3171 struct manager_action *act_found;
3173 struct message m = { 0 };
3190 curlen = strlen(src);
3191 for (x = 0; x < curlen; x++) {
3193 if (src[x] ==
'\r' && x+1 < curlen && src[x+1] ==
'\n')
3195 else if (src[x] ==
'\n')
3200 if (x && m.hdrcount < ARRAY_LEN(m.headers)) {
3203 m.headers[m.hdrcount++] = src;
3214 if (!strcasecmp(action,
"login")) {
3218 act_found = action_find(action);
3231 ao2_lock(act_found);
3235 ao2_unlock(act_found);
3237 if (!act_found->
module || mod_ref) {
3238 ret = act_found->
func(&s, &m);
3242 ao2_unlock(act_found);
3244 ao2_t_ref(act_found, -1,
"done with found action object");
3266 s->hook->
helper(EVENT_FLAG_HOOKRESPONSE,
"HookResponse",
string);
3270 stream = s->stream ? s->stream : s->session->
stream;
3272 len = strlen(
string);
3296 #define ASTMAN_APPEND_BUF_INITSIZE 256
3300 if (s->hook || (s->tcptls_session && s->tcptls_session->
stream)) {
3303 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3327 if (s->hook || (s->tcptls_session != NULL && s->tcptls_session->
stream != NULL)) {
3330 ast_verbose(
"No connection stream in astman_append, should not happen\n");
3344 #define MSG_MOREDATA ((char *)astman_send_response)
3365 if (!ast_strlen_zero(
id)) {
3381 astman_flush(s, buf);
3426 static void astman_start_ack(
struct mansession *s,
const struct message *m)
3436 static struct ast_str *astman_send_list_complete_start_common(
struct mansession *s,
const struct message *m,
const char *event_name,
int count)
3446 ast_str_set(&buf, 0,
"Event: %s\r\n", event_name);
3447 if (!ast_strlen_zero(
id)) {
3451 "EventList: Complete\r\n"
3452 "ListItems: %d\r\n",
3458 static void astman_send_list_complete(
struct mansession *s,
const struct message *m,
const char *event_name,
int count)
3460 struct ast_str *buf = astman_send_list_complete_start_common(s, m, event_name, count);
3463 astman_flush(s, buf);
3469 struct ast_str *buf = astman_send_list_complete_start_common(s, m, event_name, count);
3471 astman_flush(s, buf);
3483 ast_mutex_lock(&s->lock);
3489 ast_mutex_unlock(&s->lock);
3500 ao2_lock(s->session);
3504 ao2_unlock(s->session);
3509 static enum ast_transport mansession_get_transport(
const struct mansession *s)
3511 return s->tcptls_session->parent->
tls_cfg ? AST_TRANSPORT_TLS :
3515 static void report_invalid_user(
const struct mansession *s,
const char *username)
3517 char session_id[32];
3521 .common.service =
"AMI",
3522 .common.account_id = username,
3524 .common.local_addr = {
3525 .addr = &s->tcptls_session->parent->local_address,
3526 .transport = mansession_get_transport(s),
3528 .common.remote_addr = {
3529 .addr = &s->session->
addr,
3530 .transport = mansession_get_transport(s),
3532 .common.session_id = session_id,
3535 snprintf(session_id,
sizeof(session_id),
"%p", s);
3540 static void report_failed_acl(
const struct mansession *s,
const char *username)
3542 char session_id[32];
3546 .common.service =
"AMI",
3547 .common.account_id = username,
3549 .common.local_addr = {
3550 .addr = &s->tcptls_session->parent->local_address,
3551 .transport = mansession_get_transport(s),
3553 .common.remote_addr = {
3554 .addr = &s->session->
addr,
3555 .transport = mansession_get_transport(s),
3557 .common.session_id = session_id,
3560 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3565 static void report_inval_password(
const struct mansession *s,
const char *username)
3567 char session_id[32];
3571 .common.service =
"AMI",
3572 .common.account_id = username,
3574 .common.local_addr = {
3575 .addr = &s->tcptls_session->parent->local_address,
3576 .transport = mansession_get_transport(s),
3578 .common.remote_addr = {
3579 .addr = &s->session->
addr,
3580 .transport = mansession_get_transport(s),
3582 .common.session_id = session_id,
3585 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3590 static void report_auth_success(
const struct mansession *s)
3592 char session_id[32];
3596 .common.service =
"AMI",
3597 .common.account_id = s->session->
username,
3599 .common.local_addr = {
3600 .addr = &s->tcptls_session->parent->local_address,
3601 .transport = mansession_get_transport(s),
3603 .common.remote_addr = {
3604 .addr = &s->session->
addr,
3605 .transport = mansession_get_transport(s),
3607 .common.session_id = session_id,
3610 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3615 static void report_req_not_allowed(
const struct mansession *s,
const char *action)
3617 char session_id[32];
3618 char request_type[64];
3622 .common.service =
"AMI",
3623 .common.account_id = s->session->
username,
3625 .common.local_addr = {
3626 .addr = &s->tcptls_session->parent->local_address,
3627 .transport = mansession_get_transport(s),
3629 .common.remote_addr = {
3630 .addr = &s->session->
addr,
3631 .transport = mansession_get_transport(s),
3633 .common.session_id = session_id,
3638 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3639 snprintf(request_type,
sizeof(request_type),
"Action: %s", action);
3644 static void report_req_bad_format(
const struct mansession *s,
const char *action)
3646 char session_id[32];
3647 char request_type[64];
3651 .common.service =
"AMI",
3652 .common.account_id = s->session->
username,
3654 .common.local_addr = {
3655 .addr = &s->tcptls_session->parent->local_address,
3656 .transport = mansession_get_transport(s),
3658 .common.remote_addr = {
3659 .addr = &s->session->
addr,
3660 .transport = mansession_get_transport(s),
3662 .common.session_id = session_id,
3667 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3668 snprintf(request_type,
sizeof(request_type),
"Action: %s", action);
3673 static void report_failed_challenge_response(
const struct mansession *s,
3674 const char *response,
const char *expected_response)
3676 char session_id[32];
3680 .common.service =
"AMI",
3681 .common.account_id = s->session->
username,
3683 .common.local_addr = {
3684 .addr = &s->tcptls_session->parent->local_address,
3685 .transport = mansession_get_transport(s),
3687 .common.remote_addr = {
3688 .addr = &s->session->
addr,
3689 .transport = mansession_get_transport(s),
3691 .common.session_id = session_id,
3698 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3703 static void report_session_limit(
const struct mansession *s)
3705 char session_id[32];
3709 .common.service =
"AMI",
3710 .common.account_id = s->session->
username,
3712 .common.local_addr = {
3713 .addr = &s->tcptls_session->parent->local_address,
3714 .transport = mansession_get_transport(s),
3716 .common.remote_addr = {
3717 .addr = &s->session->
addr,
3718 .transport = mansession_get_transport(s),
3720 .common.session_id = session_id,
3723 snprintf(session_id,
sizeof(session_id),
"%p", s->session);
3735 static int authenticate(
struct mansession *s,
const struct message *m)
3740 struct ast_manager_user *user = NULL;
3741 regex_t *regex_filter;
3744 if (ast_strlen_zero(username)) {
3752 report_invalid_user(s, username);
3754 }
else if (user->
acl && (
ast_apply_acl(user->
acl, &s->session->
addr,
"Manager User ACL: ") == AST_SENSE_DENY)) {
3755 report_failed_acl(s, username);
3759 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->
challenge) && user->
secret) {
3762 char md5key[256] =
"";
3764 unsigned char digest[16];
3767 MD5Update(&md5, (
unsigned char *) s->session->
challenge, strlen(s->session->
challenge));
3768 MD5Update(&md5, (
unsigned char *) user->
secret, strlen(user->
secret));
3769 MD5Final(digest, &md5);
3770 for (x = 0; x < 16; x++)
3771 len += sprintf(md5key + len,
"%02hhx", digest[x]);
3772 if (!strcmp(md5key, key)) {
3775 report_failed_challenge_response(s, key, md5key);
3778 ast_debug(1,
"MD5 authentication is not possible. challenge: '%s'\n",
3781 }
else if (user->
secret) {
3782 if (!strcmp(password, user->
secret)) {
3785 report_inval_password(s, username);
3809 while ((regex_filter = ao2_iterator_next(&filter_iter))) {
3810 ao2_t_link(s->session->
whitefilters, regex_filter,
"add white user filter to session");
3811 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3816 while ((regex_filter = ao2_iterator_next(&filter_iter))) {
3817 ao2_t_link(s->session->
blackfilters, regex_filter,
"add black user filter to session");
3818 ao2_t_ref(regex_filter, -1,
"remove iterator ref");
3826 report_auth_success(s);
3832 static int action_ping(
struct mansession *s,
const struct message *m)
3838 if (!ast_strlen_zero(actionid)){
3844 "Timestamp: %ld.%06lu\r\n"
3846 (
long) now.tv_sec, (
unsigned long) now.tv_usec);
3852 if (new_live_dangerously && !live_dangerously)
3854 ast_log(LOG_WARNING,
"Manager Configuration load protection disabled.\n");
3857 if (!new_live_dangerously && live_dangerously)
3859 ast_log(LOG_NOTICE,
"Manager Configuration load protection enabled.\n");
3861 live_dangerously = new_live_dangerously;
3873 char *stripped_filename;
3874 RAII_VAR(
char *, path, NULL, ast_free);
3875 RAII_VAR(
char *, real_path, NULL, ast_std_free);
3877 if (live_dangerously) {
3884 if (stripped_filename[0] ==
'/') {
3885 real_path = realpath(stripped_filename, NULL);
3887 if (
ast_asprintf(&path,
"%s/%s", ast_config_AST_CONFIG_DIR, stripped_filename) == -1) {
3890 real_path = realpath(path, NULL);
3904 static int action_getconfig(
struct mansession *s,
const struct message *m)
3910 const char *category_name;
3918 if (ast_strlen_zero(fn)) {
3927 }
else if (ret == -1) {
3933 if (cfg == CONFIG_STATUS_FILEMISSING) {
3936 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
3941 astman_start_ack(s, m);
3947 astman_append(s,
"Category-%06d: %s\r\n", catcount, category_name);
3956 ast_free(templates);
3966 if (!ast_strlen_zero(category) && catcount == 0) {
3976 static int action_listcategories(
struct mansession *s,
const struct message *m)
3985 if (ast_strlen_zero(fn)) {
3993 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
3998 astman_start_ack(s, m);
4004 if (catcount == 0) {
4018 if (*in ==
'\\' || *in ==
'\"') {
4033 static void astman_append_json(
struct mansession *s,
const char *str)
4042 static int action_getconfigjson(
struct mansession *s,
const struct message *m)
4049 const char *category_name;
4054 if (ast_strlen_zero(fn)) {
4067 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
4072 astman_start_ack(s, m);
4080 astman_append_json(s, category_name);
4093 ast_free(templates);
4099 astman_append_json(s, v->
name);
4101 astman_append_json(s, v->
value);
4120 const char *action, *cat, *var, *value, *match, *line, *options;
4125 for (x = 0; x < 100000; x++) {
4126 unsigned int object = 0;
4130 int ignoreerror = 0;
4131 RAII_VAR(
char *, inherit, NULL, ast_free);
4132 RAII_VAR(
char *, catfilter, NULL, ast_free);
4138 snprintf(hdr,
sizeof(hdr),
"Action-%06d", x);
4140 if (ast_strlen_zero(action))
4143 snprintf(hdr,
sizeof(hdr),
"Cat-%06d", x);
4145 if (ast_strlen_zero(cat)) {
4146 result = UNSPECIFIED_CATEGORY;
4150 snprintf(hdr,
sizeof(hdr),
"Var-%06d", x);
4153 snprintf(hdr,
sizeof(hdr),
"Value-%06d", x);
4156 if (!ast_strlen_zero(value) && *value ==
'>') {
4161 snprintf(hdr,
sizeof(hdr),
"Match-%06d", x);
4164 snprintf(hdr,
sizeof(hdr),
"Line-%06d", x);
4167 snprintf(hdr,
sizeof(hdr),
"Options-%06d", x);
4169 if (!ast_strlen_zero(options)) {
4170 char copy[strlen(options) + 1];
4171 strcpy(copy, options);
4174 if (!strcasecmp(
"allowdups", token)) {
4178 if (!strcasecmp(
"template", token)) {
4182 if (!strcasecmp(
"ignoreerror", token)) {
4205 if (!strcasecmp(action,
"newcat")) {
4207 char *tmpl_name = NULL;
4214 result = FAILURE_NEWCAT;
4227 result = FAILURE_ALLOCATION;
4235 result = FAILURE_ALLOCATION;
4239 ast_category_destroy(category);
4241 result = FAILURE_TEMPLATE;
4247 if (category != NULL) {
4248 if (ast_strlen_zero(match)) {
4252 ast_category_destroy(category);
4253 result = FAILURE_NEWCAT;
4258 }
else if (!strcasecmp(action,
"renamecat")) {
4259 if (ast_strlen_zero(value)) {
4260 result = UNSPECIFIED_ARGUMENT;
4266 ast_category_rename(category, value);
4271 result = UNKNOWN_CATEGORY;
4274 }
else if (!strcasecmp(action,
"delcat")) {
4281 if (!foundcat && !ignoreerror) {
4282 result = UNKNOWN_CATEGORY;
4285 }
else if (!strcasecmp(action,
"emptycat")) {
4293 result = UNKNOWN_CATEGORY;
4296 }
else if (!strcasecmp(action,
"update")) {
4297 if (ast_strlen_zero(var)) {
4298 result = UNSPECIFIED_ARGUMENT;
4312 result = UNKNOWN_CATEGORY;
4317 result = FAILURE_UPDATE;
4320 }
else if (!strcasecmp(action,
"delete")) {
4321 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) {
4322 result = UNSPECIFIED_ARGUMENT;
4329 if (!ast_variable_delete(category, var, match, line)) {
4336 result = UNKNOWN_CATEGORY;
4340 if (!foundvar && !ignoreerror) {
4341 result = FAILURE_UPDATE;
4344 }
else if (!strcasecmp(action,
"append")) {
4345 if (ast_strlen_zero(var)) {
4346 result = UNSPECIFIED_ARGUMENT;
4352 if (!(v = ast_variable_new(var, value, dfn))) {
4353 result = FAILURE_ALLOCATION;
4356 if (
object || (match && !strcasecmp(match,
"object"))) {
4359 ast_variable_append(category, v);
4364 result = UNKNOWN_CATEGORY;
4367 }
else if (!strcasecmp(action,
"insert")) {
4368 if (ast_strlen_zero(var) || ast_strlen_zero(line)) {
4369 result = UNSPECIFIED_ARGUMENT;
4375 if (!(v = ast_variable_new(var, value, dfn))) {
4376 result = FAILURE_ALLOCATION;
4379 ast_variable_insert(category, v, line);
4384 result = UNKNOWN_CATEGORY;
4389 ast_log(LOG_WARNING,
"Action-%06d: %s not handled\n", x, action);
4390 result = UNKNOWN_ACTION;
4399 static int action_updateconfig(
struct mansession *s,
const struct message *m)
4407 const char *preserve_effective_context_string =
astman_get_header(m,
"PreserveEffectiveContext");
4411 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) {
4422 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
4428 ast_include_rename(cfg, sfn, dfn);
4429 if (!ast_strlen_zero(preserve_effective_context_string) && !
ast_true(preserve_effective_context_string)) {
4430 preserve_effective_context = CONFIG_SAVE_FLAG_NONE;
4439 if (!ast_strlen_zero(rld)) {
4449 case UNKNOWN_ACTION:
4452 case UNKNOWN_CATEGORY:
4455 case UNSPECIFIED_CATEGORY:
4458 case UNSPECIFIED_ARGUMENT:
4461 case FAILURE_ALLOCATION:
4464 case FAILURE_NEWCAT:
4467 case FAILURE_DELCAT:
4470 case FAILURE_EMPTYCAT:
4473 case FAILURE_UPDATE:
4476 case FAILURE_DELETE:
4479 case FAILURE_APPEND:
4482 case FAILURE_TEMPLATE:
4490 static int action_createconfig(
struct mansession *s,
const struct message *m)
4494 struct ast_str *filepath = ast_str_alloca(PATH_MAX);
4495 ast_str_set(&filepath, 0,
"%s/", ast_config_AST_CONFIG_DIR);
4498 if ((fd = open(
ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) {
4508 static int action_waitevent(
struct mansession *s,
const struct message *m)
4517 if (!ast_strlen_zero(
id)) {
4518 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4523 if (!ast_strlen_zero(timeouts)) {
4524 sscanf(timeouts,
"%30i", &timeout);
4537 ao2_lock(s->session);
4545 time_t now = time(NULL);
4551 if (timeout < 0 || timeout > max) {
4558 ao2_unlock(s->session);
4563 ast_debug(1,
"Starting waiting for an event!\n");
4565 for (x = 0; x < timeout || timeout < 0; x++) {
4566 ao2_lock(s->session);
4567 if (AST_RWLIST_NEXT(s->session->
last_ev, eq_next)) {
4573 ao2_unlock(s->session);
4594 ast_debug(1,
"Finished waiting for an event!\n");
4598 struct eventqent *eqe = s->session->
last_ev;
4603 ao2_lock(s->session);
4605 while ((eqe = advance_event(eqe))) {
4606 if (((s->session->
readperm & eqe->category) == eqe->category)
4607 && ((s->session->
send_events & eqe->category) == eqe->category)
4608 && match_filter(s, eqe->eventdata)) {
4614 "Event: WaitEventComplete\r\n"
4617 ao2_unlock(s->session);
4620 ast_debug(1,
"Abandoning event request!\n");
4626 static int action_listcommands(
struct mansession *s,
const struct message *m)
4628 struct manager_action *cur;
4631 astman_start_ack(s, m);
4633 AST_RWLIST_TRAVERSE(&actions, cur, list) {
4645 static int action_events(
struct mansession *s,
const struct message *m)
4652 if (!ast_strlen_zero(
id)) {
4653 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
4659 if (broken_events_action) {
4664 for (x = 0; x < ARRAY_LEN(perms); x++) {
4665 if (!strcasecmp(perms[x].label,
"all") && res == perms[x].num) {
4670 "Events: On\r\n\r\n", id_text);
4671 }
else if (res == 0)
4673 "Events: Off\r\n\r\n", id_text);
4679 "Events: On\r\n\r\n", id_text);
4682 "Events: Off\r\n\r\n", id_text);
4689 static int action_logoff(
struct mansession *s,
const struct message *m)
4695 static int action_login(
struct mansession *s,
const struct message *m)
4704 if (authenticate(s, m)) {
4716 && (s->session->
readperm & EVENT_FLAG_SYSTEM)
4721 long lastreloaded = 0;
4725 if (ast_startuptime.tv_sec) {
4726 tmp =
ast_tvsub(curtime, ast_startuptime);
4727 uptime = tmp.tv_sec;
4730 if (ast_lastreloadtime.tv_sec) {
4731 tmp =
ast_tvsub(curtime, ast_lastreloadtime);
4732 lastreloaded = tmp.tv_sec;
4738 "LastReload: %ld\r\n"
4739 "Status: Fully Booted\r\n\r\n", cat_str, uptime, lastreloaded);
4744 static int action_challenge(
struct mansession *s,
const struct message *m)
4748 if (!strcasecmp(authtype,
"MD5")) {
4749 if (ast_strlen_zero(s->session->
challenge)) {
4753 astman_start_ack(s, m);
4775 int channels_matched = 0;
4777 if (ast_strlen_zero(name_or_regex)) {
4782 if (!ast_strlen_zero(
id)) {
4783 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n",
id);
4788 if (cause_validator) {
4789 causecode = cause_validator(name_or_regex, cause);
4790 }
else if (!ast_strlen_zero(cause)) {
4792 causecode = strtol(cause, &endptr, 10);
4793 if (causecode < 0 || causecode > 127 || *endptr !=
'\0') {
4794 ast_log(LOG_NOTICE,
"Invalid 'Cause: %s' in manager action Hangup\n", cause);
4803 if (name_or_regex[0] !=
'/') {
4805 ast_log(LOG_NOTICE,
"Request to hangup non-existent channel: %s\n",
4811 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4815 ast_channel_name(c));
4817 hangup_handler(c, causecode);
4829 if (!regex_string) {
4836 astman_send_error(s, m,
"Regex format invalid, Channel param should be /regex/");
4837 ast_free(regex_string);
4842 if (regcomp(®exbuf,
ast_str_buffer(regex_string), REG_EXTENDED | REG_NOSUB)) {
4844 ast_free(regex_string);
4853 if (regexec(®exbuf, ast_channel_name(c), 0, NULL, 0)) {
4857 ast_verb(3,
"%sManager '%s' from %s, hanging up channel: %s\n",
4861 ast_channel_name(c));
4863 hangup_handler(c, causecode);
4867 "Event: ChannelHungup\r\n"
4870 "\r\n", ast_channel_name(c), idText);
4876 ast_free(regex_string);
4878 astman_send_list_complete(s, m,
"ChannelsHungupListComplete", channels_matched);
4883 static int action_hangup(
struct mansession *s,
const struct message *m)
4889 static int action_setvar(
struct mansession *s,
const struct message *m)
4897 if (ast_strlen_zero(varname)) {
4902 if (!ast_strlen_zero(name)) {
4922 static int action_getvar(
struct mansession *s,
const struct message *m)
4928 char workspace[1024];
4930 if (ast_strlen_zero(varname)) {
4941 if (!ast_strlen_zero(name)) {
4948 workspace[0] =
'\0';
4949 if (varname[strlen(varname) - 1] ==
')') {
4953 ast_func_read(c, (
char *) varname, workspace,
sizeof(workspace));
4955 ast_log(LOG_ERROR,
"Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
4957 ast_func_read(c, (
char *) varname, workspace,
sizeof(workspace));
4968 astman_start_ack(s, m);
4969 astman_append(s,
"Variable: %s\r\nValue: %s\r\n\r\n", varname,
S_OR(varval,
""));
4974 static void generate_status(
struct mansession *s,
struct ast_channel *chan,
char **vars,
int varc,
int all_variables,
char *id_text,
int *count)
4977 long elapsed_seconds;
4980 struct ast_str *write_transpath = ast_str_alloca(256);
4981 struct ast_str *read_transpath = ast_str_alloca(256);
4995 if (!snapshot_str) {
4999 if (all_variables) {
5004 if (!variable_str) {
5009 elapsed_seconds =
ast_tvdiff_sec(now, ast_channel_creationtime(chan));
5013 for (i = 0; i < varc; i++) {
5014 char valbuf[512], *ret = NULL;
5016 if (vars[i][strlen(vars[i]) - 1] ==
')') {
5017 if (
ast_func_read(chan, vars[i], valbuf,
sizeof(valbuf)) < 0) {
5025 ast_str_append(&variable_str, 0,
"Variable: %s=%s\r\n", vars[i], ret);
5029 if (all_variables) {
5034 ast_var_name(variables), ast_var_value(variables));
5039 effective_id = ast_channel_connected_effective_id(chan);
5043 "Privilege: Call\r\n"
5047 "EffectiveConnectedLineNum: %s\r\n"
5048 "EffectiveConnectedLineName: %s\r\n"
5049 "TimeToHangup: %ld\r\n"
5051 "Application: %s\r\n"
5053 "Nativeformats: %s\r\n"
5054 "Readformat: %s\r\n"
5056 "Writeformat: %s\r\n"
5057 "Writetrans: %s\r\n"
5058 "Callgroup: %llu\r\n"
5059 "Pickupgroup: %llu\r\n"
5066 S_OR(ast_channel_dialed(chan)->
number.str,
""),
5069 (
long)ast_channel_whentohangup(chan)->tv_sec,
5071 ast_channel_appl(chan),
5072 ast_channel_data(chan),
5078 ast_channel_callgroup(chan),
5079 ast_channel_pickupgroup(chan),
5080 (
long)elapsed_seconds,
5085 ao2_cleanup(bridge);
5094 int all_variables = 0;
5099 int all = ast_strlen_zero(name);
5106 if (!ast_strlen_zero(all_chan_variables)) {
5107 all_variables =
ast_true(all_chan_variables);
5131 if (!ast_strlen_zero(
id)) {
5132 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n",
id);
5137 if (!ast_strlen_zero(chan_variables)) {
5143 ast_channel_lock(chan);
5145 generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
5147 ast_channel_unlock(chan);
5184 obj_size = payload_size +
sizeof(*obj);
5191 obj->action = action;
5192 obj->payload_size = payload_size;
5193 memcpy(obj->payload, payload, payload_size);
5213 strlen(body) + 1, AST_FRAME_READ_ACTION_SEND_TEXT);
5227 const char *content_type)
5233 NULL, NULL, content_type, body);
5245 static int action_sendtext(
struct mansession *s,
const struct message *m)
5253 if (ast_strlen_zero(name)) {
5258 if (ast_strlen_zero(textmsg)) {
5273 res = ast_strlen_zero(content_type) ?
queue_sendtext(c, textmsg) :
5307 if (ast_strlen_zero(name)) {
5312 if (ast_strlen_zero(context)) {
5316 if (ast_strlen_zero(exten)) {
5320 if (ast_strlen_zero(priority)) {
5324 if (sscanf(priority,
"%30d", &pi) != 1) {
5332 if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) {
5334 if (ast_strlen_zero(exten2)) {
5338 if (ast_strlen_zero(priority2)) {
5342 if (sscanf(priority2,
"%30d", &pi2) != 1) {
5353 snprintf(buf,
sizeof(buf),
"Channel does not exist: %s", name);
5357 if (ast_check_hangup_locked(chan)) {
5363 if (ast_strlen_zero(name2)) {
5377 snprintf(buf,
sizeof(buf),
"ExtraChannel does not exist: %s", name2);
5382 if (ast_check_hangup_locked(chan2)) {
5390 ast_channel_lock(chan);
5395 ast_channel_unlock(chan);
5397 ast_channel_lock(chan2);
5402 ast_channel_unlock(chan2);
5406 if (!ast_strlen_zero(context2)) {
5433 static int action_blind_transfer(
struct mansession *s,
const struct message *m)
5440 if (ast_strlen_zero(name)) {
5445 if (ast_strlen_zero(exten)) {
5456 if (ast_strlen_zero(context)) {
5457 context = ast_channel_context(chan);
5479 static int action_atxfer(
struct mansession *s,
const struct message *m)
5485 char feature_code[AST_FEATURE_MAX_LEN];
5488 if (ast_strlen_zero(name)) {
5492 if (ast_strlen_zero(exten)) {
5502 ast_channel_lock(chan);
5503 if (ast_get_builtin_feature(chan,
"atxfer", feature_code,
sizeof(feature_code)) ||
5504 ast_strlen_zero(feature_code)) {
5505 ast_channel_unlock(chan);
5510 ast_channel_unlock(chan);
5512 if (!ast_strlen_zero(context)) {
5516 for (digit = feature_code; *digit; ++digit) {
5517 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
5521 for (digit = exten; *digit; ++digit) {
5522 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
5533 static int action_cancel_atxfer(
struct mansession *s,
const struct message *m)
5540 if (ast_strlen_zero(name)) {
5550 ast_channel_lock(chan);
5551 feature_code = ast_get_chan_features_atxferabort(chan);
5552 ast_channel_unlock(chan);
5554 if (!feature_code) {
5560 for (digit = feature_code; *digit; ++digit) {
5561 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *digit };
5564 ast_free(feature_code);
5574 static int check_blacklist(
const char *cmd)
5576 char *cmd_copy, *cur_cmd;
5577 char *cmd_words[AST_MAX_CMD_LEN] = { NULL, };
5583 if (ast_strlen_zero(cur_cmd)) {
5588 cmd_words[i] = cur_cmd;
5591 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) {
5594 for (j = 0; command_blacklist[i].words[j]; j++) {
5595 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) {
5613 char *buf = NULL, *final_buf = NULL, *delim, *output;
5614 char template[] =
"/tmp/ast-ami-XXXXXX";
5618 if (ast_strlen_zero(cmd)) {
5623 if (check_blacklist(cmd)) {
5628 if ((fd = mkstemp(
template)) < 0) {
5637 if ((len = lseek(fd, 0, SEEK_END)) < 0) {
5638 astman_append(s,
"Message: Failed to determine number of characters: %s\r\n", strerror(errno));
5639 goto action_command_cleanup;
5646 if (!buf || !final_buf) {
5648 goto action_command_cleanup;
5651 if (lseek(fd, 0, SEEK_SET) < 0) {
5652 astman_append(s,
"Message: Failed to set position on temporary file: %s\r\n", strerror(errno));
5653 goto action_command_cleanup;
5656 if (read(fd, buf, len) < 0) {
5657 astman_append(s,
"Message: Failed to read from temporary file: %s\r\n", strerror(errno));
5658 goto action_command_cleanup;
5663 final_buf[len] =
'\0';
5666 if (len && final_buf[len - 1] ==
'\n') {
5667 final_buf[len - 1] =
'\0';
5673 while ((output = strsep(&delim,
"\n"))) {
5677 action_command_cleanup:
5684 ast_free(final_buf);
5720 ao2_cleanup(doomed->
cap);
5726 static void *fast_originate(
void *data)
5734 .uniqueid = in->channelid,
5735 .uniqueid2 = in->otherchannelid
5738 if (!ast_strlen_zero(in->app)) {
5740 in->timeout, in->app, in->appdata, &reason,
5742 S_OR(in->cid_num, NULL),
5743 S_OR(in->cid_name, NULL),
5744 in->vars, in->account, &chan, &assignedids);
5747 in->timeout, in->context, in->exten, in->priority, &reason,
5749 S_OR(in->cid_num, NULL),
5750 S_OR(in->cid_name, NULL),
5751 in->vars, in->account, &chan, in->early_media, &assignedids);
5759 if (!ast_strlen_zero(in->app)) {
5760 ast_manager_event_multichan(EVENT_FLAG_CALL,
"OriginateResponse", chan ? 1 : 0, chans,
5764 "Application: %s\r\n"
5768 "CallerIDNum: %s\r\n"
5769 "CallerIDName: %s\r\n",
5770 in->idtext, res ?
"Failure" :
"Success",
5771 chan ? ast_channel_name(chan) : requested_channel,
5772 in->app, in->appdata, reason,
5773 chan ? ast_channel_uniqueid(chan) :
S_OR(in->channelid,
"<unknown>"),
5774 S_OR(in->cid_num,
"<unknown>"),
5775 S_OR(in->cid_name,
"<unknown>")
5778 ast_manager_event_multichan(EVENT_FLAG_CALL,
"OriginateResponse", chan ? 1 : 0, chans,
5786 "CallerIDNum: %s\r\n"
5787 "CallerIDName: %s\r\n",
5788 in->idtext, res ?
"Failure" :
"Success",
5789 chan ? ast_channel_name(chan) : requested_channel,
5790 in->context, in->exten, reason,
5791 chan ? ast_channel_uniqueid(chan) :
S_OR(in->channelid,
"<unknown>"),
5792 S_OR(in->cid_num,
"<unknown>"),
5793 S_OR(in->cid_name,
"<unknown>")
5799 ast_channel_unlock(chan);
5802 destroy_fast_originate_helper(in);
5806 static int aocmessage_get_unit_entry(
const struct message *m,
struct ast_aoc_unit_entry *
entry,
unsigned int entry_num)
5808 const char *unitamount;
5809 const char *unittype;
5810 struct ast_str *str = ast_str_alloca(32);
5812 memset(entry, 0,
sizeof(*entry));
5814 ast_str_set(&str, 0,
"UnitAmount(%u)", entry_num);
5820 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount,
"%30u", &entry->amount) == 1)) {
5821 entry->valid_amount = 1;
5824 if (!ast_strlen_zero(unittype) && sscanf(unittype,
"%30u", &entry->type) == 1) {
5825 entry->valid_type = 1;
5841 const char *association_num =
astman_get_header(m,
"ChargingAssociationNumber");
5844 enum ast_aoc_type _msgtype;
5845 enum ast_aoc_charge_type _chargetype;
5847 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL;
5849 unsigned int _currencyamount = 0;
5850 int _association_id = 0;
5851 unsigned int _association_plan = 0;
5855 if (ast_strlen_zero(chargetype)) {
5857 goto aocmessage_cleanup;
5860 _msgtype = strcasecmp(msgtype,
"d") ? AST_AOC_E : AST_AOC_D;
5862 if (!strcasecmp(chargetype,
"NA")) {
5863 _chargetype = AST_AOC_CHARGE_NA;
5864 }
else if (!strcasecmp(chargetype,
"Free")) {
5865 _chargetype = AST_AOC_CHARGE_FREE;
5866 }
else if (!strcasecmp(chargetype,
"Currency")) {
5867 _chargetype = AST_AOC_CHARGE_CURRENCY;
5868 }
else if (!strcasecmp(chargetype,
"Unit")) {
5869 _chargetype = AST_AOC_CHARGE_UNIT;
5872 goto aocmessage_cleanup;
5875 if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
5877 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount,
"%30u", &_currencyamount) != 1)) {
5878 astman_send_error(s, m,
"Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency");
5879 goto aocmessage_cleanup;
5882 if (ast_strlen_zero(mult)) {
5883 astman_send_error(s, m,
"ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
5884 goto aocmessage_cleanup;
5885 }
else if (!strcasecmp(mult,
"onethousandth")) {
5886 _mult = AST_AOC_MULT_ONETHOUSANDTH;
5887 }
else if (!strcasecmp(mult,
"onehundredth")) {
5888 _mult = AST_AOC_MULT_ONEHUNDREDTH;
5889 }
else if (!strcasecmp(mult,
"onetenth")) {
5890 _mult = AST_AOC_MULT_ONETENTH;
5891 }
else if (!strcasecmp(mult,
"one")) {
5892 _mult = AST_AOC_MULT_ONE;
5893 }
else if (!strcasecmp(mult,
"ten")) {
5894 _mult = AST_AOC_MULT_TEN;
5895 }
else if (!strcasecmp(mult,
"hundred")) {
5896 _mult = AST_AOC_MULT_HUNDRED;
5897 }
else if (!strcasecmp(mult,
"thousand")) {
5898 _mult = AST_AOC_MULT_THOUSAND;
5901 goto aocmessage_cleanup;
5908 goto aocmessage_cleanup;
5911 if (_msgtype == AST_AOC_D) {
5912 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype,
"subtotal")) {
5913 _totaltype = AST_AOC_SUBTOTAL;
5916 if (ast_strlen_zero(aocbillingid)) {
5918 }
else if (!strcasecmp(aocbillingid,
"Normal")) {
5919 _billingid = AST_AOC_BILLING_NORMAL;
5920 }
else if (!strcasecmp(aocbillingid,
"ReverseCharge")) {
5921 _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
5922 }
else if (!strcasecmp(aocbillingid,
"CreditCard")) {
5923 _billingid = AST_AOC_BILLING_CREDIT_CARD;
5926 goto aocmessage_cleanup;
5929 if (ast_strlen_zero(aocbillingid)) {
5931 }
else if (!strcasecmp(aocbillingid,
"Normal")) {
5932 _billingid = AST_AOC_BILLING_NORMAL;
5933 }
else if (!strcasecmp(aocbillingid,
"ReverseCharge")) {
5934 _billingid = AST_AOC_BILLING_REVERSE_CHARGE;
5935 }
else if (!strcasecmp(aocbillingid,
"CreditCard")) {
5936 _billingid = AST_AOC_BILLING_CREDIT_CARD;
5937 }
else if (!strcasecmp(aocbillingid,
"CallFwdUnconditional")) {
5938 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL;
5939 }
else if (!strcasecmp(aocbillingid,
"CallFwdBusy")) {
5940 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY;
5941 }
else if (!strcasecmp(aocbillingid,
"CallFwdNoReply")) {
5942 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY;
5943 }
else if (!strcasecmp(aocbillingid,
"CallDeflection")) {
5944 _billingid = AST_AOC_BILLING_CALL_DEFLECTION;
5945 }
else if (!strcasecmp(aocbillingid,
"CallTransfer")) {
5946 _billingid = AST_AOC_BILLING_CALL_TRANSFER;
5949 goto aocmessage_cleanup;
5952 if (!ast_strlen_zero(association_id) && (sscanf(association_id,
"%30d", &_association_id) != 1)) {
5954 goto aocmessage_cleanup;
5956 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan,
"%30u", &_association_plan) != 1)) {
5958 goto aocmessage_cleanup;
5961 if (_association_id) {
5963 }
else if (!ast_strlen_zero(association_num)) {
5968 if (_chargetype == AST_AOC_CHARGE_CURRENCY) {
5970 }
else if (_chargetype == AST_AOC_CHARGE_UNIT) {
5975 for (i = 0; i < 32; i++) {
5976 if (aocmessage_get_unit_entry(m, &entry, i)) {
5985 astman_send_error(s, m,
"Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit");
5986 goto aocmessage_cleanup;
6002 static int action_aoc_s_submessage(
struct mansession *s,
const struct message *m,
6008 const char *currencyamount =
__astman_get_header(m,
"CurrencyAmount", GET_HEADER_LAST_MATCH);
6013 const char *granularitytimescale =
__astman_get_header(m,
"GranularityTimeScale", GET_HEADER_LAST_MATCH);
6018 enum ast_aoc_s_charged_item _chargeditem;
6019 enum ast_aoc_s_rate_type _ratetype;
6021 unsigned int _currencyamount = 0;
6023 unsigned int _time = 0;
6024 enum ast_aoc_time_scale _scale = 0;
6025 unsigned int _granularity = 0;
6026 enum ast_aoc_time_scale _granularity_time_scale = AST_AOC_TIME_SCALE_MINUTE;
6028 enum ast_aoc_volume_unit _volumeunit = 0;
6030 if (ast_strlen_zero(chargeditem)) {
6032 goto aocmessage_cleanup;
6035 if (ast_strlen_zero(ratetype)) {
6037 goto aocmessage_cleanup;
6040 if (!strcasecmp(chargeditem,
"NA")) {
6041 _chargeditem = AST_AOC_CHARGED_ITEM_NA;
6042 }
else if (!strcasecmp(chargeditem,
"SpecialArrangement")) {
6043 _chargeditem = AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT;
6044 }
else if (!strcasecmp(chargeditem,
"BasicCommunication")) {
6045 _chargeditem = AST_AOC_CHARGED_ITEM_BASIC_COMMUNICATION;
6046 }
else if (!strcasecmp(chargeditem,
"CallAttempt")) {
6047 _chargeditem = AST_AOC_CHARGED_ITEM_CALL_ATTEMPT;
6048 }
else if (!strcasecmp(chargeditem,
"CallSetup")) {
6049 _chargeditem = AST_AOC_CHARGED_ITEM_CALL_SETUP;
6050 }
else if (!strcasecmp(chargeditem,
"UserUserInfo")) {
6051 _chargeditem = AST_AOC_CHARGED_ITEM_USER_USER_INFO;
6052 }
else if (!strcasecmp(chargeditem,
"SupplementaryService")) {
6053 _chargeditem = AST_AOC_CHARGED_ITEM_SUPPLEMENTARY_SERVICE;
6056 goto aocmessage_cleanup;
6059 if (!strcasecmp(ratetype,
"NA")) {
6060 _ratetype = AST_AOC_RATE_TYPE_NA;
6061 }
else if (!strcasecmp(ratetype,
"Free")) {
6062 _ratetype = AST_AOC_RATE_TYPE_FREE;
6063 }
else if (!strcasecmp(ratetype,
"FreeFromBeginning")) {
6064 _ratetype = AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING;
6065 }
else if (!strcasecmp(ratetype,
"Duration")) {
6066 _ratetype = AST_AOC_RATE_TYPE_DURATION;
6067 }
else if (!strcasecmp(ratetype,
"Flat")) {
6068 _ratetype = AST_AOC_RATE_TYPE_FLAT;
6069 }
else if (!strcasecmp(ratetype,
"Volume")) {
6070 _ratetype = AST_AOC_RATE_TYPE_VOLUME;
6071 }
else if (!strcasecmp(ratetype,
"SpecialCode")) {
6072 _ratetype = AST_AOC_RATE_TYPE_SPECIAL_CODE;
6075 goto aocmessage_cleanup;
6078 if (_ratetype > AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING) {
6079 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount,
"%30u",
6080 &_currencyamount) != 1)) {
6081 astman_send_error(s, m,
"Invalid CurrencyAmount, CurrencyAmount is a required when RateType is non-free");
6082 goto aocmessage_cleanup;
6085 if (ast_strlen_zero(mult)) {
6086 astman_send_error(s, m,
"ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency.");
6087 goto aocmessage_cleanup;
6088 }
else if (!strcasecmp(mult,
"onethousandth")) {
6089 _mult = AST_AOC_MULT_ONETHOUSANDTH;
6090 }
else if (!strcasecmp(mult,
"onehundredth")) {
6091 _mult = AST_AOC_MULT_ONEHUNDREDTH;
6092 }
else if (!strcasecmp(mult,
"onetenth")) {
6093 _mult = AST_AOC_MULT_ONETENTH;
6094 }
else if (!strcasecmp(mult,
"one")) {
6095 _mult = AST_AOC_MULT_ONE;
6096 }
else if (!strcasecmp(mult,
"ten")) {
6097 _mult = AST_AOC_MULT_TEN;
6098 }
else if (!strcasecmp(mult,
"hundred")) {
6099 _mult = AST_AOC_MULT_HUNDRED;
6100 }
else if (!strcasecmp(mult,
"thousand")) {
6101 _mult = AST_AOC_MULT_THOUSAND;
6104 goto aocmessage_cleanup;
6108 if (_ratetype == AST_AOC_RATE_TYPE_DURATION) {
6109 if (ast_strlen_zero(timescale)) {
6110 astman_send_error(s, m,
"TimeScale unspecified, TimeScale is required when RateType is Duration.");
6111 goto aocmessage_cleanup;
6112 }
else if (!strcasecmp(timescale,
"onehundredthsecond")) {
6113 _scale = AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
6114 }
else if (!strcasecmp(timescale,
"onetenthsecond")) {
6115 _scale = AST_AOC_TIME_SCALE_TENTH_SECOND;
6116 }
else if (!strcasecmp(timescale,
"second")) {
6117 _scale = AST_AOC_TIME_SCALE_SECOND;
6118 }
else if (!strcasecmp(timescale,
"tenseconds")) {
6119 _scale = AST_AOC_TIME_SCALE_TEN_SECOND;
6120 }
else if (!strcasecmp(timescale,
"minute")) {
6121 _scale = AST_AOC_TIME_SCALE_MINUTE;
6122 }
else if (!strcasecmp(timescale,
"hour")) {
6123 _scale = AST_AOC_TIME_SCALE_HOUR;
6124 }
else if (!strcasecmp(timescale,
"day")) {
6125 _scale = AST_AOC_TIME_SCALE_DAY;
6128 goto aocmessage_cleanup;
6131 if (ast_strlen_zero(time) || (sscanf(time,
"%30u", &_time) != 1)) {
6132 astman_send_error(s, m,
"Invalid Time, Time is a required when RateType is Duration");
6133 goto aocmessage_cleanup;
6136 if (!ast_strlen_zero(granularity)) {
6137 if ((sscanf(time,
"%30u", &_granularity) != 1)) {
6139 goto aocmessage_cleanup;
6142 if (ast_strlen_zero(granularitytimescale)) {
6143 astman_send_error(s, m,
"Invalid GranularityTimeScale, GranularityTimeScale is a required when Granularity is specified");
6144 }
else if (!strcasecmp(granularitytimescale,
"onehundredthsecond")) {
6145 _granularity_time_scale = AST_AOC_TIME_SCALE_HUNDREDTH_SECOND;
6146 }
else if (!strcasecmp(granularitytimescale,
"onetenthsecond")) {
6147 _granularity_time_scale = AST_AOC_TIME_SCALE_TENTH_SECOND;
6148 }
else if (!strcasecmp(granularitytimescale,
"second")) {
6149 _granularity_time_scale = AST_AOC_TIME_SCALE_SECOND;
6150 }
else if (!strcasecmp(granularitytimescale,
"tenseconds")) {
6151 _granularity_time_scale = AST_AOC_TIME_SCALE_TEN_SECOND;
6152 }
else if (!strcasecmp(granularitytimescale,
"minute")) {
6153 _granularity_time_scale = AST_AOC_TIME_SCALE_MINUTE;
6154 }
else if (!strcasecmp(granularitytimescale,
"hour")) {
6155 _granularity_time_scale = AST_AOC_TIME_SCALE_HOUR;
6156 }
else if (!strcasecmp(granularitytimescale,
"day")) {
6157 _granularity_time_scale = AST_AOC_TIME_SCALE_DAY;
6160 goto aocmessage_cleanup;
6164 if (ast_strlen_zero(chargingtype) || strcasecmp(chargingtype,
"continuouscharging") == 0) {
6166 }
else if (strcasecmp(chargingtype,
"stepfunction") == 0 ) {
6170 goto aocmessage_cleanup;
6174 if (_ratetype == AST_AOC_RATE_TYPE_VOLUME) {
6175 if (ast_strlen_zero(volumeunit)) {
6176 astman_send_error(s, m,
"VolumeUnit unspecified, VolumeUnit is required when RateType is Volume.");
6177 goto aocmessage_cleanup;
6178 }
else if (!strcasecmp(timescale,
"octet")) {
6179 _volumeunit = AST_AOC_VOLUME_UNIT_OCTET;
6180 }
else if (!strcasecmp(timescale,
"segment")) {
6181 _volumeunit = AST_AOC_VOLUME_UNIT_SEGMENT;
6182 }
else if (!strcasecmp(timescale,
"message")) {
6183 _volumeunit = AST_AOC_VOLUME_UNIT_MESSAGE;
6186 goto aocmessage_cleanup;
6190 if (_chargeditem == AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT
6191 || _ratetype == AST_AOC_RATE_TYPE_SPECIAL_CODE) {
6192 if (ast_strlen_zero(code) || (sscanf(code,
"%30u", &_code) != 1)) {
6193 astman_send_error(s, m,
"Invalid Code, Code is a required when ChargedItem is SpecialArrangement and when RateType is SpecialCode");
6194 goto aocmessage_cleanup;
6198 if (_chargeditem == AST_AOC_CHARGED_ITEM_SPECIAL_ARRANGEMENT) {
6200 }
else if (_ratetype == AST_AOC_RATE_TYPE_DURATION) {
6202 currencyname, _time, _scale, _granularity, _granularity_time_scale, _step);
6203 }
else if (_ratetype == AST_AOC_RATE_TYPE_FLAT) {
6206 }
else if (_ratetype == AST_AOC_RATE_TYPE_VOLUME) {
6208 _mult, currencyname);
6209 }
else if (_ratetype == AST_AOC_RATE_TYPE_SPECIAL_CODE) {
6211 }
else if (_ratetype == AST_AOC_RATE_TYPE_FREE) {
6213 }
else if (_ratetype == AST_AOC_RATE_TYPE_FREE_FROM_BEGINNING) {
6215 }
else if (_ratetype == AST_AOC_RATE_TYPE_NA) {
6227 const struct message *m)
6232 static const char hdr[] =
"ChargedItem:";
6233 struct message sm = { 0 };
6238 goto aocmessage_cleanup;
6241 hdrlen = strlen(hdr);
6242 for (x = 0; x < m->hdrcount; x++) {
6243 if (strncasecmp(hdr, m->headers[x], hdrlen) == 0) {
6245 if (action_aoc_s_submessage(s, &sm, decoded) == -1) {
6246 goto aocmessage_cleanup;
6252 sm.headers[sm.hdrcount] = m->headers[x];
6256 if (action_aoc_s_submessage(s, &sm, decoded) == -1) {
6257 goto aocmessage_cleanup;
6269 static int action_aocmessage(
struct mansession *s,
const struct message *m)
6279 size_t encoded_size = 0;
6281 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) {
6282 astman_send_error(s, m,
"Channel and PartialChannel are not specified. Specify at least one of these.");
6283 goto aocmessage_cleanup;
6292 goto aocmessage_cleanup;
6295 if (strcasecmp(msgtype,
"d") == 0 || strcasecmp(msgtype,
"e") == 0) {
6296 decoded = action_aoc_de_message(s, m);
6298 else if (strcasecmp(msgtype,
"s") == 0) {
6299 decoded = action_aoc_s_message(s, m);
6303 goto aocmessage_cleanup;
6307 goto aocmessage_cleanup;
6314 astman_send_error(s, m,
"Error encoding AOC message, could not queue onto channel");
6328 static int action_originate(
struct mansession *s,
const struct message *m)
6351 char *l = NULL, *n = NULL;
6360 int bridge_early = 0;
6373 goto fast_orig_cleanup;
6376 if (ast_strlen_zero(name)) {
6379 goto fast_orig_cleanup;
6381 if (!ast_strlen_zero(priority) && (sscanf(priority,
"%30d", &pi) != 1)) {
6385 goto fast_orig_cleanup;
6388 if (!ast_strlen_zero(timeout) && (sscanf(timeout,
"%30d", &to) != 1)) {
6391 goto fast_orig_cleanup;
6395 data = strchr(tmp,
'/');
6399 goto fast_orig_cleanup;
6405 if (ast_strlen_zero(n)) {
6411 if (ast_strlen_zero(l)) {
6415 if (!ast_strlen_zero(codecs)) {
6420 if (!ast_strlen_zero(app) && s->session) {
6421 int bad_appdata = 0;
6424 if (!(s->session->
writeperm & EVENT_FLAG_SYSTEM)
6426 strcasestr(app,
"system") ||
6428 strcasestr(app,
"exec") ||
6430 strcasestr(app,
"agi") ||
6432 strcasestr(app,
"mixmonitor") ||
6433 strcasestr(app,
"externalivr") ||
6434 strcasestr(app,
"originate") ||
6435 (strstr(appdata,
"SHELL") && (bad_appdata = 1)) ||
6436 (strstr(appdata,
"EVAL") && (bad_appdata = 1))
6439 snprintf(error_buf,
sizeof(error_buf),
"Originate Access Forbidden: %s", bad_appdata ?
"Data" :
"Application");
6442 goto fast_orig_cleanup;
6447 if (exten && context && pi) {
6452 goto fast_orig_cleanup;
6458 if (s->session && s->session->
chanvars) {
6467 for (v = vars; v->
next; v = v->
next );
6473 bridge_early =
ast_true(early_media);
6484 if (!ast_strlen_zero(
id)) {
6502 fast->early_media = bridge_early;
6503 fast->priority = pi;
6504 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) {
6505 destroy_fast_originate_helper(fast);
6511 }
else if (!ast_strlen_zero(app)) {
6514 assignedids.uniqueid ? &assignedids : NULL);
6517 if (exten && context && pi) {
6520 l, n, vars, account, NULL, bridge_early,
6521 assignedids.uniqueid ? &assignedids : NULL , gosub);
6524 astman_send_error(s, m,
"Originate with 'Exten' requires 'Context' and 'Priority'");
6527 goto fast_orig_cleanup;
6541 static int action_mailboxstatus(
struct mansession *s,
const struct message *m)
6546 if (ast_strlen_zero(mailbox)) {
6551 astman_start_ack(s, m);
6554 "Waiting: %d\r\n\r\n", mailbox, ret);
6558 static int action_mailboxcount(
struct mansession *s,
const struct message *m)
6561 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;;
6563 if (ast_strlen_zero(mailbox)) {
6568 astman_start_ack(s, m);
6571 "UrgMessages: %d\r\n"
6572 "NewMessages: %d\r\n"
6573 "OldMessages: %d\r\n"
6575 mailbox, urgentmsgs, newmsgs, oldmsgs);
6579 static int action_extensionstate(
struct mansession *s,
const struct message *m)
6586 if (ast_strlen_zero(exten)) {
6590 if (ast_strlen_zero(context)) {
6591 context =
"default";
6595 ast_get_hint(hint,
sizeof(hint), NULL, 0, NULL, context, exten);
6596 astman_start_ack(s, m);
6602 "StatusText: %s\r\n"
6604 exten, context, hint, status,
6609 static int action_presencestate(
struct mansession *s,
const struct message *m)
6612 enum ast_presence_state
state;
6616 if (ast_strlen_zero(provider)) {
6621 state = ast_presence_state(provider, &subtype, &message);
6622 if (state == AST_PRESENCE_INVALID) {
6627 astman_start_ack(s, m);
6631 if (!ast_strlen_zero(subtype)) {
6635 if (!ast_strlen_zero(message)) {
6641 "PresenceMessage: %s\r\n",
6649 static int action_timeout(
struct mansession *s,
const struct message *m)
6654 struct timeval when = { timeout, 0 };
6656 if (ast_strlen_zero(name)) {
6661 if (!timeout || timeout < 0) {
6671 when.tv_usec = (timeout - when.tv_sec) * 1000000.0;
6673 ast_channel_lock(c);
6675 ast_channel_unlock(c);
6683 static int whitefilter_cmp_fn(
void *obj,
void *arg,
void *data,
int flags)
6685 regex_t *regex_filter = obj;
6686 const char *eventdata = arg;
6689 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
6697 static int blackfilter_cmp_fn(
void *obj,
void *arg,
void *data,
int flags)
6699 regex_t *regex_filter = obj;
6700 const char *eventdata = arg;
6703 if (!regexec(regex_filter, eventdata, 0, NULL, 0)) {
6722 if (!strcasecmp(operation,
"Add")) {
6725 if (res != FILTER_SUCCESS) {
6726 if (res == FILTER_ALLOC_FAILED) {
6729 }
else if (res == FILTER_COMPILE_FAIL) {
6730 astman_send_error(s, m,
"Filter did not compile. Check the syntax of the filter given.");
6769 regex_t *new_filter = ao2_t_alloc(
sizeof(*new_filter), event_filter_destructor,
"event_filter allocation");
6773 return FILTER_ALLOC_FAILED;
6776 if (filter_pattern[0] ==
'!') {
6783 if (regcomp(new_filter, filter_pattern, REG_EXTENDED | REG_NOSUB)) {
6784 ao2_t_ref(new_filter, -1,
"failed to make regex");
6785 return FILTER_COMPILE_FAIL;
6788 if (is_blackfilter) {
6789 ao2_t_link(blackfilters, new_filter,
"link new filter into black user container");
6791 ao2_t_link(whitefilters, new_filter,
"link new filter into white user container");
6796 return FILTER_SUCCESS;
6799 static int match_filter(
struct mansession *s,
char *eventdata)
6803 if (manager_debug) {
6804 ast_verbose(
"<-- Examining AMI event: -->\n%s\n", eventdata);
6806 ast_debug(4,
"Examining AMI event:\n%s\n", eventdata);
6837 ao2_lock(s->session);
6838 if (s->session->
stream != NULL) {
6839 struct eventqent *eqe = s->session->
last_ev;
6841 while ((eqe = advance_event(eqe))) {
6843 ast_debug(3,
"Received CloseSession event\n");
6847 (s->session->
readperm & eqe->category) == eqe->category &&
6848 (s->session->
send_events & eqe->category) == eqe->category) {
6849 if (match_filter(s, eqe->eventdata)) {
6850 if (
send_string(s, eqe->eventdata) < 0 || s->write_error)
6857 ao2_unlock(s->session);
6861 static int action_userevent(
struct mansession *s,
const struct message *m)
6869 for (x = 0; x < m->hdrcount; x++) {
6870 if (strncasecmp(
"UserEvent:", m->headers[x], strlen(
"UserEvent:")) &&
6871 strncasecmp(
"Action:", m->headers[x], strlen(
"Action:"))) {
6887 if (!ast_strlen_zero(actionid)) {
6888 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n", actionid);
6895 "AMIversion: %s\r\n"
6896 "AsteriskVersion: %s\r\n"
6897 "SystemName: %s\r\n"
6898 "CoreMaxCalls: %d\r\n"
6899 "CoreMaxLoadAvg: %f\r\n"
6900 "CoreRunUser: %s\r\n"
6901 "CoreRunGroup: %s\r\n"
6902 "CoreMaxFilehandles: %d\r\n"
6903 "CoreRealTimeEnabled: %s\r\n"
6904 "CoreCDRenabled: %s\r\n"
6905 "CoreHTTPenabled: %s\r\n"
6906 "SoundsSearchCustomDir: %s\r\n"
6911 ast_config_AST_SYSTEM_NAME,
6914 ast_config_AST_RUN_USER,
6915 ast_config_AST_RUN_GROUP,
6930 char startuptime[150], startupdate[150];
6931 char reloadtime[150], reloaddate[150];
6934 if (!ast_strlen_zero(actionid)) {
6935 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n", actionid);
6941 ast_strftime(startuptime,
sizeof(startuptime),
"%H:%M:%S", &tm);
6942 ast_strftime(startupdate,
sizeof(startupdate),
"%Y-%m-%d", &tm);
6944 ast_strftime(reloadtime,
sizeof(reloadtime),
"%H:%M:%S", &tm);
6945 ast_strftime(reloaddate,
sizeof(reloaddate),
"%Y-%m-%d", &tm);
6949 "CoreStartupDate: %s\r\n"
6950 "CoreStartupTime: %s\r\n"
6951 "CoreReloadDate: %s\r\n"
6952 "CoreReloadTime: %s\r\n"
6953 "CoreCurrentCalls: %d\r\n"
7007 if (!ast_strlen_zero(actionid)) {
7008 snprintf(idText,
sizeof(idText),
"ActionID: %s\r\n", actionid);
7018 for (; (cs = ao2_iterator_next(&it_chans));
ao2_ref(cs, -1)) {
7020 char durbuf[16] =
"";
7027 int duration, durh, durm, durs;
7030 durh = duration / 3600;
7031 durm = (duration % 3600) / 60;
7032 durs = duration % 60;
7033 snprintf(durbuf,
sizeof(durbuf),
"%02d:%02d:%02d", durh, durm, durs);
7037 "Event: CoreShowChannel\r\n"
7040 "Application: %s\r\n"
7041 "ApplicationData: %s\r\n"
7058 astman_send_list_complete(s, m,
"CoreShowChannelsComplete", numchans);
7071 ast_log(LOG_ERROR,
"Unable to append channel to channel map\n");
7087 char *current_channel_uid;
7090 while ((current_channel_uid = ao2_iterator_next(&iter))) {
7092 int add_channel_res;
7096 if (!strcmp(current_channel_uid, channel_snapshot->
base->
uniqueid)) {
7097 ao2_ref(current_channel_uid, -1);
7102 if (!current_channel_snapshot) {
7103 ast_debug(5,
"Unable to get channel snapshot\n");
7104 ao2_ref(current_channel_uid, -1);
7109 if (add_channel_res) {
7111 ao2_ref(current_channel_snapshot, -1);
7112 ao2_ref(current_channel_uid, -1);
7120 int size = strlen(current_channel_snapshot->
base->
name);
7121 char other_local[size + 1];
7126 other_local[size] =
'\0';
7129 if (!other_local_snapshot) {
7130 ast_debug(5,
"Unable to get other local channel snapshot\n");
7131 ao2_ref(current_channel_snapshot, -1);
7132 ao2_ref(current_channel_uid, -1);
7138 ao2_ref(current_channel_snapshot, -1);
7139 ao2_ref(current_channel_uid, -1);
7140 ao2_ref(other_local_snapshot, -1);
7145 if (other_bridge_snapshot) {
7149 ao2_ref(current_channel_snapshot, -1);
7150 ao2_ref(current_channel_uid, -1);
7151 ao2_ref(other_local_snapshot, -1);
7152 ao2_ref(other_bridge_snapshot, -1);
7170 char *current_channel_name;
7178 if (!ast_strlen_zero(actionid)) {
7179 snprintf(id_text,
sizeof(id_text),
"ActionID: %s\r\n", actionid);
7184 if (ast_strlen_zero(channel_name)) {
7190 if (!channel_snapshot) {
7196 if (!bridge_snapshot) {
7218 while ((current_channel_name = ao2_iterator_next(&i))) {
7220 "Event: CoreShowChannelMap\r\n"
7223 "ConnectedChannel: %s\r\n\r\n",
7226 current_channel_name);
7257 ast_debug(1,
"**** ModuleCheck .so file %s\n", module);
7265 if (!ast_strlen_zero(
id)) {
7269 #if !defined(LOW_MEMORY)
7281 static int manager_moduleload(
struct mansession *s,
const struct message *m)
7288 if (!loadtype || strlen(loadtype) == 0) {
7291 if ((!module || strlen(module) == 0) && strcasecmp(loadtype,
"reload") != 0) {
7295 if (!strcasecmp(loadtype,
"load")) {
7302 }
else if (!strcasecmp(loadtype,
"unload")) {
7309 }
else if (!strcasecmp(loadtype,
"refresh")) {
7316 }
else if (!strcasecmp(loadtype,
"reload")) {
7318 if (!ast_strlen_zero(module)) {
7321 switch (reload_res) {
7352 static void log_action(
const struct message *m,
const char *action)
7357 if (!manager_debug) {
7366 for (x = 0; x < m->hdrcount; ++x) {
7367 if (!strncasecmp(m->headers[x],
"Secret", 6)) {
7374 ast_verbose(
"<--- Examining AMI action: -->\n%s\n",
ast_str_buffer(buf));
7394 struct manager_action *act_found;
7395 struct ast_manager_user *user = NULL;
7396 const char *username;
7400 if (ast_strlen_zero(action)) {
7401 report_req_bad_format(s,
"NONE");
7408 log_action(m, action);
7411 ast_log(LOG_ERROR,
"Unable to process manager action '%s'. Asterisk is shutting down.\n", action);
7419 && strcasecmp(action,
"Login")
7420 && strcasecmp(action,
"Logoff")
7421 && strcasecmp(action,
"Challenge")) {
7423 report_req_not_allowed(s, action);
7432 && (!strcasecmp(action,
"Login")
7433 || !strcasecmp(action,
"Challenge"))) {
7436 if (!ast_strlen_zero(username) && check_manager_session_inuse(username)) {
7441 report_session_limit(s);
7452 act_found = action_find(action);
7461 ao2_lock(act_found);
7465 ao2_unlock(act_found);
7466 if (mod_ref || !act_found->
module) {
7468 ret = act_found->
func(s, m);
7473 ao2_unlock(act_found);
7482 report_req_not_allowed(s, action);
7487 ao2_t_ref(act_found, -1,
"done with found action object");
7491 report_req_bad_format(s, action);
7492 snprintf(buf,
sizeof(buf),
"Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
7522 int maxlen =
sizeof(s->session->
inbuf) - 1;
7523 char *src = s->session->
inbuf;
7531 for (x = 0; x < s->session->
inlen; x++) {
7533 if (src[x] ==
'\r' && x+1 < s->session->
inlen && src[x + 1] ==
'\n') {
7535 }
else if (src[x] ==
'\n') {
7540 memmove(output, src, x);
7543 s->session->
inlen -= x;
7544 memmove(src, src + x, s->session->
inlen);
7547 if (s->session->
inlen >= maxlen) {
7551 src[0] = src[s->session->
inlen - 1];
7552 s->session->
inlen = 1;
7553 s->parsing = MESSAGE_LINE_TOO_LONG;
7559 if(time(&now) == -1) {
7560 ast_log(LOG_ERROR,
"error executing time(): %s\n", strerror(errno));
7564 timeout = (authtimeout - (now - s->session->authstart)) * 1000;
7587 if (s->session->
kicked) {
7588 ast_debug(1,
"Manager session has been kicked\n");
7594 if (errno == EINTR || errno == EAGAIN) {
7597 ast_log(LOG_WARNING,
"poll() returned error: %s\n", strerror(errno));
7601 ao2_lock(s->session);
7606 s->session->
inlen += res;
7607 src[s->session->
inlen] =
'\0';
7610 ao2_unlock(s->session);
7623 static void handle_parse_error(
struct mansession *s,
struct message *m,
char *error)
7627 s->parsing = MESSAGE_OKAY;
7642 struct message m = { 0 };
7643 char header_buf[
sizeof(s->session->
inbuf)] = {
'\0' };
7659 if (time(&now) == -1) {
7660 ast_log(LOG_ERROR,
"error executing time(): %s\n", strerror(errno));
7665 if (now - s->session->authstart > authtimeout) {
7666 if (displayconnects) {
7674 }
else if (res > 0) {
7676 if (ast_strlen_zero(header_buf)) {
7683 switch (s->parsing) {
7687 case MESSAGE_LINE_TOO_LONG:
7688 handle_parse_error(s, &m,
"Failed to parse message: line too long");
7694 }
else if (m.hdrcount < ARRAY_LEN(m.headers)) {
7695 m.headers[m.hdrcount] =
ast_strdup(header_buf);
7696 if (!m.headers[m.hdrcount]) {
7730 .tcptls_session = data,
7744 if (session == NULL) {
7753 ast_log(LOG_WARNING,
"Failed to set TCP_NODELAY on manager connection: %s\n", strerror(errno));
7761 ast_mutex_init(&s.lock);
7766 s.session = session;
7770 if(time(&session->authstart) == -1) {
7771 ast_log(LOG_ERROR,
"error executing time(): %s; disconnecting client\n", strerror(errno));
7773 ao2_unlock(session);
7774 session_destroy(session);
7777 ao2_unlock(session);
7788 astman_append(&s,
"Asterisk Call Manager/%s\r\n", AMI_VERSION);
7790 if ((res = do_message(&s)) < 0 || s.write_error || session->
kicked) {
7804 if (displayconnects) {
7809 session_destroy(session);
7811 ast_mutex_destroy(&s.lock);
7823 time_t now = time(NULL);
7833 while ((session = ao2_iterator_next(&i)) && n_max > 0) {
7837 && VERBOSITY_ATLEAST(2)
7839 ast_verb(2,
"HTTP Manager '%s' timed out from %s\n",
7842 ao2_unlock(session);
7843 session_destroy(session);
7847 ao2_unlock(session);
7861 struct eventqent *tmp =
ast_malloc(
sizeof(*tmp) + strlen(str));
7870 tmp->category = category;
7873 AST_RWLIST_NEXT(tmp, eq_next) = NULL;
7874 strcpy(tmp->eventdata, str);
7877 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next);
7894 ast_str_append(pbuf, 0,
"ChanVariable(%s): %s=%s\r\n", ast_channel_name(chan), var->name, var->value);
7901 #define MANAGER_EVENT_BUF_INITSIZE 256
7903 static int __attribute__((format(printf, 9, 0))) __manager_event_sessions_va(
7916 const char *cat_str;
7921 if (!ast_strlen_zero(manager_disabledevents)) {
7923 ast_debug(3,
"AMI Event '%s' is globally disabled, skipping\n", event);
7937 "Privilege: %s\r\n",
7940 if (timestampevents) {
7943 "Timestamp: %ld.%06lu\r\n",
7944 (
long)now.tv_sec, (
unsigned long) now.tv_usec);
7946 if (manager_debug) {
7950 "SequenceNumber: %d\r\n",
7958 if (!ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
7960 "SystemName: %s\r\n",
7961 ast_config_AST_SYSTEM_NAME);
7965 for (i = 0; i < chancount; i++) {
7966 append_channel_vars(&buf, chans[i]);
7979 while ((session = ao2_iterator_next(&iter))) {
7998 struct manager_custom_hook *hook;
8001 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) {
8010 static int __attribute__((format(printf, 9, 0))) __manager_event_sessions(
8026 res = __manager_event_sessions_va(sessions, category, event, chancount, chans,
8027 file, line, func, fmt, ap);
8033 struct ast_channel **chans,
const char *file,
int line,
const char *func,
8034 const char *fmt, ...)
8040 if (!any_manager_listeners(sessions)) {
8042 ao2_cleanup(sessions);
8047 res = __manager_event_sessions_va(sessions, category, event, chancount, chans,
8048 file, line, func, fmt, ap);
8050 ao2_cleanup(sessions);
8059 struct manager_action *cur;
8062 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) {
8063 if (!strcasecmp(action, cur->
action)) {
8064 AST_RWLIST_REMOVE_CURRENT(list);
8068 AST_RWLIST_TRAVERSE_SAFE_END;
8080 ao2_t_ref(cur, -1,
"action object removed from list");
8081 ast_verb(5,
"Manager unregistered action %s\n", action);
8087 static int manager_state_cb(
const char *context,
const char *exten,
struct ast_state_cb_info *info,
void *data)
8093 ast_get_hint(hint,
sizeof(hint), NULL, 0, NULL, context, exten);
8095 switch(info->reason) {
8102 "StatusText: %s\r\n",
8121 info->presence_subtype,
8122 info->presence_message);
8128 static int ast_manager_register_struct(
struct manager_action *act)
8130 struct manager_action *cur, *
prev = NULL;
8133 AST_RWLIST_TRAVERSE(&actions, cur, list) {
8138 ast_log(LOG_WARNING,
"Manager: Action '%s' already registered\n", act->
action);
8148 ao2_t_ref(act, +1,
"action object added to list");
8151 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list);
8153 AST_RWLIST_INSERT_HEAD(&actions, act, list);
8156 ast_verb(5,
"Manager registered action %s\n", act->
action);
8169 static void action_destroy(
void *obj)
8171 struct manager_action *doomed = obj;
8185 struct manager_action *cur;
8187 cur = ao2_t_alloc(
sizeof(*cur), action_destroy, action);
8192 ao2_t_ref(cur, -1,
"action object creation failed");
8201 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
8237 if (ast_manager_register_struct(cur)) {
8238 ao2_t_ref(cur, -1,
"action object registration failed");
8242 ao2_t_ref(cur, -1,
"action object registration successful");
8260 enum output_format {
8266 static const char *
const contenttype[] = {
8267 [FORMAT_RAW] =
"plain",
8268 [FORMAT_HTML] =
"html",
8269 [FORMAT_XML] =
"xml",
8293 while ((session = ao2_iterator_next(&i))) {
8299 ao2_unlock(session);
8322 if (nonce == 0 || username == NULL || stale == NULL) {
8332 while ((session = ao2_iterator_next(&i))) {
8337 }
else if (!strcasecmp(session->
username, username) && session->
oldnonce == nonce) {
8341 ao2_unlock(session);
8359 ao2_unlock(session);
8382 while ((session = ao2_iterator_next(&i))) {
8386 ao2_unlock(session);
8390 ao2_unlock(session);
8415 while ((session = ao2_iterator_next(&i))) {
8419 ao2_unlock(session);
8423 ao2_unlock(session);
8436 static void xml_copy_escape(
struct ast_str **out,
const char *src,
int mode)
8441 const char *save = src;
8442 int space =
sizeof(buf);
8444 for ( ; *src || dst != buf ; src++) {
8445 if (*src ==
'\0' || space < 10) {
8449 space =
sizeof(buf);
8456 if (save == src && isdigit(*src)) {
8462 }
else if (!isalnum(*src)) {
8471 strcpy(dst,
"<");
8476 strcpy(dst,
">");
8481 strcpy(dst,
""");
8486 strcpy(dst,
"'");
8491 strcpy(dst,
"&");
8497 *dst++ = mode ? tolower(*src) : *src;
8508 static int variable_count_hash_fn(
const void *vvc,
const int flags)
8515 static int variable_count_cmp_fn(
void *obj,
void *vstr,
int flags)
8557 const char *dest = NULL;
8559 const char *objtype = NULL;
8562 int xml = (format == FORMAT_XML);
8568 for (v = get_vars; v; v = v->
next) {
8569 if (!strcasecmp(v->
name,
"ajaxdest")) {
8571 }
else if (!strcasecmp(v->
name,
"ajaxobjtype")) {
8575 if (ast_strlen_zero(dest)) {
8578 if (ast_strlen_zero(objtype)) {
8579 objtype =
"generic";
8585 val = strsep(&in,
"\r\n");
8586 if (in && *in ==
'\n') {
8590 ast_debug(5,
"inobj %d in_data %d line <%s>\n", inobj, in_data, val);
8591 if (ast_strlen_zero(val)) {
8602 "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
8613 ast_str_append(out, 0,
"<response type='object' id='%s'><%s", dest, objtype);
8616 variable_count_hash_fn, NULL, variable_count_cmp_fn);
8624 xml_copy_escape(out, val, 0);
8629 var = strsep(&val,
":");
8637 var =
"Opaque-data";
8643 if ((vc = ao2_find(vco, var, 0))) {
8647 vc = ao2_alloc(
sizeof(*vc), NULL);
8653 xml_copy_escape(out, var, xml ? 1 | 2 : 0);
8654 if (vc->count > 1) {
8659 xml_copy_escape(out, val, 0);
8660 if (!in_data || !*in) {
8667 "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
8672 static void close_mansession_file(
struct mansession *s)
8678 ast_log(LOG_ERROR,
"Attempted to close file/file descriptor on mansession without a valid file or file descriptor.\n");
8696 l = lseek(fd, 0, SEEK_CUR);
8698 if (MAP_FAILED == (buf = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0))) {
8699 ast_log(LOG_WARNING,
"mmap failed. Manager output was not processed\n");
8701 if (format == FORMAT_XML || format == FORMAT_HTML) {
8708 }
else if (format == FORMAT_XML || format == FORMAT_HTML) {
8712 close_mansession_file(s);
8717 enum output_format format,
8718 const struct ast_sockaddr *remote_address,
const char *uri,
8722 struct mansession s = { .session = NULL, .tcptls_session = ser };
8728 char template[] =
"/tmp/ast-http-XXXXXX";
8729 struct ast_str *http_header = NULL, *out = NULL;
8730 struct message m = { 0 };
8732 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
8733 ast_http_error(ser, 501,
"Not Implemented",
"Attempt to use unimplemented / unsupported method");
8747 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (out of memory)");
8759 while ((session->
managerid = ast_random() ^ (
unsigned long) session) == 0) {
8764 ao2_unlock(session);
8769 ast_mutex_init(&s.lock);
8771 if (http_header == NULL || out == NULL) {
8773 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (ast_str_create() out of memory)");
8774 goto generic_callback_out;
8777 s.session = session;
8778 fd = mkstemp(
template);
8781 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (mkstemp failed)");
8782 goto generic_callback_out;
8786 ast_log(LOG_WARNING,
"HTTP Manager, fdopen failed: %s!\n", strerror(errno));
8787 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (fdopen failed)");
8789 goto generic_callback_out;
8792 if (method == AST_HTTP_POST) {
8797 ast_http_error(ser, 413,
"Request Entity Too Large",
"Body too large");
8798 close_mansession_file(&s);
8799 goto generic_callback_out;
8803 close_mansession_file(&s);
8804 goto generic_callback_out;
8806 ast_http_error(ser, 400,
"Bad Request",
"Error parsing request body");
8807 close_mansession_file(&s);
8808 goto generic_callback_out;
8821 if (displayconnects) {
8831 "Content-type: text/%s\r\n"
8832 "Set-Cookie: mansession_id=\"%08x\"; Version=1; Max-Age=%d\r\n"
8833 "Pragma: SuppressEvents\r\n",
8834 contenttype[format],
8837 if (format == FORMAT_XML) {
8839 }
else if (format == FORMAT_HTML) {
8846 #define ROW_FMT "<tr><td colspan=\"2\" bgcolor=\"#f1f1ff\">%s</td></tr>\r\n"
8847 #define TEST_STRING \
8848 "<form action=\"manager\" method=\"post\">\n\
8849 Action: <select name=\"action\">\n\
8850 <option value=\"\">-----></option>\n\
8851 <option value=\"login\">login</option>\n\
8852 <option value=\"command\">Command</option>\n\
8853 <option value=\"waitevent\">waitevent</option>\n\
8854 <option value=\"listcommands\">listcommands</option>\n\
8856 or <input name=\"action\"><br/>\n\
8857 CLI Command <input name=\"command\"><br>\n\
8858 user <input name=\"username\"> pass <input type=\"password\" name=\"secret\"><br>\n\
8859 <input type=\"submit\">\n</form>\n"
8861 ast_str_append(&out, 0,
"<title>Asterisk™ Manager Interface</title>");
8862 ast_str_append(&out, 0,
"<body bgcolor=\"#ffffff\"><table align=center bgcolor=\"#f1f1f1\" width=\"500\">\r\n");
8867 process_output(&s, &out, params, format);
8869 if (format == FORMAT_XML) {
8871 }
else if (format == FORMAT_HTML) {
8880 if (session->
inuse == 1) {
8881 ast_debug(1,
"Need destroy, doing it now!\n");
8884 ast_debug(1,
"Need destroy, but can't do it yet!\n");
8895 ao2_unlock(session);
8897 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
8901 generic_callback_out:
8902 ast_mutex_destroy(&s.lock);
8906 if (method == AST_HTTP_POST && params) {
8909 ast_free(http_header);
8914 session_destroy(session);
8929 enum output_format format,
8930 const struct ast_sockaddr *remote_address,
const char *uri,
8935 struct mansession s = { .session = NULL, .tcptls_session = ser };
8937 char template[] =
"/tmp/ast-http-XXXXXX";
8938 struct ast_str *http_header = NULL, *out = NULL;
8940 struct message m = { 0 };
8943 time_t time_now = time(NULL);
8944 unsigned long nonce = 0, nc;
8946 struct ast_manager_user *user = NULL;
8948 char resp_hash[256]=
"";
8950 char u_username[80];
8954 int u_displayconnects;
8956 if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
8957 ast_http_error(ser, 501,
"Not Implemented",
"Attempt to use unimplemented / unsupported method");
8962 for (v = headers; v; v = v->
next) {
8963 if (!strcasecmp(v->
name,
"Authorization")) {
8968 if (!v || ast_strlen_zero(v->
value)) {
8975 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (out of memory)");
8984 if (sscanf(d.nonce,
"%30lx", &nonce) != 1) {
8985 ast_log(LOG_WARNING,
"Received incorrect nonce in Digest <%s>\n", d.nonce);
9004 ast_http_error(ser, 403,
"Permission denied",
"Permission denied");
9021 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (out of memory)");
9030 snprintf(resp,
sizeof(resp),
"%s:%08lx:%s:%s:auth:%s", user->
a1_hash, nonce, d.nc, d.cnonce, a2_hash);
9033 snprintf(resp,
sizeof(resp),
"%s:%08lx:%s", user->
a1_hash, nonce, a2_hash);
9038 if (strncasecmp(d.response, resp_hash, strlen(resp_hash))) {
9063 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (out of memory)");
9077 if (u_displayconnects) {
9096 ao2_unlock(session);
9100 sscanf(d.nc,
"%30lx", &nc);
9101 if (session->
nc >= nc || ((time_now - session->
noncetime) > 62) ) {
9111 nonce = session->
managerid = ast_random();
9113 ao2_unlock(session);
9123 session->
sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5);
9124 ao2_unlock(session);
9126 ast_mutex_init(&s.lock);
9127 s.session = session;
9128 fd = mkstemp(
template);
9131 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (mkstemp failed)");
9132 goto auth_callback_out;
9136 ast_log(LOG_WARNING,
"HTTP Manager, fdopen failed: %s!\n", strerror(errno));
9137 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (fdopen failed)");
9139 goto auth_callback_out;
9142 if (method == AST_HTTP_POST) {
9147 ast_http_error(ser, 413,
"Request Entity Too Large",
"Body too large");
9148 close_mansession_file(&s);
9149 goto auth_callback_out;
9153 close_mansession_file(&s);
9154 goto auth_callback_out;
9156 ast_http_error(ser, 400,
"Bad Request",
"Error parsing request body");
9157 close_mansession_file(&s);
9158 goto auth_callback_out;
9166 if (u_displayconnects) {
9179 if (http_header == NULL || out == NULL) {
9181 ast_http_error(ser, 500,
"Server Error",
"Internal Server Error (ast_str_create() out of memory)");
9182 close_mansession_file(&s);
9183 goto auth_callback_out;
9186 ast_str_append(&http_header, 0,
"Content-type: text/%s\r\n", contenttype[format]);
9188 if (format == FORMAT_XML) {
9190 }
else if (format == FORMAT_HTML) {
9192 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
9194 "<title>Asterisk™ Manager Interface</title>\r\n"
9195 "</head><body style=\"background-color: #ffffff;\">\r\n"
9196 "<form method=\"POST\">\r\n"
9197 "<table align=\"center\" style=\"background-color: #f1f1f1;\" width=\"500\">\r\n"
9198 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\"><h1>Manager Tester</h1></th></tr>\r\n"
9199 "<tr><th colspan=\"2\" style=\"background-color: #f1f1ff;\">Action: <input name=\"action\" /> Cmd: <input name=\"command\" /><br>"
9200 "<input type=\"submit\" value=\"Send request\" /></th></tr>\r\n");
9203 process_output(&s, &out, params, format);
9205 if (format == FORMAT_XML) {
9207 }
else if (format == FORMAT_HTML) {
9211 ast_http_send(ser, method, 200, NULL, http_header, out, 0, 0);
9216 ast_mutex_destroy(&s.lock);
9219 if (method == AST_HTTP_POST && params) {
9223 ast_free(http_header);
9231 ao2_unlock(session);
9234 ast_debug(1,
"Need destroy, doing it now!\n");
9235 session_destroy(session);
9242 nonce = ast_random();
9245 ast_http_auth(ser, global_realm, nonce, nonce, stale, NULL);
9256 retval =
generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
9267 retval =
generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
9278 retval =
generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
9284 .description =
"Raw HTTP Manager Event Interface",
9286 .callback = rawman_http_callback,
9292 .description =
"HTML Manager Event Interface",
9294 .callback = manager_http_callback,
9300 .description =
"XML Manager Event Interface",
9302 .callback = mxml_http_callback,
9315 retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
9326 retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
9337 retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
9343 .description =
"Raw HTTP Manager Event Interface w/Digest authentication",
9346 .callback = auth_rawman_http_callback,
9352 .description =
"HTML Manager Event Interface w/Digest authentication",
9355 .callback = auth_manager_http_callback,
9361 .description =
"XML Manager Event Interface w/Digest authentication",
9364 .callback = auth_mxml_http_callback,
9373 const char *login = (
char *)arg;
9374 int *no_sessions = data;
9376 if (strcasecmp(session->
username, login) == 0) {
9387 struct ast_manager_user *user = NULL;
9395 if (ast_strlen_zero(data) ) {
9396 ast_log(LOG_WARNING,
"AMI_CLIENT() requires two arguments: AMI_CLIENT(<name>[,<arg>])\n");
9406 ast_log(LOG_ERROR,
"There's no manager user called : \"%s\"\n", args.name);
9411 if (!strcasecmp(args.param,
"sessions")) {
9412 int no_sessions = 0;
9420 snprintf(buf, len,
"%d", no_sessions);
9422 ast_log(LOG_ERROR,
"Invalid arguments provided to function AMI_CLIENT: %s\n", args.param);
9433 .
name =
"AMI_CLIENT",
9438 static int webregged = 0;
9452 ser->poll_timeout = 1;
9454 ser->poll_timeout = 5000;
9462 .master = AST_PTHREADT_NULL,
9464 .poll_timeout = 5000,
9466 .name =
"AMI server",
9467 .accept_fn = ast_tcptls_server_root,
9473 .master = AST_PTHREADT_NULL,
9474 .tls_cfg = &ami_tls_cfg,
9476 .name =
"AMI TLS server",
9477 .accept_fn = ast_tcptls_server_root,
9486 e->
command =
"manager show settings";
9488 "Usage: manager show settings\n"
9489 " Provides detailed list of the configuration of the Manager.\n";
9494 #define FORMAT " %-25.25s %-15.55s\n"
9495 #define FORMAT2 " %-25.25s %-15d\n"
9496 #define FORMAT3 " %-25.25s %s\n"
9498 return CLI_SHOWUSAGE;
9500 ast_cli(a->fd,
"\nGlobal Settings:\n");
9501 ast_cli(a->fd,
"----------------\n");
9502 ast_cli(a->fd, FORMAT,
"Manager (AMI):",
AST_CLI_YESNO(manager_enabled));
9503 ast_cli(a->fd, FORMAT,
"Web Manager (AMI/HTTP):",
AST_CLI_YESNO(webmanager_enabled));
9504 ast_cli(a->fd, FORMAT,
"TCP Bindaddress:", manager_enabled != 0 ?
ast_sockaddr_stringify(&ami_desc.local_address) :
"Disabled");
9505 ast_cli(a->fd, FORMAT2,
"HTTP Timeout (seconds):", httptimeout);
9506 ast_cli(a->fd, FORMAT,
"TLS Enable:",
AST_CLI_YESNO(ami_tls_cfg.enabled));
9507 ast_cli(a->fd, FORMAT,
"TLS Bindaddress:", ami_tls_cfg.enabled != 0 ?
ast_sockaddr_stringify(&amis_desc.local_address) :
"Disabled");
9508 ast_cli(a->fd, FORMAT,
"TLS Certfile:", ami_tls_cfg.certfile);
9509 ast_cli(a->fd, FORMAT,
"TLS Privatekey:", ami_tls_cfg.pvtfile);
9510 ast_cli(a->fd, FORMAT,
"TLS Cipher:", ami_tls_cfg.cipher);
9511 ast_cli(a->fd, FORMAT,
"Allow multiple login:",
AST_CLI_YESNO(allowmultiplelogin));
9512 ast_cli(a->fd, FORMAT,
"Display connects:",
AST_CLI_YESNO(displayconnects));
9513 ast_cli(a->fd, FORMAT,
"Timestamp events:",
AST_CLI_YESNO(timestampevents));
9514 ast_cli(a->fd, FORMAT3,
"Channel vars:",
S_OR(manager_channelvars,
""));
9515 ast_cli(a->fd, FORMAT3,
"Disabled events:",
S_OR(manager_disabledevents,
""));
9516 ast_cli(a->fd, FORMAT,
"Debug:",
AST_CLI_YESNO(manager_debug));
9526 static int ast_xml_doc_item_cmp_fn(
const void *a,
const void *b)
9530 return strcmp((*item_a)->name, (*item_b)->name);
9540 int i = 0, totalitems = 0;
9544 e->
command =
"manager show events";
9546 "Usage: manager show events\n"
9547 " Prints a listing of the available Asterisk manager interface events.\n";
9553 return CLI_SHOWUSAGE;
9563 ast_cli(a->fd,
"No manager event documentation loaded\n");
9571 ast_log(AST_LOG_ERROR,
"Unable to create iterator for events container\n");
9578 ast_log(AST_LOG_ERROR,
"Unable to create temporary sorting array for events\n");
9586 while ((item = ao2_iterator_next(it_events))) {
9587 items[totalitems++] = item;
9591 qsort(items, totalitems,
sizeof(
struct ast_xml_doc_item *), ast_xml_doc_item_cmp_fn);
9593 ast_cli(a->fd,
"Events:\n");
9594 ast_cli(a->fd,
" -------------------- -------------------- -------------------- \n");
9595 for (i = 0; i < totalitems; i++) {
9597 if ((i + 1) % 3 == 0) {
9602 if ((i + 1) % 3 != 0) {
9616 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
9618 term_color(synopsis_title,
"[Synopsis]\n", COLOR_MAGENTA, 0, 40);
9619 term_color(description_title,
"[Description]\n", COLOR_MAGENTA, 0, 40);
9620 term_color(syntax_title,
"[Syntax]\n", COLOR_MAGENTA, 0, 40);
9621 term_color(seealso_title,
"[See Also]\n", COLOR_MAGENTA, 0, 40);
9622 term_color(arguments_title,
"[Arguments]\n", COLOR_MAGENTA, 0, 40);
9626 ast_cli(a->fd,
"%s%s\n\n", synopsis_title, synopsis);
9631 ast_cli(a->fd,
"%s%s\n\n", syntax_title, syntax);
9636 ast_cli(a->fd,
"%s%s\n\n", description_title, description);
9637 ast_free(description);
9641 ast_cli(a->fd,
"%s%s\n\n", arguments_title, arguments);
9642 ast_free(arguments);
9646 ast_cli(a->fd,
"%s%s\n\n", seealso_title, seealso);
9658 if (cmd == CLI_INIT) {
9659 e->
command =
"manager show event";
9661 "Usage: manager show event <eventname>\n"
9662 " Provides a detailed description a Manager interface event.\n";
9668 ast_cli(a->fd,
"No manager event documentation loaded\n");
9672 if (cmd == CLI_GENERATE) {
9677 length = strlen(a->word);
9679 while ((item = ao2_iterator_next(&it_events))) {
9680 if (!strncasecmp(a->word, item->
name, length)) {
9694 return CLI_SHOWUSAGE;
9697 if (!(item = ao2_find(events, a->argv[3],
OBJ_KEY))) {
9698 ast_cli(a->fd,
"Could not find event '%s'\n", a->argv[3]);
9702 ast_cli(a->fd,
"Event: %s\n", a->argv[3]);
9704 print_event_instance(a, temp);
9714 AST_CLI_DEFINE(handle_showmancmd,
"Show a manager interface command"),
9719 AST_CLI_DEFINE(handle_showmanagers,
"List configured manager users"),
9720 AST_CLI_DEFINE(handle_showmanager,
"Display information on a specific manager user"),
9721 AST_CLI_DEFINE(handle_mandebug,
"Show, enable, disable debugging of the manager code"),
9725 AST_CLI_DEFINE(handle_manager_show_events,
"List manager interface events"),
9726 AST_CLI_DEFINE(handle_manager_show_event,
"Show a manager interface event"),
9743 ast_free(manager_channelvars);
9759 static void load_disabledevents(
struct ast_variable *var)
9761 ast_free(manager_disabledevents);
9769 static void manager_free_user(
struct ast_manager_user *user)
9774 ao2_t_ref(user->
whitefilters, -1,
"decrement ref for white container, should be last one");
9777 ao2_t_ref(user->
blackfilters, -1,
"decrement ref for black container, should be last one");
9788 static void manager_shutdown(
void)
9790 struct ast_manager_user *user;
9838 ao2_t_global_obj_release(event_docs,
"Dispose of event_docs");
9841 #ifdef TEST_FRAMEWORK
9842 stasis_forward_cancel(test_suite_forwarder);
9843 test_suite_forwarder = NULL;
9846 if (stasis_router) {
9848 stasis_router = NULL;
9850 stasis_forward_cancel(rtp_topic_forwarder);
9851 rtp_topic_forwarder = NULL;
9852 stasis_forward_cancel(security_topic_forwarder);
9853 security_topic_forwarder = NULL;
9854 ao2_cleanup(manager_topic);
9855 manager_topic = NULL;
9861 ast_free(ami_tls_cfg.certfile);
9862 ami_tls_cfg.certfile = NULL;
9863 ast_free(ami_tls_cfg.pvtfile);
9864 ami_tls_cfg.pvtfile = NULL;
9865 ast_free(ami_tls_cfg.cipher);
9866 ami_tls_cfg.cipher = NULL;
9867 ast_free(ami_tls_cfg.cafile);
9868 ami_tls_cfg.cafile = NULL;
9869 ast_free(ami_tls_cfg.capath);
9870 ami_tls_cfg.capath = NULL;
9875 manager_free_user(user);
9877 acl_change_stasis_unsubscribe();
9879 ast_free(manager_channelvars);
9880 ast_free(manager_disabledevents);
9892 if (!rtp_topic_forwarder) {
9897 if (!security_topic_forwarder) {
9901 stasis_router = stasis_message_router_create(manager_topic);
9902 if (!stasis_router) {
9920 static int subscribe_all(
void)
9923 ast_log(AST_LOG_ERROR,
"Failed to initialize manager subscriptions\n");
9927 ast_log(AST_LOG_ERROR,
"Failed to initialize manager system handling\n");
9931 ast_log(AST_LOG_ERROR,
"Failed to initialize manager channel handling\n");
9935 ast_log(AST_LOG_ERROR,
"Failed to initialize manager MWI handling\n");
9942 ast_log(AST_LOG_ERROR,
"Failed to initialize manager endpoints handling\n");
9950 static void manager_set_defaults(
void)
9952 manager_enabled = 0;
9953 displayconnects = 1;
9954 broken_events_action = 0;
9961 sizeof(global_realm));
9965 ami_tls_cfg.enabled = 0;
9966 ast_free(ami_tls_cfg.certfile);
9968 ast_free(ami_tls_cfg.pvtfile);
9970 ast_free(ami_tls_cfg.cipher);
9972 ast_free(ami_tls_cfg.cafile);
9974 ast_free(ami_tls_cfg.capath);
9978 static int __init_manager(
int reload,
int by_external_config)
9983 int newhttptimeout = 60;
9984 struct ast_manager_user *user = NULL;
9991 int tls_was_enabled = 0;
9992 int acl_subscription_flag = 0;
10006 if (!manager_topic) {
10051 #ifdef TEST_FRAMEWORK
10064 #ifdef AST_XML_DOCS
10066 if (temp_event_docs) {
10067 ao2_t_global_obj_replace_unref(event_docs, temp_event_docs,
"Toss old event docs");
10068 ao2_t_ref(temp_event_docs, -1,
"Remove creation ref - container holds only ref now");
10081 manager_set_defaults();
10085 if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
10087 }
else if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
10088 ast_log(LOG_NOTICE,
"Unable to open AMI configuration manager.conf, or configuration is invalid.\n");
10093 if (!by_external_config) {
10094 acl_change_stasis_unsubscribe();
10099 tls_was_enabled = ami_tls_cfg.enabled;
10100 manager_set_defaults();
10106 for (var = ast_variable_browse(cfg,
"general"); var; var = var->
next) {
10110 if (strcasecmp(var->
name,
"tlscafile")
10111 && strcasecmp(var->
name,
"tlscapath")
10112 && strcasecmp(var->
name,
"tlscadir")
10113 && strcasecmp(var->
name,
"tlsverifyclient")
10114 && strcasecmp(var->
name,
"tlsdontverifyserver")
10115 && strcasecmp(var->
name,
"tlsclientmethod")
10116 && strcasecmp(var->
name,
"sslclientmethod")
10121 if (!strcasecmp(var->
name,
"enabled")) {
10123 }
else if (!strcasecmp(var->
name,
"webenabled")) {
10124 webmanager_enabled =
ast_true(val);
10125 }
else if (!strcasecmp(var->
name,
"port")) {
10127 if (
ast_parse_arg(val, PARSE_UINT32|PARSE_IN_RANGE, &bindport, 1024, 65535)) {
10128 ast_log(LOG_WARNING,
"Invalid port number '%s'\n", val);
10131 }
else if (!strcasecmp(var->
name,
"bindaddr")) {
10135 if (
ast_parse_arg(val, PARSE_ADDR|PARSE_PORT_IGNORE, NULL)) {
10136 ast_log(LOG_WARNING,
"Invalid address '%s' specified, default '%s' will be used\n", val,
10146 }
else if (!strcasecmp(var->
name,
"brokeneventsaction")) {
10147 broken_events_action =
ast_true(val);
10148 }
else if (!strcasecmp(var->
name,
"allowmultiplelogin")) {
10149 allowmultiplelogin =
ast_true(val);
10150 }
else if (!strcasecmp(var->
name,
"displayconnects")) {
10152 }
else if (!strcasecmp(var->
name,
"timestampevents")) {
10154 }
else if (!strcasecmp(var->
name,
"debug")) {
10156 }
else if (!strcasecmp(var->
name,
"httptimeout")) {
10157 newhttptimeout = atoi(val);
10158 }
else if (!strcasecmp(var->
name,
"authtimeout")) {
10159 int timeout = atoi(var->
value);
10162 ast_log(LOG_WARNING,
"Invalid authtimeout value '%s', using default value\n", var->
value);
10164 authtimeout = timeout;
10166 }
else if (!strcasecmp(var->
name,
"authlimit")) {
10167 int limit = atoi(var->
value);
10170 ast_log(LOG_WARNING,
"Invalid authlimit value '%s', using default value\n", var->
value);
10174 }
else if (!strcasecmp(var->
name,
"channelvars")) {
10175 load_channelvars(var);
10176 }
else if (!strcasecmp(var->
name,
"disabledevents")) {
10177 load_disabledevents(var);
10179 ast_log(LOG_NOTICE,
"Invalid keyword <%s> = <%s> in manager.conf [general]\n",
10184 if (manager_enabled && !subscribed) {
10185 if (subscribe_all() != 0) {
10186 ast_log(LOG_ERROR,
"Manager subscription error\n");
10207 if (manager_enabled) {
10216 if (ucfg && (ucfg != CONFIG_STATUS_FILEUNCHANGED) && ucfg != CONFIG_STATUS_FILEINVALID) {
10217 const char *hasmanager;
10218 int genhasmanager =
ast_true(ast_variable_retrieve(ucfg,
"general",
"hasmanager"));
10221 if (!strcasecmp(cat,
"general")) {
10225 hasmanager = ast_variable_retrieve(ucfg, cat,
"hasmanager");
10226 if ((!hasmanager && genhasmanager) ||
ast_true(hasmanager)) {
10227 const char *user_secret = ast_variable_retrieve(ucfg, cat,
"secret");
10228 const char *user_read = ast_variable_retrieve(ucfg, cat,
"read");
10229 const char *user_write = ast_variable_retrieve(ucfg, cat,
"write");
10230 const char *user_displayconnects = ast_variable_retrieve(ucfg, cat,
"displayconnects");
10231 const char *user_allowmultiplelogin = ast_variable_retrieve(ucfg, cat,
"allowmultiplelogin");
10232 const char *user_writetimeout = ast_variable_retrieve(ucfg, cat,
"writetimeout");
10238 if (!(user =
ast_calloc(1,
sizeof(*user)))) {
10257 if (!user_secret) {
10258 user_secret = ast_variable_retrieve(ucfg,
"general",
"secret");
10261 user_read = ast_variable_retrieve(ucfg,
"general",
"read");
10264 user_write = ast_variable_retrieve(ucfg,
"general",
"write");
10266 if (!user_displayconnects) {
10267 user_displayconnects = ast_variable_retrieve(ucfg,
"general",
"displayconnects");
10269 if (!user_allowmultiplelogin) {
10270 user_allowmultiplelogin = ast_variable_retrieve(ucfg,
"general",
"allowmultiplelogin");
10272 if (!user_writetimeout) {
10273 user_writetimeout = ast_variable_retrieve(ucfg,
"general",
"writetimeout");
10276 if (!ast_strlen_zero(user_secret)) {
10282 user->
readperm = get_perm(user_read);
10285 user->
writeperm = get_perm(user_write);
10287 if (user_displayconnects) {
10290 if (user_allowmultiplelogin) {
10293 if (user_writetimeout) {
10294 int value = atoi(user_writetimeout);
10296 ast_log(LOG_WARNING,
"Invalid writetimeout value '%d' in users.conf\n", value);
10311 if (!strcasecmp(cat,
"general")) {
10317 if (!(user =
ast_calloc(1,
sizeof(*user)))) {
10334 manager_free_user(user);
10339 AST_RWLIST_INSERT_TAIL(&users, user, list);
10347 oldacl = user->
acl;
10351 var = ast_variable_browse(cfg, cat);
10352 for (; var; var = var->
next) {
10353 if (!strcasecmp(var->
name,
"secret")) {
10356 }
else if (!strcasecmp(var->
name,
"deny") ||
10357 !strcasecmp(var->
name,
"permit") ||
10358 !strcasecmp(var->
name,
"acl")) {
10363 ast_log(LOG_ERROR,
"Invalid ACL '%s' for manager user '%s' on line %d. Deleting user\n",
10364 var->
value, user->username, var->lineno);
10367 }
else if (!strcasecmp(var->
name,
"read") ) {
10369 }
else if (!strcasecmp(var->
name,
"write") ) {
10371 }
else if (!strcasecmp(var->
name,
"displayconnects") ) {
10373 }
else if (!strcasecmp(var->
name,
"allowmultiplelogin") ) {
10375 }
else if (!strcasecmp(var->
name,
"writetimeout")) {
10376 int value = atoi(var->
value);
10378 ast_log(LOG_WARNING,
"Invalid writetimeout value '%s' at line %d\n", var->
value, var->lineno);
10382 }
else if (!strcasecmp(var->
name,
"setvar")) {
10391 if ((varval = strchr(varname,
'='))) {
10393 if ((tmpvar = ast_variable_new(varname, varval,
""))) {
10398 }
else if (!strcasecmp(var->
name,
"eventfilter")) {
10399 const char *value = var->
value;
10411 if (acl_subscription_flag && !by_external_config) {
10412 acl_change_stasis_subscribe();
10416 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&users, user, list) {
10421 snprintf(a1,
sizeof(a1),
"%s:%s:%s", user->username, global_realm, user->
secret);
10428 AST_RWLIST_REMOVE_CURRENT(list);
10429 ast_debug(4,
"Pruning user '%s'\n", user->username);
10430 manager_free_user(user);
10432 AST_RWLIST_TRAVERSE_SAFE_END;
10436 if (webmanager_enabled && manager_enabled) {
10460 if (newhttptimeout > 0) {
10461 httptimeout = newhttptimeout;
10465 if (tls_was_enabled && !ami_tls_cfg.enabled) {
10482 ast_log(LOG_NOTICE,
"Reloading manager in response to ACL change event.\n");
10483 __init_manager(1, 1);
10486 static int unload_module(
void)
10491 static int load_module(
void)
10498 static int reload_module(
void)
10500 return __init_manager(1, 0);
10523 if (datastore->
info != info) {
10532 if ((datastore->
uid != NULL) && !strcasecmp(uid, datastore->
uid)) {
10543 const char *
header,
const char *value)
10545 if (!*fields_string) {
10547 if (!*fields_string) {
10552 return (
ast_str_append(fields_string, 0,
"%s: %s\r\n", header, value) < 0) ? -1 : 0;
10555 static void manager_event_blob_dtor(
void *obj)
10563 __attribute__((format(printf, 3, 4)))
10567 const
char *extra_fields_fmt,
10573 ast_assert(extra_fields_fmt != NULL);
10574 ast_assert(manager_event != NULL);
10589 va_start(argp, extra_fields_fmt);
10596 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Asterisk Manager Interface",
10597 .support_level = AST_MODULE_SUPPORT_CORE,
10598 .load = load_module,
10599 .unload = unload_module,
10600 .reload = reload_module,
10602 .requires =
"extconfig,acl,http",
void ast_iostream_set_exclusive_input(struct ast_iostream *stream, int exclusive_input)
Set the iostream if it can exclusively depend upon the set timeouts.
static char * ast_sockaddr_stringify_addr(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() to return an address only.
int ast_category_is_template(const struct ast_category *category)
Check if category is a template.
helper function for originate
size_t ast_msg_data_get_length(struct ast_msg_data *msg)
Get length of the structure.
struct ast_category * ast_category_new(const char *name, const char *in_file, int lineno)
Create a category.
static int get_input(struct mansession *s, char *output)
static int action_loggerrotate(struct mansession *s, const struct message *m)
Manager command "LoggerRotate" - reloads and rotates the logger in the same manner as the CLI command...
struct ast_variable * next
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
struct ast_variable * ast_variables_reverse(struct ast_variable *var)
Reverse a variable list.
struct ao2_container * blackfilters
const ast_string_field data
Struct containing info for an AMI event to send out.
static int action_command(struct mansession *s, const struct message *m)
Manager command "command" - execute CLI command.
Information needed to identify an endpoint in a call.
int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
int ast_security_event_report(const struct ast_security_event_common *sec)
Report a security event.
struct ao2_container * whitefilters
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
struct ao2_container * channels
static const char * __astman_get_header(const struct message *m, char *var, int mode)
Return a matching header value.
int ast_aoc_s_add_rate_duration(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name, unsigned long time, enum ast_aoc_time_scale time_scale, unsigned long granularity_time, enum ast_aoc_time_scale granularity_time_scale, int step_function)
Add AOC-S duration rate entry.
Main Channel structure associated with a channel.
An attempt at basic password authentication failed.
Local proxy channel special access.
struct stasis_topic * ast_rtp_topic(void)
Stasis Message Bus API topic for RTP and RTCP related messages
void astman_live_dangerously(int new_live_dangerously)
Enable/disable the inclusion of 'dangerous' configurations outside of the ast_config_AST_CONFIG_DIR.
char * str
Subscriber phone number (Malloced)
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
enum ast_security_event_type event_type
The security event sub-type.
Security Event Reporting API.
struct ast_channel_snapshot_base * base
Asterisk locking-related definitions:
void astman_append(struct mansession *s, const char *fmt,...)
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
const ast_string_field uniqueid
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
static char * handle_kickmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager kick session.
static void mansession_unlock(struct mansession *s)
Unlock the 'mansession' structure.
FYI FWIW, Successful authentication has occurred.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
int astman_verify_session_writepermissions(uint32_t ident, int perm)
Verify a session's write permissions against a permission mask.
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
const char * expected_response
Response expected to be received.
void ast_manager_unregister_hook(struct manager_custom_hook *hook)
Delete a custom hook to be called when an event is fired.
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
This is a generic (re)start routine for a TCP server, which does the socket/bind/listen and starts a ...
String manipulation functions.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
int ast_ssl_setup(struct ast_tls_config *cfg)
Set up an SSL server.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int ast_aoc_add_unit_entry(struct ast_aoc_decoded *decoded, const unsigned int amount_is_present, const unsigned int amount, const unsigned int type_is_present, const unsigned int type)
Adds a unit entry into the list of units.
static int action_reload(struct mansession *s, const struct message *m)
Send a reload event.
Asterisk version information.
int ast_aoc_s_add_special_arrangement(struct ast_aoc_decoded *decoded, unsigned int code)
Add AOC-S special arrangement entry.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
const ast_string_field extra_fields
int ast_hook_send_action(struct manager_custom_hook *hook, const char *msg)
access for hooks to send action messages to ami
struct ast_json_payload * ast_json_payload_create(struct ast_json *json)
Create an ao2 object to pass json blobs as data payloads for stasis.
void ast_manager_register_hook(struct manager_custom_hook *hook)
Add a custom hook to be called when an event is fired.
struct mansession_session::mansession_datastores datastores
void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
Set when to hang a channel up.
int stasis_message_router_set_congestion_limits(struct stasis_message_router *router, long low_water, long high_water)
Set the high and low alert water marks of the stasis message router.
Support for translation of data formats. translate.c.
int ast_manager_check_enabled(void)
Check if AMI is enabled.
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buffer, size_t count)
Write data to an iostream.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
void ast_http_auth(struct ast_tcptls_session_instance *ser, const char *realm, const unsigned long nonce, const unsigned long opaque, int stale, const char *text)
Send http "401 Unauthorized" response and close socket.
struct ast_party_name name
Subscriber name.
static int force_inline attribute_pure ast_ends_with(const char *str, const char *suffix)
Checks whether a string ends with another.
static void astman_append_headers(struct message *m, const struct ast_variable *params)
Append additional headers into the message structure from params.
struct ast_bridge_snapshot * ast_bridge_get_snapshot_by_uniqueid(const char *uniqueid)
Returns the current snapshot for the bridge.
An attempt at challenge/response auth failed.
static void json_escape(char *out, const char *in)
const char * ast_get_version(void)
Retrieve the Asterisk version string.
#define MAX_AUTH_PERM_STRING
int ast_logger_rotate(void)
Reload logger while rotating log files.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
int ast_str_append_event_header(struct ast_str **fields_string, const char *header, const char *value)
append an event header to an ast string
Iterator for JSON object key/values.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
struct varshead * ast_channel_get_manager_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_manager_vars().
ast_module_reload_result
Possible return types for ast_module_reload.
descriptor for a cli entry.
static struct ast_manager_user * get_manager_by_name_locked(const char *name)
int64_t ast_tvdiff_sec(struct timeval end, struct timeval start)
Computes the difference (in seconds) between two struct timeval instances.
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int ast_aoc_s_add_rate_flat(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S flat rate entry.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
int(* func)(struct mansession *s, const struct message *m)
Structure that contains a snapshot of information about a bridge.
struct ast_json_iter * ast_json_object_iter(struct ast_json *object)
Get an iterator pointing to the first field in a JSON object.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
int ast_config_text_file_save2(const char *filename, const struct ast_config *cfg, const char *generator, uint32_t flags)
Save a config text file.
struct eventqent * last_ev
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
Structure representing a snapshot of channel state.
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
struct ao2_container * ast_xmldoc_build_documentation(const char *type)
Build the documentation for a particular source type.
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *cat)
Delete a category.
void ast_channel_clear_flag(struct ast_channel *chan, unsigned int flag)
Clear a flag on a channel.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void ast_acl_output(int fd, struct ast_acl_list *acl, const char *prefix)
output an ACL to the provided fd
void ast_iostream_set_timeout_inactivity(struct ast_iostream *stream, int timeout)
Set the iostream inactivity timeout timer.
struct ast_str * ast_manager_build_channel_state_string_prefix(const struct ast_channel_snapshot *snapshot, const char *prefix)
Generate the AMI message body from a channel snapshot.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Checking against an IP access control list failed.
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
void * ast_aoc_destroy_decoded(struct ast_aoc_decoded *decoded)
free an ast_aoc_decoded object
Assume that the ao2_container is already locked.
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
Structure to pass both assignedid values to channel drivers.
static int action_coreshowchannelmap(struct mansession *s, const struct message *m)
Manager command "CoreShowChannelMap" - Lists all channels connected to the specified channel...
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
static int restrictedFile(const char *filename)
Check if a file is restricted or not.
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs ...
void stasis_message_router_set_formatters_default(struct stasis_message_router *router, stasis_subscription_cb callback, void *data, enum stasis_subscription_message_formatters formatters)
Sets the default route of a router with formatters.
Structure for a data store type.
Structure used to transport a message through the frame core.
int ast_pbx_outgoing_exten_predial(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
char * term_strip(char *outbuf, const char *inbuf, int maxout)
Remove colorings from a specified string.
char * str
Subscriber name (Malloced)
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
struct ast_iostream * ast_iostream_from_fd(int *fd)
Create an iostream from a file descriptor.
int ast_aoc_s_add_rate_special_charge_code(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, unsigned int code)
Add AOC-S special rate entry.
struct ast_category * prev
struct ast_security_event_common common
Common security event descriptor elements.
static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
send a response with an optional message, and terminate it with an empty line. m is used only to grab...
const ast_string_field uniqueid
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
const char * response
Response received.
int ast_iostream_get_fd(struct ast_iostream *stream)
Get an iostream's file descriptor.
static int copy(char *infile, char *outfile)
Utility function to copy a file.
static int process_events(struct mansession *s)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
arguments for the accepting thread
static char * handle_manager_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager show settings.
int ast_refresh_resource(const char *resource_name, enum ast_module_unload_mode force, int recursive)
Unload and load a module again.
Wrapper for an ast_acl linked list.
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
double ast_option_maxload
static const char * authority_to_str(int authority, struct ast_str **res)
Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be re...
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
uint32_t ast_http_manid_from_vars(struct ast_variable *headers) attribute_pure
Return manager id, if exist, from request headers.
struct ast_security_event_common common
Common security event descriptor elements.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
A request was made that is not allowed.
int ast_aoc_s_add_rate_volume(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, enum ast_aoc_volume_unit volume_unit, unsigned int amount, enum ast_aoc_currency_multiplier multiplier, const char *currency_name)
Add AOC-S volume rate entry.
static int queue_sendtext(struct ast_channel *chan, const char *body)
Queue a read action to send a text message.
ast_aoc_currency_multiplier
Defines the currency multiplier for an aoc message.
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
#define MAX_BLACKLIST_CMD_LEN
Descriptor for a manager session, either on the AMI socket or over HTTP.
static struct stasis_topic * manager_topic
A stasis_topic that all topics AMI cares about will be forwarded to.
user descriptor, as read from the config file.
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Definitions to aid in the use of thread local storage.
int ast_aoc_s_add_rate_free(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item, int from_beginning)
Add AOC-S indicating charge item is free.
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
struct ast_xml_doc_item * list_responses
Out-of-call text message support.
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Generic support for tcp/tls servers in Asterisk.
int __ast_manager_event_multichan(int category, const char *event, int chancount, struct ast_channel **chans, const char *file, int line, const char *func, const char *fmt,...)
struct ast_format_cap * cap
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION
Event descriptor version.
int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and send it to a particular extension...
struct ao2_container * blackfilters
int ast_manager_register2(const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), struct ast_module *module, const char *synopsis, const char *description)
register a new command with manager, including online help. This is the preferred way to register a m...
list of users found in the config file
static int append_event(const char *str, int category)
events are appended to a queue from where they can be dispatched to clients.
int manager_bridging_init(void)
Initialize support for AMI channel events.
void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Socket address structure.
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node ('application', 'function' or 'agi') and name...
static int purge_sessions(int n_max)
remove at most n_max stale session from the list.
struct ast_channel_snapshot_dialplan * dialplan
void astman_send_error_va(struct mansession *s, const struct message *m, const char *fmt,...)
Send error in manager transaction (with va_args support)
static struct mansession_session * unref_mansession(struct mansession_session *s)
Unreference manager session object. If no more references, then go ahead and delete it...
int ast_manager_hangup_helper(struct mansession *s, const struct message *m, manager_hangup_handler_t hangup_handler, manager_hangup_cause_validator_t cause_validator)
A manager helper function that hangs up a channel using a supplied channel type specific hangup funct...
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
STASIS_MESSAGE_TYPE_DEFN(ast_manager_get_generic_type)
Define AMI message types.
struct ast_category * ast_category_browse_filtered(struct ast_config *config, const char *category_name, struct ast_category *prev, const char *filter)
Browse categories with filters.
struct ast_xml_doc_item * ast_xmldoc_build_final_response(const char *type, const char *name, const char *module)
Generate the [final response] tag based on type of node ('application', 'function' or 'agi') and name...
#define ast_string_field_ptr_build_va(x, ptr, fmt, args)
Set a field to a complex (built) value with prebuilt va_lists.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static char * handle_showmaneventq(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager list eventq.
struct ast_xml_doc_item * ast_xmldoc_build_list_responses(const char *type, const char *name, const char *module)
Generate the [list responses] tag based on type of node ('application', 'function' or 'agi') and name...
struct ast_module * module
struct ast_str * ast_category_get_templates(const struct ast_category *category)
Return the template names this category inherits from.
static int action_filter(struct mansession *s, const struct message *m)
Manager command to add an event filter to a manager session.
static int process_message(struct mansession *s, const struct message *m)
Process an AMI message, performing desired action. Return 0 on success, -1 on error that require the ...
int ast_category_inherit(struct ast_category *existing, const struct ast_category *base)
Applies base (template) to category.
int ast_module_check(const char *name)
Check if module with the name given is loaded.
static void ast_sockaddr_setnull(struct ast_sockaddr *addr)
Sets address addr to null.
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
int args
This gets set in ast_cli_register()
const char * astman_get_header(const struct message *m, char *var)
Return the first matching variable from an array.
static struct mansession_session * find_session(uint32_t ident, int incinuse)
static struct ast_custom_function managerclient_function
description of AMI_CLIENT dialplan function
int ast_realtime_enabled(void)
Check if there's any realtime engines loaded.
int ast_webmanager_check_enabled(void)
Check if AMI/HTTP is enabled.
const char * manager_event
struct ast_variable * chanvars
struct ast_str * ast_manager_str_from_json_object(struct ast_json *blob, key_exclusion_cb exclusion_cb)
Convert a JSON object into an AMI compatible string.
struct ast_manager_event_blob * stasis_message_to_ami(struct stasis_message *msg)
Build the AMI representation of the message.
ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t count)
Read data from an iostream.
int ast_aoc_set_association_number(struct ast_aoc_decoded *decoded, const char *num, uint8_t plan)
set the charging association number for an AOC-E message
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
unsigned int ast_aoc_s_get_count(struct ast_aoc_decoded *decoded)
get the number rates associated with an AOC-S message
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
An attempt at basic password auth failed.
static int generic_http_callback(struct ast_tcptls_session_instance *ser, enum ast_http_method method, enum output_format format, const struct ast_sockaddr *remote_address, const char *uri, struct ast_variable *get_params, struct ast_variable *headers)
Configuration File Parser.
Support for Private Asterisk HTTP Servers.
int ast_app_inboxcount2(const char *mailboxes, int *urgentmsgs, int *newmsgs, int *oldmsgs)
Determine number of urgent/new/old messages in a mailbox.
struct stasis_message_type * ast_manager_get_generic_type(void)
Get the stasis_message_type for generic messages.
struct ao2_container * whitefilters
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
static int manager_modulecheck(struct mansession *s, const struct message *m)
Manager function to check if module is loaded.
Generic Advice of Charge encode and decode routines.
enum ast_transfer_result ast_bridge_transfer_blind(int is_external, struct ast_channel *transferer, const char *exten, const char *context, transfer_channel_cb new_channel_cb, void *user_data)
Blind transfer target to the extension and context provided.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
int ast_iostream_close(struct ast_iostream *stream)
Close an iostream.
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
static void * session_do(void *data)
The body of the individual manager session. Call get_input() to read one line at a time (or be woken ...
struct ast_json * ast_json_object_iter_value(struct ast_json_iter *iter)
Get the value from an iterator.
const ast_string_field appl
static AO2_GLOBAL_OBJ_STATIC(mgr_sessions)
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
const ast_string_field description
int ast_aoc_s_add_rate_na(struct ast_aoc_decoded *decoded, enum ast_aoc_s_charged_item charged_item)
Add AOC-S entry indicating charge item is not available.
struct ast_aoc_encoded * ast_aoc_encode(struct ast_aoc_decoded *decoded, size_t *out_size, struct ast_channel *chan)
encodes a decoded aoc structure so it can be passed on the wire
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Data structure associated with a custom dialplan function.
Access Control of various sorts.
Request received with bad formatting.
static struct ao2_container * codecs
Registered codecs.
#define ASTMAN_APPEND_BUF_INITSIZE
initial allocated size for the astman_append_buf and astman_send_*_va
Request denied because of a session limit.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
unsigned int registered
TRUE if the AMI action is registered and the callback can be called.
int(* manager_hangup_cause_validator_t)(const char *channel_name, const char *cause)
Callback used by ast_manager_hangup_helper that will validate the cause code.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Successful authentication.
#define AST_STRING_FIELD(name)
Declare a string field.
static enum error_type handle_updates(struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn)
helper function for action_updateconfig
static int action_coreshowchannels(struct mansession *s, const struct message *m)
Manager command "CoreShowChannels" - List currently defined channels and some information about them...
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
struct ast_variable * ast_category_first(struct ast_category *cat)
given a pointer to a category, return the root variable.
In case you didn't read that giant block of text above the mansession_session struct, the mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
const struct ast_datastore_info * info
#define AST_SECURITY_EVENT_FAILED_ACL_VERSION
Event descriptor version.
struct timeval creationtime
struct ast_variable * chanvars
int astman_verify_session_readpermissions(uint32_t ident, int perm)
Verify a session's read permissions against a permission mask.
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
static struct mansession_session * find_session_by_nonce(const char *username, unsigned long nonce, int *stale)
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
A set of macros to manage forward-linked lists.
ast_cli_command
calling arguments for new-style handlers.
struct ast_security_event_common common
Common security event descriptor elements.
#define ast_malloc(len)
A wrapper for malloc()
const char * ast_json_object_iter_key(struct ast_json_iter *iter)
Get the key from an iterator.
struct timeval sessionstart_tv
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_security_event_common common
Common security event descriptor elements.
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
static int function_amiclient(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
${AMI_CLIENT()} Dialplan function - reads manager client data
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
int astman_datastore_remove(struct mansession *s, struct ast_datastore *datastore)
Remove a datastore from a session.
enum ast_acl_sense ast_apply_acl(struct ast_acl_list *acl_list, const struct ast_sockaddr *addr, const char *purpose)
Apply a set of rules to a given IP address.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
describes a server instance
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
list of actions registered
void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg)
Send response in manager transaction.
int ast_acl_list_is_empty(struct ast_acl_list *acl_list)
Determines if an ACL is empty or if it contains entries.
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
static int manager_subscriptions_init(void)
Initialize all Stasis Message Bus API topics and routers used by the various sub-components of AMI...
struct ast_str * description
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
const ast_string_field arguments
struct ast_acl_list * acl
void ast_iostream_set_timeout_disable(struct ast_iostream *stream)
Disable the iostream timeout timer.
int ast_manager_unregister(const char *action)
support functions to register/unregister AMI action handlers,
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION
Event descriptor version.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Presence state management.
Structure that contains information about a bridge.
int ast_aoc_set_billing_id(struct ast_aoc_decoded *decoded, const enum ast_aoc_billing_id id)
set the billing id for a AOC-D or AST_AOC_E message
void ast_channel_set_manager_vars(size_t varc, char **vars)
Sets the variables to be stored in the manager_vars field of all snapshots.
static const char * user_authority_to_str(int authority, struct ast_str **res)
Convert authority code to a list of options for a user. This will only display those authority codes ...
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static int queue_read_action_payload(struct ast_channel *chan, const unsigned char *payload, size_t payload_size, enum ast_frame_read_action action)
Queue a given read action containing a payload onto a channel.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
static int strings_to_mask(const char *string)
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
static char * handle_showmancmds(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager list commands.
Support for dynamic strings.
void ast_iostream_set_timeout_sequence(struct ast_iostream *stream, struct timeval start, int timeout)
Set the iostream I/O sequence timeout timer.
static int set_eventmask(struct mansession *s, const char *eventmask)
Rather than braindead on,off this now can also accept a specific int mask value or a '...
#define ao2_unlink(container, obj)
Remove an object from a container.
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
static struct stasis_message_router * stasis_router
The stasis_message_router for all Stasis Message Bus API messages.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
void(* manager_hangup_handler_t)(struct ast_channel *chan, int causecode)
Callback used by ast_manager_hangup_helper that will actually hangup a channel.
struct ast_acl_list * ast_free_acl_list(struct ast_acl_list *acl)
Free a list of ACLs.
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
int ast_category_insert(struct ast_config *config, struct ast_category *cat, const char *match)
Inserts new category.
struct ast_variable * astman_get_variables(const struct message *m)
Get a linked list of the Variable: headers.
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode)
Unload a module.
static void xml_translate(struct ast_str **out, char *in, struct ast_variable *get_vars, enum output_format format)
Convert the input into XML or HTML. The input is supposed to be a sequence of lines of the form Name:...
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
An attempt at challenge/response authentication failed.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
struct stasis_message_router * ast_manager_get_message_router(void)
Get the stasis_message_router for AMI.
static enum add_filter_result manager_add_filter(const char *filter_pattern, struct ao2_container *whitefilters, struct ao2_container *blackfilters)
Add an event filter to a manager session.
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and execute an application on the channel...
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
int astman_is_authed(uint32_t ident)
Determine if a manager session ident is authenticated.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
const ast_string_field name
int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str **regex_pattern)
Given a string regex_string in the form of "/regex/", convert it into the form of "regex"...
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
#define ast_calloc(num, len)
A wrapper for calloc()
int manager_endpoints_init(void)
Initialize support for AMI endpoint events.
int ast_aoc_set_total_type(struct ast_aoc_decoded *decoded, const enum ast_aoc_total_type type)
Sets the type of total for a AOC-D message.
Module could not be loaded properly.
struct ast_iostream * stream
static void astman_free_headers(struct message *m)
Free headers inside message structure, but not the message structure itself.
void * ast_aoc_destroy_encoded(struct ast_aoc_encoded *encoded)
free an ast_aoc_encoded object
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
int ast_variable_update(struct ast_category *category, const char *variable, const char *value, const char *match, unsigned int object)
Update variable value within a config.
struct ast_security_event_common common
Common security event descriptor elements.
static struct stasis_forward * security_topic_forwarder
The stasis_subscription for forwarding the Security topic to the AMI topic.
const char * ast_get_http_method(enum ast_http_method method) attribute_pure
Return http method name string.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
int ast_str_append_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Append to a dynamic string using a va_list.
An API for managing task processing threads that can be shared across modules.
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
static int action_status(struct mansession *s, const struct message *m)
Manager "status" command to show channels.
static void purge_old_stuff(void *data)
cleanup code called at each iteration of server_root, guaranteed to happen every 5 seconds at most ...
static int send_string(struct mansession *s, char *string)
int stasis_message_can_be_ami(struct stasis_message *msg)
Determine if the given message can be converted to AMI.
structure to hold users read from users.conf
static int action_coresettings(struct mansession *s, const struct message *m)
Show PBX core settings information.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Structure used to handle boolean flags.
struct stasis_topic * ast_manager_get_topic(void)
Get the Stasis Message Bus API topic for AMI.
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the node content.
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
const ast_string_field data
struct ast_iostream * stream
#define ast_module_unref(mod)
Release a reference to the module.
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous AMI actions to run.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Invalid account ID specified (invalid username, for example)
struct ast_aoc_decoded * ast_aoc_create(const enum ast_aoc_type msg_type, const enum ast_aoc_charge_type charge_type, const enum ast_aoc_request requests)
creates a ast_aoc_decode object of a specific message type
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
struct ast_category * ast_category_new_template(const char *name, const char *in_file, int lineno)
Create a category making it a template.
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
static int get_manager_sessions_cb(void *obj, void *arg, void *data, int flags)
Get number of logged in sessions for a login name.
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
struct ast_security_event_common common
Common security event descriptor elements.
struct ast_security_event_common common
Common security event descriptor elements.
#define AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION
Event descriptor version.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_MAX_PUBLIC_UNIQUEID
int ast_category_empty(struct ast_category *category)
Removes and destroys all variables in a category.
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
static struct stasis_subscription * acl_change_sub
struct ast_variable * astman_get_variables_order(const struct message *m, enum variable_orders order)
Get a linked list of the Variable: headers with order specified.
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container...
static int coreshowchannelmap_add_connected_channels(struct ao2_container *channel_map, struct ast_channel_snapshot *channel_snapshot, struct ast_bridge_snapshot *bridge_snapshot)
Recursive function to get all channels in a bridge. Follow local channels as well.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
static struct mansession_session * build_mansession(const struct ast_sockaddr *addr)
Allocate manager session structure and add it to the list of sessions.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
static struct eventqent * grab_last(void)
#define EVENT_FLAG_SHUTDOWN
Fake event class used to end sessions at shutdown.
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int function_capable_string_allowed_with_auths(const char *evaluating, int writepermlist)
Checks to see if a string which can be used to evaluate functions should be rejected.
void ast_append_acl(const char *sense, const char *stuff, struct ast_acl_list **path, int *error, int *named_acl_flag)
Add a rule to an ACL struct.
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.
static int ast_instring(const char *bigstr, const char *smallstr, const char delim)
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
static char * handle_manager_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager reload.
struct ast_msg_data * ast_msg_data_alloc2(enum ast_msg_data_source_type source_type, const char *to, const char *from, const char *content_type, const char *body)
Allocates an ast_msg_data structure.
static struct stasis_forward * rtp_topic_forwarder
The stasis_subscription for forwarding the RTP topic to the AMI topic.
static int coreshowchannelmap_add_to_map(struct ao2_container *c, const char *s)
Helper function to add a channel name to the vector.
static void mansession_lock(struct mansession *s)
Lock the 'mansession' structure.
struct ast_datastore * astman_datastore_find(struct mansession *s, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a session.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
struct ast_channel_snapshot_bridge * bridge
int manager_system_init(void)
Initialize support for AMI system events.
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition of a URI handler.
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
ast_aoc_billing_id
Defines the billing id options for an aoc message.
int astman_datastore_add(struct mansession *s, struct ast_datastore *datastore)
Add a datastore to a session.
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
static void purge_events(void)
struct ast_variable * ast_http_get_post_vars(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlenco...
void ast_iostream_nonblock(struct ast_iostream *stream)
Make an iostream non-blocking.
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
Used to parse conf files containing tls/ssl options.
Data structure associated with a single frame of data.
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
int ast_in_delimited_string(const char *needle, const char *haystack, char delim)
Check if there is an exact match for 'needle' between delimiters in 'haystack'.
int(* key_exclusion_cb)(const char *key)
Callback used to determine whether a key should be skipped when converting a JSON object to a manager...
Abstract JSON element (object, array, string, int, ...).
int ast_parse_digest(const char *digest, struct ast_http_digest *d, int request, int pedantic)
Parse digest authorization header.
static char global_realm[MAXHOSTNAMELEN]
#define AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION
Event descriptor version.
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
Handy terminal functions for vt* terms.
int ast_aoc_set_association_id(struct ast_aoc_decoded *decoded, const int id)
set the charging association id for an AST_AOC_E message
Struct that contains the XML documentation for a particular item. Note that this is an ao2 ref counte...
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION
Event descriptor version.
void ast_tcptls_server_stop(struct ast_tcptls_session_args *desc)
Shutdown a running server if there is one.
struct ast_tls_config * tls_cfg
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
struct ast_str * arguments
unsigned char valid
TRUE if the name information is valid/present.
static int action_corestatus(struct mansession *s, const struct message *m)
Show PBX core status information.
Call Parking and Pickup API Includes code and algorithms from the Zapata library. ...
ast_http_method
HTTP Request methods known by Asterisk.
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
int manager_channels_init(void)
Initialize support for AMI channel events.
const ast_string_field synopsis
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
ast_frame_read_action
Actions to indicate to, and be handled on channel read.
void ast_shrink_phone_number(char *n)
Shrink a phone number in place to just digits (more accurately it just removes ()'s, .'s, and -'s...
struct ast_xml_doc_item * final_response
void ast_md5_hash(char *output, const char *input)
Produces MD5 hash based on input string.
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Pluggable RTP Architecture.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Asterisk module definitions.
static int manager_displayconnects(struct mansession_session *session)
Get displayconnects config option.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_active_channels(void)
returns number of active/allocated channels
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int manager_mwi_init(void)
Initialize support for AMI MWI events.
void ast_channel_softhangup_withcause_locked(struct ast_channel *chan, int causecode)
Lock the given channel, then request softhangup on the channel with the given causecode.
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
unsigned char valid
TRUE if the number information is valid/present.
static int action_redirect(struct mansession *s, const struct message *m)
action_redirect: The redirect manager command
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define AST_SECURITY_EVENT_SESSION_LIMIT_VERSION
Event descriptor version.
const ast_string_field seealso
Reject duplicate objects in container.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Request denied because it's not allowed.
const ast_string_field syntax
const char * request_type
Request type that was made.
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
Structure for mutex and tracking information.
static char * handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command manager list connected.
static int queue_sendtext_data(struct ast_channel *chan, const char *body, const char *content_type)
Queue a read action to send a text data message.
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
const ast_string_field name
#define AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION
Event descriptor version.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
struct ast_str * synopsis
struct ast_json_iter * ast_json_object_iter_next(struct ast_json *object, struct ast_json_iter *iter)
Get the next iterator.
#define AST_APP_ARG(name)
Define an application argument.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
int ast_aoc_set_currency_info(struct ast_aoc_decoded *decoded, const unsigned int amount, const enum ast_aoc_currency_multiplier multiplier, const char *name)
Sets the currency values for a AOC-D or AOC-E message.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
struct ast_party_number number
Subscriber phone number.
#define ao2_link(container, obj)
Add an object to a container.