]> jfr.im git - solanum.git/blobdiff - ircd/modules.c
ircd/authproc.c: avoid crash on lack of any configured DNSBLs
[solanum.git] / ircd / modules.c
index ffa080774146376b07134bf55a4b37334bda5445..bf010cb2735498b76dbcec3beab21df45bb36d16 100644 (file)
 #include "match.h"
 #include "s_serv.h"
 #include "capability.h"
+#include "hash.h"
 
 #include <ltdl.h>
 
 #ifndef LT_MODULE_EXT
-#      error "Charybdis requires loadable module support."
+#      error "Solanum requires loadable module support."
 #endif
 
 rb_dlink_list module_list;
@@ -50,6 +51,7 @@ static const char *core_module_table[] = {
        "m_ban",
        "m_die",
        "m_error",
+       "m_identified",
        "m_join",
        "m_kick",
        "m_kill",
@@ -80,6 +82,29 @@ init_modules(void)
        mod_add_path(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
 }
 
+static unsigned int prev_caps;
+
+void
+mod_remember_clicaps(void)
+{
+       prev_caps = capability_index_mask(cli_capindex);
+}
+
+void
+mod_notify_clicaps(void)
+{
+       unsigned int cur_caps = capability_index_mask(cli_capindex);
+       unsigned int del = prev_caps & ~cur_caps;
+       unsigned int new = cur_caps & ~prev_caps;
+
+       if (del)
+               sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s",
+                               me.name, capability_index_list(cli_capindex, del));
+       if (new)
+               sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :%s",
+                               me.name, capability_index_list(cli_capindex, new));
+}
+
 /* mod_find_path()
  *
  * input       - path
@@ -200,8 +225,8 @@ load_all_modules(bool warn)
                if(len > module_ext_len &&
                        rb_strncasecmp(ldirent->d_name + (len - module_ext_len), LT_MODULE_EXT, module_ext_len) == 0)
                {
-                       (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s%c%s",
-                                       ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], RB_PATH_SEPARATOR, ldirent->d_name);
+                       (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
+                                       ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], ldirent->d_name);
                        (void) load_a_module(module_fq_name, warn, MAPI_ORIGIN_CORE, false);
                }
 
@@ -224,8 +249,7 @@ load_core_modules(bool warn)
 
        for (i = 0; core_module_table[i]; i++)
        {
-               snprintf(module_name, sizeof(module_name), "%s%c%s", ircd_paths[IRCD_PATH_MODULES], RB_PATH_SEPARATOR,
-                           core_module_table[i]);
+               snprintf(module_name, sizeof(module_name), "%s/%s", ircd_paths[IRCD_PATH_MODULES], core_module_table[i]);
 
                if(load_a_module(module_name, warn, MAPI_ORIGIN_CORE, true) == false)
                {
@@ -260,7 +284,7 @@ load_one_module(const char *path, int origin, bool coremodule)
                struct stat statbuf;
                const char *mpath = pathst->data;
 
-               snprintf(modpath, sizeof(modpath), "%s%c%s%s", mpath, RB_PATH_SEPARATOR, path, LT_MODULE_EXT);
+               snprintf(modpath, sizeof(modpath), "%s/%s%s", mpath, path, LT_MODULE_EXT);
                if((strstr(modpath, "../") == NULL) && (strstr(modpath, "/..") == NULL))
                {
                        if(stat(modpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
@@ -272,7 +296,11 @@ load_one_module(const char *path, int origin, bool coremodule)
                }
        }
 
-       sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
+       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Cannot locate module %s", path);
+
+       if (server_state_foreground)
+               ierror("cannot locate module %s", path);
+
        return false;
 }
 
@@ -294,9 +322,6 @@ unload_one_module(const char *name, bool warn)
        if((mod = findmodule_byname(name)) == NULL)
                return false;
 
-       if(mod->core)
-               return false;
-
        /*
         ** XXX - The type system in C does not allow direct conversion between
         ** data and function pointers, but as it happens, most C compilers will
@@ -375,7 +400,7 @@ unload_one_module(const char *name, bool warn)
                                                idx = serv_capindex;
                                                break;
                                        default:
-                                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                                        "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
                                                        m->cap_index, m->cap_name, mod->name);
                                                ilog(L_MAIN,
@@ -384,17 +409,13 @@ unload_one_module(const char *name, bool warn)
                                                continue;
                                        }
 
-                                       if (m->cap_id != NULL)
-                                       {
-                                               capability_orphan(idx, m->cap_name);
-                                               sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s", me.name, m->cap_name);
-                                       }
+                                       capability_orphan(idx, m->cap_name);
                                }
                        }
                        break;
                }
        default:
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Unknown/unsupported MAPI version %d when unloading %s!",
                                     mod->mapi_version, mod->name);
                ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
@@ -406,12 +427,13 @@ unload_one_module(const char *name, bool warn)
 
        rb_dlinkDelete(&mod->node, &module_list);
        rb_free(mod->name);
+       rb_free(mod->path);
        rb_free(mod);
 
        if(warn)
        {
                ilog(L_MAIN, "Module %s unloaded", name);
-               sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Module %s unloaded", name);
        }
 
        return true;
@@ -431,7 +453,6 @@ load_a_module(const char *path, bool warn, int origin, bool core)
        lt_dlhandle tmpptr;
        char *mod_displayname, *c;
        const char *ver, *description = NULL;
-       size_t module_ext_len = strlen(LT_MODULE_EXT);
 
        int *mapi_version;
 
@@ -447,7 +468,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
        {
                const char *err = lt_dlerror();
 
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Error loading module %s: %s", mod_displayname, err);
                ilog(L_MAIN, "Error loading module %s: %s", mod_displayname, err);
                rb_free(mod_displayname);
@@ -465,7 +486,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
            && (mapi_version = (int *) (uintptr_t) lt_dlsym(tmpptr, "__mheader")) == NULL)
           || MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
        {
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Data format error: module %s has no MAPI header.",
                                     mod_displayname);
                ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_displayname);
@@ -483,7 +504,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
                        {
                                ilog(L_MAIN, "Module %s indicated failure during load.",
                                     mod_displayname);
-                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                                     "Module %s indicated failure during load.",
                                                     mod_displayname);
                                lt_dlclose(tmpptr);
@@ -518,14 +539,66 @@ load_a_module(const char *path, bool warn, int origin, bool core)
                {
                        struct mapi_mheader_av2 *mheader = (struct mapi_mheader_av2 *)(void *)mapi_version;     /* see above */
 
