diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 0fff4b140177b2bd9f46993490e2ac99dcfdedc4..2627e0977e0133efa1eca46c4170d177b4a9bef4 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -12770,8 +12770,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct ast_variable *v, *tmpvar; for (v = conf->chan.vars ; v ; v = v->next) { if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { - tmpvar->next = tmp->vars; - tmp->vars = tmpvar; + if (ast_variable_list_replace(&tmp->vars, tmpvar)) { + tmpvar->next = tmp->vars; + tmp->vars = tmpvar; + } } } } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index add593d9b2a03ed09f9c7992f0ffb7a048489f4c..db4bef31bfa1059b0281ebbd5360a98ed3ca40d1 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -7916,9 +7916,11 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i /* We found our match (use the first) */ /* copy vars */ for (v = user->vars ; v ; v = v->next) { - if((tmpvar = ast_variable_new(v->name, v->value, v->file))) { - tmpvar->next = iaxs[callno]->vars; - iaxs[callno]->vars = tmpvar; + if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) { + if (ast_variable_list_replace(&iaxs[callno]->vars, tmpvar)) { + tmpvar->next = iaxs[callno]->vars; + iaxs[callno]->vars = tmpvar; + } } } /* If a max AUTHREQ restriction is in place, activate it */ @@ -13179,9 +13181,11 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st if ((varval = strchr(varname, '='))) { *varval = '\0'; varval++; - if((tmpvar = ast_variable_new(varname, varval, ""))) { - tmpvar->next = user->vars; - user->vars = tmpvar; + if ((tmpvar = ast_variable_new(varname, varval, ""))) { + if (ast_variable_list_replace(&user->vars, tmpvar)) { + tmpvar->next = user->vars; + user->vars = tmpvar; + } } } } else if (!strcasecmp(v->name, "allow")) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 9f01b515fd728214766454877ab368cffdd253e1..80040aee42172955d8cedb8c2c820b39708e433f 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -31366,8 +31366,10 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list) if ((varval = strchr(varname, '='))) { *varval++ = '\0'; if ((tmpvar = ast_variable_new(varname, varval, ""))) { - tmpvar->next = list; - list = tmpvar; + if (ast_variable_list_replace(&list, tmpvar)) { + tmpvar->next = list; + list = tmpvar; + } } } return list; diff --git a/include/asterisk/config.h b/include/asterisk/config.h index 9908b905beabdb6c8e8a34f7818b95d68c036cd1..1775dfe53ccd5b7b34305809ed8198b0d8fbe515 100644 --- a/include/asterisk/config.h +++ b/include/asterisk/config.h @@ -948,6 +948,24 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s struct ast_variable *new_var); #define ast_variable_list_append(head, new_var) ast_variable_list_append_hint(head, NULL, new_var) +/*! + * \brief Replace a variable in the given list with a new value + * \since 13.30.0 + * + * \param head A pointer to an ast_variable * of the existing variable list head. May NOT be NULL + * but the content may be to initialize a new list. If so, upon return, this parameter will be updated + * with a pointer to the new list head. + * \param replacement The variable that replaces another variable in the list with the + * same name. + * + * \retval 0 if a variable was replaced in the list + * \retval -1 if no replacement occured + * + * \note The variable name comparison is performed case-sensitively + * \note If a variable is replaced, its memory is freed. + */ +int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement); + /*! * \brief Update variable value within a config * diff --git a/main/config.c b/main/config.c index 5660fbe963e39f785bf75b1093faebfc0220ffba..002ae2fc9966546515946cff2ac8e378017a4373 100644 --- a/main/config.c +++ b/main/config.c @@ -665,6 +665,22 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s return curr; } +int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement) +{ + struct ast_variable *v, **prev = head; + + for (v = *head; v; prev = &v->next, v = v->next) { + if (!strcmp(v->name, replacement->name)) { + replacement->next = v->next; + *prev = replacement; + ast_free(v); + return 0; + } + } + + return -1; +} + const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var) { const char *tmp; diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 050073b80a36dacd99355ada2b8ca1f9e2f3a3e7..355b5957dba9c8bde4c1126ccbbdc3209be04c1b 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1044,7 +1044,9 @@ static int set_var_handler(const struct aco_option *opt, return -1; } - ast_variable_list_append(&endpoint->channel_vars, new_var); + if (ast_variable_list_replace(&endpoint->channel_vars, new_var)) { + ast_variable_list_append(&endpoint->channel_vars, new_var); + } return 0; }