1 /*
2 * modules.c -- handles:
3 * support for modules in eggdrop
4 *
5 * by Darrin Smith (beldin@light.iinet.net.au)
6 */
7 /*
8 * Copyright (C) 1997 Robey Pointer
9 * Copyright (C) 1999 - 2021 Eggheads Development Team
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #include <signal.h>
27 #include "main.h"
28 #include "modules.h"
29 #include "tandem.h"
30 #include "md5/md5.h"
31 #include "users.h"
32
33 #ifndef STATIC
34 # ifdef MOD_USE_SHL
35 # include <dl.h>
36 # endif
37 # ifdef MOD_USE_DYLD
38 # include <mach-o/dyld.h>
39 # define DYLDFLAGS NSLINKMODULE_OPTION_BINDNOW|NSLINKMODULE_OPTION_PRIVATE|NSLINKMODULE_OPTION_RETURN_ON_ERROR
40 # endif
41 # ifdef MOD_USE_RLD
42 # ifdef HAVE_MACH_O_RLD_H
43 # include <mach-o/rld.h>
44 # else
45 # ifdef HAVE_RLD_H
46 # indluce <rld.h>
47 # endif
48 # endif
49 # endif
50 # ifdef MOD_USE_LOADER
51 # include <loader.h>
52 # endif
53
54 # ifdef MOD_USE_DL
55 # include <dlfcn.h>
56
57 # ifndef RTLD_GLOBAL
58 # define RTLD_GLOBAL 0
59 # endif
60 # ifndef RTLD_NOW
61 # define RTLD_NOW 1
62 # endif
63 # ifdef RTLD_LAZY
64 # define DLFLAGS RTLD_LAZY|RTLD_GLOBAL
65 # else
66 # define DLFLAGS RTLD_NOW|RTLD_GLOBAL
67 # endif
68 # endif /* MOD_USE_DL */
69 #endif /* !STATIC */
70
71 #define strncpyz strlcpy
72
73 extern struct dcc_t *dcc;
74 extern struct userrec *userlist, *lastuser;
75 extern struct chanset_t *chanset;
76
77 extern char botnetnick[], botname[], origbotname[], botuser[], ver[], log_ts[],
78 admin[], userfile[], notify_new[], helpdir[], version[], quit_msg[],
79 pid_file[];
80
81 extern int parties, noshare, dcc_total, egg_numver, userfile_perm, ignore_time,
82 must_be_owner, raw_log, max_dcc, make_userfile, default_flags,
83 require_p, share_greet, use_invites, use_exempts, password_timeout,
84 force_expire, protect_readonly, reserved_port_min, reserved_port_max,
85 copy_to_tmp, quiet_reject;
86 extern volatile sig_atomic_t do_restart;
87
88 #ifdef IPV6
89 extern int pref_af;
90 #endif
91
92 #ifdef TLS
93 extern int tls_vfyclients, tls_vfydcc, tls_vfybots;
94 #endif
95
96 extern party_t *party;
97 extern time_t now, online_since;
98 extern tand_t *tandbot;
99 extern Tcl_Interp *interp;
100 extern sock_list *socklist;
101
102 int cmd_die();
103 int xtra_kill();
104 int xtra_unpack();
105 char *check_validpass();
106 static int module_rename(char *name, char *newname);
107
108 #ifndef STATIC
109 char moddir[121] = "modules/";
110 #endif
111
112 #ifdef STATIC
113 struct static_list {
114 struct static_list *next;
115 char *name;
116 char *(*func) ();
117 } *static_modules = NULL;
118
check_static(char * name,char * (* func)())119 void check_static(char *name, char *(*func) ())
120 {
121 struct static_list *p = nmalloc(sizeof(struct static_list));
122
123 p->name = nmalloc(strlen(name) + 1);
124 strcpy(p->name, name);
125 p->func = func;
126 p->next = static_modules;
127 static_modules = p;
128 }
129 #endif /* STATIC */
130
131
132 /* The null functions */
null_func()133 void null_func()
134 {
135 }
136
false_func()137 int false_func()
138 {
139 return 0;
140 }
141
142
143 /* The REAL hooks. When these are called, a return of 0 indicates unhandled;
144 * 1 indicates handled. */
145 struct hook_entry *hook_list[REAL_HOOKS];
146
null_share(int idx,char * x)147 static void null_share(int idx, char *x)
148 {
149 if ((x[0] == 'u') && (x[1] == 'n')) {
150 putlog(LOG_BOTS, "*", "User file rejected by %s: %s", dcc[idx].nick, x + 3);
151 dcc[idx].status &= ~STAT_OFFERED;
152 if (!(dcc[idx].status & STAT_GETTING)) {
153 dcc[idx].status &= ~STAT_SHARE;
154 }
155 } else if ((x[0] != 'v') && (x[0] != 'e')) {
156 dprintf(idx, "s un Not sharing userfile.\n");
157 }
158 }
159
160 void (*encrypt_pass) (char *, char *) = 0;
161 char *(*encrypt_pass2) (char *) = 0;
162 char *(*verify_pass2) (char *, char *) = 0;
163 char *(*encrypt_string) (char *, char *) = 0;
164 char *(*decrypt_string) (char *, char *) = 0;
165 void (*shareout) () = null_func;
166 void (*sharein) (int, char *) = null_share;
167 void (*qserver) (int, char *, int) = (void (*)(int, char *, int)) null_func;
168 void (*add_mode) () = null_func;
169 int (*match_noterej) (struct userrec *, char *) =
170 (int (*)(struct userrec *, char *)) false_func;
171 int (*rfc_casecmp) (const char *, const char *) = _rfc_casecmp;
172 int (*rfc_ncasecmp) (const char *, const char *, int) = _rfc_ncasecmp;
173 int (*rfc_toupper) (int) = _rfc_toupper;
174 int (*rfc_tolower) (int) = _rfc_tolower;
175 void (*dns_hostbyip) (sockname_t *) = core_dns_hostbyip;
176 void (*dns_ipbyhost) (char *) = core_dns_ipbyhost;
177
178 module_entry *module_list;
179 dependancy *dependancy_list = NULL;
180
181 /* The horrible global lookup table for functions
182 * BUT it makes the whole thing *much* more portable than letting each
183 * OS screw up the symbols their own special way :/
184 */
185 Function global_table[] = {
186 /* 0 - 3 */
187 (Function) mod_malloc,
188 (Function) mod_free,
189 #ifdef DEBUG_CONTEXT
190 (Function) eggContext,
191 #else
192 (Function) 0,
193 #endif
194 (Function) module_rename,
195 /* 4 - 7 */
196 (Function) module_register,
197 (Function) module_find,
198 (Function) module_depend,
199 (Function) module_undepend,
200 /* 8 - 11 */
201 (Function) add_bind_table,
202 (Function) del_bind_table,
203 (Function) find_bind_table,
204 (Function) check_tcl_bind,
205 /* 12 - 15 */
206 (Function) add_builtins,
207 (Function) rem_builtins,
208 (Function) add_tcl_commands,
209 (Function) rem_tcl_commands,
210 /* 16 - 19 */
211 (Function) add_tcl_ints,
212 (Function) rem_tcl_ints,
213 (Function) add_tcl_strings,
214 (Function) rem_tcl_strings,
215 /* 20 - 23 */
216 (Function) base64_to_int,
217 (Function) int_to_base64,
218 (Function) int_to_base10,
219 (Function) simple_sprintf,
220 /* 24 - 27 */
221 (Function) botnet_send_zapf,
222 (Function) botnet_send_zapf_broad,
223 (Function) botnet_send_unlinked,
224 (Function) botnet_send_bye,
225 /* 28 - 31 */
226 (Function) botnet_send_chat,
227 (Function) botnet_send_filereject,
228 (Function) botnet_send_filesend,
229 (Function) botnet_send_filereq,
230 /* 32 - 35 */
231 (Function) botnet_send_join_idx,
232 (Function) botnet_send_part_idx,
233 (Function) updatebot,
234 (Function) nextbot,
235 /* 36 - 39 */
236 (Function) zapfbot,
237 (Function) n_free,
238 (Function) u_pass_match,
239 (Function) _user_malloc,
240 /* 40 - 43 */
241 (Function) get_user,
242 (Function) set_user,
243 (Function) add_entry_type,
244 (Function) del_entry_type,
245 /* 44 - 47 */
246 (Function) get_user_flagrec,
247 (Function) set_user_flagrec,
248 (Function) get_user_by_host,
249 (Function) get_user_by_handle,
250 /* 48 - 51 */
251 (Function) find_entry_type,
252 (Function) find_user_entry,
253 (Function) adduser,
254 (Function) deluser,
255 /* 52 - 55 */
256 (Function) addhost_by_handle,
257 (Function) delhost_by_handle,
258 (Function) readuserfile,
259 (Function) write_userfile,
260 /* 56 - 59 */
261 (Function) geticon,
262 (Function) clear_chanlist,
263 (Function) reaffirm_owners,
264 (Function) change_handle,
265 /* 60 - 63 */
266 (Function) write_user,
267 (Function) clear_userlist,
268 (Function) count_users,
269 (Function) sanity_check,
270 /* 64 - 67 */
271 (Function) break_down_flags,
272 (Function) build_flags,
273 (Function) flagrec_eq,
274 (Function) flagrec_ok,
275 /* 68 - 71 */
276 (Function) & shareout,
277 (Function) dprintf,
278 (Function) chatout,
279 (Function) chanout_but,
280 /* 72 - 75 */
281 (Function) check_validity,
282 (Function) egg_list_delete,
283 (Function) egg_list_append,
284 (Function) egg_list_contains,
285 /* 76 - 79 */
286 (Function) answer,
287 (Function) getvhost,
288 #ifdef TLS
289 (Function) ssl_handshake,
290 #else
291 (Function) 0,
292 #endif
293 (Function) tputs,
294 /* 80 - 83 */
295 (Function) new_dcc,
296 (Function) lostdcc,
297 (Function) getsock,
298 (Function) killsock,
299 /* 84 - 87 */
300 (Function) open_listen,
301 (Function) getdccaddr,
302 (Function) _get_data_ptr,
303 (Function) open_telnet,
304 /* 88 - 91 */
305 (Function) check_tcl_event,
306 (Function) 0, /* was egg_memcpy -- use memcpy() instead */
307 (Function) my_atoul,
308 (Function) my_strcpy,
309 /* 92 - 95 */
310 (Function) & dcc, /* struct dcc_t * */
311 (Function) & chanset, /* struct chanset_t * */
312 (Function) & userlist, /* struct userrec * */
313 (Function) & lastuser, /* struct userrec * */
314 /* 96 - 99 */
315 (Function) & global_bans, /* struct banrec * */
316 (Function) & global_ign, /* struct igrec * */
317 (Function) & password_timeout, /* int */
318 (Function) & share_greet, /* int */
319 /* 100 - 103 */
320 (Function) & max_dcc, /* int */
321 (Function) & require_p, /* int */
322 (Function) & ignore_time, /* int */
323 #ifdef TLS
324 (Function) dcc_fingerprint,
325 #else
326 (Function) 0, /* was use_console_r <Wcc[02/02/03]> */
327 #endif
328 /* 104 - 107 */
329 (Function) & reserved_port_min,
330 (Function) & reserved_port_max,
331 (Function) & raw_log, /* int */
332 (Function) & noshare, /* int */
333 /* 108 - 111 */
334 #ifdef TLS
335 (Function) & tls_vfybots, /* int */
336 #else
337 (Function) 0, /* gban_total -- UNUSED! (Eule) */
338 #endif
339 (Function) & make_userfile, /* int */
340 (Function) & default_flags, /* int */
341 (Function) & dcc_total, /* int */
342 /* 112 - 115 */
343 (Function) 0, /* was tempdir */
344 #ifdef TLS
345 (Function) & tls_vfyclients, /* int */
346 (Function) & tls_vfydcc, /* int */
347 #else
348 (Function) 0, /* was natip -- use getmyip() instead */
349 (Function) 0, /* was myip -- use getvhost() instead */
350 #endif
351 (Function) origbotname, /* char * */
352 /* 116 - 119 */
353 (Function) botuser, /* char * */
354 (Function) admin, /* char * */
355 (Function) userfile, /* char * */
356 (Function) ver, /* char * */
357 /* 120 - 123 */
358 (Function) notify_new, /* char * */
359 (Function) helpdir, /* char * */
360 (Function) version, /* char * */
361 (Function) botnetnick, /* char * */
362 /* 124 - 127 */
363 (Function) & DCC_CHAT_PASS, /* struct dcc_table * */
364 (Function) & DCC_BOT, /* struct dcc_table * */
365 (Function) & DCC_LOST, /* struct dcc_table * */
366 (Function) & DCC_CHAT, /* struct dcc_table * */
367 /* 128 - 131 */
368 (Function) & interp, /* Tcl_Interp * */
369 (Function) & now, /* time_t */
370 (Function) findanyidx,
371 (Function) findchan,
372 /* 132 - 135 */
373 (Function) cmd_die,
374 (Function) days,
375 (Function) daysago,
376 (Function) daysdur,
377 /* 136 - 139 */
378 (Function) ismember,
379 (Function) newsplit,
380 (Function) splitnick,
381 (Function) splitc,
382 /* 140 - 143 */
383 (Function) addignore,
384 (Function) match_ignore,
385 (Function) delignore,
386 (Function) fatal,
387 /* 144 - 147 */
388 (Function) xtra_kill,
389 (Function) xtra_unpack,
390 (Function) movefile,
391 (Function) copyfile,
392 /* 148 - 151 */
393 (Function) do_tcl,
394 (Function) readtclprog,
395 (Function) get_language,
396 (Function) def_get,
397 /* 152 - 155 */
398 (Function) makepass,
399 (Function) _wild_match,
400 (Function) maskaddr,
401 (Function) show_motd,
402 /* 156 - 159 */
403 (Function) tellhelp,
404 (Function) showhelp,
405 (Function) add_help_reference,
406 (Function) rem_help_reference,
407 /* 160 - 163 */
408 (Function) touch_laston,
409 (Function) & add_mode, /* Function * */
410 (Function) rmspace,
411 (Function) in_chain,
412 /* 164 - 167 */
413 (Function) add_note,
414 (Function) del_lang_section,
415 (Function) detect_dcc_flood,
416 (Function) flush_lines,
417 /* 168 - 171 */
418 (Function) expected_memory,
419 (Function) tell_mem_status,
420 (Function) & do_restart, /* volatile sig_atomic_t */
421 (Function) check_tcl_filt,
422 /* 172 - 175 */
423 (Function) add_hook,
424 (Function) del_hook,
425 (Function) & H_dcc, /* p_tcl_bind_list * */
426 (Function) & H_filt, /* p_tcl_bind_list * */
427 /* 176 - 179 */
428 (Function) & H_chon, /* p_tcl_bind_list * */
429 (Function) & H_chof, /* p_tcl_bind_list * */
430 (Function) & H_load, /* p_tcl_bind_list * */
431 (Function) & H_unld, /* p_tcl_bind_list * */
432 /* 180 - 183 */
433 (Function) & H_chat, /* p_tcl_bind_list * */
434 (Function) & H_act, /* p_tcl_bind_list * */
435 (Function) & H_bcst, /* p_tcl_bind_list * */
436 (Function) & H_bot, /* p_tcl_bind_list * */
437 /* 184 - 187 */
438 (Function) & H_link, /* p_tcl_bind_list * */
439 (Function) & H_disc, /* p_tcl_bind_list * */
440 (Function) & H_away, /* p_tcl_bind_list * */
441 (Function) & H_nkch, /* p_tcl_bind_list * */
442 /* 188 - 191 */
443 (Function) & USERENTRY_BOTADDR, /* struct user_entry_type * */
444 (Function) & USERENTRY_BOTFL, /* struct user_entry_type * */
445 (Function) & USERENTRY_HOSTS, /* struct user_entry_type * */
446 (Function) & USERENTRY_PASS, /* struct user_entry_type * */
447 /* 192 - 195 */
448 (Function) & USERENTRY_XTRA, /* struct user_entry_type * */
449 (Function) user_del_chan,
450 (Function) & USERENTRY_INFO, /* struct user_entry_type * */
451 (Function) & USERENTRY_COMMENT, /* struct user_entry_type * */
452 /* 196 - 199 */
453 (Function) & USERENTRY_LASTON, /* struct user_entry_type * */
454 (Function) putlog,
455 (Function) botnet_send_chan,
456 (Function) list_type_kill,
457 /* 200 - 203 */
458 (Function) logmodes,
459 (Function) masktype,
460 (Function) stripmodes,
461 (Function) stripmasktype,
462 /* 204 - 207 */
463 (Function) sub_lang,
464 (Function) & online_since, /* time_t * */
465 (Function) cmd_loadlanguage,
466 (Function) check_dcc_attrs,
467 /* 208 - 211 */
468 (Function) check_dcc_chanattrs,
469 (Function) add_tcl_coups,
470 (Function) rem_tcl_coups,
471 (Function) botname,
472 /* 212 - 215 */
473 (Function) 0, /* remove_gunk() -- UNUSED! (drummer) */
474 (Function) check_tcl_chjn,
475 (Function) sanitycheck_dcc,
476 (Function) isowner,
477 /* 216 - 219 */
478 (Function) fcopyfile,
479 (Function) copyfilef,
480 (Function) & rfc_casecmp, /* Function * */
481 (Function) & rfc_ncasecmp, /* Function * */
482 /* 220 - 223 */
483 (Function) & global_exempts, /* struct exemptrec * */
484 (Function) & global_invites, /* struct inviterec * */
485 (Function) 0, /* ginvite_total -- UNUSED! (Eule) */
486 (Function) 0, /* gexempt_total -- UNUSED! (Eule) */
487 /* 224 - 227 */
488 (Function) & H_event, /* p_tcl_bind_list * */
489 (Function) & use_exempts, /* int */
490 (Function) & use_invites, /* int */
491 (Function) & force_expire, /* int */
492 /* 228 - 231 */
493 (Function) add_lang_section,
494 (Function) _user_realloc,
495 (Function) mod_realloc,
496 (Function) xtra_set,
497 /* 232 - 235 */
498 #ifdef DEBUG_CONTEXT
499 (Function) eggContextNote,
500 #else
501 (Function) 0,
502 #endif
503 #ifdef DEBUG_ASSERT
504 (Function) eggAssert,
505 #else
506 (Function) 0,
507 #endif
508 (Function) allocsock,
509 (Function) call_hostbyip,
510 /* 236 - 239 */
511 (Function) call_ipbyhost,
512 (Function) iptostr,
513 (Function) & DCC_DNSWAIT, /* struct dcc_table * */
514 (Function) hostsanitycheck_dcc,
515 /* 240 - 243 */
516 (Function) dcc_dnsipbyhost,
517 (Function) dcc_dnshostbyip,
518 (Function) changeover_dcc,
519 (Function) make_rand_str,
520 /* 244 - 247 */
521 (Function) & protect_readonly, /* int */
522 (Function) findchan_by_dname,
523 (Function) removedcc,
524 (Function) & userfile_perm, /* int */
525 /* 248 - 251 */
526 (Function) sock_has_data,
527 (Function) bots_in_subtree,
528 (Function) users_in_subtree,
529 (Function) egg_inet_aton,
530 /* 252 - 255 */
531 (Function) egg_snprintf,
532 (Function) egg_vsnprintf,
533 (Function) 0, /* was egg_memset -- use memset() or egg_bzero() instead */
534 (Function) 0, /* was egg_strcasecmp -- use strcasecmp() instead */
535 /* 256 - 259 */
536 (Function) 0, /* was egg_strncasecmp -- use strncasecmp() instead */
537 (Function) is_file,
538 (Function) & must_be_owner, /* int */
539 (Function) & tandbot, /* tand_t * */
540 /* 260 - 263 */
541 (Function) & party, /* party_t * */
542 (Function) open_address_listen,
543 (Function) str_escape,
544 (Function) strchr_unescape,
545 /* 264 - 267 */
546 (Function) str_unescape,
547 (Function) egg_strcatn,
548 (Function) clear_chanlist_member,
549 (Function) 0, /* was fixfrom */
550 /* 268 - 271 */
551 (Function) & socklist, /* sock_list * */
552 (Function) sockoptions,
553 (Function) flush_inbuf,
554 (Function) kill_bot,
555 /* 272 - 275 */
556 (Function) quit_msg, /* char * */
557 (Function) module_load,
558 (Function) module_unload,
559 (Function) & parties, /* int */
560 /* 276 - 279 */
561 (Function) tell_bottree,
562 (Function) MD5_Init,
563 (Function) MD5_Update,
564 (Function) MD5_Final,
565 /* 280 - 283 */
566 (Function) _wild_match_per,
567 (Function) killtransfer,
568 (Function) write_ignores,
569 (Function) & copy_to_tmp, /* int */
570 /* 284 - 287 */
571 (Function) & quiet_reject, /* int */
572 (Function) file_readable,
573 (Function) setsockname,
574 (Function) open_telnet_raw,
575 /* 288 - 291 */
576 #ifdef IPV6
577 (Function) & pref_af, /* int */
578 #else
579 (Function) 0, /* IPv6 leftovers: 288 */
580 #endif
581 (Function) strip_mirc_codes,
582 (Function) check_ansi,
583 (Function) oatoi,
584 /* 292 - 295 */
585 (Function) str_isdigit,
586 (Function) remove_crlf,
587 (Function) addr_match,
588 (Function) mask_match,
589 /* 296 - 299 */
590 (Function) check_conflags,
591 (Function) increase_socks_max,
592 (Function) log_ts,
593 (Function) tcl_resultempty,
594 /* 300 - 303 */
595 (Function) tcl_resultint,
596 (Function) tcl_resultstring,
597 (Function) getdccfamilyaddr,
598 #ifndef HAVE_STRLCPY
599 (Function) strlcpy,
600 #else
601 (Function) 0,
602 #endif
603 /* 304 - 307 */
604 (Function) strncpyz,
605 #ifndef HAVE_BASE64
606 (Function) b64_ntop,
607 (Function) b64_pton,
608 #else
609 (Function) 0,
610 (Function) 0,
611 #endif
612 (Function) check_validpass,
613 /* 308 - 311 */
614 (Function) make_rand_str_from_chars,
615 (Function) add_tcl_objcommands,
616 (Function) pid_file, /* char */
617 #ifndef HAVE_EXPLICIT_BZERO
618 (Function) explicit_bzero,
619 #else
620 (Function) 0,
621 #endif
622 /* 312 - 315 */
623 (Function) & USERENTRY_PASS2, /* struct user_entry_type * */
624 (Function) crypto_verify,
625 (Function) egg_uname,
626 (Function) get_expire_time
627 };
628
init_modules(void)629 void init_modules(void)
630 {
631 int i;
632
633 module_list = nmalloc(sizeof(module_entry));
634 module_list->name = nmalloc(8);
635 strcpy(module_list->name, "eggdrop");
636 module_list->major = (egg_numver) / 10000;
637 module_list->minor = (egg_numver / 100) % 100;
638 #ifndef STATIC
639 module_list->hand = NULL;
640 #endif
641 module_list->next = NULL;
642 module_list->funcs = NULL;
643 for (i = 0; i < REAL_HOOKS; i++)
644 hook_list[i] = NULL;
645 }
646
expmem_modules(int y)647 int expmem_modules(int y)
648 {
649 int c = 0, i;
650 module_entry *p;
651 dependancy *d;
652 struct hook_entry *q;
653 Function *f;
654 #ifdef STATIC
655 struct static_list *s;
656
657 for (s = static_modules; s; s = s->next)
658 c += sizeof(struct static_list) + strlen(s->name) + 1;
659 #endif
660
661 for (i = 0; i < REAL_HOOKS; i++)
662 for (q = hook_list[i]; q; q = q->next)
663 c += sizeof(struct hook_entry);
664
665 for (d = dependancy_list; d; d = d->next)
666 c += sizeof(dependancy);
667
668 for (p = module_list; p; p = p->next) {
669 c += sizeof(module_entry);
670 c += strlen(p->name) + 1;
671 f = p->funcs;
672 if (f && f[MODCALL_EXPMEM] && !y)
673 c += (int) (f[MODCALL_EXPMEM] ());
674 }
675 return c;
676 }
677
module_register(char * name,Function * funcs,int major,int minor)678 int module_register(char *name, Function *funcs, int major, int minor)
679 {
680 module_entry *p;
681
682 for (p = module_list; p && p->name; p = p->next) {
683 if (!strcasecmp(name, p->name)) {
684 p->major = major;
685 p->minor = minor;
686 p->funcs = funcs;
687 return 1;
688 }
689 }
690
691 return 0;
692 }
693
module_load(char * name)694 const char *module_load(char *name)
695 {
696 module_entry *p;
697 char *e;
698 Function f;
699 #ifdef STATIC
700 struct static_list *sl;
701 #endif
702
703 #ifndef STATIC
704 char workbuf[1024];
705 # ifdef MOD_USE_SHL
706 shl_t hand;
707 # endif
708 # ifdef MOD_USE_DYLD
709 NSObjectFileImage file;
710 NSObjectFileImageReturnCode ret;
711 NSModule hand;
712 NSSymbol sym;
713 # endif
714 # ifdef MOD_USE_RLD
715 long ret;
716 # endif
717 # ifdef MOD_USE_LOADER
718 ldr_module_t hand;
719 # endif
720 # ifdef MOD_USE_DL
721 void *hand;
722 # endif
723 #endif /* !STATIC */
724
725 if (module_find(name, 0, 0) != NULL)
726 return MOD_ALREADYLOAD;
727
728 #ifndef STATIC
729 if (moddir[0] != '/') {
730 if (getcwd(workbuf, 1024) == NULL)
731 return MOD_BADCWD;
732 sprintf(&(workbuf[strlen(workbuf)]), "/%s%s." EGG_MOD_EXT, moddir, name);
733 } else {
734 sprintf(workbuf, "%s%s." EGG_MOD_EXT, moddir, name);
735 }
736
737 # ifdef MOD_USE_SHL
738 hand = shl_load(workbuf, BIND_IMMEDIATE, 0L);
739 if (!hand)
740 return "Can't load module.";
741 sprintf(workbuf, "%s_start", name);
742 if (shl_findsym(&hand, workbuf, (short) TYPE_PROCEDURE, (void *) &f))
743 f = NULL;
744 if (f == NULL) {
745 /* Some OS's require a _ to be prepended to the symbol name (Darwin, etc). */
746 sprintf(workbuf, "_%s_start", name);
747 if (shl_findsym(&hand, workbuf, (short) TYPE_PROCEDURE, (void *) &f))
748 f = NULL;
749 }
750 if (f == NULL) {
751 shl_unload(hand);
752 return MOD_NOSTARTDEF;
753 }
754 # endif /* MOD_USE_SHL */
755
756 # ifdef MOD_USE_DYLD
757 ret = NSCreateObjectFileImageFromFile(workbuf, &file);
758 if (ret != NSObjectFileImageSuccess)
759 return "Can't load module.";
760 hand = NSLinkModule(file, workbuf, DYLDFLAGS);
761 sprintf(workbuf, "_%s_start", name);
762 sym = NSLookupSymbolInModule(hand, workbuf);
763 if (sym)
764 f = (Function) NSAddressOfSymbol(sym);
765 else
766 f = NULL;
767 if (f == NULL) {
768 NSUnLinkModule(hand, NSUNLINKMODULE_OPTION_NONE);
769 return MOD_NOSTARTDEF;
770 }
771 # endif /* MOD_USE_DYLD */
772
773 # ifdef MOD_USE_RLD
774 ret = rld_load(NULL, (struct mach_header **) 0, workbuf, (const char *) 0);
775 if (!ret)
776 return "Can't load module.";
777 sprintf(workbuf, "_%s_start", name);
778 ret = rld_lookup(NULL, workbuf, &f)
779 if (!ret || f == NULL)
780 return MOD_NOSTARTDEF;
781 /* There isn't a reliable way to unload at this point... just keep it loaded. */
782 # endif /* MOD_USE_DYLD */
783
784 # ifdef MOD_USE_LOADER
785 hand = load(workbuf, LDR_NOFLAGS);
786 if (hand == LDR_NULL_MODULE)
787 return "Can't load module.";
788 sprintf(workbuf, "%s_start", name);
789 f = (Function) ldr_lookup_package(hand, workbuf);
790 if (f == NULL) {
791 sprintf(workbuf, "_%s_start", name);
792 f = (Function) ldr_lookup_package(hand, workbuf);
793 }
794 if (f == NULL) {
795 unload(hand);
796 return MOD_NOSTARTDEF;
797 }
798 # endif /* MOD_USE_LOADER */
799
800 # ifdef MOD_USE_DL
801 hand = dlopen(workbuf, DLFLAGS);
802 if (!hand)
803 return dlerror();
804 sprintf(workbuf, "%s_start", name);
805 f = (Function) dlsym(hand, workbuf);
806 if (f == NULL) {
807 sprintf(workbuf, "_%s_start", name);
808 f = (Function) dlsym(hand, workbuf);
809 }
810 if (f == NULL) {
811 dlclose(hand);
812 return MOD_NOSTARTDEF;
813 }
814 # endif /* MOD_USE_DL */
815 #endif /* !STATIC */
816
817 #ifdef STATIC
818 for (sl = static_modules; sl && strcasecmp(sl->name, name); sl = sl->next);
819 if (!sl)
820 return "Unknown module.";
821 f = (Function) sl->func;
822 #endif /* STATIC */
823
824 p = nmalloc(sizeof(module_entry));
825 if (p == NULL)
826 return "Malloc error";
827 p->name = nmalloc(strlen(name) + 1);
828 strcpy(p->name, name);
829 p->major = 0;
830 p->minor = 0;
831 #ifndef STATIC
832 p->hand = hand;
833 #endif
834 p->funcs = 0;
835 p->next = module_list;
836 module_list = p;
837 e = (((char *(*)()) f) (global_table));
838 if (e) {
839 module_list = module_list->next;
840 nfree(p->name);
841 nfree(p);
842 return e;
843 }
844 check_tcl_load(name);
845
846 if (exist_lang_section(name))
847 putlog(LOG_MISC, "*", MOD_LOADED_WITH_LANG, name);
848 else
849 putlog(LOG_MISC, "*", MOD_LOADED, name);
850
851 return NULL;
852 }
853
module_unload(char * name,char * user)854 char *module_unload(char *name, char *user)
855 {
856 module_entry *p = module_list, *o = NULL;
857 char *e;
858 Function *f;
859
860 while (p) {
861 if ((p->name != NULL) && !strcmp(name, p->name)) {
862 dependancy *d;
863
864 for (d = dependancy_list; d; d = d->next)
865 if (d->needed == p)
866 return MOD_NEEDED;
867
868 f = p->funcs;
869 if (f && !f[MODCALL_CLOSE])
870 return MOD_NOCLOSEDEF;
871 if (f) {
872 check_tcl_unld(name);
873 e = (((char *(*)()) f[MODCALL_CLOSE]) (user));
874 if (e != NULL)
875 return e;
876 #ifndef STATIC
877 # ifdef MOD_USE_SHL
878 shl_unload(p->hand);
879 # endif
880 # ifdef MOD_USE_DYLD
881 NSUnLinkModule(p->hand, NSUNLINKMODULE_OPTION_NONE);
882 # endif
883 # ifdef MOD_USE_LOADER
884 unload(p->hand);
885 # endif
886 # ifdef MOD_USE_DL
887 dlclose(p->hand);
888 # endif
889 #endif /* !STATIC */
890 }
891 nfree(p->name);
892 if (o == NULL)
893 module_list = p->next;
894 else
895 o->next = p->next;
896 nfree(p);
897 putlog(LOG_MISC, "*", "%s %s", MOD_UNLOADED, name);
898 return NULL;
899 }
900 o = p;
901 p = p->next;
902 }
903
904 return MOD_NOSUCH;
905 }
906
module_find(char * name,int major,int minor)907 module_entry *module_find(char *name, int major, int minor)
908 {
909 module_entry *p;
910
911 for (p = module_list; p && p->name; p = p->next) {
912 if ( (((major < p->major) || !major) || ((major == p->major) &&
913 (minor <= p->minor))) && !strcasecmp(name, p->name) )
914 return p;
915 }
916 return NULL;
917
918 }
919
module_rename(char * name,char * newname)920 static int module_rename(char *name, char *newname)
921 {
922 module_entry *p;
923
924 for (p = module_list; p; p = p->next)
925 if (!strcasecmp(newname, p->name))
926 return 0;
927
928 for (p = module_list; p && p->name; p = p->next) {
929 if (!strcasecmp(name, p->name)) {
930 nfree(p->name);
931 p->name = nmalloc(strlen(newname) + 1);
932 strcpy(p->name, newname);
933 return 1;
934 }
935 }
936 return 0;
937 }
938
module_depend(char * name1,char * name2,int major,int minor)939 Function *module_depend(char *name1, char *name2, int major, int minor)
940 {
941 module_entry *p = module_find(name2, major, minor);
942 module_entry *o = module_find(name1, 0, 0);
943 dependancy *d;
944
945 if (!p) {
946 if (module_load(name2))
947 return 0;
948 p = module_find(name2, major, minor);
949 }
950 if (!p || !o)
951 return 0;
952 d = nmalloc(sizeof(dependancy));
953
954 d->needed = p;
955 d->needing = o;
956 d->next = dependancy_list;
957 d->major = major;
958 d->minor = minor;
959 dependancy_list = d;
960 return p->funcs ? p->funcs : (Function *) 1;
961 }
962
module_undepend(char * name1)963 int module_undepend(char *name1)
964 {
965 int ok = 0;
966 module_entry *p = module_find(name1, 0, 0);
967 dependancy *d = dependancy_list, *o = NULL;
968
969 if (p == NULL)
970 return 0;
971 while (d != NULL) {
972 if (d->needing == p) {
973 if (o == NULL) {
974 dependancy_list = d->next;
975 } else {
976 o->next = d->next;
977 }
978 nfree(d);
979 if (o == NULL)
980 d = dependancy_list;
981 else
982 d = o->next;
983 ok++;
984 } else {
985 o = d;
986 d = d->next;
987 }
988 }
989 return ok;
990 }
991
mod_malloc(int size,const char * modname,const char * filename,int line)992 void *mod_malloc(int size, const char *modname, const char *filename, int line)
993 {
994 #ifdef DEBUG_MEM
995 char x[100], *p;
996
997 p = strrchr(filename, '/');
998 egg_snprintf(x, sizeof x, "%s:%s", modname, p ? p + 1 : filename);
999 x[19] = 0;
1000 return n_malloc(size, x, line);
1001 #else
1002 return nmalloc(size);
1003 #endif
1004 }
1005
mod_realloc(void * ptr,int size,const char * modname,const char * filename,int line)1006 void *mod_realloc(void *ptr, int size, const char *modname,
1007 const char *filename, int line)
1008 {
1009 #ifdef DEBUG_MEM
1010 char x[100], *p;
1011
1012 p = strrchr(filename, '/');
1013 egg_snprintf(x, sizeof x, "%s:%s", modname, p ? p + 1 : filename);
1014 x[19] = 0;
1015 return n_realloc(ptr, size, x, line);
1016 #else
1017 return nrealloc(ptr, size);
1018 #endif
1019 }
1020
mod_free(void * ptr,const char * modname,const char * filename,int line)1021 void mod_free(void *ptr, const char *modname, const char *filename, int line)
1022 {
1023 char x[100], *p;
1024
1025 p = strrchr(filename, '/');
1026 egg_snprintf(x, sizeof x, "%s:%s", modname, p ? p + 1 : filename);
1027 x[19] = 0;
1028 n_free(ptr, x, line);
1029 }
1030
1031 /* Hooks, various tables of functions to call on certain events
1032 */
add_hook(int hook_num,Function func)1033 void add_hook(int hook_num, Function func)
1034 {
1035 if (hook_num < REAL_HOOKS) {
1036 struct hook_entry *p;
1037
1038 for (p = hook_list[hook_num]; p; p = p->next)
1039 if (p->func == func)
1040 return; /* Don't add it if it's already there */
1041 p = nmalloc(sizeof(struct hook_entry));
1042
1043 p->next = hook_list[hook_num];
1044 hook_list[hook_num] = p;
1045 p->func = func;
1046 } else
1047 switch (hook_num) {
1048 case HOOK_ENCRYPT_PASS:
1049 encrypt_pass = (void (*)(char *, char *)) func;
1050 break;
1051 case HOOK_ENCRYPT_PASS2:
1052 encrypt_pass2 = (char *(*)(char *)) func;
1053 break;
1054 case HOOK_VERIFY_PASS2:
1055 verify_pass2 = (char *(*)(char *, char*)) func;
1056 break;
1057 case HOOK_ENCRYPT_STRING:
1058 encrypt_string = (char *(*)(char *, char *)) func;
1059 break;
1060 case HOOK_DECRYPT_STRING:
1061 decrypt_string = (char *(*)(char *, char *)) func;
1062 break;
1063 case HOOK_SHAREOUT:
1064 shareout = (void (*)()) func;
1065 break;
1066 case HOOK_SHAREIN:
1067 sharein = (void (*)(int, char *)) func;
1068 break;
1069 case HOOK_QSERV:
1070 if (qserver == (void (*)(int, char *, int)) null_func)
1071 qserver = (void (*)(int, char *, int)) func;
1072 break;
1073 case HOOK_ADD_MODE:
1074 if (add_mode == (void (*)()) null_func)
1075 add_mode = (void (*)()) func;
1076 break;
1077 /* special hook <drummer> */
1078 case HOOK_RFC_CASECMP:
1079 if (func == NULL) {
1080 rfc_casecmp = egg_strcasecmp;
1081 rfc_ncasecmp =
1082 (int (*)(const char *, const char *, int)) egg_strncasecmp;
1083 rfc_tolower = tolower;
1084 rfc_toupper = toupper;
1085 } else {
1086 rfc_casecmp = _rfc_casecmp;
1087 rfc_ncasecmp = _rfc_ncasecmp;
1088 rfc_tolower = _rfc_tolower;
1089 rfc_toupper = _rfc_toupper;
1090 }
1091 break;
1092 case HOOK_MATCH_NOTEREJ:
1093 if (match_noterej == false_func)
1094 match_noterej = (int (*)(struct userrec *, char *)) func;
1095 break;
1096 case HOOK_DNS_HOSTBYIP:
1097 if (dns_hostbyip == core_dns_hostbyip)
1098 dns_hostbyip = (void (*)(sockname_t *)) func;
1099 break;
1100 case HOOK_DNS_IPBYHOST:
1101 if (dns_ipbyhost == core_dns_ipbyhost)
1102 dns_ipbyhost = (void (*)(char *)) func;
1103 break;
1104 }
1105 }
1106
del_hook(int hook_num,Function func)1107 void del_hook(int hook_num, Function func)
1108 {
1109 if (hook_num < REAL_HOOKS) {
1110 struct hook_entry *p = hook_list[hook_num], *o = NULL;
1111
1112 while (p) {
1113 if (p->func == func) {
1114 if (o == NULL)
1115 hook_list[hook_num] = p->next;
1116 else
1117 o->next = p->next;
1118 nfree(p);
1119 break;
1120 }
1121 o = p;
1122 p = p->next;
1123 }
1124 } else
1125 switch (hook_num) {
1126 case HOOK_ENCRYPT_PASS:
1127 if (encrypt_pass == (void (*)(char *, char *)) func)
1128 encrypt_pass = (void (*)(char *, char *)) null_func;
1129 break;
1130 case HOOK_ENCRYPT_PASS2:
1131 if (encrypt_pass2 == (char *(*)(char *)) func)
1132 encrypt_pass2 = (char *(*)(char *)) null_func;
1133 break;
1134 case HOOK_VERIFY_PASS2:
1135 if (verify_pass2 == (char *(*)(char *, char *)) func)
1136 verify_pass2 = (char *(*)(char *, char *)) null_func;
1137 break;
1138 case HOOK_ENCRYPT_STRING:
1139 if (encrypt_string == (char *(*)(char *, char *)) func)
1140 encrypt_string = (char *(*)(char *, char *)) null_func;
1141 break;
1142 case HOOK_DECRYPT_STRING:
1143 if (decrypt_string == (char *(*)(char *, char *)) func)
1144 decrypt_string = (char *(*)(char *, char *)) null_func;
1145 break;
1146 case HOOK_SHAREOUT:
1147 if (shareout == (void (*)()) func)
1148 shareout = null_func;
1149 break;
1150 case HOOK_SHAREIN:
1151 if (sharein == (void (*)(int, char *)) func)
1152 sharein = null_share;
1153 break;
1154 case HOOK_QSERV:
1155 if (qserver == (void (*)(int, char *, int)) func)
1156 qserver = null_func;
1157 break;
1158 case HOOK_ADD_MODE:
1159 if (add_mode == (void (*)()) func)
1160 add_mode = null_func;
1161 break;
1162 case HOOK_MATCH_NOTEREJ:
1163 if (match_noterej == (int (*)(struct userrec *, char *)) func)
1164 match_noterej = false_func;
1165 break;
1166 case HOOK_DNS_HOSTBYIP:
1167 if (dns_hostbyip == (void (*)(sockname_t *)) func)
1168 dns_hostbyip = core_dns_hostbyip;
1169 break;
1170 case HOOK_DNS_IPBYHOST:
1171 if (dns_ipbyhost == (void (*)(char *)) func)
1172 dns_ipbyhost = core_dns_ipbyhost;
1173 break;
1174 }
1175 }
1176
do_module_report(int idx,int details,char * which)1177 void do_module_report(int idx, int details, char *which)
1178 {
1179 module_entry *p = module_list;
1180
1181 if (p && !which)
1182 dprintf(idx, "Loaded module information:\n");
1183 for (; p; p = p->next) {
1184 if (!which || !strcasecmp(which, p->name)) {
1185 dependancy *d;
1186
1187 if (details)
1188 dprintf(idx, " Module: %s, v %d.%d\n", p->name ? p->name : "CORE",
1189 p->major, p->minor);
1190 if (details > 1) {
1191 for (d = dependancy_list; d; d = d->next)
1192 if (d->needing == p)
1193 dprintf(idx, " requires: %s, v %d.%d\n", d->needed->name,
1194 d->major, d->minor);
1195 }
1196 if (p->funcs) {
1197 Function f = p->funcs[MODCALL_REPORT];
1198
1199 if (f != NULL)
1200 f(idx, details);
1201 }
1202 if (which)
1203 return;
1204 }
1205 }
1206 if (which)
1207 dprintf(idx, "No such module.\n");
1208 }
1209