+                       if(mheader->mapi_cap_list)
+                       {
+                               mapi_cap_list_av2 *m;
+                               for (m = mheader->mapi_cap_list; m->cap_name; ++m)
+                               {
+                                       struct CapabilityIndex *idx;
+                                       int result;
+
+                                       switch (m->cap_index)
+                                       {
+                                       case MAPI_CAP_CLIENT:
+                                               idx = cli_capindex;
+                                               break;
+                                       case MAPI_CAP_SERVER:
+                                               idx = serv_capindex;
+                                               break;
+                                       default:
+                                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
+                                                       "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
+                                                       m->cap_index, m->cap_name, mod_displayname);
+                                               ilog(L_MAIN,
+                                                       "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
+                                                       m->cap_index, m->cap_name, mod_displayname);
+                                               continue;
+                                       }
+
+                                       result = capability_put(idx, m->cap_name, m->cap_ownerdata);
+                                       if (m->cap_id != NULL)
+                                               *(m->cap_id) = result;
+                               }
+                       }
+
                        /* XXX duplicated code :( */
                        if(mheader->mapi_register && (mheader->mapi_register() == -1))
                        {
                                ilog(L_MAIN, "Module %s indicated failure during load.",
                                        mod_displayname);
-                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                                     "Module %s indicated failure during load.",
                                                     mod_displayname);
+                               if(mheader->mapi_cap_list)
+                               {
+                                       mapi_cap_list_av2 *m;
+                                       for (m = mheader->mapi_cap_list; m->cap_name; ++m)
+                                       {
+                                               struct CapabilityIndex *idx;
+                                               switch (m->cap_index)
+                                               {
+                                               case MAPI_CAP_CLIENT:
+                                                       idx = cli_capindex;
+                                                       break;
+                                               case MAPI_CAP_SERVER:
+                                                       idx = serv_capindex;
+                                                       break;
+                                               default:
+                                                       continue;
+                                               }
+                                               capability_orphan(idx, m->cap_name);
+                                       }
+                               }
                                lt_dlclose(tmpptr);
                                rb_free(mod_displayname);
                                return false;
@@ -545,7 +618,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
                                        delta /= 86400;
                                        iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems",
                                                mod_displayname, delta);
-                                       sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                                "Module %s build date is out of sync with ircd build date by %ld days, expect problems",
                                                mod_displayname, delta);
                                }
