]> jfr.im git - solanum.git/blame - ircd/modules.c
modules: fix use-after-free when reloading
[solanum.git] / ircd / modules.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * modules.c: A module loader.
4 *
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
8 *
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.
13 *
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.
18 *
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
22 * USA
212380e3
AC
23 */
24
25#include "stdinc.h"
212380e3 26#include "modules.h"
4016731b 27#include "logger.h"
212380e3
AC
28#include "ircd.h"
29#include "client.h"
30#include "send.h"
31#include "s_conf.h"
32#include "s_newconf.h"
33#include "numeric.h"
34#include "parse.h"
35#include "ircd_defs.h"
4562c604 36#include "match.h"
15feac53 37#include "s_serv.h"
8e9c6a75 38#include "capability.h"
7b641013 39#include "hash.h"
212380e3 40
f272e7ab
AC
41#include <ltdl.h>
42
9abdcf1c
EM
43#ifndef LT_MODULE_EXT
44# error "Charybdis requires loadable module support."
45#endif
46
e55a9d6a
AC
47rb_dlink_list module_list;
48rb_dlink_list mod_paths;
212380e3
AC
49
50static const char *core_module_table[] = {
431a1a27 51 "m_ban",
212380e3
AC
52 "m_die",
53 "m_error",
54 "m_join",
55 "m_kick",
56 "m_kill",
57 "m_message",
58 "m_mode",
78946542 59 "m_modules",
212380e3
AC
60 "m_nick",
61 "m_part",
62 "m_quit",
63 "m_server",
212380e3
AC
64 "m_squit",
65 NULL
66};
67
81204be8
EM
68#define MOD_WARN_DELTA (90 * 86400) /* time in seconds, 86400 seconds in a day */
69
212380e3 70void
92dad483 71init_modules(void)
212380e3 72{
f272e7ab
AC
73 if(lt_dlinit())
74 {
75 ilog(L_MAIN, "lt_dlinit failed");
c173a8ad 76 exit(EXIT_FAILURE);
f272e7ab
AC
77 }
78
212380e3 79 /* Add the default paths we look in to the module system --nenolod */
4d8cfacd
AC
80 mod_add_path(ircd_paths[IRCD_PATH_MODULES]);
81 mod_add_path(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
212380e3
AC
82}
83
28cc8bb9
EK
84static unsigned int prev_caps;
85
86void
87mod_remember_clicaps(void)
88{
89 prev_caps = capability_index_mask(cli_capindex);
90}
91
92void
93mod_notify_clicaps(void)
94{
95 unsigned int cur_caps = capability_index_mask(cli_capindex);
96 unsigned int del = prev_caps & ~cur_caps;
97 unsigned int new = cur_caps & ~prev_caps;
98
99 if (del)
100 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * DEL :%s",
101 me.name, capability_index_list(cli_capindex, del));
102 if (new)
103 sendto_local_clients_with_capability(CLICAP_CAP_NOTIFY, ":%s CAP * NEW :%s",
104 me.name, capability_index_list(cli_capindex, new));
105}
106
212380e3
AC
107/* mod_find_path()
108 *
109 * input - path
110 * output - none
111 * side effects - returns a module path from path
112 */
26c6ac3d 113static char *
212380e3
AC
114mod_find_path(const char *path)
115{
330fc5c1 116 rb_dlink_node *ptr;
26c6ac3d 117 char *mpath;
212380e3 118
5cefa1d6 119 RB_DLINK_FOREACH(ptr, mod_paths.head)
212380e3
AC
120 {
121 mpath = ptr->data;
122
26c6ac3d 123 if(!strcmp(path, mpath))
212380e3
AC
124 return mpath;
125 }
126
127 return NULL;
128}
129
130/* mod_add_path
131 *
132 * input - path
55abcbb2 133 * ouput -
212380e3
AC
134 * side effects - adds path to list
135 */
136void
137mod_add_path(const char *path)
138{
26c6ac3d 139 char *pathst;
212380e3
AC
140
141 if(mod_find_path(path))
142 return;
143
26c6ac3d 144 pathst = rb_strdup(path);
330fc5c1 145 rb_dlinkAddAlloc(pathst, &mod_paths);
212380e3
AC
146}
147
148/* mod_clear_paths()
149 *
150 * input -
151 * output -
152 * side effects - clear the lists of paths
153 */
154void
155mod_clear_paths(void)
156{
637c4932 157 rb_dlink_node *ptr, *next_ptr;
212380e3 158
637c4932 159 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
212380e3 160 {
637c4932 161 rb_free(ptr->data);
30106156 162 rb_free_rb_dlink_node(ptr);
212380e3
AC
163 }
164
165 mod_paths.head = mod_paths.tail = NULL;
166 mod_paths.length = 0;
167}
168
212380e3
AC
169/* findmodule_byname
170 *
aa483e55
EM
171 * input - module to load
172 * output - index of module on success, -1 on failure
173 * side effects - none
212380e3 174 */
e55a9d6a 175struct module *
212380e3
AC
176findmodule_byname(const char *name)
177{
e55a9d6a 178 rb_dlink_node *ptr;
c9108ea0
AC
179 char name_ext[PATH_MAX + 1];
180
dd92c99b
AC
181 rb_strlcpy(name_ext, name, sizeof name_ext);
182 rb_strlcat(name_ext, LT_MODULE_EXT, sizeof name_ext);
212380e3 183
e55a9d6a 184 RB_DLINK_FOREACH(ptr, module_list.head)
212380e3 185 {
e55a9d6a
AC
186 struct module *mod = ptr->data;
187
188 if(!irccmp(mod->name, name))
189 return mod;
c9108ea0 190
e55a9d6a
AC
191 if(!irccmp(mod->name, name_ext))
192 return mod;
212380e3 193 }
c9108ea0 194
e55a9d6a 195 return NULL;
212380e3
AC
196}
197
198/* load_all_modules()
199 *
200 * input -
201 * output -
202 * side effects -
203 */
204void
aa483e55 205load_all_modules(bool warn)
212380e3
AC
206{
207 DIR *system_module_dir = NULL;
208 struct dirent *ldirent = NULL;
209 char module_fq_name[PATH_MAX + 1];
1db8a313
EM
210 size_t module_ext_len = strlen(LT_MODULE_EXT);
211
4d8cfacd 212 system_module_dir = opendir(ircd_paths[IRCD_PATH_AUTOLOAD_MODULES]);
212380e3
AC
213
214 if(system_module_dir == NULL)
215 {
4d8cfacd 216 ilog(L_MAIN, "Could not load modules from %s: %s", ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], strerror(errno));
212380e3
AC
217 return;
218 }
219
220 while ((ldirent = readdir(system_module_dir)) != NULL)
221 {
66031753 222 size_t len = strlen(ldirent->d_name);
9abdcf1c 223
66031753 224 if(len > module_ext_len &&
f956cb0f 225 rb_strncasecmp(ldirent->d_name + (len - module_ext_len), LT_MODULE_EXT, module_ext_len) == 0)
5203cba5 226 {
66031753
EM
227 (void) snprintf(module_fq_name, sizeof(module_fq_name), "%s%c%s",
228 ircd_paths[IRCD_PATH_AUTOLOAD_MODULES], RB_PATH_SEPARATOR, ldirent->d_name);
aa483e55 229 (void) load_a_module(module_fq_name, warn, MAPI_ORIGIN_CORE, false);
5203cba5 230 }
212380e3
AC
231
232 }
233 (void) closedir(system_module_dir);
234}
235
236/* load_core_modules()
237 *
238 * input -
239 * output -
240 * side effects - core modules are loaded, if any fail, kill ircd
241 */
242void
aa483e55 243load_core_modules(bool warn)
212380e3 244{
d74fa5b5 245 char module_name[PATH_MAX];
212380e3
AC
246 int i;
247
248
249 for (i = 0; core_module_table[i]; i++)
250 {
aa483e55
EM
251 snprintf(module_name, sizeof(module_name), "%s%c%s", ircd_paths[IRCD_PATH_MODULES], RB_PATH_SEPARATOR,
252 core_module_table[i]);
212380e3 253
aa483e55 254 if(load_a_module(module_name, warn, MAPI_ORIGIN_CORE, true) == false)
212380e3
AC
255 {
256 ilog(L_MAIN,
9abdcf1c
EM
257 "Error loading core module %s: terminating ircd",
258 core_module_table[i]);
c173a8ad 259 exit(EXIT_FAILURE);
212380e3
AC
260 }
261 }
262}
263
264/* load_one_module()
265 *
266 * input -
267 * output -
268 * side effects -
269 */
aa483e55
EM
270bool
271load_one_module(const char *path, int origin, bool coremodule)
212380e3 272{
d74fa5b5 273 char modpath[PATH_MAX];
330fc5c1 274 rb_dlink_node *pathst;
212380e3 275
503727d1 276 if (server_state_foreground)
55abcbb2 277 inotice("loading module %s ...", path);
212380e3 278
aa483e55 279 if(coremodule)
216d70e9 280 origin = MAPI_ORIGIN_CORE;
216d70e9 281
5cefa1d6 282 RB_DLINK_FOREACH(pathst, mod_paths.head)
212380e3 283 {
aa483e55
EM
284 struct stat statbuf;
285 const char *mpath = pathst->data;
212380e3 286
aa483e55 287 snprintf(modpath, sizeof(modpath), "%s%c%s%s", mpath, RB_PATH_SEPARATOR, path, LT_MODULE_EXT);
212380e3
AC
288 if((strstr(modpath, "../") == NULL) && (strstr(modpath, "/..") == NULL))
289 {
aa483e55 290 if(stat(modpath, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
212380e3 291 {
aa483e55
EM
292 /* Regular files only please */
293 return load_a_module(modpath, true, origin, coremodule);
212380e3
AC
294 }
295
296 }
297 }
298
299 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot locate module %s", path);
aa483e55 300 return false;
212380e3
AC
301}
302
212380e3 303static char unknown_ver[] = "<unknown>";
8e9c6a75 304static char unknown_description[] = "<none>";
212380e3 305
212380e3
AC
306/* unload_one_module()
307 *
308 * inputs - name of module to unload
aa483e55
EM
309 * - true to say modules unloaded, false to not
310 * output - true if successful, false if error
212380e3
AC
311 * side effects - module is unloaded
312 */
aa483e55
EM
313bool
314unload_one_module(const char *name, bool warn)
212380e3 315{
e55a9d6a 316 struct module *mod;
212380e3 317
e55a9d6a 318 if((mod = findmodule_byname(name)) == NULL)
aa483e55 319 return false;
b5cfad03 320
212380e3
AC
321 /*
322 ** XXX - The type system in C does not allow direct conversion between
323 ** data and function pointers, but as it happens, most C compilers will
55abcbb2
KB
324 ** safely do this, however it is a theoretical overlow to cast as we
325 ** must do here. I have library functions to take care of this, but
326 ** despite being more "correct" for the C language, this is more
212380e3
AC
327 ** practical. Removing the abuse of the ability to cast ANY pointer
328 ** to and from an integer value here will break some compilers.
329 ** -jmallett
330 */
331 /* Left the comment in but the code isn't here any more -larne */
e55a9d6a 332 switch (mod->mapi_version)
212380e3
AC
333 {
334 case 1:
335 {
e55a9d6a 336 struct mapi_mheader_av1 *mheader = mod->mapi_header;
212380e3
AC
337 if(mheader->mapi_command_list)
338 {
339 struct Message **m;
340 for (m = mheader->mapi_command_list; *m; ++m)
341 mod_del_cmd(*m);
342 }
343
344 /* hook events are never removed, we simply lose the
345 * ability to call them --fl
346 */
347 if(mheader->mapi_hfn_list)
348 {
349 mapi_hfn_list_av1 *m;
350 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
351 remove_hook(m->hapi_name, m->fn);
352 }
353
354 if(mheader->mapi_unregister)
355 mheader->mapi_unregister();
356 break;
357 }
8e9c6a75
EM
358 case 2:
359 {
e55a9d6a 360 struct mapi_mheader_av2 *mheader = mod->mapi_header;
8e9c6a75
EM
361
362 /* XXX duplicate code :( */
363 if(mheader->mapi_command_list)
364 {
365 struct Message **m;
366 for (m = mheader->mapi_command_list; *m; ++m)
367 mod_del_cmd(*m);
368 }
369
370 /* hook events are never removed, we simply lose the
371 * ability to call them --fl
372 */
373 if(mheader->mapi_hfn_list)
374 {
375 mapi_hfn_list_av1 *m;
376 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
377 remove_hook(m->hapi_name, m->fn);
378 }
379
380 if(mheader->mapi_unregister)
381 mheader->mapi_unregister();
382
383 if(mheader->mapi_cap_list)
384 {
385 mapi_cap_list_av2 *m;
386 for (m = mheader->mapi_cap_list; m->cap_name; ++m)
387 {
388 struct CapabilityIndex *idx;
389
978b7232 390 switch (m->cap_index)
8e9c6a75
EM
391 {
392 case MAPI_CAP_CLIENT:
393 idx = cli_capindex;
394 break;
395 case MAPI_CAP_SERVER:
396 idx = serv_capindex;
397 break;
398 default:
399 sendto_realops_snomask(SNO_GENERAL, L_ALL,
400 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
e55a9d6a 401 m->cap_index, m->cap_name, mod->name);
8e9c6a75
EM
402 ilog(L_MAIN,
403 "Unknown/unsupported CAP index found of type %d on capability %s when unloading %s",
e55a9d6a 404 m->cap_index, m->cap_name, mod->name);
8e9c6a75
EM
405 continue;
406 }
407
3256156a 408 if (m->cap_id != NULL)
3256156a 409 capability_orphan(idx, m->cap_name);
8e9c6a75
EM
410 }
411 }
e8de2bfa 412 break;
8e9c6a75 413 }
212380e3
AC
414 default:
415 sendto_realops_snomask(SNO_GENERAL, L_ALL,
416 "Unknown/unsupported MAPI version %d when unloading %s!",
e55a9d6a 417 mod->mapi_version, mod->name);
212380e3 418 ilog(L_MAIN, "Unknown/unsupported MAPI version %d when unloading %s!",
e55a9d6a 419 mod->mapi_version, mod->name);
212380e3
AC
420 break;
421 }
422
e55a9d6a 423 lt_dlclose(mod->address);
212380e3 424
e55a9d6a
AC
425 rb_dlinkDelete(&mod->node, &module_list);
426 rb_free(mod->name);
427 rb_free(mod);
212380e3 428
aa483e55 429 if(warn)
212380e3
AC
430 {
431 ilog(L_MAIN, "Module %s unloaded", name);
432 sendto_realops_snomask(SNO_GENERAL, L_ALL, "Module %s unloaded", name);
433 }
434
aa483e55 435 return true;
212380e3
AC
436}
437
212380e3
AC
438/*
439 * load_a_module()
440 *
aa483e55
EM
441 * inputs - path name of module, bool to notice, int of origin, bool if core
442 * output - false if error true if success
212380e3
AC
443 * side effects - loads a module if successful
444 */
aa483e55
EM
445bool
446load_a_module(const char *path, bool warn, int origin, bool core)
212380e3 447{
e55a9d6a 448 struct module *mod;
f272e7ab 449 lt_dlhandle tmpptr;
0a87075b 450 char *mod_displayname, *c;
8e9c6a75 451 const char *ver, *description = NULL;
212380e3
AC
452
453 int *mapi_version;
454
0a87075b
EM
455 mod_displayname = rb_basename(path);
456
457 /* Trim off the ending for the display name if we have to */
458 if((c = rb_strcasestr(mod_displayname, LT_MODULE_EXT)) != NULL)
459 *c = '\0';
212380e3 460
9abdcf1c 461 tmpptr = lt_dlopenext(path);
212380e3
AC
462
463 if(tmpptr == NULL)
464 {
f272e7ab 465 const char *err = lt_dlerror();
212380e3
AC
466
467 sendto_realops_snomask(SNO_GENERAL, L_ALL,
0a87075b
EM
468 "Error loading module %s: %s", mod_displayname, err);
469 ilog(L_MAIN, "Error loading module %s: %s", mod_displayname, err);
470 rb_free(mod_displayname);
aa483e55 471 return false;
212380e3
AC
472 }
473
212380e3
AC
474 /*
475 * _mheader is actually a struct mapi_mheader_*, but mapi_version
476 * is always the first member of this structure, so we treate it
477 * as a single int in order to determine the API version.
478 * -larne.
479 */
f272e7ab 480 mapi_version = (int *) (uintptr_t) lt_dlsym(tmpptr, "_mheader");
212380e3 481 if((mapi_version == NULL
f272e7ab 482 && (mapi_version = (int *) (uintptr_t) lt_dlsym(tmpptr, "__mheader")) == NULL)
212380e3
AC
483 || MAPI_MAGIC(*mapi_version) != MAPI_MAGIC_HDR)
484 {
485 sendto_realops_snomask(SNO_GENERAL, L_ALL,
486 "Data format error: module %s has no MAPI header.",
0a87075b
EM
487 mod_displayname);
488 ilog(L_MAIN, "Data format error: module %s has no MAPI header.", mod_displayname);
f272e7ab 489 (void) lt_dlclose(tmpptr);
0a87075b 490 rb_free(mod_displayname);
aa483e55 491 return false;
212380e3
AC
492 }
493
494 switch (MAPI_VERSION(*mapi_version))
495 {
496 case 1:
497 {
29c92cf9 498 struct mapi_mheader_av1 *mheader = (struct mapi_mheader_av1 *)(void *)mapi_version; /* see above */
212380e3
AC
499 if(mheader->mapi_register && (mheader->mapi_register() == -1))
500 {
501 ilog(L_MAIN, "Module %s indicated failure during load.",
0a87075b 502 mod_displayname);
212380e3
AC
503 sendto_realops_snomask(SNO_GENERAL, L_ALL,
504 "Module %s indicated failure during load.",
0a87075b 505 mod_displayname);
f272e7ab 506 lt_dlclose(tmpptr);
0a87075b 507 rb_free(mod_displayname);
aa483e55 508 return false;
212380e3
AC
509 }
510 if(mheader->mapi_command_list)
511 {
512 struct Message **m;
513 for (m = mheader->mapi_command_list; *m; ++m)
514 mod_add_cmd(*m);
515 }
516
517 if(mheader->mapi_hook_list)
518 {
519 mapi_hlist_av1 *m;
520 for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
521 *m->hapi_id = register_hook(m->hapi_name);
522 }
523
524 if(mheader->mapi_hfn_list)
525 {
526 mapi_hfn_list_av1 *m;
527 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
528 add_hook(m->hapi_name, m->fn);
529 }
530
531 ver = mheader->mapi_module_version;
532 break;
533 }
8e9c6a75
EM
534 case 2:
535 {
536 struct mapi_mheader_av2 *mheader = (struct mapi_mheader_av2 *)(void *)mapi_version; /* see above */
212380e3 537
8e9c6a75 538 /* XXX duplicated code :( */
5eb3d7a7 539 if(mheader->mapi_register && (mheader->mapi_register() == -1))
8e9c6a75
EM
540 {
541 ilog(L_MAIN, "Module %s indicated failure during load.",
0a87075b 542 mod_displayname);
8e9c6a75
EM
543 sendto_realops_snomask(SNO_GENERAL, L_ALL,
544 "Module %s indicated failure during load.",
0a87075b 545 mod_displayname);
8e9c6a75 546 lt_dlclose(tmpptr);
0a87075b 547 rb_free(mod_displayname);
aa483e55 548 return false;
8e9c6a75 549 }
81204be8
EM
550
551 /* Basic date code checks
552 *
553 * Don't make them fatal, but do complain about differences within a certain time frame.
554 * Later on if there are major API changes we can add fatal checks.
555 * -- Elizafox
556 */
557 if(mheader->mapi_datecode != datecode && mheader->mapi_datecode > 0)
558 {
3089f59c 559 long int delta = datecode - mheader->mapi_datecode;
81204be8
EM
560 if (delta > MOD_WARN_DELTA)
561 {
562 delta /= 86400;
881acf00 563 iwarn("Module %s build date is out of sync with ircd build date by %ld days, expect problems",
0a87075b 564 mod_displayname, delta);
81204be8
EM
565 sendto_realops_snomask(SNO_GENERAL, L_ALL,
566 "Module %s build date is out of sync with ircd build date by %ld days, expect problems",
0a87075b 567 mod_displayname, delta);
81204be8
EM
568 }
569 }
570
8e9c6a75
EM
571 if(mheader->mapi_command_list)
572 {
573 struct Message **m;
574 for (m = mheader->mapi_command_list; *m; ++m)
575 mod_add_cmd(*m);
576 }
577
578 if(mheader->mapi_hook_list)
579 {
580 mapi_hlist_av1 *m;
581 for (m = mheader->mapi_hook_list; m->hapi_name; ++m)
582 *m->hapi_id = register_hook(m->hapi_name);
583 }
584
585 if(mheader->mapi_hfn_list)
586 {
587 mapi_hfn_list_av1 *m;
588 for (m = mheader->mapi_hfn_list; m->hapi_name; ++m)
589 add_hook(m->hapi_name, m->fn);
590 }
591
592 /* New in MAPI v2 - version replacement */
593 ver = mheader->mapi_module_version ? mheader->mapi_module_version : ircd_version;
594 description = mheader->mapi_module_description;
595
596 if(mheader->mapi_cap_list)
597 {
598 mapi_cap_list_av2 *m;
599 for (m = mheader->mapi_cap_list; m->cap_name; ++m)
600 {
601 struct CapabilityIndex *idx;
602 int result;
603
978b7232 604 switch (m->cap_index)
8e9c6a75
EM
605 {
606 case MAPI_CAP_CLIENT:
607 idx = cli_capindex;
608 break;
609 case MAPI_CAP_SERVER:
610 idx = serv_capindex;
611 break;
612 default:
613 sendto_realops_snomask(SNO_GENERAL, L_ALL,
614 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
0a87075b 615 m->cap_index, m->cap_name, mod_displayname);
8e9c6a75
EM
616 ilog(L_MAIN,
617 "Unknown/unsupported CAP index found of type %d on capability %s when loading %s",
0a87075b 618 m->cap_index, m->cap_name, mod_displayname);
8e9c6a75
EM
619 continue;
620 }
621
622 result = capability_put(idx, m->cap_name, m->cap_ownerdata);
623 if (m->cap_id != NULL)
624 *(m->cap_id) = result;
625 }
626 }
627 }
0e5bf029
EM
628
629 break;
212380e3
AC
630 default:
631 ilog(L_MAIN, "Module %s has unknown/unsupported MAPI version %d.",
0a87075b 632 mod_displayname, MAPI_VERSION(*mapi_version));
212380e3
AC
633 sendto_realops_snomask(SNO_GENERAL, L_ALL,
634 "Module %s has unknown/unsupported MAPI version %d.",
0a87075b 635 mod_displayname, *mapi_version);
f272e7ab 636 lt_dlclose(tmpptr);
0a87075b 637 rb_free(mod_displayname);
aa483e55 638 return false;
212380e3
AC
639 }
640
641 if(ver == NULL)
642 ver = unknown_ver;
643
8e9c6a75
EM
644 if(description == NULL)
645 description = unknown_description;
646
e55a9d6a
AC
647 mod = rb_malloc(sizeof(struct module));
648 mod->address = tmpptr;
649 mod->version = ver;
650 mod->description = description;
651 mod->core = core;
652 mod->name = rb_strdup(mod_displayname);
653 mod->mapi_header = mapi_version;
654 mod->mapi_version = MAPI_VERSION(*mapi_version);
655 mod->origin = origin;
656 rb_dlinkAdd(mod, &mod->node, &module_list);
212380e3 657
aa483e55 658 if(warn)
212380e3 659 {
c63aeb44
EM
660 const char *o;
661
978b7232 662 switch (origin)
c63aeb44 663 {
c63aeb44
EM
664 case MAPI_ORIGIN_EXTENSION:
665 o = "extension";
666 break;
667 case MAPI_ORIGIN_CORE:
668 o = "core";
669 break;
670 default:
671 o = "unknown";
672 break;
673 }
674
212380e3 675 sendto_realops_snomask(SNO_GENERAL, L_ALL,
02831b6f 676 "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
0a87075b 677 mod_displayname, ver, MAPI_VERSION(*mapi_version), o, description,
02831b6f
AC
678 (void *) tmpptr);
679 ilog(L_MAIN, "Module %s [version: %s; MAPI version: %d; origin: %s; description: \"%s\"] loaded at %p",
0a87075b 680 mod_displayname, ver, MAPI_VERSION(*mapi_version), o, description, (void *) tmpptr);
212380e3 681 }
0a87075b 682 rb_free(mod_displayname);
aa483e55 683 return true;
212380e3 684}
41390bfe 685
7b641013
EK
686void
687modules_do_reload(void *info_)
688{
689 struct modreload *info = info_;
690 struct module *mod;
691 int check_core;
6aa5c725 692 int origin;
7b641013
EK
693 char *m_bn = rb_basename(info->module);
694 struct Client *source_p = find_id(info->id);
695
696 if((mod = findmodule_byname(m_bn)) == NULL)
697 {
698 if (source_p) sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
699 rb_free(info);
700 rb_free(m_bn);
701 return;
702 }
703
6aa5c725 704 origin = mod->origin;
7b641013
EK
705 check_core = mod->core;
706
707 mod_remember_clicaps();
708
709 if(unload_one_module(m_bn, true) == false)
710 {
711 if (source_p) sendto_one_notice(source_p, ":Module %s is not loaded", m_bn);
712 rb_free(info);
713 rb_free(m_bn);
714 return;
715 }
716
6aa5c725 717 if((load_one_module(m_bn, origin, check_core) == false) && check_core)
7b641013
EK
718 {
719 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
720 "Error reloading core module: %s: terminating ircd", m_bn);
721 ilog(L_MAIN, "Error loading core module %s: terminating ircd", m_bn);
722 exit(0);
723 }
724
725 mod_notify_clicaps();
726
727 rb_free(info);
728 rb_free(m_bn);
729}
730
41390bfe
AJ
731void
732modules_do_restart(void *unused)
733{
734 unsigned int modnum = 0;
735 rb_dlink_node *ptr, *nptr;
736
28cc8bb9
EK
737 mod_remember_clicaps();
738
41390bfe
AJ
739 RB_DLINK_FOREACH_SAFE(ptr, nptr, module_list.head)
740 {
741 struct module *mod = ptr->data;
742 if(!unload_one_module(mod->name, false))
743 {
744 ilog(L_MAIN, "Module Restart: %s was not unloaded %s",
745 mod->name,
746 mod->core? "(core module)" : "");
747
748 if(!mod->core)
749 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
750 "Module Restart: %s failed to unload",
751 mod->name);
752 continue;
753 }
754
755 modnum++;
756 }
757
758 load_all_modules(false);
759 load_core_modules(false);
760 rehash(false);
761
28cc8bb9
EK
762 mod_notify_clicaps();
763
41390bfe
AJ
764 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
765 "Module Restart: %u modules unloaded, %lu modules loaded",
766 modnum, rb_dlink_list_length(&module_list));
767 ilog(L_MAIN, "Module Restart: %u modules unloaded, %lu modules loaded", modnum, rb_dlink_list_length(&module_list));
768}