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