1 /* modules/m_modules.c - module for module loading
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
26 #include "s_newconf.h"
37 static const char modules_desc
[] = "Provides module management commands";
39 static void mo_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
40 static void mo_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
41 static void mo_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
42 static void mo_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
43 static void mo_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
45 static void me_modload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
46 static void me_modlist(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
47 static void me_modreload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
48 static void me_modunload(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
49 static void me_modrestart(struct MsgBuf
*, struct Client
*, struct Client
*, int, const char **);
51 static void do_modload(struct Client
*, const char *);
52 static void do_modunload(struct Client
*, const char *);
53 static void do_modreload(struct Client
*, const char *);
54 static void do_modlist(struct Client
*, const char *);
55 static void do_modrestart(struct Client
*);
57 struct Message modload_msgtab
= {
58 "MODLOAD", 0, 0, 0, 0,
59 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modload
, 2}, {mo_modload
, 2}}
62 struct Message modunload_msgtab
= {
63 "MODUNLOAD", 0, 0, 0, 0,
64 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modunload
, 2}, {mo_modunload
, 2}}
67 struct Message modreload_msgtab
= {
68 "MODRELOAD", 0, 0, 0, 0,
69 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modreload
, 2}, {mo_modreload
, 2}}
72 struct Message modlist_msgtab
= {
73 "MODLIST", 0, 0, 0, 0,
74 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modlist
, 0}, {mo_modlist
, 0}}
77 struct Message modrestart_msgtab
= {
78 "MODRESTART", 0, 0, 0, 0,
79 {mg_unreg
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_modrestart
, 0}, {mo_modrestart
, 0}}
82 mapi_clist_av1 modules_clist
[] = { &modload_msgtab
, &modunload_msgtab
, &modreload_msgtab
, &modlist_msgtab
, &modrestart_msgtab
, NULL
};
84 DECLARE_MODULE_AV2(modules
, NULL
, NULL
, modules_clist
, NULL
, NULL
, NULL
, NULL
, modules_desc
);
86 /* load a module .. */
88 mo_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
90 if(!IsOperAdmin(source_p
))
92 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
93 me
.name
, source_p
->name
, "admin");
99 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
100 "ENCAP %s MODLOAD %s", parv
[2], parv
[1]);
101 if(match(parv
[2], me
.name
) == 0)
105 do_modload(source_p
, parv
[1]);
109 me_modload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
111 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
113 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
114 "to load modules on this server.");
118 do_modload(source_p
, parv
[1]);
122 /* unload a module .. */
124 mo_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
126 if(!IsOperAdmin(source_p
))
128 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
129 me
.name
, source_p
->name
, "admin");
135 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
136 "ENCAP %s MODUNLOAD %s", parv
[2], parv
[1]);
137 if(match(parv
[2], me
.name
) == 0)
141 do_modunload(source_p
, parv
[1]);
145 me_modunload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
147 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
149 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
150 "to load modules on this server.");
154 do_modunload(source_p
, parv
[1]);
157 /* unload and load in one! */
159 mo_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
161 if(!IsOperAdmin(source_p
))
163 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
164 me
.name
, source_p
->name
, "admin");
170 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
171 "ENCAP %s MODRELOAD %s", parv
[2], parv
[1]);
172 if(match(parv
[2], me
.name
) == 0)
176 do_modreload(source_p
, parv
[1]);
180 me_modreload(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
182 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
184 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
185 "to load modules on this server.");
189 do_modreload(source_p
, parv
[1]);
192 /* list modules .. */
194 mo_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
196 if(!IsOperAdmin(source_p
))
198 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
199 me
.name
, source_p
->name
, "admin");
205 sendto_match_servs(source_p
, parv
[2], CAP_ENCAP
, NOCAPS
,
206 "ENCAP %s MODLIST %s", parv
[2], parv
[1]);
207 if(match(parv
[2], me
.name
) == 0)
211 do_modlist(source_p
, parc
> 1 ? parv
[1] : 0);
215 me_modlist(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
217 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
219 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
220 "to load modules on this server.");
224 do_modlist(source_p
, parv
[1]);
227 /* unload and reload all modules */
229 mo_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
231 if(!IsOperAdmin(source_p
))
233 sendto_one(source_p
, form_str(ERR_NOPRIVS
),
234 me
.name
, source_p
->name
, "admin");
240 sendto_match_servs(source_p
, parv
[1], CAP_ENCAP
, NOCAPS
,
241 "ENCAP %s MODRESTART", parv
[1]);
242 if(match(parv
[1], me
.name
) == 0)
246 do_modrestart(source_p
);
250 me_modrestart(struct MsgBuf
*msgbuf_p
, struct Client
*client_p
, struct Client
*source_p
, int parc
, const char **parv
)
252 if(!find_shared_conf(source_p
->username
, source_p
->host
, source_p
->servptr
->name
, SHARED_MODULE
))
254 sendto_one_notice(source_p
, ":*** You do not have an appropriate shared block "
255 "to load modules on this server.");
259 do_modrestart(source_p
);
263 do_modload(struct Client
*source_p
, const char *module)
265 char *m_bn
= rb_basename(module);
268 if(findmodule_byname(m_bn
) != NULL
)
270 sendto_one_notice(source_p
, ":Module %s is already loaded", m_bn
);
275 origin
= strcmp(module, m_bn
) == 0 ? MAPI_ORIGIN_CORE
: MAPI_ORIGIN_EXTENSION
;
276 load_one_module(module, origin
, false);
282 do_modunload(struct Client
*source_p
, const char *module)
285 char *m_bn
= rb_basename(module);
287 if((mod
= findmodule_byname(m_bn
)) == NULL
)
289 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
296 sendto_one_notice(source_p
, ":Module %s is a core module and may not be unloaded", m_bn
);
301 if(unload_one_module(m_bn
, true) == false)
302 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
308 do_modreload(struct Client
*source_p
, const char *module)
312 char *m_bn
= rb_basename(module);
314 if((mod
= findmodule_byname(m_bn
)) == NULL
)
316 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
321 check_core
= mod
->core
;
323 if(unload_one_module(m_bn
, true) == false)
325 sendto_one_notice(source_p
, ":Module %s is not loaded", m_bn
);
330 if((load_one_module(m_bn
, mod
->origin
, check_core
) == false) && check_core
)
332 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
333 "Error reloading core module: %s: terminating ircd", m_bn
);
334 ilog(L_MAIN
, "Error loading core module %s: terminating ircd", m_bn
);
342 do_modrestart(struct Client
*source_p
)
344 unsigned int modnum
= 0;
345 rb_dlink_node
*ptr
, *nptr
;
347 sendto_one_notice(source_p
, ":Reloading all modules");
349 RB_DLINK_FOREACH_SAFE(ptr
, nptr
, module_list
.head
)
351 struct module *mod
= ptr
->data
;
352 if(!unload_one_module(mod
->name
, false))
354 ilog(L_MAIN
, "Module Restart: %s was not unloaded %s",
356 mod
->core
? "(core module)" : "");
359 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
360 "Module Restart: %s failed to unload",
368 load_all_modules(false);
369 load_core_modules(false);
372 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
373 "Module Restart: %u modules unloaded, %lu modules loaded",
374 modnum
, rb_dlink_list_length(&module_list
));
375 ilog(L_MAIN
, "Module Restart: %u modules unloaded, %lu modules loaded", modnum
, rb_dlink_list_length(&module_list
));
379 do_modlist(struct Client
*source_p
, const char *pattern
)
383 RB_DLINK_FOREACH(ptr
, module_list
.head
)
385 struct module *mod
= ptr
->data
;
389 case MAPI_ORIGIN_EXTENSION
:
390 origin
= "extension";
392 case MAPI_ORIGIN_CORE
:
402 if(match(pattern
, mod
->name
))
404 sendto_one(source_p
, form_str(RPL_MODLIST
),
405 me
.name
, source_p
->name
,
407 (unsigned long)(uintptr_t)mod
->address
, origin
,
408 mod
->core
? " (core)" : "", mod
->version
, mod
->description
);
413 sendto_one(source_p
, form_str(RPL_MODLIST
),
414 me
.name
, source_p
->name
, mod
->name
,
415 (unsigned long)(uintptr_t)mod
->address
, origin
,
416 mod
->core
? " (core)" : "", mod
->version
, mod
->description
);
420 sendto_one(source_p
, form_str(RPL_ENDOFMODLIST
), me
.name
, source_p
->name
);