diff options
-rw-r--r-- | addons/res_config_mysql.c | 7 | ||||
-rw-r--r-- | apps/app_directory.c | 18 | ||||
-rw-r--r-- | apps/app_queue.c | 65 | ||||
-rw-r--r-- | configs/samples/pjsip.conf.sample | 20 | ||||
-rw-r--r-- | include/asterisk/config.h | 12 | ||||
-rw-r--r-- | pbx/pbx_realtime.c | 13 | ||||
-rw-r--r-- | res/res_config_curl.c | 7 | ||||
-rw-r--r-- | res/res_config_ldap.c | 257 | ||||
-rw-r--r-- | res/res_config_odbc.c | 6 | ||||
-rw-r--r-- | res/res_config_pgsql.c | 9 | ||||
-rw-r--r-- | res/res_config_sqlite.c | 8 | ||||
-rw-r--r-- | res/res_config_sqlite3.c | 7 | ||||
-rw-r--r-- | res/res_pjsip.c | 51 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_distributor.c | 109 | ||||
-rw-r--r-- | res/res_pjsip_authenticator_digest.c | 105 | ||||
-rw-r--r-- | res/res_pjsip_outbound_publish.c | 13 | ||||
-rw-r--r-- | res/res_pjsip_outbound_registration.c | 13 | ||||
-rw-r--r-- | third-party/pjproject/patches/0011-r5554-svn-backport-Increase-SENDER_WIDTH-column-size.patch | 77 | ||||
-rw-r--r-- | third-party/pjproject/patches/0012-Re-1945-misc-Don-t-trigger-SRV-complete-callback-whe.patch | 59 | ||||
-rw-r--r-- | third-party/pjproject/patches/0013-r5559-svn-backport-Fix-to-resolve-DNS-SRV-crashes.patch | 112 |
20 files changed, 743 insertions, 225 deletions
diff --git a/addons/res_config_mysql.c b/addons/res_config_mysql.c index f2ef949fc..b080d118b 100644 --- a/addons/res_config_mysql.c +++ b/addons/res_config_mysql.c @@ -523,9 +523,8 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char while ((row = mysql_fetch_row(result))) { var = NULL; - cat = ast_category_new("", "", -1); + cat = ast_category_new_anonymous(); if (!cat) { - ast_log(LOG_WARNING, "Out of memory!\n"); continue; } for (i = 0; i < numFields; i++) { @@ -934,8 +933,8 @@ static struct ast_config *config_mysql(const char *database, const char *table, } if (strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) { - if (!(cur_cat = ast_category_new(row[0], "", -1))) { - ast_log(LOG_WARNING, "Out of memory!\n"); + cur_cat = ast_category_new_dynamic(row[0]); + if (!cur_cat) { break; } strcpy(last, row[0]); diff --git a/apps/app_directory.c b/apps/app_directory.c index 642b9b23a..dd80c3467 100644 --- a/apps/app_directory.c +++ b/apps/app_directory.c @@ -464,7 +464,7 @@ static struct ast_config *realtime_directory(char *context) struct ast_config *rtdata = NULL; struct ast_category *cat; struct ast_variable *var; - char *mailbox; + char *category = NULL; const char *fullname; const char *hidefromdir, *searchcontexts = NULL; struct ast_flags config_flags = { 0 }; @@ -505,13 +505,12 @@ static struct ast_config *realtime_directory(char *context) return cfg; } - mailbox = NULL; - while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { - struct ast_variable *alias; - const char *ctx = ast_variable_retrieve(rtdata, mailbox, "context"); + while ((category = ast_category_browse(rtdata, category))) { + const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox"); + const char *ctx = ast_variable_retrieve(rtdata, category, "context"); - fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); - hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir"); + fullname = ast_variable_retrieve(rtdata, category, "fullname"); + hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir"); if (ast_true(hidefromdir)) { /* Skip hidden */ continue; @@ -519,8 +518,9 @@ static struct ast_config *realtime_directory(char *context) /* password,Full Name,email,pager,options */ ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, "")); - if (ast_variable_retrieve(rtdata, mailbox, "alias")) { - for (alias = ast_variable_browse(rtdata, mailbox); alias; alias = alias->next) { + if (ast_variable_retrieve(rtdata, category, "alias")) { + struct ast_variable *alias; + for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) { if (!strcasecmp(alias->name, "alias")) { ast_str_append(&tmp, 0, "|alias=%s", alias->value); } diff --git a/apps/app_queue.c b/apps/app_queue.c index 95f4c0eed..204b4b2de 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -2914,13 +2914,19 @@ static int load_realtime_rules(void) ast_log(LOG_WARNING, "Failed to load queue rules from realtime\n"); return 0; } - while ((rulecat = ast_category_browse(cfg, rulecat)) && !ast_strlen_zero(rulecat)) { - const char *timestr, *maxstr, *minstr; + while ((rulecat = ast_category_browse(cfg, rulecat))) { + const char *timestr, *maxstr, *minstr, *rule_name; int penaltychangetime, rule_exists = 0, inserted = 0; int max_penalty = 0, min_penalty = 0, min_relative = 0, max_relative = 0; struct penalty_rule *new_penalty_rule = NULL; + + rule_name = ast_variable_retrieve(cfg, rulecat, "rule_name"); + if (ast_strlen_zero(rule_name)) { + continue; + } + AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) { - if (!(strcasecmp(rl_iter->name, rulecat))) { + if (!(strcasecmp(rl_iter->name, rule_name))) { rule_exists = 1; new_rl = rl_iter; break; @@ -2931,13 +2937,13 @@ static int load_realtime_rules(void) ast_config_destroy(cfg); return -1; } - ast_copy_string(new_rl->name, rulecat, sizeof(new_rl->name)); + ast_copy_string(new_rl->name, rule_name, sizeof(new_rl->name)); AST_LIST_INSERT_TAIL(&rule_lists, new_rl, list); } timestr = ast_variable_retrieve(cfg, rulecat, "time"); if (!(timestr) || sscanf(timestr, "%30d", &penaltychangetime) != 1) { ast_log(LOG_NOTICE, "Failed to parse time (%s) for one of the %s rules, skipping it\n", - (ast_strlen_zero(timestr) ? "invalid value" : timestr), rulecat); + (ast_strlen_zero(timestr) ? "invalid value" : timestr), rule_name); continue; } if (!(new_penalty_rule = ast_calloc(1, sizeof(*new_penalty_rule)))) { @@ -3272,7 +3278,7 @@ static void member_remove_from_queue(struct call_queue *queue, struct member *me * Search for member in queue, if found update penalty/paused state, * if no member exists create one flag it as a RT member and add to queue member list. */ -static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config) +static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config) { struct member *m; struct ao2_iterator mem_iter; @@ -3282,11 +3288,12 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc int ringinuse = q->ringinuse; const char *config_val; - const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid"); - const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface); - const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface); - const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty"); - const char *paused_str = ast_variable_retrieve(member_config, interface, "paused"); + const char *interface = ast_variable_retrieve(member_config, category, "interface"); + const char *rt_uniqueid = ast_variable_retrieve(member_config, category, "uniqueid"); + const char *membername = S_OR(ast_variable_retrieve(member_config, category, "membername"), interface); + const char *state_interface = S_OR(ast_variable_retrieve(member_config, category, "state_interface"), interface); + const char *penalty_str = ast_variable_retrieve(member_config, category, "penalty"); + const char *paused_str = ast_variable_retrieve(member_config, category, "paused"); if (ast_strlen_zero(rt_uniqueid)) { ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL")); @@ -3309,7 +3316,7 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, struc } } - if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) { + if ((config_val = ast_variable_retrieve(member_config, category, realtime_ringinuse_field))) { if (ast_true(config_val)) { ringinuse = 1; } else if (ast_false(config_val)) { @@ -3425,7 +3432,7 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as }; struct member *m; struct ao2_iterator mem_iter; - char *interface = NULL; + char *category = NULL; const char *tmp_name; char *tmp; char tmpbuf[64]; /* Must be longer than the longest queue param name. */ @@ -3526,8 +3533,8 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as } ao2_iterator_destroy(&mem_iter); - while ((interface = ast_category_browse(member_config, interface))) { - rt_handle_member_record(q, interface, member_config); + while ((category = ast_category_browse(member_config, category))) { + rt_handle_member_record(q, category, member_config); } /* Delete all realtime members that have been deleted in DB. */ @@ -3636,7 +3643,7 @@ static void update_realtime_members(struct call_queue *q) { struct ast_config *member_config = NULL; struct member *m; - char *interface = NULL; + char *category = NULL; struct ao2_iterator mem_iter; if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) { @@ -3669,8 +3676,8 @@ static void update_realtime_members(struct call_queue *q) } ao2_iterator_destroy(&mem_iter); - while ((interface = ast_category_browse(member_config, interface))) { - rt_handle_member_record(q, interface, member_config); + while ((category = ast_category_browse(member_config, category))) { + rt_handle_member_record(q, category, member_config); } /* Delete all realtime members that have been deleted in DB. */ @@ -7471,12 +7478,11 @@ static int set_member_value(const char *queuename, const char *interface, int pr if (ast_strlen_zero(queuename)) { /* This means we need to iterate through all the queues. */ if (ast_check_realtime("queues")) { - char *name; queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL); if (queue_config) { - for (name = ast_category_browse(queue_config, NULL); - !ast_strlen_zero(name); - name = ast_category_browse(queue_config, name)) { + char *category = NULL; + while ((category = ast_category_browse(queue_config, category))) { + const char *name = ast_variable_retrieve(queue_config, category, "name"); if ((q = find_load_queue_rt_friendly(name))) { foundqueue++; foundinterface += set_member_value_help_members(q, interface, property, value); @@ -9381,9 +9387,10 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char * * which have not yet been added to the in-core container */ struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL); - char *queuename; if (cfg) { - for (queuename = ast_category_browse(cfg, NULL); !ast_strlen_zero(queuename); queuename = ast_category_browse(cfg, queuename)) { + char *category = NULL; + while ((category = ast_category_browse(cfg, category))) { + const char *queuename = ast_variable_retrieve(cfg, category, "name"); if ((q = find_load_queue_rt_friendly(queuename))) { queue_t_unref(q, "Done with temporary pointer"); } @@ -9452,7 +9459,8 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char * ast_str_set(&out, 0, " %s", mem->membername); if (strcasecmp(mem->membername, mem->interface)) { ast_str_append(&out, 0, " (%s", mem->interface); - if (!ast_strlen_zero(mem->state_interface)) { + if (!ast_strlen_zero(mem->state_interface) + && strcmp(mem->state_interface, mem->interface)) { ast_str_append(&out, 0, " from %s", mem->state_interface); } ast_str_append(&out, 0, ")"); @@ -11044,14 +11052,13 @@ static int queues_data_provider_get(const struct ast_data_search *search, struct ao2_iterator i; struct call_queue *queue, *queue_realtime = NULL; struct ast_config *cfg; - char *queuename; /* load realtime queues. */ cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL); if (cfg) { - for (queuename = ast_category_browse(cfg, NULL); - !ast_strlen_zero(queuename); - queuename = ast_category_browse(cfg, queuename)) { + char *category = NULL; + while ((category = ast_category_browse(cfg, category))) { + const char *queuename = ast_variable_retrieve(cfg, category, "name"); if ((queue = find_load_queue_rt_friendly(queuename))) { queue_unref(queue); } diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 6595423c9..323100b00 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -12,6 +12,12 @@ ; If you want to see more detail please check the documentation sources ; mentioned at the top of this file. +; ============================================================================ +; NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE +; +; This file does not maintain the complete option documentation. +; ============================================================================ + ; Documentation ; ; The official documentation is at http://wiki.asterisk.org @@ -765,6 +771,14 @@ ;==========================AUTH SECTION OPTIONS========================= ;[auth] ; SYNOPSIS: Authentication type +; +; Note: Using the same auth section for inbound and outbound +; authentication is not recommended. There is a difference in +; meaning for an empty realm setting between inbound and outbound +; authentication uses. Look to the CLI config help +; "config show help res_pjsip auth realm" or on the wiki for the +; difference. +; ;auth_type=userpass ; Authentication type (default: "userpass") ;nonce_lifetime=32 ; Lifetime of a nonce associated with this ; authentication config (default: "32") @@ -959,9 +973,9 @@ ; From header username will be set to this value if ; there is no better option (such as CallerID or ; endpoint/from_user) to be used -;default_realm=asterisk ; When Asterisk generates a challenge, the realm will be - ; set to this value if there is no better option (such as - ; auth/realm) to be used +;default_realm=asterisk ; When Asterisk generates a challenge, the digest realm + ; will be set to this value if there is no better option + ; (such as auth/realm) to be used. ; Asterisk Task Processor Queue Size ; On heavy loaded system with DB storage you may need to increase diff --git a/include/asterisk/config.h b/include/asterisk/config.h index 4944a3af2..f57966b0b 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -834,6 +834,18 @@ const char *ast_config_option(struct ast_config *cfg, const char *cat, const cha struct ast_category *ast_category_new(const char *name, const char *in_file, int lineno); /*! + * \brief Create a category that is not backed by a file + * + * \param name name of new category + */ +#define ast_category_new_dynamic(name) ast_category_new(name, "", -1) + +/*! + * \brief Create a nameless category that is not backed by a file + */ +#define ast_category_new_anonymous() ast_category_new_dynamic("") + +/*! * \brief Create a category making it a template * * \param name name of new template diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c index 08c90aa62..6f5d13738 100644 --- a/pbx/pbx_realtime.c +++ b/pbx/pbx_realtime.c @@ -189,25 +189,26 @@ static struct ast_variable *realtime_switch_common(const char *table, const char if (!var && !ast_test_flag(&flags, OPTION_PATTERNS_DISABLED)) { cfg = ast_load_realtime_multientry(table, "exten LIKE", "\\_%", "context", context, "priority", pri, SENTINEL); if (cfg) { - char *cat = ast_category_browse(cfg, NULL); + char *cat = NULL; + + while ((cat = ast_category_browse(cfg, cat))) { + const char *realtime_exten = ast_variable_retrieve(cfg, cat, "exten"); - while(cat) { switch(mode) { case MODE_MATCHMORE: - match = ast_extension_close(cat, exten, 1); + match = ast_extension_close(realtime_exten, exten, 1); break; case MODE_CANMATCH: - match = ast_extension_close(cat, exten, 0); + match = ast_extension_close(realtime_exten, exten, 0); break; case MODE_MATCH: default: - match = ast_extension_match(cat, exten); + match = ast_extension_match(realtime_exten, exten); } if (match) { var = ast_category_detach_variables(ast_category_get(cfg, cat, NULL)); break; } - cat = ast_category_browse(cfg, cat); } ast_config_destroy(cfg); } diff --git a/res/res_config_curl.c b/res/res_config_curl.c index 9ad7a6e3d..06a6aef89 100644 --- a/res/res_config_curl.c +++ b/res/res_config_curl.c @@ -182,7 +182,8 @@ static struct ast_config *realtime_multi_curl(const char *url, const char *unuse continue; } - if (!(cat = ast_category_new("", "", 99999))) { + cat = ast_category_new_anonymous(); + if (!cat) { continue; } @@ -569,8 +570,10 @@ static struct ast_config *config_curl(const char *url, const char *unused, const } if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) { - if (!(cat = ast_category_new(category, "", 99999))) + cat = ast_category_new_dynamic(category); + if (!cat) { break; + } cur_cat = category; last_cat_metric = cat_metric; ast_category_append(cfg, cat); diff --git a/res/res_config_ldap.c b/res/res_config_ldap.c index 5e95853d4..8ad9e1319 100644 --- a/res/res_config_ldap.c +++ b/res/res_config_ldap.c @@ -190,7 +190,7 @@ static int semicolon_count_var(struct ast_variable *var) return 0; } - ast_debug(2, "LINE(%d) semicolon_count_var: %s\n", __LINE__, var_value->value); + ast_debug(2, "semicolon_count_var: %s\n", var_value->value); return semicolon_count_str(var_value->value); } @@ -330,7 +330,7 @@ static struct ast_variable *realtime_ldap_entry_to_var(struct ldap_table_config for (v = values; *v; v++) { value = *v; valptr = value->bv_val; - ast_debug(2, "LINE(%d) attribute_name: %s LDAP value: %s\n", __LINE__, attribute_name, valptr); + ast_debug(2, "attribute_name: %s LDAP value: %s\n", attribute_name, valptr); if (is_realmed_password_attribute) { if (!strncasecmp(valptr, "{md5}", 5)) { valptr += 5; @@ -422,7 +422,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf * value in \a variable_value; otherwise, we keep \a vars static and increase the length of the linked list of variables in the array element. * This memory must be freed outside of this function. */ - vars = ast_calloc(sizeof(struct ast_variable *), tot_count + 1); + vars = ast_calloc(tot_count + 1, sizeof(struct ast_variable *)); ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg); @@ -467,7 +467,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf delim_value = ast_strdup(valptr); if ((delim_tot_count = semicolon_count_str(delim_value)) > 0) { - ast_debug(4, "LINE(%d) is delimited %d times: %s\n", __LINE__, delim_tot_count, delim_value); + ast_debug(4, "is delimited %d times: %s\n", delim_tot_count, delim_value); is_delimited = 1; } } @@ -477,11 +477,11 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf /* for non-Static RealTime, first */ for (i = pos; !ast_strlen_zero(valptr + i); i++) { - ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i); + ast_debug(4, "DELIM pos: %d i: %d\n", pos, i); if (delim_value[i] == ';') { delim_value[i] = '\0'; - ast_debug(2, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos); + ast_debug(2, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos); if (prev) { prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name); @@ -499,9 +499,9 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf } } if (ast_strlen_zero(valptr + i)) { - ast_debug(4, "LINE(%d) DELIM pos: %d i: %d delim_count: %d\n", __LINE__, pos, i, delim_count); + ast_debug(4, "DELIM pos: %d i: %d delim_count: %d\n", pos, i, delim_count); /* Last delimited value */ - ast_debug(4, "LINE(%d) DELIM - attribute_name: %s value: %s pos: %d\n", __LINE__, attribute_name, &delim_value[pos], pos); + ast_debug(4, "DELIM - attribute_name: %s value: %s pos: %d\n", attribute_name, &delim_value[pos], pos); if (prev) { prev->next = ast_variable_new(attribute_name, &delim_value[pos], table_config->table_name); if (prev->next) { @@ -517,14 +517,14 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf ast_free(delim_value); delim_value = NULL; - ast_debug(4, "LINE(%d) DELIM pos: %d i: %d\n", __LINE__, pos, i); + ast_debug(4, "DELIM pos: %d i: %d\n", pos, i); } else { /* not delimited */ if (delim_value) { ast_free(delim_value); delim_value = NULL; } - ast_debug(2, "LINE(%d) attribute_name: %s value: %s\n", __LINE__, attribute_name, valptr); + ast_debug(2, "attribute_name: %s value: %s\n", attribute_name, valptr); if (prev) { prev->next = ast_variable_new(attribute_name, valptr, table_config->table_name); @@ -548,7 +548,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf const struct ast_variable *tmpdebug = variable_named(var, "variable_name"); const struct ast_variable *tmpdebug2 = variable_named(var, "variable_value"); if (tmpdebug && tmpdebug2) { - ast_debug(3, "LINE(%d) Added to vars - %s = %s\n", __LINE__, tmpdebug->value, tmpdebug2->value); + ast_debug(3, "Added to vars - %s = %s\n", tmpdebug->value, tmpdebug2->value); } } vars[entry_index++] = var; @@ -559,7 +559,7 @@ static struct ast_variable **realtime_ldap_result_to_vars(struct ldap_table_conf } while (delim_count <= delim_tot_count && static_table_config == table_config); if (static_table_config != table_config) { - ast_debug(3, "LINE(%d) Added to vars - non static\n", __LINE__); + ast_debug(3, "Added to vars - non static\n"); vars[entry_index++] = var; prev = NULL; @@ -926,13 +926,8 @@ static struct ast_variable **realtime_ldap_base_ap(unsigned int *entries_count_p } } - if (filter) { - ast_free(filter); - } - - if (clean_basedn) { - ast_free(clean_basedn); - } + ast_free(filter); + ast_free(clean_basedn); ast_mutex_unlock(&ldap_lock); @@ -1043,10 +1038,8 @@ static struct ast_config *realtime_multi_ldap(const char *basedn, struct ast_variable **p = vars; while (*p) { - struct ast_category *cat = NULL; - cat = ast_category_new("", table_name, -1); + struct ast_category *cat = ast_category_new_anonymous(); if (!cat) { - ast_log(LOG_ERROR, "Unable to create a new category!\n"); break; } else { struct ast_variable *var = *p; @@ -1136,7 +1129,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name * first, and since the data could easily exceed stack size, this is * allocated from the heap. */ - if (!(categories = ast_calloc(sizeof(*categories), vars_count))) { + if (!(categories = ast_calloc(vars_count, sizeof(*categories)))) { return NULL; } @@ -1195,7 +1188,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name if (!last_category || strcmp(last_category, categories[i].name) || last_category_metric != categories[i].metric) { - cur_cat = ast_category_new(categories[i].name, table_name, -1); + cur_cat = ast_category_new_dynamic(categories[i].name); if (!cur_cat) { break; } @@ -1217,6 +1210,90 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name return cfg; } +/*! + * \internal + * \brief Remove LDAP_MOD_DELETE modifications that will not succeed + * + * \details + * A LDAP_MOD_DELETE operation will fail if the LDAP entry does not already have + * the corresponding attribute. Because we may be updating multiple LDAP entries + * in a single call to update_ldap(), we may need our own copy of the + * modifications array for each one. + * + * \note + * This function dynamically allocates memory. If it returns a non-NULL pointer, + * it is up to the caller to free it with ldap_mods_free() + * + * \returns an LDAPMod * if modifications needed to be removed, NULL otherwise. + */ +static LDAPMod **massage_mods_for_entry(LDAPMessage *entry, LDAPMod **mods, size_t count) +{ + size_t i; + int remove[count]; + size_t remove_count = 0; + + for (i = 0; i < count; i++) { + BerElement *ber = NULL; + char *attribute; + int exists = 0; + + if (mods[i]->mod_op != LDAP_MOD_DELETE) { + continue; + } + + /* If we are deleting something, it has to exist */ + attribute = ldap_first_attribute(ldapConn, entry, &ber); + while (attribute) { + if (!strcasecmp(attribute, mods[i]->mod_type)) { + /* OK, we have the attribute */ + exists = 1; + ldap_memfree(attribute); + break; + } + + ldap_memfree(attribute); + attribute = ldap_next_attribute(ldapConn, entry, ber); + } + + if (!exists) { + remove[remove_count++] = i; + } + } + + if (remove_count) { + size_t k, remove_index; + LDAPMod **x = ldap_memcalloc(count - remove_count + 1, sizeof(LDAPMod *)); + for (i = 0, k = 0; i < count; i++) { + int skip = 0; + /* Is this one we have to remove? */ + for (remove_index = 0; !skip && remove_index < remove_count; remove_index++) { + skip = (remove[remove_index] == i); + } + + if (skip) { + ast_debug(3, "Skipping %s deletion because it doesn't exist\n", + mods[i]->mod_type); + continue; + } + + x[k] = ldap_memcalloc(1, sizeof(LDAPMod)); + x[k]->mod_op = mods[i]->mod_op; + x[k]->mod_type = ldap_strdup(mods[i]->mod_type); + if (mods[i]->mod_values) { + x[k]->mod_values = ldap_memcalloc(2, sizeof(char *)); + x[k]->mod_values[0] = ldap_strdup(mods[i]->mod_values[0]); + } + k++; + } + /* NULL terminate */ + x[k] = NULL; + return x; + } + + return NULL; +} + + /* \brief Function to update a set of values in ldap static mode */ static int update_ldap(const char *basedn, const char *table_name, const char *attribute, @@ -1249,7 +1326,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a } if (!attribute || !lookup) { - ast_log(LOG_WARNING, "LINE(%d): search parameters are empty.\n", __LINE__); + ast_log(LOG_WARNING, "Search parameters are empty.\n"); return -1; } ast_mutex_lock(&ldap_lock); @@ -1285,19 +1362,22 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a * one parameter/value pair and delimit them with a semicolon */ newparam = convert_attribute_name_to_ldap(table_config, field->name); if (!newparam) { - ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__); + ast_log(LOG_WARNING, "Need at least one parameter to modify.\n"); return -1; } mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */ - ldap_mods = ldap_memcalloc(sizeof(LDAPMod *), mods_size); + ldap_mods = ldap_memcalloc(mods_size, sizeof(LDAPMod *)); ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod)); - - ldap_mods[0]->mod_op = LDAP_MOD_REPLACE; ldap_mods[0]->mod_type = ldap_strdup(newparam); - ldap_mods[0]->mod_values = ast_calloc(sizeof(char *), 2); - ldap_mods[0]->mod_values[0] = ldap_strdup(field->value); + if (strlen(field->value) == 0) { + ldap_mods[0]->mod_op = LDAP_MOD_DELETE; + } else { + ldap_mods[0]->mod_op = LDAP_MOD_REPLACE; + ldap_mods[0]->mod_values = ldap_memcalloc(2, sizeof(char *)); + ldap_mods[0]->mod_values[0] = ldap_strdup(field->value); + } while ((field = field->next)) { newparam = convert_attribute_name_to_ldap(table_config, field->name); @@ -1309,7 +1389,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a ldap_mods[i]->mod_values[0] = ldap_memrealloc(ldap_mods[i]->mod_values[0], sizeof(char) * (strlen(ldap_mods[i]->mod_values[0]) + strlen(field->value) + 2)); strcat(ldap_mods[i]->mod_values[0], ";"); strcat(ldap_mods[i]->mod_values[0], field->value); - mod_exists = 1; + mod_exists = 1; break; } } @@ -1318,22 +1398,19 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a if (!mod_exists) { mods_size++; ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size); - ldap_mods[mods_size - 1] = NULL; - ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod)); - - ldap_mods[mods_size - 2]->mod_type = ldap_memcalloc(sizeof(char), strlen(newparam) + 1); - strcpy(ldap_mods[mods_size - 2]->mod_type, newparam); + ldap_mods[mods_size - 2]->mod_type = ldap_strdup(newparam); if (strlen(field->value) == 0) { ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_DELETE; } else { ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE; - - ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(sizeof(char *), 2); - ldap_mods[mods_size - 2]->mod_values[0] = ldap_memcalloc(sizeof(char), strlen(field->value) + 1); - strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value); + ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(2, sizeof(char *)); + ldap_mods[mods_size - 2]->mod_values[0] = ldap_strdup(field->value); } + + /* NULL terminate */ + ldap_mods[mods_size - 1] = NULL; } } /* freeing ldap_mods further down */ @@ -1366,27 +1443,45 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a ast_free(filter); ast_free(clean_basedn); ldap_msgfree(ldap_result_msg); - ldap_mods_free(ldap_mods, 0); + ldap_mods_free(ldap_mods, 1); return -1; } /* Ready to update */ if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) { - ast_debug(3, "LINE(%d) Modifying %s=%s hits: %d\n", __LINE__, attribute, lookup, num_entries); + ast_debug(3, "Modifying %s=%s hits: %d\n", attribute, lookup, num_entries); for (i = 0; option_debug > 2 && i < mods_size - 1; i++) { if (ldap_mods[i]->mod_op != LDAP_MOD_DELETE) { - ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]); + ast_debug(3, "%s=%s\n", ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]); } else { - ast_debug(3, "LINE(%d) deleting %s \n", __LINE__, ldap_mods[i]->mod_type); + ast_debug(3, "deleting %s\n", ldap_mods[i]->mod_type); } } ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg); - for (i = 0; ldap_entry; i++) { + for (i = 0; ldap_entry; i++) { + LDAPMod **working = ldap_mods; + LDAPMod **massaged = massage_mods_for_entry(ldap_entry, ldap_mods, mods_size - 1); + + if (massaged) { + /* Did we massage everything out of the list? */ + if (massaged[0] == NULL) { + ast_debug(3, "Nothing left to modify - skipping\n"); + ldap_mods_free(massaged, 1); + continue; + } + working = massaged; + } + dn = ldap_get_dn(ldapConn, ldap_entry); - if ((error = ldap_modify_ext_s(ldapConn, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if ((error = ldap_modify_ext_s(ldapConn, dn, working, NULL, NULL)) != LDAP_SUCCESS) { ast_log(LOG_ERROR, "Couldn't modify '%s'='%s', dn:%s because %s\n", attribute, lookup, dn, ldap_err2string(error)); } + + if (massaged) { + ldap_mods_free(massaged, 1); + } + ldap_memfree(dn); ldap_entry = ldap_next_entry(ldapConn, ldap_entry); } @@ -1396,7 +1491,7 @@ static int update_ldap(const char *basedn, const char *table_name, const char *a ast_free(filter); ast_free(clean_basedn); ldap_msgfree(ldap_result_msg); - ldap_mods_free(ldap_mods, 0); + ldap_mods_free(ldap_mods, 1); return num_entries; } @@ -1469,23 +1564,19 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct field = update_fields; newparam = convert_attribute_name_to_ldap(table_config, field->name); if (!newparam) { - ast_log(LOG_WARNING, "LINE(%d): need at least one parameter to modify.\n", __LINE__); + ast_log(LOG_WARNING, "Need at least one parameter to modify.\n"); ast_free(filter); ast_free(clean_basedn); return -1; } mods_size = 2; /* one for the first param/value pair and one for the the terminating NULL */ - ldap_mods = ast_calloc(sizeof(LDAPMod *), mods_size); - ldap_mods[0] = ast_calloc(1, sizeof(LDAPMod)); - + ldap_mods = ldap_memcalloc(mods_size, sizeof(LDAPMod *)); + ldap_mods[0] = ldap_memcalloc(1, sizeof(LDAPMod)); ldap_mods[0]->mod_op = LDAP_MOD_REPLACE; - ldap_mods[0]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1); - strcpy(ldap_mods[0]->mod_type, newparam); - - ldap_mods[0]->mod_values = ast_calloc(sizeof(char), 2); - ldap_mods[0]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1); - strcpy(ldap_mods[0]->mod_values[0], field->value); + ldap_mods[0]->mod_type = ldap_strdup(newparam); + ldap_mods[0]->mod_values = ldap_memcalloc(2, sizeof(char *)); + ldap_mods[0]->mod_values[0] = ldap_strdup(field->value); while ((field = field->next)) { newparam = convert_attribute_name_to_ldap(table_config, field->name); @@ -1505,18 +1596,15 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct /* create new mod */ if (!mod_exists) { mods_size++; - ldap_mods = ast_realloc(ldap_mods, sizeof(LDAPMod *) * mods_size); - ldap_mods[mods_size - 1] = NULL; - ldap_mods[mods_size - 2] = ast_calloc(1, sizeof(LDAPMod)); - + ldap_mods = ldap_memrealloc(ldap_mods, sizeof(LDAPMod *) * mods_size); + ldap_mods[mods_size - 2] = ldap_memcalloc(1, sizeof(LDAPMod)); ldap_mods[mods_size - 2]->mod_op = LDAP_MOD_REPLACE; + ldap_mods[mods_size - 2]->mod_type = ldap_strdup(newparam); + ldap_mods[mods_size - 2]->mod_values = ldap_memcalloc(2, sizeof(char *)); + ldap_mods[mods_size - 2]->mod_values[0] = ldap_strdup(field->value); - ldap_mods[mods_size - 2]->mod_type = ast_calloc(sizeof(char), strlen(newparam) + 1); - strcpy(ldap_mods[mods_size - 2]->mod_type, newparam); - - ldap_mods[mods_size - 2]->mod_values = ast_calloc(sizeof(char *), 2); - ldap_mods[mods_size - 2]->mod_values[0] = ast_calloc(sizeof(char), strlen(field->value) + 1); - strcpy(ldap_mods[mods_size - 2]->mod_values[0], field->value); + /* NULL terminate */ + ldap_mods[mods_size - 1] = NULL; } } /* freeing ldap_mods further down */ @@ -1550,13 +1638,13 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct ast_free(filter); ast_free(clean_basedn); ldap_msgfree(ldap_result_msg); - ldap_mods_free(ldap_mods, 0); + ldap_mods_free(ldap_mods, 1); return -1; } /* Ready to update */ if ((num_entries = ldap_count_entries(ldapConn, ldap_result_msg)) > 0) { for (i = 0; option_debug > 2 && i < mods_size - 1; i++) { - ast_debug(3, "LINE(%d) %s=%s \n", __LINE__, ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]); + ast_debug(3, "%s=%s\n", ldap_mods[i]->mod_type, ldap_mods[i]->mod_values[0]); } ldap_entry = ldap_first_entry(ldapConn, ldap_result_msg); @@ -1572,14 +1660,10 @@ static int update2_ldap(const char *basedn, const char *table_name, const struct } ast_mutex_unlock(&ldap_lock); - if (filter) { - ast_free(filter); - } - if (clean_basedn) { - ast_free(clean_basedn); - } + ast_free(filter); + ast_free(clean_basedn); ldap_msgfree(ldap_result_msg); - ldap_mods_free(ldap_mods, 0); + ldap_mods_free(ldap_mods, 1); return num_entries; } @@ -1681,6 +1765,21 @@ static int reload(void) return 0; } +static int config_can_be_inherited(const char *key) +{ + int i; + static const char * const config[] = { + "basedn", "host", "pass", "port", "protocol", "url", "user", "version", NULL + }; + + for (i = 0; config[i]; i++) { + if (!strcasecmp(key, config[i])) { + return 0; + } + } + return 1; +} + /*! \brief parse the configuration file */ static int parse_config(void) @@ -1771,7 +1870,9 @@ static int parse_config(void) if (!strcasecmp(var->name, "additionalFilter")) { table_config->additional_filter = ast_strdup(var->value); } else { - ldap_table_config_add_attribute(table_config, var->name, var->value); + if (!is_general || config_can_be_inherited(var->name)) { + ldap_table_config_add_attribute(table_config, var->name, var->value); + } } } } diff --git a/res/res_config_odbc.c b/res/res_config_odbc.c index 5a25b6b5a..114708325 100644 --- a/res/res_config_odbc.c +++ b/res/res_config_odbc.c @@ -407,9 +407,8 @@ static struct ast_config *realtime_multi_odbc(const char *database, const char * ast_log(LOG_WARNING, "SQL Fetch error! [%s]\n", ast_str_buffer(sql)); continue; } - cat = ast_category_new("","",99999); + cat = ast_category_new_anonymous(); if (!cat) { - ast_log(LOG_WARNING, "Out of memory!\n"); continue; } for (x=0;x<colcount;x++) { @@ -1016,9 +1015,8 @@ static struct ast_config *config_odbc(const char *database, const char *table, c continue; } if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) { - cur_cat = ast_category_new(q.category, "", 99999); + cur_cat = ast_category_new_dynamic(q.category); if (!cur_cat) { - ast_log(LOG_WARNING, "Out of memory!\n"); break; } strcpy(last, q.category); diff --git a/res/res_config_pgsql.c b/res/res_config_pgsql.c index f0859617d..b5f24b0f4 100644 --- a/res/res_config_pgsql.c +++ b/res/res_config_pgsql.c @@ -648,8 +648,10 @@ static struct ast_config *realtime_multi_pgsql(const char *database, const char for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { var = NULL; - if (!(cat = ast_category_new("","",99999))) + cat = ast_category_new_anonymous(); + if (!cat) { continue; + } for (i = 0; i < numFields; i++) { stringp = PQgetvalue(result, rowIndex, i); while (stringp) { @@ -1129,9 +1131,10 @@ static struct ast_config *config_pgsql(const char *database, const char *table, } if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) { - cur_cat = ast_category_new(field_category, "", 99999); - if (!cur_cat) + cur_cat = ast_category_new_dynamic(field_category); + if (!cur_cat) { break; + } ast_copy_string(last, field_category, sizeof(last)); last_cat_metric = atoi(field_cat_metric); ast_category_append(cfg, cur_cat); diff --git a/res/res_config_sqlite.c b/res/res_config_sqlite.c index 685949787..96a10b43f 100644 --- a/res/res_config_sqlite.c +++ b/res/res_config_sqlite.c @@ -874,10 +874,8 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames) } if (!args->cat_name || strcmp(args->cat_name, argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY])) { - args->cat = ast_category_new(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY], "", 99999); - + args->cat = ast_category_new_dynamic(argv[RES_CONFIG_SQLITE_CONFIG_CATEGORY]); if (!args->cat) { - ast_log(LOG_WARNING, "Unable to allocate category\n"); return 1; } @@ -1086,8 +1084,8 @@ static int add_rt_multi_cfg_entry(void *arg, int argc, char **argv, char **colum return 1; } - if (!(cat = ast_category_new(cat_name, "", 99999))) { - ast_log(LOG_WARNING, "Unable to allocate category\n"); + cat = ast_category_new_dynamic(cat_name); + if (!cat) { return 1; } diff --git a/res/res_config_sqlite3.c b/res/res_config_sqlite3.c index 8c514b07c..087843a68 100644 --- a/res/res_config_sqlite3.c +++ b/res/res_config_sqlite3.c @@ -503,7 +503,8 @@ static int append_row_to_cfg(void *arg, int num_columns, char **values, char **c struct ast_category *cat; int i; - if (!(cat = ast_category_new("", "", 99999))) { + cat = ast_category_new_anonymous(); + if (!cat) { return SQLITE_ABORT; } @@ -723,8 +724,8 @@ static int static_realtime_cb(void *arg, int num_columns, char **values, char ** } if (!args->cat_name || strcmp(args->cat_name, values[COL_CATEGORY])) { - if (!(args->cat = ast_category_new(values[COL_CATEGORY], "", 99999))) { - ast_log(LOG_WARNING, "Unable to allocate category\n"); + args->cat = ast_category_new_dynamic(values[COL_CATEGORY]); + if (!args->cat) { return SQLITE_ABORT; } diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 90eb37263..4dead21f5 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -112,9 +112,15 @@ This is a comma-delimited list of <replaceable>auth</replaceable> sections defined in <filename>pjsip.conf</filename> to be used to verify inbound connection attempts. </para><para> - Endpoints without an <literal>authentication</literal> object - configured will allow connections without vertification. - </para></description> + Endpoints without an authentication object + configured will allow connections without verification.</para> + <note><para> + Using the same auth section for inbound and outbound + authentication is not recommended. There is a difference in + meaning for an empty realm setting between inbound and outbound + authentication uses. See the auth realm description for details. + </para></note> + </description> </configOption> <configOption name="callerid"> <synopsis>CallerID information for the endpoint</synopsis> @@ -329,7 +335,18 @@ <synopsis>Default Music On Hold class</synopsis> </configOption> <configOption name="outbound_auth"> - <synopsis>Authentication object used for outbound requests</synopsis> + <synopsis>Authentication object(s) used for outbound requests</synopsis> + <description><para> + This is a comma-delimited list of <replaceable>auth</replaceable> + sections defined in <filename>pjsip.conf</filename> used to respond + to outbound connection authentication challenges.</para> + <note><para> + Using the same auth section for inbound and outbound + authentication is not recommended. There is a difference in + meaning for an empty realm setting between inbound and outbound + authentication uses. See the auth realm description for details. + </para></note> + </description> </configOption> <configOption name="outbound_proxy"> <synopsis>Proxy through which to send requests, a full SIP URI must be provided</synopsis> @@ -967,8 +984,30 @@ <synopsis>PlainText password used for authentication.</synopsis> <description><para>Only used when auth_type is <literal>userpass</literal>.</para></description> </configOption> - <configOption name="realm" default="asterisk"> + <configOption name="realm"> <synopsis>SIP realm for endpoint</synopsis> + <description><para> + The treatment of this value depends upon how the authentication + object is used. + </para><para> + When used as an inbound authentication object, the realm is sent + as part of the challenge so the peer can know which key to use + when responding. An empty value will use the + <replaceable>global</replaceable> section's + <literal>default_realm</literal> value when issuing a challenge. + </para><para> + When used as an outbound authentication object, the realm is + matched with the received challenge realm to determine which + authentication object to use when responding to the challenge. An + empty value matches any challenging realm when determining + which authentication object matches a received challenge. + </para> + <note><para> + Using the same auth section for inbound and outbound + authentication is not recommended. There is a difference in + meaning for an empty realm setting between inbound and outbound + authentication uses.</para></note> + </description> </configOption> <configOption name="type"> <synopsis>Must be 'auth'</synopsis> @@ -1512,7 +1551,7 @@ used.</synopsis> </configOption> <configOption name="default_realm" default="asterisk"> - <synopsis>When Asterisk generates an challenge, the digest will be + <synopsis>When Asterisk generates a challenge, the digest realm will be set to this value if there is no better option (such as auth/realm) to be used.</synopsis> </configOption> diff --git a/res/res_pjsip/pjsip_distributor.c b/res/res_pjsip/pjsip_distributor.c index eabfa4ba9..cca26a83c 100644 --- a/res/res_pjsip/pjsip_distributor.c +++ b/res/res_pjsip/pjsip_distributor.c @@ -43,7 +43,6 @@ struct ast_sched_context *prune_context; /* From the auth/realm realtime column size */ #define MAX_REALM_LENGTH 40 -static char default_realm[MAX_REALM_LENGTH + 1]; #define DEFAULT_SUSPECTS_BUCKETS 53 @@ -120,12 +119,12 @@ static struct ast_taskprocessor *find_request_serializer(pjsip_rx_data *rdata) tsx = pjsip_tsx_layer_find_tsx(&tsx_key, PJ_TRUE); if (!tsx) { - ast_debug(1, "Could not find %.*s transaction for %d response.\n", - (int) pj_strlen(&rdata->msg_info.cseq->method.name), - pj_strbuf(&rdata->msg_info.cseq->method.name), - rdata->msg_info.msg->line.status.code); + ast_debug(1, "Could not find transaction for %s.\n", + pjsip_rx_data_get_info(rdata)); return NULL; } + ast_debug(3, "Found transaction %s for %s.\n", + tsx->obj_name, pjsip_rx_data_get_info(rdata)); if (tsx->last_tx) { const char *serializer_name; @@ -402,21 +401,14 @@ static pj_bool_t distributor(pjsip_rx_data *rdata) if (serializer) { /* We have a serializer so we know where to send the message. */ } else if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG) { - ast_debug(3, "No dialog serializer for response %s. Using request transaction as basis\n", + ast_debug(3, "No dialog serializer for %s. Using request transaction as basis.\n", pjsip_rx_data_get_info(rdata)); serializer = find_request_serializer(rdata); if (!serializer) { - if (ast_taskprocessor_alert_get()) { - /* We're overloaded, ignore the unmatched response. */ - ast_debug(3, "Taskprocessor overload alert: Ignoring unmatched '%s'.\n", - pjsip_rx_data_get_info(rdata)); - return PJ_TRUE; - } - /* - * Pick a serializer for the unmatched response. Maybe - * the stack can figure out what it is for, or we really - * should just toss it regardless. + * Pick a serializer for the unmatched response. + * We couldn't determine what serializer originally + * sent the request or the serializer is gone. */ serializer = ast_sip_get_distributor_serializer(rdata); } @@ -462,35 +454,54 @@ static pj_bool_t distributor(pjsip_rx_data *rdata) return PJ_TRUE; } -static struct ast_sip_auth *artificial_auth; +static struct ast_sip_auth *alloc_artificial_auth(char *default_realm) +{ + struct ast_sip_auth *fake_auth; + + fake_auth = ast_sorcery_alloc(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, + "artificial"); + if (!fake_auth) { + return NULL; + } + + ast_string_field_set(fake_auth, realm, default_realm); + ast_string_field_set(fake_auth, auth_user, ""); + ast_string_field_set(fake_auth, auth_pass, ""); + fake_auth->type = AST_SIP_AUTH_TYPE_ARTIFICIAL; + + return fake_auth; +} + +static AO2_GLOBAL_OBJ_STATIC(artificial_auth); static int create_artificial_auth(void) { - if (!(artificial_auth = ast_sorcery_alloc( - ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, "artificial"))) { + char default_realm[MAX_REALM_LENGTH + 1]; + struct ast_sip_auth *fake_auth; + + ast_sip_get_default_realm(default_realm, sizeof(default_realm)); + fake_auth = alloc_artificial_auth(default_realm); + if (!fake_auth) { ast_log(LOG_ERROR, "Unable to create artificial auth\n"); return -1; } - ast_string_field_set(artificial_auth, realm, default_realm); - ast_string_field_set(artificial_auth, auth_user, ""); - ast_string_field_set(artificial_auth, auth_pass, ""); - artificial_auth->type = AST_SIP_AUTH_TYPE_ARTIFICIAL; + ao2_global_obj_replace_unref(artificial_auth, fake_auth); + ao2_ref(fake_auth, -1); return 0; } struct ast_sip_auth *ast_sip_get_artificial_auth(void) { - ao2_ref(artificial_auth, +1); - return artificial_auth; + return ao2_global_obj_ref(artificial_auth); } static struct ast_sip_endpoint *artificial_endpoint = NULL; static int create_artificial_endpoint(void) { - if (!(artificial_endpoint = ast_sorcery_alloc( - ast_sip_get_sorcery(), "endpoint", NULL))) { + artificial_endpoint = ast_sorcery_alloc(ast_sip_get_sorcery(), "endpoint", NULL); + if (!artificial_endpoint) { return -1; } @@ -760,7 +771,7 @@ static int distribute(void *data) .start_mod = &distributor_mod, .idx_after_start = 1, }; - pj_bool_t handled; + pj_bool_t handled = PJ_FALSE; pjsip_rx_data *rdata = data; int is_request = rdata->msg_info.msg->type == PJSIP_REQUEST_MSG; int is_ack = is_request ? rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD : 0; @@ -968,20 +979,40 @@ static int clean_task(const void *data) static void global_loaded(const char *object_type) { - char *identifier_order = ast_sip_get_endpoint_identifier_order(); - char *io_copy = identifier_order ? ast_strdupa(identifier_order) : NULL; - char *identify_method; - - ast_free(identifier_order); - using_auth_username = 0; - while ((identify_method = ast_strip(strsep(&io_copy, ",")))) { - if (!strcmp(identify_method, "auth_username")) { - using_auth_username = 1; - break; + 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_ref(fake_auth, -1); + } + } + ast_sip_get_unidentified_request_thresholds(&unidentified_count, &unidentified_period, &unidentified_prune_interval); /* Clean out the old task, if any */ @@ -1114,7 +1145,7 @@ void ast_sip_destroy_distributor(void) internal_sip_unregister_service(&endpoint_mod); internal_sip_unregister_service(&distributor_mod); - ao2_cleanup(artificial_auth); + ao2_global_obj_release(artificial_auth); ao2_cleanup(artificial_endpoint); ast_sorcery_observer_remove(ast_sip_get_sorcery(), "global", &global_observer); diff --git a/res/res_pjsip_authenticator_digest.c b/res/res_pjsip_authenticator_digest.c index 4bc35c5ff..ef57e3754 100644 --- a/res/res_pjsip_authenticator_digest.c +++ b/res/res_pjsip_authenticator_digest.c @@ -87,46 +87,46 @@ static void auth_store_cleanup(void *data) AST_THREADSTORAGE_CUSTOM(auth_store, NULL, auth_store_cleanup); /*! - * \brief Store authentication information in thread-local storage + * \brief Store shallow copy authentication information in thread-local storage */ -static int store_auth(struct ast_sip_auth *auth) +static int store_auth(const struct ast_sip_auth *auth) { - struct ast_sip_auth **pointing; + const struct ast_sip_auth **pointing; + pointing = ast_threadstorage_get(&auth_store, sizeof(pointing)); - if (!pointing || *pointing) { + if (!pointing) { return -1; } - ao2_ref(auth, +1); *pointing = auth; return 0; } /*! - * \brief Remove authentication information from thread-local storage + * \brief Remove shallow copy authentication information from thread-local storage */ static int remove_auth(void) { struct ast_sip_auth **pointing; + pointing = ast_threadstorage_get(&auth_store, sizeof(pointing)); if (!pointing) { return -1; } - ao2_cleanup(*pointing); *pointing = NULL; return 0; } /*! - * \brief Retrieve authentication information from thread-local storage + * \brief Retrieve shallow copy authentication information from thread-local storage */ -static struct ast_sip_auth *get_auth(void) +static const struct ast_sip_auth *get_auth(void) { struct ast_sip_auth **auth; + auth = ast_threadstorage_get(&auth_store, sizeof(auth)); - if (auth && *auth) { - ao2_ref(*auth, +1); + if (auth) { return *auth; } return NULL; @@ -150,7 +150,9 @@ static struct ast_sip_auth *get_auth(void) static pj_status_t digest_lookup(pj_pool_t *pool, const pj_str_t *realm, const pj_str_t *acc_name, pjsip_cred_info *info) { - RAII_VAR(struct ast_sip_auth *, auth, get_auth(), ao2_cleanup); + const struct ast_sip_auth *auth; + + auth = get_auth(); if (!auth) { return PJSIP_SC_FORBIDDEN; } @@ -312,7 +314,7 @@ enum digest_verify_result { * \return CMP_MATCH on successful authentication * \return 0 on failed authentication */ -static int verify(struct ast_sip_auth *auth, pjsip_rx_data *rdata, pj_pool_t *pool) +static int verify(const struct ast_sip_auth *auth, pjsip_rx_data *rdata, pj_pool_t *pool) { pj_status_t authed; int response_code; @@ -329,9 +331,7 @@ static int verify(struct ast_sip_auth *auth, pjsip_rx_data *rdata, pj_pool_t *po setup_auth_srv(pool, &auth_server, auth->realm); store_auth(auth); - authed = pjsip_auth_srv_verify(&auth_server, rdata, &response_code); - remove_auth(); if (authed == PJ_SUCCESS) { @@ -389,47 +389,88 @@ static enum ast_sip_check_auth_result digest_check_auth(struct ast_sip_endpoint pjsip_rx_data *rdata, pjsip_tx_data *tdata) { struct ast_sip_auth **auths; + struct ast_sip_auth **auths_shallow; enum digest_verify_result *verify_res; + struct ast_sip_endpoint *artificial_endpoint; enum ast_sip_check_auth_result res; - int i; + int idx; + int is_artificial; 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); + ast_assert(0 < auth_size); auths = ast_alloca(auth_size * sizeof(*auths)); verify_res = ast_alloca(auth_size * sizeof(*verify_res)); - if (!auths) { + artificial_endpoint = ast_sip_get_artificial_endpoint(); + if (!artificial_endpoint) { + /* Should not happen except possibly if we are shutting down. */ return AST_SIP_AUTHENTICATION_ERROR; } - if (endpoint == artificial_endpoint) { + is_artificial = endpoint == artificial_endpoint; + ao2_ref(artificial_endpoint, -1); + if (is_artificial) { + ast_assert(auth_size == 1); auths[0] = ast_sip_get_artificial_auth(); - } else if (ast_sip_retrieve_auths(&endpoint->inbound_auths, auths)) { - res = AST_SIP_AUTHENTICATION_ERROR; - goto cleanup; + if (!auths[0]) { + /* Should not happen except possibly if we are shutting down. */ + return AST_SIP_AUTHENTICATION_ERROR; + } + } else { + memset(auths, 0, auth_size * sizeof(*auths)); + 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, default_realm); + /* Setup shallow copy of auths */ + if (ast_strlen_zero(default_realm)) { + auths_shallow = auths; + } else { + /* + * Set default realm on a shallow copy of the authentication + * objects that don't have a realm set. + */ + auths_shallow = ast_alloca(auth_size * sizeof(*auths_shallow)); + for (idx = 0; idx < auth_size; ++idx) { + if (ast_strlen_zero(auths[idx]->realm)) { + /* + * Make a shallow copy and set the default realm on it. + * + * The stack allocation is OK here. Normally this will + * loop one time. If you have multiple auths then you + * shouldn't need more auths than the normal complement + * of fingers and toes. Otherwise, you should check + * your sanity for setting up your system up that way. + */ + auths_shallow[idx] = ast_alloca(sizeof(**auths_shallow)); + memcpy(auths_shallow[idx], auths[idx], sizeof(**auths_shallow)); + *((char **) (&auths_shallow[idx]->realm)) = default_realm; + ast_debug(3, "Using default realm '%s' on incoming auth '%s'.\n", + default_realm, ast_sorcery_object_get_id(auths_shallow[idx])); + } else { + auths_shallow[idx] = auths[idx]; + } } - verify_res[i] = verify(auths[i], rdata, tdata->pool); - if (verify_res[i] == AUTH_SUCCESS) { + } + + for (idx = 0; idx < auth_size; ++idx) { + verify_res[idx] = verify(auths_shallow[idx], rdata, tdata->pool); + if (verify_res[idx] == AUTH_SUCCESS) { res = AST_SIP_AUTHENTICATION_SUCCESS; goto cleanup; } - if (verify_res[i] == AUTH_FAIL) { + if (verify_res[idx] == AUTH_FAIL) { failures++; } } - for (i = 0; i < auth_size; ++i) { - challenge(auths[i]->realm, tdata, rdata, verify_res[i] == AUTH_STALE); + for (idx = 0; idx < auth_size; ++idx) { + challenge(auths_shallow[idx]->realm, tdata, rdata, verify_res[idx] == AUTH_STALE); } if (failures == auth_size) { diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c index 87680480c..53eb6aca7 100644 --- a/res/res_pjsip_outbound_publish.c +++ b/res/res_pjsip_outbound_publish.c @@ -55,7 +55,18 @@ <synopsis>Expiration time for publications in seconds</synopsis> </configOption> <configOption name="outbound_auth" default=""> - <synopsis>Authentication object to be used for outbound publishes.</synopsis> + <synopsis>Authentication object(s) to be used for outbound publishes.</synopsis> + <description><para> + This is a comma-delimited list of <replaceable>auth</replaceable> + sections defined in <filename>pjsip.conf</filename> used to respond + to outbound authentication challenges.</para> + <note><para> + Using the same auth section for inbound and outbound + authentication is not recommended. There is a difference in + meaning for an empty realm setting between inbound and outbound + authentication uses. See the auth realm description for details. + </para></note> + </description> </configOption> <configOption name="outbound_proxy" default=""> <synopsis>SIP URI of the outbound proxy used to send publishes</synopsis> diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index d486ccd63..137f3a832 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -82,7 +82,18 @@ <synopsis>Maximum number of registration attempts.</synopsis> </configOption> <configOption name="outbound_auth" default=""> - <synopsis>Authentication object to be used for outbound registrations.</synopsis> + <synopsis>Authentication object(s) to be used for outbound registrations.</synopsis> + <description><para> + This is a comma-delimited list of <replaceable>auth</replaceable> + sections defined in <filename>pjsip.conf</filename> used to respond + to outbound authentication challenges.</para> + <note><para> + Using the same auth section for inbound and outbound + authentication is not recommended. There is a difference in + meaning for an empty realm setting between inbound and outbound + authentication uses. See the auth realm description for details. + </para></note> + </description> </configOption> <configOption name="outbound_proxy" default=""> <synopsis>Outbound Proxy used to send registrations</synopsis> diff --git a/third-party/pjproject/patches/0011-r5554-svn-backport-Increase-SENDER_WIDTH-column-size.patch b/third-party/pjproject/patches/0011-r5554-svn-backport-Increase-SENDER_WIDTH-column-size.patch new file mode 100644 index 000000000..4c53337a3 --- /dev/null +++ b/third-party/pjproject/patches/0011-r5554-svn-backport-Increase-SENDER_WIDTH-column-size.patch @@ -0,0 +1,77 @@ +From df1ceb301c8a17969c467e3cf00246cfc28d1732 Mon Sep 17 00:00:00 2001 +From: Richard Mudgett <rmudgett@digium.com> +Date: Mon, 20 Feb 2017 12:19:05 -0600 +Subject: [PATCH 1/5] r5554 svn backport Increase SENDER_WIDTH column size for + 64-bit systems. + +Re #1994 (misc): Make the log's sender and thread width a compile-time configurable setting. + +Thanks to Richard Mudgett for the suggestion. +--- + pjlib/include/pj/config.h | 27 +++++++++++++++++++++++++++ + pjlib/src/pj/log.c | 4 ++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/pjlib/include/pj/config.h b/pjlib/include/pj/config.h +index 079d69b..3523f50 100644 +--- a/pjlib/include/pj/config.h ++++ b/pjlib/include/pj/config.h +@@ -442,6 +442,33 @@ + #endif + + /** ++ * Log sender width. ++ * ++ * Default: 22 (for 64-bit machines), 14 otherwise ++ */ ++#ifndef PJ_LOG_SENDER_WIDTH ++# if PJ_HAS_STDINT_H ++# include <stdint.h> ++# if (UINTPTR_MAX == 0xffffffffffffffff) ++# define PJ_LOG_SENDER_WIDTH 22 ++# else ++# define PJ_LOG_SENDER_WIDTH 14 ++# endif ++# else ++# define PJ_LOG_SENDER_WIDTH 14 ++# endif ++#endif ++ ++/** ++ * Log thread name width. ++ * ++ * Default: 12 ++ */ ++#ifndef PJ_LOG_THREAD_WIDTH ++# define PJ_LOG_THREAD_WIDTH 12 ++#endif ++ ++/** + * Colorfull terminal (for logging etc). + * + * Default: 1 +diff --git a/pjlib/src/pj/log.c b/pjlib/src/pj/log.c +index 293ad46..cf7ac37 100644 +--- a/pjlib/src/pj/log.c ++++ b/pjlib/src/pj/log.c +@@ -380,7 +380,7 @@ PJ_DEF(void) pj_log( const char *sender, int level, + pre += pj_utoa_pad(ptime.msec, pre, 3, '0'); + } + if (log_decor & PJ_LOG_HAS_SENDER) { +- enum { SENDER_WIDTH = 14 }; ++ enum { SENDER_WIDTH = PJ_LOG_SENDER_WIDTH }; + pj_size_t sender_len = strlen(sender); + if (pre!=log_buffer) *pre++ = ' '; + if (sender_len <= SENDER_WIDTH) { +@@ -395,7 +395,7 @@ PJ_DEF(void) pj_log( const char *sender, int level, + } + } + if (log_decor & PJ_LOG_HAS_THREAD_ID) { +- enum { THREAD_WIDTH = 12 }; ++ enum { THREAD_WIDTH = PJ_LOG_THREAD_WIDTH }; + const char *thread_name = pj_thread_get_name(pj_thread_this()); + pj_size_t thread_len = strlen(thread_name); + *pre++ = ' '; +-- +2.7.4 + diff --git a/third-party/pjproject/patches/0012-Re-1945-misc-Don-t-trigger-SRV-complete-callback-whe.patch b/third-party/pjproject/patches/0012-Re-1945-misc-Don-t-trigger-SRV-complete-callback-whe.patch new file mode 100644 index 000000000..e65556f22 --- /dev/null +++ b/third-party/pjproject/patches/0012-Re-1945-misc-Don-t-trigger-SRV-complete-callback-whe.patch @@ -0,0 +1,59 @@ +From 783de8956190c47a70ffefed56a1a2b21a62b235 Mon Sep 17 00:00:00 2001 +From: Riza Sulistyo <riza@teluu.com> +Date: Mon, 23 Jan 2017 01:34:12 +0000 +Subject: [PATCH 2/5] Re #1945 (misc): Don't trigger SRV complete callback when + there is a parse error. + +git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@5536 74dad513-b988-da41-8d7b-12977e46ad98 +--- + pjlib-util/src/pjlib-util/srv_resolver.c | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/pjlib-util/src/pjlib-util/srv_resolver.c b/pjlib-util/src/pjlib-util/srv_resolver.c +index 8a4a599..8a2f7e1 100644 +--- a/pjlib-util/src/pjlib-util/srv_resolver.c ++++ b/pjlib-util/src/pjlib-util/srv_resolver.c +@@ -652,6 +652,7 @@ static void dns_callback(void *user_data, + + } else if (query_job->dns_state == PJ_DNS_TYPE_A) { + pj_bool_t is_type_a, srv_completed; ++ pj_dns_addr_record rec; + + /* Clear outstanding job */ + if (common->type == PJ_DNS_TYPE_A) { +@@ -668,15 +669,26 @@ static void dns_callback(void *user_data, + + is_type_a = (common->type == PJ_DNS_TYPE_A); + ++ /* Parse response */ ++ if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { ++ status = pj_dns_parse_addr_response(pkt, &rec); ++ if (status!=PJ_SUCCESS) { ++ char errmsg[PJ_ERR_MSG_SIZE]; ++ ++ PJ_LOG(4,(query_job->objname, ++ "DNS %s record parse error for '%.*s'." ++ " Err=%d (%s)", ++ (is_type_a ? "A" : "AAAA"), ++ (int)query_job->domain_part.slen, ++ query_job->domain_part.ptr, ++ status, ++ pj_strerror(status,errmsg,sizeof(errmsg)).ptr)); ++ } ++ } ++ + /* Check that we really have answer */ + if (status==PJ_SUCCESS && pkt->hdr.anscount != 0) { + char addr[PJ_INET6_ADDRSTRLEN]; +- pj_dns_addr_record rec; +- +- /* Parse response */ +- status = pj_dns_parse_addr_response(pkt, &rec); +- if (status != PJ_SUCCESS) +- goto on_error; + + pj_assert(rec.addr_count != 0); + +-- +2.7.4 + diff --git a/third-party/pjproject/patches/0013-r5559-svn-backport-Fix-to-resolve-DNS-SRV-crashes.patch b/third-party/pjproject/patches/0013-r5559-svn-backport-Fix-to-resolve-DNS-SRV-crashes.patch new file mode 100644 index 000000000..dc03cbc20 --- /dev/null +++ b/third-party/pjproject/patches/0013-r5559-svn-backport-Fix-to-resolve-DNS-SRV-crashes.patch @@ -0,0 +1,112 @@ +From d9d52f005f6d0242ea84e7c59ad6b25f052c8485 Mon Sep 17 00:00:00 2001 +From: Richard Mudgett <rmudgett@digium.com> +Date: Mon, 20 Feb 2017 12:05:32 -0600 +Subject: [PATCH 3/5] r5559 svn backport Fix to resolve DNS SRV crashes. + +Re #1994 (misc): Don't try to resolve a DNS SRV query that is already considered resolved. +Thanks to Richard Mudgett for the patch. + +srv_resolver.c: Don't try to send query if already considered resolved. + +* In resolve_hostnames() don't try to resolve a query that is already +considered resolved. + +* In resolve_hostnames() fix DNS typo in comments. + +* In build_server_entries() move a common expression assigning to cnt +earlier. + +sip_transport.c: Fix tdata object name to actually contain the pointer. + +It helps if the logs referencing a tdata object buffer actually have +a name that includes the correct pointer as part of the name. Also +since the tdata has its own pool it helps if any logs referencing the +pool have the same name as the tdata object. This change brings tdata +logging in line with how tsx objects are named. +--- + pjlib-util/src/pjlib-util/srv_resolver.c | 18 +++++++++++++----- + pjsip/src/pjsip/sip_transport.c | 3 ++- + 2 files changed, 15 insertions(+), 6 deletions(-) + +diff --git a/pjlib-util/src/pjlib-util/srv_resolver.c b/pjlib-util/src/pjlib-util/srv_resolver.c +index 8a2f7e1..84ad3f6 100644 +--- a/pjlib-util/src/pjlib-util/srv_resolver.c ++++ b/pjlib-util/src/pjlib-util/srv_resolver.c +@@ -407,8 +407,9 @@ static void build_server_entries(pj_dns_srv_async_query *query_job, + for (i=0; i<query_job->srv_cnt; ++i) { + pj_in_addr addr; + pj_in6_addr addr6; ++ unsigned cnt = query_job->srv[i].addr_cnt; + +- if (query_job->srv[i].addr_cnt != 0) { ++ if (cnt != 0) { + /* IP address already resolved */ + continue; + } +@@ -417,7 +418,6 @@ static void build_server_entries(pj_dns_srv_async_query *query_job, + pj_inet_pton(pj_AF_INET(), &query_job->srv[i].target_name, + &addr) == PJ_SUCCESS) + { +- unsigned cnt = query_job->srv[i].addr_cnt; + pj_sockaddr_init(pj_AF_INET(), &query_job->srv[i].addr[cnt], + NULL, query_job->srv[i].port); + query_job->srv[i].addr[cnt].ipv4.sin_addr = addr; +@@ -427,7 +427,6 @@ static void build_server_entries(pj_dns_srv_async_query *query_job, + pj_inet_pton(pj_AF_INET6(), &query_job->srv[i].target_name, + &addr6) == PJ_SUCCESS) + { +- unsigned cnt = query_job->srv[i].addr_cnt; + pj_sockaddr_init(pj_AF_INET6(), &query_job->srv[i].addr[cnt], + NULL, query_job->srv[i].port); + query_job->srv[i].addr[cnt].ipv6.sin6_addr = addr6; +@@ -480,6 +479,15 @@ static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) + for (i=0; i<query_job->srv_cnt; ++i) { + struct srv_target *srv = &query_job->srv[i]; + ++ if (srv->addr_cnt != 0) { ++ /* ++ * This query is already counted as resolved because of the ++ * additional records in the SRV response or the target name ++ * is an IP address exception in build_server_entries(). ++ */ ++ continue; ++ } ++ + PJ_LOG(5, (query_job->objname, + "Starting async DNS A query_job for %.*s", + (int)srv->target_name.slen, +@@ -493,7 +501,7 @@ static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) + + status = PJ_SUCCESS; + +- /* Start DNA A record query */ ++ /* Start DNS A record query */ + if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA_ONLY) == 0) + { + if ((query_job->option & PJ_DNS_SRV_RESOLVE_AAAA) != 0) { +@@ -511,7 +519,7 @@ static pj_status_t resolve_hostnames(pj_dns_srv_async_query *query_job) + &srv->common, &srv->q_a); + } + +- /* Start DNA AAAA record query */ ++ /* Start DNS AAAA record query */ + if (status == PJ_SUCCESS && + (query_job->option & PJ_DNS_SRV_RESOLVE_AAAA) != 0) + { +diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c +index d672a6d..6dd14d1 100644 +--- a/pjsip/src/pjsip/sip_transport.c ++++ b/pjsip/src/pjsip/sip_transport.c +@@ -422,7 +422,8 @@ PJ_DEF(pj_status_t) pjsip_tx_data_create( pjsip_tpmgr *mgr, + tdata = PJ_POOL_ZALLOC_T(pool, pjsip_tx_data); + tdata->pool = pool; + tdata->mgr = mgr; +- pj_memcpy(tdata->obj_name, pool->obj_name, PJ_MAX_OBJ_NAME); ++ pj_ansi_snprintf(tdata->obj_name, sizeof(tdata->obj_name), "tdta%p", tdata); ++ pj_memcpy(pool->obj_name, tdata->obj_name, sizeof(pool->obj_name)); + + status = pj_atomic_create(tdata->pool, 0, &tdata->ref_cnt); + if (status != PJ_SUCCESS) { +-- +2.7.4 + |