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; }
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg) { char *copy; char *name; int res; if (!on_aor || ast_strlen_zero(aors)) { return 0; } copy = ast_strdupa(aors); while ((name = ast_strip(strsep(©, ",")))) { struct ast_sip_aor *aor; aor = ast_sip_location_retrieve_aor(name); if (aor) { res = on_aor(aor, arg, 0); ao2_ref(aor, -1); if (res) { return -1; } } } return 0; }
/*! \brief Custom handler for TLS cipher setting */ static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { struct ast_sip_transport *transport = obj; char *parse; char *name; int res = 0; RAII_VAR(struct ast_sip_transport_state *, state, find_or_create_temporary_state(transport), ao2_cleanup); if (!state) { return -1; } parse = ast_strdupa(S_OR(var->value, "")); while ((name = ast_strip(strsep(&parse, ",")))) { if (ast_strlen_zero(name)) { continue; } if (ARRAY_LEN(state->ciphers) <= state->tls.ciphers_num) { ast_log(LOG_ERROR, "Too many ciphers specified\n"); res = -1; break; } res |= transport_cipher_add(state, name); } return res ? -1 : 0; }
static void parse_apps(const char *val) { char *apps = ast_strdupa(val); char *cur_app; if (!ast_cel_track_event(AST_CEL_APP_START) && !ast_cel_track_event(AST_CEL_APP_END)) { ast_log(LOG_WARNING, "An apps= config line, but not tracking APP events\n"); return; } while ((cur_app = strsep(&apps, ","))) { char *app; cur_app = ast_strip(cur_app); if (ast_strlen_zero(cur_app)) { continue; } if (!(app = ao2_alloc(strlen(cur_app) + 1, NULL))) { continue; } strcpy(app, cur_app); ao2_link(appset, app); ao2_ref(app, -1); app = NULL; } }
static void parse_events(const char *val) { char *events = ast_strdupa(val); char *cur_event; while ((cur_event = strsep(&events, ","))) { enum ast_cel_event_type event_type; cur_event = ast_strip(cur_event); if (ast_strlen_zero(cur_event)) { continue; } event_type = ast_cel_str_to_event_type(cur_event); if (event_type == 0) { /* All events */ eventset = (int64_t) -1; } else if (event_type == -1) { ast_log(LOG_WARNING, "Unknown event name '%s'\n", cur_event); } else { eventset |= ((int64_t) 1 << event_type); } } }
/*! * \internal * \brief Send a NOTIFY request to the endpoint. * * \detail Iterates over an endpoint's AORs sending a NOTIFY request * with the appropriate payload information to each contact. */ static int notify_endpoint(void *obj) { RAII_VAR(struct notify_data *, data, obj, ao2_cleanup); char *aor_name, *aors; if (ast_strlen_zero(data->endpoint->aors)) { ast_log(LOG_WARNING, "Unable to NOTIFY - " "endpoint has no configured AORs\n"); return -1; } aors = ast_strdupa(data->endpoint->aors); while ((aor_name = ast_strip(strsep(&aors, ",")))) { RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(aor_name), ao2_cleanup); RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup); if (!aor || !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) { continue; } ao2_callback(contacts, OBJ_NODATA, notify_contact, data); } return 0; }
void ast_sip_location_retrieve_contact_and_aor_from_list(const char *aor_list, struct ast_sip_aor **aor, struct ast_sip_contact **contact) { char *aor_name; char *rest; /* If the location is still empty we have nowhere to go */ if (ast_strlen_zero(aor_list) || !(rest = ast_strdupa(aor_list))) { ast_log(LOG_WARNING, "Unable to determine contacts from empty aor list\n"); return; } *aor = NULL; *contact = NULL; while ((aor_name = ast_strip(strsep(&rest, ",")))) { *aor = ast_sip_location_retrieve_aor(aor_name); if (!(*aor)) { continue; } *contact = ast_sip_location_retrieve_first_aor_contact(*aor); /* If a valid contact is available use its URI for dialing */ if (*contact) { break; } ao2_ref(*aor, -1); *aor = NULL; } }
/*! \brief Custom handler for permanent URIs */ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { struct ast_sip_aor *aor = obj; const char *aor_id = ast_sorcery_object_get_id(aor); char *contacts; char *contact_uri; if (ast_strlen_zero(var->value)) { return 0; } contacts = ast_strdupa(var->value); while ((contact_uri = ast_strip(strsep(&contacts, ",")))) { struct ast_sip_contact *contact; struct ast_sip_contact_status *status; char hash[33]; char contact_id[strlen(aor_id) + sizeof(hash) + 2]; if (ast_strlen_zero(contact_uri)) { continue; } if (ast_sip_validate_uri_length(contact_uri)) { ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit: %s\n", contact_uri); return -1; } if (!aor->permanent_contacts) { aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL); if (!aor->permanent_contacts) { return -1; } } ast_md5_hash(hash, contact_uri); snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash); contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id); if (!contact) { return -1; } ast_string_field_set(contact, uri, contact_uri); status = ast_res_pjsip_find_or_create_contact_status(contact); if (!status) { ao2_ref(contact, -1); return -1; } ao2_ref(status, -1); ao2_link(aor->permanent_contacts, contact); ao2_ref(contact, -1); } 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 ami_sip_qualify(struct mansession *s, const struct message *m) { const char *endpoint_name = astman_get_header(m, "Endpoint"); RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup); char *aors; char *aor_name; if (ast_strlen_zero(endpoint_name)) { astman_send_error(s, m, "Endpoint parameter missing."); return 0; } endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name); if (!endpoint) { astman_send_error(s, m, "Unable to retrieve endpoint\n"); return 0; } /* send a qualify for all contacts registered with the endpoint */ if (ast_strlen_zero(endpoint->aors)) { astman_send_error(s, m, "No AoRs configured for endpoint\n"); return 0; } aors = ast_strdupa(endpoint->aors); while ((aor_name = ast_strip(strsep(&aors, ",")))) { struct ast_sip_aor *aor; struct ao2_container *contacts; aor = ast_sip_location_retrieve_aor(aor_name); if (!aor) { continue; } contacts = ast_sip_location_retrieve_aor_contacts(aor); if (contacts) { ao2_callback(contacts, OBJ_NODATA, ami_contact_cb, NULL); ao2_ref(contacts, -1); } ao2_ref(aor, -1); } astman_send_ack(s, m, "Endpoint found, will qualify"); return 0; }
int ast_callerid_parse(char *input_str, char **name, char **location) { char *ls; char *le; char *name_start; char *instr; int quotes_stripped = 0; /* Handle surrounding quotes */ input_str = ast_strip(input_str); instr = ast_strip_quoted(input_str, "\"", "\""); if (instr != input_str) { quotes_stripped = 1; } /* Try "name" <location> format or name <location> format or with a missing > */ if ((ls = strrchr(instr, '<'))) { if ((le = strrchr(ls, '>'))) { *le = '\0'; /* location found, trim off the brackets */ } *ls = '\0'; *location = ls + 1; /* and this is the result */ name_start = ast_strip_quoted(instr, "\"", "\""); } else { /* no valid brackets */ char tmp[256]; ast_copy_string(tmp, instr, sizeof(tmp)); ast_shrink_phone_number(tmp); if (!quotes_stripped && ast_isphonenumber(tmp)) { /* Assume it's just a location */ name_start = NULL; strcpy(instr, tmp); /* safe, because tmp will always be the same size or smaller than instr */ *location = instr; } else { /* Assume it's just a name. */ *location = NULL; name_start = ast_strip_quoted(instr, "\"", "\""); } } if (name_start) { ast_unescape_quoted(name_start); } *name = name_start; return 0; }
static void global_loaded(const char *object_type) { char default_realm[MAX_REALM_LENGTH + 1]; struct ast_sip_auth *fake_auth; char *identifier_order; /* Update using_auth_username */ identifier_order = ast_sip_get_endpoint_identifier_order(); if (identifier_order) { char *identify_method; char *io_copy = ast_strdupa(identifier_order); int new_using = 0; ast_free(identifier_order); while ((identify_method = ast_strip(strsep(&io_copy, ",")))) { if (!strcmp(identify_method, "auth_username")) { new_using = 1; break; } } using_auth_username = new_using; } /* Update default_realm of artificial_auth */ ast_sip_get_default_realm(default_realm, sizeof(default_realm)); fake_auth = ast_sip_get_artificial_auth(); if (!fake_auth || strcmp(fake_auth->realm, default_realm)) { ao2_cleanup(fake_auth); fake_auth = alloc_artificial_auth(default_realm); if (fake_auth) { ao2_global_obj_replace_unref(artificial_auth, fake_auth); } } ao2_cleanup(fake_auth); ast_sip_get_unidentified_request_thresholds(&unidentified_count, &unidentified_period, &unidentified_prune_interval); /* Clean out the old task, if any */ ast_sched_clean_by_callback(prune_context, prune_task, clean_task); /* Have to do something with the return value to shut up the stupid compiler. */ if (ast_sched_add_variable(prune_context, unidentified_prune_interval * 1000, prune_task, NULL, 1) < 0) { return; } }
static int load_column_config(const char *tmp) { char *col = NULL; char *cols = NULL, *save = NULL; char *escaped = NULL; struct ast_str *column_string = NULL; if (ast_strlen_zero(tmp)) { ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n"); return -1; } if (!(column_string = ast_str_create(1024))) { ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table); return -1; } if (!(save = cols = ast_strdup(tmp))) { ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table); ast_free(column_string); return -1; } while ((col = strsep(&cols, ","))) { col = ast_strip(col); escaped = sqlite3_mprintf("%q", col); if (!escaped) { ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table); ast_free(column_string); ast_free(save); return -1; } ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped); sqlite3_free(escaped); } if (!(columns = ast_strdup(ast_str_buffer(column_string)))) { ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table); ast_free(column_string); ast_free(save); return -1; } ast_free(column_string); ast_free(save); return 0; }
/*! * \internal * \brief For an endpoint try to match the given contact->aor. */ static int on_endpoint(void *obj, void *arg, int flags) { struct ast_sip_endpoint *endpoint = obj; char *contact_aor = arg; char *aor_name; char *aors; if (!arg || ast_strlen_zero(endpoint->aors)) { return 0; } aors = ast_strdupa(endpoint->aors); while ((aor_name = ast_strip(strsep(&aors, ",")))) { if (!strcmp(contact_aor, aor_name)) { return CMP_MATCH; } } return 0; }
int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg) { char *copy, *name; if (!on_aor || ast_strlen_zero(aors)) { return 0; } copy = ast_strdupa(aors); while ((name = ast_strip(strsep(©, ",")))) { RAII_VAR(struct ast_sip_aor *, aor, ast_sip_location_retrieve_aor(name), ao2_cleanup); if (!aor) { continue; } if (on_aor(aor, arg, 0)) { return -1; } } return 0; }
/*! * \internal * \brief For an endpoint iterate over and qualify all aors/contacts */ static int cli_qualify_contacts(void *data) { char *aors; char *aor_name; RAII_VAR(struct qualify_data *, qual_data, data, qualify_data_destroy); struct ast_sip_endpoint *endpoint = qual_data->endpoint; int cli_fd = qual_data->cli_fd; const char *endpoint_name = ast_sorcery_object_get_id(endpoint); if (ast_strlen_zero(endpoint->aors)) { ast_cli(cli_fd, "Endpoint %s has no AoR's configured\n", endpoint_name); return 0; } aors = ast_strdupa(endpoint->aors); while ((aor_name = ast_strip(strsep(&aors, ",")))) { struct ast_sip_aor *aor; struct ao2_container *contacts; aor = ast_sip_location_retrieve_aor(aor_name); if (!aor) { continue; } contacts = ast_sip_location_retrieve_aor_contacts(aor); if (contacts) { ast_cli(cli_fd, "Sending qualify to endpoint %s\n", endpoint_name); ao2_callback_data(contacts, OBJ_NODATA, cli_on_contact, &cli_fd, endpoint); ao2_ref(contacts, -1); } ao2_ref(aor, -1); } return 0; }
static int aor_update_endpoint_state(void *obj, void *arg, int flags) { struct ast_sip_endpoint *endpoint = obj; const char *endpoint_name = ast_sorcery_object_get_id(endpoint); char *aor = arg; char *endpoint_aor; char *endpoint_aors; if (ast_strlen_zero(aor) || ast_strlen_zero(endpoint->aors)) { return 0; } endpoint_aors = ast_strdupa(endpoint->aors); while ((endpoint_aor = ast_strip(strsep(&endpoint_aors, ",")))) { if (!strcmp(aor, endpoint_aor)) { if (ast_sip_persistent_endpoint_update_state(endpoint_name, AST_ENDPOINT_ONLINE) == -1) { ast_log(LOG_WARNING, "Unable to find persistent endpoint '%s' for aor '%s'\n", endpoint_name, aor); } } } return 0; }
static struct ast_variable *parse_cookies(char *cookies) { char *cur; struct ast_variable *vars = NULL, *var; /* Skip Cookie: */ cookies += 8; while ((cur = strsep(&cookies, ";"))) { char *name, *val; name = val = cur; strsep(&val, "="); if (ast_strlen_zero(name) || ast_strlen_zero(val)) { continue; } name = ast_strip(name); val = ast_strip_quoted(val, "\"", "\""); if (ast_strlen_zero(name) || ast_strlen_zero(val)) { continue; } if (option_debug) { ast_log(LOG_DEBUG, "mmm ... cookie! Name: '%s' Value: '%s'\n", name, val); } var = ast_variable_new(name, val); var->next = vars; vars = var; } return vars; }
static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; int num_rows = 0; char sql[256]; char *stringp; char *chunk; char *op; const char *newparam, *newval; struct ast_variable *var = NULL, *prev = NULL; if (!table) { ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n"); return NULL; } /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return NULL; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ op = strchr(newparam, ' ') ? "" : " ="; snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) op = " ="; else op = ""; snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval); } va_end(ap); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return NULL; } if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return NULL; } } ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql); if ((num_rows = PQntuples(result)) > 0) { int i = 0; int rowIndex = 0; int numFields = PQnfields(result); char **fieldnames = NULL; ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows); if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { ast_mutex_unlock(&pgsql_lock); PQclear(result); return NULL; } for (i = 0; i < numFields; i++) fieldnames[i] = PQfname(result, i); for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { for (i = 0; i < numFields; i++) { stringp = PQgetvalue(result, rowIndex, i); while (stringp) { chunk = strsep(&stringp, ";"); if (chunk && !ast_strlen_zero(ast_strip(chunk))) { if (prev) { prev->next = ast_variable_new(fieldnames[i], chunk); if (prev->next) { prev = prev->next; } } else { prev = var = ast_variable_new(fieldnames[i], chunk); } } } } } free(fieldnames); } else { ast_log(LOG_WARNING, "Postgresql RealTime: Could not find any rows in table %s.\n", table); } ast_mutex_unlock(&pgsql_lock); PQclear(result); return var; }
static int app_exec(struct ast_channel *chan, void *data) { struct ast_module_user *lu; struct playlist_entry *entry; const char *args = data; int child_stdin[2] = { 0,0 }; int child_stdout[2] = { 0,0 }; int child_stderr[2] = { 0,0 }; int res = -1; int test_available_fd = -1; int gen_active = 0; int pid; char *argv[32]; int argc = 1; char *buf, *command; FILE *child_commands = NULL; FILE *child_errors = NULL; FILE *child_events = NULL; struct ivr_localuser foo = { .playlist = AST_LIST_HEAD_INIT_VALUE, .finishlist = AST_LIST_HEAD_INIT_VALUE, }; struct ivr_localuser *u = &foo; sigset_t fullset, oldset; lu = ast_module_user_add(chan); sigfillset(&fullset); pthread_sigmask(SIG_BLOCK, &fullset, &oldset); u->abort_current_sound = 0; u->chan = chan; if (ast_strlen_zero(args)) { ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n"); ast_module_user_remove(lu); return -1; } buf = ast_strdupa(data); argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0])); if (pipe(child_stdin)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno)); goto exit; } if (pipe(child_stdout)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno)); goto exit; } if (pipe(child_stderr)) { ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno)); goto exit; } if (chan->_state != AST_STATE_UP) { ast_answer(chan); } if (ast_activate_generator(chan, &gen, u) < 0) { ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n"); goto exit; } else gen_active = 1; pid = fork(); if (pid < 0) { ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno)); goto exit; } if (!pid) { /* child process */ int i; signal(SIGPIPE, SIG_DFL); pthread_sigmask(SIG_UNBLOCK, &fullset, NULL); if (ast_opt_high_priority) ast_set_priority(0); dup2(child_stdin[0], STDIN_FILENO); dup2(child_stdout[1], STDOUT_FILENO); dup2(child_stderr[1], STDERR_FILENO); for (i = STDERR_FILENO + 1; i < 1024; i++) close(i); execv(argv[0], argv); fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno)); _exit(1); } else { /* parent process */ int child_events_fd = child_stdin[1]; int child_commands_fd = child_stdout[0]; int child_errors_fd = child_stderr[0]; struct ast_frame *f; int ms; int exception; int ready_fd; int waitfds[2] = { child_errors_fd, child_commands_fd }; struct ast_channel *rchan; pthread_sigmask(SIG_SETMASK, &oldset, NULL); close(child_stdin[0]); child_stdin[0] = 0; close(child_stdout[1]); child_stdout[1] = 0; close(child_stderr[1]); child_stderr[1] = 0; if (!(child_events = fdopen(child_events_fd, "w"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n"); goto exit; } if (!(child_commands = fdopen(child_commands_fd, "r"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n"); goto exit; } if (!(child_errors = fdopen(child_errors_fd, "r"))) { ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n"); goto exit; } test_available_fd = open("/dev/null", O_RDONLY); setvbuf(child_events, NULL, _IONBF, 0); setvbuf(child_commands, NULL, _IONBF, 0); setvbuf(child_errors, NULL, _IONBF, 0); res = 0; while (1) { if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) { ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n"); res = -1; break; } if (ast_check_hangup(chan)) { ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n"); send_child_event(child_events, 'H', NULL, chan); res = -1; break; } ready_fd = 0; ms = 100; errno = 0; exception = 0; rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms); if (!AST_LIST_EMPTY(&u->finishlist)) { AST_LIST_LOCK(&u->finishlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) { send_child_event(child_events, 'F', entry->filename, chan); free(entry); } AST_LIST_UNLOCK(&u->finishlist); } if (rchan) { /* the channel has something */ f = ast_read(chan); if (!f) { ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n"); send_child_event(child_events, 'H', NULL, chan); res = -1; break; } if (f->frametype == AST_FRAME_DTMF) { send_child_event(child_events, f->subclass, NULL, chan); if (u->option_autoclear) { if (!u->abort_current_sound && !u->playing_silence) send_child_event(child_events, 'T', NULL, chan); AST_LIST_LOCK(&u->playlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) { send_child_event(child_events, 'D', entry->filename, chan); free(entry); } if (!u->playing_silence) u->abort_current_sound = 1; AST_LIST_UNLOCK(&u->playlist); } } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) { ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n"); send_child_event(child_events, 'H', NULL, chan); ast_frfree(f); res = -1; break; } ast_frfree(f); } else if (ready_fd == child_commands_fd) { char input[1024]; if (exception || feof(child_commands)) { ast_chan_log(LOG_WARNING, chan, "Child process went away\n"); res = -1; break; } if (!fgets(input, sizeof(input), child_commands)) continue; command = ast_strip(input); ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input); if (strlen(input) < 4) continue; if (input[0] == 'S') { if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) { ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]); send_child_event(child_events, 'Z', NULL, chan); strcpy(&input[2], "exception"); } if (!u->abort_current_sound && !u->playing_silence) send_child_event(child_events, 'T', NULL, chan); AST_LIST_LOCK(&u->playlist); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) { send_child_event(child_events, 'D', entry->filename, chan); free(entry); } if (!u->playing_silence) u->abort_current_sound = 1; entry = make_entry(&input[2]); if (entry) AST_LIST_INSERT_TAIL(&u->playlist, entry, list); AST_LIST_UNLOCK(&u->playlist); } else if (input[0] == 'A') { if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) { ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]); send_child_event(child_events, 'Z', NULL, chan); strcpy(&input[2], "exception"); } entry = make_entry(&input[2]); if (entry) { AST_LIST_LOCK(&u->playlist); AST_LIST_INSERT_TAIL(&u->playlist, entry, list); AST_LIST_UNLOCK(&u->playlist); } } else if (input[0] == 'H') { ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]); send_child_event(child_events, 'H', NULL, chan); break; } else if (input[0] == 'O') { if (!strcasecmp(&input[2], "autoclear")) u->option_autoclear = 1; else if (!strcasecmp(&input[2], "noautoclear")) u->option_autoclear = 0; else ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]); } } else if (ready_fd == child_errors_fd) { char input[1024]; if (exception || (dup2(child_commands_fd, test_available_fd) == -1) || feof(child_errors)) { ast_chan_log(LOG_WARNING, chan, "Child process went away\n"); res = -1; break; } if (fgets(input, sizeof(input), child_errors)) { command = ast_strip(input); ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command); } } else if ((ready_fd < 0) && ms) { if (errno == 0 || errno == EINTR) continue; ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno)); break; } } } exit: if (gen_active) ast_deactivate_generator(chan); if (child_events) fclose(child_events); if (child_commands) fclose(child_commands); if (child_errors) fclose(child_errors); if (test_available_fd > -1) { close(test_available_fd); } if (child_stdin[0]) close(child_stdin[0]); if (child_stdin[1]) close(child_stdin[1]); if (child_stdout[0]) close(child_stdout[0]); if (child_stdout[1]) close(child_stdout[1]); if (child_stderr[0]) close(child_stderr[0]); if (child_stderr[1]) close(child_stderr[1]); while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) free(entry); ast_module_user_remove(lu); return res; }
static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap) { PGresult *result = NULL; int num_rows = 0, pgerror; char sql[256], escapebuf[513]; const char *initfield = NULL; char *stringp; char *chunk; char *op; const char *newparam, *newval; struct ast_variable *var = NULL; struct ast_config *cfg = NULL; struct ast_category *cat = NULL; if (!table) { ast_log(LOG_WARNING, "PostgreSQL RealTime: No table specified.\n"); return NULL; } if (!(cfg = ast_config_new())) return NULL; /* Get the first parameter and first value in our list of passed paramater/value pairs */ newparam = va_arg(ap, const char *); newval = va_arg(ap, const char *); if (!newparam || !newval) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); if (pgsqlConn) { PQfinish(pgsqlConn); pgsqlConn = NULL; }; return NULL; } initfield = ast_strdupa(newparam); if ((op = strchr(initfield, ' '))) { *op = '\0'; } /* Create the first part of the query using the first parameter/value pairs we just extracted If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ if (!strchr(newparam, ' ')) op = " ="; else op = ""; PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, escapebuf); while ((newparam = va_arg(ap, const char *))) { newval = va_arg(ap, const char *); if (!strchr(newparam, ' ')) op = " ="; else op = ""; PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); if (pgerror) { ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); va_end(ap); return NULL; } snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, escapebuf); } if (initfield) { snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); } va_end(ap); /* We now have our complete statement; Lets connect to the server and execute it. */ ast_mutex_lock(&pgsql_lock); if (!pgsql_reconnect(database)) { ast_mutex_unlock(&pgsql_lock); return NULL; } if (!(result = PQexec(pgsqlConn, sql))) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s\n", PQerrorMessage(pgsqlConn)); ast_mutex_unlock(&pgsql_lock); return NULL; } else { ExecStatusType result_status = PQresultStatus(result); if (result_status != PGRES_COMMAND_OK && result_status != PGRES_TUPLES_OK && result_status != PGRES_NONFATAL_ERROR) { ast_log(LOG_WARNING, "PostgreSQL RealTime: Failed to query database. Check debug for more info.\n"); ast_debug(1, "PostgreSQL RealTime: Query: %s\n", sql); ast_debug(1, "PostgreSQL RealTime: Query Failed because: %s (%s)\n", PQresultErrorMessage(result), PQresStatus(result_status)); ast_mutex_unlock(&pgsql_lock); return NULL; } } ast_debug(1, "PostgreSQL RealTime: Result=%p Query: %s\n", result, sql); if ((num_rows = PQntuples(result)) > 0) { int numFields = PQnfields(result); int i = 0; int rowIndex = 0; char **fieldnames = NULL; ast_debug(1, "PostgreSQL RealTime: Found %d rows.\n", num_rows); if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { ast_mutex_unlock(&pgsql_lock); PQclear(result); return NULL; } for (i = 0; i < numFields; i++) fieldnames[i] = PQfname(result, i); for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { var = NULL; if (!(cat = ast_category_new("","",99999))) continue; for (i = 0; i < numFields; i++) { stringp = PQgetvalue(result, rowIndex, i); while (stringp) { chunk = strsep(&stringp, ";"); if (!ast_strlen_zero(ast_strip(chunk))) { if (initfield && !strcmp(initfield, fieldnames[i])) { ast_category_rename(cat, chunk); } var = ast_variable_new(fieldnames[i], chunk, ""); ast_variable_append(cat, var); } } } ast_category_append(cfg, cat); } ast_free(fieldnames); } else { ast_log(LOG_WARNING, "PostgreSQL RealTime: Could not find any rows in table %s.\n", table); } ast_mutex_unlock(&pgsql_lock); PQclear(result); return cfg; }
static int register_aor(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint, struct ast_sip_aor *aor, const char *aor_name) { struct aor_core_response response = { .code = 500, }; struct ao2_container *contacts = NULL; ao2_lock(aor); contacts = ast_sip_location_retrieve_aor_contacts_nolock(aor); if (!contacts) { ao2_unlock(aor); pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, response.code, NULL, NULL, NULL); return PJ_TRUE; } register_aor_core(rdata, endpoint, aor, aor_name, contacts, &response); ao2_cleanup(contacts); ao2_unlock(aor); /* Now send the REGISTER response to the peer */ if (response.tdata) { ast_sip_send_stateful_response(rdata, response.tdata, endpoint); } else { pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, response.code, NULL, NULL, NULL); } return PJ_TRUE; } static int match_aor(const char *aor_name, const char *id) { if (ast_strlen_zero(aor_name)) { return 0; } if (!strcmp(aor_name, id)) { ast_debug(3, "Matched id '%s' to aor '%s'\n", id, aor_name); return 1; } return 0; } 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; }