1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
19 #include "inspircd_config.h"
21 #include "inspircd_io.h"
22 #include "inspircd_util.h"
25 #include <sys/errno.h>
29 #include <ext/hash_map>
46 #include "inspstring.h"
47 #include "helperfuncs.h"
51 extern std::vector<Module*> modules;
52 extern std::vector<ircd_module*> factory;
55 extern char ServerName[MAXBUF];
56 extern char Network[MAXBUF];
57 extern char ServerDesc[MAXBUF];
58 extern char AdminName[MAXBUF];
59 extern char AdminEmail[MAXBUF];
60 extern char AdminNick[MAXBUF];
61 extern char diepass[MAXBUF];
62 extern char restartpass[MAXBUF];
63 extern char motd[MAXBUF];
64 extern char rules[MAXBUF];
65 extern char list[MAXBUF];
66 extern char PrefixQuit[MAXBUF];
67 extern char DieValue[MAXBUF];
70 extern int WHOWAS_STALE;
71 extern int WHOWAS_MAX;
73 extern time_t startup_time;
74 extern int NetBufferSize;
75 extern time_t nb_start;
77 extern std::vector<std::string> module_names;
79 extern int boundPortCount;
82 extern int ports[MAXSOCKS];
84 extern std::stringstream config_f;
86 extern FILE *log_file;
88 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, irc::StrHashComp> user_hash;
89 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, irc::StrHashComp> chan_hash;
90 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, irc::InAddr_HashComp> address_cache;
91 typedef nspace::hash_map<std::string, WhoWasUser*, nspace::hash<string>, irc::StrHashComp> whowas_hash;
92 typedef std::deque<command_t> command_table;
95 extern user_hash clientlist;
96 extern chan_hash chanlist;
97 extern whowas_hash whowas;
98 extern command_table cmdlist;
99 extern file_cache MOTD;
100 extern file_cache RULES;
101 extern address_cache IP;
105 std::vector<KLine> klines;
106 std::vector<GLine> glines;
107 std::vector<ZLine> zlines;
108 std::vector<QLine> qlines;
109 std::vector<ELine> elines;
111 // Reads the default bans from the config file.
112 // only a very small number of bans are defined
113 // this way these days, such as qlines against
114 // services nicks, etc.
116 void read_xline_defaults()
123 for (int i = 0; i < ConfValueEnum("badip",&config_f); i++)
125 ConfValue("badip","ipmask",i,ipmask,&config_f);
126 ConfValue("badip","reason",i,reason,&config_f);
127 add_zline(0,"<Config>",reason,ipmask);
128 log(DEBUG,"Read Z line (badip tag): ipmask=%s reason=%s",ipmask,reason);
131 for (int i = 0; i < ConfValueEnum("badnick",&config_f); i++)
133 ConfValue("badnick","nick",i,nick,&config_f);
134 ConfValue("badnick","reason",i,reason,&config_f);
135 add_qline(0,"<Config>",reason,nick);
136 log(DEBUG,"Read Q line (badnick tag): nick=%s reason=%s",nick,reason);
139 for (int i = 0; i < ConfValueEnum("badhost",&config_f); i++)
141 ConfValue("badhost","host",i,host,&config_f);
142 ConfValue("badhost","reason",i,reason,&config_f);
143 add_kline(0,"<Config>",reason,host);
144 log(DEBUG,"Read K line (badhost tag): host=%s reason=%s",host,reason);
146 for (int i = 0; i < ConfValueEnum("exception",&config_f); i++)
148 ConfValue("exception","host",i,host,&config_f);
149 ConfValue("exception","reason",i,reason,&config_f);
150 add_eline(0,"<Config>",reason,host);
151 log(DEBUG,"Read E line (exception tag): host=%s reason=%s",host,reason);
157 void add_gline(long duration, const char* source,const char* reason,const char* hostmask)
161 item.duration = duration;
162 strlcpy(item.hostmask,hostmask,199);
163 strlcpy(item.reason,reason,MAXBUF);
164 strlcpy(item.source,source,255);
166 item.set_time = TIME;
167 glines.push_back(item);
170 // adds an e:line (exception to bans)
172 void add_eline(long duration, const char* source, const char* reason, const char* hostmask)
176 item.duration = duration;
177 strlcpy(item.hostmask,hostmask,199);
178 strlcpy(item.reason,reason,MAXBUF);
179 strlcpy(item.source,source,255);
181 item.set_time = TIME;
182 elines.push_back(item);
187 void add_qline(long duration, const char* source, const char* reason, const char* nickname)
191 item.duration = duration;
192 strlcpy(item.nick,nickname,63);
193 strlcpy(item.reason,reason,MAXBUF);
194 strlcpy(item.source,source,255);
196 item.is_global = false;
197 item.set_time = TIME;
198 qlines.push_back(item);
203 void add_zline(long duration, const char* source, const char* reason, const char* ipaddr)
207 item.duration = duration;
208 if (strchr(ipaddr,'@'))
210 while (*ipaddr != '@')
214 strlcpy(item.ipaddr,ipaddr,39);
215 strlcpy(item.reason,reason,MAXBUF);
216 strlcpy(item.source,source,255);
218 item.is_global = false;
219 item.set_time = TIME;
220 zlines.push_back(item);
225 void add_kline(long duration, const char* source, const char* reason, const char* hostmask)
229 item.duration = duration;
230 strlcpy(item.hostmask,hostmask,200);
231 strlcpy(item.reason,reason,MAXBUF);
232 strlcpy(item.source,source,255);
234 item.set_time = TIME;
235 klines.push_back(item);
238 // deletes a g:line, returns true if the line existed and was removed
240 bool del_gline(const char* hostmask)
242 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
244 if (!strcasecmp(hostmask,i->hostmask))
253 // deletes a e:line, returns true if the line existed and was removed
255 bool del_eline(const char* hostmask)
257 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
259 if (!strcasecmp(hostmask,i->hostmask))
268 // deletes a q:line, returns true if the line existed and was removed
270 bool del_qline(const char* nickname)
272 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
274 if (!strcasecmp(nickname,i->nick))
283 bool qline_make_global(const char* nickname)
285 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
287 if (!strcasecmp(nickname,i->nick))
296 bool zline_make_global(const char* ipaddr)
298 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
300 if (!strcasecmp(ipaddr,i->ipaddr))
309 // deletes a z:line, returns true if the line existed and was removed
311 bool del_zline(const char* ipaddr)
313 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
315 if (!strcasecmp(ipaddr,i->ipaddr))
324 // deletes a k:line, returns true if the line existed and was removed
326 bool del_kline(const char* hostmask)
328 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
330 if (!strcasecmp(hostmask,i->hostmask))
339 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
341 char* matches_qline(const char* nick)
345 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
347 if (match(nick,i->nick))
355 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
357 char* matches_gline(const char* host)
361 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
363 if (match(host,i->hostmask))
371 char* matches_exception(const char* host)
376 snprintf(host2,MAXBUF,"*@%s",host);
377 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
379 if ((match(host,i->hostmask)) || (match(host2,i->hostmask)))
388 void gline_set_creation_time(char* host, time_t create_time)
390 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
392 if (!strcasecmp(host,i->hostmask))
394 i->set_time = create_time;
401 void qline_set_creation_time(char* nick, time_t create_time)
403 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
405 if (!strcasecmp(nick,i->nick))
407 i->set_time = create_time;
414 void zline_set_creation_time(char* ip, time_t create_time)
416 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
418 if (!strcasecmp(ip,i->ipaddr))
420 i->set_time = create_time;
427 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
429 char* matches_zline(const char* ipaddr)
433 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
435 if (match(ipaddr,i->ipaddr))
443 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
445 char* matches_kline(const char* host)
449 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
451 if (match(host,i->hostmask))
459 // removes lines that have expired
463 bool go_again = true;
464 time_t current = TIME;
466 // because we mess up an iterator when we remove from the vector, we must bail from
467 // the loop early if we delete an item, therefore this outer while loop is required.
469 // 30/11/2005-- I can imagine that if we get a large number of *lines, this would perform dog slow.
470 // While we try and think of a better solution, for now I've simply split the loops up, instead of
471 // one huge while () -- this means if we remove a g-line, we only need to re-check glines, not z/g/.
472 // lines too, hopefully a little faster, even if it looks a little messier ;) --w00t
478 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
480 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
482 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
496 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
498 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
500 WriteOpers("Expiring timed E-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
514 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
516 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
518 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
532 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
534 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
536 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
551 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
553 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
555 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
564 // applies lines, removing clients and changing nicks etc as applicable
568 bool go_again = true;
572 if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()))
578 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
580 if (!strcasecmp(u->second->server,ServerName))
582 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
585 // ignore people matching exempts
586 if (matches_exception(host))
591 char* check = matches_gline(host);
594 WriteOpers("*** User %s matches G-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",check);
595 snprintf(reason,MAXBUF,"G-Lined: %s",check);
596 kill_link(u->second,reason);
603 char* check = matches_kline(host);
606 WriteOpers("*** User %s matches K-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",check);
607 snprintf(reason,MAXBUF,"K-Lined: %s",check);
608 kill_link(u->second,reason);
615 char* check = matches_qline(u->second->nick);
618 snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
619 WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",u->second->host,check);
620 kill_link(u->second,reason);
627 char* check = matches_zline(u->second->ip);
630 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
631 WriteOpers("*** User %s matches Z-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",u->second->host,check);
632 kill_link(u->second,reason);
642 void stats_k(userrec* user)
644 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
646 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
650 void stats_g(userrec* user)
652 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
654 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
658 void stats_q(userrec* user)
660 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
662 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
666 void stats_z(userrec* user)
668 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
670 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
674 void stats_e(userrec* user)
676 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
678 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);