2 * ircd-ratbox: A slightly useful ircd.
3 * modules.c: A module loader.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 * $Id: modules.c 3161 2007-01-25 07:23:01Z nenolod $
34 #include "s_newconf.h"
37 #include "ircd_defs.h"
43 struct module **modlist
= NULL
;
45 static const char *core_module_table
[] = {
62 #define MODS_INCREMENT 10
64 int max_mods
= MODS_INCREMENT
;
66 static rb_dlink_list mod_paths
;
68 static int mo_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
69 static int mo_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
70 static int mo_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
71 static int mo_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
72 static int mo_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
74 static int me_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
75 static int me_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
76 static int me_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
77 static int me_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
78 static int me_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
80 static int do_modload(struct Client
*, const char *);
81 static int do_modunload(struct Client
*, const char *);
82 static int do_modreload(struct Client
*, const char *);
83 static int do_modlist(struct Client
*, const char *);
84 static int do_modrestart(struct Client
*);
86 struct Message modload_msgtab
= {
87 "MODLOAD", 0, 0, 0, MFLG_SLOW
,
88 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modload
, 2}, {mo_modload
, 2}}
91 struct Message modunload_msgtab
= {
92 "MODUNLOAD", 0, 0, 0, MFLG_SLOW
,
93 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modunload
, 2}, {mo_modunload
, 2}}
96 struct Message modreload_msgtab
= {
97 "MODRELOAD", 0, 0, 0, MFLG_SLOW
,
98 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modreload
, 2}, {mo_modreload
, 2}}
101 struct Message modlist_msgtab
= {
102 "MODLIST", 0, 0, 0, MFLG_SLOW
,
103 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modlist
, 0}, {mo_modlist
, 0}}
106 struct Message modrestart_msgtab
= {
107 "MODRESTART", 0, 0, 0, MFLG_SLOW
,
108 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modrestart
, 0}, {mo_modrestart
, 0}}
116 ilog(L_MAIN
, "lt_dlinit failed");
120 mod_add_cmd(&modload_msgtab
);
121 mod_add_cmd(&modunload_msgtab
);
122 mod_add_cmd(&modreload_msgtab
);
123 mod_add_cmd(&modlist_msgtab
);
124 mod_add_cmd(&modrestart_msgtab
);
126 /* Add the default paths we look in to the module system --nenolod */
127 mod_add_path(MODPATH
);
128 mod_add_path(AUTOMODPATH
);
135 * side effects - returns a module path from path
138 mod_find_path(const char *path
)
143 RB_DLINK_FOREACH(ptr
, mod_paths
.head
)
147 if(!strcmp(path
, mpath
))
158 * side effects - adds path to list
161 mod_add_path(const char *path
)
165 if(mod_find_path(path
))
168 pathst
= rb_strdup(path
);
169 rb_dlinkAddAlloc(pathst
, &mod_paths
);
176 * side effects - clear the lists of paths
179 mod_clear_paths(void)
181 rb_dlink_node
*ptr
, *next_ptr
;
183 RB_DLINK_FOREACH_SAFE(ptr
, next_ptr
, mod_paths
.head
)
186 rb_free_rb_dlink_node(ptr
);
189 mod_paths
.head
= mod_paths
.tail
= NULL
;
190 mod_paths
.length
= 0;
201 findmodule_byname(const char *name
)
205 for (i
= 0; i
< num_mods
; i
++)
207 if(!irccmp(modlist
[i
]->name
, name
))
213 /* load_all_modules()
220 load_all_modules(int warn
)
222 DIR *system_module_dir
= NULL
;
223 struct dirent
*ldirent
= NULL
;
224 char module_fq_name
[PATH_MAX
+ 1];
229 modlist
= (struct module **) rb_malloc(sizeof(struct module *) * (MODS_INCREMENT
));
231 max_mods
= MODS_INCREMENT
;
233 system_module_dir
= opendir(AUTOMODPATH
);
235 if(system_module_dir
== NULL
)
237 ilog(L_MAIN
, "Could not load modules from %s: %s", AUTOMODPATH
, strerror(errno
));
241 while ((ldirent
= readdir(system_module_dir
)) != NULL
)
243 len
= strlen(ldirent
->d_name
);
244 if((len
> 3) && !strcmp(ldirent
->d_name
+len
-3, ".la"))
246 (void) snprintf(module_fq_name
, sizeof(module_fq_name
), "%s/%s", AUTOMODPATH
, ldirent
->d_name
);
247 (void) load_a_module(module_fq_name
, warn
, 0);
251 (void) closedir(system_module_dir
);
254 /* load_core_modules()
258 * side effects - core modules are loaded, if any fail, kill ircd
261 load_core_modules(int warn
)
263 char module_name
[PATH_MAX
];
267 for (i
= 0; core_module_table
[i
]; i
++)
269 snprintf(module_name
, sizeof(module_name
), "%s/%s%s", MODPATH
,
270 core_module_table
[i
], ".la");
272 if(load_a_module(module_name
, warn
, 1) == -1)
275 "Error loading core module %s%s: terminating ircd",
276 core_module_table
[i
], ".la");
289 load_one_module(const char *path
, int coremodule
)
291 char modpath
[PATH_MAX
];
292 rb_dlink_node
*pathst
;
297 if (server_state_foreground
== 1)
298 inotice("loading module %s ...", path
);
300 RB_DLINK_FOREACH(pathst
, mod_paths
.head
)
302 mpath
= pathst
->data
;
304 snprintf(modpath
, sizeof(modpath
), "%s/%s", mpath
, path
);
305 if((strstr(modpath
, "../") == NULL
) && (strstr(modpath
, "/..") == NULL
))
307 if(stat(modpath
, &statbuf
) == 0)
309 if(S_ISREG(statbuf
.st_mode
))
311 /* Regular files only please */
313 return load_a_module(modpath
, 1, 1);
315 return load_a_module(modpath
, 1, 0);
322 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Cannot locate module %s", path
);
327 /* load a module .. */
329 mo_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
331 if(!IsOperAdmin(source_p
))
333 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
334 me
.name
, source_p
->name
, "admin");
340 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
341 "ENCAP %s MODLOAD %s", parv
[2], parv
[1]);
342 if (match(parv
[2], me
.name
) == 0)
346 return do_modload(source_p
, parv
[1]);
350 me_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
352 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
354 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
355 "to load modules on this server.");
359 return do_modload(source_p
, parv
[1]);
363 do_modload(struct Client
*source_p
, const char *module)
365 char *m_bn
= rb_basename(module);
367 if(findmodule_byname(m_bn
) != -1)
369 sendto_one_notice(source_p
, ":Module %s is already loaded", m_bn
);
374 load_one_module(module, 0);
382 /* unload a module .. */
384 mo_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
386 if(!IsOperAdmin(source_p
))
388 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
389 me
.name
, source_p
->name
, "admin");
395 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
396 "ENCAP %s MODUNLOAD %s", parv
[2], parv
[1]);
397 if (match(parv
[2], me
.name
) == 0)
401 return do_modunload(source_p
, parv
[1]);
405 me_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
407 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
409 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
410 "to load modules on this server.");
414 return do_modunload(source_p
, parv
[1]);
418 do_modunload(struct Client
*source_p
, const char *module)
421 char *m_bn
= rb_basename(module);
423 if((modindex
= findmodule_byname(m_bn
)) == -1)
425 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
430 if(modlist
[modindex
]->core
== 1)
432 sendto_one_notice(source_p
, ":Module %s is a core module and may not be unloaded", m_bn
);
437 if(unload_one_module(m_bn
, 1) == -1)
439 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
446 /* unload and load in one! */
448 mo_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
450 if(!IsOperAdmin(source_p
))
452 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
453 me
.name
, source_p
->name
, "admin");
459 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
460 "ENCAP %s MODRELOAD %s", parv
[2], parv
[1]);
461 if (match(parv
[2], me
.name
) == 0)
465 return do_modreload(source_p
, parv
[1]);
469 me_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
471 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
473 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
474 "to load modules on this server.");
478 return do_modreload(source_p
, parv
[1]);
482 do_modreload(struct Client
*source_p
, const char *module)
486 char *m_bn
= rb_basename(module);
488 if((modindex
= findmodule_byname(m_bn
)) == -1)
490 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
495 check_core
= modlist
[modindex
]->core
;
497 if(unload_one_module(m_bn
, 1) == -1)
499 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
504 if((load_one_module(m_bn
, check_core
) == -1) && check_core
)
506 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
507 "Error reloading core module: %s: terminating ircd", m_bn
);
508 ilog(L_MAIN
, "Error loading core module %s: terminating ircd", m_bn
);
516 /* list modules .. */
518 mo_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
520 if(!IsOperAdmin(source_p
))
522 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
523 me
.name
, source_p
->name
, "admin");
529 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
530 "ENCAP %s MODLIST %s", parv
[2], parv
[1]);
531 if (match(parv
[2], me
.name
) == 0)
535 return do_modlist(source_p
, parc
> 1 ? parv
[1] : 0);
539 me_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
541 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
543 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
544 "to load modules on this server.");
548 return do_modlist(source_p
, parv
[1]);
552 do_modlist(struct Client
*source_p
, const char *pattern
)
556 for (i
= 0; i
< num_mods
; i
++)
560 if(match(pattern
, modlist
[i
]->name
))
562 sendto_one(source_p
, form_str(RPL_MODLIST
),
563 me
.name
, source_p
->name
,
565 (unsigned long)(uintptr_t)modlist
[i
]->address
,
566 modlist
[i
]->version
, modlist
[i
]->core
? "(core)" : "");
571 sendto_one(source_p
, form_str(RPL_MODLIST
),
572 me
.name
, source_p
->name
, modlist
[i
]->name
,
573 (unsigned long)(uintptr_t)modlist
[i
]->address
, modlist
[i
]->version
,
574 modlist
[i
]->core
? "(core)" : "");
578 sendto_one(source_p
, form_str(RPL_ENDOFMODLIST
), me
.name
, source_p
->name
);
582 /* unload and reload all modules */
584 mo_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
586 if(!IsOperAdmin(source_p
))
588 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
589 me
.name
, source_p
->name
, "admin");
595 sendto_match_servs(source_p
, parv
[1], CAP_ENCAP
, NOCAPS
,
596 "ENCAP %s MODRESTART", parv
[1]);
597 if (match(parv
[1], me
.name
) == 0)
601 return do_modrestart(source_p
);
605 me_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
607 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
609 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
610 "to load modules on this server.");
614 return do_modrestart(source_p
);
618 do_modrestart(struct Client
*source_p
)
622 sendto_one_notice(source_p
, ":Reloading all modules");
626 unload_one_module(modlist
[0]->name
, 0);
629 load_core_modules(0);
632 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
633 "Module Restart: %d modules unloaded, %d modules loaded",
635 ilog(L_MAIN
, "Module Restart: %d modules unloaded, %d modules loaded", modnum
, num_mods
);
640 static void increase_modlist(void);
642 #define MODS_INCREMENT 10
644 static char unknown_ver
[] = "<unknown>";
646 /* unload_one_module()
648 * inputs - name of module to unload
649 * - 1 to say modules unloaded, 0 to not
650 * output - 0 if successful, -1 if error
651 * side effects - module is unloaded
654 unload_one_module(const char *name
, int warn
)
658 if((modindex
= findmodule_byname(name
)) == -1)
662 ** XXX - The type system in C does not allow direct conversion between
663 ** data and function pointers, but as it happens, most C compilers will
664 ** safely do this, however it is a theoretical overlow to cast as we
665 ** must do here. I have library functions to take care of this, but
666 ** despite being more "correct" for the C language, this is more
667 ** practical. Removing the abuse of the ability to cast ANY pointer
668 ** to and from an integer value here will break some compilers.
671 /* Left the comment in but the code isn't here any more -larne */
672 switch (modlist
[modindex
]->mapi_version
)
676 struct mapi_mheader_av1
*mheader
= modlist
[modindex
]->mapi_header
;
677 if(mheader
->mapi_command_list
)
680 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
684 /* hook events are never removed, we simply lose the
685 * ability to call them --fl
687 if(mheader
->mapi_hfn_list
)
689 mapi_hfn_list_av1
*m
;
690 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
691 remove_hook(m
->hapi_name
, m
->fn
);
694 if(mheader
->mapi_unregister
)
695 mheader
->mapi_unregister();
699 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
700 "Unknown/unsupported MAPI version %d when unloading %s!",
701 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
702 ilog(L_MAIN
, "Unknown/unsupported MAPI version %d when unloading %s!",
703 modlist
[modindex
]->mapi_version
, modlist
[modindex
]->name
);
707 lt_dlclose(modlist
[modindex
]->address
);
709 rb_free(modlist
[modindex
]->name
);
710 rb_free(modlist
[modindex
]);
711 memmove(&modlist
[modindex
], &modlist
[modindex
+ 1],
712 sizeof(struct module *) * ((num_mods
- 1) - modindex
));
719 ilog(L_MAIN
, "Module %s unloaded", name
);
720 sendto_realops_snomask(SNO_GENERAL
, L_ALL
, "Module %s unloaded", name
);
730 * inputs - path name of module, int to notice, int of core
731 * output - -1 if error 0 if success
732 * side effects - loads a module if successful
735 load_a_module(const char *path
, int warn
, int core
)
743 mod_basename
= rb_basename(path
);
745 tmpptr
= lt_dlopen(path
);
749 const char *err
= lt_dlerror();
751 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
752 "Error loading module %s: %s", mod_basename
, err
);
753 ilog(L_MAIN
, "Error loading module %s: %s", mod_basename
, err
);
754 rb_free(mod_basename
);
760 * _mheader is actually a struct mapi_mheader_*, but mapi_version
761 * is always the first member of this structure, so we treate it
762 * as a single int in order to determine the API version.
765 mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "_mheader");
766 if((mapi_version
== NULL
767 && (mapi_version
= (int *) (uintptr_t) lt_dlsym(tmpptr
, "__mheader")) == NULL
)
768 || MAPI_MAGIC(*mapi_version
) != MAPI_MAGIC_HDR
)
770 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
771 "Data format error: module %s has no MAPI header.",
773 ilog(L_MAIN
, "Data format error: module %s has no MAPI header.", mod_basename
);
774 (void) lt_dlclose(tmpptr
);
775 rb_free(mod_basename
);
779 switch (MAPI_VERSION(*mapi_version
))
783 struct mapi_mheader_av1
*mheader
= (struct mapi_mheader_av1
*)(void *)mapi_version
; /* see above */
784 if(mheader
->mapi_register
&& (mheader
->mapi_register() == -1))
786 ilog(L_MAIN
, "Module %s indicated failure during load.",
788 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
789 "Module %s indicated failure during load.",
792 rb_free(mod_basename
);
795 if(mheader
->mapi_command_list
)
798 for (m
= mheader
->mapi_command_list
; *m
; ++m
)
802 if(mheader
->mapi_hook_list
)
805 for (m
= mheader
->mapi_hook_list
; m
->hapi_name
; ++m
)
806 *m
->hapi_id
= register_hook(m
->hapi_name
);
809 if(mheader
->mapi_hfn_list
)
811 mapi_hfn_list_av1
*m
;
812 for (m
= mheader
->mapi_hfn_list
; m
->hapi_name
; ++m
)
813 add_hook(m
->hapi_name
, m
->fn
);
816 ver
= mheader
->mapi_module_version
;
821 ilog(L_MAIN
, "Module %s has unknown/unsupported MAPI version %d.",
822 mod_basename
, MAPI_VERSION(*mapi_version
));
823 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
824 "Module %s has unknown/unsupported MAPI version %d.",
825 mod_basename
, *mapi_version
);
827 rb_free(mod_basename
);
836 modlist
[num_mods
] = rb_malloc(sizeof(struct module));
837 modlist
[num_mods
]->address
= tmpptr
;
838 modlist
[num_mods
]->version
= ver
;
839 modlist
[num_mods
]->core
= core
;
840 modlist
[num_mods
]->name
= rb_strdup(mod_basename
);
841 modlist
[num_mods
]->mapi_header
= mapi_version
;
842 modlist
[num_mods
]->mapi_version
= MAPI_VERSION(*mapi_version
);
847 sendto_realops_snomask(SNO_GENERAL
, L_ALL
,
848 "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
849 mod_basename
, ver
, MAPI_VERSION(*mapi_version
),
850 (unsigned long) tmpptr
);
851 ilog(L_MAIN
, "Module %s [version: %s; MAPI version: %d] loaded at 0x%lx",
852 mod_basename
, ver
, MAPI_VERSION(*mapi_version
), (unsigned long) tmpptr
);
854 rb_free(mod_basename
);
863 * side effects - expand the size of modlist if necessary
866 increase_modlist(void)
868 struct module **new_modlist
= NULL
;
870 if((num_mods
+ 1) < max_mods
)
873 new_modlist
= (struct module **) rb_malloc(sizeof(struct module *) *
874 (max_mods
+ MODS_INCREMENT
));
875 memcpy((void *) new_modlist
, (void *) modlist
, sizeof(struct module *) * num_mods
);
878 modlist
= new_modlist
;
879 max_mods
+= MODS_INCREMENT
;