/*! * \internal * \brief Create an identity header for an outgoing message * \param hdr_name The name of the header to create * \param tdata The message to place the header on * \param id The identification information for the new header * \return newly-created header */ static pjsip_fromto_hdr *create_new_id_hdr(const pj_str_t *hdr_name, pjsip_tx_data *tdata, const struct ast_party_id *id) { pjsip_fromto_hdr *id_hdr; pjsip_fromto_hdr *base; pjsip_name_addr *id_name_addr; pjsip_sip_uri *id_uri; base = tdata->msg->type == PJSIP_REQUEST_MSG ? PJSIP_MSG_FROM_HDR(tdata->msg) : PJSIP_MSG_TO_HDR(tdata->msg); id_hdr = pjsip_from_hdr_create(tdata->pool); id_hdr->type = PJSIP_H_OTHER; pj_strdup(tdata->pool, &id_hdr->name, hdr_name); id_hdr->sname.slen = 0; id_name_addr = pjsip_uri_clone(tdata->pool, base->uri); id_uri = pjsip_uri_get_uri(id_name_addr->uri); if (id->name.valid) { int name_buf_len = strlen(id->name.str) * 2 + 1; char *name_buf = ast_alloca(name_buf_len); ast_escape_quoted(id->name.str, name_buf, name_buf_len); pj_strdup2(tdata->pool, &id_name_addr->display, name_buf); } pj_strdup2(tdata->pool, &id_uri->user, id->number.str); id_hdr->uri = (pjsip_uri *) id_name_addr; return id_hdr; }
/*! * \brief Check authentication using Digest scheme * * This function will check an incoming message against configured authentication * options. If \b any of the incoming Authorization headers result in successful * authentication, then authentication is considered successful. * * \see ast_sip_check_authentication */ static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pjsip_tx_data *tdata) { struct ast_sip_auth **auths; enum digest_verify_result *verify_res; enum ast_sip_check_auth_result res; int i; int failures = 0; size_t auth_size; RAII_VAR(struct ast_sip_endpoint *, artificial_endpoint, ast_sip_get_artificial_endpoint(), ao2_cleanup); auth_size = AST_VECTOR_SIZE(&endpoint->inbound_auths); auths = ast_alloca(auth_size * sizeof(*auths)); verify_res = ast_alloca(auth_size * sizeof(*verify_res)); if (!auths) { return AST_SIP_AUTHENTICATION_ERROR; } if (endpoint == artificial_endpoint) { auths[0] = ast_sip_get_artificial_auth(); } else if (ast_sip_retrieve_auths(&endpoint->inbound_auths, auths)) { res = AST_SIP_AUTHENTICATION_ERROR; goto cleanup; } for (i = 0; i < auth_size; ++i) { if (ast_strlen_zero(auths[i]->realm)) { ast_string_field_set(auths[i], realm, "asterisk"); } verify_res[i] = verify(auths[i], rdata, tdata->pool); if (verify_res[i] == AUTH_SUCCESS) { res = AST_SIP_AUTHENTICATION_SUCCESS; goto cleanup; } if (verify_res[i] == AUTH_FAIL) { failures++; } } for (i = 0; i < auth_size; ++i) { challenge(auths[i]->realm, tdata, rdata, verify_res[i] == AUTH_STALE); } if (failures == auth_size) { res = AST_SIP_AUTHENTICATION_FAILED; } else { res = AST_SIP_AUTHENTICATION_CHALLENGE; } cleanup: ast_sip_cleanup_auths(auths, auth_size); return res; }
static char *find_aor_name(const char *username, const char *domain, const char *aors) { char *configured_aors; char *aors_buf; char *aor_name; char *id_domain; struct ast_sip_domain_alias *alias; id_domain = ast_alloca(strlen(username) + strlen(domain) + 2); sprintf(id_domain, "%s@%s", username, domain); aors_buf = ast_strdupa(aors); /* Look for exact match on username@domain */ configured_aors = aors_buf; while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) { if (match_aor(aor_name, id_domain)) { return ast_strdup(aor_name); } } /* If there's a domain alias, look for exact match on username@domain_alias */ alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain); if (alias) { char *id_domain_alias = ast_alloca(strlen(username) + strlen(alias->domain) + 2); sprintf(id_domain, "%s@%s", username, alias->domain); ao2_cleanup(alias); configured_aors = strcpy(aors_buf, aors);/* Safe */ while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) { if (match_aor(aor_name, id_domain_alias)) { return ast_strdup(aor_name); } } } if (ast_strlen_zero(username)) { /* No username, no match */ return NULL; } /* Look for exact match on username only */ configured_aors = strcpy(aors_buf, aors);/* Safe */ while ((aor_name = ast_strip(strsep(&configured_aors, ",")))) { if (match_aor(aor_name, username)) { return ast_strdup(aor_name); } } return NULL; }
static int set_outbound_authentication_credentials(pjsip_auth_clt_sess *auth_sess, const struct ast_sip_auth_vector *auth_vector, pjsip_rx_data *challenge) { size_t auth_size = AST_VECTOR_SIZE(auth_vector); struct ast_sip_auth **auths = ast_alloca(auth_size * sizeof(*auths)); pjsip_cred_info *auth_creds = ast_alloca(auth_size * sizeof(*auth_creds)); pjsip_www_authenticate_hdr *auth_hdr = NULL; int res = 0; int i; if (ast_sip_retrieve_auths(auth_vector, auths)) { res = -1; goto cleanup; } auth_hdr = get_auth_header(challenge); if (auth_hdr == NULL) { res = -1; ast_log(LOG_ERROR, "Unable to find authenticate header in challenge.\n"); goto cleanup; } for (i = 0; i < auth_size; ++i) { if (ast_strlen_zero(auths[i]->realm)) { auth_creds[i].realm = auth_hdr->challenge.common.realm; } else { pj_cstr(&auth_creds[i].realm, auths[i]->realm); } pj_cstr(&auth_creds[i].username, auths[i]->auth_user); pj_cstr(&auth_creds[i].scheme, "digest"); switch (auths[i]->type) { case AST_SIP_AUTH_TYPE_USER_PASS: pj_cstr(&auth_creds[i].data, auths[i]->auth_pass); auth_creds[i].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; break; case AST_SIP_AUTH_TYPE_MD5: pj_cstr(&auth_creds[i].data, auths[i]->md5_creds); auth_creds[i].data_type = PJSIP_CRED_DATA_DIGEST; break; case AST_SIP_AUTH_TYPE_ARTIFICIAL: ast_log(LOG_ERROR, "Trying to set artificial outbound auth credentials shouldn't happen.\n"); break; } } pjsip_auth_clt_set_credentials(auth_sess, auth_size, auth_creds); cleanup: ast_sip_cleanup_auths(auths, auth_size); return res; }
static char *complete_mailbox(const char *word, int state) { struct ao2_iterator iter; int wordlen = strlen(word); int which = 0; char *ret = NULL; char *regex; const struct ast_mwi_mailbox_object *mailbox; RAII_VAR(struct ao2_container *, mailboxes, NULL, ao2_cleanup); regex = ast_alloca(2 + wordlen); sprintf(regex, "^%s", word);/* Safe */ mailboxes = ast_mwi_mailbox_get_by_regex(regex); if (!mailboxes) { return NULL; } iter = ao2_iterator_init(mailboxes, 0); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { if (++which > state) { ret = ast_strdup(ast_sorcery_object_get_id(mailbox)); ast_mwi_mailbox_unref(mailbox); break; } } ao2_iterator_destroy(&iter); return ret; }
struct ast_named_lock *__ast_named_lock_get(const char *filename, int lineno, const char *func, enum ast_named_lock_type lock_type, const char *keyspace, const char *key) { struct ast_named_lock *lock = NULL; int concat_key_buff_len = strlen(keyspace) + strlen(key) + 2; char *concat_key = ast_alloca(concat_key_buff_len); sprintf(concat_key, "%s-%s", keyspace, key); /* Safe */ ao2_lock(named_locks); lock = ao2_find(named_locks, concat_key, OBJ_SEARCH_KEY | OBJ_NOLOCK); if (lock) { ao2_unlock(named_locks); ast_assert((ao2_options_get(lock) & AO2_ALLOC_OPT_LOCK_MASK) == lock_type); return lock; } lock = ao2_alloc_options(sizeof(*lock) + concat_key_buff_len, NULL, lock_type); if (lock) { strcpy(lock->key, concat_key); /* Safe */ ao2_link_flags(named_locks, lock, OBJ_NOLOCK); } ao2_unlock(named_locks); return lock; }
/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ static struct ast_channel *my_ast_get_channel_by_name_locked(const char *channame) { char *chkchan; struct pickup_by_name_args pickup_args; /* Check if channel name contains a '-'. * In this case the channel name will be interpreted as full channel name. */ if (strchr(channame, '-')) { /* check full channel name */ pickup_args.len = strlen(channame); pickup_args.name = channame; } else { /* need to append a '-' for the comparison so we check full channel name, * i.e SIP/hgc- , use a temporary variable so original stays the same for * debugging. */ pickup_args.len = strlen(channame) + 1; chkchan = ast_alloca(pickup_args.len + 1); strcpy(chkchan, channame); strcat(chkchan, "-"); pickup_args.name = chkchan; } return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0); }
/*! * \brief [lua_CFunction] Return a lua 'variable' object (for access from lua, don't call * directly) * * This function is called to lookup a variable construct a 'variable' object. * It would be called in the following example as would be seen in * extensions.lua. * * \code * channel.variable * \endcode */ static int lua_get_variable(lua_State *L) { struct ast_channel *chan; const char *name = luaL_checkstring(L, 2); char *value = NULL; char *workspace = ast_alloca(LUA_BUF_SIZE); workspace[0] = '\0'; lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_pushvalue(L, 2); lua_push_variable_table(L); /* if this is not a request for a dialplan funciton attempt to retrieve * the value of the variable */ if (!ast_strlen_zero(name) && name[strlen(name) - 1] != ')') { pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan)); } if (value) { lua_pushstring(L, value); lua_setfield(L, -2, "value"); } return 1; }
/*! * \internal * \brief Create an identity header for an outgoing message * \param hdr_name The name of the header to create * \param tdata The message to place the header on * \param id The identification information for the new header * \return newly-created header */ static pjsip_fromto_hdr *create_new_id_hdr(const pj_str_t *hdr_name, pjsip_fromto_hdr *base, pjsip_tx_data *tdata, const struct ast_party_id *id) { pjsip_fromto_hdr *id_hdr; pjsip_name_addr *id_name_addr; pjsip_sip_uri *id_uri; id_hdr = pjsip_from_hdr_create(tdata->pool); id_hdr->type = PJSIP_H_OTHER; pj_strdup(tdata->pool, &id_hdr->name, hdr_name); id_hdr->sname.slen = 0; id_name_addr = pjsip_uri_clone(tdata->pool, base->uri); id_uri = pjsip_uri_get_uri(id_name_addr->uri); if (id->name.valid) { int name_buf_len = strlen(id->name.str) * 2 + 1; char *name_buf = ast_alloca(name_buf_len); ast_escape_quoted(id->name.str, name_buf, name_buf_len); pj_strdup2(tdata->pool, &id_name_addr->display, name_buf); } else { /* * We need to clear the remnants of the clone or it'll be left set. * pj_strdup2 is safe to call with a NULL src and it resets both slen and ptr. */ pj_strdup2(tdata->pool, &id_name_addr->display, NULL); } pj_strdup2(tdata->pool, &id_uri->user, id->number.str); id_hdr->uri = (pjsip_uri *) id_name_addr; return id_hdr; }
static int on_aor_update_endpoint_state(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; struct ao2_container *endpoints; RAII_VAR(struct ast_variable *, var, NULL, ast_variables_destroy); const char *aor_name = ast_sorcery_object_get_id(aor); char *aor_like; if (ast_strlen_zero(aor_name)) { return -1; } if (aor->permanent_contacts && ((int)(aor->qualify_frequency * 1000)) <= 0) { aor_like = ast_alloca(strlen(aor_name) + 3); sprintf(aor_like, "%%%s%%", aor_name); var = ast_variable_new("aors LIKE", aor_like, ""); if (!var) { return -1; } endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint", AST_RETRIEVE_FLAG_MULTIPLE, var); if (endpoints) { /* * Because aors are a string list, we have to use a pattern match but since a simple * pattern match could return an endpoint that has an aor of "aaabccc" when searching * for "abc", we still have to iterate over them to find an exact aor match. */ ao2_callback(endpoints, 0, aor_update_endpoint_state, (char *)aor_name); ao2_ref(endpoints, -1); } } return 0; }
static int spy_sayname(struct ast_channel *chan, const char *mailbox, const char *context) { char *mailbox_id; mailbox_id = ast_alloca(strlen(mailbox) + strlen(context) + 2); sprintf(mailbox_id, "%s@%s", mailbox, context); /* Safe */ return ast_app_sayname(chan, mailbox_id); }
static HOOK_T ssl_write(void *cookie, const char *buf, LEN_T len) { #if 0 char *s = ast_alloca(len+1); strncpy(s, buf, len); s[len] = '\0'; ast_verb(0, "ssl write size %d <%s>\n", (int)len, s); #endif return SSL_write(cookie, buf, len); }
static int test_semi(char *string1, char *string2, int test_len) { char *test2 = NULL; if (test_len >= 0) { test2 = ast_alloca(test_len); *test2 = '\0'; } ast_escape_semicolons(string1, test2, test_len); if (test2 != NULL && strcmp(string2, test2) == 0) { return 1; } else { return 0; } }
/*! * \internal * \brief Implements PJSIP_HEADER 'read' by searching the for the requested header. * * Retrieve the header_datastore. * Search for the nth matching header. * Validate the pjsip_hdr found. * Parse pjsip_hdr into a name and value. * Return the value. */ static int read_header(void *obj) { struct header_data *data = obj; pjsip_hdr *hdr = NULL; char *pj_hdr_string; size_t pj_hdr_string_len; char *p; size_t plen; RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(data->channel->session, header_datastore.type), ao2_cleanup); if (!datastore || !datastore->data) { ast_debug(1, "There was no datastore from which to read headers.\n"); return -1; } hdr = find_header((struct hdr_list *) datastore->data, data->header_name, data->header_number); if (!hdr) { ast_debug(1, "There was no header named %s.\n", data->header_name); return -1; } pj_hdr_string = ast_alloca(data->len); pj_hdr_string_len = pjsip_hdr_print_on(hdr, pj_hdr_string, data->len); pj_hdr_string[pj_hdr_string_len] = '\0'; p = strchr(pj_hdr_string, ':'); if (!p) { ast_log(AST_LOG_ERROR, "A malformed header was returned from pjsip_hdr_print_on.\n"); return -1; } ++p; p = ast_strip(p); plen = strlen(p); if (plen + 1 > data->len) { ast_log(AST_LOG_ERROR, "Buffer isn't big enough to hold header value. %zu > %zu\n", plen + 1, data->len); return -1; } ast_copy_string(data->buf, p, data->len); return 0; }
static int sort_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen) { char *strings, *ptrkey, *ptrvalue; int count=1, count2, element_count=0; struct sortable_keys *sortable_keys; *buffer = '\0'; if (!data) return ERROR_NOARG; strings = ast_strdupa(data); for (ptrkey = strings; *ptrkey; ptrkey++) { if (*ptrkey == ',') count++; } sortable_keys = ast_alloca(count * sizeof(struct sortable_keys)); memset(sortable_keys, 0, count * sizeof(struct sortable_keys)); /* Parse each into a struct */ count2 = 0; while ((ptrkey = strsep(&strings, ","))) { ptrvalue = strchr(ptrkey, ':'); if (!ptrvalue) { count--; continue; } *ptrvalue++ = '\0'; sortable_keys[count2].key = ptrkey; sscanf(ptrvalue, "%30f", &sortable_keys[count2].value); count2++; } /* Sort the structs */ qsort(sortable_keys, count, sizeof(struct sortable_keys), sort_subroutine); for (count2 = 0; count2 < count; count2++) { int blen = strlen(buffer); if (element_count++) { strncat(buffer + blen, ",", buflen - blen - 1); blen++; } strncat(buffer + blen, sortable_keys[count2].key, buflen - blen - 1); } return 0; }
static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri *uri) { char *configured_aors, *aor_name; pjsip_sip_uri *sip_uri; char *domain_name; RAII_VAR(struct ast_str *, id, NULL, ast_free); if (ast_strlen_zero(endpoint->aors)) { return NULL; } sip_uri = pjsip_uri_get_uri(uri); domain_name = ast_alloca(sip_uri->host.slen + 1); ast_copy_pj_str(domain_name, &sip_uri->host, sip_uri->host.slen + 1); configured_aors = ast_strdupa(endpoint->aors); /* Iterate the configured AORs to see if the user or the user+domain match */ while ((aor_name = strsep(&configured_aors, ","))) { struct ast_sip_domain_alias *alias = NULL; if (!pj_strcmp2(&sip_uri->user, aor_name)) { break; } if (!id && !(id = ast_str_create(sip_uri->user.slen + sip_uri->host.slen + 2))) { return NULL; } ast_str_set(&id, 0, "%.*s@", (int)sip_uri->user.slen, sip_uri->user.ptr); if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) { ast_str_append(&id, 0, "%s", alias->domain); ao2_cleanup(alias); } else { ast_str_append(&id, 0, "%s", domain_name); } if (!strcmp(aor_name, ast_str_buffer(id))) { ast_free(id); break; } } if (ast_strlen_zero(aor_name)) { return NULL; } return ast_sip_location_retrieve_aor(aor_name); }
/*! * \brief [lua_CFunction] Used to get the value of a variable or dialplan * function (for access from lua, don't call directly) * * The value of the variable or function is returned. This function is the * 'get()' function in the following example as would be seen in * extensions.lua. * * \code * channel.variable:get() * \endcode */ static int lua_get_variable_value(lua_State *L) { struct ast_channel *chan; char *value = NULL, *name; char *workspace = ast_alloca(LUA_BUF_SIZE); int autoservice; workspace[0] = '\0'; if (!lua_istable(L, 1)) { lua_pushstring(L, "User probably used '.' instead of ':' for retrieving a channel variable value"); return lua_error(L); } lua_getfield(L, LUA_REGISTRYINDEX, "channel"); chan = lua_touserdata(L, -1); lua_pop(L, 1); lua_getfield(L, 1, "name"); name = ast_strdupa(lua_tostring(L, -1)); lua_pop(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, "autoservice"); autoservice = lua_toboolean(L, -1); lua_pop(L, 1); if (autoservice) ast_autoservice_stop(chan); /* if this is a dialplan function then use ast_func_read(), otherwise * use pbx_retrieve_variable() */ if (!ast_strlen_zero(name) && name[strlen(name) - 1] == ')') { value = ast_func_read(chan, name, workspace, LUA_BUF_SIZE) ? NULL : workspace; } else { pbx_retrieve_variable(chan, name, &value, workspace, LUA_BUF_SIZE, ast_channel_varshead(chan)); } if (autoservice) ast_autoservice_start(chan); if (value) { lua_pushstring(L, value); } else { lua_pushnil(L); } return 1; }
int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags) { struct ast_sip_cli_context *context = arg; struct ast_variable *i; int max_name_width = 13; int max_value_width = 14; int width; char *separator; struct ast_variable *objset; if (!context->output_buffer) { return -1; } objset = ast_sorcery_objectset_create(ast_sip_get_sorcery(),obj); if (!objset) { return -1; } for (i = objset; i; i = i->next) { if (i->name) { width = strlen(i->name); max_name_width = width > max_name_width ? width : max_name_width; } if (i->value) { width = strlen(i->value); max_value_width = width > max_value_width ? width : max_value_width; } } separator = ast_alloca(max_name_width + max_value_width + 8); memset(separator, '=', max_name_width + max_value_width + 3); separator[max_name_width + max_value_width + 3] = 0; ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, "ParameterName", "ParameterValue"); ast_str_append(&context->output_buffer, 0, " %s\n", separator); objset = ast_variable_list_sort(objset); for (i = objset; i; i = i->next) { ast_str_append(&context->output_buffer, 0, " %-*s : %s\n", max_name_width, i->name, i->value); } ast_variables_destroy(objset); return 0; }
static int db_open(void) { char *dbname; struct stat dont_care; if (!(dbname = ast_alloca(strlen(ast_config_AST_DB) + sizeof(".sqlite3")))) { return -1; } strcpy(dbname, ast_config_AST_DB); strcat(dbname, ".sqlite3"); if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) { if (convert_bdb_to_sqlite3()) { ast_log(LOG_ERROR, "*** Database conversion failed!\n"); ast_log(LOG_ERROR, "*** Asterisk now uses SQLite3 for its internal\n"); ast_log(LOG_ERROR, "*** database. Conversion from the old astdb\n"); ast_log(LOG_ERROR, "*** failed. Most likely the astdb2sqlite3 utility\n"); ast_log(LOG_ERROR, "*** was not selected for build. To convert the\n"); ast_log(LOG_ERROR, "*** old astdb, please delete '%s'\n", dbname); ast_log(LOG_ERROR, "*** and re-run 'make menuselect' and select astdb2sqlite3\n"); ast_log(LOG_ERROR, "*** in the Utilities section, then 'make && make install'.\n"); ast_log(LOG_ERROR, "*** It is also imperative that the user under which\n"); ast_log(LOG_ERROR, "*** Asterisk runs have write permission to the directory\n"); ast_log(LOG_ERROR, "*** where the database resides.\n"); sleep(5); } else { ast_log(LOG_NOTICE, "Database conversion succeeded!\n"); } } ast_mutex_lock(&dblock); if (sqlite3_open(dbname, &astdb) != SQLITE_OK) { ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb)); sqlite3_close(astdb); ast_mutex_unlock(&dblock); return -1; } ast_mutex_unlock(&dblock); return 0; }
/*! * \internal * \brief Set name and number information on an identity header. * \param pool Memory pool to use for string duplication * \param id_hdr A From, P-Asserted-Identity, or Remote-Party-ID header to modify * \param id The identity information to apply to the header */ static void modify_id_header(pj_pool_t *pool, pjsip_fromto_hdr *id_hdr, const struct ast_party_id *id) { pjsip_name_addr *id_name_addr; pjsip_sip_uri *id_uri; id_name_addr = (pjsip_name_addr *) id_hdr->uri; id_uri = pjsip_uri_get_uri(id_name_addr->uri); if (id->name.valid) { int name_buf_len = strlen(id->name.str) * 2 + 1; char *name_buf = ast_alloca(name_buf_len); ast_escape_quoted(id->name.str, name_buf, name_buf_len); pj_strdup2(pool, &id_name_addr->display, name_buf); } if (id->number.valid) { pj_strdup2(pool, &id_uri->user, id->number.str); } }
static void set_cause_code(struct respoke_session *session, enum respoke_status status) { struct ast_control_pvt_cause_code *cause_code; int size; const char *cause = respoke_status_to_str(status); /* size of the cause = sizeof + "RESPOKE " + cause */ size = sizeof(*cause_code) + 9 + strlen(cause); cause_code = ast_alloca(size); memset(cause_code, 0, size); ast_copy_string(cause_code->chan_name, ast_channel_name(session->channel), AST_CHANNEL_NAME); snprintf(cause_code->code, size - sizeof(*cause_code) + 1, "RESPOKE %s", cause); cause_code->ast_cause = hangup_reason_to_cause(status); ast_queue_control_data(session->channel, AST_CONTROL_PVT_CAUSE_CODE, cause_code, size); ast_channel_hangupcause_hash_set(session->channel, cause_code, size); }
/*! \brief Write function for websocket traffic */ int AST_OPTIONAL_API_NAME(ast_websocket_write)(struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length) { size_t header_size = 2; /* The minimum size of a websocket frame is 2 bytes */ char *frame; uint64_t length = 0; if (actual_length < 126) { length = actual_length; } else if (actual_length < (1 << 16)) { length = 126; /* We need an additional 2 bytes to store the extended length */ header_size += 2; } else { length = 127; /* We need an additional 8 bytes to store the really really extended length */ header_size += 8; } frame = ast_alloca(header_size); memset(frame, 0, sizeof(*frame)); frame[0] = opcode | 0x80; frame[1] = length; /* Use the additional available bytes to store the length */ if (length == 126) { put_unaligned_uint16(&frame[2], htons(actual_length)); } else if (length == 127) { put_unaligned_uint64(&frame[2], htonl(actual_length)); } if (fwrite(frame, 1, header_size, session->f) != header_size) { return -1; } if (fwrite(payload, 1, actual_length, session->f) != actual_length) { return -1; } return 0; }
/*! * \internal \brief The cURL header callback function */ static size_t curl_header_callback(char *buffer, size_t size, size_t nitems, void *data) { struct curl_bucket_file_data *cb_data = data; size_t realsize; char *value; char *header; realsize = size * nitems; if (realsize > MAX_HEADER_LENGTH) { ast_log(LOG_WARNING, "cURL header length of '%zu' is too large: max %d\n", realsize, MAX_HEADER_LENGTH); return 0; } /* buffer may not be NULL terminated */ header = ast_alloca(realsize + 1); memcpy(header, buffer, realsize); header[realsize] = '\0'; value = strchr(header, ':'); if (!value) { /* Not a header we care about; bail */ return realsize; } *value++ = '\0'; if (strcasecmp(header, "ETag") && strcasecmp(header, "Cache-Control") && strcasecmp(header, "Last-Modified") && strcasecmp(header, "Content-Type") && strcasecmp(header, "Expires")) { return realsize; } value = ast_trim_blanks(ast_skip_blanks(value)); header = ast_str_to_lower(header); ast_bucket_file_metadata_set(cb_data->bucket_file, header, value); return realsize; }
/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ static struct ast_channel *find_by_channel(struct ast_channel *chan, const char *channame) { struct ast_channel *target; char *chkchan; struct pickup_by_name_args pickup_args; pickup_args.chan = chan; if (strchr(channame, '-')) { /* * Use the given channel name string as-is. This allows a full channel * name with a typical sequence number to be used as well as still * allowing the odd partial channel name that has a '-' in it to still * work, i.e. Local/bob@en-phone. */ pickup_args.len = strlen(channame); pickup_args.name = channame; } else { /* * Append a '-' for the comparison so we check the channel name less * a sequence number, i.e Find SIP/bob- and not SIP/bobby. */ pickup_args.len = strlen(channame) + 1; chkchan = ast_alloca(pickup_args.len + 1); strcpy(chkchan, channame);/* Safe */ strcat(chkchan, "-"); pickup_args.name = chkchan; } target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0); if (target) { return target; } /* Now try a search for uniqueid. */ pickup_args.name = channame; pickup_args.len = 0; return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0); }
/*! * \internal * \brief Find an endpoint associated with the given contact. */ static struct ast_sip_endpoint *find_an_endpoint(struct ast_sip_contact *contact) { struct ao2_container *endpoints; struct ast_sip_endpoint *endpoint; struct ast_variable *var; char *aor = ast_alloca(strlen(contact->aor) + 3); sprintf(aor, "%%%s%%", contact->aor); var = ast_variable_new("aors LIKE", aor, ""); endpoints = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "endpoint", AST_RETRIEVE_FLAG_MULTIPLE, var); ast_variables_destroy(var); /* * Because aors are a string list, we have to use a pattern match but since a simple * pattern match could return an endpoint that has an aor of "aaabccc" when searching * for "abc", we still have to iterate over them to find an exact aor match. */ endpoint = ao2_callback(endpoints, 0, on_endpoint, (char *)contact->aor); ao2_ref(endpoints, -1); return endpoint; }
static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint) { struct ast_sip_aor *aor = NULL; char *aor_name = NULL; char *domain_name; char *username = NULL; int i; for (i = 0; i < AST_VECTOR_SIZE(&endpoint->ident_method_order); ++i) { pjsip_sip_uri *uri; pjsip_authorization_hdr *header = NULL; switch (AST_VECTOR_GET(&endpoint->ident_method_order, i)) { case AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME: uri = pjsip_uri_get_uri(rdata->msg_info.to->uri); domain_name = ast_alloca(uri->host.slen + 1); ast_copy_pj_str(domain_name, &uri->host, uri->host.slen + 1); username = ast_alloca(uri->user.slen + 1); ast_copy_pj_str(username, &uri->user, uri->user.slen + 1); /* * We may want to match without any user options getting * in the way. */ AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username); aor_name = find_aor_name(username, domain_name, endpoint->aors); if (aor_name) { ast_debug(3, "Matched aor '%s' by To username\n", aor_name); } break; case AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME: while ((header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, header ? header->next : NULL))) { if (header && !pj_stricmp2(&header->scheme, "digest")) { username = ast_alloca(header->credential.digest.username.slen + 1); ast_copy_pj_str(username, &header->credential.digest.username, header->credential.digest.username.slen + 1); domain_name = ast_alloca(header->credential.digest.realm.slen + 1); ast_copy_pj_str(domain_name, &header->credential.digest.realm, header->credential.digest.realm.slen + 1); aor_name = find_aor_name(username, domain_name, endpoint->aors); if (aor_name) { ast_debug(3, "Matched aor '%s' by Authentication username\n", aor_name); break; } } } break; default: continue; } if (aor_name) { break; } } if (ast_strlen_zero(aor_name) || !(aor = ast_sip_location_retrieve_aor(aor_name))) { /* The provided AOR name was not found (be it within the configuration or sorcery itself) */ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 404, NULL, NULL, NULL); ast_sip_report_req_no_support(endpoint, rdata, "registrar_requested_aor_not_found"); ast_log(LOG_WARNING, "AOR '%s' not found for endpoint '%s'\n", username ?: "", ast_sorcery_object_get_id(endpoint)); }
static int record_file(struct stasis_app_control *control, struct ast_channel *chan, void *data) { struct stasis_app_recording *recording = data; char *acceptdtmf; int res; ast_assert(recording != NULL); if (stasis_app_get_bridge(control)) { ast_log(LOG_ERROR, "Cannot record channel while in bridge\n"); recording_fail(control, recording, "Cannot record channel while in bridge"); return -1; } switch (recording->options->terminate_on) { case STASIS_APP_RECORDING_TERMINATE_NONE: case STASIS_APP_RECORDING_TERMINATE_INVALID: acceptdtmf = ""; break; case STASIS_APP_RECORDING_TERMINATE_ANY: acceptdtmf = "#*0123456789abcd"; break; default: acceptdtmf = ast_alloca(2); acceptdtmf[0] = recording->options->terminate_on; acceptdtmf[1] = '\0'; } res = ast_auto_answer(chan); if (res != 0) { ast_debug(3, "%s: Failed to answer\n", ast_channel_uniqueid(chan)); recording_fail(control, recording, "Failed to answer channel"); return -1; } recording_set_state( recording, STASIS_APP_RECORDING_STATE_RECORDING, NULL); ast_play_and_record_full(chan, NULL, /* playfile */ recording->absolute_name, recording->options->max_duration_seconds, recording->options->format, &recording->duration.total, recording->options->max_silence_seconds ? &recording->duration.energy_only : NULL, recording->options->beep, -1, /* silencethreshold */ recording->options->max_silence_seconds * 1000, NULL, /* path */ acceptdtmf, NULL, /* canceldtmf */ 1, /* skip_confirmation_sound */ recording->options->if_exists); ast_debug(3, "%s: Recording complete\n", ast_channel_uniqueid(chan)); recording_set_state( recording, STASIS_APP_RECORDING_STATE_COMPLETE, NULL); stasis_app_control_unregister_add_rule(control, &rule_recording); return 0; }
int callerid_feed(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec) { int mylen = len; int olen; int b = 'X'; int res; int x; short *buf; buf = ast_alloca(2 * len + cid->oldlen); memcpy(buf, cid->oldstuff, cid->oldlen); mylen += cid->oldlen/2; for (x = 0; x < len; x++) buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]); while (mylen >= 160) { olen = mylen; res = fsk_serial(&cid->fskd, buf, &mylen, &b); if (mylen < 0) { ast_log(LOG_ERROR, "No start bit found in fsk data.\n"); return -1; } buf += (olen - mylen); if (res < 0) { ast_log(LOG_NOTICE, "fsk_serial failed\n"); return -1; } if (res == 1) { if (b > 0xff) { if (cid->sawflag != 5) { /* Ignore invalid bytes */ continue; } /* * We can tollerate an error on the checksum character since the * checksum character is the last character in the message and * it validates the message. * * Remove character error flags. * Bit 8 : Parity error * Bit 9 : Framing error */ b &= 0xff; } switch (cid->sawflag) { case 0: /* Look for flag */ if (b == 'U') cid->sawflag = 2; break; case 2: /* Get lead-in */ if ((b == 0x04) || (b == 0x80) || (b == 0x06) || (b == 0x82)) { cid->type = b; cid->sawflag = 3; cid->cksum = b; } break; case 3: /* Get length */ /* Not a lead in. We're ready */ cid->sawflag = 4; cid->len = b; cid->pos = 0; cid->cksum += b; break; case 4: /* Retrieve message */ if (cid->pos >= 128) { ast_log(LOG_WARNING, "Caller ID too long???\n"); return -1; } cid->rawdata[cid->pos++] = b; cid->len--; cid->cksum += b; if (!cid->len) { cid->rawdata[cid->pos] = '\0'; cid->sawflag = 5; } break; case 5: /* Check checksum */ if ((b + cid->cksum) & 0xff) { ast_log(LOG_NOTICE, "Caller*ID failed checksum\n"); /* Try again */ cid->sawflag = 0; break; } cid->number[0] = '\0'; cid->name[0] = '\0'; /* Update flags */ cid->flags = 0; /* If we get this far we're fine. */ if ((cid->type == 0x80) || (cid->type == 0x82)) { /* MDMF */ /* Go through each element and process */ for (x = 0; x < cid->pos;) { switch (cid->rawdata[x++]) { case 1: /* Date */ break; case 2: /* Number */ case 3: /* Number (for Zebble) */ case 4: /* Number */ res = cid->rawdata[x]; if (res > 32) { ast_log(LOG_NOTICE, "Truncating long caller ID number from %d bytes to 32\n", cid->rawdata[x]); res = 32; } if (ast_strlen_zero(cid->number)) { memcpy(cid->number, cid->rawdata + x + 1, res); /* Null terminate */ cid->number[res] = '\0'; } break; case 6: /* Stentor Call Qualifier (ie. Long Distance call) */ break; case 7: /* Name */ case 8: /* Name */ res = cid->rawdata[x]; if (res > 32) { ast_log(LOG_NOTICE, "Truncating long caller ID name from %d bytes to 32\n", cid->rawdata[x]); res = 32; } memcpy(cid->name, cid->rawdata + x + 1, res); cid->name[res] = '\0'; break; case 11: /* Message Waiting */ res = cid->rawdata[x + 1]; if (res) cid->flags |= CID_MSGWAITING; else cid->flags |= CID_NOMSGWAITING; break; case 17: /* UK: Call type, 1=Voice Call, 2=Ringback when free, 129=Message waiting */ case 19: /* UK: Network message system status (Number of messages waiting) */ case 22: /* Something French */ break; default: ast_log(LOG_NOTICE, "Unknown IE %d\n", cid->rawdata[x - 1]); } res = cid->rawdata[x]; if (0 > res){ /* Negative offset in the CID Spill */ ast_log(LOG_NOTICE, "IE %d has bad field length of %d at offset %d\n", cid->rawdata[x-1], cid->rawdata[x], x); /* Try again */ cid->sawflag = 0; break; /* Exit the loop */ } x += cid->rawdata[x]; x++; } } else if (cid->type == 0x6) { /* VMWI SDMF */ if (cid->rawdata[2] == 0x42) { cid->flags |= CID_MSGWAITING; } else if (cid->rawdata[2] == 0x6f) { cid->flags |= CID_NOMSGWAITING; } } else { /* SDMF */ ast_copy_string(cid->number, cid->rawdata + 8, sizeof(cid->number)); } if (!strcmp(cid->number, "P")) { strcpy(cid->number, ""); cid->flags |= CID_PRIVATE_NUMBER; } else if (!strcmp(cid->number, "O") || ast_strlen_zero(cid->number)) { strcpy(cid->number, ""); cid->flags |= CID_UNKNOWN_NUMBER; } if (!strcmp(cid->name, "P")) { strcpy(cid->name, ""); cid->flags |= CID_PRIVATE_NAME; } else if (!strcmp(cid->name, "O") || ast_strlen_zero(cid->name)) { strcpy(cid->name, ""); cid->flags |= CID_UNKNOWN_NAME; } return 1; break; default: ast_log(LOG_ERROR, "Dunno what to do with a digit in sawflag %d\n", cid->sawflag); } } } if (mylen) { memcpy(cid->oldstuff, buf, mylen * 2); cid->oldlen = mylen * 2; } else cid->oldlen = 0; return 0; }
int callerid_feed_jp(struct callerid_state *cid, unsigned char *ubuf, int len, format_t codec) { int mylen = len; int olen; int b = 'X'; int b2; int res; int x; short *buf; buf = ast_alloca(2 * len + cid->oldlen); memcpy(buf, cid->oldstuff, cid->oldlen); mylen += cid->oldlen / 2; for (x = 0; x < len; x++) buf[x+cid->oldlen/2] = AST_XLAW(ubuf[x]); while (mylen >= 160) { b = b2 = 0; olen = mylen; res = fsk_serial(&cid->fskd, buf, &mylen, &b); if (mylen < 0) { ast_log(LOG_ERROR, "No start bit found in fsk data.\n"); return -1; } buf += (olen - mylen); if (res < 0) { ast_log(LOG_NOTICE, "fsk_serial failed\n"); return -1; } if (res == 1) { b2 = b; b &= 0x7f; /* crc checksum calculation */ if (cid->sawflag > 1) cid->crc = calc_crc(cid->crc, (unsigned char) b2); /* Ignore invalid bytes */ if (b > 0xff) continue; /* skip DLE if needed */ if (cid->sawflag > 0) { if (cid->sawflag != 5 && cid->skipflag == 0 && b == 0x10) { cid->skipflag = 1 ; continue ; } } if (cid->skipflag == 1) cid->skipflag = 0 ; /* caller id retrieval */ switch (cid->sawflag) { case 0: /* DLE */ if (b == 0x10) { cid->sawflag = 1; cid->skipflag = 0; cid->crc = 0; } break; case 1: /* SOH */ if (b == 0x01) cid->sawflag = 2; break ; case 2: /* HEADER */ if (b == 0x07) cid->sawflag = 3; break; case 3: /* STX */ if (b == 0x02) cid->sawflag = 4; break; case 4: /* SERVICE TYPE */ if (b == 0x40) cid->sawflag = 5; break; case 5: /* Frame Length */ cid->sawflag = 6; break; case 6: /* NUMBER TYPE */ cid->sawflag = 7; cid->pos = 0; cid->rawdata[cid->pos++] = b; break; case 7: /* NUMBER LENGTH */ cid->sawflag = 8; cid->len = b; if ((cid->len+2) >= sizeof(cid->rawdata)) { ast_log(LOG_WARNING, "too long caller id string\n") ; return -1; } cid->rawdata[cid->pos++] = b; break; case 8: /* Retrieve message */ cid->rawdata[cid->pos++] = b; cid->len--; if (cid->len<=0) { cid->rawdata[cid->pos] = '\0'; cid->sawflag = 9; } break; case 9: /* ETX */ cid->sawflag = 10; break; case 10: /* CRC Checksum 1 */ cid->sawflag = 11; break; case 11: /* CRC Checksum 2 */ cid->sawflag = 12; if (cid->crc != 0) { ast_log(LOG_WARNING, "crc checksum error\n") ; return -1; } /* extract caller id data */ for (x = 0; x < cid->pos;) { switch (cid->rawdata[x++]) { case 0x02: /* caller id number */ cid->number[0] = '\0'; cid->name[0] = '\0'; cid->flags = 0; res = cid->rawdata[x++]; ast_copy_string(cid->number, &cid->rawdata[x], res+1); x += res; break; case 0x21: /* additional information */ /* length */ x++; /* number type */ switch (cid->rawdata[x]) { case 0x00: /* unknown */ case 0x01: /* international number */ case 0x02: /* domestic number */ case 0x03: /* network */ case 0x04: /* local call */ case 0x06: /* short dial number */ case 0x07: /* reserved */ default: /* reserved */ ast_debug(2, "cid info:#1=%X\n", (unsigned)cid->rawdata[x]); break ; } x++; /* numbering plan octed 4 */ x++; /* numbering plan octed 5 */ switch (cid->rawdata[x]) { case 0x00: /* unknown */ case 0x01: /* recommendation E.164 ISDN */ case 0x03: /* recommendation X.121 */ case 0x04: /* telex dial plan */ case 0x08: /* domestic dial plan */ case 0x09: /* private dial plan */ case 0x05: /* reserved */ default: /* reserved */ ast_debug(2, "cid info:#2=%X\n", (unsigned)cid->rawdata[x]); break ; } x++; break ; case 0x04: /* no callerid reason */ /* length */ x++; /* no callerid reason code */ switch (cid->rawdata[x]) { case 'P': /* caller id denied by user */ case 'O': /* service not available */ case 'C': /* pay phone */ case 'S': /* service congested */ cid->flags |= CID_UNKNOWN_NUMBER; ast_debug(2, "no cid reason:%c\n", cid->rawdata[x]); break ; } x++; break ; case 0x09: /* dialed number */ /* length */ res = cid->rawdata[x++]; /* dialed number */ x += res; break ; case 0x22: /* dialed number additional information */ /* length */ x++; /* number type */ switch (cid->rawdata[x]) { case 0x00: /* unknown */ case 0x01: /* international number */ case 0x02: /* domestic number */ case 0x03: /* network */ case 0x04: /* local call */ case 0x06: /* short dial number */ case 0x07: /* reserved */ default: /* reserved */ if (option_debug > 1) ast_log(LOG_NOTICE, "did info:#1=%X\n", (unsigned)cid->rawdata[x]); break ; } x++; /* numbering plan octed 4 */ x++; /* numbering plan octed 5 */ switch (cid->rawdata[x]) { case 0x00: /* unknown */ case 0x01: /* recommendation E.164 ISDN */ case 0x03: /* recommendation X.121 */ case 0x04: /* telex dial plan */ case 0x08: /* domestic dial plan */ case 0x09: /* private dial plan */ case 0x05: /* reserved */ default: /* reserved */ ast_debug(2, "did info:#2=%X\n", (unsigned)cid->rawdata[x]); break ; } x++; break ; } } return 1; break; default: ast_log(LOG_ERROR, "invalid value in sawflag %d\n", cid->sawflag); } } } if (mylen) { memcpy(cid->oldstuff, buf, mylen * 2); cid->oldlen = mylen * 2; } else cid->oldlen = 0; return 0; }
static int cpeid_exec(struct ast_channel *chan, const char *idata) { int res=0; unsigned char cpeid[4]; int gotgeometry = 0; int gotcpeid = 0; int width, height, buttons; char *data[4]; unsigned int x; for (x = 0; x < 4; x++) data[x] = ast_alloca(80); strcpy(data[0], "** CPE Info **"); strcpy(data[1], "Identifying CPE..."); strcpy(data[2], "Please wait..."); res = ast_adsi_load_session(chan, NULL, 0, 1); if (res > 0) { cpeid_setstatus(chan, data, 0); res = ast_adsi_get_cpeid(chan, cpeid, 0); if (res > 0) { gotcpeid = 1; ast_verb(3, "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", (unsigned)cpeid[0], (unsigned)cpeid[1], (unsigned)cpeid[2], (unsigned)cpeid[3], ast_channel_name(chan)); } if (res > -1) { strcpy(data[1], "Measuring CPE..."); strcpy(data[2], "Please wait..."); cpeid_setstatus(chan, data, 0); res = ast_adsi_get_cpeinfo(chan, &width, &height, &buttons, 0); if (res > -1) { ast_verb(3, "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, ast_channel_name(chan)); gotgeometry = 1; } } if (res > -1) { if (gotcpeid) snprintf(data[1], 80, "CPEID: %02x:%02x:%02x:%02x", (unsigned)cpeid[0], (unsigned)cpeid[1], (unsigned)cpeid[2], (unsigned)cpeid[3]); else strcpy(data[1], "CPEID Unknown"); if (gotgeometry) snprintf(data[2], 80, "Geom: %dx%d, %d buttons", width, height, buttons); else strcpy(data[2], "Geometry unknown"); strcpy(data[3], "Press # to exit"); cpeid_setstatus(chan, data, 1); for(;;) { res = ast_waitfordigit(chan, 1000); if (res < 0) break; if (res == '#') { res = 0; break; } } ast_adsi_unload_session(chan); } } return res; }