callback to display queues status in manager More...
Data Structures | |
struct | actions |
list of actions registered More... | |
struct | all_events |
struct | ast_manager_user |
user descriptor, as read from the config file. More... | |
struct | channelvars |
struct | eventqent |
struct | fast_originate_helper |
helper function for originate More... | |
struct | manager_channel_variable |
struct | manager_hooks |
list of hooks registered More... | |
struct | mansession |
struct | mansession_session |
struct | permalias |
struct | users |
list of users found in the config file More... | |
Defines | |
#define | ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf | |
#define | DEFAULT_REALM "asterisk" |
#define | GET_HEADER_FIRST_MATCH 0 |
#define | GET_HEADER_LAST_MATCH 1 |
#define | GET_HEADER_SKIP_EMPTY 2 |
#define | MANAGER_EVENT_BUF_INITSIZE 256 |
#define | MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP. | |
#define | MSG_MOREDATA ((char *)astman_send_response) |
send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field. | |
Enumerations | |
enum | error_type { UNKNOWN_ACTION = 1, UNKNOWN_CATEGORY, UNSPECIFIED_CATEGORY, UNSPECIFIED_ARGUMENT, FAILURE_ALLOCATION, FAILURE_NEWCAT, FAILURE_DELCAT, FAILURE_EMPTYCAT, FAILURE_UPDATE, FAILURE_DELETE, FAILURE_APPEND } |
enum | mansession_message_parsing { MESSAGE_OKAY, MESSAGE_LINE_TOO_LONG } |
Functions | |
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,...) |
static const char * | __astman_get_header (const struct message *m, char *var, int mode) |
Return a matching header value. | |
static void | __init_astman_append_buf (void) |
thread local buffer for astman_append | |
static void | __init_manager_event_buf (void) |
static void | __init_manager_event_funcbuf (void) |
static void | __init_userevent_buf (void) |
static int | action_aocmessage (struct mansession *s, const struct message *m) |
static int | action_atxfer (struct mansession *s, const struct message *m) |
static int | action_challenge (struct mansession *s, const struct message *m) |
static int | action_command (struct mansession *s, const struct message *m) |
Manager command "command" - execute CLI command. | |
static int | action_coresettings (struct mansession *s, const struct message *m) |
Show PBX core settings information. | |
static int | action_coreshowchannels (struct mansession *s, const struct message *m) |
Manager command "CoreShowChannels" - List currently defined channels and some information about them. | |
static int | action_corestatus (struct mansession *s, const struct message *m) |
Show PBX core status information. | |
static int | action_createconfig (struct mansession *s, const struct message *m) |
static void | action_destroy (void *obj) |
static int | action_events (struct mansession *s, const struct message *m) |
static int | action_extensionstate (struct mansession *s, const struct message *m) |
static struct manager_action * | action_find (const char *name) |
static int | action_getconfig (struct mansession *s, const struct message *m) |
static int | action_getconfigjson (struct mansession *s, const struct message *m) |
static int | action_getvar (struct mansession *s, const struct message *m) |
static int | action_hangup (struct mansession *s, const struct message *m) |
static int | action_listcategories (struct mansession *s, const struct message *m) |
static int | action_listcommands (struct mansession *s, const struct message *m) |
static int | action_login (struct mansession *s, const struct message *m) |
static int | action_logoff (struct mansession *s, const struct message *m) |
static int | action_mailboxcount (struct mansession *s, const struct message *m) |
static int | action_mailboxstatus (struct mansession *s, const struct message *m) |
static int | action_originate (struct mansession *s, const struct message *m) |
static int | action_ping (struct mansession *s, const struct message *m) |
static int | action_redirect (struct mansession *s, const struct message *m) |
action_redirect: The redirect manager command | |
static int | action_reload (struct mansession *s, const struct message *m) |
Send a reload event. | |
static int | action_sendtext (struct mansession *s, const struct message *m) |
static int | action_setvar (struct mansession *s, const struct message *m) |
static int | action_status (struct mansession *s, const struct message *m) |
Manager "status" command to show channels. | |
static int | action_timeout (struct mansession *s, const struct message *m) |
static int | action_updateconfig (struct mansession *s, const struct message *m) |
static int | action_userevent (struct mansession *s, const struct message *m) |
static int | action_waitevent (struct mansession *s, const struct message *m) |
static struct eventqent * | advance_event (struct eventqent *e) |
static int | aocmessage_get_unit_entry (const struct message *m, struct ast_aoc_unit_entry *entry, unsigned int entry_num) |
static void | append_channel_vars (struct ast_str **pbuf, struct ast_channel *chan) |
static int | append_event (const char *str, int category) |
int | ast_hook_send_action (struct manager_custom_hook *hook, const char *msg) |
Registered hooks can call this function to invoke actions and they will receive responses through registered callback. | |
static int | ast_instring (const char *bigstr, const char *smallstr, const char delim) |
int | ast_manager_register2 (const char *action, int auth, int(*func)(struct mansession *s, const struct message *m), const char *synopsis, const char *description) |
register a new command with manager, including online help. This is the preferred way to register a manager command | |
void | ast_manager_register_hook (struct manager_custom_hook *hook) |
Add a custom hook to be called when an event is fired. | |
static int | ast_manager_register_struct (struct manager_action *act) |
int | ast_manager_unregister (char *action) |
Unregister a registered manager command. | |
void | ast_manager_unregister_hook (struct manager_custom_hook *hook) |
Delete a custom hook to be called when an event is fired. | |
void | astman_append (struct mansession *s, const char *fmt,...) |
static void | astman_append_json (struct mansession *s, const char *str) |
const char * | astman_get_header (const struct message *m, char *var) |
Return the first matching variable from an array. | |
struct ast_variable * | astman_get_variables (const struct message *m) |
Get a linked list of the Variable: headers. | |
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. | |
void | astman_send_ack (struct mansession *s, const struct message *m, char *msg) |
Send ack in manager transaction. | |
void | astman_send_error (struct mansession *s, const struct message *m, char *error) |
Send error in manager transaction. | |
void | astman_send_listack (struct mansession *s, const struct message *m, char *msg, char *listflag) |
Send ack in manager list transaction. | |
void | astman_send_response (struct mansession *s, const struct message *m, char *resp, char *msg) |
Send response in manager transaction. | |
static void | astman_send_response_full (struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag) |
static void | astman_start_ack (struct mansession *s, const struct message *m) |
static int | authenticate (struct mansession *s, const struct message *m) |
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 returned. | |
static int | blackfilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
static struct mansession_session * | build_mansession (struct sockaddr_in sin) |
Allocate manager session structure and add it to the list of sessions. | |
static int | check_blacklist (const char *cmd) |
int | check_manager_enabled (void) |
Check if AMI is enabled. | |
static int | check_manager_session_inuse (const char *name) |
int | check_webmanager_enabled (void) |
Check if AMI/HTTP is enabled. | |
static void | destroy_fast_originate_helper (struct fast_originate_helper *doomed) |
static int | do_message (struct mansession *s) |
static void | event_filter_destructor (void *obj) |
static void * | fast_originate (void *data) |
static void | free_channelvars (void) |
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. | |
static int | get_input (struct mansession *s, char *output) |
static struct ast_manager_user * | get_manager_by_name_locked (const char *name) |
static int | get_perm (const char *instr) |
static struct eventqent * | grab_last (void) |
static char * | handle_manager_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager reload. | |
static char * | handle_mandebug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void | handle_parse_error (struct mansession *s, struct message *m, char *error) |
static char * | handle_showmanager (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmanagers (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmancmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static char * | handle_showmancmds (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list commands. | |
static char * | handle_showmanconn (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list connected. | |
static char * | handle_showmaneventq (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
CLI command manager list eventq. | |
static enum error_type | handle_updates (struct mansession *s, const struct message *m, struct ast_config *cfg, const char *dfn) |
static void | json_escape (char *out, const char *in) |
static struct ast_variable * | man_do_variable_value (struct ast_variable *head, const char *hdr_val) |
static int | manager_displayconnects (struct mansession_session *session) |
Get displayconnects config option. | |
static int | manager_modulecheck (struct mansession *s, const struct message *m) |
static int | manager_moduleload (struct mansession *s, const struct message *m) |
static int | manager_state_cb (char *context, char *exten, int state, void *data) |
static int | mansession_cmp_fn (void *obj, void *arg, int flags) |
static struct sockaddr_in * | mansession_encode_sin_local (const struct mansession *s, struct sockaddr_in *sin_local) |
static enum ast_security_event_transport_type | mansession_get_transport (const struct mansession *s) |
static void | mansession_lock (struct mansession *s) |
Lock the 'mansession' structure. | |
static void | mansession_unlock (struct mansession *s) |
Unlock the 'mansession' structure. | |
static int | match_filter (struct mansession *s, char *eventdata) |
static int | process_events (struct mansession *s) |
static int | process_message (struct mansession *s, const struct message *m) |
static void | purge_events (void) |
static void | purge_sessions (int n_max) |
remove at most n_max stale session from the list. | |
static void | report_auth_success (const struct mansession *s) |
static void | report_failed_acl (const struct mansession *s, const char *username) |
static void | report_failed_challenge_response (const struct mansession *s, const char *response, const char *expected_response) |
static void | report_inval_password (const struct mansession *s, const char *username) |
static void | report_invalid_user (const struct mansession *s, const char *username) |
static void | report_req_bad_format (const struct mansession *s, const char *action) |
static void | report_req_not_allowed (const struct mansession *s, const char *action) |
static void | report_session_limit (const struct mansession *s) |
static int | send_string (struct mansession *s, char *string) |
static void | session_destroy (struct mansession_session *s) |
static void | session_destructor (void *obj) |
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 up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ). | |
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 ',' delim list of mask strings (the same as manager.conf) -anthm. | |
static int | strings_to_mask (const char *string) |
static struct mansession_session * | unref_mansession (struct mansession_session *s) |
Unreference manager session object. If no more references, then go ahead and delete it. | |
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 that have an explicit match on authority. | |
static int | whitefilter_cmp_fn (void *obj, void *arg, void *data, int flags) |
Variables | |
static int | allowmultiplelogin = 1 |
static struct ast_threadstorage | astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } |
static int | authlimit |
static int | authtimeout |
static int | broken_events_action |
struct { | |
const char * words [AST_MAX_CMD_LEN] | |
} | command_blacklist [] |
static const int | DEFAULT_AUTHLIMIT = 50 |
static const int | DEFAULT_AUTHTIMEOUT = 30 |
static const int | DEFAULT_BROKENEVENTSACTION = 0 |
static const int | DEFAULT_DISPLAYCONNECTS = 1 |
static const int | DEFAULT_ENABLED = 0 |
static const int | DEFAULT_HTTPTIMEOUT = 60 |
static const int | DEFAULT_MANAGERDEBUG = 0 |
static const int | DEFAULT_TIMESTAMPEVENTS = 0 |
static const int | DEFAULT_WEBENABLED = 0 |
static int | displayconnects |
static char | global_realm [MAXHOSTNAMELEN] |
static int | httptimeout |
static char * | manager_channelvars |
static int | manager_debug = 0 |
static int | manager_enabled = 0 |
static struct ast_threadstorage | manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } |
static struct ast_threadstorage | manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } |
static struct permalias | perms [] |
static struct ao2_container * | sessions = NULL |
static int | timestampevents |
static int | unauth_sessions = 0 |
static struct ast_threadstorage | userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } |
static int | webmanager_enabled = 0 |
callback to display queues status in manager
#define ASTMAN_APPEND_BUF_INITSIZE 256 |
initial allocated size for the astman_append_buf
Definition at line 2063 of file manager.c.
Referenced by astman_append().
#define DEFAULT_REALM "asterisk" |
Definition at line 911 of file manager.c.
Referenced by manager_set_defaults(), and reload_config().
#define GET_HEADER_FIRST_MATCH 0 |
Definition at line 1806 of file manager.c.
Referenced by astman_get_header().
#define GET_HEADER_LAST_MATCH 1 |
Definition at line 1807 of file manager.c.
Referenced by __astman_get_header().
#define GET_HEADER_SKIP_EMPTY 2 |
Definition at line 1808 of file manager.c.
Referenced by __astman_get_header(), and process_message().
#define MANAGER_EVENT_BUF_INITSIZE 256 |
Definition at line 5266 of file manager.c.
Referenced by __ast_manager_event_multichan().
#define MAX_BLACKLIST_CMD_LEN 2 |
Descriptor for a manager session, either on the AMI socket or over HTTP.
Definition at line 927 of file manager.c.
Referenced by check_blacklist().
#define MSG_MOREDATA ((char *)astman_send_response) |
send a response with an optional message, and terminate it with an empty line. m is used only to grab the 'ActionID' field.
Use the explicit constant MSG_MOREDATA to remove the empty line. XXX MSG_MOREDATA should go to a header file.
Definition at line 2104 of file manager.c.
Referenced by astman_send_response_full(), and astman_start_ack().
enum error_type |
Doxygen group
UNKNOWN_ACTION | |
UNKNOWN_CATEGORY | |
UNSPECIFIED_CATEGORY | |
UNSPECIFIED_ARGUMENT | |
FAILURE_ALLOCATION | |
FAILURE_NEWCAT | |
FAILURE_DELCAT | |
FAILURE_EMPTYCAT | |
FAILURE_UPDATE | |
FAILURE_DELETE | |
FAILURE_APPEND |
Definition at line 844 of file manager.c.
00844 { 00845 UNKNOWN_ACTION = 1, 00846 UNKNOWN_CATEGORY, 00847 UNSPECIFIED_CATEGORY, 00848 UNSPECIFIED_ARGUMENT, 00849 FAILURE_ALLOCATION, 00850 FAILURE_NEWCAT, 00851 FAILURE_DELCAT, 00852 FAILURE_EMPTYCAT, 00853 FAILURE_UPDATE, 00854 FAILURE_DELETE, 00855 FAILURE_APPEND 00856 };
Definition at line 1002 of file manager.c.
01002 { 01003 MESSAGE_OKAY, 01004 MESSAGE_LINE_TOO_LONG 01005 };
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 * | contents, | |||
... | ||||
) |
External routines may send asterisk manager events this way
category | Event category, matches manager authorization | |
event | Event name | |
chancount | Number of channels in chans parameter | |
chans | A pointer to an array of channels involved in the event | |
contents | Format string describing event |
Definition at line 5268 of file manager.c.
References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, append_channel_vars(), append_event(), ast_atomic_fetchadd_int(), AST_PTHREADT_NULL, AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_append_va(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_tvnow(), authority_to_str(), manager_custom_hook::helper, manager_event_buf, MANAGER_EVENT_BUF_INITSIZE, mansession_session::pending_event, eventqent::seq, sessions, unref_mansession(), and mansession_session::waiting_thread.
05270 { 05271 struct mansession_session *session; 05272 struct manager_custom_hook *hook; 05273 struct ast_str *auth = ast_str_alloca(80); 05274 const char *cat_str; 05275 va_list ap; 05276 struct timeval now; 05277 struct ast_str *buf; 05278 int i; 05279 05280 if (!(sessions && ao2_container_count(sessions)) && AST_RWLIST_EMPTY(&manager_hooks)) { 05281 return 0; 05282 } 05283 05284 if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) { 05285 return -1; 05286 } 05287 05288 cat_str = authority_to_str(category, &auth); 05289 ast_str_set(&buf, 0, 05290 "Event: %s\r\nPrivilege: %s\r\n", 05291 event, cat_str); 05292 05293 if (timestampevents) { 05294 now = ast_tvnow(); 05295 ast_str_append(&buf, 0, 05296 "Timestamp: %ld.%06lu\r\n", 05297 (long)now.tv_sec, (unsigned long) now.tv_usec); 05298 } 05299 if (manager_debug) { 05300 static int seq; 05301 ast_str_append(&buf, 0, 05302 "SequenceNumber: %d\r\n", 05303 ast_atomic_fetchadd_int(&seq, 1)); 05304 ast_str_append(&buf, 0, 05305 "File: %s\r\nLine: %d\r\nFunc: %s\r\n", file, line, func); 05306 } 05307 05308 va_start(ap, fmt); 05309 ast_str_append_va(&buf, 0, fmt, ap); 05310 va_end(ap); 05311 for (i = 0; i < chancount; i++) { 05312 append_channel_vars(&buf, chans[i]); 05313 } 05314 05315 ast_str_append(&buf, 0, "\r\n"); 05316 05317 append_event(ast_str_buffer(buf), category); 05318 05319 /* Wake up any sleeping sessions */ 05320 if (sessions) { 05321 struct ao2_iterator i; 05322 i = ao2_iterator_init(sessions, 0); 05323 while ((session = ao2_iterator_next(&i))) { 05324 ao2_lock(session); 05325 if (session->waiting_thread != AST_PTHREADT_NULL) { 05326 pthread_kill(session->waiting_thread, SIGURG); 05327 } else { 05328 /* We have an event to process, but the mansession is 05329 * not waiting for it. We still need to indicate that there 05330 * is an event waiting so that get_input processes the pending 05331 * event instead of polling. 05332 */ 05333 session->pending_event = 1; 05334 } 05335 ao2_unlock(session); 05336 unref_mansession(session); 05337 } 05338 ao2_iterator_destroy(&i); 05339 } 05340 05341 if (!AST_RWLIST_EMPTY(&manager_hooks)) { 05342 AST_RWLIST_RDLOCK(&manager_hooks); 05343 AST_RWLIST_TRAVERSE(&manager_hooks, hook, list) { 05344 hook->helper(category, event, ast_str_buffer(buf)); 05345 } 05346 AST_RWLIST_UNLOCK(&manager_hooks); 05347 } 05348 05349 return 0; 05350 }
static const char* __astman_get_header | ( | const struct message * | m, | |
char * | var, | |||
int | mode | |||
) | [static] |
Return a matching header value.
Generic function to return either the first or the last matching header from a list of variables, possibly skipping empty strings.
Definition at line 1823 of file manager.c.
References ast_skip_blanks(), ast_strlen_zero(), GET_HEADER_LAST_MATCH, GET_HEADER_SKIP_EMPTY, message::hdrcount, message::headers, and value.
Referenced by astman_get_header(), and process_message().
01824 { 01825 int x, l = strlen(var); 01826 const char *result = ""; 01827 01828 if (!m) { 01829 return result; 01830 } 01831 01832 for (x = 0; x < m->hdrcount; x++) { 01833 const char *h = m->headers[x]; 01834 if (!strncasecmp(var, h, l) && h[l] == ':') { 01835 const char *value = h + l + 1; 01836 value = ast_skip_blanks(value); /* ignore leading spaces in the value */ 01837 /* found a potential candidate */ 01838 if ((mode & GET_HEADER_SKIP_EMPTY) && ast_strlen_zero(value)) { 01839 continue; /* not interesting */ 01840 } 01841 if (mode & GET_HEADER_LAST_MATCH) { 01842 result = value; /* record the last match so far */ 01843 } else { 01844 return value; 01845 } 01846 } 01847 } 01848 01849 return result; 01850 }
static void __init_astman_append_buf | ( | void | ) | [static] |
thread local buffer for astman_append
static void __init_manager_event_buf | ( | void | ) | [static] |
static void __init_manager_event_funcbuf | ( | void | ) | [static] |
static void __init_userevent_buf | ( | void | ) | [static] |
static int action_aocmessage | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3919 of file manager.c.
References ast_aoc_unit_entry::amount, aocmessage_get_unit_entry(), ast_aoc_add_unit_entry(), AST_AOC_BILLING_CALL_DEFLECTION, AST_AOC_BILLING_CALL_FWD_BUSY, AST_AOC_BILLING_CALL_FWD_NO_REPLY, AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL, AST_AOC_BILLING_CALL_TRANSFER, AST_AOC_BILLING_CREDIT_CARD, AST_AOC_BILLING_NA, AST_AOC_BILLING_NORMAL, AST_AOC_BILLING_REVERSE_CHARGE, AST_AOC_CHARGE_CURRENCY, AST_AOC_CHARGE_FREE, AST_AOC_CHARGE_NA, AST_AOC_CHARGE_UNIT, ast_aoc_create(), AST_AOC_D, ast_aoc_destroy_decoded(), ast_aoc_destroy_encoded(), AST_AOC_E, ast_aoc_encode(), AST_AOC_MULT_HUNDRED, AST_AOC_MULT_ONE, AST_AOC_MULT_ONEHUNDREDTH, AST_AOC_MULT_ONETENTH, AST_AOC_MULT_ONETHOUSANDTH, AST_AOC_MULT_TEN, AST_AOC_MULT_THOUSAND, ast_aoc_set_association_id(), ast_aoc_set_association_number(), ast_aoc_set_billing_id(), ast_aoc_set_currency_info(), ast_aoc_set_total_type(), AST_AOC_SUBTOTAL, AST_AOC_TOTAL, ast_channel_get_by_name(), ast_channel_get_by_name_prefix(), ast_channel_unref, AST_CONTROL_AOC, ast_indicate_data(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.
Referenced by __init_manager().
03920 { 03921 const char *channel = astman_get_header(m, "Channel"); 03922 const char *pchannel = astman_get_header(m, "ChannelPrefix"); 03923 const char *msgtype = astman_get_header(m, "MsgType"); 03924 const char *chargetype = astman_get_header(m, "ChargeType"); 03925 const char *currencyname = astman_get_header(m, "CurrencyName"); 03926 const char *currencyamount = astman_get_header(m, "CurrencyAmount"); 03927 const char *mult = astman_get_header(m, "CurrencyMultiplier"); 03928 const char *totaltype = astman_get_header(m, "TotalType"); 03929 const char *aocbillingid = astman_get_header(m, "AOCBillingId"); 03930 const char *association_id= astman_get_header(m, "ChargingAssociationId"); 03931 const char *association_num = astman_get_header(m, "ChargingAssociationNumber"); 03932 const char *association_plan = astman_get_header(m, "ChargingAssociationPlan"); 03933 03934 enum ast_aoc_type _msgtype; 03935 enum ast_aoc_charge_type _chargetype; 03936 enum ast_aoc_currency_multiplier _mult = AST_AOC_MULT_ONE; 03937 enum ast_aoc_total_type _totaltype = AST_AOC_TOTAL; 03938 enum ast_aoc_billing_id _billingid = AST_AOC_BILLING_NA; 03939 unsigned int _currencyamount = 0; 03940 int _association_id = 0; 03941 unsigned int _association_plan = 0; 03942 struct ast_channel *chan = NULL; 03943 03944 struct ast_aoc_decoded *decoded = NULL; 03945 struct ast_aoc_encoded *encoded = NULL; 03946 size_t encoded_size = 0; 03947 03948 if (ast_strlen_zero(channel) && ast_strlen_zero(pchannel)) { 03949 astman_send_error(s, m, "Channel and PartialChannel are not specified. Specify at least one of these."); 03950 goto aocmessage_cleanup; 03951 } 03952 03953 if (!(chan = ast_channel_get_by_name(channel)) && !ast_strlen_zero(pchannel)) { 03954 chan = ast_channel_get_by_name_prefix(pchannel, strlen(pchannel)); 03955 } 03956 03957 if (!chan) { 03958 astman_send_error(s, m, "No such channel"); 03959 goto aocmessage_cleanup; 03960 } 03961 03962 if (ast_strlen_zero(msgtype) || (strcasecmp(msgtype, "d") && strcasecmp(msgtype, "e"))) { 03963 astman_send_error(s, m, "Invalid MsgType"); 03964 goto aocmessage_cleanup; 03965 } 03966 03967 if (ast_strlen_zero(chargetype)) { 03968 astman_send_error(s, m, "ChargeType not specified"); 03969 goto aocmessage_cleanup; 03970 } 03971 03972 _msgtype = strcasecmp(msgtype, "d") ? AST_AOC_E : AST_AOC_D; 03973 03974 if (!strcasecmp(chargetype, "NA")) { 03975 _chargetype = AST_AOC_CHARGE_NA; 03976 } else if (!strcasecmp(chargetype, "Free")) { 03977 _chargetype = AST_AOC_CHARGE_FREE; 03978 } else if (!strcasecmp(chargetype, "Currency")) { 03979 _chargetype = AST_AOC_CHARGE_CURRENCY; 03980 } else if (!strcasecmp(chargetype, "Unit")) { 03981 _chargetype = AST_AOC_CHARGE_UNIT; 03982 } else { 03983 astman_send_error(s, m, "Invalid ChargeType"); 03984 goto aocmessage_cleanup; 03985 } 03986 03987 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 03988 03989 if (ast_strlen_zero(currencyamount) || (sscanf(currencyamount, "%30u", &_currencyamount) != 1)) { 03990 astman_send_error(s, m, "Invalid CurrencyAmount, CurrencyAmount is a required when ChargeType is Currency"); 03991 goto aocmessage_cleanup; 03992 } 03993 03994 if (ast_strlen_zero(mult)) { 03995 astman_send_error(s, m, "ChargeMultiplier unspecified, ChargeMultiplier is required when ChargeType is Currency."); 03996 goto aocmessage_cleanup; 03997 } else if (!strcasecmp(mult, "onethousandth")) { 03998 _mult = AST_AOC_MULT_ONETHOUSANDTH; 03999 } else if (!strcasecmp(mult, "onehundredth")) { 04000 _mult = AST_AOC_MULT_ONEHUNDREDTH; 04001 } else if (!strcasecmp(mult, "onetenth")) { 04002 _mult = AST_AOC_MULT_ONETENTH; 04003 } else if (!strcasecmp(mult, "one")) { 04004 _mult = AST_AOC_MULT_ONE; 04005 } else if (!strcasecmp(mult, "ten")) { 04006 _mult = AST_AOC_MULT_TEN; 04007 } else if (!strcasecmp(mult, "hundred")) { 04008 _mult = AST_AOC_MULT_HUNDRED; 04009 } else if (!strcasecmp(mult, "thousand")) { 04010 _mult = AST_AOC_MULT_THOUSAND; 04011 } else { 04012 astman_send_error(s, m, "Invalid ChargeMultiplier"); 04013 goto aocmessage_cleanup; 04014 } 04015 } 04016 04017 /* create decoded object and start setting values */ 04018 if (!(decoded = ast_aoc_create(_msgtype, _chargetype, 0))) { 04019 astman_send_error(s, m, "Message Creation Failed"); 04020 goto aocmessage_cleanup; 04021 } 04022 04023 if (_msgtype == AST_AOC_D) { 04024 if (!ast_strlen_zero(totaltype) && !strcasecmp(totaltype, "subtotal")) { 04025 _totaltype = AST_AOC_SUBTOTAL; 04026 } 04027 04028 if (ast_strlen_zero(aocbillingid)) { 04029 /* ignore this is optional */ 04030 } else if (!strcasecmp(aocbillingid, "Normal")) { 04031 _billingid = AST_AOC_BILLING_NORMAL; 04032 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04033 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04034 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04035 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04036 } else { 04037 astman_send_error(s, m, "Invalid AOC-D AOCBillingId"); 04038 goto aocmessage_cleanup; 04039 } 04040 } else { 04041 if (ast_strlen_zero(aocbillingid)) { 04042 /* ignore this is optional */ 04043 } else if (!strcasecmp(aocbillingid, "Normal")) { 04044 _billingid = AST_AOC_BILLING_NORMAL; 04045 } else if (!strcasecmp(aocbillingid, "ReverseCharge")) { 04046 _billingid = AST_AOC_BILLING_REVERSE_CHARGE; 04047 } else if (!strcasecmp(aocbillingid, "CreditCard")) { 04048 _billingid = AST_AOC_BILLING_CREDIT_CARD; 04049 } else if (!strcasecmp(aocbillingid, "CallFwdUnconditional")) { 04050 _billingid = AST_AOC_BILLING_CALL_FWD_UNCONDITIONAL; 04051 } else if (!strcasecmp(aocbillingid, "CallFwdBusy")) { 04052 _billingid = AST_AOC_BILLING_CALL_FWD_BUSY; 04053 } else if (!strcasecmp(aocbillingid, "CallFwdNoReply")) { 04054 _billingid = AST_AOC_BILLING_CALL_FWD_NO_REPLY; 04055 } else if (!strcasecmp(aocbillingid, "CallDeflection")) { 04056 _billingid = AST_AOC_BILLING_CALL_DEFLECTION; 04057 } else if (!strcasecmp(aocbillingid, "CallTransfer")) { 04058 _billingid = AST_AOC_BILLING_CALL_TRANSFER; 04059 } else { 04060 astman_send_error(s, m, "Invalid AOC-E AOCBillingId"); 04061 goto aocmessage_cleanup; 04062 } 04063 04064 if (!ast_strlen_zero(association_id) && (sscanf(association_id, "%30d", &_association_id) != 1)) { 04065 astman_send_error(s, m, "Invalid ChargingAssociationId"); 04066 goto aocmessage_cleanup; 04067 } 04068 if (!ast_strlen_zero(association_plan) && (sscanf(association_plan, "%30u", &_association_plan) != 1)) { 04069 astman_send_error(s, m, "Invalid ChargingAssociationPlan"); 04070 goto aocmessage_cleanup; 04071 } 04072 04073 if (_association_id) { 04074 ast_aoc_set_association_id(decoded, _association_id); 04075 } else if (!ast_strlen_zero(association_num)) { 04076 ast_aoc_set_association_number(decoded, association_num, _association_plan); 04077 } 04078 } 04079 04080 if (_chargetype == AST_AOC_CHARGE_CURRENCY) { 04081 ast_aoc_set_currency_info(decoded, _currencyamount, _mult, ast_strlen_zero(currencyname) ? NULL : currencyname); 04082 } else if (_chargetype == AST_AOC_CHARGE_UNIT) { 04083 struct ast_aoc_unit_entry entry; 04084 int i; 04085 04086 /* multiple unit entries are possible, lets get them all */ 04087 for (i = 0; i < 32; i++) { 04088 if (aocmessage_get_unit_entry(m, &entry, i)) { 04089 break; /* that's the end then */ 04090 } 04091 04092 ast_aoc_add_unit_entry(decoded, entry.valid_amount, entry.amount, entry.valid_type, entry.type); 04093 } 04094 04095 /* at least one unit entry is required */ 04096 if (!i) { 04097 astman_send_error(s, m, "Invalid UnitAmount(0), At least one valid unit entry is required when ChargeType is set to Unit"); 04098 goto aocmessage_cleanup; 04099 } 04100 04101 } 04102 04103 ast_aoc_set_billing_id(decoded, _billingid); 04104 ast_aoc_set_total_type(decoded, _totaltype); 04105 04106 04107 if ((encoded = ast_aoc_encode(decoded, &encoded_size, NULL)) && !ast_indicate_data(chan, AST_CONTROL_AOC, encoded, encoded_size)) { 04108 astman_send_ack(s, m, "AOC Message successfully queued on channel"); 04109 } else { 04110 astman_send_error(s, m, "Error encoding AOC message, could not queue onto channel"); 04111 } 04112 04113 aocmessage_cleanup: 04114 04115 ast_aoc_destroy_decoded(decoded); 04116 ast_aoc_destroy_encoded(encoded); 04117 04118 if (chan) { 04119 chan = ast_channel_unref(chan); 04120 } 04121 return 0; 04122 }
static int action_atxfer | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3647 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_find_call_feature(), AST_FRAME_DTMF, ast_queue_frame(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, ast_call_feature::exten, exten, and pbx_builtin_setvar_helper().
Referenced by __init_manager().
03648 { 03649 const char *name = astman_get_header(m, "Channel"); 03650 const char *exten = astman_get_header(m, "Exten"); 03651 const char *context = astman_get_header(m, "Context"); 03652 struct ast_channel *chan = NULL; 03653 struct ast_call_feature *atxfer_feature = NULL; 03654 char *feature_code = NULL; 03655 03656 if (ast_strlen_zero(name)) { 03657 astman_send_error(s, m, "No channel specified"); 03658 return 0; 03659 } 03660 if (ast_strlen_zero(exten)) { 03661 astman_send_error(s, m, "No extension specified"); 03662 return 0; 03663 } 03664 03665 if (!(atxfer_feature = ast_find_call_feature("atxfer"))) { 03666 astman_send_error(s, m, "No attended transfer feature found"); 03667 return 0; 03668 } 03669 03670 if (!(chan = ast_channel_get_by_name(name))) { 03671 astman_send_error(s, m, "Channel specified does not exist"); 03672 return 0; 03673 } 03674 03675 if (!ast_strlen_zero(context)) { 03676 pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); 03677 } 03678 03679 for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { 03680 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03681 ast_queue_frame(chan, &f); 03682 } 03683 03684 for (feature_code = (char *)exten; feature_code && *feature_code; ++feature_code) { 03685 struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; 03686 ast_queue_frame(chan, &f); 03687 } 03688 03689 chan = ast_channel_unref(chan); 03690 03691 astman_send_ack(s, m, "Atxfer successfully queued"); 03692 03693 return 0; 03694 }
static int action_challenge | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3149 of file manager.c.
References ast_random(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), mansession_session::challenge, mansession_lock(), mansession_unlock(), and mansession::session.
Referenced by __init_manager().
03150 { 03151 const char *authtype = astman_get_header(m, "AuthType"); 03152 03153 if (!strcasecmp(authtype, "MD5")) { 03154 if (ast_strlen_zero(s->session->challenge)) { 03155 snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random()); 03156 } 03157 mansession_lock(s); 03158 astman_start_ack(s, m); 03159 astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge); 03160 mansession_unlock(s); 03161 } else { 03162 astman_send_error(s, m, "Must specify AuthType"); 03163 } 03164 return 0; 03165 }
static int action_command | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager command "command" - execute CLI command.
Definition at line 3732 of file manager.c.
References ast_cli_command, ast_free, ast_log(), AST_LOG_WARNING, ast_malloc, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), check_blacklist(), errno, LOG_WARNING, and term_strip().
Referenced by __init_manager().
03733 { 03734 const char *cmd = astman_get_header(m, "Command"); 03735 const char *id = astman_get_header(m, "ActionID"); 03736 char *buf = NULL, *final_buf = NULL; 03737 char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */ 03738 int fd; 03739 off_t l; 03740 03741 if (ast_strlen_zero(cmd)) { 03742 astman_send_error(s, m, "No command provided"); 03743 return 0; 03744 } 03745 03746 if (check_blacklist(cmd)) { 03747 astman_send_error(s, m, "Command blacklisted"); 03748 return 0; 03749 } 03750 03751 if ((fd = mkstemp(template)) < 0) { 03752 ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno)); 03753 astman_send_error(s, m, "Command response construction error"); 03754 return 0; 03755 } 03756 03757 astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n"); 03758 if (!ast_strlen_zero(id)) { 03759 astman_append(s, "ActionID: %s\r\n", id); 03760 } 03761 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 03762 ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */ 03763 /* Determine number of characters available */ 03764 if ((l = lseek(fd, 0, SEEK_END)) < 0) { 03765 ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno)); 03766 goto action_command_cleanup; 03767 } 03768 03769 /* This has a potential to overflow the stack. Hence, use the heap. */ 03770 buf = ast_malloc(l + 1); 03771 final_buf = ast_malloc(l + 1); 03772 03773 if (!buf || !final_buf) { 03774 ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n"); 03775 goto action_command_cleanup; 03776 } 03777 03778 if (lseek(fd, 0, SEEK_SET) < 0) { 03779 ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno)); 03780 goto action_command_cleanup; 03781 } 03782 03783 if (read(fd, buf, l) < 0) { 03784 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 03785 goto action_command_cleanup; 03786 } 03787 03788 buf[l] = '\0'; 03789 term_strip(final_buf, buf, l); 03790 final_buf[l] = '\0'; 03791 astman_append(s, "%s", final_buf); 03792 03793 action_command_cleanup: 03794 03795 close(fd); 03796 unlink(template); 03797 astman_append(s, "--END COMMAND--\r\n\r\n"); 03798 03799 ast_free(buf); 03800 ast_free(final_buf); 03801 03802 return 0; 03803 }
static int action_coresettings | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core settings information.
Definition at line 4468 of file manager.c.
References AMI_VERSION, AST_CLI_YESNO, ast_config_AST_RUN_GROUP, ast_config_AST_RUN_USER, ast_config_AST_SYSTEM_NAME, ast_get_version(), ast_realtime_enabled(), ast_strlen_zero(), astman_append(), astman_get_header(), check_cdr_enabled(), check_webmanager_enabled(), option_maxcalls, option_maxfiles, and option_maxload.
Referenced by __init_manager().
04469 { 04470 const char *actionid = astman_get_header(m, "ActionID"); 04471 char idText[150]; 04472 04473 if (!ast_strlen_zero(actionid)) { 04474 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04475 } else { 04476 idText[0] = '\0'; 04477 } 04478 04479 astman_append(s, "Response: Success\r\n" 04480 "%s" 04481 "AMIversion: %s\r\n" 04482 "AsteriskVersion: %s\r\n" 04483 "SystemName: %s\r\n" 04484 "CoreMaxCalls: %d\r\n" 04485 "CoreMaxLoadAvg: %f\r\n" 04486 "CoreRunUser: %s\r\n" 04487 "CoreRunGroup: %s\r\n" 04488 "CoreMaxFilehandles: %d\r\n" 04489 "CoreRealTimeEnabled: %s\r\n" 04490 "CoreCDRenabled: %s\r\n" 04491 "CoreHTTPenabled: %s\r\n" 04492 "\r\n", 04493 idText, 04494 AMI_VERSION, 04495 ast_get_version(), 04496 ast_config_AST_SYSTEM_NAME, 04497 option_maxcalls, 04498 option_maxload, 04499 ast_config_AST_RUN_USER, 04500 ast_config_AST_RUN_GROUP, 04501 option_maxfiles, 04502 AST_CLI_YESNO(ast_realtime_enabled()), 04503 AST_CLI_YESNO(check_cdr_enabled()), 04504 AST_CLI_YESNO(check_webmanager_enabled()) 04505 ); 04506 return 0; 04507 }
static int action_coreshowchannels | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager command "CoreShowChannels" - List currently defined channels and some information about them.
Definition at line 4577 of file manager.c.
References ast_channel::_state, ast_channel::appl, ast_bridged_channel(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_state2str(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), ast_channel::caller, ast_channel::cdr, ast_channel::connected, ast_channel::context, ast_channel::data, ast_channel::exten, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::priority, S_COR, S_OR, ast_cdr::start, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by __init_manager().
04578 { 04579 const char *actionid = astman_get_header(m, "ActionID"); 04580 char idText[256]; 04581 struct ast_channel *c = NULL; 04582 int numchans = 0; 04583 int duration, durh, durm, durs; 04584 struct ast_channel_iterator *iter; 04585 04586 if (!ast_strlen_zero(actionid)) { 04587 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04588 } else { 04589 idText[0] = '\0'; 04590 } 04591 04592 if (!(iter = ast_channel_iterator_all_new())) { 04593 astman_send_error(s, m, "Memory Allocation Failure"); 04594 return 1; 04595 } 04596 04597 astman_send_listack(s, m, "Channels will follow", "start"); 04598 04599 for (; (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) { 04600 struct ast_channel *bc; 04601 char durbuf[10] = ""; 04602 04603 ast_channel_lock(c); 04604 04605 bc = ast_bridged_channel(c); 04606 if (c->cdr && !ast_tvzero(c->cdr->start)) { 04607 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000); 04608 durh = duration / 3600; 04609 durm = (duration % 3600) / 60; 04610 durs = duration % 60; 04611 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs); 04612 } 04613 04614 astman_append(s, 04615 "Event: CoreShowChannel\r\n" 04616 "%s" 04617 "Channel: %s\r\n" 04618 "UniqueID: %s\r\n" 04619 "Context: %s\r\n" 04620 "Extension: %s\r\n" 04621 "Priority: %d\r\n" 04622 "ChannelState: %u\r\n" 04623 "ChannelStateDesc: %s\r\n" 04624 "Application: %s\r\n" 04625 "ApplicationData: %s\r\n" 04626 "CallerIDnum: %s\r\n" 04627 "CallerIDname: %s\r\n" 04628 "ConnectedLineNum: %s\r\n" 04629 "ConnectedLineName: %s\r\n" 04630 "Duration: %s\r\n" 04631 "AccountCode: %s\r\n" 04632 "BridgedChannel: %s\r\n" 04633 "BridgedUniqueID: %s\r\n" 04634 "\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, 04635 ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "", 04636 S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""), 04637 S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""), 04638 S_COR(c->connected.id.number.valid, c->connected.id.number.str, ""), 04639 S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""), 04640 durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : ""); 04641 04642 ast_channel_unlock(c); 04643 04644 numchans++; 04645 } 04646 04647 astman_append(s, 04648 "Event: CoreShowChannelsComplete\r\n" 04649 "EventList: Complete\r\n" 04650 "ListItems: %d\r\n" 04651 "%s" 04652 "\r\n", numchans, idText); 04653 04654 ast_channel_iterator_destroy(iter); 04655 04656 return 0; 04657 }
static int action_corestatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Show PBX core status information.
Definition at line 4510 of file manager.c.
References ast_active_channels(), ast_lastreloadtime, ast_localtime(), ast_startuptime, ast_strftime(), ast_strlen_zero(), astman_append(), and astman_get_header().
Referenced by __init_manager().
04511 { 04512 const char *actionid = astman_get_header(m, "ActionID"); 04513 char idText[150]; 04514 char startuptime[150], startupdate[150]; 04515 char reloadtime[150], reloaddate[150]; 04516 struct ast_tm tm; 04517 04518 if (!ast_strlen_zero(actionid)) { 04519 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", actionid); 04520 } else { 04521 idText[0] = '\0'; 04522 } 04523 04524 ast_localtime(&ast_startuptime, &tm, NULL); 04525 ast_strftime(startuptime, sizeof(startuptime), "%H:%M:%S", &tm); 04526 ast_strftime(startupdate, sizeof(startupdate), "%Y-%m-%d", &tm); 04527 ast_localtime(&ast_lastreloadtime, &tm, NULL); 04528 ast_strftime(reloadtime, sizeof(reloadtime), "%H:%M:%S", &tm); 04529 ast_strftime(reloaddate, sizeof(reloaddate), "%Y-%m-%d", &tm); 04530 04531 astman_append(s, "Response: Success\r\n" 04532 "%s" 04533 "CoreStartupDate: %s\r\n" 04534 "CoreStartupTime: %s\r\n" 04535 "CoreReloadDate: %s\r\n" 04536 "CoreReloadTime: %s\r\n" 04537 "CoreCurrentCalls: %d\r\n" 04538 "\r\n", 04539 idText, 04540 startupdate, 04541 startuptime, 04542 reloaddate, 04543 reloadtime, 04544 ast_active_channels() 04545 ); 04546 return 0; 04547 }
static int action_createconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2923 of file manager.c.
References ast_config_AST_CONFIG_DIR, AST_FILE_MODE, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), astman_get_header(), astman_send_ack(), astman_send_error(), and errno.
Referenced by __init_manager().
02924 { 02925 int fd; 02926 const char *fn = astman_get_header(m, "Filename"); 02927 struct ast_str *filepath = ast_str_alloca(PATH_MAX); 02928 ast_str_set(&filepath, 0, "%s/", ast_config_AST_CONFIG_DIR); 02929 ast_str_append(&filepath, 0, "%s", fn); 02930 02931 if ((fd = open(ast_str_buffer(filepath), O_CREAT | O_EXCL, AST_FILE_MODE)) != -1) { 02932 close(fd); 02933 astman_send_ack(s, m, "New configuration file created successfully"); 02934 } else { 02935 astman_send_error(s, m, strerror(errno)); 02936 } 02937 02938 return 0; 02939 }
static void action_destroy | ( | void * | obj | ) | [static] |
Definition at line 5457 of file manager.c.
References ast_string_field_free_memory.
Referenced by ast_manager_register2().
05458 { 05459 struct manager_action *doomed = obj; 05460 05461 if (doomed->synopsis) { 05462 /* The string fields were initialized. */ 05463 ast_string_field_free_memory(doomed); 05464 } 05465 }
static int action_events | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3067 of file manager.c.
References ARRAY_LEN, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), permalias::num, perms, and set_eventmask().
Referenced by __init_manager().
03068 { 03069 const char *mask = astman_get_header(m, "EventMask"); 03070 int res, x; 03071 const char *id = astman_get_header(m, "ActionID"); 03072 char id_text[256]; 03073 03074 if (!ast_strlen_zero(id)) { 03075 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); 03076 } else { 03077 id_text[0] = '\0'; 03078 } 03079 03080 res = set_eventmask(s, mask); 03081 if (broken_events_action) { 03082 /* if this option is set we should not return a response on 03083 * error, or when all events are set */ 03084 03085 if (res > 0) { 03086 for (x = 0; x < ARRAY_LEN(perms); x++) { 03087 if (!strcasecmp(perms[x].label, "all") && res == perms[x].num) { 03088 return 0; 03089 } 03090 } 03091 astman_append(s, "Response: Success\r\n%s" 03092 "Events: On\r\n\r\n", id_text); 03093 } else if (res == 0) 03094 astman_append(s, "Response: Success\r\n%s" 03095 "Events: Off\r\n\r\n", id_text); 03096 return 0; 03097 } 03098 03099 if (res > 0) 03100 astman_append(s, "Response: Success\r\n%s" 03101 "Events: On\r\n\r\n", id_text); 03102 else if (res == 0) 03103 astman_append(s, "Response: Success\r\n%s" 03104 "Events: Off\r\n\r\n", id_text); 03105 else 03106 astman_send_error(s, m, "Invalid event mask"); 03107 03108 return 0; 03109 }
static int action_extensionstate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4306 of file manager.c.
References ast_extension_state(), ast_get_hint(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), context, exten, and status.
Referenced by __init_manager().
04307 { 04308 const char *exten = astman_get_header(m, "Exten"); 04309 const char *context = astman_get_header(m, "Context"); 04310 char hint[256] = ""; 04311 int status; 04312 if (ast_strlen_zero(exten)) { 04313 astman_send_error(s, m, "Extension not specified"); 04314 return 0; 04315 } 04316 if (ast_strlen_zero(context)) { 04317 context = "default"; 04318 } 04319 status = ast_extension_state(NULL, context, exten); 04320 ast_get_hint(hint, sizeof(hint) - 1, NULL, 0, NULL, context, exten); 04321 astman_start_ack(s, m); 04322 astman_append(s, "Message: Extension Status\r\n" 04323 "Exten: %s\r\n" 04324 "Context: %s\r\n" 04325 "Hint: %s\r\n" 04326 "Status: %d\r\n\r\n", 04327 exten, context, hint, status); 04328 return 0; 04329 }
static struct manager_action* action_find | ( | const char * | name | ) | [static, read] |
Definition at line 1075 of file manager.c.
References manager_action::action, ao2_t_ref, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, and AST_RWLIST_UNLOCK.
Referenced by ast_hook_send_action(), and process_message().
01076 { 01077 struct manager_action *act; 01078 01079 AST_RWLIST_RDLOCK(&actions); 01080 AST_RWLIST_TRAVERSE(&actions, act, list) { 01081 if (!strcasecmp(name, act->action)) { 01082 ao2_t_ref(act, +1, "found action object"); 01083 break; 01084 } 01085 } 01086 AST_RWLIST_UNLOCK(&actions); 01087 01088 return act; 01089 }
static int action_getconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2537 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02538 { 02539 struct ast_config *cfg; 02540 const char *fn = astman_get_header(m, "Filename"); 02541 const char *category = astman_get_header(m, "Category"); 02542 int catcount = 0; 02543 int lineno = 0; 02544 char *cur_category = NULL; 02545 struct ast_variable *v; 02546 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02547 02548 if (ast_strlen_zero(fn)) { 02549 astman_send_error(s, m, "Filename not specified"); 02550 return 0; 02551 } 02552 cfg = ast_config_load2(fn, "manager", config_flags); 02553 if (cfg == CONFIG_STATUS_FILEMISSING) { 02554 astman_send_error(s, m, "Config file not found"); 02555 return 0; 02556 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02557 astman_send_error(s, m, "Config file has invalid format"); 02558 return 0; 02559 } 02560 02561 astman_start_ack(s, m); 02562 while ((cur_category = ast_category_browse(cfg, cur_category))) { 02563 if (ast_strlen_zero(category) || (!ast_strlen_zero(category) && !strcmp(category, cur_category))) { 02564 lineno = 0; 02565 astman_append(s, "Category-%06d: %s\r\n", catcount, cur_category); 02566 for (v = ast_variable_browse(cfg, cur_category); v; v = v->next) { 02567 astman_append(s, "Line-%06d-%06d: %s=%s\r\n", catcount, lineno++, v->name, v->value); 02568 } 02569 catcount++; 02570 } 02571 } 02572 if (!ast_strlen_zero(category) && catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02573 astman_append(s, "No categories found\r\n"); 02574 } 02575 ast_config_destroy(cfg); 02576 astman_append(s, "\r\n"); 02577 02578 return 0; 02579 }
static int action_getconfigjson | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2647 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), ast_variable_browse(), astman_append(), astman_append_json(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by __init_manager().
02648 { 02649 struct ast_config *cfg; 02650 const char *fn = astman_get_header(m, "Filename"); 02651 char *category = NULL; 02652 struct ast_variable *v; 02653 int comma1 = 0; 02654 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02655 02656 if (ast_strlen_zero(fn)) { 02657 astman_send_error(s, m, "Filename not specified"); 02658 return 0; 02659 } 02660 02661 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02662 astman_send_error(s, m, "Config file not found"); 02663 return 0; 02664 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02665 astman_send_error(s, m, "Config file has invalid format"); 02666 return 0; 02667 } 02668 02669 astman_start_ack(s, m); 02670 astman_append(s, "JSON: {"); 02671 while ((category = ast_category_browse(cfg, category))) { 02672 int comma2 = 0; 02673 02674 astman_append(s, "%s\"", comma1 ? "," : ""); 02675 astman_append_json(s, category); 02676 astman_append(s, "\":["); 02677 comma1 = 1; 02678 for (v = ast_variable_browse(cfg, category); v; v = v->next) { 02679 astman_append(s, "%s\"", comma2 ? "," : ""); 02680 astman_append_json(s, v->name); 02681 astman_append(s, "\":\""); 02682 astman_append_json(s, v->value); 02683 astman_append(s, "\""); 02684 comma2 = 1; 02685 } 02686 astman_append(s, "]"); 02687 } 02688 astman_append(s, "}\r\n\r\n"); 02689 02690 ast_config_destroy(cfg); 02691 02692 return 0; 02693 }
static int action_getvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3243 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_dummy_channel_alloc, ast_func_read(), ast_log(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), function_capable_string_allowed_with_auths(), LOG_ERROR, pbx_retrieve_variable(), S_OR, mansession::session, and mansession_session::writeperm.
Referenced by __init_manager().
03244 { 03245 struct ast_channel *c = NULL; 03246 const char *name = astman_get_header(m, "Channel"); 03247 const char *varname = astman_get_header(m, "Variable"); 03248 char *varval; 03249 char workspace[1024]; 03250 03251 if (ast_strlen_zero(varname)) { 03252 astman_send_error(s, m, "No variable specified"); 03253 return 0; 03254 } 03255 03256 /* We don't want users with insufficient permissions using certain functions. */ 03257 if (!(function_capable_string_allowed_with_auths(varname, s->session->writeperm))) { 03258 astman_send_error(s, m, "GetVar Access Forbidden: Variable"); 03259 return 0; 03260 } 03261 03262 if (!ast_strlen_zero(name)) { 03263 if (!(c = ast_channel_get_by_name(name))) { 03264 astman_send_error(s, m, "No such channel"); 03265 return 0; 03266 } 03267 } 03268 03269 workspace[0] = '\0'; 03270 if (varname[strlen(varname) - 1] == ')') { 03271 if (!c) { 03272 c = ast_dummy_channel_alloc(); 03273 if (c) { 03274 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03275 } else 03276 ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n"); 03277 } else { 03278 ast_func_read(c, (char *) varname, workspace, sizeof(workspace)); 03279 } 03280 varval = workspace; 03281 } else { 03282 pbx_retrieve_variable(c, varname, &varval, workspace, sizeof(workspace), NULL); 03283 } 03284 03285 if (c) { 03286 c = ast_channel_unref(c); 03287 } 03288 03289 astman_start_ack(s, m); 03290 astman_append(s, "Variable: %s\r\nValue: %s\r\n\r\n", varname, S_OR(varval, "")); 03291 03292 return 0; 03293 }
static int action_hangup | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3167 of file manager.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_debug, ast_log(), AST_SOFTHANGUP_EXPLICIT, ast_softhangup_nolock(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::hangupcause, and LOG_NOTICE.
Referenced by __init_manager().
03168 { 03169 struct ast_channel *c = NULL; 03170 int causecode = 0; /* all values <= 0 mean 'do not set hangupcause in channel' */ 03171 const char *name = astman_get_header(m, "Channel"); 03172 const char *cause = astman_get_header(m, "Cause"); 03173 03174 if (ast_strlen_zero(name)) { 03175 astman_send_error(s, m, "No channel specified"); 03176 return 0; 03177 } 03178 03179 if (!ast_strlen_zero(cause)) { 03180 char *endptr; 03181 causecode = strtol(cause, &endptr, 10); 03182 if (causecode < 0 || causecode > 127 || *endptr != '\0') { 03183 ast_log(LOG_NOTICE, "Invalid 'Cause: %s' in manager action Hangup\n", cause); 03184 /* keep going, better to hangup without cause than to not hang up at all */ 03185 causecode = 0; /* do not set channel's hangupcause */ 03186 } 03187 } 03188 03189 if (!(c = ast_channel_get_by_name(name))) { 03190 astman_send_error(s, m, "No such channel"); 03191 return 0; 03192 } 03193 03194 ast_channel_lock(c); 03195 if (causecode > 0) { 03196 ast_debug(1, "Setting hangupcause of channel %s to %d (is %d now)\n", 03197 c->name, causecode, c->hangupcause); 03198 c->hangupcause = causecode; 03199 } 03200 ast_softhangup_nolock(c, AST_SOFTHANGUP_EXPLICIT); 03201 ast_channel_unlock(c); 03202 03203 c = ast_channel_unref(c); 03204 03205 astman_send_ack(s, m, "Channel Hungup"); 03206 03207 return 0; 03208 }
static int action_listcategories | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2581 of file manager.c.
References ast_category_browse(), ast_config_destroy(), ast_config_load2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), eventqent::category, CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, and CONFIG_STATUS_FILEINVALID.
Referenced by __init_manager().
02582 { 02583 struct ast_config *cfg; 02584 const char *fn = astman_get_header(m, "Filename"); 02585 char *category = NULL; 02586 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02587 int catcount = 0; 02588 02589 if (ast_strlen_zero(fn)) { 02590 astman_send_error(s, m, "Filename not specified"); 02591 return 0; 02592 } 02593 if (!(cfg = ast_config_load2(fn, "manager", config_flags))) { 02594 astman_send_error(s, m, "Config file not found"); 02595 return 0; 02596 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02597 astman_send_error(s, m, "Config file has invalid format"); 02598 return 0; 02599 } 02600 astman_start_ack(s, m); 02601 while ((category = ast_category_browse(cfg, category))) { 02602 astman_append(s, "Category-%06d: %s\r\n", catcount, category); 02603 catcount++; 02604 } 02605 if (catcount == 0) { /* TODO: actually, a config with no categories doesn't even get loaded */ 02606 astman_append(s, "Error: no categories found\r\n"); 02607 } 02608 ast_config_destroy(cfg); 02609 astman_append(s, "\r\n"); 02610 02611 return 0; 02612 }
static int action_listcommands | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3048 of file manager.c.
References manager_action::action, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, astman_append(), astman_start_ack(), manager_action::authority, authority_to_str(), mansession::session, and mansession_session::writeperm.
Referenced by __init_manager().
03049 { 03050 struct manager_action *cur; 03051 struct ast_str *temp = ast_str_alloca(256); 03052 03053 astman_start_ack(s, m); 03054 AST_RWLIST_RDLOCK(&actions); 03055 AST_RWLIST_TRAVERSE(&actions, cur, list) { 03056 if ((s->session->writeperm & cur->authority) || cur->authority == 0) { 03057 astman_append(s, "%s: %s (Priv: %s)\r\n", 03058 cur->action, cur->synopsis, authority_to_str(cur->authority, &temp)); 03059 } 03060 } 03061 AST_RWLIST_UNLOCK(&actions); 03062 astman_append(s, "\r\n"); 03063 03064 return 0; 03065 }
static int action_login | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3117 of file manager.c.
References ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_OPT_FLAG_FULLY_BOOTED, ast_options, ast_str_alloca, ast_test_flag, ast_verb, astman_append(), astman_send_ack(), astman_send_error(), authenticate(), mansession_session::authenticated, authority_to_str(), EVENT_FLAG_SYSTEM, manager_displayconnects(), mansession_session::managerid, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sin, unauth_sessions, and mansession_session::username.
Referenced by __init_manager().
03118 { 03119 03120 /* still authenticated - don't process again */ 03121 if (s->session->authenticated) { 03122 astman_send_ack(s, m, "Already authenticated"); 03123 return 0; 03124 } 03125 03126 if (authenticate(s, m)) { 03127 sleep(1); 03128 astman_send_error(s, m, "Authentication failed"); 03129 return -1; 03130 } 03131 s->session->authenticated = 1; 03132 ast_atomic_fetchadd_int(&unauth_sessions, -1); 03133 if (manager_displayconnects(s->session)) { 03134 ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr)); 03135 } 03136 astman_send_ack(s, m, "Authentication accepted"); 03137 if ((s->session->send_events & EVENT_FLAG_SYSTEM) 03138 && (s->session->readperm & EVENT_FLAG_SYSTEM) 03139 && ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) { 03140 struct ast_str *auth = ast_str_alloca(80); 03141 const char *cat_str = authority_to_str(EVENT_FLAG_SYSTEM, &auth); 03142 astman_append(s, "Event: FullyBooted\r\n" 03143 "Privilege: %s\r\n" 03144 "Status: Fully Booted\r\n\r\n", cat_str); 03145 } 03146 return 0; 03147 }
static int action_logoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3111 of file manager.c.
References astman_send_response().
Referenced by __init_manager().
03112 { 03113 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 03114 return -1; 03115 }
static int action_mailboxcount | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4285 of file manager.c.
References ast_app_inboxcount2(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.
Referenced by __init_manager().
04286 { 04287 const char *mailbox = astman_get_header(m, "Mailbox"); 04288 int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0;; 04289 04290 if (ast_strlen_zero(mailbox)) { 04291 astman_send_error(s, m, "Mailbox not specified"); 04292 return 0; 04293 } 04294 ast_app_inboxcount2(mailbox, &urgentmsgs, &newmsgs, &oldmsgs); 04295 astman_start_ack(s, m); 04296 astman_append(s, "Message: Mailbox Message Count\r\n" 04297 "Mailbox: %s\r\n" 04298 "UrgMessages: %d\r\n" 04299 "NewMessages: %d\r\n" 04300 "OldMessages: %d\r\n" 04301 "\r\n", 04302 mailbox, urgentmsgs, newmsgs, oldmsgs); 04303 return 0; 04304 }
static int action_mailboxstatus | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4268 of file manager.c.
References ast_app_has_voicemail(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_start_ack(), and mailbox.
Referenced by __init_manager().
04269 { 04270 const char *mailbox = astman_get_header(m, "Mailbox"); 04271 int ret; 04272 04273 if (ast_strlen_zero(mailbox)) { 04274 astman_send_error(s, m, "Mailbox not specified"); 04275 return 0; 04276 } 04277 ret = ast_app_has_voicemail(mailbox, NULL); 04278 astman_start_ack(s, m); 04279 astman_append(s, "Message: Mailbox Status\r\n" 04280 "Mailbox: %s\r\n" 04281 "Waiting: %d\r\n\r\n", mailbox, ret); 04282 return 0; 04283 }
static int action_originate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4124 of file manager.c.
References app, ast_callerid_parse(), ast_calloc, ast_copy_string(), ast_findlabel_extension(), AST_FORMAT_SLINEAR, ast_free, ast_parse_allow_disallow(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_pthread_create_detached, ast_shrink_phone_number(), ast_string_field_build, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variables_destroy(), astman_get_header(), astman_get_variables(), astman_send_ack(), astman_send_error(), cid_name, cid_num, context, ast_frame::data, destroy_fast_originate_helper(), EVENT_FLAG_SYSTEM, exten, fast_originate(), fast_originate_helper::format, fast_originate_helper::priority, mansession::session, fast_originate_helper::timeout, fast_originate_helper::vars, and mansession_session::writeperm.
Referenced by __init_manager().
04125 { 04126 const char *name = astman_get_header(m, "Channel"); 04127 const char *exten = astman_get_header(m, "Exten"); 04128 const char *context = astman_get_header(m, "Context"); 04129 const char *priority = astman_get_header(m, "Priority"); 04130 const char *timeout = astman_get_header(m, "Timeout"); 04131 const char *callerid = astman_get_header(m, "CallerID"); 04132 const char *account = astman_get_header(m, "Account"); 04133 const char *app = astman_get_header(m, "Application"); 04134 const char *appdata = astman_get_header(m, "Data"); 04135 const char *async = astman_get_header(m, "Async"); 04136 const char *id = astman_get_header(m, "ActionID"); 04137 const char *codecs = astman_get_header(m, "Codecs"); 04138 struct ast_variable *vars; 04139 char *tech, *data; 04140 char *l = NULL, *n = NULL; 04141 int pi = 0; 04142 int res; 04143 int to = 30000; 04144 int reason = 0; 04145 char tmp[256]; 04146 char tmp2[256]; 04147 format_t format = AST_FORMAT_SLINEAR; 04148 04149 pthread_t th; 04150 if (ast_strlen_zero(name)) { 04151 astman_send_error(s, m, "Channel not specified"); 04152 return 0; 04153 } 04154 if (!ast_strlen_zero(priority) && (sscanf(priority, "%30d", &pi) != 1)) { 04155 if ((pi = ast_findlabel_extension(NULL, context, exten, priority, NULL)) < 1) { 04156 astman_send_error(s, m, "Invalid priority"); 04157 return 0; 04158 } 04159 } 04160 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%30d", &to) != 1)) { 04161 astman_send_error(s, m, "Invalid timeout"); 04162 return 0; 04163 } 04164 ast_copy_string(tmp, name, sizeof(tmp)); 04165 tech = tmp; 04166 data = strchr(tmp, '/'); 04167 if (!data) { 04168 astman_send_error(s, m, "Invalid channel"); 04169 return 0; 04170 } 04171 *data++ = '\0'; 04172 ast_copy_string(tmp2, callerid, sizeof(tmp2)); 04173 ast_callerid_parse(tmp2, &n, &l); 04174 if (n) { 04175 if (ast_strlen_zero(n)) { 04176 n = NULL; 04177 } 04178 } 04179 if (l) { 04180 ast_shrink_phone_number(l); 04181 if (ast_strlen_zero(l)) { 04182 l = NULL; 04183 } 04184 } 04185 if (!ast_strlen_zero(codecs)) { 04186 format = 0; 04187 ast_parse_allow_disallow(NULL, &format, codecs, 1); 04188 } 04189 if (!ast_strlen_zero(app) && s->session) { 04190 int bad_appdata = 0; 04191 /* To run the System application (or anything else that goes to 04192 * shell), you must have the additional System privilege */ 04193 if (!(s->session->writeperm & EVENT_FLAG_SYSTEM) 04194 && ( 04195 strcasestr(app, "system") || /* System(rm -rf /) 04196 TrySystem(rm -rf /) */ 04197 strcasestr(app, "exec") || /* Exec(System(rm -rf /)) 04198 TryExec(System(rm -rf /)) */ 04199 strcasestr(app, "agi") || /* AGI(/bin/rm,-rf /) 04200 EAGI(/bin/rm,-rf /) */ 04201 strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */ 04202 strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */ 04203 (strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */ 04204 (strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 04205 )) { 04206 char error_buf[64]; 04207 snprintf(error_buf, sizeof(error_buf), "Originate Access Forbidden: %s", bad_appdata ? "Data" : "Application"); 04208 astman_send_error(s, m, error_buf); 04209 return 0; 04210 } 04211 } 04212 /* Allocate requested channel variables */ 04213 vars = astman_get_variables(m); 04214 04215 if (ast_true(async)) { 04216 struct fast_originate_helper *fast; 04217 04218 fast = ast_calloc(1, sizeof(*fast)); 04219 if (!fast || ast_string_field_init(fast, 252)) { 04220 ast_free(fast); 04221 ast_variables_destroy(vars); 04222 res = -1; 04223 } else { 04224 if (!ast_strlen_zero(id)) { 04225 ast_string_field_build(fast, idtext, "ActionID: %s\r\n", id); 04226 } 04227 ast_string_field_set(fast, tech, tech); 04228 ast_string_field_set(fast, data, data); 04229 ast_string_field_set(fast, app, app); 04230 ast_string_field_set(fast, appdata, appdata); 04231 ast_string_field_set(fast, cid_num, l); 04232 ast_string_field_set(fast, cid_name, n); 04233 ast_string_field_set(fast, context, context); 04234 ast_string_field_set(fast, exten, exten); 04235 ast_string_field_set(fast, account, account); 04236 fast->vars = vars; 04237 fast->format = format; 04238 fast->timeout = to; 04239 fast->priority = pi; 04240 if (ast_pthread_create_detached(&th, NULL, fast_originate, fast)) { 04241 destroy_fast_originate_helper(fast); 04242 res = -1; 04243 } else { 04244 res = 0; 04245 } 04246 } 04247 } else if (!ast_strlen_zero(app)) { 04248 res = ast_pbx_outgoing_app(tech, format, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL); 04249 /* Any vars memory was passed to ast_pbx_outgoing_app(). */ 04250 } else { 04251 if (exten && context && pi) { 04252 res = ast_pbx_outgoing_exten(tech, format, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL); 04253 /* Any vars memory was passed to ast_pbx_outgoing_exten(). */ 04254 } else { 04255 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 04256 ast_variables_destroy(vars); 04257 return 0; 04258 } 04259 } 04260 if (!res) { 04261 astman_send_ack(s, m, "Originate successfully queued"); 04262 } else { 04263 astman_send_error(s, m, "Originate failed"); 04264 } 04265 return 0; 04266 }
static int action_ping | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2519 of file manager.c.
References ast_strlen_zero(), ast_tvnow(), astman_append(), and astman_get_header().
Referenced by __init_manager().
02520 { 02521 const char *actionid = astman_get_header(m, "ActionID"); 02522 struct timeval now = ast_tvnow(); 02523 02524 astman_append(s, "Response: Success\r\n"); 02525 if (!ast_strlen_zero(actionid)){ 02526 astman_append(s, "ActionID: %s\r\n", actionid); 02527 } 02528 astman_append( 02529 s, 02530 "Ping: Pong\r\n" 02531 "Timestamp: %ld.%06lu\r\n" 02532 "\r\n", 02533 (long) now.tv_sec, (unsigned long) now.tv_usec); 02534 return 0; 02535 }
static int action_redirect | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
action_redirect: The redirect manager command
Definition at line 3494 of file manager.c.
References ast_async_goto(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_check_hangup_locked(), ast_clear_flag, ast_findlabel_extension(), AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT, AST_FLAG_BRIDGE_HANGUP_DONT, ast_set_flag, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), context, exten, ast_channel::pbx, and ast_channel::priority.
Referenced by __init_manager().
03495 { 03496 char buf[256]; 03497 const char *name = astman_get_header(m, "Channel"); 03498 const char *name2 = astman_get_header(m, "ExtraChannel"); 03499 const char *exten = astman_get_header(m, "Exten"); 03500 const char *exten2 = astman_get_header(m, "ExtraExten"); 03501 const char *context = astman_get_header(m, "Context"); 03502 const char *context2 = astman_get_header(m, "ExtraContext"); 03503 const char *priority = astman_get_header(m, "Priority"); 03504 const char *priority2 = astman_get_header(m, "ExtraPriority"); 03505 struct ast_channel *chan; 03506 struct ast_channel *chan2; 03507 int pi = 0; 03508 int pi2 = 0; 03509 int res; 03510 03511 if (ast_strlen_zero(name)) { 03512 astman_send_error(s, m, "Channel not specified"); 03513 return 0; 03514 } 03515 03516 if (ast_strlen_zero(context)) { 03517 astman_send_error(s, m, "Context not specified"); 03518 return 0; 03519 } 03520 if (ast_strlen_zero(exten)) { 03521 astman_send_error(s, m, "Exten not specified"); 03522 return 0; 03523 } 03524 if (ast_strlen_zero(priority)) { 03525 astman_send_error(s, m, "Priority not specified"); 03526 return 0; 03527 } 03528 if (sscanf(priority, "%30d", &pi) != 1) { 03529 pi = ast_findlabel_extension(NULL, context, exten, priority, NULL); 03530 } 03531 if (pi < 1) { 03532 astman_send_error(s, m, "Priority is invalid"); 03533 return 0; 03534 } 03535 03536 if (!ast_strlen_zero(name2) && !ast_strlen_zero(context2)) { 03537 /* We have an ExtraChannel and an ExtraContext */ 03538 if (ast_strlen_zero(exten2)) { 03539 astman_send_error(s, m, "ExtraExten not specified"); 03540 return 0; 03541 } 03542 if (ast_strlen_zero(priority2)) { 03543 astman_send_error(s, m, "ExtraPriority not specified"); 03544 return 0; 03545 } 03546 if (sscanf(priority2, "%30d", &pi2) != 1) { 03547 pi2 = ast_findlabel_extension(NULL, context2, exten2, priority2, NULL); 03548 } 03549 if (pi2 < 1) { 03550 astman_send_error(s, m, "ExtraPriority is invalid"); 03551 return 0; 03552 } 03553 } 03554 03555 chan = ast_channel_get_by_name(name); 03556 if (!chan) { 03557 snprintf(buf, sizeof(buf), "Channel does not exist: %s", name); 03558 astman_send_error(s, m, buf); 03559 return 0; 03560 } 03561 if (ast_check_hangup_locked(chan)) { 03562 astman_send_error(s, m, "Redirect failed, channel not up."); 03563 chan = ast_channel_unref(chan); 03564 return 0; 03565 } 03566 03567 if (ast_strlen_zero(name2)) { 03568 /* Single channel redirect in progress. */ 03569 if (chan->pbx) { 03570 ast_channel_lock(chan); 03571 /* don't let the after-bridge code run the h-exten */ 03572 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); 03573 ast_channel_unlock(chan); 03574 } 03575 res = ast_async_goto(chan, context, exten, pi); 03576 if (!res) { 03577 astman_send_ack(s, m, "Redirect successful"); 03578 } else { 03579 astman_send_error(s, m, "Redirect failed"); 03580 } 03581 chan = ast_channel_unref(chan); 03582 return 0; 03583 } 03584 03585 chan2 = ast_channel_get_by_name(name2); 03586 if (!chan2) { 03587 snprintf(buf, sizeof(buf), "ExtraChannel does not exist: %s", name2); 03588 astman_send_error(s, m, buf); 03589 chan = ast_channel_unref(chan); 03590 return 0; 03591 } 03592 if (ast_check_hangup_locked(chan2)) { 03593 astman_send_error(s, m, "Redirect failed, extra channel not up."); 03594 chan2 = ast_channel_unref(chan2); 03595 chan = ast_channel_unref(chan); 03596 return 0; 03597 } 03598 03599 /* Dual channel redirect in progress. */ 03600 if (chan->pbx) { 03601 ast_channel_lock(chan); 03602 /* don't let the after-bridge code run the h-exten */ 03603 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT 03604 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03605 ast_channel_unlock(chan); 03606 } 03607 if (chan2->pbx) { 03608 ast_channel_lock(chan2); 03609 /* don't let the after-bridge code run the h-exten */ 03610 ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT 03611 | AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03612 ast_channel_unlock(chan2); 03613 } 03614 res = ast_async_goto(chan, context, exten, pi); 03615 if (!res) { 03616 if (!ast_strlen_zero(context2)) { 03617 res = ast_async_goto(chan2, context2, exten2, pi2); 03618 } else { 03619 res = ast_async_goto(chan2, context, exten, pi); 03620 } 03621 if (!res) { 03622 astman_send_ack(s, m, "Dual Redirect successful"); 03623 } else { 03624 astman_send_error(s, m, "Secondary redirect failed"); 03625 } 03626 } else { 03627 astman_send_error(s, m, "Redirect failed"); 03628 } 03629 03630 /* Release the bridge wait. */ 03631 if (chan->pbx) { 03632 ast_channel_lock(chan); 03633 ast_clear_flag(chan, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03634 ast_channel_unlock(chan); 03635 } 03636 if (chan2->pbx) { 03637 ast_channel_lock(chan2); 03638 ast_clear_flag(chan2, AST_FLAG_BRIDGE_DUAL_REDIRECT_WAIT); 03639 ast_channel_unlock(chan2); 03640 } 03641 03642 chan2 = ast_channel_unref(chan2); 03643 chan = ast_channel_unref(chan); 03644 return 0; 03645 }
static int action_reload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Send a reload event.
Definition at line 4550 of file manager.c.
References ast_module_reload(), astman_get_header(), astman_send_ack(), astman_send_error(), and S_OR.
Referenced by __init_manager().
04551 { 04552 const char *module = astman_get_header(m, "Module"); 04553 int res = ast_module_reload(S_OR(module, NULL)); 04554 04555 switch (res) { 04556 case -1: 04557 astman_send_error(s, m, "A reload is in progress"); 04558 break; 04559 case 0: 04560 astman_send_error(s, m, "No such module"); 04561 break; 04562 case 1: 04563 astman_send_error(s, m, "Module does not support reload"); 04564 break; 04565 case 2: 04566 astman_send_ack(s, m, "Module Reloaded"); 04567 break; 04568 default: 04569 astman_send_error(s, m, "An unknown error occurred"); 04570 break; 04571 } 04572 return 0; 04573 }
static int action_sendtext | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3459 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_sendtext(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
03460 { 03461 struct ast_channel *c = NULL; 03462 const char *name = astman_get_header(m, "Channel"); 03463 const char *textmsg = astman_get_header(m, "Message"); 03464 int res = 0; 03465 03466 if (ast_strlen_zero(name)) { 03467 astman_send_error(s, m, "No channel specified"); 03468 return 0; 03469 } 03470 03471 if (ast_strlen_zero(textmsg)) { 03472 astman_send_error(s, m, "No Message specified"); 03473 return 0; 03474 } 03475 03476 if (!(c = ast_channel_get_by_name(name))) { 03477 astman_send_error(s, m, "No such channel"); 03478 return 0; 03479 } 03480 03481 res = ast_sendtext(c, textmsg); 03482 c = ast_channel_unref(c); 03483 03484 if (res >= 0) { 03485 astman_send_ack(s, m, "Success"); 03486 } else { 03487 astman_send_error(s, m, "Failure"); 03488 } 03489 03490 return 0; 03491 }
static int action_setvar | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 3210 of file manager.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), pbx_builtin_setvar_helper(), and S_OR.
Referenced by __init_manager().
03211 { 03212 struct ast_channel *c = NULL; 03213 const char *name = astman_get_header(m, "Channel"); 03214 const char *varname = astman_get_header(m, "Variable"); 03215 const char *varval = astman_get_header(m, "Value"); 03216 int res = 0; 03217 03218 if (ast_strlen_zero(varname)) { 03219 astman_send_error(s, m, "No variable specified"); 03220 return 0; 03221 } 03222 03223 if (!ast_strlen_zero(name)) { 03224 if (!(c = ast_channel_get_by_name(name))) { 03225 astman_send_error(s, m, "No such channel"); 03226 return 0; 03227 } 03228 } 03229 03230 res = pbx_builtin_setvar_helper(c, varname, S_OR(varval, "")); 03231 03232 if (c) { 03233 c = ast_channel_unref(c); 03234 } 03235 if (res == 0) { 03236 astman_send_ack(s, m, "Variable Set"); 03237 } else { 03238 astman_send_error(s, m, "Variable not set"); 03239 } 03240 return 0; 03241 }
static int action_status | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Manager "status" command to show channels.
Definition at line 3297 of file manager.c.
References ast_channel::_bridge, ast_channel::_state, AST_APP_ARG, ast_channel_get_by_name(), ast_channel_iterator_all_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, AST_DECLARE_APP_ARGS, ast_free, ast_func_read(), AST_STANDARD_APP_ARGS, ast_state2str(), ast_str_append(), ast_str_buffer(), ast_str_create(), ast_str_reset(), ast_strdupa, ast_strlen_zero(), ast_tvnow(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), ast_channel::bridge, ast_channel::caller, ast_channel::cdr, channels, ast_channel::connected, ast_channel::context, ast_channel::exten, function_capable_string_allowed_with_auths(), ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, ast_channel::pbx, pbx_retrieve_variable(), ast_channel::priority, S_COR, S_OR, mansession::session, ast_cdr::start, ast_party_name::str, ast_party_number::str, str, ast_party_name::valid, ast_party_number::valid, and mansession_session::writeperm.
Referenced by __init_manager().
03298 { 03299 const char *name = astman_get_header(m, "Channel"); 03300 const char *cvariables = astman_get_header(m, "Variables"); 03301 char *variables = ast_strdupa(S_OR(cvariables, "")); 03302 struct ast_channel *c; 03303 char bridge[256]; 03304 struct timeval now = ast_tvnow(); 03305 long elapsed_seconds = 0; 03306 int channels = 0; 03307 int all = ast_strlen_zero(name); /* set if we want all channels */ 03308 const char *id = astman_get_header(m, "ActionID"); 03309 char idText[256]; 03310 AST_DECLARE_APP_ARGS(vars, 03311 AST_APP_ARG(name)[100]; 03312 ); 03313 struct ast_str *str = ast_str_create(1000); 03314 struct ast_channel_iterator *iter = NULL; 03315 03316 if (!ast_strlen_zero(id)) { 03317 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 03318 } else { 03319 idText[0] = '\0'; 03320 } 03321 03322 if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) { 03323 astman_send_error(s, m, "Status Access Forbidden: Variables"); 03324 return 0; 03325 } 03326 03327 if (all) { 03328 if (!(iter = ast_channel_iterator_all_new())) { 03329 ast_free(str); 03330 astman_send_error(s, m, "Memory Allocation Failure"); 03331 return 1; 03332 } 03333 c = ast_channel_iterator_next(iter); 03334 } else { 03335 if (!(c = ast_channel_get_by_name(name))) { 03336 astman_send_error(s, m, "No such channel"); 03337 ast_free(str); 03338 return 0; 03339 } 03340 } 03341 03342 astman_send_ack(s, m, "Channel status will follow"); 03343 03344 if (!ast_strlen_zero(cvariables)) { 03345 AST_STANDARD_APP_ARGS(vars, variables); 03346 } 03347 03348 /* if we look by name, we break after the first iteration */ 03349 for (; c; c = ast_channel_iterator_next(iter)) { 03350 ast_channel_lock(c); 03351 03352 if (!ast_strlen_zero(cvariables)) { 03353 int i; 03354 ast_str_reset(str); 03355 for (i = 0; i < vars.argc; i++) { 03356 char valbuf[512], *ret = NULL; 03357 03358 if (vars.name[i][strlen(vars.name[i]) - 1] == ')') { 03359 if (ast_func_read(c, vars.name[i], valbuf, sizeof(valbuf)) < 0) { 03360 valbuf[0] = '\0'; 03361 } 03362 ret = valbuf; 03363 } else { 03364 pbx_retrieve_variable(c, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL); 03365 } 03366 03367 ast_str_append(&str, 0, "Variable: %s=%s\r\n", vars.name[i], ret); 03368 } 03369 } 03370 03371 channels++; 03372 if (c->_bridge) { 03373 snprintf(bridge, sizeof(bridge), "BridgedChannel: %s\r\nBridgedUniqueid: %s\r\n", c->_bridge->name, c->_bridge->uniqueid); 03374 } else { 03375 bridge[0] = '\0'; 03376 } 03377 if (c->pbx) { 03378 if (c->cdr) { 03379 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec; 03380 } 03381 astman_append(s, 03382 "Event: Status\r\n" 03383 "Privilege: Call\r\n" 03384 "Channel: %s\r\n" 03385 "CallerIDNum: %s\r\n" 03386 "CallerIDName: %s\r\n" 03387 "ConnectedLineNum: %s\r\n" 03388 "ConnectedLineName: %s\r\n" 03389 "Accountcode: %s\r\n" 03390 "ChannelState: %u\r\n" 03391 "ChannelStateDesc: %s\r\n" 03392 "Context: %s\r\n" 03393 "Extension: %s\r\n" 03394 "Priority: %d\r\n" 03395 "Seconds: %ld\r\n" 03396 "%s" 03397 "Uniqueid: %s\r\n" 03398 "%s" 03399 "%s" 03400 "\r\n", 03401 c->name, 03402 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03403 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03404 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03405 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03406 c->accountcode, 03407 c->_state, 03408 ast_state2str(c->_state), c->context, 03409 c->exten, c->priority, (long)elapsed_seconds, bridge, c->uniqueid, ast_str_buffer(str), idText); 03410 } else { 03411 astman_append(s, 03412 "Event: Status\r\n" 03413 "Privilege: Call\r\n" 03414 "Channel: %s\r\n" 03415 "CallerIDNum: %s\r\n" 03416 "CallerIDName: %s\r\n" 03417 "ConnectedLineNum: %s\r\n" 03418 "ConnectedLineName: %s\r\n" 03419 "Account: %s\r\n" 03420 "State: %s\r\n" 03421 "%s" 03422 "Uniqueid: %s\r\n" 03423 "%s" 03424 "%s" 03425 "\r\n", 03426 c->name, 03427 S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"), 03428 S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"), 03429 S_COR(c->connected.id.number.valid, c->connected.id.number.str, "<unknown>"), 03430 S_COR(c->connected.id.name.valid, c->connected.id.name.str, "<unknown>"), 03431 c->accountcode, 03432 ast_state2str(c->_state), bridge, c->uniqueid, 03433 ast_str_buffer(str), idText); 03434 } 03435 03436 ast_channel_unlock(c); 03437 c = ast_channel_unref(c); 03438 03439 if (!all) { 03440 break; 03441 } 03442 } 03443 03444 if (iter) { 03445 ast_channel_iterator_destroy(iter); 03446 } 03447 03448 astman_append(s, 03449 "Event: StatusComplete\r\n" 03450 "%s" 03451 "Items: %d\r\n" 03452 "\r\n", idText, channels); 03453 03454 ast_free(str); 03455 03456 return 0; 03457 }
static int action_timeout | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4331 of file manager.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_setwhentohangup_tv(), ast_channel_unlock, ast_channel_unref, ast_strlen_zero(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
04332 { 04333 struct ast_channel *c; 04334 const char *name = astman_get_header(m, "Channel"); 04335 double timeout = atof(astman_get_header(m, "Timeout")); 04336 struct timeval when = { timeout, 0 }; 04337 04338 if (ast_strlen_zero(name)) { 04339 astman_send_error(s, m, "No channel specified"); 04340 return 0; 04341 } 04342 04343 if (!timeout || timeout < 0) { 04344 astman_send_error(s, m, "No timeout specified"); 04345 return 0; 04346 } 04347 04348 if (!(c = ast_channel_get_by_name(name))) { 04349 astman_send_error(s, m, "No such channel"); 04350 return 0; 04351 } 04352 04353 when.tv_usec = (timeout - when.tv_sec) * 1000000.0; 04354 04355 ast_channel_lock(c); 04356 ast_channel_setwhentohangup_tv(c, when); 04357 ast_channel_unlock(c); 04358 c = ast_channel_unref(c); 04359 04360 astman_send_ack(s, m, "Timeout Set"); 04361 04362 return 0; 04363 }
static int action_updateconfig | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2845 of file manager.c.
References ast_config_destroy(), ast_config_load2(), ast_config_text_file_save(), ast_include_rename(), ast_module_reload(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), CONFIG_FLAG_NOCACHE, CONFIG_FLAG_WITHCOMMENTS, CONFIG_STATUS_FILEINVALID, FAILURE_ALLOCATION, FAILURE_APPEND, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, handle_updates(), UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, and UNSPECIFIED_CATEGORY.
Referenced by __init_manager().
02846 { 02847 struct ast_config *cfg; 02848 const char *sfn = astman_get_header(m, "SrcFilename"); 02849 const char *dfn = astman_get_header(m, "DstFilename"); 02850 int res; 02851 const char *rld = astman_get_header(m, "Reload"); 02852 struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS | CONFIG_FLAG_NOCACHE }; 02853 enum error_type result; 02854 02855 if (ast_strlen_zero(sfn) || ast_strlen_zero(dfn)) { 02856 astman_send_error(s, m, "Filename not specified"); 02857 return 0; 02858 } 02859 if (!(cfg = ast_config_load2(sfn, "manager", config_flags))) { 02860 astman_send_error(s, m, "Config file not found"); 02861 return 0; 02862 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 02863 astman_send_error(s, m, "Config file has invalid format"); 02864 return 0; 02865 } 02866 result = handle_updates(s, m, cfg, dfn); 02867 if (!result) { 02868 ast_include_rename(cfg, sfn, dfn); /* change the include references from dfn to sfn, so things match up */ 02869 res = ast_config_text_file_save(dfn, cfg, "Manager"); 02870 ast_config_destroy(cfg); 02871 if (res) { 02872 astman_send_error(s, m, "Save of config failed"); 02873 return 0; 02874 } 02875 astman_send_ack(s, m, NULL); 02876 if (!ast_strlen_zero(rld)) { 02877 if (ast_true(rld)) { 02878 rld = NULL; 02879 } 02880 ast_module_reload(rld); 02881 } 02882 } else { 02883 ast_config_destroy(cfg); 02884 switch(result) { 02885 case UNKNOWN_ACTION: 02886 astman_send_error(s, m, "Unknown action command"); 02887 break; 02888 case UNKNOWN_CATEGORY: 02889 astman_send_error(s, m, "Given category does not exist"); 02890 break; 02891 case UNSPECIFIED_CATEGORY: 02892 astman_send_error(s, m, "Category not specified"); 02893 break; 02894 case UNSPECIFIED_ARGUMENT: 02895 astman_send_error(s, m, "Problem with category, value, or line (if required)"); 02896 break; 02897 case FAILURE_ALLOCATION: 02898 astman_send_error(s, m, "Memory allocation failure, this should not happen"); 02899 break; 02900 case FAILURE_NEWCAT: 02901 astman_send_error(s, m, "Create category did not complete successfully"); 02902 break; 02903 case FAILURE_DELCAT: 02904 astman_send_error(s, m, "Delete category did not complete successfully"); 02905 break; 02906 case FAILURE_EMPTYCAT: 02907 astman_send_error(s, m, "Empty category did not complete successfully"); 02908 break; 02909 case FAILURE_UPDATE: 02910 astman_send_error(s, m, "Update did not complete successfully"); 02911 break; 02912 case FAILURE_DELETE: 02913 astman_send_error(s, m, "Delete did not complete successfully"); 02914 break; 02915 case FAILURE_APPEND: 02916 astman_send_error(s, m, "Append did not complete successfully"); 02917 break; 02918 } 02919 } 02920 return 0; 02921 }
static int action_userevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4448 of file manager.c.
References ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_thread_get(), astman_get_header(), astman_send_ack(), EVENT_FLAG_USER, message::hdrcount, message::headers, manager_event, and userevent_buf.
Referenced by __init_manager().
04449 { 04450 const char *event = astman_get_header(m, "UserEvent"); 04451 struct ast_str *body = ast_str_thread_get(&userevent_buf, 16); 04452 int x; 04453 04454 ast_str_reset(body); 04455 04456 for (x = 0; x < m->hdrcount; x++) { 04457 if (strncasecmp("UserEvent:", m->headers[x], strlen("UserEvent:"))) { 04458 ast_str_append(&body, 0, "%s\r\n", m->headers[x]); 04459 } 04460 } 04461 04462 astman_send_ack(s, m, "Event Sent"); 04463 manager_event(EVENT_FLAG_USER, "UserEvent", "UserEvent: %s\r\n%s", event, ast_str_buffer(body)); 04464 return 0; 04465 }
static int action_waitevent | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2941 of file manager.c.
References advance_event(), ao2_lock, ao2_unlock, ast_debug, AST_PTHREADT_NULL, AST_RWLIST_NEXT, ast_strlen_zero(), ast_wait_for_input(), astman_append(), astman_get_header(), astman_send_response(), eventqent::category, eventqent::eventdata, mansession_session::fd, mansession_session::last_ev, mansession_session::managerid, match_filter(), mansession_session::needdestroy, mansession_session::readperm, mansession_session::send_events, mansession::session, mansession_session::sessiontimeout, and mansession_session::waiting_thread.
Referenced by __init_manager().
02942 { 02943 const char *timeouts = astman_get_header(m, "Timeout"); 02944 int timeout = -1; 02945 int x; 02946 int needexit = 0; 02947 const char *id = astman_get_header(m, "ActionID"); 02948 char idText[256]; 02949 02950 if (!ast_strlen_zero(id)) { 02951 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 02952 } else { 02953 idText[0] = '\0'; 02954 } 02955 02956 if (!ast_strlen_zero(timeouts)) { 02957 sscanf(timeouts, "%30i", &timeout); 02958 if (timeout < -1) { 02959 timeout = -1; 02960 } 02961 /* XXX maybe put an upper bound, or prevent the use of 0 ? */ 02962 } 02963 02964 ao2_lock(s->session); 02965 if (s->session->waiting_thread != AST_PTHREADT_NULL) { 02966 pthread_kill(s->session->waiting_thread, SIGURG); 02967 } 02968 02969 if (s->session->managerid) { /* AMI-over-HTTP session */ 02970 /* 02971 * Make sure the timeout is within the expire time of the session, 02972 * as the client will likely abort the request if it does not see 02973 * data coming after some amount of time. 02974 */ 02975 time_t now = time(NULL); 02976 int max = s->session->sessiontimeout - now - 10; 02977 02978 if (max < 0) { /* We are already late. Strange but possible. */ 02979 max = 0; 02980 } 02981 if (timeout < 0 || timeout > max) { 02982 timeout = max; 02983 } 02984 if (!s->session->send_events) { /* make sure we record events */ 02985 s->session->send_events = -1; 02986 } 02987 } 02988 ao2_unlock(s->session); 02989 02990 /* XXX should this go inside the lock ? */ 02991 s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */ 02992 ast_debug(1, "Starting waiting for an event!\n"); 02993 02994 for (x = 0; x < timeout || timeout < 0; x++) { 02995 ao2_lock(s->session); 02996 if (AST_RWLIST_NEXT(s->session->last_ev, eq_next)) { 02997 needexit = 1; 02998 } 02999 /* We can have multiple HTTP session point to the same mansession entry. 03000 * The way we deal with it is not very nice: newcomers kick out the previous 03001 * HTTP session. XXX this needs to be improved. 03002 */ 03003 if (s->session->waiting_thread != pthread_self()) { 03004 needexit = 1; 03005 } 03006 if (s->session->needdestroy) { 03007 needexit = 1; 03008 } 03009 ao2_unlock(s->session); 03010 if (needexit) { 03011 break; 03012 } 03013 if (s->session->managerid == 0) { /* AMI session */ 03014 if (ast_wait_for_input(s->session->fd, 1000)) { 03015 break; 03016 } 03017 } else { /* HTTP session */ 03018 sleep(1); 03019 } 03020 } 03021 ast_debug(1, "Finished waiting for an event!\n"); 03022 03023 ao2_lock(s->session); 03024 if (s->session->waiting_thread == pthread_self()) { 03025 struct eventqent *eqe = s->session->last_ev; 03026 astman_send_response(s, m, "Success", "Waiting for Event completed."); 03027 while ((eqe = advance_event(eqe))) { 03028 if (((s->session->readperm & eqe->category) == eqe->category) 03029 && ((s->session->send_events & eqe->category) == eqe->category) 03030 && match_filter(s, eqe->eventdata)) { 03031 astman_append(s, "%s", eqe->eventdata); 03032 } 03033 s->session->last_ev = eqe; 03034 } 03035 astman_append(s, 03036 "Event: WaitEventComplete\r\n" 03037 "%s" 03038 "\r\n", idText); 03039 s->session->waiting_thread = AST_PTHREADT_NULL; 03040 } else { 03041 ast_debug(1, "Abandoning event request!\n"); 03042 } 03043 ao2_unlock(s->session); 03044 03045 return 0; 03046 }
Definition at line 1793 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_NEXT, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, eventqent::next, and eventqent::usecount.
Referenced by action_waitevent(), and process_events().
01794 { 01795 struct eventqent *next; 01796 01797 AST_RWLIST_RDLOCK(&all_events); 01798 if ((next = AST_RWLIST_NEXT(e, eq_next))) { 01799 ast_atomic_fetchadd_int(&next->usecount, 1); 01800 ast_atomic_fetchadd_int(&e->usecount, -1); 01801 } 01802 AST_RWLIST_UNLOCK(&all_events); 01803 return next; 01804 }
static int aocmessage_get_unit_entry | ( | const struct message * | m, | |
struct ast_aoc_unit_entry * | entry, | |||
unsigned int | entry_num | |||
) | [static] |
Definition at line 3894 of file manager.c.
References ast_aoc_unit_entry::amount, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), astman_get_header(), str, ast_aoc_unit_entry::type, ast_aoc_unit_entry::valid_amount, and ast_aoc_unit_entry::valid_type.
Referenced by action_aocmessage().
03895 { 03896 const char *unitamount; 03897 const char *unittype; 03898 struct ast_str *str = ast_str_alloca(32); 03899 03900 memset(entry, 0, sizeof(*entry)); 03901 03902 ast_str_set(&str, 0, "UnitAmount(%u)", entry_num); 03903 unitamount = astman_get_header(m, ast_str_buffer(str)); 03904 03905 ast_str_set(&str, 0, "UnitType(%u)", entry_num); 03906 unittype = astman_get_header(m, ast_str_buffer(str)); 03907 03908 if (!ast_strlen_zero(unitamount) && (sscanf(unitamount, "%30u", &entry->amount) == 1)) { 03909 entry->valid_amount = 1; 03910 } 03911 03912 if (!ast_strlen_zero(unittype) && sscanf(unittype, "%30u", &entry->type) == 1) { 03913 entry->valid_type = 1; 03914 } 03915 03916 return 0; 03917 }
static void append_channel_vars | ( | struct ast_str ** | pbuf, | |
struct ast_channel * | chan | |||
) | [static] |
Definition at line 5240 of file manager.c.
References ast_func_read2(), AST_LIST_TRAVERSE, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_thread_get(), manager_channel_variable::isfunc, manager_event_funcbuf, manager_channel_variable::name, pbx_builtin_getvar_helper(), and var.
Referenced by __ast_manager_event_multichan().
05241 { 05242 struct manager_channel_variable *var; 05243 05244 AST_RWLIST_RDLOCK(&channelvars); 05245 AST_LIST_TRAVERSE(&channelvars, var, entry) { 05246 const char *val; 05247 struct ast_str *res; 05248 05249 if (var->isfunc) { 05250 res = ast_str_thread_get(&manager_event_funcbuf, 16); 05251 if (res && ast_func_read2(chan, var->name, &res, 0) == 0) { 05252 val = ast_str_buffer(res); 05253 } else { 05254 val = NULL; 05255 } 05256 } else { 05257 val = pbx_builtin_getvar_helper(chan, var->name); 05258 } 05259 ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : ""); 05260 } 05261 AST_RWLIST_UNLOCK(&channelvars); 05262 }
static int append_event | ( | const char * | str, | |
int | category | |||
) | [static] |
Definition at line 5214 of file manager.c.
References ast_atomic_fetchadd_int(), ast_malloc, AST_RWLIST_INSERT_TAIL, AST_RWLIST_NEXT, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvnow(), eventqent::category, eventqent::eventdata, eventqent::seq, eventqent::tv, and eventqent::usecount.
Referenced by __ast_manager_event_multichan(), and __init_manager().
05215 { 05216 struct eventqent *tmp = ast_malloc(sizeof(*tmp) + strlen(str)); 05217 static int seq; /* sequence number */ 05218 05219 if (!tmp) { 05220 return -1; 05221 } 05222 05223 /* need to init all fields, because ast_malloc() does not */ 05224 tmp->usecount = 0; 05225 tmp->category = category; 05226 tmp->seq = ast_atomic_fetchadd_int(&seq, 1); 05227 tmp->tv = ast_tvnow(); 05228 AST_RWLIST_NEXT(tmp, eq_next) = NULL; 05229 strcpy(tmp->eventdata, str); 05230 05231 AST_RWLIST_WRLOCK(&all_events); 05232 AST_RWLIST_INSERT_TAIL(&all_events, tmp, eq_next); 05233 AST_RWLIST_UNLOCK(&all_events); 05234 05235 return 0; 05236 }
int ast_hook_send_action | ( | struct manager_custom_hook * | hook, | |
const char * | msg | |||
) |
Registered hooks can call this function to invoke actions and they will receive responses through registered callback.
hook | the file identifier specified in manager_custom_hook struct when registering a hook | |
msg | ami action mesage string e.g. "Action: SipPeers\r\n" |
0 | on Success | |
non-zero | on Failure |
Definition at line 1950 of file manager.c.
References action_find(), manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ARRAY_LEN, ast_free, ast_strdup, astman_get_header(), mansession::f, manager_action::func, message::hdrcount, message::headers, mansession::hook, manager_action::registered, and mansession::session.
01951 { 01952 const char *action; 01953 int ret = 0; 01954 struct manager_action *act_found; 01955 struct mansession s = {.session = NULL, }; 01956 struct message m = { 0 }; 01957 char *dup_str; 01958 char *src; 01959 int x = 0; 01960 int curlen; 01961 01962 if (hook == NULL) { 01963 return -1; 01964 } 01965 01966 /* Create our own copy of the AMI action msg string. */ 01967 src = dup_str = ast_strdup(msg); 01968 if (!dup_str) { 01969 return -1; 01970 } 01971 01972 /* convert msg string to message struct */ 01973 curlen = strlen(src); 01974 for (x = 0; x < curlen; x++) { 01975 int cr; /* set if we have \r */ 01976 if (src[x] == '\r' && x+1 < curlen && src[x+1] == '\n') 01977 cr = 2; /* Found. Update length to include \r\n */ 01978 else if (src[x] == '\n') 01979 cr = 1; /* also accept \n only */ 01980 else 01981 continue; 01982 /* don't keep empty lines */ 01983 if (x && m.hdrcount < ARRAY_LEN(m.headers)) { 01984 /* ... but trim \r\n and terminate the header string */ 01985 src[x] = '\0'; 01986 m.headers[m.hdrcount++] = src; 01987 } 01988 x += cr; 01989 curlen -= x; /* remaining size */ 01990 src += x; /* update pointer */ 01991 x = -1; /* reset loop */ 01992 } 01993 01994 action = astman_get_header(&m, "Action"); 01995 if (strcasecmp(action, "login")) { 01996 act_found = action_find(action); 01997 if (act_found) { 01998 /* 01999 * we have to simulate a session for this action request 02000 * to be able to pass it down for processing 02001 * This is necessary to meet the previous design of manager.c 02002 */ 02003 s.hook = hook; 02004 s.f = (void*)1; /* set this to something so our request will make it through all functions that test it*/ 02005 02006 ao2_lock(act_found); 02007 if (act_found->registered && act_found->func) { 02008 ++act_found->active_count; 02009 ao2_unlock(act_found); 02010 ret = act_found->func(&s, &m); 02011 ao2_lock(act_found); 02012 --act_found->active_count; 02013 } else { 02014 ret = -1; 02015 } 02016 ao2_unlock(act_found); 02017 ao2_t_ref(act_found, -1, "done with found action object"); 02018 } 02019 } 02020 ast_free(dup_str); 02021 return ret; 02022 }
static int ast_instring | ( | const char * | bigstr, | |
const char * | smallstr, | |||
const char | delim | |||
) | [static] |
Tells you if smallstr exists inside bigstr which is delim by delim and uses no buf or stringsep ast_instring("this|that|more","this",'|') == 1;
feel free to move this to app.c -anthm
Definition at line 1259 of file manager.c.
References eventqent::next.
Referenced by get_perm().
01260 { 01261 const char *val = bigstr, *next; 01262 01263 do { 01264 if ((next = strchr(val, delim))) { 01265 if (!strncmp(val, smallstr, (next - val))) { 01266 return 1; 01267 } else { 01268 continue; 01269 } 01270 } else { 01271 return !strcmp(smallstr, val); 01272 } 01273 } while (*(val = (next + 1))); 01274 01275 return 0; 01276 }
int ast_manager_register2 | ( | const char * | action, | |
int | auth, | |||
int(*)(struct mansession *s, const struct message *m) | func, | |||
const char * | synopsis, | |||
const char * | description | |||
) |
register a new command with manager, including online help. This is the preferred way to register a manager command
Register a manager command with the manager interface.
Definition at line 5469 of file manager.c.
References manager_action::action, action_destroy(), ao2_alloc, ao2_t_ref, ast_free, ast_manager_register_struct(), AST_STATIC_DOC, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), AST_XML_DOC, ast_xmldoc_build_arguments(), ast_xmldoc_build_description(), ast_xmldoc_build_seealso(), ast_xmldoc_build_synopsis(), ast_xmldoc_build_syntax(), manager_action::authority, manager_action::docsrc, and manager_action::func.
Referenced by load_module().
05470 { 05471 struct manager_action *cur; 05472 05473 cur = ao2_alloc(sizeof(*cur), action_destroy); 05474 if (!cur) { 05475 return -1; 05476 } 05477 if (ast_string_field_init(cur, 128)) { 05478 ao2_t_ref(cur, -1, "action object creation failed"); 05479 return -1; 05480 } 05481 05482 cur->action = action; 05483 cur->authority = auth; 05484 cur->func = func; 05485 #ifdef AST_XML_DOCS 05486 if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) { 05487 char *tmpxml; 05488 05489 tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL); 05490 ast_string_field_set(cur, synopsis, tmpxml); 05491 ast_free(tmpxml); 05492 05493 tmpxml = ast_xmldoc_build_syntax("manager", action, NULL); 05494 ast_string_field_set(cur, syntax, tmpxml); 05495 ast_free(tmpxml); 05496 05497 tmpxml = ast_xmldoc_build_description("manager", action, NULL); 05498 ast_string_field_set(cur, description, tmpxml); 05499 ast_free(tmpxml); 05500 05501 tmpxml = ast_xmldoc_build_seealso("manager", action, NULL); 05502 ast_string_field_set(cur, seealso, tmpxml); 05503 ast_free(tmpxml); 05504 05505 tmpxml = ast_xmldoc_build_arguments("manager", action, NULL); 05506 ast_string_field_set(cur, arguments, tmpxml); 05507 ast_free(tmpxml); 05508 05509 cur->docsrc = AST_XML_DOC; 05510 } else 05511 #endif 05512 { 05513 ast_string_field_set(cur, synopsis, synopsis); 05514 ast_string_field_set(cur, description, description); 05515 #ifdef AST_XML_DOCS 05516 cur->docsrc = AST_STATIC_DOC; 05517 #endif 05518 } 05519 if (ast_manager_register_struct(cur)) { 05520 ao2_t_ref(cur, -1, "action object registration failed"); 05521 return -1; 05522 } 05523 05524 ao2_t_ref(cur, -1, "action object registration successful"); 05525 return 0; 05526 }
void ast_manager_register_hook | ( | struct manager_custom_hook * | hook | ) |
Add a custom hook to be called when an event is fired.
Add a custom hook to be called when an event is fired
hook | struct manager_custom_hook object to add |
Definition at line 1092 of file manager.c.
References AST_RWLIST_INSERT_TAIL, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01093 { 01094 AST_RWLIST_WRLOCK(&manager_hooks); 01095 AST_RWLIST_INSERT_TAIL(&manager_hooks, hook, list); 01096 AST_RWLIST_UNLOCK(&manager_hooks); 01097 }
static int ast_manager_register_struct | ( | struct manager_action * | act | ) | [static] |
Definition at line 5414 of file manager.c.
References manager_action::action, ao2_t_ref, ast_log(), AST_RWLIST_INSERT_AFTER, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, LOG_WARNING, and manager_action::registered.
Referenced by ast_manager_register2().
05415 { 05416 struct manager_action *cur, *prev = NULL; 05417 05418 AST_RWLIST_WRLOCK(&actions); 05419 AST_RWLIST_TRAVERSE(&actions, cur, list) { 05420 int ret; 05421 05422 ret = strcasecmp(cur->action, act->action); 05423 if (ret == 0) { 05424 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 05425 AST_RWLIST_UNLOCK(&actions); 05426 return -1; 05427 } 05428 if (ret > 0) { /* Insert these alphabetically */ 05429 prev = cur; 05430 break; 05431 } 05432 } 05433 05434 ao2_t_ref(act, +1, "action object added to list"); 05435 act->registered = 1; 05436 if (prev) { 05437 AST_RWLIST_INSERT_AFTER(&actions, prev, act, list); 05438 } else { 05439 AST_RWLIST_INSERT_HEAD(&actions, act, list); 05440 } 05441 05442 ast_verb(2, "Manager registered action %s\n", act->action); 05443 05444 AST_RWLIST_UNLOCK(&actions); 05445 05446 return 0; 05447 }
int ast_manager_unregister | ( | char * | action | ) |
Unregister a registered manager command.
action | Name of registered Action: |
Definition at line 5355 of file manager.c.
References manager_action::action, manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, and manager_action::registered.
Referenced by __unload_module(), astdb_shutdown(), data_shutdown(), features_shutdown(), manager_shutdown(), unload_module(), and unload_pbx().
05356 { 05357 struct manager_action *cur; 05358 05359 AST_RWLIST_WRLOCK(&actions); 05360 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&actions, cur, list) { 05361 if (!strcasecmp(action, cur->action)) { 05362 AST_RWLIST_REMOVE_CURRENT(list); 05363 break; 05364 } 05365 } 05366 AST_RWLIST_TRAVERSE_SAFE_END; 05367 AST_RWLIST_UNLOCK(&actions); 05368 05369 if (cur) { 05370 time_t now; 05371 05372 /* 05373 * We have removed the action object from the container so we 05374 * are no longer in a hurry. 05375 */ 05376 ao2_lock(cur); 05377 cur->registered = 0; 05378 ao2_unlock(cur); 05379 05380 /* 05381 * Wait up to 5 seconds for any active invocations to complete 05382 * before returning. We have to wait instead of blocking 05383 * because we may be waiting for ourself to complete. 05384 */ 05385 now = time(NULL); 05386 while (cur->active_count) { 05387 if (5 <= time(NULL) - now) { 05388 ast_debug(1, 05389 "Unregister manager action %s timed out waiting for %u active instances to complete\n", 05390 action, cur->active_count); 05391 break; 05392 } 05393 05394 sched_yield(); 05395 } 05396 05397 ao2_t_ref(cur, -1, "action object removed from list"); 05398 ast_verb(2, "Manager unregistered action %s\n", action); 05399 } 05400 05401 return 0; 05402 }
void ast_manager_unregister_hook | ( | struct manager_custom_hook * | hook | ) |
Delete a custom hook to be called when an event is fired.
Delete a custom hook to be called when an event is fired
hook | struct manager_custom_hook object to delete |
Definition at line 1100 of file manager.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and manager_action::list.
01101 { 01102 AST_RWLIST_WRLOCK(&manager_hooks); 01103 AST_RWLIST_REMOVE(&manager_hooks, hook, list); 01104 AST_RWLIST_UNLOCK(&manager_hooks); 01105 }
void astman_append | ( | struct mansession * | s, | |
const char * | fmt, | |||
... | ||||
) |
utility functions for creating AMI replies
Definition at line 2068 of file manager.c.
References ast_str_buffer(), ast_str_set_va(), ast_str_thread_get(), ast_verbose, astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE, mansession_session::f, mansession::f, send_string(), and mansession::session.
Referenced by __iax2_show_peers(), _sip_show_peer(), _sip_show_peers_one(), _skinny_show_device(), _skinny_show_devices(), _skinny_show_line(), _skinny_show_lines(), action_agents(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_ping(), action_status(), action_waitevent(), ast_cli_netstats(), astman_append_json(), astman_send_response_full(), data_result_manager_output(), do_print(), manager_data_get(), manager_dbget(), manager_iax2_show_netstats(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_mute_mixmonitor(), manager_mutestream(), manager_parking_status(), manager_queue_rule_show(), manager_queues_show(), manager_queues_status(), manager_queues_summary(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), and session_do().
02069 { 02070 va_list ap; 02071 struct ast_str *buf; 02072 02073 if (!(buf = ast_str_thread_get(&astman_append_buf, ASTMAN_APPEND_BUF_INITSIZE))) { 02074 return; 02075 } 02076 02077 va_start(ap, fmt); 02078 ast_str_set_va(&buf, 0, fmt, ap); 02079 va_end(ap); 02080 02081 if (s->f != NULL || s->session->f != NULL) { 02082 send_string(s, ast_str_buffer(buf)); 02083 } else { 02084 ast_verbose("fd == -1 in astman_append, should not happen\n"); 02085 } 02086 }
static void astman_append_json | ( | struct mansession * | s, | |
const char * | str | |||
) | [static] |
Definition at line 2638 of file manager.c.
References ast_alloca, astman_append(), and json_escape().
Referenced by action_getconfigjson().
02639 { 02640 char *buf; 02641 02642 buf = ast_alloca(2 * strlen(str) + 1); 02643 json_escape(buf, str); 02644 astman_append(s, "%s", buf); 02645 }
const char* astman_get_header | ( | const struct message * | m, | |
char * | var | |||
) |
Return the first matching variable from an array.
Get header from mananger transaction.
Definition at line 1860 of file manager.c.
References __astman_get_header(), and GET_HEADER_FIRST_MATCH.
Referenced by _sip_show_peer(), _sip_show_peers(), _skinny_show_devices(), _skinny_show_lines(), action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coresettings(), action_coreshowchannels(), action_corestatus(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdishowchannels(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_ping(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), action_waitevent(), aocmessage_get_unit_entry(), ast_hook_send_action(), astman_send_response_full(), authenticate(), change_monitor_action(), do_pause_or_unpause(), handle_updates(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_iax2_show_peer_list(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_jabber_send(), manager_list_voicemail_users(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queue_rule_show(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_show_dialplan(), manager_show_registry(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sip_show_peers(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().
01861 { 01862 return __astman_get_header(m, var, GET_HEADER_FIRST_MATCH); 01863 }
struct ast_variable* astman_get_variables | ( | const struct message * | m | ) | [read] |
Get a linked list of the Variable: headers.
Definition at line 1918 of file manager.c.
References astman_get_variables_order(), and ORDER_REVERSE.
Referenced by action_originate().
01919 { 01920 return astman_get_variables_order(m, ORDER_REVERSE); 01921 }
struct ast_variable* astman_get_variables_order | ( | const struct message * | m, | |
enum variable_orders | order | |||
) | [read] |
Get a linked list of the Variable: headers with order specified.
Definition at line 1923 of file manager.c.
References ast_variables_reverse(), message::hdrcount, message::headers, man_do_variable_value(), and ORDER_NATURAL.
Referenced by astman_get_variables(), and manager_sipnotify().
01925 { 01926 int varlen; 01927 int x; 01928 struct ast_variable *head = NULL; 01929 01930 static const char var_hdr[] = "Variable:"; 01931 01932 /* Process all "Variable:" headers. */ 01933 varlen = strlen(var_hdr); 01934 for (x = 0; x < m->hdrcount; x++) { 01935 if (strncasecmp(var_hdr, m->headers[x], varlen)) { 01936 continue; 01937 } 01938 head = man_do_variable_value(head, m->headers[x] + varlen); 01939 } 01940 01941 if (order == ORDER_NATURAL) { 01942 head = ast_variables_reverse(head); 01943 } 01944 01945 return head; 01946 }
void astman_send_ack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg | |||
) |
Send ack in manager transaction.
Definition at line 2135 of file manager.c.
References astman_send_response_full().
Referenced by action_add_agi_cmd(), action_agent_logoff(), action_agents(), action_aocmessage(), action_atxfer(), action_bridge(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_dahdishowchannels(), action_hangup(), action_login(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), action_userevent(), change_monitor_action(), do_pause_or_unpause(), manager_add_queue_member(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_list_voicemail_users(), manager_moduleload(), manager_optimize_away(), manager_park(), manager_parking_status(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_queues_status(), manager_queues_summary(), manager_remove_queue_member(), manager_sipnotify(), meetmemute(), start_monitor_action(), and stop_monitor_action().
02136 { 02137 astman_send_response_full(s, m, "Success", msg, NULL); 02138 }
void astman_send_error | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | error | |||
) |
Send error in manager transaction.
Definition at line 2130 of file manager.c.
References astman_send_response_full().
Referenced by _sip_qualify_peer(), _sip_show_peer(), action_add_agi_cmd(), action_agent_logoff(), action_aocmessage(), action_atxfer(), action_bridge(), action_challenge(), action_command(), action_coreshowchannels(), action_createconfig(), action_dahdidialoffhook(), action_dahdidndoff(), action_dahdidndon(), action_dahdirestart(), action_events(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_hangup(), action_listcategories(), action_login(), action_mailboxcount(), action_mailboxstatus(), action_meetmelist(), action_originate(), action_redirect(), action_reload(), action_sendtext(), action_setvar(), action_status(), action_timeout(), action_transfer(), action_transferhangup(), action_updateconfig(), change_monitor_action(), do_message(), do_pause_or_unpause(), handle_parse_error(), manager_add_queue_member(), manager_data_get(), manager_dbdel(), manager_dbdeltree(), manager_dbget(), manager_dbput(), manager_jabber_send(), manager_modulecheck(), manager_moduleload(), manager_mute_mixmonitor(), manager_mutestream(), manager_optimize_away(), manager_park(), manager_pause_queue_member(), manager_play_dtmf(), manager_queue_log_custom(), manager_queue_member_penalty(), manager_queue_reload(), manager_queue_reset(), manager_remove_queue_member(), manager_show_dialplan(), manager_show_dialplan_helper(), manager_sip_qualify_peer(), manager_sip_show_peer(), manager_sipnotify(), manager_skinny_show_device(), manager_skinny_show_line(), meetmemute(), process_message(), start_monitor_action(), and stop_monitor_action().
02131 { 02132 astman_send_response_full(s, m, "Error", error, NULL); 02133 }
void astman_send_listack | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | msg, | |||
char * | listflag | |||
) |
Send ack in manager list transaction.
Definition at line 2145 of file manager.c.
References astman_send_response_full().
Referenced by action_coreshowchannels(), action_meetmelist(), manager_dpsendack(), manager_iax2_show_peers(), manager_iax2_show_registry(), manager_show_registry(), manager_sip_show_peers(), manager_skinny_show_devices(), and manager_skinny_show_lines().
02146 { 02147 astman_send_response_full(s, m, "Success", msg, listflag); 02148 }
void astman_send_response | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg | |||
) |
Send response in manager transaction.
Definition at line 2125 of file manager.c.
References astman_send_response_full().
Referenced by action_logoff(), and action_waitevent().
02126 { 02127 astman_send_response_full(s, m, resp, msg, NULL); 02128 }
static void astman_send_response_full | ( | struct mansession * | s, | |
const struct message * | m, | |||
char * | resp, | |||
char * | msg, | |||
char * | listflag | |||
) | [static] |
Definition at line 2105 of file manager.c.
References ast_strlen_zero(), astman_append(), astman_get_header(), and MSG_MOREDATA.
Referenced by astman_send_ack(), astman_send_error(), astman_send_listack(), astman_send_response(), and astman_start_ack().
02106 { 02107 const char *id = astman_get_header(m, "ActionID"); 02108 02109 astman_append(s, "Response: %s\r\n", resp); 02110 if (!ast_strlen_zero(id)) { 02111 astman_append(s, "ActionID: %s\r\n", id); 02112 } 02113 if (listflag) { 02114 astman_append(s, "EventList: %s\r\n", listflag); /* Start, complete, cancelled */ 02115 } 02116 if (msg == MSG_MOREDATA) { 02117 return; 02118 } else if (msg) { 02119 astman_append(s, "Message: %s\r\n\r\n", msg); 02120 } else { 02121 astman_append(s, "\r\n"); 02122 } 02123 }
static void astman_start_ack | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2140 of file manager.c.
References astman_send_response_full(), and MSG_MOREDATA.
Referenced by action_challenge(), action_extensionstate(), action_getconfig(), action_getconfigjson(), action_getvar(), action_listcategories(), action_listcommands(), action_mailboxcount(), and action_mailboxstatus().
02141 { 02142 astman_send_response_full(s, m, "Success", MSG_MOREDATA, NULL); 02143 }
static int authenticate | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 2422 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_t_link, ao2_t_ref, ast_apply_ha(), ast_copy_string(), ast_debug, ast_inet_ntoa(), ast_log(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_sockaddr_from_sin, ast_strlen_zero(), ast_tvnow(), astman_get_header(), mansession_session::blackfilters, ast_manager_user::blackfilters, mansession_session::challenge, get_manager_by_name_locked(), ast_manager_user::ha, len(), LOG_NOTICE, MD5Final(), MD5Init(), MD5Update(), ast_manager_user::readperm, mansession_session::readperm, report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), S_OR, ast_manager_user::secret, mansession::session, mansession_session::sessionstart, mansession_session::sessionstart_tv, set_eventmask(), mansession_session::sin, mansession_session::username, mansession_session::whitefilters, ast_manager_user::whitefilters, ast_manager_user::writeperm, mansession_session::writeperm, ast_manager_user::writetimeout, and mansession_session::writetimeout.
Referenced by action_login().
02423 { 02424 const char *username = astman_get_header(m, "Username"); 02425 const char *password = astman_get_header(m, "Secret"); 02426 int error = -1; 02427 struct ast_manager_user *user = NULL; 02428 regex_t *regex_filter; 02429 struct ao2_iterator filter_iter; 02430 struct ast_sockaddr addr; 02431 02432 if (ast_strlen_zero(username)) { /* missing username */ 02433 return -1; 02434 } 02435 02436 /* locate user in locked state */ 02437 AST_RWLIST_WRLOCK(&users); 02438 02439 ast_sockaddr_from_sin(&addr, &s->session->sin); 02440 02441 if (!(user = get_manager_by_name_locked(username))) { 02442 report_invalid_user(s, username); 02443 ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02444 } else if (user->ha && !ast_apply_ha(user->ha, &addr)) { 02445 report_failed_acl(s, username); 02446 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02447 } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) { 02448 const char *key = astman_get_header(m, "Key"); 02449 if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) { 02450 int x; 02451 int len = 0; 02452 char md5key[256] = ""; 02453 struct MD5Context md5; 02454 unsigned char digest[16]; 02455 02456 MD5Init(&md5); 02457 MD5Update(&md5, (unsigned char *) s->session->challenge, strlen(s->session->challenge)); 02458 MD5Update(&md5, (unsigned char *) user->secret, strlen(user->secret)); 02459 MD5Final(digest, &md5); 02460 for (x = 0; x < 16; x++) 02461 len += sprintf(md5key + len, "%2.2x", (unsigned)digest[x]); 02462 if (!strcmp(md5key, key)) { 02463 error = 0; 02464 } else { 02465 report_failed_challenge_response(s, key, md5key); 02466 } 02467 } else { 02468 ast_debug(1, "MD5 authentication is not possible. challenge: '%s'\n", 02469 S_OR(s->session->challenge, "")); 02470 } 02471 } else if (user->secret) { 02472 if (!strcmp(password, user->secret)) { 02473 error = 0; 02474 } else { 02475 report_inval_password(s, username); 02476 } 02477 } 02478 02479 if (error) { 02480 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username); 02481 AST_RWLIST_UNLOCK(&users); 02482 return -1; 02483 } 02484 02485 /* auth complete */ 02486 02487 /* All of the user parameters are copied to the session so that in the event 02488 * of a reload and a configuration change, the session parameters are not 02489 * changed. */ 02490 ast_copy_string(s->session->username, username, sizeof(s->session->username)); 02491 s->session->readperm = user->readperm; 02492 s->session->writeperm = user->writeperm; 02493 s->session->writetimeout = user->writetimeout; 02494 02495 filter_iter = ao2_iterator_init(user->whitefilters, 0); 02496 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02497 ao2_t_link(s->session->whitefilters, regex_filter, "add white user filter to session"); 02498 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02499 } 02500 ao2_iterator_destroy(&filter_iter); 02501 02502 filter_iter = ao2_iterator_init(user->blackfilters, 0); 02503 while ((regex_filter = ao2_iterator_next(&filter_iter))) { 02504 ao2_t_link(s->session->blackfilters, regex_filter, "add black user filter to session"); 02505 ao2_t_ref(regex_filter, -1, "remove iterator ref"); 02506 } 02507 ao2_iterator_destroy(&filter_iter); 02508 02509 s->session->sessionstart = time(NULL); 02510 s->session->sessionstart_tv = ast_tvnow(); 02511 set_eventmask(s, astman_get_header(m, "Events")); 02512 02513 report_auth_success(s); 02514 02515 AST_RWLIST_UNLOCK(&users); 02516 return 0; 02517 }
static const char* authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options. Note that the EVENT_FLAG_ALL authority will always be returned.
Definition at line 1235 of file manager.c.
References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), and perms.
Referenced by __ast_manager_event_multichan(), action_listcommands(), action_login(), handle_showmancmd(), and handle_showmancmds().
01236 { 01237 int i; 01238 char *sep = ""; 01239 01240 ast_str_reset(*res); 01241 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01242 if (authority & perms[i].num) { 01243 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01244 sep = ","; 01245 } 01246 } 01247 01248 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01249 ast_str_append(res, 0, "<none>"); 01250 01251 return ast_str_buffer(*res); 01252 }
static int blackfilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4379 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
static struct mansession_session* build_mansession | ( | struct sockaddr_in | sin | ) | [static, read] |
Allocate manager session structure and add it to the list of sessions.
Definition at line 1375 of file manager.c.
References ao2_alloc, ao2_container_alloc, ao2_link, ao2_ref, AST_PTHREADT_NULL, mansession_session::blackfilters, mansession_session::fd, mansession_session::send_events, session_destructor(), sessions, mansession_session::sin, mansession_session::waiting_thread, mansession_session::whitefilters, and mansession_session::writetimeout.
Referenced by auth_http_callback(), generic_http_callback(), and session_do().
01376 { 01377 struct mansession_session *newsession; 01378 01379 if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) { 01380 return NULL; 01381 } 01382 01383 if (!(newsession->whitefilters = ao2_container_alloc(1, NULL, NULL))) { 01384 ao2_ref(newsession, -1); 01385 return NULL; 01386 } 01387 01388 if (!(newsession->blackfilters = ao2_container_alloc(1, NULL, NULL))) { 01389 ao2_ref(newsession, -1); /* session_destructor will cleanup the other filter */ 01390 return NULL; 01391 } 01392 01393 newsession->fd = -1; 01394 newsession->waiting_thread = AST_PTHREADT_NULL; 01395 newsession->writetimeout = 100; 01396 newsession->send_events = -1; 01397 newsession->sin = sin; 01398 01399 ao2_link(sessions, newsession); 01400 01401 return newsession; 01402 }
static int check_blacklist | ( | const char * | cmd | ) | [static] |
Definition at line 3696 of file manager.c.
References ARRAY_LEN, ast_strdupa, ast_strip(), ast_strlen_zero(), command_blacklist, match(), MAX_BLACKLIST_CMD_LEN, and words.
Referenced by action_command().
03697 { 03698 char *cmd_copy, *cur_cmd; 03699 char *cmd_words[MAX_BLACKLIST_CMD_LEN] = { NULL, }; 03700 int i; 03701 03702 cmd_copy = ast_strdupa(cmd); 03703 for (i = 0; i < MAX_BLACKLIST_CMD_LEN && (cur_cmd = strsep(&cmd_copy, " ")); i++) { 03704 cur_cmd = ast_strip(cur_cmd); 03705 if (ast_strlen_zero(cur_cmd)) { 03706 i--; 03707 continue; 03708 } 03709 03710 cmd_words[i] = cur_cmd; 03711 } 03712 03713 for (i = 0; i < ARRAY_LEN(command_blacklist); i++) { 03714 int j, match = 1; 03715 03716 for (j = 0; command_blacklist[i].words[j]; j++) { 03717 if (ast_strlen_zero(cmd_words[j]) || strcasecmp(cmd_words[j], command_blacklist[i].words[j])) { 03718 match = 0; 03719 break; 03720 } 03721 } 03722 03723 if (match) { 03724 return 1; 03725 } 03726 } 03727 03728 return 0; 03729 }
int check_manager_enabled | ( | void | ) |
Check if AMI is enabled.
Definition at line 1107 of file manager.c.
Referenced by handle_show_settings().
01108 { 01109 return manager_enabled; 01110 }
static int check_manager_session_inuse | ( | const char * | name | ) | [static] |
Definition at line 1418 of file manager.c.
References ao2_find, mansession_session::inuse, sessions, and unref_mansession().
Referenced by process_message().
01419 { 01420 struct mansession_session *session = ao2_find(sessions, (char *) name, 0); 01421 int inuse = 0; 01422 01423 if (session) { 01424 inuse = 1; 01425 unref_mansession(session); 01426 } 01427 return inuse; 01428 }
int check_webmanager_enabled | ( | void | ) |
Check if AMI/HTTP is enabled.
Definition at line 1112 of file manager.c.
Referenced by action_coresettings(), and handle_show_settings().
01113 { 01114 return (webmanager_enabled && manager_enabled); 01115 }
static void destroy_fast_originate_helper | ( | struct fast_originate_helper * | doomed | ) | [static] |
Definition at line 3833 of file manager.c.
References ast_free, ast_string_field_free_memory, ast_variables_destroy(), and fast_originate_helper::vars.
Referenced by action_originate(), and fast_originate().
03834 { 03835 ast_variables_destroy(doomed->vars); 03836 ast_string_field_free_memory(doomed); 03837 ast_free(doomed); 03838 }
static int do_message | ( | struct mansession * | s | ) | [static] |
Definition at line 4985 of file manager.c.
References ARRAY_LEN, ast_free, ast_inet_ntoa(), ast_log(), ast_strdup, ast_strlen_zero(), ast_verb, astman_send_error(), mansession_session::authenticated, mansession_session::authstart, errno, get_input(), handle_parse_error(), message::hdrcount, message::headers, mansession_session::inbuf, LOG_ERROR, mansession_lock(), mansession_unlock(), MESSAGE_LINE_TOO_LONG, MESSAGE_OKAY, mansession::parsing, process_events(), process_message(), mansession::session, and mansession_session::sin.
Referenced by session_do().
04986 { 04987 struct message m = { 0 }; 04988 char header_buf[sizeof(s->session->inbuf)] = { '\0' }; 04989 int res; 04990 int idx; 04991 int hdr_loss; 04992 time_t now; 04993 04994 hdr_loss = 0; 04995 for (;;) { 04996 /* Check if any events are pending and do them if needed */ 04997 if (process_events(s)) { 04998 res = -1; 04999 break; 05000 } 05001 res = get_input(s, header_buf); 05002 if (res == 0) { 05003 /* No input line received. */ 05004 if (!s->session->authenticated) { 05005 if (time(&now) == -1) { 05006 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 05007 res = -1; 05008 break; 05009 } 05010 05011 if (now - s->session->authstart > authtimeout) { 05012 if (displayconnects) { 05013 ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout); 05014 } 05015 res = -1; 05016 break; 05017 } 05018 } 05019 continue; 05020 } else if (res > 0) { 05021 /* Input line received. */ 05022 if (ast_strlen_zero(header_buf)) { 05023 if (hdr_loss) { 05024 mansession_lock(s); 05025 astman_send_error(s, &m, "Too many lines in message or allocation failure"); 05026 mansession_unlock(s); 05027 res = 0; 05028 } else { 05029 switch (s->parsing) { 05030 case MESSAGE_OKAY: 05031 res = process_message(s, &m) ? -1 : 0; 05032 break; 05033 case MESSAGE_LINE_TOO_LONG: 05034 handle_parse_error(s, &m, "Failed to parse message: line too long"); 05035 res = 0; 05036 break; 05037 } 05038 } 05039 break; 05040 } else if (m.hdrcount < ARRAY_LEN(m.headers)) { 05041 m.headers[m.hdrcount] = ast_strdup(header_buf); 05042 if (!m.headers[m.hdrcount]) { 05043 /* Allocation failure. */ 05044 hdr_loss = 1; 05045 } else { 05046 ++m.hdrcount; 05047 } 05048 } else { 05049 /* Too many lines in message. */ 05050 hdr_loss = 1; 05051 } 05052 } else { 05053 /* Input error. */ 05054 break; 05055 } 05056 } 05057 05058 /* Free AMI request headers. */ 05059 for (idx = 0; idx < m.hdrcount; ++idx) { 05060 ast_free((void *) m.headers[idx]); 05061 } 05062 return res; 05063 }
static void event_filter_destructor | ( | void * | obj | ) | [static] |
Definition at line 1339 of file manager.c.
Referenced by __init_manager().
static void* fast_originate | ( | void * | data | ) | [static] |
Definition at line 3840 of file manager.c.
References fast_originate_helper::account, fast_originate_helper::app, fast_originate_helper::appdata, AST_CHANNEL_NAME, ast_channel_unlock, ast_manager_event_multichan, ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), fast_originate_helper::cid_name, fast_originate_helper::cid_num, fast_originate_helper::context, fast_originate_helper::data, destroy_fast_originate_helper(), EVENT_FLAG_CALL, fast_originate_helper::exten, fast_originate_helper::format, fast_originate_helper::idtext, fast_originate_helper::priority, S_OR, fast_originate_helper::tech, fast_originate_helper::timeout, and fast_originate_helper::vars.
Referenced by action_originate().
03841 { 03842 struct fast_originate_helper *in = data; 03843 int res; 03844 int reason = 0; 03845 struct ast_channel *chan = NULL, *chans[1]; 03846 char requested_channel[AST_CHANNEL_NAME]; 03847 03848 if (!ast_strlen_zero(in->app)) { 03849 res = ast_pbx_outgoing_app(in->tech, in->format, (char *) in->data, 03850 in->timeout, in->app, in->appdata, &reason, 1, 03851 S_OR(in->cid_num, NULL), 03852 S_OR(in->cid_name, NULL), 03853 in->vars, in->account, &chan); 03854 } else { 03855 res = ast_pbx_outgoing_exten(in->tech, in->format, (char *) in->data, 03856 in->timeout, in->context, in->exten, in->priority, &reason, 1, 03857 S_OR(in->cid_num, NULL), 03858 S_OR(in->cid_name, NULL), 03859 in->vars, in->account, &chan); 03860 } 03861 /* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */ 03862 in->vars = NULL; 03863 03864 if (!chan) { 03865 snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data); 03866 } 03867 /* Tell the manager what happened with the channel */ 03868 chans[0] = chan; 03869 ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans, 03870 "%s" 03871 "Response: %s\r\n" 03872 "Channel: %s\r\n" 03873 "Context: %s\r\n" 03874 "Exten: %s\r\n" 03875 "Reason: %d\r\n" 03876 "Uniqueid: %s\r\n" 03877 "CallerIDNum: %s\r\n" 03878 "CallerIDName: %s\r\n", 03879 in->idtext, res ? "Failure" : "Success", 03880 chan ? chan->name : requested_channel, in->context, in->exten, reason, 03881 chan ? chan->uniqueid : "<null>", 03882 S_OR(in->cid_num, "<unknown>"), 03883 S_OR(in->cid_name, "<unknown>") 03884 ); 03885 03886 /* Locked by ast_pbx_outgoing_exten or ast_pbx_outgoing_app */ 03887 if (chan) { 03888 ast_channel_unlock(chan); 03889 } 03890 destroy_fast_originate_helper(in); 03891 return NULL; 03892 }
static void free_channelvars | ( | void | ) | [static] |
Definition at line 7253 of file manager.c.
References ast_free, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and var.
Referenced by load_channelvars(), and manager_set_defaults().
07254 { 07255 struct manager_channel_variable *var; 07256 AST_RWLIST_WRLOCK(&channelvars); 07257 while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) { 07258 ast_free(var); 07259 } 07260 AST_RWLIST_UNLOCK(&channelvars); 07261 }
static int function_capable_string_allowed_with_auths | ( | const char * | evaluating, | |
int | writepermlist | |||
) | [static] |
Checks to see if a string which can be used to evaluate functions should be rejected.
Definition at line 1199 of file manager.c.
References EVENT_FLAG_SYSTEM.
Referenced by action_getvar(), and action_status().
01200 { 01201 if (!(writepermlist & EVENT_FLAG_SYSTEM) 01202 && ( 01203 strstr(evaluating, "SHELL") || /* NoOp(${SHELL(rm -rf /)}) */ 01204 strstr(evaluating, "EVAL") /* NoOp(${EVAL(${some_var_containing_SHELL})}) */ 01205 )) { 01206 return 0; 01207 } 01208 return 1; 01209 }
static int get_input | ( | struct mansession * | s, | |
char * | output | |||
) | [static] |
Read one full line (including crlf) from the manager socket.
* \r\n is the only valid terminator for the line. * (Note that, later, '\0' will be considered as the end-of-line marker, * so everything between the '\0' and the '\r\n' will not be used). * Also note that we assume output to have at least "maxlen" space. *
Definition at line 4870 of file manager.c.
References ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_log(), AST_PTHREADT_NULL, ast_wait_for_input(), mansession_session::authenticated, mansession_session::authstart, errno, mansession_session::f, mansession_session::fd, mansession_session::inbuf, mansession_session::inlen, LOG_ERROR, LOG_WARNING, MESSAGE_LINE_TOO_LONG, mansession::parsing, mansession_session::pending_event, mansession::session, mansession_session::sin, ast_frame::src, and mansession_session::waiting_thread.
Referenced by do_message().
04871 { 04872 int res, x; 04873 int maxlen = sizeof(s->session->inbuf) - 1; 04874 char *src = s->session->inbuf; 04875 int timeout = -1; 04876 time_t now; 04877 04878 /* 04879 * Look for \r\n within the buffer. If found, copy to the output 04880 * buffer and return, trimming the \r\n (not used afterwards). 04881 */ 04882 for (x = 0; x < s->session->inlen; x++) { 04883 int cr; /* set if we have \r */ 04884 if (src[x] == '\r' && x+1 < s->session->inlen && src[x + 1] == '\n') { 04885 cr = 2; /* Found. Update length to include \r\n */ 04886 } else if (src[x] == '\n') { 04887 cr = 1; /* also accept \n only */ 04888 } else { 04889 continue; 04890 } 04891 memmove(output, src, x); /*... but trim \r\n */ 04892 output[x] = '\0'; /* terminate the string */ 04893 x += cr; /* number of bytes used */ 04894 s->session->inlen -= x; /* remaining size */ 04895 memmove(src, src + x, s->session->inlen); /* remove used bytes */ 04896 return 1; 04897 } 04898 if (s->session->inlen >= maxlen) { 04899 /* no crlf found, and buffer full - sorry, too long for us */ 04900 ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_inet_ntoa(s->session->sin.sin_addr), src); 04901 s->session->inlen = 0; 04902 s->parsing = MESSAGE_LINE_TOO_LONG; 04903 } 04904 res = 0; 04905 while (res == 0) { 04906 /* calculate a timeout if we are not authenticated */ 04907 if (!s->session->authenticated) { 04908 if(time(&now) == -1) { 04909 ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno)); 04910 return -1; 04911 } 04912 04913 timeout = (authtimeout - (now - s->session->authstart)) * 1000; 04914 if (timeout < 0) { 04915 /* we have timed out */ 04916 return 0; 04917 } 04918 } 04919 04920 ao2_lock(s->session); 04921 if (s->session->pending_event) { 04922 s->session->pending_event = 0; 04923 ao2_unlock(s->session); 04924 return 0; 04925 } 04926 s->session->waiting_thread = pthread_self(); 04927 ao2_unlock(s->session); 04928 04929 res = ast_wait_for_input(s->session->fd, timeout); 04930 04931 ao2_lock(s->session); 04932 s->session->waiting_thread = AST_PTHREADT_NULL; 04933 ao2_unlock(s->session); 04934 } 04935 if (res < 0) { 04936 /* If we get a signal from some other thread (typically because 04937 * there are new events queued), return 0 to notify the caller. 04938 */ 04939 if (errno == EINTR || errno == EAGAIN) { 04940 return 0; 04941 } 04942 ast_log(LOG_WARNING, "poll() returned error: %s\n", strerror(errno)); 04943 return -1; 04944 } 04945 04946 ao2_lock(s->session); 04947 res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f); 04948 if (res < 1) { 04949 res = -1; /* error return */ 04950 } else { 04951 s->session->inlen += res; 04952 src[s->session->inlen] = '\0'; 04953 res = 0; 04954 } 04955 ao2_unlock(s->session); 04956 return res; 04957 }
static struct ast_manager_user* get_manager_by_name_locked | ( | const char * | name | ) | [static, read] |
lookup an entry in the list of registered users. must be called with the list lock held.
Definition at line 1435 of file manager.c.
References AST_RWLIST_TRAVERSE, ast_manager_user::list, and ast_manager_user::username.
Referenced by __init_manager(), auth_http_callback(), authenticate(), handle_showmanager(), and manager_displayconnects().
01436 { 01437 struct ast_manager_user *user = NULL; 01438 01439 AST_RWLIST_TRAVERSE(&users, user, list) { 01440 if (!strcasecmp(user->username, name)) { 01441 break; 01442 } 01443 } 01444 01445 return user; 01446 }
static int get_perm | ( | const char * | instr | ) | [static] |
Definition at line 1278 of file manager.c.
References ARRAY_LEN, ast_instring(), permalias::num, and perms.
Referenced by __init_manager(), and strings_to_mask().
static struct eventqent* grab_last | ( | void | ) | [static, read] |
Grab a reference to the last event, update usecount as needed. Can handle a NULL pointer.
Definition at line 1121 of file manager.c.
References ast_atomic_fetchadd_int(), AST_RWLIST_LAST, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and eventqent::usecount.
Referenced by auth_http_callback(), generic_http_callback(), and session_do().
01122 { 01123 struct eventqent *ret; 01124 01125 AST_RWLIST_WRLOCK(&all_events); 01126 ret = AST_RWLIST_LAST(&all_events); 01127 /* the list is never empty now, but may become so when 01128 * we optimize it in the future, so be prepared. 01129 */ 01130 if (ret) { 01131 ast_atomic_fetchadd_int(&ret->usecount, 1); 01132 } 01133 AST_RWLIST_UNLOCK(&all_events); 01134 return ret; 01135 }
static char* handle_manager_reload | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager reload.
Definition at line 1774 of file manager.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, reload_manager(), and ast_cli_entry::usage.
01775 { 01776 switch (cmd) { 01777 case CLI_INIT: 01778 e->command = "manager reload"; 01779 e->usage = 01780 "Usage: manager reload\n" 01781 " Reloads the manager configuration.\n"; 01782 return NULL; 01783 case CLI_GENERATE: 01784 return NULL; 01785 } 01786 if (a->argc > 2) { 01787 return CLI_SHOWUSAGE; 01788 } 01789 reload_manager(); 01790 return CLI_SUCCESS; 01791 }
static char* handle_mandebug | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1548 of file manager.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.
01549 { 01550 switch (cmd) { 01551 case CLI_INIT: 01552 e->command = "manager set debug [on|off]"; 01553 e->usage = "Usage: manager set debug [on|off]\n Show, enable, disable debugging of the manager code.\n"; 01554 return NULL; 01555 case CLI_GENERATE: 01556 return NULL; 01557 } 01558 01559 if (a->argc == 3) { 01560 ast_cli(a->fd, "manager debug is %s\n", manager_debug? "on" : "off"); 01561 } else if (a->argc == 4) { 01562 if (!strcasecmp(a->argv[3], "on")) { 01563 manager_debug = 1; 01564 } else if (!strcasecmp(a->argv[3], "off")) { 01565 manager_debug = 0; 01566 } else { 01567 return CLI_SHOWUSAGE; 01568 } 01569 } 01570 return CLI_SUCCESS; 01571 }
static void handle_parse_error | ( | struct mansession * | s, | |
struct message * | m, | |||
char * | error | |||
) | [static] |
Definition at line 4968 of file manager.c.
References astman_send_error(), mansession_lock(), mansession_unlock(), MESSAGE_OKAY, and mansession::parsing.
Referenced by do_message().
04969 { 04970 mansession_lock(s); 04971 astman_send_error(s, m, error); 04972 s->parsing = MESSAGE_OKAY; 04973 mansession_unlock(s); 04974 }
static char* handle_showmanager | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1573 of file manager.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_manager_user::displayconnects, ast_cli_args::fd, get_manager_by_name_locked(), ast_manager_user::ha, ast_cli_args::n, ast_cli_args::pos, ast_manager_user::readperm, ast_manager_user::secret, ast_cli_entry::usage, user_authority_to_str(), ast_manager_user::username, ast_cli_args::word, and ast_manager_user::writeperm.
01574 { 01575 struct ast_manager_user *user = NULL; 01576 int l, which; 01577 char *ret = NULL; 01578 struct ast_str *rauthority = ast_str_alloca(128); 01579 struct ast_str *wauthority = ast_str_alloca(128); 01580 01581 switch (cmd) { 01582 case CLI_INIT: 01583 e->command = "manager show user"; 01584 e->usage = 01585 " Usage: manager show user <user>\n" 01586 " Display all information related to the manager user specified.\n"; 01587 return NULL; 01588 case CLI_GENERATE: 01589 l = strlen(a->word); 01590 which = 0; 01591 if (a->pos != 3) { 01592 return NULL; 01593 } 01594 AST_RWLIST_RDLOCK(&users); 01595 AST_RWLIST_TRAVERSE(&users, user, list) { 01596 if ( !strncasecmp(a->word, user->username, l) && ++which > a->n ) { 01597 ret = ast_strdup(user->username); 01598 break; 01599 } 01600 } 01601 AST_RWLIST_UNLOCK(&users); 01602 return ret; 01603 } 01604 01605 if (a->argc != 4) { 01606 return CLI_SHOWUSAGE; 01607 } 01608 01609 AST_RWLIST_RDLOCK(&users); 01610 01611 if (!(user = get_manager_by_name_locked(a->argv[3]))) { 01612 ast_cli(a->fd, "There is no manager called %s\n", a->argv[3]); 01613 AST_RWLIST_UNLOCK(&users); 01614 return CLI_SUCCESS; 01615 } 01616 01617 ast_cli(a->fd, "\n"); 01618 ast_cli(a->fd, 01619 " username: %s\n" 01620 " secret: %s\n" 01621 " acl: %s\n" 01622 " read perm: %s\n" 01623 " write perm: %s\n" 01624 "displayconnects: %s\n", 01625 (user->username ? user->username : "(N/A)"), 01626 (user->secret ? "<Set>" : "(N/A)"), 01627 (user->ha ? "yes" : "no"), 01628 user_authority_to_str(user->readperm, &rauthority), 01629 user_authority_to_str(user->writeperm, &wauthority), 01630 (user->displayconnects ? "yes" : "no")); 01631 01632 AST_RWLIST_UNLOCK(&users); 01633 01634 return CLI_SUCCESS; 01635 }
static char* handle_showmanagers | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1637 of file manager.c.
References ast_cli_args::argc, ast_cli(), AST_RWLIST_EMPTY, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_manager_user::list, ast_cli_entry::usage, and ast_manager_user::username.
01638 { 01639 struct ast_manager_user *user = NULL; 01640 int count_amu = 0; 01641 switch (cmd) { 01642 case CLI_INIT: 01643 e->command = "manager show users"; 01644 e->usage = 01645 "Usage: manager show users\n" 01646 " Prints a listing of all managers that are currently configured on that\n" 01647 " system.\n"; 01648 return NULL; 01649 case CLI_GENERATE: 01650 return NULL; 01651 } 01652 if (a->argc != 3) { 01653 return CLI_SHOWUSAGE; 01654 } 01655 01656 AST_RWLIST_RDLOCK(&users); 01657 01658 /* If there are no users, print out something along those lines */ 01659 if (AST_RWLIST_EMPTY(&users)) { 01660 ast_cli(a->fd, "There are no manager users.\n"); 01661 AST_RWLIST_UNLOCK(&users); 01662 return CLI_SUCCESS; 01663 } 01664 01665 ast_cli(a->fd, "\nusername\n--------\n"); 01666 01667 AST_RWLIST_TRAVERSE(&users, user, list) { 01668 ast_cli(a->fd, "%s\n", user->username); 01669 count_amu++; 01670 } 01671 01672 AST_RWLIST_UNLOCK(&users); 01673 01674 ast_cli(a->fd,"-------------------\n" 01675 "%d manager users configured.\n", count_amu); 01676 return CLI_SUCCESS; 01677 }
static char* handle_showmancmd | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 1466 of file manager.c.
References manager_action::action, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_free, AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, ast_strdup, AST_XML_DOC, ast_xmldoc_printable(), manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_MAGENTA, ast_cli_entry::command, manager_action::docsrc, ast_cli_args::fd, ast_cli_args::n, S_OR, synopsis, term_color(), ast_cli_entry::usage, and ast_cli_args::word.
01467 { 01468 struct manager_action *cur; 01469 struct ast_str *authority; 01470 int num, l, which; 01471 char *ret = NULL; 01472 #ifdef AST_XML_DOCS 01473 char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64]; 01474 #endif 01475 01476 switch (cmd) { 01477 case CLI_INIT: 01478 e->command = "manager show command"; 01479 e->usage = 01480 "Usage: manager show command <actionname> [<actionname> [<actionname> [...]]]\n" 01481 " Shows the detailed description for a specific Asterisk manager interface command.\n"; 01482 return NULL; 01483 case CLI_GENERATE: 01484 l = strlen(a->word); 01485 which = 0; 01486 AST_RWLIST_RDLOCK(&actions); 01487 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01488 if (!strncasecmp(a->word, cur->action, l) && ++which > a->n) { 01489 ret = ast_strdup(cur->action); 01490 break; /* make sure we exit even if ast_strdup() returns NULL */ 01491 } 01492 } 01493 AST_RWLIST_UNLOCK(&actions); 01494 return ret; 01495 } 01496 authority = ast_str_alloca(80); 01497 if (a->argc < 4) { 01498 return CLI_SHOWUSAGE; 01499 } 01500 01501 #ifdef AST_XML_DOCS 01502 /* setup the titles */ 01503 term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40); 01504 term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40); 01505 term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40); 01506 term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40); 01507 term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40); 01508 #endif 01509 01510 AST_RWLIST_RDLOCK(&actions); 01511 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01512 for (num = 3; num < a->argc; num++) { 01513 if (!strcasecmp(cur->action, a->argv[num])) { 01514 #ifdef AST_XML_DOCS 01515 if (cur->docsrc == AST_XML_DOC) { 01516 char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1); 01517 char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1); 01518 char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1); 01519 char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1); 01520 char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1); 01521 ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", 01522 syntax_title, syntax, 01523 synopsis_title, synopsis, 01524 description_title, description, 01525 arguments_title, arguments, 01526 seealso_title, seealso); 01527 ast_free(syntax); 01528 ast_free(synopsis); 01529 ast_free(description); 01530 ast_free(arguments); 01531 ast_free(seealso); 01532 } else 01533 #endif 01534 { 01535 ast_cli(a->fd, "Action: %s\nSynopsis: %s\nPrivilege: %s\n%s\n", 01536 cur->action, cur->synopsis, 01537 authority_to_str(cur->authority, &authority), 01538 S_OR(cur->description, "")); 01539 } 01540 } 01541 } 01542 } 01543 AST_RWLIST_UNLOCK(&actions); 01544 01545 return CLI_SUCCESS; 01546 }
static char* handle_showmancmds | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list commands.
Definition at line 1680 of file manager.c.
References manager_action::action, ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, ast_str_alloca, manager_action::authority, authority_to_str(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, HSMC_FORMAT, and ast_cli_entry::usage.
01681 { 01682 struct manager_action *cur; 01683 struct ast_str *authority; 01684 #define HSMC_FORMAT " %-15.15s %-15.15s %-55.55s\n" 01685 switch (cmd) { 01686 case CLI_INIT: 01687 e->command = "manager show commands"; 01688 e->usage = 01689 "Usage: manager show commands\n" 01690 " Prints a listing of all the available Asterisk manager interface commands.\n"; 01691 return NULL; 01692 case CLI_GENERATE: 01693 return NULL; 01694 } 01695 authority = ast_str_alloca(80); 01696 ast_cli(a->fd, HSMC_FORMAT, "Action", "Privilege", "Synopsis"); 01697 ast_cli(a->fd, HSMC_FORMAT, "------", "---------", "--------"); 01698 01699 AST_RWLIST_RDLOCK(&actions); 01700 AST_RWLIST_TRAVERSE(&actions, cur, list) { 01701 ast_cli(a->fd, HSMC_FORMAT, cur->action, authority_to_str(cur->authority, &authority), cur->synopsis); 01702 } 01703 AST_RWLIST_UNLOCK(&actions); 01704 01705 return CLI_SUCCESS; 01706 }
static char* handle_showmanconn | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list connected.
Definition at line 1709 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_cli(), ast_inet_ntoa(), CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, mansession_session::fd, ast_cli_args::fd, HSMCONN_FORMAT1, HSMCONN_FORMAT2, mansession_session::inuse, mansession_session::readperm, sessions, mansession_session::sessionstart, mansession_session::sin, unref_mansession(), ast_cli_entry::usage, mansession_session::username, and mansession_session::writeperm.
01710 { 01711 struct mansession_session *session; 01712 time_t now = time(NULL); 01713 #define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n" 01714 #define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n" 01715 int count = 0; 01716 struct ao2_iterator i; 01717 01718 switch (cmd) { 01719 case CLI_INIT: 01720 e->command = "manager show connected"; 01721 e->usage = 01722 "Usage: manager show connected\n" 01723 " Prints a listing of the users that are currently connected to the\n" 01724 "Asterisk manager interface.\n"; 01725 return NULL; 01726 case CLI_GENERATE: 01727 return NULL; 01728 } 01729 01730 ast_cli(a->fd, HSMCONN_FORMAT1, "Username", "IP Address", "Start", "Elapsed", "FileDes", "HttpCnt", "Read", "Write"); 01731 01732 i = ao2_iterator_init(sessions, 0); 01733 while ((session = ao2_iterator_next(&i))) { 01734 ao2_lock(session); 01735 ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm); 01736 count++; 01737 ao2_unlock(session); 01738 unref_mansession(session); 01739 } 01740 ao2_iterator_destroy(&i); 01741 ast_cli(a->fd, "%d users connected.\n", count); 01742 01743 return CLI_SUCCESS; 01744 }
static char* handle_showmaneventq | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
CLI command manager list eventq.
Definition at line 1748 of file manager.c.
References ast_cli(), AST_RWLIST_RDLOCK, AST_RWLIST_TRAVERSE, AST_RWLIST_UNLOCK, eventqent::category, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, eventqent::eventdata, ast_cli_args::fd, ast_cli_entry::usage, and eventqent::usecount.
01749 { 01750 struct eventqent *s; 01751 switch (cmd) { 01752 case CLI_INIT: 01753 e->command = "manager show eventq"; 01754 e->usage = 01755 "Usage: manager show eventq\n" 01756 " Prints a listing of all events pending in the Asterisk manger\n" 01757 "event queue.\n"; 01758 return NULL; 01759 case CLI_GENERATE: 01760 return NULL; 01761 } 01762 AST_RWLIST_RDLOCK(&all_events); 01763 AST_RWLIST_TRAVERSE(&all_events, s, eq_next) { 01764 ast_cli(a->fd, "Usecount: %d\n", s->usecount); 01765 ast_cli(a->fd, "Category: %d\n", s->category); 01766 ast_cli(a->fd, "Event:\n%s", s->eventdata); 01767 } 01768 AST_RWLIST_UNLOCK(&all_events); 01769 01770 return CLI_SUCCESS; 01771 }
static enum error_type handle_updates | ( | struct mansession * | s, | |
const struct message * | m, | |||
struct ast_config * | cfg, | |||
const char * | dfn | |||
) | [static] |
Definition at line 2696 of file manager.c.
References ast_category_append(), ast_category_delete(), ast_category_destroy(), ast_category_empty(), ast_category_get(), ast_category_insert(), ast_category_new(), ast_category_rename(), ast_free, ast_log(), ast_str_create(), ast_strlen_zero(), ast_variable_append(), ast_variable_delete(), ast_variable_insert(), ast_variable_new(), ast_variable_update(), astman_get_header(), eventqent::category, FAILURE_ALLOCATION, FAILURE_DELCAT, FAILURE_DELETE, FAILURE_EMPTYCAT, FAILURE_NEWCAT, FAILURE_UPDATE, LOG_WARNING, match(), ast_variable::object, UNKNOWN_ACTION, UNKNOWN_CATEGORY, UNSPECIFIED_ARGUMENT, UNSPECIFIED_CATEGORY, value, and var.
Referenced by action_updateconfig().
02697 { 02698 int x; 02699 char hdr[40]; 02700 const char *action, *cat, *var, *value, *match, *line; 02701 struct ast_category *category; 02702 struct ast_variable *v; 02703 struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); 02704 enum error_type result = 0; 02705 02706 for (x = 0; x < 100000; x++) { /* 100000 = the max number of allowed updates + 1 */ 02707 unsigned int object = 0; 02708 02709 snprintf(hdr, sizeof(hdr), "Action-%06d", x); 02710 action = astman_get_header(m, hdr); 02711 if (ast_strlen_zero(action)) /* breaks the for loop if no action header */ 02712 break; /* this could cause problems if actions come in misnumbered */ 02713 02714 snprintf(hdr, sizeof(hdr), "Cat-%06d", x); 02715 cat = astman_get_header(m, hdr); 02716 if (ast_strlen_zero(cat)) { /* every action needs a category */ 02717 result = UNSPECIFIED_CATEGORY; 02718 break; 02719 } 02720 02721 snprintf(hdr, sizeof(hdr), "Var-%06d", x); 02722 var = astman_get_header(m, hdr); 02723 02724 snprintf(hdr, sizeof(hdr), "Value-%06d", x); 02725 value = astman_get_header(m, hdr); 02726 02727 if (!ast_strlen_zero(value) && *value == '>') { 02728 object = 1; 02729 value++; 02730 } 02731 02732 snprintf(hdr, sizeof(hdr), "Match-%06d", x); 02733 match = astman_get_header(m, hdr); 02734 02735 snprintf(hdr, sizeof(hdr), "Line-%06d", x); 02736 line = astman_get_header(m, hdr); 02737 02738 if (!strcasecmp(action, "newcat")) { 02739 if (ast_category_get(cfg,cat)) { /* check to make sure the cat doesn't */ 02740 result = FAILURE_NEWCAT; /* already exist */ 02741 break; 02742 } 02743 if (!(category = ast_category_new(cat, dfn, -1))) { 02744 result = FAILURE_ALLOCATION; 02745 break; 02746 } 02747 if (ast_strlen_zero(match)) { 02748 ast_category_append(cfg, category); 02749 } else { 02750 if (ast_category_insert(cfg, category, match)) { 02751 result = FAILURE_NEWCAT; 02752 ast_category_destroy(category); 02753 break; 02754 } 02755 } 02756 } else if (!strcasecmp(action, "renamecat")) { 02757 if (ast_strlen_zero(value)) { 02758 result = UNSPECIFIED_ARGUMENT; 02759 break; 02760 } 02761 if (!(category = ast_category_get(cfg, cat))) { 02762 result = UNKNOWN_CATEGORY; 02763 break; 02764 } 02765 ast_category_rename(category, value); 02766 } else if (!strcasecmp(action, "delcat")) { 02767 if (ast_category_delete(cfg, cat)) { 02768 result = FAILURE_DELCAT; 02769 break; 02770 } 02771 } else if (!strcasecmp(action, "emptycat")) { 02772 if (ast_category_empty(cfg, cat)) { 02773 result = FAILURE_EMPTYCAT; 02774 break; 02775 } 02776 } else if (!strcasecmp(action, "update")) { 02777 if (ast_strlen_zero(var)) { 02778 result = UNSPECIFIED_ARGUMENT; 02779 break; 02780 } 02781 if (!(category = ast_category_get(cfg,cat))) { 02782 result = UNKNOWN_CATEGORY; 02783 break; 02784 } 02785 if (ast_variable_update(category, var, value, match, object)) { 02786 result = FAILURE_UPDATE; 02787 break; 02788 } 02789 } else if (!strcasecmp(action, "delete")) { 02790 if ((ast_strlen_zero(var) && ast_strlen_zero(line))) { 02791 result = UNSPECIFIED_ARGUMENT; 02792 break; 02793 } 02794 if (!(category = ast_category_get(cfg, cat))) { 02795 result = UNKNOWN_CATEGORY; 02796 break; 02797 } 02798 if (ast_variable_delete(category, var, match, line)) { 02799 result = FAILURE_DELETE; 02800 break; 02801 } 02802 } else if (!strcasecmp(action, "append")) { 02803 if (ast_strlen_zero(var)) { 02804 result = UNSPECIFIED_ARGUMENT; 02805 break; 02806 } 02807 if (!(category = ast_category_get(cfg, cat))) { 02808 result = UNKNOWN_CATEGORY; 02809 break; 02810 } 02811 if (!(v = ast_variable_new(var, value, dfn))) { 02812 result = FAILURE_ALLOCATION; 02813 break; 02814 } 02815 if (object || (match && !strcasecmp(match, "object"))) { 02816 v->object = 1; 02817 } 02818 ast_variable_append(category, v); 02819 } else if (!strcasecmp(action, "insert")) { 02820 if (ast_strlen_zero(var) || ast_strlen_zero(line)) { 02821 result = UNSPECIFIED_ARGUMENT; 02822 break; 02823 } 02824 if (!(category = ast_category_get(cfg, cat))) { 02825 result = UNKNOWN_CATEGORY; 02826 break; 02827 } 02828 if (!(v = ast_variable_new(var, value, dfn))) { 02829 result = FAILURE_ALLOCATION; 02830 break; 02831 } 02832 ast_variable_insert(category, v, line); 02833 } 02834 else { 02835 ast_log(LOG_WARNING, "Action-%06d: %s not handled\n", x, action); 02836 result = UNKNOWN_ACTION; 02837 break; 02838 } 02839 } 02840 ast_free(str1); 02841 ast_free(str2); 02842 return result; 02843 }
static void json_escape | ( | char * | out, | |
const char * | in | |||
) | [static] |
The amount of space in out must be at least ( 2 * strlen(in) + 1 )
Definition at line 2618 of file manager.c.
Referenced by astman_append_json().
static struct ast_variable* man_do_variable_value | ( | struct ast_variable * | head, | |
const char * | hdr_val | |||
) | [static, read] |
Definition at line 1874 of file manager.c.
References args, AST_APP_ARG, AST_DECLARE_APP_ARGS, ast_skip_blanks(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_variable_new(), ast_variable::next, parse(), and var.
Referenced by astman_get_variables_order().
01875 { 01876 char *parse; 01877 AST_DECLARE_APP_ARGS(args, 01878 AST_APP_ARG(vars)[64]; 01879 ); 01880 01881 hdr_val = ast_skip_blanks(hdr_val); /* ignore leading spaces in the value */ 01882 parse = ast_strdupa(hdr_val); 01883 01884 /* Break the header value string into name=val pair items. */ 01885 AST_STANDARD_APP_ARGS(args, parse); 01886 if (args.argc) { 01887 int y; 01888 01889 /* Process each name=val pair item. */ 01890 for (y = 0; y < args.argc; y++) { 01891 struct ast_variable *cur; 01892 char *var; 01893 char *val; 01894 01895 if (!args.vars[y]) { 01896 continue; 01897 } 01898 var = val = args.vars[y]; 01899 strsep(&val, "="); 01900 01901 /* XXX We may wish to trim whitespace from the strings. */ 01902 if (!val || ast_strlen_zero(var)) { 01903 continue; 01904 } 01905 01906 /* Create new variable list node and prepend it to the list. */ 01907 cur = ast_variable_new(var, val, ""); 01908 if (cur) { 01909 cur->next = head; 01910 head = cur; 01911 } 01912 } 01913 } 01914 01915 return head; 01916 }
static int manager_displayconnects | ( | struct mansession_session * | session | ) | [static] |
Get displayconnects config option.
session | manager session to get parameter from. |
Definition at line 1452 of file manager.c.
References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_manager_user::displayconnects, get_manager_by_name_locked(), and mansession_session::username.
Referenced by action_login(), generic_http_callback(), purge_sessions(), and session_do().
01453 { 01454 struct ast_manager_user *user = NULL; 01455 int ret = 0; 01456 01457 AST_RWLIST_RDLOCK(&users); 01458 if ((user = get_manager_by_name_locked (session->username))) { 01459 ret = user->displayconnects; 01460 } 01461 AST_RWLIST_UNLOCK(&users); 01462 01463 return ret; 01464 }
static int manager_modulecheck | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4660 of file manager.c.
References ast_copy_string(), ast_file_version_find(), ast_log(), ast_module_check(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), LOG_DEBUG, and version.
Referenced by __init_manager().
04661 { 04662 int res; 04663 const char *module = astman_get_header(m, "Module"); 04664 const char *id = astman_get_header(m, "ActionID"); 04665 char idText[256]; 04666 #if !defined(LOW_MEMORY) 04667 const char *version; 04668 #endif 04669 char filename[PATH_MAX]; 04670 char *cut; 04671 04672 ast_copy_string(filename, module, sizeof(filename)); 04673 if ((cut = strchr(filename, '.'))) { 04674 *cut = '\0'; 04675 } else { 04676 cut = filename + strlen(filename); 04677 } 04678 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".so"); 04679 ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); 04680 res = ast_module_check(filename); 04681 if (!res) { 04682 astman_send_error(s, m, "Module not loaded"); 04683 return 0; 04684 } 04685 snprintf(cut, (sizeof(filename) - strlen(filename)) - 1, ".c"); 04686 ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); 04687 #if !defined(LOW_MEMORY) 04688 version = ast_file_version_find(filename); 04689 #endif 04690 04691 if (!ast_strlen_zero(id)) { 04692 snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); 04693 } else { 04694 idText[0] = '\0'; 04695 } 04696 astman_append(s, "Response: Success\r\n%s", idText); 04697 #if !defined(LOW_MEMORY) 04698 astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); 04699 #endif 04700 return 0; 04701 }
static int manager_moduleload | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4703 of file manager.c.
References AST_FORCE_SOFT, ast_load_resource(), ast_module_reload(), ast_strlen_zero(), ast_unload_resource(), astman_get_header(), astman_send_ack(), and astman_send_error().
Referenced by __init_manager().
04704 { 04705 int res; 04706 const char *module = astman_get_header(m, "Module"); 04707 const char *loadtype = astman_get_header(m, "LoadType"); 04708 04709 if (!loadtype || strlen(loadtype) == 0) { 04710 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04711 } 04712 if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) { 04713 astman_send_error(s, m, "Need module name"); 04714 } 04715 04716 if (!strcasecmp(loadtype, "load")) { 04717 res = ast_load_resource(module); 04718 if (res) { 04719 astman_send_error(s, m, "Could not load module."); 04720 } else { 04721 astman_send_ack(s, m, "Module loaded."); 04722 } 04723 } else if (!strcasecmp(loadtype, "unload")) { 04724 res = ast_unload_resource(module, AST_FORCE_SOFT); 04725 if (res) { 04726 astman_send_error(s, m, "Could not unload module."); 04727 } else { 04728 astman_send_ack(s, m, "Module unloaded."); 04729 } 04730 } else if (!strcasecmp(loadtype, "reload")) { 04731 if (!ast_strlen_zero(module)) { 04732 res = ast_module_reload(module); 04733 if (res == 0) { 04734 astman_send_error(s, m, "No such module."); 04735 } else if (res == 1) { 04736 astman_send_error(s, m, "Module does not support reload action."); 04737 } else { 04738 astman_send_ack(s, m, "Module reloaded."); 04739 } 04740 } else { 04741 ast_module_reload(NULL); /* Reload all modules */ 04742 astman_send_ack(s, m, "All modules reloaded"); 04743 } 04744 } else 04745 astman_send_error(s, m, "Incomplete ModuleLoad action."); 04746 return 0; 04747 }
static int manager_state_cb | ( | char * | context, | |
char * | exten, | |||
int | state, | |||
void * | data | |||
) | [static] |
Definition at line 5404 of file manager.c.
References ast_get_hint(), EVENT_FLAG_CALL, and manager_event.
Referenced by __init_manager().
05405 { 05406 /* Notify managers of change */ 05407 char hint[512]; 05408 ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, context, exten); 05409 05410 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nHint: %s\r\nStatus: %d\r\n", exten, context, hint, state); 05411 return 0; 05412 }
static int mansession_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
int | flags | |||
) | [static] |
Definition at line 1404 of file manager.c.
References CMP_MATCH, str, and mansession_session::username.
Referenced by __init_manager().
01405 { 01406 struct mansession_session *s = obj; 01407 char *str = arg; 01408 return !strcasecmp(s->username, str) ? CMP_MATCH : 0; 01409 }
static struct sockaddr_in* mansession_encode_sin_local | ( | const struct mansession * | s, | |
struct sockaddr_in * | sin_local | |||
) | [static, read] |
Definition at line 2185 of file manager.c.
References ast_sockaddr_to_sin, ast_tcptls_session_args::local_address, ast_tcptls_session_instance::parent, and mansession::tcptls_session.
Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().
02187 { 02188 ast_sockaddr_to_sin(&s->tcptls_session->parent->local_address, 02189 sin_local); 02190 02191 return sin_local; 02192 }
static enum ast_security_event_transport_type mansession_get_transport | ( | const struct mansession * | s | ) | [static] |
Definition at line 2179 of file manager.c.
References AST_SECURITY_EVENT_TRANSPORT_TCP, AST_SECURITY_EVENT_TRANSPORT_TLS, ast_tcptls_session_instance::parent, mansession::tcptls_session, and ast_tcptls_session_args::tls_cfg.
Referenced by report_auth_success(), report_failed_acl(), report_failed_challenge_response(), report_inval_password(), report_invalid_user(), report_req_bad_format(), report_req_not_allowed(), and report_session_limit().
02180 { 02181 return s->tcptls_session->parent->tls_cfg ? AST_SECURITY_EVENT_TRANSPORT_TLS : 02182 AST_SECURITY_EVENT_TRANSPORT_TCP; 02183 }
static void mansession_lock | ( | struct mansession * | s | ) | [static] |
Lock the 'mansession' structure.
Definition at line 2151 of file manager.c.
References ast_mutex_lock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02152 { 02153 ast_mutex_lock(&s->lock); 02154 }
static void mansession_unlock | ( | struct mansession * | s | ) | [static] |
Unlock the 'mansession' structure.
Definition at line 2157 of file manager.c.
References ast_mutex_unlock, and mansession::lock.
Referenced by action_challenge(), do_message(), handle_parse_error(), and process_message().
02158 { 02159 ast_mutex_unlock(&s->lock); 02160 }
static int match_filter | ( | struct mansession * | s, | |
char * | eventdata | |||
) | [static] |
Definition at line 4394 of file manager.c.
References ao2_container_count(), ao2_t_callback_data, ast_debug, blackfilter_cmp_fn(), mansession_session::blackfilters, OBJ_NODATA, mansession::session, whitefilter_cmp_fn(), and mansession_session::whitefilters.
Referenced by action_waitevent(), and process_events().
04395 { 04396 int result = 0; 04397 04398 ast_debug(3, "Examining event:\n%s\n", eventdata); 04399 if (!ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04400 return 1; /* no filtering means match all */ 04401 } else if (ao2_container_count(s->session->whitefilters) && !ao2_container_count(s->session->blackfilters)) { 04402 /* white filters only: implied black all filter processed first, then white filters */ 04403 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04404 } else if (!ao2_container_count(s->session->whitefilters) && ao2_container_count(s->session->blackfilters)) { 04405 /* black filters only: implied white all filter processed first, then black filters */ 04406 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04407 } else { 04408 /* white and black filters: implied black all filter processed first, then white filters, and lastly black filters */ 04409 ao2_t_callback_data(s->session->whitefilters, OBJ_NODATA, whitefilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04410 if (result) { 04411 result = 0; 04412 ao2_t_callback_data(s->session->blackfilters, OBJ_NODATA, blackfilter_cmp_fn, eventdata, &result, "find filter in session filter container"); 04413 } 04414 } 04415 04416 return result; 04417 }
static int process_events | ( | struct mansession * | s | ) | [static] |
Send any applicable events to the client listening on this socket. Wait only for a finite time on each event, and drop all events whether they are successfully sent or not.
Definition at line 4424 of file manager.c.
References advance_event(), ao2_lock, ao2_unlock, mansession_session::authenticated, eventqent::category, eventqent::eventdata, mansession_session::f, mansession_session::last_ev, match_filter(), mansession_session::readperm, mansession_session::send_events, send_string(), and mansession::session.
Referenced by do_message(), and process_message().
04425 { 04426 int ret = 0; 04427 04428 ao2_lock(s->session); 04429 if (s->session->f != NULL) { 04430 struct eventqent *eqe = s->session->last_ev; 04431 04432 while ((eqe = advance_event(eqe))) { 04433 if (!ret && s->session->authenticated && 04434 (s->session->readperm & eqe->category) == eqe->category && 04435 (s->session->send_events & eqe->category) == eqe->category) { 04436 if (match_filter(s, eqe->eventdata)) { 04437 if (send_string(s, eqe->eventdata) < 0) 04438 ret = -1; /* don't send more */ 04439 } 04440 } 04441 s->session->last_ev = eqe; 04442 } 04443 } 04444 ao2_unlock(s->session); 04445 return ret; 04446 }
static int process_message | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 4762 of file manager.c.
References __astman_get_header(), manager_action::action, action_find(), manager_action::active_count, ao2_lock, ao2_t_ref, ao2_unlock, ast_debug, ast_strlen_zero(), astman_get_header(), astman_send_error(), mansession_session::authenticated, manager_action::authority, check_manager_session_inuse(), manager_action::func, GET_HEADER_SKIP_EMPTY, mansession_lock(), mansession_unlock(), process_events(), manager_action::registered, report_req_bad_format(), report_req_not_allowed(), report_session_limit(), mansession::session, and mansession_session::writeperm.
Referenced by auth_http_callback(), do_message(), and generic_http_callback().
04763 { 04764 int ret = 0; 04765 struct manager_action *act_found; 04766 const char *user; 04767 const char *action; 04768 04769 action = __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY); 04770 if (ast_strlen_zero(action)) { 04771 report_req_bad_format(s, "NONE"); 04772 mansession_lock(s); 04773 astman_send_error(s, m, "Missing action in request"); 04774 mansession_unlock(s); 04775 return 0; 04776 } 04777 04778 if (!s->session->authenticated 04779 && strcasecmp(action, "Login") 04780 && strcasecmp(action, "Logoff") 04781 && strcasecmp(action, "Challenge")) { 04782 if (!s->session->authenticated) { 04783 report_req_not_allowed(s, action); 04784 } 04785 mansession_lock(s); 04786 astman_send_error(s, m, "Permission denied"); 04787 mansession_unlock(s); 04788 return 0; 04789 } 04790 04791 if (!allowmultiplelogin 04792 && !s->session->authenticated 04793 && (!strcasecmp(action, "Login") 04794 || !strcasecmp(action, "Challenge"))) { 04795 user = astman_get_header(m, "Username"); 04796 04797 if (!ast_strlen_zero(user) && check_manager_session_inuse(user)) { 04798 report_session_limit(s); 04799 sleep(1); 04800 mansession_lock(s); 04801 astman_send_error(s, m, "Login Already In Use"); 04802 mansession_unlock(s); 04803 return -1; 04804 } 04805 } 04806 04807 act_found = action_find(action); 04808 if (act_found) { 04809 /* Found the requested AMI action. */ 04810 int acted = 0; 04811 04812 if ((s->session->writeperm & act_found->authority) 04813 || act_found->authority == 0) { 04814 /* We have the authority to execute the action. */ 04815 ao2_lock(act_found); 04816 if (act_found->registered && act_found->func) { 04817 ast_debug(1, "Running action '%s'\n", act_found->action); 04818 ++act_found->active_count; 04819 ao2_unlock(act_found); 04820 ret = act_found->func(s, m); 04821 acted = 1; 04822 ao2_lock(act_found); 04823 --act_found->active_count; 04824 } 04825 ao2_unlock(act_found); 04826 } 04827 if (!acted) { 04828 /* 04829 * We did not execute the action because access was denied, it 04830 * was no longer registered, or no action was really registered. 04831 * Complain about it and leave. 04832 */ 04833 report_req_not_allowed(s, action); 04834 mansession_lock(s); 04835 astman_send_error(s, m, "Permission denied"); 04836 mansession_unlock(s); 04837 } 04838 ao2_t_ref(act_found, -1, "done with found action object"); 04839 } else { 04840 char buf[512]; 04841 04842 report_req_bad_format(s, action); 04843 snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action); 04844 mansession_lock(s); 04845 astman_send_error(s, m, buf); 04846 mansession_unlock(s); 04847 } 04848 if (ret) { 04849 return ret; 04850 } 04851 /* Once done with our message, deliver any pending events unless the 04852 requester doesn't want them as part of this response. 04853 */ 04854 if (ast_strlen_zero(astman_get_header(m, "SuppressEvents"))) { 04855 return process_events(s); 04856 } else { 04857 return ret; 04858 } 04859 }
static void purge_events | ( | void | ) | [static] |
Purge unused events. Remove elements from the head as long as their usecount is 0 and there is a next element.
Definition at line 1141 of file manager.c.
References ast_free, AST_RWLIST_FIRST, AST_RWLIST_NEXT, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_REMOVE_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_tvdiff_sec(), ast_tvnow(), eventqent::tv, and eventqent::usecount.
Referenced by purge_old_stuff().
01142 { 01143 struct eventqent *ev; 01144 struct timeval now = ast_tvnow(); 01145 01146 AST_RWLIST_WRLOCK(&all_events); 01147 while ( (ev = AST_RWLIST_FIRST(&all_events)) && 01148 ev->usecount == 0 && AST_RWLIST_NEXT(ev, eq_next)) { 01149 AST_RWLIST_REMOVE_HEAD(&all_events, eq_next); 01150 ast_free(ev); 01151 } 01152 01153 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&all_events, ev, eq_next) { 01154 /* Never release the last event */ 01155 if (!AST_RWLIST_NEXT(ev, eq_next)) { 01156 break; 01157 } 01158 01159 /* 2.5 times whatever the HTTP timeout is (maximum 2.5 hours) is the maximum time that we will definitely cache an event */ 01160 if (ev->usecount == 0 && ast_tvdiff_sec(now, ev->tv) > (httptimeout > 3600 ? 3600 : httptimeout) * 2.5) { 01161 AST_RWLIST_REMOVE_CURRENT(eq_next); 01162 ast_free(ev); 01163 } 01164 } 01165 AST_RWLIST_TRAVERSE_SAFE_END; 01166 AST_RWLIST_UNLOCK(&all_events); 01167 }
static void purge_sessions | ( | int | n_max | ) | [static] |
remove at most n_max stale session from the list.
Definition at line 5181 of file manager.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_unlock, ast_inet_ntoa(), ast_verb, mansession_session::authenticated, mansession_session::inuse, manager_displayconnects(), session_destroy(), sessions, mansession_session::sessiontimeout, mansession_session::sin, unref_mansession(), mansession_session::username, and VERBOSITY_ATLEAST.
Referenced by purge_old_stuff().
05182 { 05183 struct mansession_session *session; 05184 time_t now = time(NULL); 05185 struct ao2_iterator i; 05186 05187 if (!sessions) { 05188 return; 05189 } 05190 05191 i = ao2_iterator_init(sessions, 0); 05192 while ((session = ao2_iterator_next(&i)) && n_max > 0) { 05193 ao2_lock(session); 05194 if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) { 05195 if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) { 05196 ast_verb(2, "HTTP Manager '%s' timed out from %s\n", 05197 session->username, ast_inet_ntoa(session->sin.sin_addr)); 05198 } 05199 ao2_unlock(session); 05200 session_destroy(session); 05201 n_max--; 05202 } else { 05203 ao2_unlock(session); 05204 unref_mansession(session); 05205 } 05206 } 05207 ao2_iterator_destroy(&i); 05208 }
static void report_auth_success | ( | const struct mansession * | s | ) | [static] |
Definition at line 2272 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SUCCESSFUL_AUTH, AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, ast_security_event_successful_auth::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by authenticate().
02273 { 02274 struct sockaddr_in sin_local; 02275 char session_id[32]; 02276 struct ast_security_event_successful_auth successful_auth = { 02277 .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH, 02278 .common.version = AST_SECURITY_EVENT_SUCCESSFUL_AUTH_VERSION, 02279 .common.service = "AMI", 02280 .common.account_id = s->session->username, 02281 .common.session_tv = &s->session->sessionstart_tv, 02282 .common.local_addr = { 02283 .sin = mansession_encode_sin_local(s, &sin_local), 02284 .transport = mansession_get_transport(s), 02285 }, 02286 .common.remote_addr = { 02287 .sin = &s->session->sin, 02288 .transport = mansession_get_transport(s), 02289 }, 02290 .common.session_id = session_id, 02291 }; 02292 02293 snprintf(session_id, sizeof(session_id), "%p", s->session); 02294 02295 ast_security_event_report(AST_SEC_EVT(&successful_auth)); 02296 }
static void report_failed_acl | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2220 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_FAILED_ACL, AST_SECURITY_EVENT_FAILED_ACL_VERSION, ast_security_event_report(), ast_security_event_failed_acl::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02221 { 02222 struct sockaddr_in sin_local; 02223 char session_id[32]; 02224 struct ast_security_event_failed_acl failed_acl_event = { 02225 .common.event_type = AST_SECURITY_EVENT_FAILED_ACL, 02226 .common.version = AST_SECURITY_EVENT_FAILED_ACL_VERSION, 02227 .common.service = "AMI", 02228 .common.account_id = username, 02229 .common.session_tv = &s->session->sessionstart_tv, 02230 .common.local_addr = { 02231 .sin = mansession_encode_sin_local(s, &sin_local), 02232 .transport = mansession_get_transport(s), 02233 }, 02234 .common.remote_addr = { 02235 .sin = &s->session->sin, 02236 .transport = mansession_get_transport(s), 02237 }, 02238 .common.session_id = session_id, 02239 }; 02240 02241 snprintf(session_id, sizeof(session_id), "%p", s->session); 02242 02243 ast_security_event_report(AST_SEC_EVT(&failed_acl_event)); 02244 }
static void report_failed_challenge_response | ( | const struct mansession * | s, | |
const char * | response, | |||
const char * | expected_response | |||
) | [static] |
Definition at line 2358 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_CHAL_RESP_FAILED, AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, ast_security_event_report(), mansession_session::challenge, ast_security_event_chal_resp_failed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by authenticate().
02360 { 02361 struct sockaddr_in sin_local; 02362 char session_id[32]; 02363 struct ast_security_event_chal_resp_failed chal_resp_failed = { 02364 .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED, 02365 .common.version = AST_SECURITY_EVENT_CHAL_RESP_FAILED_VERSION, 02366 .common.service = "AMI", 02367 .common.account_id = s->session->username, 02368 .common.session_tv = &s->session->sessionstart_tv, 02369 .common.local_addr = { 02370 .sin = mansession_encode_sin_local(s, &sin_local), 02371 .transport = mansession_get_transport(s), 02372 }, 02373 .common.remote_addr = { 02374 .sin = &s->session->sin, 02375 .transport = mansession_get_transport(s), 02376 }, 02377 .common.session_id = session_id, 02378 02379 .challenge = s->session->challenge, 02380 .response = response, 02381 .expected_response = expected_response, 02382 }; 02383 02384 snprintf(session_id, sizeof(session_id), "%p", s->session); 02385 02386 ast_security_event_report(AST_SEC_EVT(&chal_resp_failed)); 02387 }
static void report_inval_password | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2246 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_PASSWORD, AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, ast_security_event_report(), ast_security_event_inval_password::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02247 { 02248 struct sockaddr_in sin_local; 02249 char session_id[32]; 02250 struct ast_security_event_inval_password inval_password = { 02251 .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD, 02252 .common.version = AST_SECURITY_EVENT_INVAL_PASSWORD_VERSION, 02253 .common.service = "AMI", 02254 .common.account_id = username, 02255 .common.session_tv = &s->session->sessionstart_tv, 02256 .common.local_addr = { 02257 .sin = mansession_encode_sin_local(s, &sin_local), 02258 .transport = mansession_get_transport(s), 02259 }, 02260 .common.remote_addr = { 02261 .sin = &s->session->sin, 02262 .transport = mansession_get_transport(s), 02263 }, 02264 .common.session_id = session_id, 02265 }; 02266 02267 snprintf(session_id, sizeof(session_id), "%p", s->session); 02268 02269 ast_security_event_report(AST_SEC_EVT(&inval_password)); 02270 }
static void report_invalid_user | ( | const struct mansession * | s, | |
const char * | username | |||
) | [static] |
Definition at line 2194 of file manager.c.
References AST_SEC_EVT, AST_SECURITY_EVENT_INVAL_ACCT_ID, AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, ast_security_event_report(), ast_security_event_inval_acct_id::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, and mansession_session::sin.
Referenced by authenticate().
02195 { 02196 struct sockaddr_in sin_local; 02197 char session_id[32]; 02198 struct ast_security_event_inval_acct_id inval_acct_id = { 02199 .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID, 02200 .common.version = AST_SECURITY_EVENT_INVAL_ACCT_ID_VERSION, 02201 .common.service = "AMI", 02202 .common.account_id = username, 02203 .common.session_tv = &s->session->sessionstart_tv, 02204 .common.local_addr = { 02205 .sin = mansession_encode_sin_local(s, &sin_local), 02206 .transport = mansession_get_transport(s), 02207 }, 02208 .common.remote_addr = { 02209 .sin = &s->session->sin, 02210 .transport = mansession_get_transport(s), 02211 }, 02212 .common.session_id = session_id, 02213 }; 02214 02215 snprintf(session_id, sizeof(session_id), "%p", s); 02216 02217 ast_security_event_report(AST_SEC_EVT(&inval_acct_id)); 02218 }
static void report_req_bad_format | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2328 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_BAD_FORMAT, AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, ast_security_event_req_bad_format::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02329 { 02330 struct sockaddr_in sin_local; 02331 char session_id[32]; 02332 char request_type[64]; 02333 struct ast_security_event_req_bad_format req_bad_format = { 02334 .common.event_type = AST_SECURITY_EVENT_REQ_BAD_FORMAT, 02335 .common.version = AST_SECURITY_EVENT_REQ_BAD_FORMAT_VERSION, 02336 .common.service = "AMI", 02337 .common.account_id = s->session->username, 02338 .common.session_tv = &s->session->sessionstart_tv, 02339 .common.local_addr = { 02340 .sin = mansession_encode_sin_local(s, &sin_local), 02341 .transport = mansession_get_transport(s), 02342 }, 02343 .common.remote_addr = { 02344 .sin = &s->session->sin, 02345 .transport = mansession_get_transport(s), 02346 }, 02347 .common.session_id = session_id, 02348 02349 .request_type = request_type, 02350 }; 02351 02352 snprintf(session_id, sizeof(session_id), "%p", s->session); 02353 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02354 02355 ast_security_event_report(AST_SEC_EVT(&req_bad_format)); 02356 }
static void report_req_not_allowed | ( | const struct mansession * | s, | |
const char * | action | |||
) | [static] |
Definition at line 2298 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_REQ_NOT_ALLOWED, AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, ast_security_event_req_not_allowed::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02299 { 02300 struct sockaddr_in sin_local; 02301 char session_id[32]; 02302 char request_type[64]; 02303 struct ast_security_event_req_not_allowed req_not_allowed = { 02304 .common.event_type = AST_SECURITY_EVENT_REQ_NOT_ALLOWED, 02305 .common.version = AST_SECURITY_EVENT_REQ_NOT_ALLOWED_VERSION, 02306 .common.service = "AMI", 02307 .common.account_id = s->session->username, 02308 .common.session_tv = &s->session->sessionstart_tv, 02309 .common.local_addr = { 02310 .sin = mansession_encode_sin_local(s, &sin_local), 02311 .transport = mansession_get_transport(s), 02312 }, 02313 .common.remote_addr = { 02314 .sin = &s->session->sin, 02315 .transport = mansession_get_transport(s), 02316 }, 02317 .common.session_id = session_id, 02318 02319 .request_type = request_type, 02320 }; 02321 02322 snprintf(session_id, sizeof(session_id), "%p", s->session); 02323 snprintf(request_type, sizeof(request_type), "Action: %s", action); 02324 02325 ast_security_event_report(AST_SEC_EVT(&req_not_allowed)); 02326 }
static void report_session_limit | ( | const struct mansession * | s | ) | [static] |
Definition at line 2389 of file manager.c.
References AST_SEC_EVT, ast_security_event_report(), AST_SECURITY_EVENT_SESSION_LIMIT, AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, ast_security_event_session_limit::common, ast_security_event_common::event_type, mansession_encode_sin_local(), mansession_get_transport(), mansession::session, mansession_session::sessionstart_tv, mansession_session::sin, and mansession_session::username.
Referenced by process_message().
02390 { 02391 struct sockaddr_in sin_local; 02392 char session_id[32]; 02393 struct ast_security_event_session_limit session_limit = { 02394 .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT, 02395 .common.version = AST_SECURITY_EVENT_SESSION_LIMIT_VERSION, 02396 .common.service = "AMI", 02397 .common.account_id = s->session->username, 02398 .common.session_tv = &s->session->sessionstart_tv, 02399 .common.local_addr = { 02400 .sin = mansession_encode_sin_local(s, &sin_local), 02401 .transport = mansession_get_transport(s), 02402 }, 02403 .common.remote_addr = { 02404 .sin = &s->session->sin, 02405 .transport = mansession_get_transport(s), 02406 }, 02407 .common.session_id = session_id, 02408 }; 02409 02410 snprintf(session_id, sizeof(session_id), "%p", s->session); 02411 02412 ast_security_event_report(AST_SEC_EVT(&session_limit)); 02413 }
static int send_string | ( | struct mansession * | s, | |
char * | string | |||
) | [static] |
helper function to send a string to the socket. Return -1 on error (e.g. buffer full).
Definition at line 2029 of file manager.c.
References ast_careful_fwrite(), EVENT_FLAG_HOOKRESPONSE, mansession_session::f, mansession::f, f, mansession_session::fd, mansession::fd, manager_custom_hook::helper, mansession::hook, mansession::session, mansession::write_error, and mansession_session::writetimeout.
Referenced by astman_append(), and process_events().
02030 { 02031 int res; 02032 FILE *f = s->f ? s->f : s->session->f; 02033 int fd = s->f ? s->fd : s->session->fd; 02034 02035 /* It's a result from one of the hook's action invocation */ 02036 if (s->hook) { 02037 /* 02038 * to send responses, we're using the same function 02039 * as for receiving events. We call the event "HookResponse" 02040 */ 02041 s->hook->helper(EVENT_FLAG_HOOKRESPONSE, "HookResponse", string); 02042 return 0; 02043 } 02044 02045 if ((res = ast_careful_fwrite(f, fd, string, strlen(string), s->session->writetimeout))) { 02046 s->write_error = 1; 02047 } 02048 02049 return res; 02050 }
static void session_destroy | ( | struct mansession_session * | s | ) | [static] |
Definition at line 1411 of file manager.c.
References ao2_unlink, sessions, and unref_mansession().
Referenced by auth_http_callback(), generic_http_callback(), purge_sessions(), and session_do().
01412 { 01413 ao2_unlink(sessions, s); 01414 unref_mansession(s); 01415 }
static void session_destructor | ( | void * | obj | ) | [static] |
Definition at line 1345 of file manager.c.
References ao2_t_ref, ast_atomic_fetchadd_int(), ast_datastore_free(), AST_LIST_REMOVE_HEAD, mansession_session::blackfilters, mansession_session::datastores, mansession_session::f, mansession_session::last_ev, eventqent::usecount, and mansession_session::whitefilters.
Referenced by build_mansession().
01346 { 01347 struct mansession_session *session = obj; 01348 struct eventqent *eqe = session->last_ev; 01349 struct ast_datastore *datastore; 01350 01351 /* Get rid of each of the data stores on the session */ 01352 while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) { 01353 /* Free the data store */ 01354 ast_datastore_free(datastore); 01355 } 01356 01357 if (session->f != NULL) { 01358 fflush(session->f); 01359 fclose(session->f); 01360 } 01361 if (eqe) { 01362 ast_atomic_fetchadd_int(&eqe->usecount, -1); 01363 } 01364 01365 if (session->whitefilters) { 01366 ao2_t_ref(session->whitefilters, -1, "decrement ref for white container, should be last one"); 01367 } 01368 01369 if (session->blackfilters) { 01370 ao2_t_ref(session->blackfilters, -1, "decrement ref for black container, should be last one"); 01371 } 01372 }
static void* session_do | ( | void * | data | ) | [static] |
The body of the individual manager session. Call get_input() to read one line at a time (or be woken up on new events), collect the lines in a message until found an empty line, and execute the request. In any case, deliver events asynchronously through process_events() (called from here if no line is available, or at the end of process_message(). ).
Definition at line 5073 of file manager.c.
References AMI_VERSION, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_inet_ntoa(), AST_LIST_HEAD_INIT_NOLOCK, ast_log(), ast_mutex_destroy, ast_mutex_init, ast_sockaddr_to_sin, ast_tcptls_stream_set_exclusive_input(), ast_tcptls_stream_set_timeout_disable(), ast_tcptls_stream_set_timeout_sequence(), ast_tvnow(), ast_verb, astman_append(), mansession_session::authenticated, mansession_session::authstart, build_mansession(), mansession_session::datastores, do_message(), errno, mansession::f, mansession_session::f, ast_tcptls_session_instance::f, mansession::fd, mansession_session::fd, ast_tcptls_session_instance::fd, ast_frame::flags, grab_last(), mansession_session::last_ev, mansession::lock, LOG_ERROR, LOG_WARNING, manager_displayconnects(), ast_tcptls_session_instance::remote_address, mansession::session, session_destroy(), mansession_session::sin, ast_tcptls_session_instance::stream_cookie, unauth_sessions, mansession_session::username, and mansession::write_error.
05074 { 05075 struct ast_tcptls_session_instance *ser = data; 05076 struct mansession_session *session; 05077 struct mansession s = { 05078 .tcptls_session = data, 05079 }; 05080 int flags; 05081 int res; 05082 struct sockaddr_in ser_remote_address_tmp; 05083 struct protoent *p; 05084 05085 if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) { 05086 fclose(ser->f); 05087 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05088 goto done; 05089 } 05090 05091 ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp); 05092 session = build_mansession(ser_remote_address_tmp); 05093 05094 if (session == NULL) { 05095 fclose(ser->f); 05096 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05097 goto done; 05098 } 05099 05100 /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm. 05101 * This is necessary to prevent delays (caused by buffering) as we 05102 * write to the socket in bits and pieces. */ 05103 p = getprotobyname("tcp"); 05104 if (p) { 05105 int arg = 1; 05106 if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 05107 ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\nSome manager actions may be slow to respond.\n", strerror(errno)); 05108 } 05109 } else { 05110 ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n"); 05111 } 05112 05113 /* make sure socket is non-blocking */ 05114 flags = fcntl(ser->fd, F_GETFL); 05115 flags |= O_NONBLOCK; 05116 fcntl(ser->fd, F_SETFL, flags); 05117 05118 ao2_lock(session); 05119 /* Hook to the tail of the event queue */ 05120 session->last_ev = grab_last(); 05121 05122 ast_mutex_init(&s.lock); 05123 05124 /* these fields duplicate those in the 'ser' structure */ 05125 session->fd = s.fd = ser->fd; 05126 session->f = s.f = ser->f; 05127 session->sin = ser_remote_address_tmp; 05128 s.session = session; 05129 05130 AST_LIST_HEAD_INIT_NOLOCK(&session->datastores); 05131 05132 if(time(&session->authstart) == -1) { 05133 ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno)); 05134 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05135 ao2_unlock(session); 05136 session_destroy(session); 05137 goto done; 05138 } 05139 ao2_unlock(session); 05140 05141 /* 05142 * We cannot let the stream exclusively wait for data to arrive. 05143 * We have to wake up the task to send async events. 05144 */ 05145 ast_tcptls_stream_set_exclusive_input(ser->stream_cookie, 0); 05146 05147 ast_tcptls_stream_set_timeout_sequence(ser->stream_cookie, 05148 ast_tvnow(), authtimeout * 1000); 05149 05150 astman_append(&s, "Asterisk Call Manager/%s\r\n", AMI_VERSION); /* welcome prompt */ 05151 for (;;) { 05152 if ((res = do_message(&s)) < 0 || s.write_error) { 05153 break; 05154 } 05155 if (session->authenticated) { 05156 ast_tcptls_stream_set_timeout_disable(ser->stream_cookie); 05157 } 05158 } 05159 /* session is over, explain why and terminate */ 05160 if (session->authenticated) { 05161 if (manager_displayconnects(session)) { 05162 ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr)); 05163 } 05164 } else { 05165 ast_atomic_fetchadd_int(&unauth_sessions, -1); 05166 if (displayconnects) { 05167 ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr)); 05168 } 05169 } 05170 05171 session_destroy(session); 05172 05173 ast_mutex_destroy(&s.lock); 05174 done: 05175 ao2_ref(ser, -1); 05176 ser = NULL; 05177 return NULL; 05178 }
static int set_eventmask | ( | struct mansession * | s, | |
const char * | eventmask | |||
) | [static] |
Rather than braindead on,off this now can also accept a specific int mask value or a ',' delim list of mask strings (the same as manager.conf) -anthm.
Definition at line 2166 of file manager.c.
References ao2_lock, ao2_unlock, mansession_session::send_events, mansession::session, and strings_to_mask().
Referenced by action_events(), and authenticate().
02167 { 02168 int maskint = strings_to_mask(eventmask); 02169 02170 ao2_lock(s->session); 02171 if (maskint >= 0) { 02172 s->session->send_events = maskint; 02173 } 02174 ao2_unlock(s->session); 02175 02176 return maskint; 02177 }
static int strings_to_mask | ( | const char * | string | ) | [static] |
A number returns itself, false returns 0, true returns all flags, other strings return the flags that are set.
Definition at line 1299 of file manager.c.
References ARRAY_LEN, ast_false(), ast_strlen_zero(), ast_true(), get_perm(), permalias::num, and perms.
Referenced by set_eventmask().
01300 { 01301 const char *p; 01302 01303 if (ast_strlen_zero(string)) { 01304 return -1; 01305 } 01306 01307 for (p = string; *p; p++) { 01308 if (*p < '0' || *p > '9') { 01309 break; 01310 } 01311 } 01312 if (!*p) { /* all digits */ 01313 return atoi(string); 01314 } 01315 if (ast_false(string)) { 01316 return 0; 01317 } 01318 if (ast_true(string)) { /* all permissions */ 01319 int x, ret = 0; 01320 for (x = 0; x < ARRAY_LEN(perms); x++) { 01321 ret |= perms[x].num; 01322 } 01323 return ret; 01324 } 01325 return get_perm(string); 01326 }
static struct mansession_session* unref_mansession | ( | struct mansession_session * | s | ) | [static, read] |
Unreference manager session object. If no more references, then go ahead and delete it.
Definition at line 1330 of file manager.c.
References ao2_ref, ast_log(), and LOG_DEBUG.
Referenced by __ast_manager_event_multichan(), astman_is_authed(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), check_manager_session_inuse(), find_session(), find_session_by_nonce(), handle_showmanconn(), purge_sessions(), and session_destroy().
01331 { 01332 int refcount = ao2_ref(s, -1); 01333 if (manager_debug) { 01334 ast_log(LOG_DEBUG, "Mansession: %p refcount now %d\n", s, refcount - 1); 01335 } 01336 return s; 01337 }
static const char* user_authority_to_str | ( | int | authority, | |
struct ast_str ** | res | |||
) | [static] |
Convert authority code to a list of options for a user. This will only display those authority codes that have an explicit match on authority.
Definition at line 1213 of file manager.c.
References ARRAY_LEN, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_strlen(), permalias::num, and perms.
Referenced by handle_showmanager().
01214 { 01215 int i; 01216 char *sep = ""; 01217 01218 ast_str_reset(*res); 01219 for (i = 0; i < ARRAY_LEN(perms) - 1; i++) { 01220 if ((authority & perms[i].num) == perms[i].num) { 01221 ast_str_append(res, 0, "%s%s", sep, perms[i].label); 01222 sep = ","; 01223 } 01224 } 01225 01226 if (ast_str_strlen(*res) == 0) /* replace empty string with something sensible */ 01227 ast_str_append(res, 0, "<none>"); 01228 01229 return ast_str_buffer(*res); 01230 }
static int whitefilter_cmp_fn | ( | void * | obj, | |
void * | arg, | |||
void * | data, | |||
int | flags | |||
) | [static] |
Definition at line 4365 of file manager.c.
References CMP_MATCH, and CMP_STOP.
Referenced by match_filter().
int allowmultiplelogin = 1 [static] |
struct ast_threadstorage astman_append_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_astman_append_buf , .custom_init = NULL , } [static] |
Definition at line 2059 of file manager.c.
Referenced by astman_append().
int authtimeout [static] |
int broken_events_action [static] |
struct { ... } command_blacklist[] [static] |
Referenced by check_blacklist().
const int DEFAULT_AUTHLIMIT = 50 [static] |
Default setting for authlimit
Definition at line 896 of file manager.c.
Referenced by reload_config().
const int DEFAULT_AUTHTIMEOUT = 30 [static] |
Default setting for authtimeout
Definition at line 895 of file manager.c.
Referenced by reload_config().
const int DEFAULT_BROKENEVENTSACTION = 0 [static] |
const int DEFAULT_DISPLAYCONNECTS = 1 [static] |
const int DEFAULT_ENABLED = 0 [static] |
const int DEFAULT_HTTPTIMEOUT = 60 [static] |
const int DEFAULT_MANAGERDEBUG = 0 [static] |
const int DEFAULT_TIMESTAMPEVENTS = 0 [static] |
const int DEFAULT_WEBENABLED = 0 [static] |
int displayconnects [static] |
char global_realm[MAXHOSTNAMELEN] [static] |
Default realm
Definition at line 912 of file manager.c.
Referenced by __init_manager(), auth_http_callback(), and manager_set_defaults().
int httptimeout [static] |
char* manager_channelvars [static] |
int manager_debug = 0 [static] |
int manager_enabled = 0 [static] |
struct ast_threadstorage manager_event_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_buf , .custom_init = NULL , } [static] |
Definition at line 5265 of file manager.c.
Referenced by __ast_manager_event_multichan().
struct ast_threadstorage manager_event_funcbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_manager_event_funcbuf , .custom_init = NULL , } [static] |
Definition at line 5238 of file manager.c.
Referenced by append_channel_vars().
helper functions to convert back and forth between string and numeric representation of set of flags
Referenced by action_events(), authority_to_str(), get_perm(), strings_to_mask(), and user_authority_to_str().
struct ao2_container* sessions = NULL [static] |
Definition at line 1023 of file manager.c.
Referenced by __ast_manager_event_multichan(), __init_manager(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), build_mansession(), check_manager_session_inuse(), find_session(), find_session_by_nonce(), handle_showmanconn(), purge_sessions(), and session_destroy().
int timestampevents [static] |
int unauth_sessions = 0 [static] |
Definition at line 914 of file manager.c.
Referenced by action_login(), and session_do().
struct ast_threadstorage userevent_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_userevent_buf , .custom_init = NULL , } [static] |
Definition at line 2060 of file manager.c.
Referenced by action_userevent().
int webmanager_enabled = 0 [static] |