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 * ---------------------------------------------------
18 #include "inspircd_io.h"
19 #include "inspircd_util.h"
20 #include "inspircd_config.h"
23 #include <sys/errno.h>
24 #include <sys/ioctl.h>
25 #include <sys/utsname.h>
30 #include <ext/hash_map>
42 #include "connection.h"
53 #include "inspstring.h"
56 #define nspace __gnu_cxx
65 extern std::vector<Module*> modules;
66 extern std::vector<ircd_module*> factory;
69 extern char ServerName[MAXBUF];
70 extern char Network[MAXBUF];
71 extern char ServerDesc[MAXBUF];
72 extern char AdminName[MAXBUF];
73 extern char AdminEmail[MAXBUF];
74 extern char AdminNick[MAXBUF];
75 extern char diepass[MAXBUF];
76 extern char restartpass[MAXBUF];
77 extern char motd[MAXBUF];
78 extern char rules[MAXBUF];
79 extern char list[MAXBUF];
80 extern char PrefixQuit[MAXBUF];
81 extern char DieValue[MAXBUF];
84 extern int WHOWAS_STALE;
85 extern int WHOWAS_MAX;
87 extern time_t startup_time;
88 extern int NetBufferSize;
89 extern time_t nb_start;
91 extern std::vector<int> fd_reap;
92 extern std::vector<std::string> module_names;
94 extern int boundPortCount;
96 extern int UDPportCount;
97 extern int ports[MAXSOCKS];
98 extern int defaultRoute;
100 extern std::vector<long> auth_cookies;
101 extern std::stringstream config_f;
103 extern serverrec* me[32];
105 extern FILE *log_file;
110 template<> struct hash<in_addr>
112 template<> struct nspace::hash<in_addr>
115 size_t operator()(const struct in_addr &a) const
118 memcpy(&q,&a,sizeof(size_t));
123 template<> struct hash<string>
125 template<> struct nspace::hash<string>
128 size_t operator()(const string &s) const
131 static struct hash<const char *> strhash;
132 strlcpy(a,s.c_str(),MAXBUF);
143 bool operator()(const string& s1, const string& s2) const
145 char a[MAXBUF],b[MAXBUF];
146 strlcpy(a,s1.c_str(),MAXBUF);
147 strlcpy(b,s2.c_str(),MAXBUF);
148 return (strcasecmp(a,b) == 0);
153 struct InAddr_HashComp
156 bool operator()(const in_addr &s1, const in_addr &s2) const
161 memcpy(&q,&s1,sizeof(size_t));
162 memcpy(&p,&s2,sizeof(size_t));
170 typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, StrHashComp> user_hash;
171 typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, StrHashComp> chan_hash;
172 typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, InAddr_HashComp> address_cache;
173 typedef std::deque<command_t> command_table;
176 extern user_hash clientlist;
177 extern chan_hash chanlist;
178 extern user_hash whowas;
179 extern command_table cmdlist;
180 extern file_cache MOTD;
181 extern file_cache RULES;
182 extern address_cache IP;
186 std::vector<KLine> klines;
187 std::vector<GLine> glines;
188 std::vector<ZLine> zlines;
189 std::vector<QLine> qlines;
190 std::vector<ELine> elines;
192 // Reads the default bans from the config file.
193 // only a very small number of bans are defined
194 // this way these days, such as qlines against
195 // services nicks, etc.
197 void read_xline_defaults()
204 for (int i = 0; i < ConfValueEnum("badip",&config_f); i++)
206 ConfValue("badip","ipmask",i,ipmask,&config_f);
207 ConfValue("badip","reason",i,reason,&config_f);
208 add_zline(0,"<Config>",reason,ipmask);
209 log(DEBUG,"Read Z line (badip tag): ipmask=%s reason=%s",ipmask,reason);
212 for (int i = 0; i < ConfValueEnum("badnick",&config_f); i++)
214 ConfValue("badnick","nick",i,nick,&config_f);
215 ConfValue("badnick","reason",i,reason,&config_f);
216 add_qline(0,"<Config>",reason,nick);
217 log(DEBUG,"Read Q line (badnick tag): nick=%s reason=%s",nick,reason);
220 for (int i = 0; i < ConfValueEnum("badhost",&config_f); i++)
222 ConfValue("badhost","host",i,host,&config_f);
223 ConfValue("badhost","reason",i,reason,&config_f);
224 add_kline(0,"<Config>",reason,host);
225 log(DEBUG,"Read K line (badhost tag): host=%s reason=%s",host,reason);
227 for (int i = 0; i < ConfValueEnum("exception",&config_f); i++)
229 ConfValue("exception","host",i,host,&config_f);
230 ConfValue("exception","reason",i,reason,&config_f);
231 add_eline(0,"<Config>",reason,host);
232 log(DEBUG,"Read E line (exception tag): host=%s reason=%s",host,reason);
238 void add_gline(long duration, char* source, char* reason, char* hostmask)
242 item.duration = duration;
243 strlcpy(item.hostmask,hostmask,MAXBUF);
244 strlcpy(item.reason,reason,MAXBUF);
245 strlcpy(item.source,source,MAXBUF);
247 item.set_time = TIME;
248 glines.push_back(item);
251 // adds an e:line (exception to bans)
253 void add_eline(long duration, char* source, char* reason, char* hostmask)
257 item.duration = duration;
258 strlcpy(item.hostmask,hostmask,MAXBUF);
259 strlcpy(item.reason,reason,MAXBUF);
260 strlcpy(item.source,source,MAXBUF);
262 item.set_time = TIME;
263 elines.push_back(item);
268 void add_qline(long duration, char* source, char* reason, char* nickname)
272 item.duration = duration;
273 strlcpy(item.nick,nickname,MAXBUF);
274 strlcpy(item.reason,reason,MAXBUF);
275 strlcpy(item.source,source,MAXBUF);
277 item.is_global = false;
278 item.set_time = TIME;
279 qlines.push_back(item);
284 void add_zline(long duration, char* source, char* reason, char* ipaddr)
288 item.duration = duration;
289 strlcpy(item.ipaddr,ipaddr,MAXBUF);
290 strlcpy(item.reason,reason,MAXBUF);
291 strlcpy(item.source,source,MAXBUF);
293 item.is_global = false;
294 item.set_time = TIME;
295 zlines.push_back(item);
300 void add_kline(long duration, char* source, char* reason, char* hostmask)
304 item.duration = duration;
305 strlcpy(item.hostmask,hostmask,MAXBUF);
306 strlcpy(item.reason,reason,MAXBUF);
307 strlcpy(item.source,source,MAXBUF);
309 item.set_time = TIME;
310 klines.push_back(item);
313 // deletes a g:line, returns true if the line existed and was removed
315 bool del_gline(char* hostmask)
317 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
319 if (!strcasecmp(hostmask,i->hostmask))
328 // deletes a e:line, returns true if the line existed and was removed
330 bool del_eline(char* hostmask)
332 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
334 if (!strcasecmp(hostmask,i->hostmask))
343 // deletes a q:line, returns true if the line existed and was removed
345 bool del_qline(char* nickname)
347 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
349 if (!strcasecmp(nickname,i->nick))
358 bool qline_make_global(char* nickname)
360 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
362 if (!strcasecmp(nickname,i->nick))
371 bool zline_make_global(char* ipaddr)
373 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
375 if (!strcasecmp(ipaddr,i->ipaddr))
384 void sync_xlines(serverrec* serv, char* tcp_host)
388 // for zlines and qlines, we should first check if theyre global...
389 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
393 snprintf(data,MAXBUF,"} %s %s %ld %ld :%s",i->ipaddr,i->source,i->set_time,i->duration,i->reason);
394 serv->SendPacket(data,tcp_host);
397 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
401 snprintf(data,MAXBUF,"{ %s %s %ld %ld :%s",i->nick,i->source,i->set_time,i->duration,i->reason);
402 serv->SendPacket(data,tcp_host);
405 // glines are always global, so no need to check
406 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
408 snprintf(data,MAXBUF,"# %s %s %ld %ld :%s",i->hostmask,i->source,i->set_time,i->duration,i->reason);
409 serv->SendPacket(data,tcp_host);
414 // deletes a z:line, returns true if the line existed and was removed
416 bool del_zline(char* ipaddr)
418 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
420 if (!strcasecmp(ipaddr,i->ipaddr))
429 // deletes a k:line, returns true if the line existed and was removed
431 bool del_kline(char* hostmask)
433 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
435 if (!strcasecmp(hostmask,i->hostmask))
444 // returns a pointer to the reason if a nickname matches a qline, NULL if it didnt match
446 char* matches_qline(const char* nick)
450 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
452 if (match(nick,i->nick))
460 // returns a pointer to the reason if a host matches a gline, NULL if it didnt match
462 char* matches_gline(const char* host)
466 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
468 if (match(host,i->hostmask))
476 char* matches_exception(const char* host)
481 snprintf(host2,MAXBUF,"*@%s",host);
482 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
484 if ((match(host,i->hostmask)) || (match(host2,i->hostmask)))
493 void gline_set_creation_time(char* host, time_t create_time)
495 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
497 if (!strcasecmp(host,i->hostmask))
499 i->set_time = create_time;
506 void qline_set_creation_time(char* nick, time_t create_time)
508 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
510 if (!strcasecmp(nick,i->nick))
512 i->set_time = create_time;
519 void zline_set_creation_time(char* ip, time_t create_time)
521 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
523 if (!strcasecmp(ip,i->ipaddr))
525 i->set_time = create_time;
532 // returns a pointer to the reason if an ip address matches a zline, NULL if it didnt match
534 char* matches_zline(const char* ipaddr)
538 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
540 if (match(ipaddr,i->ipaddr))
548 // returns a pointer to the reason if a host matches a kline, NULL if it didnt match
550 char* matches_kline(const char* host)
554 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
556 if (match(host,i->hostmask))
564 // removes lines that have expired
568 bool go_again = true;
569 time_t current = TIME;
571 // because we mess up an iterator when we remove from the vector, we must bail from
572 // the loop early if we delete an item, therefore this outer while loop is required.
577 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
579 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
581 WriteOpers("Expiring timed K-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
588 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
590 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
592 WriteOpers("Expiring timed E-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
599 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
601 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
603 WriteOpers("Expiring timed G-Line %s (set by %s %d seconds ago)",i->hostmask,i->source,i->duration);
610 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
612 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
614 WriteOpers("Expiring timed Z-Line %s (set by %s %d seconds ago)",i->ipaddr,i->source,i->duration);
621 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
623 if ((current > (i->duration + i->set_time)) && (i->duration > 0))
625 WriteOpers("Expiring timed Q-Line %s (set by %s %d seconds ago)",i->nick,i->source,i->duration);
634 // applies lines, removing clients and changing nicks etc as applicable
638 bool go_again = true;
642 if ((!glines.size()) && (!klines.size()) && (!zlines.size()) && (!qlines.size()))
648 for (user_hash::const_iterator u = clientlist.begin(); u != clientlist.end(); u++)
650 if (!strcasecmp(u->second->server,ServerName))
652 snprintf(host,MAXBUF,"%s@%s",u->second->ident,u->second->host);
655 // ignore people matching exempts
656 if (matches_exception(host))
661 char* check = matches_gline(host);
664 WriteOpers("*** User %s matches G-Line: %s",u->second->nick,check);
665 snprintf(reason,MAXBUF,"G-Lined: %s",check);
666 kill_link(u->second,reason);
673 char* check = matches_kline(host);
676 WriteOpers("*** User %s matches K-Line: %s",u->second->nick,check);
677 snprintf(reason,MAXBUF,"K-Lined: %s",check);
678 kill_link(u->second,reason);
685 char* check = matches_qline(u->second->nick);
688 snprintf(reason,MAXBUF,"Matched Q-Lined nick: %s",check);
689 WriteOpers("*** Q-Lined nickname %s from %s: %s",u->second->nick,u->second->host,check);
690 kill_link(u->second,reason);
697 char* check = matches_zline(u->second->ip);
700 snprintf(reason,MAXBUF,"Z-Lined: %s",check);
701 WriteOpers("*** User %s matches Z-Line: %s",u->second->nick,u->second->host,check);
702 kill_link(u->second,reason);
712 void stats_k(userrec* user)
714 for (std::vector<KLine>::iterator i = klines.begin(); i != klines.end(); i++)
716 WriteServ(user->fd,"216 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
720 void stats_g(userrec* user)
722 for (std::vector<GLine>::iterator i = glines.begin(); i != glines.end(); i++)
724 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);
728 void stats_q(userrec* user)
730 for (std::vector<QLine>::iterator i = qlines.begin(); i != qlines.end(); i++)
732 WriteServ(user->fd,"217 %s :%s %d %d %s %s",user->nick,i->nick,i->set_time,i->duration,i->source,i->reason);
736 void stats_z(userrec* user)
738 for (std::vector<ZLine>::iterator i = zlines.begin(); i != zlines.end(); i++)
740 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->ipaddr,i->set_time,i->duration,i->source,i->reason);
744 void stats_e(userrec* user)
746 for (std::vector<ELine>::iterator i = elines.begin(); i != elines.end(); i++)
748 WriteServ(user->fd,"223 %s :%s %d %d %s %s",user->nick,i->hostmask,i->set_time,i->duration,i->source,i->reason);