]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
pjsip: Update ACLs on named ACL changes.
authorJoshua C. Colp <jcolp@sangoma.com>
Tue, 18 Feb 2020 13:10:16 +0000 (13:10 +0000)
committerJoshua Colp <jcolp@sangoma.com>
Thu, 20 Feb 2020 10:52:03 +0000 (04:52 -0600)
This change extends the Sorcery API to allow a wizard to be
told to explicitly reload objects or a specific object type
even if the wizard believes that nothing has changed.

This has been leveraged by res_pjsip and res_pjsip_acl to
reload endpoints and PJSIP ACLs when a named ACL changes.

ASTERISK-28697

Change-Id: Ib8fee9bd9dd490db635132c479127a4114c1ca0b

include/asterisk/sorcery.h
main/sorcery.c
res/res_pjsip/pjsip_configuration.c
res/res_pjsip_acl.c
res/res_sorcery_config.c

index 3a0e1b81a5c75d6e99c8bc3294e89c0f003d91ed..a0ec6535845948dc36469cd344f4ce774368694a 100644 (file)
@@ -323,6 +323,9 @@ struct ast_sorcery_wizard {
 
        /* \brief Callback for whether or not the wizard believes the object is stale */
        int (*is_stale)(const struct ast_sorcery *sorcery, void *data, void *object);
+
+       /*! \brief Optional callback for forcing a reload to occur, even if wizard has determined no changes */
+       void (*force_reload)(void *data, const struct ast_sorcery *sorcery, const char *type);
 };
 
 /*! \brief Interface for a sorcery object type observer */
@@ -1059,6 +1062,17 @@ void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type
  */
 void ast_sorcery_reload(const struct ast_sorcery *sorcery);
 
+/*!
+ * \brief Inform any wizards to reload persistent objects, even if no changes determined
+ *
+ * \param sorcery Pointer to a sorcery structure
+ *
+ * \since 13.32.0
+ * \since 16.9.0
+ * \since 17.3.0
+ */
+void ast_sorcery_force_reload(const struct ast_sorcery *sorcery);
+
 /*!
  * \brief Inform any wizards of a specific object type to reload persistent objects
  *
@@ -1067,6 +1081,19 @@ void ast_sorcery_reload(const struct ast_sorcery *sorcery);
  */
 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type);
 
+/*!
+ * \brief Inform any wizards of a specific object type to reload persistent objects
+ *        even if no changes determined
+ *
+ * \param sorcery Pointer to a sorcery structure
+ * \param type Name of the object type to reload
+ *
+ * \since 13.32.0
+ * \since 16.9.0
+ * \since 17.3.0
+ */
+void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type);
+
 /*!
  * \brief Increase the reference count of a sorcery structure
  *
index d8378457111225c34258665e4eb73ac055df80fb..0ada81e3f71b931a83a1e0390816098ce70602a6 100644 (file)
@@ -245,6 +245,9 @@ struct sorcery_load_details {
 
        /*! \brief Whether this is a reload or not */
        unsigned int reload:1;
+
+       /*! \brief Whether this is forced or not */
+       unsigned int force:1;
 };
 
 /*! \brief Registered sorcery wizards */
@@ -1250,7 +1253,15 @@ static int sorcery_wizard_load(void *obj, void *arg, int flags)
        struct sorcery_load_details *details = arg;
        void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
 
-       load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload;
+       if (details->reload) {
+               if (details->force && wizard->wizard->callbacks.force_reload) {
+                       load = wizard->wizard->callbacks.force_reload;
+               } else {
+                       load = wizard->wizard->callbacks.reload;
+               }
+       } else {
+               load = wizard->wizard->callbacks.load;
+       }
 
        if (load) {
                NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
@@ -1408,6 +1419,23 @@ void ast_sorcery_reload(const struct ast_sorcery *sorcery)
 
 }
 
+void ast_sorcery_force_reload(const struct ast_sorcery *sorcery)
+{
+       struct sorcery_load_details details = {
+               .sorcery = sorcery,
+               .reload = 1,
+               .force = 1,
+       };
+
+       NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
+               sorcery->module_name, sorcery, 1);
+
+       ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
+
+       NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
+               sorcery->module_name, sorcery, 1);
+}
+
 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
 {
        RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
@@ -1423,6 +1451,22 @@ void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *ty
        sorcery_object_load(object_type, &details, 0);
 }
 
