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 * ---------------------------------------------------
20 #include "inspircd_io.h"
21 #include "inspircd_util.h"
22 #include "inspircd_config.h"
25 #include <sys/errno.h>
29 #include <ext/hash_map>
37 #include "connection.h"
48 #include "inspstring.h"
49 #include "helperfuncs.h"
53 extern std::vector<Module*> modules;
54 extern std::vector<ircd_module*> factory;
57 extern char ServerName[MAXBUF];
58 extern char Network[MAXBUF];
59 extern char ServerDesc[MAXBUF];
60 extern char AdminName[MAXBUF];
61 extern char AdminEmail[MAXBUF];
62 extern char AdminNick[MAXBUF];
63 extern char diepass[MAXBUF];
64 extern char restartpass[MAXBUF];
65 extern char motd[MAXBUF];
66 extern char rules[MAXBUF];
67 extern char list[MAXBUF];
68 extern char PrefixQuit[MAXBUF];
69 extern char DieValue[MAXBUF];
72 extern int WHOWAS_STALE;
73 extern int WHOWAS_MAX;
75 extern time_t startup_time;
76 extern int NetBufferSize;
77 extern time_t nb_start;
79 extern std::vector<std::string> module_names;
81 extern int boundPortCount;
83 extern int SERVERportCount;
84 extern int ports[MAXSOCKS];
85 extern int defaultRoute;
87 extern std::vector<long> auth_cookies;
88 extern std::stringstream config_f;
90 extern serverrec* me[32];
92 extern FILE *log_file;
94 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, irc::StrHashComp> user_hash;
95 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, irc::StrHashComp> chan_hash;
96 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, irc::InAddr_HashComp> address_cache;
97 typedef nspace::hash_map<std::string, WhoWasUser*, nspace::hash<string>, irc::StrHashComp> whowas_hash;
98 typedef std::deque<command_t> command_table;
101 extern user_hash clientlist;
102 extern chan_hash chanlist;
103 extern whowas_hash whowas;
104 extern command_table cmdlist;
105 extern file_cache MOTD;
106 extern file_cache RULES;
107 extern address_cache IP;
111 std::vector<KLine> klines;
112 std::vector<GLine> glines;
113 std::vector<ZLine> zlines;
114 std::vector<QLine> qlines;
115 std::vector<ELine> elines;
117 // Reads the default bans from the config file.
118 // only a very small number of bans are defined
119 // this way these days, such as qlines against
120 // services nicks, etc.
122 void read_xline_defaults()
129 for (int i = 0; i < ConfValueEnum("badip",&config_f); i++)
131 ConfValue("badip","ipmask",i,ipmask,&config_f);
132 ConfValue("badip","reason",i,reason,&config_f);
133 add_zline(0,"<Config>",reason,ipmask);
134 log(DEBUG,"Read Z line (badip tag): ipmask=%s reason=%s",ipmask,reason);
137 for (int i = 0; i < ConfValueEnum("badnick",&config_f); i++)
139 ConfValue("badnick","nick",i,nick,&config_f);
140 ConfValue("badnick","reason",i,reason,&config_f);
141 add_qline(0,"<Config>",reason,nick);
142 log(DEBUG,"Read Q line (badnick tag): nick=%s reason=%s",nick,reason);
145 for (int i = 0; i < ConfValueEnum("badhost",&config_f); i++)
147 ConfValue("badhost","host",i,host,&config_f);
148 ConfValue("badhost","reason",i,reason,&config_f);
149 add_kline(0,"<Config>",reason,host);
150 log(DEBUG,"Read K line (badhost tag): host=%s reason=%s",host,reason);
152 for (int i = 0; i < ConfValueEnum("exception",&config_f); i++)
154 ConfValue("exception","host",i,host,&config_f);
155 ConfValue("exception","reason",i,reason,&config_f);
156 add_eline(0,"<Config>",reason,host);
157 log(DEBUG,"Read E line (exception tag): host=%s reason=%s",host,reason);
163 void add_gline(long duration, const char* source,const char* reason,const char* hostmask)
167 item.duration = duration;
168 strlcpy(item.hostmask,hostmask,199);
169 strlcpy(item.reason,reason,MAXBUF);
170 strlcpy(item.source,source,255);
172 item.set_time = TIME;
173 glines.push_back(item);
176 // adds an e:line (exception to bans)
178 void add_eline(long duration, const char* source, const char* reason, const char* hostmask)
182 item.duration = duration;
183 strlcpy(item.hostmask,hostmask,199);
184 strlcpy(item.reason,reason,MAXBUF);
185 strlcpy(item.source,source,255);
187 item.set_time = TIME;
188 elines.push_back(item);
193 void add_qline(long duration, const char* source, const char* reason, const char* nickname)
197 item.duration = duration;
198 strlcpy(item.nick,nickname,63);
199 strlcpy(item.reason,reason,MAXBUF);
200 strlcpy(item.source,source,255);
202 item.is_global = false;
203 item.set_time = TIME;
204 qlines.push_back(item);
209 void add_zline(long duration, const char* source, const char* reason, const char* ipaddr)
213 item.duration = duration;
214 if (strchr(ipaddr,'@'))
216 while (*ipaddr != '@')
220 strlcpy(item.ipaddr,ipaddr,39);
221 strlcpy(item.reason,reason,MAXBUF);
222 strlcpy(item.source,source,255);
224 item.is_global = false;
225 item.set_time = TIME;
226 zlines.push_back(item);
231 void add_kline(long duration, const char* source, const char* reason, const char* hostmask)
235 item.duration = duration;
236 strlcpy(item.hostmask,hostmask,200);
237 strlcpy(item.reason,reason,MAXBUF);
238 strlcpy(item.source,source,255);
240 item.set_time = TIME;
241 klines.push_back(item);
244 // deletes a g:line, returns true if the line existed and was removed
246 bool del_gline(const char* hostmask)
248 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
250 if (!strcasecmp(hostmask,i->hostmask))
259 // deletes a e:line, returns true if the line existed and was removed
261 bool del_eline(const char* hostmask)
263 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
265 if (!strcasecmp(hostmask,i->hostmask))
274 // deletes a q:line, returns true if the line existed and was removed
276 bool del_qline(const char* nickname)
278 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
280 if (!strcasecmp(nickname,i->nick))
289 bool qline_make_global(const char* nickname)
291 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
293 if (!strcasecmp(nickname,i->nick))
302 bool zline_make_global(const char* ipaddr)
304 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
306 if (!strcasecmp(ipaddr,i->ipaddr))
315 void sync_xlines(serverrec* serv, char* tcp_host)
319 // for zlines and qlines, we should first check if theyre global...
320 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
324 snprintf(data,MAXBUF,"%s } %s %s %lu %lu :%s",CreateSum().c_str(),i->ipaddr,i->source,(unsigned long)i->set_time,(unsigned long)i->duration,i->reason);
325 serv->SendPacket(data,tcp_host);
328 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
332 snprintf(data,MAXBUF,"%s { %s %s %lu %lu :%s",CreateSum().c_str(),i->nick,i->source,(unsigned long)i->set_time,(unsigned long)i->duration,i->reason);
333 serv->SendPacket(data,tcp_host);
336 // glines are always global, so no need to check
337 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
339 snprintf(data,MAXBUF,"%s # %s %s %lu %lu :%s",CreateSum().c_str(),i->hostmask,i->source,(unsigned long)i->set_time,(unsigned long)i->duration,i->reason);
340 serv->SendPacket(data,tcp_host);
345 // deletes a z:line, returns true if the line existed and was removed
347 bool del_zline(const char* ipaddr)
349 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
351 if (!strcasecmp(ipaddr,i->ipaddr))
360 // deletes a k:line, returns true if the line existed and was removed
362 bool del_kline(const char* hostmask)
364 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
366 if (!strcasecmp(hostmask,i->hostmask))
375 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
377 char* matches_qline(const char* nick)
381 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
383 if (match(nick,i->nick))
391 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
393 char* matches_gline(const char* host)
397 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
399 if (match(host,i->hostmask))
407 char* matches_exception(const char* host)
412 snprintf(host2,MAXBUF,"*@%s",host);
413 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
415 if ((match(host,i->hostmask)) || (match(host2,i->hostmask)))
424 void gline_set_creation_time(char* host, time_t create_time)
426 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
428 if (!strcasecmp(host,i->hostmask))
430 i->set_time = create_time;
437 void qline_set_creation_time(char* nick, time_t create_time)
439 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
441 if (!strcasecmp(nick,i->nick))
443 i->set_time = create_time;
450 void zline_set_creation_time(char* ip, time_t create_time)
452 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
454 if (!strcasecmp(ip,i->ipaddr))
456 i->set_time = create_time;
463 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
465 char* matches_zline(const char* ipaddr)
469 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
471 if (match(ipaddr,i->ipaddr))
479 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
481 char* matches_kline(const char* host)
485 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
487 if (match(host,i->hostmask))
495 // removes lines that have expired
499 bool go_again = true;
500 time_t current = TIME;
502 // because we mess up an iterator when we remove from the vector, we must bail from
503 // the loop early if we delete an item, therefore this outer while loop is required.
508 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
510 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
512 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
519 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
521 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
523 WriteOpers("Expiring timed E-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
530 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
532 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
534 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
541 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
543 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
545 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
552 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
554 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
556 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
565 // applies lines, removing clients and changing nicks etc as applicable
569 bool go_again = true;
573 if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()))
579 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
581 if (!strcasecmp(u->second->server,ServerName))
583 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
586 // ignore people matching exempts
587 if (matches_exception(host))
592 char* check = matches_gline(host);
595 WriteOpers("*** User %s matches G-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",check);
596 snprintf(reason,MAXBUF,"G-Lined: %s",check);
597 kill_link(u->second,reason);
604 char* check = matches_kline(host);
607 WriteOpers("*** User %s matches K-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",check);
608 snprintf(reason,MAXBUF,"K-Lined: %s",check);
609 kill_link(u->second,reason);
616 char* check = matches_qline(u->second->nick);
619 snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
620 WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",u->second->host,check);
621 kill_link(u->second,reason);
628 char* check = matches_zline(u->second->ip);
631 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
632 WriteOpers("*** User %s matches Z-Line: %s",u->second->registered == 7 ? u->second->nick:"<unknown>",u->second->host,check);
633 kill_link(u->second,reason);
643 void stats_k(userrec* user)
645 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
647 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
651 void stats_g(userrec* user)
653 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
655 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
659 void stats_q(userrec* user)
661 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
663 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
667 void stats_z(userrec* user)
669 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
671 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
675 void stats_e(userrec* user)
677 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
679 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);