@@ -569,54 +642,24 @@ load_a_module(const char *path, bool warn, int origin, bool core)
                        {
                                mapi_hfn_list_av1 *m;
                                for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
-                                       add_hook(m->hapi_name, m->fn);
+                               {
+                                       int priority = m->priority;
+                                       if (priority == 0)
+                                               priority = HOOK_NORMAL;
+                                       add_hook_prio(m->hapi_name, m->fn, priority);
+                               }
                        }
 
                        /* New in MAPI v2 - version replacement */
                        ver = mheader->mapi_module_version ? mheader->mapi_module_version : ircd_version;
                        description = mheader->mapi_module_description;
-
-                       if(mheader->mapi_cap_list)
-                       {
-                               mapi_cap_list_av2 *m;
-                               for (m = mheader->mapi_cap_list; m->cap_name; ++m)
-                               {
-                                       struct CapabilityIndex *idx;
-                                       int result;
-
-                                       switch (m->cap_index)
-                                       {
-                                       case MAPI_CAP_CLIENT:
-                                               idx = cli_capindex;
-                                               break;
-                                       case MAPI_CAP_SERVER:
-                                               idx = serv_capindex;
-                                               break;
-                                       default:
-                                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
-                                                       "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
-                                                       m->cap_index, m->cap_name, mod_displayname);
-                                               ilog(L_MAIN,
-                                                       "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
-                                                       m->cap_index, m->cap_name, mod_displayname);
-                                               continue;
-                                       }
-
-                                       result = capability_put(idx, m->cap_name, m->cap_ownerdata);
-                                       if (m->cap_id != NULL)
-                                       {
-                                               *(m->cap_id) = result;
-                                               sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * ADD :%s", me.name, m->cap_name);
-                                       }
-                               }
-                       }
                }
 
                break;
        default:
                ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
                     mod_displayname, MAPI_VERSION(*mapi_version));
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Module %s has unknown/unsupported MAPI version %d.",
                                     mod_displayname, *mapi_version);
                lt_dlclose(tmpptr);
@@ -639,6 +682,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
        mod->mapi_header = mapi_version;
        mod->mapi_version = MAPI_VERSION(*mapi_version);
        mod->origin = origin;
+       mod->path = rb_strdup(path);
        rb_dlinkAdd(mod, &mod->node, &module_list);
 
        if(warn)
@@ -658,7 +702,7 @@ load_a_module(const char *path, bool warn, int origin, bool core)
                        break;
                }
 
-               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
                                     mod_displayname, ver, MAPI_VERSION(*mapi_version), o, description,
                                     (void *) tmpptr);
@@ -669,12 +713,63 @@ load_a_module(const char *path, bool warn, int origin, bool core)
        return true;
 }
 
+void
+modules_do_reload(void *info_)
+{
+       struct modreload *info = info_;
+       struct module *mod;
+       int check_core;
+       int origin;
+       char *m_bn = rb_basename(info->module);
+       char *path;
+       struct Client *source_p = find_id(info->id);
+
+       if((mod = findmodule_byname(m_bn)) == NULL)
+       {
+               if (source_p) sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
+               rb_free(info);
+               rb_free(m_bn);
+               return;
+       }
+
+       origin = mod->origin;
+       check_core = mod->core;
+       path = rb_strdup(mod->path);
+
+       mod_remember_clicaps();
+
+       if(unload_one_module(m_bn, true) == false)
+       {
+               if (source_p) sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
+               rb_free(info);
+               rb_free(m_bn);
+               rb_free(path);
+               return;
+       }
+
+       if((load_a_module(path, true, origin, check_core) == false) && check_core)
+       {
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
+                                    "Error reloading core module: %s: terminating ircd", m_bn);
+               ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
+               exit(0);
+       }
+
+       mod_notify_clicaps();
+
+       rb_free(info);
+       rb_free(m_bn);
+       rb_free(path);
+}
+
 void
 modules_do_restart(void *unused)
 {
        unsigned int modnum = 0;
        rb_dlink_node *ptr, *nptr;
 
+       mod_remember_clicaps();
+
        RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head)
        {
                struct module *mod = ptr->data;
@@ -698,6 +793,8 @@ modules_do_restart(void *unused)
        load_core_modules(false);
        rehash(false);
 
+       mod_notify_clicaps();
+
        sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                             "Module Restart: %u modules unloaded, %lu modules loaded",
                             modnum, rb_dlink_list_length(&module_list));