+void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
+{
+       RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+       struct sorcery_load_details details = {
+               .sorcery = sorcery,
+               .reload = 1,
+               .force = 1,
+       };
+
+       if (!object_type) {
+               return;
+       }
+
+       sorcery_object_load(object_type, &details, 0);
+}
+
 void ast_sorcery_ref(struct ast_sorcery *sorcery)
 {
        ao2_ref(sorcery, +1);
index 355b5957dba9c8bde4c1126ccbbdc3209be04c1b..8d5b5a85073c86db77491acd34e13c5ccc423f21 100644 (file)
@@ -34,6 +34,8 @@
 #include "asterisk/statsd.h"
 #include "asterisk/pbx.h"
 #include "asterisk/stream.h"
+#include "asterisk/stasis.h"
+#include "asterisk/security_events.h"
 
 /*! \brief Number of buckets for persistent endpoint information */
 #define PERSISTENT_BUCKETS 53
@@ -49,6 +51,8 @@ static struct ao2_container *persistent_endpoints;
 
 static struct ast_sorcery *sip_sorcery;
 
+static struct stasis_subscription *acl_change_sub;
+
 /*! \brief Hashing function for persistent endpoint information */
 static int persistent_endpoint_hash(const void *obj, const int flags)
 {
@@ -1787,6 +1791,16 @@ static void load_all_endpoints(void)
        ao2_cleanup(endpoints);
 }
 
+static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub,
+       struct stasis_message *message)
+{
+       if (stasis_message_type(message) != ast_named_acl_change_type()) {
+               return;
+       }
+
+       ast_sorcery_force_reload_object(sip_sorcery, "endpoint");
+}
+
 int ast_res_pjsip_initialize_configuration(void)
 {
        if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) ||
@@ -2007,6 +2021,10 @@ int ast_res_pjsip_initialize_configuration(void)
 
        ast_sip_location_prune_boot_contacts();
 
+       acl_change_sub = stasis_subscribe(ast_security_topic(), acl_change_stasis_cb, NULL);
+       stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type());
+       stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
+
        return 0;
 }
 
@@ -2016,6 +2034,7 @@ void ast_res_pjsip_destroy_configuration(void)
                return;
        }
 
+       acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
        ast_sip_destroy_sorcery_global();
        ast_sip_destroy_sorcery_location();
        ast_sip_destroy_sorcery_auth();
index 8caf70344a775bf03c95c35a6ba4ed2e01ddf39d..3bf0f6fe6094b317cce6fe2079bf5e2d38cfc2a3 100644 (file)
@@ -31,6 +31,8 @@
 #include "asterisk/logger.h"
 #include "asterisk/sorcery.h"
 #include "asterisk/acl.h"
+#include "asterisk/stasis.h"
+#include "asterisk/security_events.h"
 
 /*** DOCUMENTATION
        <configInfo name="res_pjsip_acl" language="en_US">
        </configInfo>
  ***/
 
+static struct stasis_subscription *acl_change_sub;
+
 static int apply_acl(pjsip_rx_data *rdata, struct ast_acl_list *acl)
 {
        struct ast_sockaddr addr;
@@ -280,6 +284,16 @@ static void *acl_alloc(const char *name)
        return sip_acl;
 }
 
+static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub,
+       struct stasis_message *message)
+{
+       if (stasis_message_type(message) != ast_named_acl_change_type()) {
+               return;
+       }
+
+       ast_sorcery_force_reload_object(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
+}
+
 static int load_module(void)
 {
        ast_sorcery_apply_config(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
@@ -304,12 +318,18 @@ static int load_module(void)
 
        ast_sorcery_load_object(ast_sip_get_sorcery(), SIP_SORCERY_ACL_TYPE);
 
+       acl_change_sub = stasis_subscribe(ast_security_topic(), acl_change_stasis_cb, NULL);
+       stasis_subscription_accept_message_type(acl_change_sub, ast_named_acl_change_type());
+       stasis_subscription_set_filter(acl_change_sub, STASIS_SUBSCRIPTION_FILTER_SELECTIVE);
+
        ast_sip_register_service(&acl_module);
+
        return AST_MODULE_LOAD_SUCCESS;
 }
 
 static int unload_module(void)
 {
+       acl_change_sub = stasis_unsubscribe_and_join(acl_change_sub);
        ast_sip_unregister_service(&acl_module);
        return 0;
 }
index 8e5ee205a8de2c0d30da24b3b4623ee6f24d2e16..602978924cf24373a6bf40e2abd0124ccfce33cd 100644 (file)
@@ -103,6 +103,7 @@ static struct ast_sorcery_wizard config_object_wizard = {
        .open = sorcery_config_open,
        .load = sorcery_config_load,
        .reload = sorcery_config_reload,
+       .force_reload = sorcery_config_load,
        .retrieve_id = sorcery_config_retrieve_id,
        .retrieve_fields = sorcery_config_retrieve_fields,
        .retrieve_multiple = sorcery_config_retrieve_multiple,