/* * ================================================================= * Filename: hostnameonly.c * Description: Host-name only connections * Author: AngryWolf * Documentation: hostnameonly.txt (comes with the package) * ================================================================= */ #include "config.h" #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "msg.h" #include "channel.h" #include #include #include #include #include #ifdef _WIN32 #include #endif #include #include "h.h" #ifdef STRIPBADWORDS #include "badwords.h" #endif #ifdef _WIN32 #include "version.h" #endif extern ConfigEntry *config_find_entry(ConfigEntry *ce, char *name); extern void sendto_one(aClient *to, char *pattern, ...); #define DEF_REASON "Couldn't resolve your hostname; connection refused" #define DelHook(x) if (x) HookDel(x); x = NULL #define ircstrdup(x,y) if (x) MyFree(x); if (!y) x = NULL; else x = strdup(y) #define ircfree(x) if (x) MyFree(x); x = NULL static int cb_test(ConfigFile *, ConfigEntry *, int, int *); static int cb_conf(ConfigFile *, ConfigEntry *, int); static int cb_rehash(); static int cb_stats(aClient *sptr, char *stats); static int cb_pre_connect(aClient *sptr); static Hook *HookConfTest = NULL, *HookConfRun = NULL, *HookConfRehash = NULL; static Hook *HookPreConn = NULL, *HookStats = NULL; static unsigned hostnameonly_enable; static unsigned hostnameonly_notify; static char *hostnameonly_reason; ModuleHeader MOD_HEADER(hostnameonly) = { "hostnameonly", "$Id: hostnameonly.c,v 4.1 2004/07/05 09:53:11 angrywolf Exp $", "hostname-only connections", "3.2-b8-1", NULL }; // ================================================================= // Functions related to loading/unloading configuration // ================================================================= static void InitConf() { hostnameonly_enable = 0; hostnameonly_notify = 0; hostnameonly_reason = NULL; } static void FreeConf() { ircfree(hostnameonly_reason); } // ================================================================= // Module functions // ================================================================= DLLFUNC int MOD_TEST(hostnameonly)(ModuleInfo *modinfo) { HookConfTest = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGTEST, cb_test); return MOD_SUCCESS; } DLLFUNC int MOD_INIT(hostnameonly)(ModuleInfo *modinfo) { InitConf(); HookConfRun = HookAddEx(modinfo->handle, HOOKTYPE_CONFIGRUN, cb_conf); HookConfRehash = HookAddEx(modinfo->handle, HOOKTYPE_REHASH, cb_rehash); HookStats = HookAddEx(modinfo->handle, HOOKTYPE_STATS, cb_stats); HookPreConn = HookAddEx(modinfo->handle, HOOKTYPE_PRE_LOCAL_CONNECT, cb_pre_connect); return MOD_SUCCESS; } DLLFUNC int MOD_LOAD(hostnameonly)(int module_load) { return MOD_SUCCESS; } DLLFUNC int MOD_UNLOAD(hostnameonly)(int module_unload) { FreeConf(); DelHook(HookPreConn); DelHook(HookStats); DelHook(HookConfRehash); DelHook(HookConfRun); DelHook(HookConfTest); return MOD_SUCCESS; } // ================================================================= // Config file interfacing // ================================================================= static int cb_rehash() { FreeConf(); InitConf(); return 1; } static int cb_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) { ConfigEntry *cep; int errors = 0; if (type != CONFIG_SET) return 0; if (!strcmp(ce->ce_varname, "hostnameonly")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!cep->ce_varname) { config_error("%s:%i: blank set::hostnameonly item", cep->ce_fileptr->cf_filename, cep->ce_varlinenum); errors++; continue; } if (!cep->ce_vardata) { config_error("%s:%i: set::hostnameonly::%s item without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname); errors++; continue; } if (!strcmp(cep->ce_varname, "enable")) ; else if (!strcmp(cep->ce_varname, "notify-opers")) ; else if (!strcmp(cep->ce_varname, "reason")) ; else { config_error("%s:%i: unknown directive set::hostnameonly::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname); errors++; } } *errs = errors; return errors ? -1 : 1; } else return 0; } static int cb_conf(ConfigFile *cf, ConfigEntry *ce, int type) { ConfigEntry *cep; if (type != CONFIG_SET) return 0; if (!strcmp(ce->ce_varname, "hostnameonly")) { for (cep = ce->ce_entries; cep; cep = cep->ce_next) { if (!strcmp(cep->ce_varname, "enable")) hostnameonly_enable = config_checkval(cep->ce_vardata, CFG_YESNO); if (!strcmp(cep->ce_varname, "notify-opers")) hostnameonly_notify = config_checkval(cep->ce_vardata, CFG_YESNO); if (!strcmp(cep->ce_varname, "reason")) { ircstrdup(hostnameonly_reason, cep->ce_vardata); } } return 1; } return 0; } static int cb_stats(aClient *sptr, char *stats) { if (*stats == 'S') { sendto_one(sptr, ":%s %i %s :hostnameonly::enable: %d", me.name, RPL_TEXT, sptr->name, hostnameonly_enable); sendto_one(sptr, ":%s %i %s :hostnameonly::notify-opers: %d", me.name, RPL_TEXT, sptr->name, hostnameonly_notify); sendto_one(sptr, ":%s %i %s :hostnameonly::reason: %s", me.name, RPL_TEXT, sptr->name, hostnameonly_reason ? hostnameonly_reason : ""); } return 0; } static int cb_pre_connect(aClient *sptr) { char *host, *ip_addr; if (hostnameonly_enable) { #ifdef GetIP ip_addr = GetIP(sptr); #else ip_addr = Inet_ia2p(&sptr->ip); #endif if (!strcmp(ip_addr, sptr->user->realhost)) { host = make_user_host(sptr->user->username, ip_addr); #ifdef GetIP if (Find_except(sptr, host, CONF_EXCEPT_BAN)) #else if (Find_except(host, CONF_EXCEPT_BAN)) #endif return 0; if (hostnameonly_notify) sendto_snomask(SNO_EYES, "*** Client %s!%s@%s has an IP address only; connection refused", sptr->name, sptr->user->username, ip_addr); return exit_client(sptr, sptr, sptr, hostnameonly_reason ? hostnameonly_reason : DEF_REASON); } } return 0; }